def print_screen_info(self): w, h = self.get_root_window_size() try: display = prettify_plug_name(self.root.get_screen().get_display().get_name()) except Exception: display = "" self.do_print_screen_info(display, w, h)
def get_property(self, prop): #subclasses can define properties as attributes: attr_name = prop.replace("-", "_") if hasattr(self, attr_name): return getattr(self, attr_name) #otherwise fallback to default behaviour: if prop == "title": return prettify_plug_name( self.window.get_screen().get_display().get_name()) if prop == "client-machine": return socket.gethostname() if prop == "window-type": return ["NORMAL"] if prop == "fullscreen": return False if prop == "shadow": return True if prop == "depth": return 24 if prop == "scaling": return None if prop == "opacity": return None if prop == "size-hints": size = self.get_dimensions() return { "maximum-size": size, "minimum-size": size, "base-size": size, } if prop == "class-instance": osn = do_get_generic_os_name() if osn == "Linux": try: osn += "-" + get_linux_distribution()[0].replace(" ", "-") except Exception: # pragma: no cover pass return ("xpra-%s" % osn.lower(), "Xpra %s" % osn.replace("-", " ")) if prop == "icons": try: icon_name = get_icon_filename( (get_generic_os_name() or "").lower() + ".png") from PIL import Image img = Image.open(icon_name) log("Image(%s)=%s", icon_name, img) if img: icon_data = load_binary_file(icon_name) assert icon_data w, h = img.size img.close() icon = (w, h, "png", icon_data) icons = (icon, ) return icons except Exception: # pragma: no cover log("failed to return window icon") return () if prop == "content-type": return "desktop" raise ValueError("invalid property: %s" % prop)
def save_fakeXinerama_config(supported=True, source="", ss=[]): """ returns True if the fakexinerama config was modified """ global current_xinerama_config def delfile(msg): global current_xinerama_config if msg: log.warn(msg) cleanup_fakeXinerama() oldconf = current_xinerama_config current_xinerama_config = None return oldconf is not None if not supported: return delfile(None) if len(ss)==0: return delfile("cannot save fake xinerama settings: no display found") if len(ss)>1: return delfile("cannot save fake xinerama settings: more than one display found") if len(ss)==2 and type(ss[0])==int and type(ss[1])==int: #just WxH, not enough display information return delfile("cannot save fake xinerama settings: missing display data from client %s" % source) display_info = ss[0] if len(display_info)<10: return delfile("cannot save fake xinerama settings: incomplete display data from client %s" % source) #display_name, width, height, width_mm, height_mm, \ #monitors, work_x, work_y, work_width, work_height = s[:11] monitors = display_info[5] if len(monitors)>=10: return delfile("cannot save fake xinerama settings: too many monitors! (%s)" % len(monitors)) #generate the file data: from xpra import __version__ data = ["# file generated by xpra %s for display %s" % (__version__, os.environ.get("DISPLAY")), "# %s monitors:" % len(monitors), "%s" % len(monitors)] #the new config (numeric values only) config = [len(monitors)] for i, m in enumerate(monitors): if len(m)<7: return delfile("cannot save fake xinerama settings: incomplete monitor data for monitor: %s" % m) plug_name, x, y, width, height, wmm, hmm = m[:7] data.append("# %s (%smm x %smm)" % (prettify_plug_name(plug_name, "monitor %s" % i), wmm, hmm)) data.append("%s %s %s %s" % (x, y, width, height)) config.append((x, y, width, height)) if current_xinerama_config==config: #we assume that no other process is going to overwrite the deprecated .fakexinerama log("fake xinerama config unchanged") return False current_xinerama_config = config data.append("") contents = "\n".join(data) for filename in fakeXinerama_config_files: try: with open(filename, 'wb') as f: f.write(contents) except Exception as e: log.warn("Error writing fake xinerama file '%s':", filename) log.warn(" %s", e) log("saved %s monitors to fake xinerama files: %s", len(monitors), fakeXinerama_config_files) return True
def makeRootWindowModels(self): screenlog("makeRootWindowModels() root=%s, display_options=%s", self.root, self.display_options) self.capture = self.setup_capture() model_class = self.get_root_window_model_class() models = [] display_name = prettify_plug_name(self.root.get_screen().get_display().get_name()) monitors = self.get_shadow_monitors() match_str = None multi_window = MULTI_WINDOW geometries = None if "=" in self.display_options: #parse the display options as a dictionary: opt_dict = parse_simple_dict(self.display_options) windows = opt_dict.get("windows") if windows: self.window_matches = windows.split("/") return self.makeDynamicWindowModels() match_str = opt_dict.get("plug") multi_window = parse_bool("multi-window", opt_dict.get("multi-window", multi_window)) geometries_str = opt_dict.get("geometry") if geometries_str: geometries = parse_geometries(geometries_str) else: try: geometries = parse_geometries(self.display_options) except Exception: match_str = self.display_options if not multi_window or geometries: for geometry in (geometries or (self.root.get_geometry()[:4],)): model = model_class(self.root, self.capture, display_name, geometry) models.append(model) return models found = [] screenlog("capture inputs matching %r", match_str or "all") for i, monitor in enumerate(monitors): plug_name, x, y, width, height, scale_factor = monitor title = display_name if plug_name or i>1: title = plug_name or str(i) found.append(plug_name or title) if match_str and not(title in match_str or plug_name in match_str): screenlog.info(" skipped monitor %s", plug_name or title) continue geometry = (x, y, width, height) model = model_class(self.root, self.capture, title, geometry) models.append(model) screenlog("monitor %i: %10s geometry=%s, scale factor=%s", i, title, geometry, scale_factor) screenlog("makeRootWindowModels()=%s", models) if not models and match_str: screenlog.warn("Warning: no monitors found matching %r", match_str) screenlog.warn(" only found: %s", csv(found)) return models
def get_property(self, prop): if prop == "title": return prettify_plug_name( self.window.get_screen().get_display().get_name()) elif prop == "client-machine": return socket.gethostname() elif prop == "window-type": return ["NORMAL"] elif prop == "fullscreen": return False elif prop == "shadow": return True elif prop == "scaling": return None elif prop == "opacity": return None elif prop == "size-hints": size = self.window.get_size() return { "maximum-size": size, "minimum-size": size, "base-size": size } elif prop == "class-instance": osn = self.get_generic_os_name() return ("xpra-%s" % osn, "Xpra-%s" % osn.upper()) elif prop == "icon": #convert it to a cairo surface.. #because that's what the property is expected to be try: import gtk.gdk from xpra.platform.paths import get_icon icon_name = self.get_generic_os_name() + ".png" icon = get_icon(icon_name) log("icon(%s)=%s", icon_name, icon) if not icon: return None import cairo surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, icon.get_width(), icon.get_height()) gc = gtk.gdk.CairoContext(cairo.Context(surf)) gc.set_source_pixbuf(icon, 0, 0) gc.paint() log("icon=%s", surf) return surf except: log("failed to return window icon") return None else: raise Exception("invalid property: %s" % prop) return None
def get_property(self, prop): if prop=="title": return prettify_plug_name(self.window.get_screen().get_display().get_name()) elif prop=="client-machine": return socket.gethostname() elif prop=="window-type": return ["NORMAL"] elif prop=="fullscreen": return False elif prop=="shadow": return True elif prop=="scaling": return None elif prop=="opacity": return None elif prop=="size-hints": size = self.window.get_size() return {"maximum-size" : size, "minimum-size" : size, "base-size" : size} elif prop=="class-instance": osn = self.get_generic_os_name() return ("xpra-%s" % osn, "Xpra-%s" % osn.upper()) elif prop=="icon": #convert it to a cairo surface.. #because that's what the property is expected to be try: import gtk.gdk from xpra.platform.paths import get_icon icon_name = self.get_generic_os_name()+".png" icon = get_icon(icon_name) log("icon(%s)=%s", icon_name, icon) if not icon: return None import cairo surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, icon.get_width(), icon.get_height()) gc = gtk.gdk.CairoContext(cairo.Context(surf)) gc.set_source_pixbuf(icon, 0, 0) gc.paint() log("icon=%s", surf) return surf except: log("failed to return window icon") return None else: raise ValueError("invalid property: %s" % prop) return None
def get_property(self, prop): #subclasses can define properties as attributes: attr_name = prop.replace("-", "_") if hasattr(self, attr_name): return getattr(self, attr_name) #otherwise fallback to default behaviour: if prop == "title": return prettify_plug_name( self.window.get_screen().get_display().get_name()) elif prop == "client-machine": return socket.gethostname() elif prop == "window-type": return ["NORMAL"] elif prop == "fullscreen": return False elif prop == "shadow": return True elif prop == "scaling": return None elif prop == "opacity": return None elif prop == "size-hints": size = self.get_dimensions() return { "maximum-size": size, "minimum-size": size, "base-size": size } elif prop == "class-instance": osn = get_generic_os_name() return ("xpra-%s" % osn, "Xpra-%s" % osn.upper()) elif prop == "icon": try: from xpra.platform.paths import get_icon icon_name = get_generic_os_name() + ".png" icon = get_icon(icon_name) log("icon(%s)=%s", icon_name, icon) return icon except: log("failed to return window icon") return None elif prop == "content-type": return "desktop" else: raise ValueError("invalid property: %s" % prop) return None
def __init__(self, root_window, capture=None): self.window = root_window self.title = prettify_plug_name( root_window.get_screen().get_display().get_name()) self.geometry = root_window.get_geometry()[:4] self.capture = capture self.property_names = [ "title", "class-instance", "client-machine", "window-type", "size-hints", "icons", "shadow", "depth", ] self.dynamic_property_names = [] self.internal_property_names = ["content-type"]
def get_property(self, prop): if prop=="title": return prettify_plug_name(self.window.get_screen().get_display().get_name()) elif prop=="client-machine": return socket.gethostname() elif prop=="window-type": return ["NORMAL"] elif prop=="fullscreen": return False elif prop=="scaling": return None elif prop=="opacity": return None elif prop=="size-hints": size = self.window.get_size() return RootSizeHints(size) else: raise Exception("invalid property: %s" % prop) return None
def get_property(self, prop): if prop == "title": return prettify_plug_name( self.window.get_screen().get_display().get_name()) elif prop == "client-machine": return socket.gethostname() elif prop == "window-type": return ["NORMAL"] elif prop == "fullscreen": return False elif prop == "shadow": return True elif prop == "scaling": return None elif prop == "opacity": return None elif prop == "size-hints": size = self.window.get_size() return { "maximum-size": size, "minimum-size": size, "base-size": size } elif prop == "class-instance": osn = get_generic_os_name() return ("xpra-%s" % osn, "Xpra-%s" % osn.upper()) elif prop == "icon": try: from xpra.platform.paths import get_icon icon_name = get_generic_os_name() + ".png" icon = get_icon(icon_name) log("icon(%s)=%s", icon_name, icon) return icon except: log("failed to return window icon") return None else: raise ValueError("invalid property: %s" % prop) return None
def makeRootWindowModels(self): screenlog("makeRootWindowModels() root=%s, display_options=%s", self.root, self.display_options) self.capture = self.setup_capture() model_class = self.get_root_window_model_class() models = [] display_name = prettify_plug_name( self.root.get_screen().get_display().get_name()) monitors = self.get_shadow_monitors() match_str = None multi_window = MULTI_WINDOW geometries = None def parse_geometry(s): try: parts = s.split("@") if len(parts) == 1: x = y = 0 else: x, y = [int(v.strip(" ")) for v in parts[1].split("x")] w, h = [int(v.strip(" ")) for v in parts[0].split("x")] geometry = [x, y, w, h] screenlog("capture geometry: %s", geometry) return geometry except ValueError: screenlog("failed to parse geometry %r", s, exc_info=True) screenlog.error( "Error: invalid display geometry specified: %r", s) screenlog.error(" use the format: WIDTHxHEIGHT@x,y") raise def parse_geometries(s): g = [] for geometry_str in s.split("/"): if geometry_str: g.append(parse_geometry(geometry_str)) return g if "=" in self.display_options: #parse the display options as a dictionary: opt_dict = parse_simple_dict(self.display_options) match_str = opt_dict.get("plug") multi_window = parse_bool( "multi-window", opt_dict.get("multi-window", multi_window)) geometries_str = opt_dict.get("geometry") if geometries_str: geometries = parse_geometries(geometries_str) else: try: geometries = parse_geometries(self.display_options) except: match_str = self.display_options if not multi_window or geometries: for geometry in (geometries or (None, )): model = model_class(self.root, self.capture) model.title = display_name if geometry: model.geometry = geometry models.append(model) return models found = [] screenlog("capture inputs matching %r", match_str or "all") for i, monitor in enumerate(monitors): plug_name, x, y, width, height, scale_factor = monitor title = display_name if plug_name or i > 1: title = plug_name or str(i) found.append(plug_name or title) if match_str and not (title in match_str or plug_name in match_str): screenlog.info(" skipped monitor %s", plug_name or title) continue model = model_class(self.root, self.capture) model.title = title model.geometry = (x, y, width, height) models.append(model) screenlog("monitor %i: %10s geometry=%s, scale factor=%s", i, title, model.geometry, scale_factor) screenlog("makeRootWindowModels()=%s", models) if not models and match_str: screenlog.warn("Warning: no monitors found matching %r", match_str) screenlog.warn(" only found: %s", csv(found)) return models
def save_fakeXinerama_config(supported=True, source="", ss=()): """ returns True if the fakexinerama config was modified """ global current_xinerama_config def delfile(msg): global current_xinerama_config if msg: log.warn(msg) cleanup_fakeXinerama() oldconf = current_xinerama_config current_xinerama_config = None return oldconf is not None if not supported: return delfile(None) if not ss: return delfile("cannot save fake xinerama settings: no display found") if len(ss) > 1: return delfile( "cannot save fake xinerama settings: more than one display found") display_info = ss[0] if len(display_info) == 2 and isinstance( display_info[0], int) and isinstance(display_info[1], int): #just WxH, not enough display information return delfile( "cannot save fake xinerama settings: missing display data from client %s" % source) if len(display_info) < 10: return delfile( "cannot save fake xinerama settings: incomplete display data from client %s" % source) #display_name, width, height, width_mm, height_mm, \ #monitors, work_x, work_y, work_width, work_height = s[:11] monitors = display_info[5] if len(monitors) >= 10: return delfile( "cannot save fake xinerama settings: too many monitors! (%s)" % len(monitors)) #generate the file data: data = [ "# file generated by xpra %s for display %s" % (XPRA_VERSION, os.environ.get("DISPLAY")), "# %s monitors:" % len(monitors), "%s" % len(monitors) ] #the new config (numeric values only) config = [len(monitors)] for i, m in enumerate(monitors): if len(m) < 7: return delfile( "cannot save fake xinerama settings: incomplete monitor data for monitor: %s" % m) plug_name, x, y, width, height, wmm, hmm = m[:7] data.append( "# %s (%smm x %smm)" % (prettify_plug_name(plug_name, "monitor %s" % i), wmm, hmm)) data.append("%s %s %s %s" % (x, y, width, height)) config.append((x, y, width, height)) if current_xinerama_config == config: #we assume that no other process is going to overwrite the deprecated .fakexinerama log("fake xinerama config unchanged") return False log("fake xinerama config changed:") log(" old=%s", current_xinerama_config) log(" new=%s", config) current_xinerama_config = config data.append("") contents = "\n".join(data) for filename in fakeXinerama_config_files: try: with open(filename, 'wb') as f: f.write(contents.encode("utf8")) except Exception as e: log("writing to '%s'", filename, exc_info=True) log.warn("Error writing fake xinerama file '%s':", filename) log.warn(" %s", e) log("saved %s monitors to fake xinerama files: %s", len(monitors), fakeXinerama_config_files) return True
def __init__(self, client, session_name, window_icon_pixbuf, conn, get_pixbuf): gtk.Window.__init__(self) self.client = client self.session_name = session_name self.connection = conn self.last_populate_time = 0 self.last_populate_statistics = 0 self.is_closed = False self.get_pixbuf = get_pixbuf if not self.session_name or self.session_name=="Xpra": title = "Session Info" else: title = "%s: Session Info" % self.session_name self.set_title(title) self.set_destroy_with_parent(True) self.set_resizable(True) self.set_decorated(True) if window_icon_pixbuf: self.set_icon(window_icon_pixbuf) self.set_position(WIN_POS_CENTER) #tables on the left in a vbox with buttons at the top: self.tab_box = gtk.VBox(False, 0) self.tab_button_box = gtk.HBox(True, 0) self.tabs = [] #pairs of button, table self.populate_cb = None self.tab_box.pack_start(self.tab_button_box, expand=False, fill=True, padding=0) #Package Table: tb, _ = self.table_tab("package.png", "Software", self.populate_package) #title row: tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0) tb.inc() def make_os_str(*args): s = os_info(*args) return "\n".join(s) distro = "" if hasattr(python_platform, "linux_distribution"): distro = python_platform.linux_distribution() LOCAL_PLATFORM_NAME = make_os_str(sys.platform, python_platform.release(), python_platform.platform(), distro) SERVER_PLATFORM_NAME = make_os_str(self.client._remote_platform, self.client._remote_platform_release, self.client._remote_platform_platform, self.client._remote_platform_linux_distribution) tb.new_row("Operating System", label(LOCAL_PLATFORM_NAME), label(SERVER_PLATFORM_NAME)) scaps = self.client.server_capabilities from xpra.__init__ import __version__ tb.new_row("Xpra", label(__version__), label(self.client._remote_version or "unknown")) cl_rev, cl_ch, cl_date = "unknown", "", "" try: from xpra.build_info import BUILD_DATE as cl_date, BUILD_TIME as cl_time from xpra.src_info import REVISION as cl_rev, LOCAL_MODIFICATIONS as cl_ch #@UnresolvedImport except: pass def make_version_str(version): if version and type(version) in (tuple, list): version = ".".join([str(x) for x in version]) return version or "unknown" def server_info(*prop_names): for x in prop_names: v = scaps.capsget(x) if v is not None: return v if self.client.server_last_info: v = self.client.server_last_info.get(x) if v is not None: return v return None def server_version_info(*prop_names): return make_version_str(server_info(*prop_names)) def make_revision_str(rev, changes): if not changes: return rev return "%s (%s changes)" % (rev, changes) def make_datetime(date, time): if not time: return date return "%s %s" % (date, time) tb.new_row("Revision", label(make_revision_str(cl_rev, cl_ch)), label(make_revision_str(self.client._remote_revision, server_version_info("build.local_modifications", "local_modifications")))) tb.new_row("Build date", label(make_datetime(cl_date, cl_time)), label(make_datetime(server_info("build_date", "build.date"), server_info("build.time")))) gtk_version_info = get_gtk_version_info() def client_vinfo(prop, fallback="unknown"): k = "%s.version" % prop return label(make_version_str(gtk_version_info.get(k, fallback))) def server_vinfo(prop): k = "%s.version" % prop fk = "%s_version" % prop return label(server_version_info(k, fk)) tb.new_row("Glib", client_vinfo("glib"), server_vinfo("glib")) tb.new_row("PyGlib", client_vinfo("pyglib"), server_vinfo("pyglib")) tb.new_row("Gobject", client_vinfo("gobject"), server_vinfo("gobject")) tb.new_row("PyGTK", client_vinfo("pygtk", ""), server_vinfo("pygtk")) tb.new_row("GTK", client_vinfo("gtk"), server_vinfo("gtk")) tb.new_row("GDK", client_vinfo("gdk"), server_vinfo("gdk")) tb.new_row("Cairo", client_vinfo("cairo"), server_vinfo("cairo")) tb.new_row("Pango", client_vinfo("pango"), server_vinfo("pango")) tb.new_row("Python", label(python_platform.python_version()), label(server_version_info("server.python.version", "python_version", "python.version"))) cl_gst_v, cl_pygst_v = "", "" try: from xpra.sound.gstreamer_util import gst_version as cl_gst_v, pygst_version as cl_pygst_v except Exception as e: log("cannot load gstreamer: %s", e) tb.new_row("GStreamer", label(make_version_str(cl_gst_v)), label(server_version_info("sound.gst.version", "gst_version"))) tb.new_row("pygst", label(make_version_str(cl_pygst_v)), label(server_version_info("sound.pygst.version", "pygst_version"))) tb.new_row("OpenGL", label(make_version_str(self.client.opengl_props.get("opengl", "n/a"))), label("n/a")) tb.new_row("OpenGL Vendor", label(make_version_str(self.client.opengl_props.get("vendor", ""))), label("n/a")) tb.new_row("PyOpenGL", label(make_version_str(self.client.opengl_props.get("pyopengl", "n/a"))), label("n/a")) # Features Table: vbox = self.vbox_tab("features.png", "Features", self.populate_features) #add top table: tb = TableBuilder(rows=1, columns=2) table = tb.get_table() al = gtk.Alignment(xalign=0.5, yalign=0.5, xscale=0.0, yscale=1.0) al.add(table) vbox.pack_start(al, expand=True, fill=False, padding=10) #top table contents: randr_box = gtk.HBox(False, 20) self.server_randr_label = label() self.server_randr_icon = gtk.Image() randr_box.add(self.server_randr_icon) randr_box.add(self.server_randr_label) tb.new_row("RandR Support", randr_box) opengl_box = gtk.HBox(False, 20) self.client_opengl_label = label() self.client_opengl_label.set_line_wrap(True) self.client_opengl_icon = gtk.Image() opengl_box.add(self.client_opengl_icon) opengl_box.add(self.client_opengl_label) tb.new_row("Client OpenGL", opengl_box) self.opengl_buffering = label() tb.new_row("OpenGL Buffering", self.opengl_buffering) self.server_mmap_icon = gtk.Image() tb.new_row("Memory Mapped Transfers", self.server_mmap_icon) self.server_clipboard_icon = gtk.Image() tb.new_row("Clipboard", self.server_clipboard_icon) self.server_notifications_icon = gtk.Image() tb.new_row("Notification Forwarding", self.server_notifications_icon) self.server_bell_icon = gtk.Image() tb.new_row("Bell Forwarding", self.server_bell_icon) self.server_cursors_icon = gtk.Image() tb.new_row("Cursor Forwarding", self.server_cursors_icon) speaker_box = gtk.HBox(False, 20) self.server_speaker_icon = gtk.Image() speaker_box.add(self.server_speaker_icon) self.speaker_codec_label = label() speaker_box.add(self.speaker_codec_label) tb.new_row("Speaker Forwarding", speaker_box) microphone_box = gtk.HBox(False, 20) self.server_microphone_icon = gtk.Image() microphone_box.add(self.server_microphone_icon) self.microphone_codec_label = label() microphone_box.add(self.microphone_codec_label) tb.new_row("Microphone Forwarding", microphone_box) #add bottom table: tb = TableBuilder(rows=1, columns=3) table = tb.get_table() vbox.pack_start(table, expand=True, fill=True, padding=20) #bottom table headings: tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Client"), 1, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Server"), 2, xoptions=EXPAND|FILL, xpadding=0) tb.inc() #bottom table contents: self.client_encodings_label = label() self.client_encodings_label.set_line_wrap(True) self.client_encodings_label.set_size_request(250, -1) self.server_encodings_label = label() self.server_encodings_label.set_line_wrap(True) self.server_encodings_label.set_size_request(250, -1) tb.new_row("Encodings", self.client_encodings_label, self.server_encodings_label) self.client_speaker_codecs_label = label() self.server_speaker_codecs_label = label() tb.new_row("Speaker Codecs", self.client_speaker_codecs_label, self.server_speaker_codecs_label) self.client_microphone_codecs_label = label() self.server_microphone_codecs_label = label() tb.new_row("Microphone Codecs", self.client_microphone_codecs_label, self.server_microphone_codecs_label) self.client_packet_encoders_label = label() self.server_packet_encoders_label = label() tb.new_row("Packet Encoders", self.client_packet_encoders_label, self.server_packet_encoders_label) self.client_packet_compressors_label = label() self.server_packet_compressors_label = label() tb.new_row("Packet Compressors", self.client_packet_compressors_label, self.server_packet_compressors_label) # Connection Table: tb, _ = self.table_tab("connect.png", "Connection", self.populate_connection) tb.new_row("Server Endpoint", label(self.connection.target)) if self.client.server_display: tb.new_row("Server Display", label(prettify_plug_name(self.client.server_display))) hostname = scaps.strget("hostname") if hostname: tb.new_row("Server Hostname", label(hostname)) if self.client.server_platform: tb.new_row("Server Platform", label(self.client.server_platform)) self.server_load_label = label() tb.new_row("Server Load", self.server_load_label, label_tooltip="Average over 1, 5 and 15 minutes") self.session_started_label = label() tb.new_row("Session Started", self.session_started_label) self.session_connected_label = label() tb.new_row("Session Connected", self.session_connected_label) self.input_packets_label = label() tb.new_row("Packets Received", self.input_packets_label) self.input_bytes_label = label() tb.new_row("Bytes Received", self.input_bytes_label) self.output_packets_label = label() tb.new_row("Packets Sent", self.output_packets_label) self.output_bytes_label = label() tb.new_row("Bytes Sent", self.output_bytes_label) self.compression_label = label() tb.new_row("Encoding + Compression", self.compression_label) self.connection_type_label = label() tb.new_row("Connection Type", self.connection_type_label) self.input_encryption_label = label() tb.new_row("Input Encryption", self.input_encryption_label) self.output_encryption_label = label() tb.new_row("Output Encryption", self.output_encryption_label) self.speaker_label = label() self.speaker_details = label(font="monospace 10") tb.new_row("Speaker", self.speaker_label, self.speaker_details) self.microphone_label = label() tb.new_row("Microphone", self.microphone_label) # Details: tb, stats_box = self.table_tab("browse.png", "Statistics", self.populate_statistics) tb.widget_xalign = 1.0 tb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Latest"), 1, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Minimum"), 2, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Average"), 3, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("90 percentile"), 4, xoptions=EXPAND|FILL, xpadding=0) tb.attach(title_box("Maximum"), 5, xoptions=EXPAND|FILL, xpadding=0) tb.inc() def maths_labels(): return label(), label(), label(), label(), label() self.server_latency_labels = maths_labels() tb.add_row(label("Server Latency (ms)", "The time it takes for the server to respond to pings"), *self.server_latency_labels) self.client_latency_labels = maths_labels() tb.add_row(label("Client Latency (ms)", "The time it takes for the client to respond to pings, as measured by the server"), *self.client_latency_labels) if self.client.windows_enabled: if self.client.server_info_request: self.batch_labels = maths_labels() tb.add_row(label("Batch Delay (ms)", "How long the server waits for new screen updates to accumulate before processing them"), *self.batch_labels) self.damage_labels = maths_labels() tb.add_row(label("Damage Latency (ms)", "The time it takes to compress a frame and pass it to the OS network layer"), *self.damage_labels) self.quality_labels = maths_labels() tb.add_row(label("Encoding Quality (pct)"), *self.quality_labels) self.speed_labels = maths_labels() tb.add_row(label("Encoding Speed (pct)"), *self.speed_labels) self.decoding_labels = maths_labels() tb.add_row(label("Decoding Latency (ms)", "How long it takes the client to decode a screen update"), *self.decoding_labels) self.regions_per_second_labels = maths_labels() tb.add_row(label("Regions/s", "The number of screen updates per second (includes both partial and full screen updates)"), *self.regions_per_second_labels) self.regions_sizes_labels = maths_labels() tb.add_row(label("Pixels/region", "The number of pixels per screen update"), *self.regions_sizes_labels) self.pixels_per_second_labels = maths_labels() tb.add_row(label("Pixels/s", "The number of pixels processed per second"), *self.pixels_per_second_labels) #Window count stats: wtb = TableBuilder() stats_box.add(wtb.get_table()) #title row: wtb.attach(title_box(""), 0, xoptions=EXPAND|FILL, xpadding=0) wtb.attach(title_box("Regular"), 1, xoptions=EXPAND|FILL, xpadding=0) wtb.attach(title_box("Transient"), 2, xoptions=EXPAND|FILL, xpadding=0) wtb.attach(title_box("Trays"), 3, xoptions=EXPAND|FILL, xpadding=0) if self.client.client_supports_opengl: wtb.attach(title_box("OpenGL"), 4, xoptions=EXPAND|FILL, xpadding=0) wtb.inc() wtb.attach(label("Windows:"), 0, xoptions=EXPAND|FILL, xpadding=0) self.windows_managed_label = label() wtb.attach(self.windows_managed_label, 1) self.transient_managed_label = label() wtb.attach(self.transient_managed_label, 2) self.trays_managed_label = label() wtb.attach(self.trays_managed_label, 3) if self.client.client_supports_opengl: self.opengl_label = label() wtb.attach(self.opengl_label, 4) #add encoder info: etb = TableBuilder() stats_box.add(etb.get_table()) self.encoder_info_box = gtk.HBox(spacing=4) etb.new_row("Window Encoders", self.encoder_info_box) if not is_gtk3(): #needs porting to cairo... self.graph_box = gtk.VBox(False, 10) self.add_tab("statistics.png", "Graphs", self.populate_graphs, self.graph_box) bandwidth_label = "Bandwidth used" if SHOW_PIXEL_STATS: bandwidth_label += ",\nand number of pixels rendered" self.bandwidth_graph = self.add_graph_button(bandwidth_label, self.save_graphs) self.connect("realize", self.populate_graphs) self.latency_graph = self.add_graph_button(None, self.save_graphs) self.pixel_in_data = deque(maxlen=N_SAMPLES+4) self.net_in_bytecount = deque(maxlen=N_SAMPLES+4) self.net_out_bytecount = deque(maxlen=N_SAMPLES+4) self.sound_in_bytecount = deque(maxlen=N_SAMPLES+4) self.sound_out_bytecount = deque(maxlen=N_SAMPLES+4) self.set_border_width(15) self.add(self.tab_box) if not is_gtk3(): self.set_geometry_hints(self.tab_box) def window_deleted(*args): self.is_closed = True self.connect('delete_event', window_deleted) self.show_tab(self.tabs[0][2]) self.set_size_request(-1, 480) self.init_counters() self.populate() self.populate_all() gobject.timeout_add(1000, self.populate) gobject.timeout_add(100, self.populate_tab) add_close_accel(self, self.destroy)
def save_fakexinerama_config(self): """ returns True if the fakexinerama config was modified """ xinerama_files = self.get_xinerama_filenames() def delfile(msg): if msg: log.warn(msg) self.cleanup_fakexinerama() oldconf = self.current_xinerama_config self.current_xinerama_config = None return oldconf is not None if not self.fake_xinerama: return delfile(None) ui_client_count = len([True for s in self._server_sources.values() if s.ui_client]) if ui_client_count!=1: return delfile("fakeXinerama can only be enabled for a single client (found %s)" % ui_client_count) source = self._server_sources.values()[0] ss = source.screen_sizes if len(ss)==0: return delfile("cannot save fake xinerama settings: no display found") if len(ss)>1: return delfile("cannot save fake xinerama settings: more than one display found") if len(ss)==2 and type(ss[0])==int and type(ss[1])==int: #just WxH, not enough display information return delfile("cannot save fake xinerama settings: missing display data from client %s" % source) display_info = ss[0] if len(display_info)<10: return delfile("cannot save fake xinerama settings: incomplete display data from client %s" % source) #display_name, width, height, width_mm, height_mm, \ #monitors, work_x, work_y, work_width, work_height = s[:11] monitors = display_info[5] if len(monitors)>=10: return delfile("cannot save fake xinerama settings: too many monitors! (%s)" % len(monitors)) #generate the file data: from xpra import __version__ data = ["# file generated by xpra %s for display %s" % (__version__, os.environ.get("DISPLAY")), "# %s monitors:" % len(monitors), "%s" % len(monitors)] #the new config (numeric values only) config = [len(monitors)] for i, m in enumerate(monitors): if len(m)<7: return delfile("cannot save fake xinerama settings: incomplete monitor data for monitor: %s" % m) plug_name, x, y, width, height, wmm, hmm = m[:7] data.append("# %s (%smm x %smm)" % (prettify_plug_name(plug_name, "monitor %s" % i), wmm, hmm)) data.append("%s %s %s %s" % (x, y, width, height)) config.append((x, y, width, height)) if self.current_xinerama_config==config: #we assume that no other process is going to overwrite the deprecated .fakexinerama log("fake xinerama config unchanged") return False self.current_xinerama_config = config data.append("") contents = "\n".join(data) for filename in xinerama_files: try: with open(filename, 'wb') as f: f.write(contents) except Exception as e: log.warn("error writing fake xinerama file %s: %s", filename, e) log("saved %s monitors to fake xinerama files: %s", len(monitors), xinerama_files) return True
"cannot save fake xinerama settings: too many monitors! (%s)" % len(monitors)) #generate the file data: data = ["# %s monitors:" % len(monitors), "%s" % len(monitors)] #the new config (numeric values only) config = [len(monitors)] i = 0 for m in monitors: if len(m) < 7: return delfile( "cannot save fake xinerama settings: incomplete monitor data for monitor: %s" % m) plug_name, x, y, width, height, wmm, hmm = m[:7] data.append( "# %s (%smm x %smm)" % (prettify_plug_name(plug_name, "monitor %s" % i), wmm, hmm)) data.append("%s %s %s %s" % (x, y, width, height)) config.append((x, y, width, height)) i += 1 data.append("") contents = "\n".join(data) for filename in xinerama_files: try: f = None try: f = open(filename, 'wb') f.write(contents) except Exception, e: log.warn("error writing fake xinerama file %s: %s", filename, e) pass
#display_name, width, height, width_mm, height_mm, \ #monitors, work_x, work_y, work_width, work_height = s[:11] monitors = display_info[5] if len(monitors)>=10: return delfile("cannot save fake xinerama settings: too many monitors! (%s)" % len(monitors)) #generate the file data: data = ["# %s monitors:" % len(monitors), "%s" % len(monitors)] #the new config (numeric values only) config = [len(monitors)] i = 0 for m in monitors: if len(m)<7: return delfile("cannot save fake xinerama settings: incomplete monitor data for monitor: %s" % m) plug_name, x, y, width, height, wmm, hmm = m[:8] data.append("# %s (%smm x %smm)" % (prettify_plug_name(plug_name, "monitor %s" % i), wmm, hmm)) data.append("%s %s %s %s" % (x, y, width, height)) config.append((x, y, width, height)) i += 1 data.append("") contents = "\n".join(data) for filename in xinerama_files: try: f = None try: f = open(filename, 'wb') f.write(contents) except Exception, e: log.warn("error writing fake xinerama file %s: %s", filename, e) pass finally: