Beispiel #1
0
    def _do_paint_rgb(self, cairo_format, has_alpha, img_data, x, y, width, height, rowstride, options):
        """ must be called from UI thread """
        log("cairo._do_paint_rgb(%s, %s, %s bytes,%s,%s,%s,%s,%s,%s)", cairo_format, has_alpha, len(img_data), x, y, width, height, rowstride, options)
        rgb_format = options.strget("rgb_format", "RGB")
        if _memoryview and isinstance(img_data, _memoryview):
            #Pixbuf cannot use the memoryview directly:
            img_data = img_data.tobytes()
        #"cairo.ImageSurface.create_for_data" is not implemented in GTK3! ARGH!
        # http://cairographics.org/documentation/pycairo/3/reference/surfaces.html#cairo.ImageSurface.create_for_data
        # "Not yet available in Python 3"
        #
        #It is available in the cffi cairo bindings, which can be used instead of pycairo
        # but then we can't use it from the draw callbacks:
        # https://mail.gnome.org/archives/python-hackers-list/2011-December/msg00004.html
        # "PyGObject just lacks the glue code that allows it to pass the statically-wrapped
        # cairo.Pattern to introspected methods"

        if not is_gtk3() and rgb_format in ("ARGB", "XRGB"):
            #the pixel format is also what cairo expects
            #maybe we should also check that the stride is acceptable for cairo?
            #cairo_stride = cairo.ImageSurface.format_stride_for_width(cairo_format, width)
            #log("cairo_stride=%s, stride=%s", cairo_stride, rowstride)
            img_surface = cairo.ImageSurface.create_for_data(img_data, cairo_format, width, height, rowstride)
            return self.cairo_paint_surface(img_surface, x, y)

        if not is_gtk3() and rgb_format in ("RGBA", "RGBX"):
            #with GTK2, we can use a pixbuf from RGB(A) pixels
            if rgb_format=="RGBA":
                #we have to unpremultiply for pixbuf!
                img_data = self.unpremultiply(img_data)
            pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, has_alpha, 8, width, height, rowstride)
            return self.cairo_paint_pixbuf(pixbuf, x, y)

        #PIL fallback
        PIL = get_codec("PIL")
        if has_alpha:
            oformat = "RGBA"
        else:
            oformat = "RGB"
        img = PIL.Image.frombuffer(oformat, (width,height), img_data, "raw", rgb_format, rowstride, 1)
        #This is insane, the code below should work, but it doesn't:
        # img_data = bytearray(img.tostring('raw', oformat, 0, 1))
        # pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, True, 8, width, height, rowstride)
        # success = self.cairo_paint_pixbuf(pixbuf, x, y)
        #So we still rountrip via PNG:
        png = BytesIOClass()
        img.save(png, format="PNG")
        reader = BytesIOClass(png.getvalue())
        png.close()
        img = cairo.ImageSurface.create_from_png(reader)
        return self.cairo_paint_surface(img, x, y)
Beispiel #2
0
def get_preferred_size(widget):
    if is_gtk3():
        #ignore "min", we only care about "natural":
        _, w = widget.get_preferred_width()
        _, h = widget.get_preferred_height()
        return w, h
    return widget.size_request()
Beispiel #3
0
def get_pixbuf_from_data(rgb_data, has_alpha, w, h, rowstride):
    if is_gtk3():
        data = array.array('B', strtobytes(rgb_data))
        return GdkPixbuf.Pixbuf.new_from_data(data, GdkPixbuf.Colorspace.RGB,
                                         True, 8, w, h, rowstride,
                                         None, None)
    return gdk.pixbuf_new_from_data(rgb_data, gdk.COLORSPACE_RGB, has_alpha, 8, w, h, rowstride)
Beispiel #4
0
def add_close_accel(window, callback):
    if is_gtk3():
        return      #TODO: implement accel for gtk3
    accel_group = gtk.AccelGroup()
    accel_group.connect_group(ord('w'), gdk.CONTROL_MASK, gtk.ACCEL_LOCKED, callback)
    window.add_accel_group(accel_group)
    accel_group = gtk.AccelGroup()
    key, mod = gtk.accelerator_parse('<Alt>F4')
    accel_group.connect_group(key, mod, gtk.ACCEL_LOCKED, callback)
    escape_key, modifier = gtk.accelerator_parse('Escape')
    accel_group.connect_group(escape_key, modifier, gtk.ACCEL_LOCKED |  gtk.ACCEL_VISIBLE, callback)
    window.add_accel_group(accel_group)
Beispiel #5
0
 def owner_changed(self, cb, event):
     r = {}
     if not is_gtk3():
         r = {gtk.gdk.OWNER_CHANGE_CLOSE : "close",
              gtk.gdk.OWNER_CHANGE_DESTROY : "destroy",
              gtk.gdk.OWNER_CHANGE_NEW_OWNER : "new owner"}
     owner = self.clipboard.get_owner()
     #print("xid=%s, owner=%s" % (self.value_entry.get_window().xid, event.owner))
     weownit = (owner is not None)
     if weownit:
         owner_info="(us)"
     else:
         owner_info = hex(event.owner)
     self.log("Owner changed, reason: %s, new owner=%s" % (
                     r.get(event.reason, event.reason), owner_info))
Beispiel #6
0
def add_close_accel(window, callback):
    if is_gtk3():
        def connect(ag, *args):
            ag.connect(*args)
    else:
        def connect(ag, *args):
            ag.connect_group(*args)
    accel_group = gtk.AccelGroup()
    key, mod = gtk.accelerator_parse('<control>F4')
    connect(accel_group, key, mod, ACCEL_LOCKED, callback)
    window.add_accel_group(accel_group)
    accel_group = gtk.AccelGroup()
    key, mod = gtk.accelerator_parse('<Alt>F4')
    connect(accel_group, key, mod, ACCEL_LOCKED, callback)
    escape_key, modifier = gtk.accelerator_parse('Escape')
    connect(accel_group, escape_key, modifier, ACCEL_LOCKED |  ACCEL_VISIBLE, callback)
    window.add_accel_group(accel_group)
Beispiel #7
0
def about(on_close=None):
	global about_dialog
	if about_dialog:
		about_dialog.show()
		about_dialog.present()
		return
	from xpra.platform.paths import get_icon
	xpra_icon = get_icon("xpra.png")
	dialog = gtk.AboutDialog()
	if not is_gtk3():
		def on_website_hook(dialog, web, *args):
			''' called when the website item is selected '''
			webbrowser.open(SITE_URL)
		def on_email_hook(dialog, mail, *args):
			webbrowser.open("mailto://[email protected]")
		gtk.about_dialog_set_url_hook(on_website_hook)
		gtk.about_dialog_set_email_hook(on_email_hook)
		if xpra_icon:
			dialog.set_icon(xpra_icon)
	dialog.set_name("Xpra")
	dialog.set_version(__version__)
	dialog.set_authors(('Antoine Martin <*****@*****.**>',
						'Nathaniel Smith <*****@*****.**>',
						'Serviware - Arthur Huillet <*****@*****.**>'))
	_license = load_license()
	dialog.set_license(_license or "Your installation may be corrupted,"
					+ " the license text for GPL version 2 could not be found,"
					+ "\nplease refer to:\nhttp://www.gnu.org/licenses/gpl-2.0.txt")
	dialog.set_comments("\n".join(get_build_info()))
	dialog.set_website(SITE_URL)
	dialog.set_website_label(SITE_DOMAIN)
	if xpra_icon:
		dialog.set_logo(xpra_icon)
	if hasattr(dialog, "set_program_name"):
		dialog.set_program_name(APPLICATION_NAME)
	def close(*args):
		close_about()
		#the about function may be called as a widget callback
		#so avoid calling the widget as if it was a function!
		if on_close and hasattr(on_close, '__call__'):
			on_close()
	dialog.connect("response", close)
	add_close_accel(dialog, close)
	about_dialog = dialog
	dialog.show()
Beispiel #8
0
def make_client(error_cb, opts):
    app = None
    if not opts.client_toolkit:
        from xpra.gtk_common.gobject_compat import import_gobject, is_gtk3
        import_gobject()
        if is_gtk3():
            opts.client_toolkit = "gtk3"
        else:
            opts.client_toolkit = "gtk2"

    ct = opts.client_toolkit.lower()
    toolkits = {}
    try:
        import gtk.gdk                      #@UnusedImport
        import xpra.client.gtk2             #@UnusedImport
        toolkits["gtk2"] = "xpra.client.gtk2.client"
    except Exception, e:
        print("cannot load gtk2: %s" % e)
Beispiel #9
0
 def do_setup_xprops(self, *args):
     log("do_setup_xprops(%s)", args)
     if is_gtk3():
         log("x11 root properties and XSETTINGS are not supported yet with GTK3")
         return
     ROOT_PROPS = ["RESOURCE_MANAGER", "_NET_WORKAREA", "_NET_CURRENT_DESKTOP"]
     try:
         from xpra.x11.xsettings import XSettingsWatcher
         from xpra.x11.xroot_props import XRootPropWatcher
         if self._xsettings_watcher is None:
             self._xsettings_watcher = XSettingsWatcher()
             self._xsettings_watcher.connect("xsettings-changed", self._handle_xsettings_changed)
             self._handle_xsettings_changed()
         if self._root_props_watcher is None:
             self._root_props_watcher = XRootPropWatcher(ROOT_PROPS)
             self._root_props_watcher.connect("root-prop-changed", self._handle_root_prop_changed)
             #ensure we get the initial value:
             self._root_props_watcher.do_notify("RESOURCE_MANAGER")
     except ImportError as e:
         log.error("failed to load X11 properties/settings bindings: %s - root window properties will not be propagated", e)
