def query_xkbmap(self): log("query_xkbmap()") ( self.xkbmap_layout, self.xkbmap_layouts, self.xkbmap_variant, self.xkbmap_variants, self.xkbmap_options, ) = self.get_layout_spec() spec = self.get_keymap_spec() self.xkbmap_print, self.xkbmap_query, self.xkbmap_query_struct = spec log("query_xkbmap() get_keymap_spec()=%s", spec) self.xkbmap_keycodes = self.get_full_keymap() log("query_xkbmap() get_full_keymap()=%s", self.xkbmap_keycodes) self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap() log("query_xkbmap() %s.get_x11_keymap()=%s", self.keyboard, self.xkbmap_x11_keycodes) mods = self.keyboard.get_keymap_modifiers() ( self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing, ) = mods log("query_xkbmap() %s.get_keymap_modifiers()=%s", self.keyboard, mods) self.update_hash() log("layout=%s, layouts=%s, variant=%s, variants=%s", self.xkbmap_layout, self.xkbmap_layouts, self.xkbmap_variant, self.xkbmap_variants) log("print=%s, query=%s, struct=%s", nonl(self.xkbmap_print), nonl(self.xkbmap_query), self.xkbmap_query_struct) log("keycodes=%s", ellipsizer(self.xkbmap_keycodes)) log("x11 keycodes=%s", ellipsizer(self.xkbmap_x11_keycodes)) log("mod managed: %s", self.xkbmap_mod_managed) log("mod meanings: %s", self.xkbmap_mod_meanings) log("mod pointermissing: %s", self.xkbmap_mod_pointermissing) log("hash=%s", self.hash)
def proxy_got_contents(self, request_id, selection, target, dtype, dformat, data): def no_contents(): self.send("clipboard-contents-none", request_id, selection) dtype = bytestostr(dtype) if is_debug_enabled("clipboard"): log("proxy_got_contents(%s, %s, %s, %s, %s, %s:%s) data=0x%s..", request_id, selection, target, dtype, dformat, type(data), len(data or ""), hexstr((data or "")[:200])) if dtype is None or data is None or (dformat==0 and not data): no_contents() return truncated = 0 if self.max_clipboard_send_size > 0: log("perform clipboard limit checking - datasize - %d, %d", len(data), self.max_clipboard_send_size) max_send_datalen = self.max_clipboard_send_size * 8 // get_format_size(dformat) if len(data) > max_send_datalen: truncated = len(data) - max_send_datalen data = data[:max_send_datalen] munged = self._munge_raw_selection_to_wire(target, dtype, dformat, data) if is_debug_enabled("clipboard"): log("clipboard raw -> wire: %r -> %r", (dtype, dformat, ellipsizer(data)), ellipsizer(munged)) wire_encoding, wire_data = munged if wire_encoding is None: no_contents() return wire_data = self._may_compress(dtype, dformat, wire_data) if wire_data is not None: packet = ["clipboard-contents", request_id, selection, dtype, dformat, wire_encoding, wire_data] if self.clipboard_contents_slice_fix: #sending the extra argument requires the fix packet.append(truncated) self.send(*packet)
def peek_connection(conn, timeout=PEEK_TIMEOUT_MS): log = get_network_logger() log("peek_connection(%s, %i)", conn, timeout) PEEK_SIZE = 8192 start = monotonic_time() peek_data = b"" while not peek_data and int(1000 * (monotonic_time() - start)) < timeout: try: peek_data = conn.peek(PEEK_SIZE) except (OSError, IOError): pass except ValueError: log("peek_connection(%s, %i) failed", conn, timeout, exc_info=True) break if not peek_data: sleep(timeout / 4000.0) line1 = b"" log("socket %s peek: got %i bytes", conn, len(peek_data)) set_socket_timeout(conn, PEEK_TIMEOUT_MS * 1000) if peek_data: line1 = peek_data.splitlines()[0] log("socket peek=%s", ellipsizer(peek_data, limit=512)) log("socket peek hex=%s", hexstr(peek_data[:128])) log("socket peek line1=%s", ellipsizer(line1)) return peek_data, line1
def _read_thread_loop(self): log.info("udp read thread loop starting") try: while not self._closed: try: buf, bfrom = self._socket.recvfrom(READ_BUFFER_SIZE) except Exception as e: log("_read_thread_loop() buffer=%s, from=%s", ellipsizer(buf), bfrom, exc_info=True) if can_retry(e): continue raise if not buf: log("read thread: eof") break values = list(_header_struct.unpack_from(buf[:_header_size])) + [buf[_header_size:], bfrom] try: self._process_packet_cb(self, *values) except Exception as e: log("_read_thread_loop() buffer=%s, from=%s", ellipsizer(buf), bfrom, exc_info=True) if not self._closed: log.error("Error: UDP packet processing error:") log.error(" %s", e) del e except Exception as e: #can happen during close(), in which case we just ignore: if not self._closed: log.error("Error: read on %s failed: %s", self._socket, type(e), exc_info=True) log("udp read thread loop ended") self.close()
def peek_connection(conn, timeout=PEEK_TIMEOUT_MS, size=PEEK_SIZE): log = get_network_logger() log("peek_connection(%s, %i)", conn, timeout) peek_data = b"" start = monotonic_time() elapsed = 0 set_socket_timeout(conn, PEEK_TIMEOUT_MS * 1000) while elapsed <= timeout: try: peek_data = conn.peek(size) if peek_data: break except OSError: log("peek_connection(%s, %i) failed", conn, timeout, exc_info=True) except ValueError: log("peek_connection(%s, %i) failed", conn, timeout, exc_info=True) break sleep(timeout / 4000.0) elapsed = int(1000 * (monotonic_time() - start)) log("peek: elapsed=%s, timeout=%s", elapsed, timeout) line1 = b"" log("socket %s peek: got %i bytes", conn, len(peek_data)) if peek_data: line1 = peek_data.splitlines()[0] log("socket peek=%s", ellipsizer(peek_data, limit=512)) log("socket peek hex=%s", hexstr(peek_data[:128])) log("socket peek line1=%s", ellipsizer(line1)) return peek_data, line1
def got_token(self, targets, target_data=None, claim=True, synchronous_client=False): # the remote end now owns the clipboard self.cancel_emit_token() if not self._enabled: return self._got_token_events += 1 log( "got token, selection=%s, targets=%s, target data=%s, claim=%s, synchronous_client=%s, can-receive=%s", self._selection, targets, ellipsizer(target_data), claim, synchronous_client, self._can_receive) if claim: self._have_token = True if not self._can_receive: return if target_data and claim: targets = target_data.keys() text_targets = tuple(x for x in targets if x in TEXT_TARGETS) for text_target in text_targets: dtype, dformat, data = target_data.get(text_target) if dformat != 8: continue text = net_utf8(data) log("setting text data %s / %s of size %i: %s", dtype, dformat, len(text), ellipsizer(text)) self._owner_change_embargo = monotonic() self.clipboard.set_text(text, len(text)) return
def __init__(self, uid, gid, env_options, session_options, socket_dir, video_encoder_modules, pings, client_conn, disp_desc, client_state, cipher, encryption_key, server_conn, caps, message_queue): ProxyInstance.__init__(self, session_options, video_encoder_modules, pings, disp_desc, cipher, encryption_key, caps) QueueScheduler.__init__(self) Process.__init__(self, name=str(client_conn), daemon=False) self.client_conn = client_conn self.server_conn = server_conn self.uid = uid self.gid = gid self.env_options = env_options self.socket_dir = socket_dir self.client_state = client_state log("ProxyProcess%s", (uid, gid, env_options, session_options, socket_dir, video_encoder_modules, client_conn, disp_desc, ellipsizer(client_state), cipher, encryption_key, server_conn, "%s: %s.." % (type(caps), ellipsizer(caps)), message_queue)) self.message_queue = message_queue #for handling the local unix domain socket: self.control_socket_cleanup = None self.control_socket = None self.control_socket_thread = None self.control_socket_path = None self.potential_protocols = [] self.max_connections = MAX_CONCURRENT_CONNECTIONS
def svg_to_png(filename, icondata, w=128, h=128): Rsvg = load_Rsvg() if not Rsvg: return None try: import cairo #'\sinkscape:[a-zA-Z]*=["a-zA-Z0-9]*' img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128) ctx = cairo.Context(img) handle = Rsvg.Handle.new_from_data(icondata) handle.render_cairo(ctx) buf = BytesIO() img.write_to_png(buf) icondata = buf.getvalue() buf.close() return icondata except Exception: log("svg_to_png%s", (icondata, w, h), exc_info=True) if re.findall(INKSCAPE_RE, icondata): #try again after stripping the bogus inkscape attributes #as some rsvg versions can't handle that (ie: Debian Bullseye) icondata = re.sub(INKSCAPE_RE, b"", icondata) return svg_to_png(filename, icondata, w, h) log.error("Error: failed to convert svg icon") log.error(" '%s':", filename) log.error(" %i bytes, %s", len(icondata), ellipsizer(icondata))
def got_token(self, targets, target_data=None, claim=True, synchronous_client=False): # the remote end now owns the clipboard self.cancel_emit_token() if not self._enabled: return self._got_token_events += 1 log("got token, selection=%s, targets=%s, target data=%s, claim=%s, can-receive=%s", self._selection, targets, ellipsizer(target_data), claim, self._can_receive) if claim: self._have_token = True if self._can_receive: self.targets = tuple(bytestostr(x) for x in (targets or ())) self.target_data = target_data or {} if targets and claim: xatoms = strings_to_xatoms(targets) self.got_contents("TARGETS", "ATOM", 32, xatoms) if target_data and synchronous_client and claim: targets = target_data.keys() text_targets = tuple(x for x in targets if x in TEXT_TARGETS) if text_targets: target = text_targets[0] dtype, dformat, data = target_data.get(target) dtype = bytestostr(dtype) self.got_contents(target, dtype, dformat, data) if self._can_receive and claim: self.claim()
def got_token(self, targets, target_data=None, claim=True, _synchronous_client=False): # the remote end now owns the clipboard self.cancel_emit_token() if not self._enabled: return self._got_token_events += 1 log( "got token, selection=%s, targets=%s, target data=%s, claim=%s, can-receive=%s", self._selection, targets, ellipsizer(target_data), claim, self._can_receive) if self._can_receive: self.targets = _filter_targets(targets or ()) self.target_data = target_data or {} if targets: self.got_contents("TARGETS", "ATOM", 32, targets) if target_data: for target, td_def in target_data.items(): dtype, dformat, data = td_def dtype = bytestostr(dtype) self.got_contents(target, dtype, dformat, data) #since we claim to be greedy #the peer should have sent us the target and target_data, #if not then request it: if not targets: self.send_clipboard_request_handler(self, self._selection, "TARGETS") if not claim: log("token packet without claim, not setting the token flag") return if claim: self._have_token = True
def set_selection_response(self, requestor, target, prop, dtype, dformat, data, time=0): log("set_selection_response(%s, %s, %s, %s, %s, %r, %i)", requestor, target, prop, dtype, dformat, ellipsizer(data), time) #answer the selection request: try: xid = requestor.get_xid() if not prop: log.warn("Warning: cannot set clipboard response") log.warn(" property is unset for requestor %s", self.get_wininfo(xid)) return with xsync: if data is not None: X11Window.XChangeProperty(xid, prop, dtype, dformat, data) else: #maybe even delete the property? #X11Window.XDeleteProperty(xid, prop) prop = None X11Window.sendSelectionNotify(xid, self._selection, target, prop, time) except XError as e: log("failed to set selection", exc_info=True) log.warn("Warning: failed to set selection for target '%s'", target) log.warn(" on requestor %s", self.get_wininfo(xid)) log.warn(" property '%s'", prop) log.warn(" %s", e)
def _process_gibberish(self, packet): log("process_gibberish(%s)", ellipsizer(packet)) message, data = packet[1:3] from xpra.net.socket_util import guess_packet_type #pylint: disable=import-outside-toplevel packet_type = guess_packet_type(data) p = self._protocol exit_code = EXIT_PACKET_FAILURE pcount = p.input_packetcount if p else 0 if pcount<=1: exit_code = EXIT_CONNECTION_FAILED netlog.error("Error: failed to connect") else: netlog.error("Error: received an invalid packet") if packet_type=="xpra": netlog.error(" xpra server bug or mangled packet") if packet_type and packet_type!="xpra": netlog.error(" this is a '%s' packet,", packet_type) netlog.error(" not from an xpra server?") else: netlog.error(" received uninterpretable nonsense: %r", message) data = bytestostr(data).strip("\n\r") show_as_text = pcount<=1 and len(data)<128 and all((c in string.printable) or c in ("\n\r") for c in data) if show_as_text: if data.find("\n")>=0: netlog.error(" data:") for x in data.split("\n"): netlog.error(" %r", x.split("\0")[0]) else: netlog.error(" data: %r", data) else: netlog.error(" packet no %i data: %s", pcount, nonl(repr_ellipsized(data))) self.quit(exit_code)
def __init__(self, session_options, video_encoder_modules, pings, disp_desc, cipher, encryption_key, caps): self.session_options = session_options self.video_encoder_modules = video_encoder_modules self.pings = pings self.disp_desc = disp_desc self.cipher = cipher self.encryption_key = encryption_key self.caps = caps log("ProxyInstance%s", (session_options, video_encoder_modules, disp_desc, cipher, encryption_key, "%s: %s.." % (type(caps), ellipsizer(caps)))) self.uuid = get_hex_uuid() self.client_protocol = None self.server_protocol = None #ping handling: self.client_last_ping = 0 self.server_last_ping = 0 self.client_last_ping_echo = 0 self.server_last_ping_echo = 0 self.client_last_ping_latency = 0 self.server_last_ping_latency = 0 self.client_ping_timer = None self.server_ping_timer = None self.client_challenge_packet = None self.exit = False self.lost_windows = None self.encode_queue = None #holds draw packets to encode self.encode_thread = None self.video_encoding_defs = None self.video_encoders = None self.video_encoders_last_used_time = None self.video_encoder_types = None self.video_helper = None
def after_handshake(self, cb, *args): log("after_handshake(%s, %s) on_handshake=%s", cb, args, ellipsizer(self._on_handshake)) if self._on_handshake is None: #handshake has already occurred, just call it: self.idle_add(cb, *args) else: self._on_handshake.append((cb, args))
def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon): if not self.dbus_check(dbus_id): return self.may_retry = True try: icon_string = self.get_icon_string(nid, app_icon, icon) log("get_icon_string%s=%s", (nid, app_icon, ellipsizer(icon)), icon_string) try: app_str = self.app_name_format % app_name except TypeError: app_str = app_name or "Xpra" self.last_notification = (dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon) def NotifyReply(notification_id): log("NotifyReply(%s) for nid=%i", notification_id, nid) self.actual_notification_id[nid] = int(notification_id) dbus_hints = self.parse_hints(hints) self.dbusnotify.Notify(app_str, 0, icon_string, summary, body, actions, dbus_hints, expire_timeout, reply_handler=NotifyReply, error_handler=self.NotifyError) except Exception: log.error("Error: dbus notify failed", exc_info=True)
def get_workarea(): if not is_Wayland(): try: d = get_current_desktop() if d < 0: return None workarea = _get_X11_root_property("_NET_WORKAREA", "CARDINAL") if not workarea: return None screenlog("get_workarea() _NET_WORKAREA=%s (%s), len=%s", ellipsizer(workarea), type(workarea), len(workarea)) #workarea comes as a list of 4 CARDINAL dimensions (x,y,w,h), one for each desktop sizeof_long = struct.calcsize(b"@L") if len(workarea) < (d + 1) * 4 * sizeof_long: screenlog.warn("get_workarea() invalid _NET_WORKAREA value") else: cur_workarea = workarea[d * 4 * sizeof_long:(d + 1) * 4 * sizeof_long] v = struct.unpack(b"@LLLL", cur_workarea) screenlog("get_workarea() %s=%s", hexstr(cur_workarea), v) return v except Exception as e: screenlog("get_workarea()", exc_info=True) screenlog.warn("Warning: failed to query workarea: %s", e) return None
def get_text(): formats = get_clipboard_formats() matching = [] for u in (utf8, not utf8): if u: fmts = [win32con.CF_UNICODETEXT] else: fmts = [win32con.CF_TEXT, win32con.CF_OEMTEXT] matching += [fmt for fmt in formats if fmt in fmts] log("supported formats: %s (prefer utf8: %s)", csv(format_names(matching)), utf8) if not matching: log("no supported formats, only: %s", csv(format_names(formats))) errback() return True data_handle = None fmt = None for fmt in matching: data_handle = GetClipboardData(fmt) log("GetClipboardData(%s)=%#x", format_name(fmt), data_handle or 0) if data_handle: break if not data_handle: log("no valid data handle using %s (may try again)", csv(format_names(matching))) return False data = GlobalLock(data_handle) if not data: log("failed to lock data handle %#x (may try again)", data_handle) return False log("got data handle lock %#x for format '%s'", data, format_name(fmt)) try: if fmt == win32con.CF_UNICODETEXT: try: v = w_to_utf8(data) except Exception as e: log("w_to_utf8(..)", exc_info=True) errback(str(e)) return True callback(v) return True #CF_TEXT or CF_OEMTEXT: astr = cast(data, LPCSTR) s = astr.value.decode("latin1") if CONVERT_LINE_ENDINGS: s = s.replace("\r\n", "\n") b = s.encode("latin1") ulen = len(b) if ulen > MAX_CLIPBOARD_PACKET_SIZE: errback("text data is too large: %i characters" % ulen) return True log("got %i bytes of TEXT data: %s", len(b), ellipsizer(b)) callback(b) return True finally: GlobalUnlock(data)
def _process_gibberish(self, packet): log("process_gibberish(%s)", ellipsizer(packet)) message, data = packet[1:3] p = self._protocol show_as_text = p and p.input_packetcount == 0 and len( data) < 128 and all(c in string.printable for c in bytestostr(data)) if show_as_text: #looks like the first packet back is just text, print it: data = bytestostr(data) if data.find("\n") >= 0: for x in data.splitlines(): netlog.warn(x) else: netlog.error("Error: failed to connect, received") netlog.error(" %s", repr_ellipsized(data)) else: from xpra.net.socket_util import guess_packet_type packet_type = guess_packet_type(data) log("guess_packet_type(%r)=%s", data, packet_type) if packet_type and packet_type != "xpra": netlog.error("Error: received a %s packet", packet_type) netlog.error(" this is not an xpra server?") else: netlog.error("Error: received uninterpretable nonsense: %s", message) if p: netlog.error(" packet no %i data: %s", p.input_packetcount, repr_ellipsized(data)) else: netlog.error(" data: %s", repr_ellipsized(data)) self.quit(EXIT_PACKET_FAILURE)
def get_encryption_key(self): conn = self._protocol._conn keydata = parse_encoded_bin_data(conn.options.get("keydata", None)) cryptolog("get_encryption_key() connection options keydata=%s", ellipsizer(keydata)) if keydata: return keydata keyfile = conn.options.get("encryption-keyfile") or conn.options.get("keyfile") or self.encryption_keyfile if keyfile: if not os.path.isabs(keyfile): keyfile = os.path.abspath(keyfile) if os.path.exists(keyfile): key = filedata_nocrlf(keyfile) if key: cryptolog("get_encryption_key() loaded %i bytes from '%s'", len(key or ""), keyfile) return key else: cryptolog("get_encryption_key() keyfile '%s' is empty", keyfile) else: cryptolog("get_encryption_key() file '%s' does not exist", keyfile) XPRA_ENCRYPTION_KEY = "XPRA_ENCRYPTION_KEY" key = strtobytes(os.environ.get(XPRA_ENCRYPTION_KEY, '')) cryptolog("get_encryption_key() got %i bytes from '%s' environment variable", len(key or ""), XPRA_ENCRYPTION_KEY) if key: return key.strip(b"\n\r") raise InitExit(EXIT_ENCRYPTION, "no encryption key")
def server_connection_established(self): #don't bother parsing the network caps: #* it could cause errors if the caps are missing #* we don't care about sending anything back after hello log("server_capabilities: %s", ellipsizer(self.server_capabilities)) log("protocol state: %s", self._protocol.save_state()) self.do_command() return True
def got_text_target(dtype, dformat, data): log("got_text_target(%s, %s, %s)", dtype, dformat, ellipsizer(data)) if not (dtype and dformat and data): send_token_with_targets() return token_data = (targets, (target, dtype, dformat, data)) self._have_token = False self.emit("send-clipboard-token", token_data)
def got_contents(self, target, dtype=None, dformat=None, data=None): #if this is the special target 'TARGETS', cache the result: if target=="TARGETS" and dtype=="ATOM" and dformat==32: self.targets = xatoms_to_strings(data) #the remote peer sent us a response, #find all the pending requests for this target #and give them the response they are waiting for: pending = self.remote_requests.pop(target, []) log("got_contents%s pending=%s", (target, dtype, dformat, ellipsizer(data)), csv(pending)) for requestor, actual_target, prop, time in pending: if log.is_debug_enabled(): log("setting response %s as '%s' on property '%s' of window %s as %s", ellipsizer(data), actual_target, prop, self.get_wininfo(requestor.get_xid()), dtype) if actual_target!=target and dtype==target: dtype = actual_target self.set_selection_response(requestor, actual_target, prop, dtype, dformat, data, time)
def set_clipboard_image(self, img_format, img_data): image_formats = {} if COMPRESSED_IMAGES: #first save it as binary compressed data: fmt_name = LPCSTR(img_format.upper().encode("latin1")+b"\0") #ie: "PNG" fmt = RegisterClipboardFormatA(fmt_name) if fmt: buf = create_string_buffer(img_data) pbuf = cast(byref(buf), c_void_p) l = len(img_data) data_handle = GlobalAlloc(GMEM_MOVEABLE, l) if not data_handle: log.error("Error: failed to allocate %i bytes of global memory", l) return True data = GlobalLock(data_handle) if not data: log("failed to lock data handle %#x (may try again)", data_handle) return False log("got data handle lock %#x for %i bytes of '%s' data", data, l, img_format) try: memmove(data, pbuf, l) finally: GlobalUnlock(data) image_formats[fmt] = data_handle #also convert it to a bitmap: from PIL import Image buf = BytesIO(img_data) img = Image.open(buf) if img.mode!="RGBA": img = img.convert("RGBA") rgb_data = img.tobytes("raw", "BGRA") w, h = img.size log("set_clipboard_image(%s, %s) image size=%s, BGR buffer=%i bytes", img_format, ellipsizer(data), img.size, len(rgb_data)) header = BITMAPINFOHEADER() memset(byref(header), 0, sizeof(BITMAPINFOHEADER )) header.biSize = sizeof(BITMAPINFOHEADER) header.biWidth = w header.biHeight = -h header.biPlanes = 1 header.biBitCount = 32 header.biCompression = BI_RGB header.biSizeImage = 0 header.biXPelsPerMeter = 10 header.biYPelsPerMeter = 10 bitmapinfo = BITMAPINFO() bitmapinfo.bmiColors = 0 memmove(byref(bitmapinfo.bmiHeader), byref(header), sizeof(BITMAPINFOHEADER)) rgb_buf = create_string_buffer(rgb_data) pbuf = cast(byref(rgb_buf), c_void_p) hdc = GetDC(None) CBM_INIT = 4 bitmap = CreateDIBitmap(hdc, byref(header), CBM_INIT, pbuf, byref(bitmapinfo), win32con.DIB_RGB_COLORS) ReleaseDC(None, hdc) image_formats[win32con.CF_BITMAP] = bitmap self.do_set_clipboard_image(image_formats)
def got_local_contents(self, target, dtype=None, dformat=None, data=None): data = self.filter_data(dtype, dformat, data) target_requests = self.local_requests.pop(target, {}) for timer, got_contents in target_requests.values(): if log.is_debug_enabled(): log("got_local_contents: calling %s%s", got_contents, (dtype, dformat, ellipsizer(data))) GLib.source_remove(timer) got_contents(dtype, dformat, data)
def _process_invalid(self, packet): message, data = packet[1:3] netlog.info("Received invalid packet: %s", message) netlog(" data: %s", ellipsizer(data)) p = self._protocol exit_code = EXIT_PACKET_FAILURE if not p or p.input_packetcount<=1: exit_code = EXIT_CONNECTION_FAILED self.quit(exit_code)
def do_property_notify(self, event): log("do_property_notify(%s)", event) if not self._enabled: return #ie: atom="PRIMARY-TARGETS", atom="PRIMARY-STRING" parts = event.atom.split("-", 1) assert len(parts)==2 #selection = parts[0] #ie: PRIMARY target = parts[1] #ie: VALUE dtype = "" dformat = 8 try: with xsync: dtype, dformat = X11Window.GetWindowPropertyType(self.xid, event.atom, True) dtype = bytestostr(dtype) MAX_DATA_SIZE = 4*1024*1024 data = X11Window.XGetWindowProperty(self.xid, event.atom, dtype, None, MAX_DATA_SIZE, True) #all the code below deals with INCRemental transfers: if dtype=="INCR" and not self.incr_data_size: #start of an incremental transfer, extract the size assert dformat==32 self.incr_data_size = struct.unpack("@L", data)[0] self.incr_data_chunks = [] self.incr_data_type = None log("incremental clipboard data of size %s", self.incr_data_size) self.reschedule_incr_data_timer() return if self.incr_data_size>0: #incremental is now in progress: if not self.incr_data_type: self.incr_data_type = dtype elif self.incr_data_type!=dtype: log.error("Error: invalid change of data type") log.error(" from %s to %s", self.incr_data_type, dtype) self.reset_incr_data() self.cancel_incr_data_timer() return if data: log("got incremental data: %i bytes", len(data)) self.incr_data_chunks.append(data) self.reschedule_incr_data_timer() return self.cancel_incr_data_timer() data = b"".join(self.incr_data_chunks) log("got incremental data termination, total size=%i bytes", len(data)) self.reset_incr_data() self.got_local_contents(target, dtype, dformat, data) return except PropertyError: log("do_property_notify() property '%s' is gone?", event.atom, exc_info=True) return log("%s=%s (%s : %s)", event.atom, ellipsizer(data), dtype, dformat) if target=="TARGETS": self.targets = xatoms_to_strings(data or b"") self.got_local_contents(target, dtype, dformat, data)
def do_print_pdf(hdc, title=b"PDF Print Test", pdf_data=None): assert pdf_data, "no pdf data" from xpra.log import Logger log = Logger("printing", "win32") log("pdfium=%s", pdfium) buf = c_char_p(pdf_data) log("pdf data buffer: %s", ellipsizer(pdf_data)) log("FPDF_InitLibraryWithConfig=%s", FPDF_InitLibraryWithConfig) config = FPDF_LIBRARY_CONFIG() config.m_pUserFontPaths = None config.version = 2 config.m_pIsolate = None config.m_v8EmbedderSlot = 0 FPDF_InitLibraryWithConfig(config) x = 0 y = 0 w = GetDeviceCaps(hdc, win32con.HORZRES) h = GetDeviceCaps(hdc, win32con.VERTRES) rotate = 0 log("printer device size: %ix%i", w, h) flags = FPDF_PRINTING | FPDF_DEBUG_INFO try: doc = FPDF_LoadMemDocument(cast(buf, c_void_p), len(pdf_data), None) if not doc: log.error("Error: FPDF_LoadMemDocument failed, error: %s", get_error()) return -1 log("FPDF_LoadMemDocument(..)=%s", doc) count = FPDF_GetPageCount(doc) log("FPDF_GetPageCount(%s)=%s", doc, count) docinfo = DOCINFO() docinfo.lpszDocName = LPCSTR(b"%s\0" % title) jobid = StartDocA(hdc, pointer(docinfo)) if jobid < 0: log.error("Error: StartDocA failed: %i", jobid) return jobid log("StartDocA()=%i", jobid) try: for i in range(count): page = FPDF_LoadPage(doc, i) if not page: log.error( "Error: FPDF_LoadPage failed for page %i, error: %s", i, get_error()) return -2 log("FPDF_LoadPage()=%s page %i loaded", page, i) FPDF_RenderPage(hdc, page, x, y, w, h, rotate, flags) log("FPDF_RenderPage page %i rendered", i) finally: EndDoc(hdc) finally: FPDF_DestroyLibrary() return jobid
def got_contents(self, target, dtype=None, dformat=None, data=None): #if this is the special target 'TARGETS', cache the result: if target == "TARGETS" and dtype == "ATOM" and dformat == 32: self.targets = _filter_targets(data) #TODO: tell system what targets we have log("got_contents: tell OS we have %s", csv(self.targets)) image_formats = tuple(x for x in ("image/png", "image/jpeg") if x in self.targets) if image_formats: #request it: self.send_clipboard_request_handler(self, self._selection, image_formats[0]) elif dformat == 8 and dtype in TEXT_TARGETS: log("we got a byte string: %s", ellipsizer(data)) self.set_clipboard_text(net_utf8(data)) elif dformat == 8 and dtype.startswith("image/"): img_format = dtype.split("/")[-1] #ie: 'png' self.set_clipboard_image(img_format, data) else: log("no handling: target=%s, dtype=%s, dformat=%s, data=%s", target, dtype, dformat, ellipsizer(data))
def with_gl_context(self, cb, *args): da = self._backing if da and da.get_mapped(): gl_context = self.gl_context() if gl_context: with gl_context: cb(gl_context, *args) else: cb(None, *args) else: log("GLDrawingArea.with_gl_context delayed: %s%s", cb, ellipsizer(args)) self.on_realize_cb.append((cb, args))
def _clipboard_got_contents(self, request_id, dtype=None, dformat=None, data=None): try: timer, selection, target = self._clipboard_outstanding_requests.pop(request_id) except KeyError: log.warn("Warning: request id %i not found", request_id) log.warn(" timed out already?") return finally: self.progress() glib.source_remove(timer) proxy = self._get_proxy(selection) log("clipboard got contents%s: proxy=%s for selection=%s", (request_id, dtype, dformat, ellipsizer(data)), proxy, selection) if proxy: proxy.got_contents(target, dtype, dformat, data)