Beispiel #10
0
def get_gtk_version_info():
    #update props given:
    global GTK_VERSION_INFO
    def av(k, v):
        GTK_VERSION_INFO.setdefault(k, {})["version"] = v
    if not GTK_VERSION_INFO:
        if hasattr(gtk, "pygtk_version"):
            av("pygtk", gtk.pygtk_version)
        if hasattr(gtk, "gtk_version"):
            #GTK2:
            av("gtk", gtk.gtk_version)
        elif hasattr(gtk, "_version"):
            #GTK3:
            av("gtk", gtk._version)
        if hasattr(gdk, "__version__"):
            #GTK2:
            av("gdk", gdk.__version__)
        elif hasattr(gdk, "_version"):
            #GTK3:
            av("gdk", gdk._version)
        if is_gtk3():
            try:
                import gi
                av("gi", gi.__version__)
            except:
                pass
        if hasattr(gobject, "pygobject_version"):
            av("gobject", gobject.pygobject_version)
        elif hasattr(gobject, "_version"):
            av("gobject", gobject._version)
        if hasattr(cairo, "version"):
            av("cairo", cairo.version)
        if hasattr(pango, "version_string"):
            av("pango", pango.version_string())
        try:
            import glib
            av("glib", glib.glib_version)
            av("pyglib", glib.pyglib_version)
        except:
            pass
    return GTK_VERSION_INFO.copy()
Beispiel #11
0
def grok_modifier_map(display, meanings):
    """Return an dict mapping modifier names to corresponding X modifier
    bitmasks."""
    #TODO: needs fixing for GTK3
    from xpra.keyboard.mask import MODIFIER_MAP
    modifier_map = MODIFIER_MAP.copy()
    modifier_map.update({
        "scroll":   0,
        "num":      0,
        "meta":     0,
        "super":    0,
        "hyper":    0,
        "alt":      0,
        })
    if not meanings:
        meanings = DEFAULT_MODIFIER_MEANINGS

    (max_keypermod, keycodes) = X11Keyboard.get_modifier_map()
    assert len(keycodes) == 8 * max_keypermod
    keymap = keymap_get_for_display(display)
    for i in range(8):
        for j in range(max_keypermod):
            keycode = keycodes[i * max_keypermod + j]
            if keycode:
                entries = keymap.get_entries_for_keycode(keycode)
                if entries is None:
                    # This keycode has no entry in the keymap:
                    continue
                if is_gtk3():
                    found, _, keyvals = entries
                    if not found:
                        continue
                else:
                    #(keyval, _, _, _) in entries
                    keyvals = [x[0] for x in entries]
                for keyval in keyvals:
                    keyval_name = gdk.keyval_name(keyval)
                    modifier = meanings.get(keyval_name)
                    if modifier:
                        modifier_map[modifier] |= (1 << i)
    return modifier_map
Beispiel #12
0
def get_gtk_version_info():
    #update props given:
    global GTK_VERSION_INFO
    if not GTK_VERSION_INFO:
        if hasattr(gtk, "pygtk_version"):
            GTK_VERSION_INFO["pygtk.version"] = gtk.pygtk_version
        if hasattr(gtk, "gtk_version"):
            #GTK2:
            GTK_VERSION_INFO["gtk.version"] = gtk.gtk_version
        elif hasattr(gtk, "_version"):
            #GTK3:
            GTK_VERSION_INFO["gtk.version"] = gtk._version
        if hasattr(gdk, "__version__"):
            #GTK2:
            GTK_VERSION_INFO["gdk.version"] = gdk.__version__
        elif hasattr(gdk, "_version"):
            #GTK3:
            GTK_VERSION_INFO["gdk.version"] = gdk._version
        if is_gtk3():
            try:
                import gi
                GTK_VERSION_INFO["gi.version"] = gi.__version__
            except:
                pass
        if hasattr(gobject, "pygobject_version"):
            GTK_VERSION_INFO["gobject.version"] = gobject.pygobject_version
        elif hasattr(gobject, "_version"):
            GTK_VERSION_INFO["gobject.version"] = gobject._version
        if hasattr(cairo, "version"):
            GTK_VERSION_INFO["cairo.version"] = cairo.version
        if hasattr(pango, "version_string"):
            GTK_VERSION_INFO["pango.version"] = pango.version_string()
        try:
            import glib
            GTK_VERSION_INFO["glib.version"] = glib.glib_version
            GTK_VERSION_INFO["pyglib.version"] = glib.pyglib_version
        except:
            pass
    return GTK_VERSION_INFO.copy()
Beispiel #13
0
    def    __init__(self):
        self.window = gtk.Window()
        self.window.connect("destroy", self.destroy)
        self.window.set_default_size(540, 800)
        self.window.set_border_width(20)
        self.window.set_title("Keyboard State Tool")

        # Title
        vbox = gtk.VBox(False, 0)
        vbox.set_spacing(15)
        label = gtk.Label("Keyboard State")
        label.modify_font(pango.FontDescription("sans 13"))
        vbox.pack_start(label)

        self.modifiers = gtk.Label()
        vbox.add(self.modifiers)

        self.mouse = gtk.Label()
        vbox.add(self.mouse)

        self.keys = gtk.Label()
        fixed = pango.FontDescription('monospace 9')
        self.keys.modify_font(fixed)
        vbox.add(self.keys)

        self.window.add(vbox)
        self.window.show_all()
        gobject.timeout_add(100, self.populate_modifiers)

        self.key_events = maxdeque(maxlen=35)
        self.window.connect("key-press-event", self.key_press)
        self.window.connect("key-release-event", self.key_release)
        if not is_gtk3():
            self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))

        icon = get_icon("keyboard.png")
        if icon:
            self.window.set_icon(icon)
Beispiel #14
0
def imagebutton(title, icon, tooltip=None, clicked_callback=None, icon_size=32, default=False, min_size=None, label_color=None):
    button = gtk.Button(title)
    settings = button.get_settings()
    settings.set_property('gtk-button-images', True)
    if icon:
        button.set_image(scaled_image(icon, icon_size))
    if tooltip:
        button.set_tooltip_text(tooltip)
    if min_size:
        button.set_size_request(min_size, min_size)
    if clicked_callback:
        button.connect("clicked", clicked_callback)
    if default:
        if is_gtk3():
            button.set_can_default(True)
        else:
            button.set_flags(gtk.CAN_DEFAULT)
    if label_color:
        alignment = button.get_children()[0]
        b_hbox = alignment.get_children()[0]
        label = b_hbox.get_children()[1]
        label.modify_fg(STATE_NORMAL, label_color)
    return button
import os
import sys

#pygtk3 vs pygtk2 (sigh)
from xpra.gtk_common.gobject_compat import import_gobject, import_cairo, is_gtk3
gobject = import_gobject()
cairo   = import_cairo()

from xpra.client.window_backing_base import WindowBackingBase, unpremultiply_argb
from xpra.log import Logger
log = Logger("paint")

#transparency with GTK:
# - on MS Windows: not supported
# - on OSX: only with gtk3
DEFAULT_HAS_ALPHA = not sys.platform.startswith("win") and (not sys.platform.startswith("darwin") or is_gtk3())
GTK_ALPHA_SUPPORTED = (unpremultiply_argb is not None) and os.environ.get("XPRA_ALPHA", DEFAULT_HAS_ALPHA) in (True, "1")


"""
Generic GTK superclass for Backing code (for both GTK2 and GTK3),
see CairoBacking, PixmapBacking and TrayBacking for actual implementations.
(some may override HAS_ALPHA, TrayBacking does)
"""
class GTKWindowBacking(WindowBackingBase):

    HAS_ALPHA = GTK_ALPHA_SUPPORTED

    def __init__(self, wid, window_alpha):
        WindowBackingBase.__init__(self, wid, window_alpha and self.HAS_ALPHA, gobject.idle_add)
Beispiel #16
0
 def init_opengl(self, enable_opengl):
     opengllog("init_opengl(%s)", enable_opengl)
     #enable_opengl can be True, False or None (auto-detect)
     if enable_opengl is False:
         self.opengl_props["info"] = "disabled by configuration"
         return
     from xpra.scripts.config import OpenGL_safety_check
     from xpra.platform.gui import gl_check as platform_gl_check
     warnings = []
     for check in (OpenGL_safety_check, platform_gl_check):
         opengllog("checking with %s", check)
         warning = check()
         opengllog("%s()=%s", check, warning)
         if warning:
             warnings.append(warning)
     self.opengl_props["info"] = ""
     if warnings:
         if enable_opengl is True:
             opengllog.warn("OpenGL safety warning (enabled at your own risk):")
             for warning in warnings:
                 opengllog.warn(" %s", warning)
             self.opengl_props["info"] = "forced enabled despite: %s" % (", ".join(warnings))
         else:
             opengllog.warn("OpenGL disabled:", warning)
             for warning in warnings:
                 opengllog.warn(" %s", warning)
             self.opengl_props["info"] = "disabled: %s" % (", ".join(warnings))
             return
     try:
         opengllog("init_opengl: going to import xpra.client.gl")
         __import__("xpra.client.gl", {}, {}, [])
         __import__("xpra.client.gl.gtk_compat", {}, {}, [])
         gl_check = __import__("xpra.client.gl.gl_check", {}, {}, ["check_support"])
         opengllog("init_opengl: gl_check=%s", gl_check)
         self.opengl_props = gl_check.check_support(force_enable=(enable_opengl is True))
         opengllog("init_opengl: found props %s", self.opengl_props)
         GTK_GL_CLIENT_WINDOW_MODULE = "xpra.client.gl.gtk%s.gl_client_window" % (2+int(is_gtk3()))
         opengllog("init_opengl: trying to load GL client window module '%s'", GTK_GL_CLIENT_WINDOW_MODULE)
         gl_client_window = __import__(GTK_GL_CLIENT_WINDOW_MODULE, {}, {}, ["GLClientWindow"])
         self.GLClientWindowClass = gl_client_window.GLClientWindow
         self.client_supports_opengl = True
         #only enable opengl by default if force-enabled or if safe to do so:
         self.opengl_enabled = (enable_opengl is True) or self.opengl_props.get("safe", False)
         self.gl_texture_size_limit = self.opengl_props.get("texture-size-limit", 16*1024)
         self.gl_max_viewport_dims = self.opengl_props.get("max-viewport-dims", (self.gl_texture_size_limit, self.gl_texture_size_limit))
         if min(self.gl_max_viewport_dims)<4*1024:
             opengllog.warn("Warning: OpenGL is disabled:")
             opengllog.warn(" the maximum viewport size is too low: %s", self.gl_max_viewport_dims)
             self.opengl_enabled = False
         elif self.gl_texture_size_limit<4*1024:
             opengllog.warn("Warning: OpenGL is disabled:")
             opengllog.warn(" the texture size limit is too low: %s", self.gl_texture_size_limit)
             self.opengl_enabled = False
         self.GLClientWindowClass.MAX_VIEWPORT_DIMS = self.gl_max_viewport_dims
         self.GLClientWindowClass.MAX_BACKING_DIMS = self.gl_texture_size_limit, self.gl_texture_size_limit
         self.GLClientWindowClass.MAX_VIEWPORT_DIMS = 8192, 8192
         self.GLClientWindowClass.MAX_BACKING_DIMS = 4096, 4096
         mww, mwh = self.max_window_size
         opengllog("OpenGL: enabled=%s, texture-size-limit=%s, max-window-size=%s", self.opengl_enabled, self.gl_texture_size_limit, self.max_window_size)
         if self.opengl_enabled and self.gl_texture_size_limit<16*1024 and (mww==0 or mwh==0 or self.gl_texture_size_limit<mww or self.gl_texture_size_limit<mwh):
             #log at warn level if the limit is low:
             #(if we're likely to hit it - if the screen is as big or bigger)
             w, h = self.get_root_size()
             l = opengllog.info
             if w>=self.gl_texture_size_limit or h>=self.gl_texture_size_limit:
                 l = log.warn
             l("Warning: OpenGL windows will be clamped to the maximum texture size %ix%i", self.gl_texture_size_limit, self.gl_texture_size_limit)
             l(" for OpenGL %s renderer '%s'", pver(self.opengl_props.get("opengl", "")), self.opengl_props.get("renderer", "unknown"))
         driver_info = self.opengl_props.get("renderer") or self.opengl_props.get("vendor") or "unknown card"
         if self.opengl_enabled:
             opengllog.info("OpenGL enabled with %s", driver_info)
         elif self.client_supports_opengl:
             opengllog("OpenGL supported with %s, but not enabled", driver_info)
     except ImportError as e:
         opengllog.warn("OpenGL support is missing:")
         opengllog.warn(" %s", e)
         self.opengl_props["info"] = str(e)
     except RuntimeError as e:
         opengllog.warn("OpenGL support could not be enabled on this hardware:")
         opengllog.warn(" %s", e)
         self.opengl_props["info"] = str(e)
     except Exception as e:
         opengllog.error("Error loading OpenGL support:")
         opengllog.error(" %s", e, exc_info=True)
         self.opengl_props["info"] = str(e)
Beispiel #17
0
# later version. See the file COPYING for details.

# A tray implemented using gtk.StatusIcon

import os
import sys
from xpra.util import envbool
from xpra.gtk_common.gobject_compat import import_gtk, import_gdk, is_gtk3
gtk = import_gtk()
gdk = import_gdk()

from xpra.client.tray_base import TrayBase, log
from xpra.gtk_common.gtk_util import get_icon_from_file, get_pixbuf_from_data, INTERP_HYPER

ORIENTATION = {}
if not is_gtk3():
    #where was this moved to??
    ORIENTATION[gtk.ORIENTATION_HORIZONTAL] = "HORIZONTAL"
    ORIENTATION[gtk.ORIENTATION_VERTICAL]   = "VERTICAL"

GUESS_GEOMETRY = sys.platform.startswith("win") or sys.platform.startswith("darwin")
GUESS_GEOMETRY = envbool("XPRA_GUESS_ICON_GEOMETRY", GUESS_GEOMETRY)
log("tray GUESS_GEOMETRY=%s", GUESS_GEOMETRY)


class GTKStatusIconTray(TrayBase):

    def __init__(self, *args, **kwargs):
        TrayBase.__init__(self, *args, **kwargs)
        self.tray_widget = gtk.StatusIcon()
        self.tray_widget.set_tooltip_text(self.tooltip or "Xpra")
Beispiel #18
0
 def get_group_leader(self, wid, metadata, override_redirect):
     transient_for = metadata.intget("transient-for", -1)
     log("get_group_leader: transient_for=%s", transient_for)
     if transient_for>0:
         client_window = self._id_to_window.get(transient_for)
         if client_window:
             gdk_window = client_window.get_window()
             if gdk_window:
                 return gdk_window
     pid = metadata.intget("pid", -1)
     leader_xid = metadata.intget("group-leader-xid", -1)
     leader_wid = metadata.intget("group-leader-wid", -1)
     group_leader_window = self._id_to_window.get(leader_wid)
     if group_leader_window:
         #leader is another managed window
         log("found group leader window %s for wid=%s", group_leader_window, leader_wid)
         return group_leader_window
     log("get_group_leader: leader pid=%s, xid=%s, wid=%s", pid, leader_xid, leader_wid)
     reftype = "xid"
     ref = leader_xid
     if ref<0:
         reftype = "leader-wid"
         ref = leader_wid
     if ref<0:
         ci = metadata.strlistget("class-instance")
         if ci:
             reftype = "class"
             ref = "|".join(ci)
         elif pid>0:
             reftype = "pid"
             ref = pid
         elif transient_for>0:
             #this should have matched a client window above..
             #but try to use it anyway:
             reftype = "transient-for"
             ref = transient_for
         else:
             #no reference to use
             return None
     refkey = "%s:%s" % (reftype, ref)
     group_leader_window = self._ref_to_group_leader.get(refkey)
     if group_leader_window:
         log("found existing group leader window %s using ref=%s", group_leader_window, refkey)
         return group_leader_window
     #we need to create one:
     title = "%s group leader for %s" % (self.session_name or "Xpra", pid)
     #group_leader_window = gdk.Window(None, 1, 1, gdk.WINDOW_TOPLEVEL, 0, gdk.INPUT_ONLY, title)
     #static new(parent, attributes, attributes_mask)
     if is_gtk3():
         #long winded and annoying
         attributes = gdk.WindowAttr()
         attributes.width = 1
         attributes.height = 1
         attributes.title = title
         attributes.wclass = gdk.WindowWindowClass.INPUT_ONLY
         attributes.event_mask = 0
         attributes_mask = gdk.WindowAttributesType.TITLE | gdk.WindowAttributesType.WMCLASS
         group_leader_window = gdk.Window(None, attributes, attributes_mask)
         group_leader_window.resize(1, 1)
     else:
         #gtk2:
         group_leader_window = gdk.Window(None, 1, 1, gdk.WINDOW_TOPLEVEL, 0, gdk.INPUT_ONLY, title)
     self._ref_to_group_leader[refkey] = group_leader_window
     #avoid warning on win32...
     if not sys.platform.startswith("win"):
         #X11 spec says window should point to itself:
         group_leader_window.set_group(group_leader_window)
     log("new hidden group leader window %s for ref=%s", group_leader_window, refkey)
     self._group_leader_wids.setdefault(group_leader_window, []).append(wid)
     return group_leader_window
Beispiel #19
0
    def setup_window(self):
        self.window = gtk.Window()
        self.window.connect("destroy", self.close)
        self.window.set_default_size(400, 300)
        self.window.set_border_width(20)
        self.window.set_title("Xpra Bug Report")
        self.window.modify_bg(STATE_NORMAL,
                              gdk.Color(red=65535, green=65535, blue=65535))

        icon_pixbuf = self.get_icon("bugs.png")
        if icon_pixbuf:
            self.window.set_icon(icon_pixbuf)
        self.window.set_position(WIN_POS_CENTER)

        vbox = gtk.VBox(False, 0)
        vbox.set_spacing(15)

        # Title
        hbox = gtk.HBox(False, 0)
        icon_pixbuf = self.get_icon("xpra.png")
        if icon_pixbuf and self.show_about:
            from xpra.gtk_common.about import about
            logo_button = gtk.Button("")
            settings = logo_button.get_settings()
            settings.set_property('gtk-button-images', True)
            logo_button.connect("clicked", about)
            logo_button.set_tooltip_text("About")
            image = gtk.Image()
            image.set_from_pixbuf(icon_pixbuf)
            logo_button.set_image(image)
            hbox.pack_start(logo_button, expand=False, fill=False)

        label = gtk.Label("Xpra Bug Report Tool")
        label.modify_font(pango.FontDescription("sans 14"))
        hbox.pack_start(label, expand=True, fill=True)
        vbox.pack_start(hbox)

        #the box containing all the input:
        ibox = gtk.VBox(False, 0)
        ibox.set_spacing(3)
        vbox.pack_start(ibox)

        # Description
        al = gtk.Alignment(xalign=0, yalign=0.5, xscale=0.0, yscale=0)
        al.add(gtk.Label("Please describe the problem:"))
        ibox.pack_start(al)
        #self.description = gtk.Entry(max=128)
        #self.description.set_width_chars(40)
        self.description = gtk.TextView()
        self.description.set_accepts_tab(True)
        self.description.set_justification(JUSTIFY_LEFT)
        self.description.set_border_width(2)
        self.description.set_size_request(300, 80)
        self.description.modify_bg(
            STATE_NORMAL, gdk.Color(red=32768, green=32768, blue=32768))
        ibox.pack_start(self.description, expand=False, fill=False)

        # Toggles:
        al = gtk.Alignment(xalign=0, yalign=0.5, xscale=0.0, yscale=0)
        al.add(gtk.Label("Include:"))
        ibox.pack_start(al)
        #generic toggles:
        from xpra.gtk_common.keymap import get_gtk_keymap
        from xpra.codecs.loader import codec_versions, load_codecs
        load_codecs()
        try:
            from xpra.sound.wrapper import query_sound

            def get_sound_info():
                return query_sound()
        except:
            get_sound_info = None

        def get_gl_info():
            if self.opengl_info:
                return self.opengl_info
            try:
                from xpra.client.gl.gl_check import check_support
                return check_support(force_enable=True)
            except Exception as e:
                return {"error": str(e)}

        from xpra.net.net_util import get_info as get_net_info
        from xpra.platform.paths import get_info as get_path_info
        from xpra.platform.gui import get_info as get_gui_info
        from xpra.version_util import get_version_info, get_platform_info, get_host_info

        def get_sys_info():
            from xpra.platform.info import get_user_info
            from xpra.scripts.config import read_xpra_defaults
            return {
                "argv": sys.argv,
                "path": sys.path,
                "exec_prefix": sys.exec_prefix,
                "executable": sys.executable,
                "version": get_version_info(),
                "platform": get_platform_info(),
                "host": get_host_info(),
                "paths": get_path_info(),
                "gtk": get_gtk_version_info(),
                "gui": get_gui_info(),
                "display": get_display_info(),
                "user": get_user_info(),
                "env": os.environ,
                "config": read_xpra_defaults(),
            }

        get_screenshot, take_screenshot_fn = None, None
        #screenshot: may have OS-specific code
        try:
            from xpra.platform.gui import take_screenshot
            take_screenshot_fn = take_screenshot
        except:
            log("failed to load platfrom specific screenshot code",
                exc_info=True)
        if not take_screenshot_fn:
            #try with Pillow:
            try:
                from PIL import ImageGrab  #@UnresolvedImport
                from xpra.os_util import StringIOClass

                def pillow_imagegrab_screenshot():
                    img = ImageGrab.grab()
                    out = StringIOClass()
                    img.save(out, format="PNG")
                    v = out.getvalue()
                    out.close()
                    return (img.width, img.height, "png", img.width * 3, v)

                take_screenshot_fn = pillow_imagegrab_screenshot
            except Exception as e:
                log("cannot use Pillow's ImageGrab: %s", e)
        if not take_screenshot_fn:
            #default: gtk screen capture
            try:
                from xpra.server.shadow.gtk_root_window_model import GTKRootWindowModel
                rwm = GTKRootWindowModel(gtk.gdk.get_default_root_window())
                take_screenshot_fn = rwm.take_screenshot
            except:
                log("failed to load gtk screenshot code", exc_info=True)
        log("take_screenshot_fn=%s", take_screenshot_fn)
        if take_screenshot_fn:

            def get_screenshot():
                #take_screenshot() returns: w, h, "png", rowstride, data
                return take_screenshot_fn()[4]

        self.toggles = (
            ("system", "txt", "System", get_sys_info,
             "Xpra version, platform and host information"),
            ("network", "txt", "Network", get_net_info,
             "Compression, packet encoding and encryption"),
            ("encoding", "txt", "Encodings", codec_versions,
             "Picture encodings supported"),
            ("opengl", "txt", "OpenGL", get_gl_info,
             "OpenGL driver and features"),
            ("sound", "txt", "Sound", get_sound_info,
             "Sound codecs and GStreamer version information"),
            ("keyboard", "txt", "Keyboard Mapping", get_gtk_keymap,
             "Keyboard layout and key mapping"),
            ("xpra-info", "txt", "Server Info", self.get_server_info,
             "Full server information from 'xpra info'"),
            ("screenshot", "png", "Screenshot", get_screenshot, ""),
        )
        for name, _, title, value_cb, tooltip in self.toggles:
            cb = gtk.CheckButton(title +
                                 [" (not available)", ""][bool(value_cb)])
            cb.set_active(self.includes.get(name, True))
            cb.set_sensitive(bool(value_cb))
            cb.set_tooltip_text(tooltip)
            ibox.pack_start(cb)
            setattr(self, name, cb)

        # Buttons:
        hbox = gtk.HBox(False, 20)
        vbox.pack_start(hbox)

        def btn(label, tooltip, callback, icon_name=None):
            btn = gtk.Button(label)
            btn.set_tooltip_text(tooltip)
            btn.connect("clicked", callback)
            if icon_name:
                icon = self.get_icon(icon_name)
                if icon:
                    btn.set_image(scaled_image(icon, 24))
            hbox.pack_start(btn)
            return btn

        if not is_gtk3():
            #clipboard does not work in gtk3..
            btn("Copy to clipboard", "Copy all data to clipboard",
                self.copy_clicked, "clipboard.png")
        btn("Save", "Save Bug Report", self.save_clicked, "download.png")
        btn("Cancel", "", self.close, "quit.png")

        def accel_close(*args):
            self.close()

        add_close_accel(self.window, accel_close)
        vbox.show_all()
        self.window.vbox = vbox
        self.window.add(vbox)
#pygtk3 vs pygtk2 (sigh)
from xpra.gtk_common.gobject_compat import import_glib, import_cairo, is_gtk3
glib = import_glib()
cairo   = import_cairo()

from xpra.util import envbool
from xpra.os_util import WIN32, OSX
from xpra.client.window_backing_base import WindowBackingBase
from xpra.log import Logger
log = Logger("paint")

#transparency with GTK:
# - on MS Windows: not supported
# - on OSX: only with gtk3
DEFAULT_HAS_ALPHA = not WIN32 and (not OSX or is_gtk3())
GTK_ALPHA_SUPPORTED = envbool("XPRA_ALPHA", DEFAULT_HAS_ALPHA)


"""
Generic GTK superclass for Backing code (for both GTK2 and GTK3),
see CairoBacking, PixmapBacking and TrayBacking for actual implementations.
(some may override HAS_ALPHA, TrayBacking does)
"""
class GTKWindowBacking(WindowBackingBase):

    HAS_ALPHA = GTK_ALPHA_SUPPORTED

    def __init__(self, wid, window_alpha):
        WindowBackingBase.__init__(self, wid, window_alpha and self.HAS_ALPHA, glib.idle_add)
Beispiel #21
0
gtk = import_gtk()
gdk = import_gdk()

from xpra.log import Logger
log = Logger("gtk", "util")

GTK_VERSION_INFO = {}
if hasattr(gtk, "pygtk_version"):
    GTK_VERSION_INFO["pygtk_version"] = gtk.pygtk_version
if hasattr(gtk, "gtk_version"):
    GTK_VERSION_INFO["gtk_version"] = gtk.gtk_version
elif hasattr(gtk, "_version"):
    GTK_VERSION_INFO["gtk_version"] = gtk._version


if is_gtk3():
    #where is this gone now?
    FILL = None
else:
    FILL = gtk.FILL


def add_gtk_version_info(props, gtk, prefix="", new_namespace=False):
    #update props given:
    global GTK_VERSION_INFO
    for k,v in GTK_VERSION_INFO.items():
        if new_namespace:
            k = k.replace("_", ".")
        props[prefix+k] = v

Beispiel #22
0
gtk = import_gtk()
gdk = import_gdk()
from xpra.gtk_common.gtk_util import get_xwindow

from xpra.log import Logger
log = Logger("x11", "window")

try:
    from xpra.x11.gtk2.gdk_bindings import (
                    get_pywindow,               #@UnresolvedImport
                    get_xvisual,                #@UnresolvedImport
                   )
except ImportError as e:
    #we should only ever be missing the gdk_bindings with GTK3 builds:
    log("cannot import gdk bindings", exc_info=True)
    assert is_gtk3()
    def missing_fn(*args):
        raise NotImplementedError()
    get_pywindow, get_xvisual = missing_fn, missing_fn

from xpra.x11.bindings.window_bindings import (
                constants,                      #@UnresolvedImport
                X11WindowBindings,          #@UnresolvedImport
                PropertyError)              #@UnresolvedImport
X11Window = X11WindowBindings()

from xpra.os_util import StringIOClass
from xpra.gtk_common.error import xsync, XError
from xpra.codecs.argb.argb import premultiply_argb_in_place #@UnresolvedImport

Beispiel #23
0
def main():
    from xpra.platform import program_context
    with program_context("Xpra-Sound-Source"):
        import os.path
        if "-v" in sys.argv:
            log.enable_debug()
            sys.argv.remove("-v")

        if len(sys.argv) not in (2, 3):
            log.error("usage: %s filename [codec] [--encoder=rencode]", sys.argv[0])
            return 1
        filename = sys.argv[1]
        if filename=="-":
            from xpra.os_util import disable_stdout_buffering
            disable_stdout_buffering()
        elif os.path.exists(filename):
            log.error("file %s already exists", filename)
            return 1
        codec = None

        codecs = get_codecs()
        if len(sys.argv)==3:
            codec = sys.argv[2]
            if codec not in codecs:
                log.error("invalid codec: %s, codecs supported: %s", codec, codecs)
                return 1
        else:
            parts = filename.split(".")
            if len(parts)>1:
                extension = parts[-1]
                if extension.lower() in codecs:
                    codec = extension.lower()
                    log.info("guessed codec %s from file extension %s", codec, extension)
            if codec is None:
                codec = MP3
                log.info("using default codec: %s", codec)

        #in case we're running against pulseaudio,
        #try to setup the env:
        try:
            from xpra.platform.paths import get_icon_filename
            f = get_icon_filename("xpra.png")
            from xpra.sound.pulseaudio.pulseaudio_util import add_audio_tagging_env
            add_audio_tagging_env(icon_path=f)
        except Exception as e:
            log.warn("failed to setup pulseaudio tagging: %s", e)

        from threading import Lock
        if filename=="-":
            f = sys.stdout
        else:
            f = open(filename, "wb")
        ss = SoundSource(codecs=[codec])
        lock = Lock()
        def new_buffer(ss, data, metadata):
            log.info("new buffer: %s bytes (%s), metadata=%s", len(data), type(data), metadata)
            with lock:
                if f:
                    f.write(data)
                    f.flush()

        from xpra.gtk_common.gobject_compat import import_glib
        glib = import_glib()
        glib_mainloop = glib.MainLoop()

        ss.connect("new-buffer", new_buffer)
        ss.start()

        import signal
        def deadly_signal(sig, frame):
            log.warn("got deadly signal %s", SIGNAMES.get(sig, sig))
            glib.idle_add(ss.stop)
            glib.idle_add(glib_mainloop.quit)
            def force_quit(sig, frame):
                sys.exit()
            signal.signal(signal.SIGINT, force_quit)
            signal.signal(signal.SIGTERM, force_quit)
        from xpra.gtk_common.gobject_compat import is_gtk3
        if not is_gtk3():
            signal.signal(signal.SIGINT, deadly_signal)
        signal.signal(signal.SIGTERM, deadly_signal)

        try:
            glib_mainloop.run()
        except Exception as e:
            log.error("main loop error: %s", e)
        ss.stop()

        f.flush()
        if f!=sys.stdout:
            log.info("wrote %s bytes to %s", f.tell(), filename)
        with lock:
            f.close()
            f = None
        return 0
Beispiel #24
0
def import_gst():
    global gst, has_gst, gst_vinfo, gst_major_version
    if has_gst is not None:
        return gst

    from xpra.gtk_common.gobject_compat import is_gtk3
    if is_gtk3():
        imports = [(import_gst1, 1)]
    else:
        imports = [
            (import_gst0_10, 0),
            (import_gst1, 1),
        ]
        if GSTREAMER1:
            imports.reverse()  #try gst1 first:
    errs = {}
    saved_sys_path = sys.path[:]
    saved_os_environ = os.environ.copy()
    for import_function, MV in imports:
        #restore os.environ and sys.path
        sys.path = saved_sys_path[:]
        os.environ.clear()
        os.environ.update(saved_os_environ)
        vstr = get_version_str(MV)
        #hacks to locate gstreamer plugins on win32 and osx:
        if WIN32:
            frozen = hasattr(
                sys, "frozen") and sys.frozen in ("windows_exe", "console_exe",
                                                  True)
            log("gstreamer_util: frozen=%s", frozen)
            if frozen:
                #on win32, we keep separate trees
                #because GStreamer 0.10 and 1.x were built using different and / or incompatible version of the same libraries:
                from xpra.platform.paths import get_app_dir
                gst_dir = os.path.join(
                    get_app_dir(), "gstreamer-%s" %
                    vstr)  #ie: C:\Program Files\Xpra\gstreamer-0.10
                os.environ["GST_PLUGIN_PATH"] = gst_dir
                if MV == 1:
                    gst_bin_dir = os.path.join(
                        gst_dir,
                        "bin")  #ie: C:\Program Files\Xpra\gstreamer-0.10\bin
                    os.environ["PATH"] = os.pathsep.join(
                        x for x in (gst_bin_dir, os.environ.get("PATH", ""))
                        if x)
                    sys.path.insert(0, gst_bin_dir)
                    scanner = os.path.join(gst_bin_dir,
                                           "gst-plugin-scanner.exe")
                    if os.path.exists(scanner):
                        os.environ["GST_PLUGIN_SCANNER"] = scanner
                    gi_dir = os.path.join(get_app_dir(),
                                          "girepository-%s" % vstr)
                    os.environ["GI_TYPELIB_PATH"] = gi_dir
        elif OSX:
            bundle_contents = os.environ.get("GST_BUNDLE_CONTENTS")
            log("OSX: GST_BUNDLE_CONTENTS=%s", bundle_contents)
            if bundle_contents:
                os.environ["GST_PLUGIN_PATH"] = os.path.join(
                    bundle_contents, "Resources", "lib", "gstreamer-%s" % vstr)
                os.environ["GST_PLUGIN_SCANNER"] = os.path.join(
                    bundle_contents, "Helpers", "gst-plugin-scanner-%s" % vstr)
                if MV == 1:
                    gi_dir = os.path.join(bundle_contents, "Resources", "lib",
                                          "girepository-%s" % vstr)
                    os.environ["GI_TYPELIB_PATH"] = gi_dir
        if MV < 1:
            #we should not be loading the gi bindings
            try:
                del os.environ["GI_TYPELIB_PATH"]
            except:
                pass
        log(
            "GStreamer %s environment: %s", vstr,
            dict(
                (k, v) for k, v in os.environ.items()
                if (k.startswith("GST") or k.startswith("GI") or k == "PATH")))
        log("GStreamer %s sys.path=%s", vstr, csv(sys.path))

        try:
            log("trying to import GStreamer %s using %s", get_version_str(MV),
                import_function)
            _gst = import_function()
            v = _gst.version()
            if v[-1] == 0:
                v = v[:-1]
            gst_vinfo = ".".join((str(x) for x in v))
            gst_major_version = MV
            gst = _gst
            break
        except Exception as e:
            log("Warning failed to import GStreamer %s", vstr, exc_info=True)
            errs[vstr] = e
    if gst:
        log("Python GStreamer version %s for Python %s.%s", gst_vinfo,
            sys.version_info[0], sys.version_info[1])
    else:
        log.warn("Warning: failed to import GStreamer:")
        for vstr, e in errs.items():
            log.warn(" %s failed with: %s", vstr, e)
    has_gst = gst is not None
    return gst
Beispiel #25
0
def add_window_hooks(window):
    log("add_window_hooks(%s) WINDOW_HOOKS=%s, GROUP_LEADER=%s, UNDECORATED_STYLE=%s, MAX_SIZE_HINT=%s, GEOMETRY=%s",
            window, WINDOW_HOOKS, GROUP_LEADER, UNDECORATED_STYLE, MAX_SIZE_HINT, GEOMETRY)
    if not WINDOW_HOOKS:
        #allows us to disable the win32 hooks for testing
        return
    try:
        gdk_window = window.get_window()
        #win32 cannot use set_group by default:
        gdk_window.set_group = noop
    except:
        gdk_window = None
    #window handle:
    try:
        handle = gdk_window.handle
    except:
        handle = None
    if not handle:
        from xpra.gtk_common.gobject_compat import is_gtk3
        if is_gtk3():
            #access the missing gdk_win32_window_get_handle function using ctypes:
            try:
                ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
                ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object]
                gdkwin_gpointer = ctypes.pythonapi.PyCapsule_GetPointer(gdk_window.__gpointer__, None)
                gdkdll = ctypes.CDLL ("libgdk-3-0.dll")
                handle = gdkdll.gdk_win32_window_get_handle(gdkwin_gpointer)
            except Exception as e:
                log.warn("failed to get window handle", exc_info=True)
    if not handle:
        log.warn("Warning: cannot add window hooks without a window handle!")
        return
    log("add_window_hooks(%s) gdk window=%s, hwnd=%#x", window, gdk_window, handle)

    if GROUP_LEADER:
        #windows 7 onwards can use AppUserModel to emulate the group leader stuff:
        propsys = get_propsys()
        log("win32 hooks: propsys=%s", propsys)
        if propsys:
            gdk_window.set_group = types.MethodType(win32_propsys_set_group_leader, gdk_window)
            log("hooked group leader override using %s", propsys)

    if UNDECORATED_STYLE:
        #OR windows never have any decorations or taskbar menu
        if not window._override_redirect:
            #the method to call to fix things up:
            window.fixup_window_style = types.MethodType(fixup_window_style, window)
            #override set_decorated so we can preserve the taskbar menu for undecorated windows
            window.__set_decorated = window.set_decorated
            window.set_decorated = types.MethodType(set_decorated, window)
            #override after_window_state_updated so we can re-add the missing style options
            #(somehow doing it from on_realize which calls add_window_hooks is not enough)
            window.connect("state-updated", window_state_updated)
            #call it at least once:
            window.fixup_window_style()

    if CLIP_CURSOR:
        window.pointer_grab = types.MethodType(pointer_grab, window)
        window.pointer_ungrab = types.MethodType(pointer_ungrab, window)

    if MAX_SIZE_HINT or LANGCHANGE:
        #glue code for gtk to win32 APIs:
        #add event hook class:
        win32hooks = Win32Hooks(handle)
        log("add_window_hooks(%s) added hooks for hwnd %#x: %s", window, handle, win32hooks)
        window.win32hooks = win32hooks
        win32hooks.max_size = None
        win32hooks.setup()

        if GEOMETRY:
            #save original geometry function:
            window.__apply_geometry_hints = window.apply_geometry_hints
            window.apply_geometry_hints = types.MethodType(apply_geometry_hints, window)
            #apply current max-size from hints, if any:
            if window.geometry_hints:
                apply_maxsize_hints(window, window.geometry_hints)

        if LANGCHANGE:
            def inputlangchange(hwnd, event, wParam, lParam):
                log("WM_INPUTLANGCHANGE: character set: %i, input locale identifier: %i", wParam, lParam)
                window.keyboard_layout_changed("WM_INPUTLANGCHANGE", wParam, lParam)
            win32hooks.add_window_event_handler(win32con.WM_INPUTLANGCHANGE, inputlangchange)
        if WHEEL:
            VERTICAL = "vertical"
            HORIZONTAL = "horizontal"
            class WheelEvent(AdHocStruct):
                pass
            def handle_wheel(orientation, wParam, lParam):
                distance = wParam>>16
                keys = wParam & 0xFFFF
                y = lParam>>16
                x = lParam & 0xFFFF
                cval = getattr(window, "_win32_%swheel" % orientation, 0)
                nval = cval + distance
                units = nval // WHEEL_DELTA
                client = getattr(window, "_client")
                wid = getattr(window, "_id", 0)
                mouselog("mousewheel: orientation=%s distance=%.1f, units=%i, new value=%.1f, keys=%#x, x=%i, y=%i, client=%s, wid=%i", orientation, distance, units, nval, keys, x, y, client, wid)
                if units!=0 and client and wid>0:
                    if orientation==VERTICAL:
                        button = 4 + int(units<0)       #4 for UP, 5 for DOWN
                    else:
                        button = 7 - int(units<0)       #6 for LEFT, 7 for RIGHT
                    buttons = []
                    modifiers = client.get_current_modifiers()
                    def send_button(pressed):
                        client.send_button(wid, button, pressed, (x, y), modifiers, buttons)
                    count = 0
                    v = nval
                    while abs(v)>=WHEEL_DELTA:
                        send_button(True)
                        send_button(False)
                        if v>0:
                            v -= WHEEL_DELTA
                        else:
                            v += WHEEL_DELTA
                        count += 1
                    mouselog("mousewheel: send %i wheel events to the server for distance=%s, remainder=%s", count, nval, v)
                    setattr(window, "_win32_%swheel" % orientation, v)
            def mousewheel(hwnd, event, wParam, lParam):
                handle_wheel(VERTICAL, wParam, lParam)
                return 0
            def mousehwheel(hwnd, event, wParam, lParam):
                handle_wheel(HORIZONTAL, wParam, lParam)
                return 0
            WM_MOUSEHWHEEL = 0x020E
            win32hooks.add_window_event_handler(win32con.WM_MOUSEWHEEL, mousewheel)
            win32hooks.add_window_event_handler(WM_MOUSEHWHEEL, mousehwheel)
            def reset_wheel_counters(*args):
                mouselog("window lost focus, resetting current wheel deltas")
                for orientation in (VERTICAL, HORIZONTAL):
                    setattr(window, "_win32_%swheel" % orientation, 0)
            window.connect("focus-out-event", reset_wheel_counters)
Beispiel #26
0
def get_display_info():
    display = display_get_default()
    info = {
            "root"                  : get_default_root_window().get_geometry(),
            "root-size"             : get_root_size(),
            "screens"               : display.get_n_screens(),
            "name"                  : display.get_name(),
            "pointer"               : display.get_pointer()[1:3],
            "devices"               : len(display.list_devices()),
            "default_cursor_size"   : display.get_default_cursor_size(),
            "maximal_cursor_size"   : display.get_maximal_cursor_size(),
            "pointer_is_grabbed"    : display.pointer_is_grabbed(),
            }
    sinfo = info.setdefault("supports", {})
    for x in ("composite", "cursor_alpha", "cursor_color", "selection_notification", "clipboard_persistence", "shapes"):
        f = "supports_"+x
        if hasattr(display, f):
            fn = getattr(display, f)
            sinfo[x]  = fn()
    info["screens"] = get_screens_info()
    if is_gtk3():
        dm = display.get_device_manager()
        for dt, name in {gdk.DeviceType.MASTER  : "master",
                         gdk.DeviceType.SLAVE   : "slave",
                         gdk.DeviceType.FLOATING: "floating"}.items():
            dinfo = info.setdefault("device", {})
            dtinfo = dinfo.setdefault(name, {})
            devices = dm.list_devices(dt)
            for i, d in enumerate(devices):
                dtinfo[i] = d.get_name()
    else:
        devices = display.list_devices()
        for i, d in enumerate(devices):
            dinfo = info.setdefault("device", {}).setdefault(i, {})
            dinfo[""] = d.get_name()
            AXES_STR = {
                        gdk.AXIS_IGNORE         : "IGNORE",
                        gdk.AXIS_X              : "X",
                        gdk.AXIS_Y              : "Y",
                        gdk.AXIS_PRESSURE       : "PRESSURE",
                        gdk.AXIS_XTILT          : "XTILT",
                        gdk.AXIS_YTILT          : "YTILT",
                        gdk.AXIS_WHEEL          : "WHEEL",
                        gdk.AXIS_LAST           : "LAST",
                        }
            MODE_STR = {
                        gdk.MODE_DISABLED       : "DISABLED",
                        gdk.MODE_SCREEN         : "SCREEN",
                        gdk.MODE_WINDOW         : "WINDOW",
                        }
            SOURCE_STR = {
                        gdk.SOURCE_MOUSE        : "MOUSE",
                        gdk.SOURCE_PEN          : "PEN",
                        gdk.SOURCE_ERASER       : "ERASER",
                        gdk.SOURCE_CURSOR       : "CURSOR",
                        }
            def notrans(v, d):
                return v
            MOD_STR = {
                        gdk.SHIFT_MASK          : "SHIFT",
                        gdk.LOCK_MASK           : "LOCK",
                        gdk.CONTROL_MASK        : "CONTROL",
                        gdk.MOD1_MASK           : "MOD1",
                        gdk.MOD2_MASK           : "MOD2",
                        gdk.MOD3_MASK           : "MOD3",
                        gdk.MOD4_MASK           : "MOD4",
                        gdk.MOD5_MASK           : "MOD5",
                        gdk.BUTTON1_MASK        : "BUTTON1",
                        gdk.BUTTON2_MASK        : "BUTTON2",
                        gdk.BUTTON3_MASK        : "BUTTON3",
                        gdk.BUTTON4_MASK        : "BUTTON4",
                        gdk.BUTTON5_MASK        : "BUTTON5",
                        gdk.RELEASE_MASK        : "RELEASE",
                       }
            def modtrans(mod):
                return [v for k,v in MOD_STR.items() if k&mod]
            def keys_trans(l, d):
                #GdkModifierType can be converted to an int
                return [(k,modtrans(v)) for (k,v) in l]
            for name, trans in {"axes"          : AXES_STR.get,
                                "has_cursor"    : notrans,
                                "keys"          : keys_trans,
                                "mode"          : MODE_STR.get,
                                "num_axes"      : notrans,
                                "num_keys"      : notrans,
                                "source"        : SOURCE_STR.get}.items():
                try:
                    v = getattr(d, name)
                    dinfo[name] = trans(v, v)
                except:
                    pass
    return info
Beispiel #27
0
def get_screen_info(display, screen):
    info = {}
    try:
        w = screen.get_root_window()
        info["root"] = w.get_geometry()
    except:
        pass
    info["name"] = screen.make_display_name()
    for x in ("width", "height", "width_mm", "height_mm", "resolution", "primary_monitor"):
        fn = getattr(screen, "get_"+x)
        try:
            info[x] = int(fn())
        except:
            pass
    info["monitors"] = screen.get_n_monitors()
    m_info = info.setdefault("monitor", {})
    for i in range(screen.get_n_monitors()):
        m_info[i] = get_monitor_info(display, screen, i)
    try:
        import cairo
        fo = screen.get_font_options()
        #win32 and osx return nothing here...
        if fo:
            fontoptions = info.setdefault("fontoptions", {})
            for x,vdict in {
                            "antialias"     : {cairo.ANTIALIAS_DEFAULT      : "default", cairo.ANTIALIAS_NONE       : "none",   cairo.ANTIALIAS_GRAY        : "gray",   cairo.ANTIALIAS_SUBPIXEL    : "subpixel"},
                            "hint_metrics"  : {cairo.HINT_METRICS_DEFAULT   : "default", cairo.HINT_METRICS_OFF     : "off",    cairo.HINT_METRICS_ON       : "on"},
                            "hint_style"    : {cairo.HINT_STYLE_DEFAULT     : "default", cairo.HINT_STYLE_NONE      : "none",   cairo.HINT_STYLE_SLIGHT     : "slight", cairo.HINT_STYLE_MEDIUM     : "medium", cairo.HINT_STYLE_FULL       : "full"},
                            "subpixel_order": {cairo.SUBPIXEL_ORDER_DEFAULT : "default", cairo.SUBPIXEL_ORDER_RGB   : "RGB",    cairo.SUBPIXEL_ORDER_BGR    : "BGR",    cairo.SUBPIXEL_ORDER_VRGB   : "VRGB",   cairo.SUBPIXEL_ORDER_VBGR   : "VBGR"},
                            }.items():
                fn = getattr(fo, "get_"+x)
                val = fn()
                fontoptions[x] = vdict.get(val, val)
    except:
        pass
    vinfo = info.setdefault("visual", {})
    def visual(name, v):
        if not v:
            return
        for x, vdict in {"bits_per_rgb" : {},
                         "byte_order"   : {LSB_FIRST    : "LSB", MSB_FIRST  : "MSB"},
                         "colormap_size": {},
                         "depth"        : {},
                         "red_pixel_details"    : {},
                         "green_pixel_details"  : {},
                         "blue_pixel_details"   : {},
                         "visual_type"  : {STATIC_GRAY : "STATIC_GRAY", GRAYSCALE : "GRAYSCALE",  STATIC_COLOR : "STATIC_COLOR", PSEUDO_COLOR : "PSEUDO_COLOR", TRUE_COLOR : "TRUE_COLOR", DIRECT_COLOR : "DIRECT_COLOR"},
                         }.items():
            val = None
            try:
                val = getattr(v, x.replace("visual_"))  #ugly workaround for "visual_type" -> "type" for GTK2...
            except:
                try:
                    fn = getattr(v, "get_"+x)
                    val = fn()
                except:
                    pass
            if val is not None:
                vinfo.setdefault(name, {})[x] = vdict.get(val, val)
    try:
        visual("rgb", screen.get_rgb_visual())
    except:
        pass    #not in gtk3?
    visual("rgba", screen.get_rgba_visual())
    visual("system_visual", screen.get_system_visual())
    if SHOW_ALL_VISUALS:
        for i, v in enumerate(screen.list_visuals()):
            visual(i, v)
    #gtk.settings
    if is_gtk3():
        def get_setting(key):
            #try string first, then int
            for t in (gobject.TYPE_STRING, gobject.TYPE_INT):
                v = gobject.Value()
                v.init(t)
                if screen.get_setting(key, v):
                    return v.get_value()
            return None
    else:
        settings = gtk.settings_get_for_screen(screen)
        def get_setting(key):
            return settings.get_property(key)
    sinfo = info.setdefault("settings", {})
    try:
        for x in ("antialias", "dpi", "hinting", "hintstyle", "rgba"):
            try:
                v = get_setting("gtk-xft-"+x)
            except:
                continue
            if v is None:
                v = ""
            sinfo[x] = v
    except:
        pass
    return info
Beispiel #28
0
    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)
Beispiel #29
0
def get_display_info():
    display = display_get_default()
    info = {
            "root"                  : get_default_root_window().get_geometry(),
            "root-size"             : get_root_size(),
            "screens"               : display.get_n_screens(),
            "name"                  : display.get_name(),
            "pointer"               : display.get_pointer()[1:3],
            "devices"               : len(display.list_devices()),
            "default_cursor_size"   : display.get_default_cursor_size(),
            "maximal_cursor_size"   : display.get_maximal_cursor_size(),
            "pointer_is_grabbed"    : display.pointer_is_grabbed(),
            }
    for x in ("composite", "cursor_alpha", "cursor_color", "selection_notification", "clipboard_persistence", "shapes"):
        f = "supports_"+x
        if hasattr(display, f):
            fn = getattr(display, f)
            info[x]  = fn()
    for i in range(display.get_n_screens()):
        screen = display.get_screen(i)
        sk = "screen[%s]" % i
        try:
            w = screen.get_root_window()
            info[sk+".root"] = w.get_geometry()
        except:
            pass
        info[sk+".name"] = screen.make_display_name()
        for x in ("width", "height", "width_mm", "height_mm", "resolution", "primary_monitor"):
            fn = getattr(screen, "get_"+x)
            try:
                info[sk+"."+x] = int(fn())
            except:
                pass
        info[sk+".monitors"] = screen.get_n_monitors()
        for j in range(screen.get_n_monitors()):
            mk = "screen[%s].monitor[%s]" % (i, j)
            geom = screen.get_monitor_geometry(j)
            for x in ("x", "y", "width", "height"):
                info[mk+"."+x] = getattr(geom, x)
            if hasattr(screen, "get_monitor_plug_name"):
                info[mk+".plug_name"] = screen.get_monitor_plug_name(j) or ""
            for x in ("scale_factor", "width_mm", "height_mm"):
                try:
                    fn = getattr(screen, "get_monitor_"+x)
                    info[mk+"."+x] = int(fn(j))
                except:
                    pass
            if hasattr(screen, "get_monitor_workarea"): #GTK3.4:
                rectangle = screen.get_monitor_workarea(j)
                for x in ("x", "y", "width", "height"):
                    info[mk+".workarea."+x] = getattr(rectangle, x)
        try:
            import cairo
            fo = screen.get_font_options()
            #win32 and osx return nothing here...
            if fo:
                fk = sk+".fontoptions"
                for x,vdict in {
                                "antialias"     : {cairo.ANTIALIAS_DEFAULT      : "default", cairo.ANTIALIAS_NONE       : "none",   cairo.ANTIALIAS_GRAY        : "gray",   cairo.ANTIALIAS_SUBPIXEL    : "subpixel"},
                                "hint_metrics"  : {cairo.HINT_METRICS_DEFAULT   : "default", cairo.HINT_METRICS_OFF     : "off",    cairo.HINT_METRICS_ON       : "on"},
                                "hint_style"    : {cairo.HINT_STYLE_DEFAULT     : "default", cairo.HINT_STYLE_NONE      : "none",   cairo.HINT_STYLE_SLIGHT     : "slight", cairo.HINT_STYLE_MEDIUM     : "medium", cairo.HINT_STYLE_FULL       : "full"},
                                "subpixel_order": {cairo.SUBPIXEL_ORDER_DEFAULT : "default", cairo.SUBPIXEL_ORDER_RGB   : "RGB",    cairo.SUBPIXEL_ORDER_BGR    : "BGR",    cairo.SUBPIXEL_ORDER_VRGB   : "VRGB",   cairo.SUBPIXEL_ORDER_VBGR   : "VBGR"},
                                }.items():
                    fn = getattr(fo, "get_"+x)
                    val = fn()
                    info[fk+"."+x] = vdict.get(val, val)
        except:
            pass
        def visual(k, v):
            if not v:
                return
            vk = sk+"."+k       #ie: screen[0].rgb
            for x, vdict in {"bits_per_rgb" : {},
                             "byte_order"   : {LSB_FIRST    : "LSB", MSB_FIRST  : "MSB"},
                             "colormap_size": {},
                             "depth"        : {},
                             "red_pixel_details"    : {},
                             "green_pixel_details"  : {},
                             "blue_pixel_details"   : {},
                             "visual_type"  : {STATIC_GRAY : "STATIC_GRAY", GRAYSCALE : "GRAYSCALE",  STATIC_COLOR : "STATIC_COLOR", PSEUDO_COLOR : "PSEUDO_COLOR", TRUE_COLOR : "TRUE_COLOR", DIRECT_COLOR : "DIRECT_COLOR"},
                             }.items():
                val = None
                try:
                    val = getattr(v, x.replace("visual_"))  #ugly workaround for "visual_type" -> "type" for GTK2...
                except:
                    try:
                        fn = getattr(v, "get_"+x)
                        val = fn()
                    except:
                        pass
                if val is not None:
                    info[vk+"."+x] = vdict.get(val, val)
        try:
            visual("rgb", screen.get_rgb_visual())
        except:
            pass    #not in gtk3?
        visual("rgba", screen.get_rgba_visual())
        visual("system_visual", screen.get_system_visual())
        visuals = screen.list_visuals()
        info[sk+".visuals"] = len(visuals)
        #gtk.settings
        if is_gtk3():
            def get_setting(key):
                #try string first, then int
                for t in (gobject.TYPE_STRING, gobject.TYPE_INT):
                    v = gobject.Value()
                    v.init(t)
                    if screen.get_setting(key, v):
                        return v.get_value()
                return None
        else:
            settings = gtk.settings_get_for_screen(screen)
            def get_setting(key):
                return settings.get_property(key)
        try:
            ssk = "%s.settings" % sk
            for x in ("antialias", "dpi", "hinting", "hintstyle", "rgba"):
                try:
                    v = get_setting("gtk-xft-"+x)
                except:
                    continue
                if v is None:
                    v = ""
                info[ssk+"."+x] = v
        except:
            pass
    if is_gtk3():
        dm = display.get_device_manager()
        for dt, name in {gdk.DeviceType.MASTER  : "master",
                         gdk.DeviceType.SLAVE   : "slave",
                         gdk.DeviceType.FLOATING: "floating"}.items():
            dk = "devices.%s" % name
            devices = dm.list_devices(dt)
            info[dk] = len(devices)
            for i, d in enumerate(devices):
                info[dk+"[%s]" % i] = d.get_name()
    else:
        devices = display.list_devices()
        info["devices"] = len(devices)
        for i, d in enumerate(devices):
            info["device[%s]" % i] = d.get_name()
    return info
Beispiel #30
0
    def setup_window(self):
        self.window = gtk.Window()
        self.window.connect("destroy", self.close)
        self.window.set_default_size(400, 300)
        self.window.set_border_width(20)
        self.window.set_title("Xpra Bug Report")
        self.window.modify_bg(STATE_NORMAL, gdk.Color(red=65535, green=65535, blue=65535))

        icon_pixbuf = self.get_icon("bugs.png")
        if icon_pixbuf:
            self.window.set_icon(icon_pixbuf)
        self.window.set_position(WIN_POS_CENTER)

        vbox = gtk.VBox(False, 0)
        vbox.set_spacing(15)

        # Title
        hbox = gtk.HBox(False, 0)
        icon_pixbuf = self.get_icon("xpra.png")
        if icon_pixbuf and self.show_about:
            from xpra.gtk_common.about import about
            logo_button = gtk.Button("")
            settings = logo_button.get_settings()
            settings.set_property('gtk-button-images', True)
            logo_button.connect("clicked", about)
            logo_button.set_tooltip_text("About")
            image = gtk.Image()
            image.set_from_pixbuf(icon_pixbuf)
            logo_button.set_image(image)
            hbox.pack_start(logo_button, expand=False, fill=False)

        label = gtk.Label("Xpra Bug Report Tool")
        label.modify_font(pango.FontDescription("sans 14"))
        hbox.pack_start(label, expand=True, fill=True)
        vbox.pack_start(hbox)

        #the box containing all the input:
        ibox = gtk.VBox(False, 0)
        ibox.set_spacing(3)
        vbox.pack_start(ibox)

        # Description
        al = gtk.Alignment(xalign=0, yalign=0.5, xscale=0.0, yscale=0)
        al.add(gtk.Label("Please describe the problem:"))
        ibox.pack_start(al)
        #self.description = gtk.Entry(max=128)
        #self.description.set_width_chars(40)
        self.description = gtk.TextView()
        self.description.set_accepts_tab(True)
        self.description.set_justification(JUSTIFY_LEFT)
        self.description.set_border_width(2)
        self.description.set_size_request(300, 80)
        self.description.modify_bg(STATE_NORMAL, gdk.Color(red=32768, green=32768, blue=32768))
        ibox.pack_start(self.description, expand=False, fill=False)

        # Toggles:
        al = gtk.Alignment(xalign=0, yalign=0.5, xscale=0.0, yscale=0)
        al.add(gtk.Label("Include:"))
        ibox.pack_start(al)
        #generic toggles:
        from xpra.gtk_common.keymap import get_gtk_keymap
        from xpra.codecs.loader import codec_versions, load_codecs
        load_codecs()
        try:
            from xpra.sound.wrapper import query_sound
            def get_sound_info():
                return query_sound()
        except:
            get_sound_info = None
        if self.opengl_info:
            def get_gl_info():
                return self.opengl_info
        else:
            try:
                from xpra.client.gl.gl_check import check_support
                def get_gl_info():
                    return check_support(force_enable=True)
            except:
                get_gl_info = None
        from xpra.net.net_util import get_info as get_net_info
        from xpra.platform.paths import get_info as get_path_info
        from xpra.platform.gui import get_info as get_gui_info
        from xpra.version_util import get_version_info, get_platform_info, get_host_info
        def get_sys_info():
            from xpra.platform.info import get_user_info
            from xpra.scripts.config import read_xpra_defaults
            return {
                    "argv"          : sys.argv,
                    "path"          : sys.path,
                    "exec_prefix"   : sys.exec_prefix,
                    "executable"    : sys.executable,
                    "version"       : get_version_info(),
                    "platform"      : get_platform_info(),
                    "host"          : get_host_info(),
                    "paths"         : get_path_info(),
                    "gtk"           : get_gtk_version_info(),
                    "gui"           : get_gui_info(),
                    "display"       : get_display_info(),
                    "user"          : get_user_info(),
                    "env"           : os.environ,
                    "config"        : read_xpra_defaults(),
                    }
        get_screenshot, take_screenshot_fn = None, None
        #screenshot: may have OS-specific code
        try:
            from xpra.platform.gui import take_screenshot
            take_screenshot_fn = take_screenshot
        except:
            log("failed to load platfrom specific screenshot code", exc_info=True)
        if not take_screenshot_fn:
            #try with Pillow:
            try:
                from PIL import ImageGrab           #@UnresolvedImport
                from xpra.os_util import StringIOClass
                def pillow_imagegrab_screenshot():
                    img = ImageGrab.grab()
                    out = StringIOClass()
                    img.save(out, format="PNG")
                    v = out.getvalue()
                    out.close()
                    return (img.width, img.height, "png", img.width*3, v)
                take_screenshot_fn = pillow_imagegrab_screenshot
            except Exception as e:
                log("cannot use Pillow's ImageGrab: %s", e)
        if not take_screenshot_fn:
            #default: gtk screen capture
            try:
                from xpra.server.shadow.gtk_root_window_model import GTKRootWindowModel
                rwm = GTKRootWindowModel(gtk.gdk.get_default_root_window())
                take_screenshot_fn = rwm.take_screenshot
            except:
                log("failed to load gtk screenshot code", exc_info=True)
        log("take_screenshot_fn=%s", take_screenshot_fn)
        if take_screenshot_fn:
            def get_screenshot():
                #take_screenshot() returns: w, h, "png", rowstride, data
                return take_screenshot_fn()[4]
        self.toggles = (
                   ("system",       "txt",  "System",           get_sys_info,   "Xpra version, platform and host information"),
                   ("network",      "txt",  "Network",          get_net_info,   "Compression, packet encoding and encryption"),
                   ("encoding",     "txt",  "Encodings",        codec_versions, "Picture encodings supported"),
                   ("opengl",       "txt",  "OpenGL",           get_gl_info,    "OpenGL driver and features"),
                   ("sound",        "txt",  "Sound",            get_sound_info, "Sound codecs and GStreamer version information"),
                   ("keyboard",     "txt",  "Keyboard Mapping", get_gtk_keymap, "Keyboard layout and key mapping"),
                   ("xpra-info",    "txt",  "Server Info",      self.get_server_info, "Full server information from 'xpra info'"),
                   ("screenshot",   "png",  "Screenshot",       get_screenshot, ""),
                   )
        for name, _, title, value_cb, tooltip in self.toggles:
            cb = gtk.CheckButton(title+[" (not available)", ""][bool(value_cb)])
            cb.set_active(self.includes.get(name, True))
            cb.set_sensitive(bool(value_cb))
            cb.set_tooltip_text(tooltip)
            ibox.pack_start(cb)
            setattr(self, name, cb)

        # Buttons:
        hbox = gtk.HBox(False, 20)
        vbox.pack_start(hbox)
        def btn(label, tooltip, callback, icon_name=None):
            btn = gtk.Button(label)
            btn.set_tooltip_text(tooltip)
            btn.connect("clicked", callback)
            if icon_name:
                icon = self.get_icon(icon_name)
                if icon:
                    btn.set_image(scaled_image(icon, 24))
            hbox.pack_start(btn)
            return btn

        if not is_gtk3():
            #clipboard does not work in gtk3..
            btn("Copy to clipboard", "Copy all data to clipboard", self.copy_clicked, "clipboard.png")
        btn("Save", "Save Bug Report", self.save_clicked, "download.png")
        btn("Cancel", "", self.close, "quit.png")

        def accel_close(*args):
            self.close()
        add_close_accel(self.window, accel_close)
        vbox.show_all()
        self.window.vbox = vbox
        self.window.add(vbox)
Beispiel #31
0
 def popup_menu_workaround(self, menu):
     #win32 workaround:
     if sys.platform.startswith("win") and not is_gtk3():
         self.add_popup_menu_workaround(menu)
Beispiel #32
0
def main():
    from xpra.platform import init, clean
    init("Sound-Record")
    try:
        from xpra.gtk_common.gobject_compat import import_glib
        glib = import_glib()
        args = sys.argv
        log.enable_debug()
        import os.path
        if len(args) not in (2, 3):
            print("usage: %s [-v|--verbose] filename [codec]" % sys.argv[0])
            return 1
        filename = args[1]
        if not os.path.exists(filename):
            print("file %s does not exist" % filename)
            return 2
        codecs = get_codecs()
        if len(args)==3:
            codec = args[2]
            if codec not in codecs:
                print("invalid codec: %s" % codec)
                print("only supported: %s" % str(codecs.keys()))
                return 2
            codecs = [codec]
        else:
            codec = None
            parts = filename.split(".")
            if len(parts)>1:
                extension = parts[-1]
                if extension.lower() in codecs:
                    codec = extension.lower()
                    print("guessed codec %s from file extension %s" % (codec, extension))
            if codec is None:
                print("assuming this is an mp3 file...")
                codec = MP3
            codecs = [codec]

        log.enable_debug()
        with open(filename, "rb") as f:
            data = f.read()
        print("loaded %s bytes from %s" % (len(data), filename))
        #force no leak since we push all the data at once
        global QUEUE_LEAK, QUEUE_SILENT
        QUEUE_LEAK = GST_QUEUE_NO_LEAK
        QUEUE_SILENT = 1
        ss = SoundSink(codecs=codecs)
        def eos(*args):
            print("eos")
            glib.idle_add(glib_mainloop.quit)
        ss.connect("eos", eos)
        ss.start()

        glib_mainloop = glib.MainLoop()

        import signal
        def deadly_signal(*args):
            glib.idle_add(ss.stop)
            glib.idle_add(glib_mainloop.quit)
            def force_quit(sig, frame):
                sys.exit()
            signal.signal(signal.SIGINT, force_quit)
            signal.signal(signal.SIGTERM, force_quit)
        from xpra.gtk_common.gobject_compat import is_gtk3
        if not is_gtk3():
            signal.signal(signal.SIGINT, deadly_signal)
        signal.signal(signal.SIGTERM, deadly_signal)

        def check_for_end(*args):
            qtime = ss.queue.get_property("current-level-time")//MS_TO_NS
            if qtime<=0:
                log.info("underrun (end of stream)")
                thread.start_new_thread(ss.stop, ())
                glib.timeout_add(500, glib_mainloop.quit)
                return False
            return True
        glib.timeout_add(1000, check_for_end)
        glib.idle_add(ss.add_data, data)

        glib_mainloop.run()
        return 0
    finally:
        clean()
Beispiel #33
0
def main():
    from xpra.platform import program_context
    with program_context("Sound-Record"):
        from xpra.gtk_common.gobject_compat import import_glib
        glib = import_glib()
        args = sys.argv
        log.enable_debug()
        import os.path
        if len(args) not in (2, 3):
            print("usage: %s [-v|--verbose] filename [codec]" % sys.argv[0])
            return 1
        filename = args[1]
        if not os.path.exists(filename):
            print("file %s does not exist" % filename)
            return 2
        codecs = get_codecs()
        if len(args)==3:
            codec = args[2]
            if codec not in codecs:
                print("invalid codec: %s" % codec)
                print("only supported: %s" % str(codecs.keys()))
                return 2
            codecs = [codec]
        else:
            codec = None
            parts = filename.split(".")
            if len(parts)>1:
                extension = parts[-1]
                if extension.lower() in codecs:
                    codec = extension.lower()
                    print("guessed codec %s from file extension %s" % (codec, extension))
            if codec is None:
                print("assuming this is an mp3 file...")
                codec = MP3
            codecs = [codec]

        log.enable_debug()
        with open(filename, "rb") as f:
            data = f.read()
        print("loaded %s bytes from %s" % (len(data), filename))
        #force no leak since we push all the data at once
        global QUEUE_LEAK, QUEUE_SILENT
        QUEUE_LEAK = GST_QUEUE_NO_LEAK
        QUEUE_SILENT = 1
        ss = SoundSink(codecs=codecs)
        def eos(*args):
            print("eos")
            glib.idle_add(glib_mainloop.quit)
        ss.connect("eos", eos)
        ss.start()

        glib_mainloop = glib.MainLoop()

        import signal
        def deadly_signal(*args):
            glib.idle_add(ss.stop)
            glib.idle_add(glib_mainloop.quit)
            def force_quit(sig, frame):
                sys.exit()
            signal.signal(signal.SIGINT, force_quit)
            signal.signal(signal.SIGTERM, force_quit)
        from xpra.gtk_common.gobject_compat import is_gtk3
        if not is_gtk3():
            signal.signal(signal.SIGINT, deadly_signal)
        signal.signal(signal.SIGTERM, deadly_signal)

        def check_for_end(*args):
            qtime = ss.queue.get_property("current-level-time")//MS_TO_NS
            if qtime<=0:
                log.info("underrun (end of stream)")
                thread.start_new_thread(ss.stop, ())
                glib.timeout_add(500, glib_mainloop.quit)
                return False
            return True
        glib.timeout_add(1000, check_for_end)
        glib.idle_add(ss.add_data, data)

        glib_mainloop.run()
        return 0