def get_screen_sizes(self, xscale=1, yscale=1): def xs(v): return iround(v/xscale) def ys(v): return iround(v/yscale) def swork(*workarea): return xs(workarea[0]), ys(workarea[1]), xs(workarea[2]), ys(workarea[3]) display = display_get_default() i=0 screen_sizes = [] n_screens = display.get_n_screens() screenlog("get_screen_sizes(%f, %f) found %s screens", xscale, yscale, n_screens) while i<n_screens: screen = display.get_screen(i) j = 0 monitors = [] workareas = [] #native "get_workareas()" is only valid for a single screen (but describes all the monitors) #and it is only implemented on win32 right now #other platforms only implement "get_workarea()" instead, which is reported against the screen n_monitors = screen.get_n_monitors() screenlog(" screen %s has %s monitors", i, n_monitors) if n_screens==1: workareas = get_workareas() if len(workareas)!=n_monitors: screenlog(" workareas: %s", workareas) screenlog(" number of monitors does not match number of workareas!") workareas = [] while j<screen.get_n_monitors(): geom = screen.get_monitor_geometry(j) plug_name = "" if hasattr(screen, "get_monitor_plug_name"): plug_name = screen.get_monitor_plug_name(j) or "" wmm = -1 if hasattr(screen, "get_monitor_width_mm"): wmm = screen.get_monitor_width_mm(j) hmm = -1 if hasattr(screen, "get_monitor_height_mm"): hmm = screen.get_monitor_height_mm(j) monitor = [plug_name, xs(geom.x), ys(geom.y), xs(geom.width), ys(geom.height), wmm, hmm] screenlog(" monitor %s: %s", j, monitor) if workareas: w = workareas[j] monitor += list(swork(*w)) monitors.append(tuple(monitor)) j += 1 work_x, work_y, work_width, work_height = swork(0, 0, screen.get_width(), screen.get_height()) workarea = get_workarea() if workarea: work_x, work_y, work_width, work_height = swork(*workarea) screenlog(" workarea=%s", workarea) item = (screen.make_display_name(), xs(screen.get_width()), ys(screen.get_height()), screen.get_width_mm(), screen.get_height_mm(), monitors, work_x, work_y, work_width, work_height) screenlog(" screen %s: %s", i, item) screen_sizes.append(item) i += 1 return screen_sizes
def update(self): old_hash = self.hash self.query_xkbmap() try: self.keyboard.update_modifier_map(display_get_default(), self.xkbmap_mod_meanings) except: log.error("error querying modifier map", exc_info=True) log("do_keys_changed() modifier_map=%s, old hash=%s, new hash=%s", self.keyboard.modifier_map, old_hash, self.hash) return old_hash!=self.hash
def process_ui_capabilities(self, capabilities): UIXpraClient.process_ui_capabilities(self, capabilities) if self.server_randr: display = display_get_default() i=0 while i<display.get_n_screens(): screen = display.get_screen(i) screen.connect("size-changed", self.screen_size_changed) i += 1
def make_cursor(self, cursor_data): #if present, try cursor ny name: display = display_get_default() if len(cursor_data)>=9 and cursor_types: cursor_name = bytestostr(cursor_data[8]) if cursor_name: gdk_cursor = cursor_types.get(cursor_name.upper()) if gdk_cursor is not None: cursorlog("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return new_Cursor_for_display(display, gdk_cursor) else: global missing_cursor_names if cursor_name not in missing_cursor_names: cursorlog("cursor name '%s' not found", cursor_name) missing_cursor_names.add(cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels)<w*h*4: import binascii cursorlog.warn("not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w*h*4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = get_pixbuf_from_data(pixels, True, w, h, w*4) x = max(0, min(xhot, w-1)) y = max(0, min(yhot, h-1)) csize = display.get_default_cursor_size() cmaxw, cmaxh = display.get_maximal_cursor_size() if len(cursor_data)>=11: ssize = cursor_data[9] smax = cursor_data[10] cursorlog("server cursor sizes: default=%s, max=%s", ssize, smax) cursorlog("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot,yhot, serial, w,h, len(pixels), csize, (cmaxw, cmaxh)) fw, fh = get_fixed_cursor_size() if fw>0 and fh>0 and (w!=fw or h!=fh): #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us) if w<=fw and h<=fh: cursorlog("pasting cursor of size %ix%i onto clear pixbuf of size %ix%i", w, h, fw, fh) cursor_pixbuf = get_pixbuf_from_data("\0"*fw*fh*4, True, fw, fh, fw*4) pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0) else: cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i", w, h, fw, fh) cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR) xratio, yratio = float(w)/fw, float(h)/fh x, y = int(x/xratio), int(y/yratio) elif w>cmaxw or h>cmaxh or (csize>0 and (csize<w or csize<h)): ratio = max(float(w)/cmaxw, float(h)/cmaxh, float(max(w,h))/csize) x, y, w, h = int(x/ratio), int(y/ratio), int(w/ratio), int(h/ratio) cursorlog("downscaling cursor %s by %.2f: %sx%s", pixbuf, ratio, w, h) cursor_pixbuf = pixbuf.scale_simple(w, h, INTERP_BILINEAR) else: cursor_pixbuf = pixbuf #clamp to pixbuf size: w = cursor_pixbuf.get_width() h = cursor_pixbuf.get_height() x = max(0, min(x, w-1)) y = max(0, min(y, h-1)) return new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y)
def get_ui_cursor_info(self): #(from UI thread) #now cursor size info: display = display_get_default() pos = display.get_default_screen().get_root_window().get_pointer( )[-3:-1] cinfo = {"position": pos} for prop, size in { "default": display.get_default_cursor_size(), "max": tuple(display.get_maximal_cursor_size()), }.items(): if size is None: continue cinfo["%s_size" % prop] = size return cinfo
def make_hello(self, source): capabilities = ServerBase.make_hello(self, source) if source.wants_display: display = display_get_default() max_size = tuple(display.get_maximal_cursor_size()) capabilities.update({ "display": display.get_name(), "cursor.default_size": display.get_default_cursor_size(), "cursor.max_size": max_size, }) if source.wants_versions: capabilities.update(flatten_dict(get_gtk_version_info())) return capabilities
def load_existing_windows(self): #at present, just one window is forwarded: #the root window covering the whole display display = display_get_default() screens = display.get_n_screens() with xsync: for n in range(screens): screen = display.get_screen(n) root = screen.get_root_window() model = DesktopModel(root, self.randr_exact_size) model.setup() windowlog("adding root window model %s", model) super(XpraDesktopServer, self)._add_new_window_common(model) model.managed_connect("client-contents-changed", self._contents_changed) model.managed_connect("resized", self._window_resized_signaled)
def get_gtk_keymap(ignore_keys=(None, "VoidSymbol", "0xffffff")): """ Augment the keymap we get from gtk.gdk.keymap_get_default() by adding the keyval_name. We can also ignore some keys """ from xpra.gtk_common.gtk_util import keymap_get_for_display, display_get_default, import_gdk, is_gtk3 gdk = import_gdk() display = display_get_default() if not display: return () keymap = keymap_get_for_display(display) log( "keymap_get_for_display(%s)=%s, direction=%s, bidirectional layouts: %s", display, keymap, keymap.get_direction(), keymap.have_bidi_layouts()) keycodes = [] for i in range(0, 2**8): entries = keymap.get_entries_for_keycode(i) log("get_entries_for_keycode(%s)=%s", i, entries) if not entries: continue if is_gtk3(): found, keys, keyvals = entries if not found: continue for j, key in enumerate(keys): keyval = keyvals[j] keycode = key.keycode name = gdk.keyval_name(keyval) name = KEY_TRANSLATIONS.get((name, keyval, keycode), name) group = key.group or 0 if name not in ignore_keys: keycodes.append((keyval or 0, name or "", keycode or 0, group, key.level or 0)) else: #gtk2: for keyval, keycode, group, level in entries: #assert keycode==i name = gdk.keyval_name(keyval) name = KEY_TRANSLATIONS.get((name, keyval, keycode), name) if name not in ignore_keys: keycodes.append((keyval or 0, name or "", keycode or 0, group or 0, level or 0)) log("get_gtk_keymap(%s)=%s (keymap=%s)", ignore_keys, keycodes, keymap) return keycodes
def do_run(self): if UI_THREAD_WATCHER: from xpra.platform.ui_thread_watcher import get_UI_watcher self.ui_watcher = get_UI_watcher(glib.timeout_add, glib.source_remove) self.ui_watcher.start() if server_features.windows: display = display_get_default() i = 0 while i < display.get_n_screens(): screen = display.get_screen(i) screen.connect("size-changed", self._screen_size_changed) screen.connect("monitors-changed", self._monitors_changed) i += 1 gtk_main_quit_on_fatal_exceptions_enable() log("do_run() calling %s", gtk_main) gtk_main() log("do_run() end of gtk.main()")
def get_screen_sizes(self): display = display_get_default() i = 0 screen_sizes = [] while i < display.get_n_screens(): screen = display.get_screen(i) j = 0 monitors = [] while j < screen.get_n_monitors(): geom = screen.get_monitor_geometry(j) plug_name = "" if hasattr(screen, "get_monitor_plug_name"): plug_name = screen.get_monitor_plug_name(j) or "" wmm = -1 if hasattr(screen, "get_monitor_width_mm"): wmm = screen.get_monitor_width_mm(j) hmm = -1 if hasattr(screen, "get_monitor_height_mm"): hmm = screen.get_monitor_height_mm(j) monitor = plug_name, geom.x, geom.y, geom.width, geom.height, wmm, hmm monitors.append(monitor) j += 1 work_x, work_y = 0, 0 work_width, work_height = screen.get_width(), screen.get_height() if not sys.platform.startswith("win"): try: p = gtk.gdk.atom_intern('_NET_WORKAREA') root = screen.get_root_window() work_x, work_y, work_width, work_height = root.property_get( p)[2][:4] except: pass item = (screen.make_display_name(), screen.get_width(), screen.get_height(), screen.get_width_mm(), screen.get_height_mm(), monitors, work_x, work_y, work_width, work_height) screen_sizes.append(item) i += 1 return screen_sizes
def get_screen_sizes(self): display = display_get_default() i=0 screen_sizes = [] while i<display.get_n_screens(): screen = display.get_screen(i) j = 0 monitors = [] while j<screen.get_n_monitors(): geom = screen.get_monitor_geometry(j) plug_name = "" if hasattr(screen, "get_monitor_plug_name"): plug_name = screen.get_monitor_plug_name(j) or "" wmm = -1 if hasattr(screen, "get_monitor_width_mm"): wmm = screen.get_monitor_width_mm(j) hmm = -1 if hasattr(screen, "get_monitor_height_mm"): hmm = screen.get_monitor_height_mm(j) monitor = plug_name, geom.x, geom.y, geom.width, geom.height, wmm, hmm monitors.append(monitor) j += 1 work_x, work_y = 0, 0 work_width, work_height = screen.get_width(), screen.get_height() if not sys.platform.startswith("win"): try: p = gtk.gdk.atom_intern('_NET_WORKAREA') root = screen.get_root_window() work_x, work_y, work_width, work_height = root.property_get(p)[2][:4] except: pass item = (screen.make_display_name(), screen.get_width(), screen.get_height(), screen.get_width_mm(), screen.get_height_mm(), monitors, work_x, work_y, work_width, work_height) screen_sizes.append(item) i += 1 return screen_sizes
def wm_check(wm_name, upgrading=False): with xsync: display = display_get_default() #there should only be one screen... but let's check all of them for i in range(display.get_n_screens()): screen = display.get_screen(i) root = screen.get_root_window() wm_prop = "WM_S%s" % i cwm_prop = "_NEW_WM_CM_S%s" % i wm_so = X11Window.XGetSelectionOwner(wm_prop) cwm_so = X11Window.XGetSelectionOwner(cwm_prop) log("ewmh selection owner for %s: %s", wm_prop, wm_so) log("compositing window manager %s: %s", cwm_prop, cwm_so) ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) def xid(w): if w: return "%#x" % get_xwindow(w) return None log("_NET_SUPPORTING_WM_CHECK for screen %i: %s (root=%s)", i, xid(ewmh_wm), xid(root)) if not ewmh_wm: continue name = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=True, raise_xerrors=False) if upgrading and name and name == wm_name: log.info("found previous Xpra instance") else: log.warn("Warning: found an existing window manager") log.warn(" on screen %s using window %#x: %s", i, get_xwindow(ewmh_wm), name or "unknown") if (wm_so is None or wm_so == 0) and (cwm_so is None or cwm_so == 0): if FORCE_REPLACE_WM: log.warn( "XPRA_FORCE_REPLACE_WM is set, replacing it forcibly") else: log.error("it does not own the selection '%s' or '%s'", wm_prop, cwm_prop) log.error("so we cannot take over and make it exit") log.error( "please stop %s so you can run xpra on this display", name or "the existing window manager") log.warn( "if you are certain that the window manager is already gone," ) log.warn( " you may set XPRA_FORCE_REPLACE_WM=1 to force xpra to continue" ) log.warn(" at your own risk") return False return True
def make_cursor(self, cursor_data): #if present, try cursor ny name: display = display_get_default() cursorlog("make_cursor: has-name=%s, has-cursor-types=%s, xscale=%s, yscale=%s, USE_LOCAL_CURSORS=%s", len(cursor_data)>=9, bool(cursor_types), self.xscale, self.yscale, USE_LOCAL_CURSORS) #named cursors cannot be scaled (round to 10 to compare so 0.95 and 1.05 are considered the same as 1.0, no scaling): if len(cursor_data)>=9 and cursor_types and iround(self.xscale*10)==10 and iround(self.yscale*10)==10: cursor_name = bytestostr(cursor_data[8]) if cursor_name and USE_LOCAL_CURSORS: gdk_cursor = cursor_types.get(cursor_name.upper()) if gdk_cursor is not None: cursorlog("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return new_Cursor_for_display(display, gdk_cursor) else: global missing_cursor_names if cursor_name not in missing_cursor_names: cursorlog("cursor name '%s' not found", cursor_name) missing_cursor_names.add(cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels)<w*h*4: import binascii cursorlog.warn("not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w*h*4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = get_pixbuf_from_data(pixels, True, w, h, w*4) x = max(0, min(xhot, w-1)) y = max(0, min(yhot, h-1)) csize = display.get_default_cursor_size() cmaxw, cmaxh = display.get_maximal_cursor_size() if len(cursor_data)>=11: ssize = cursor_data[9] smax = cursor_data[10] cursorlog("server cursor sizes: default=%s, max=%s", ssize, smax) cursorlog("new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot,yhot, serial, w,h, len(pixels), csize, (cmaxw, cmaxh)) fw, fh = get_fixed_cursor_size() if fw>0 and fh>0 and (w!=fw or h!=fh): #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us) if w<=fw and h<=fh: cursorlog("pasting cursor of size %ix%i onto clear pixbuf of size %ix%i", w, h, fw, fh) cursor_pixbuf = get_pixbuf_from_data("\0"*fw*fh*4, True, fw, fh, fw*4) pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0) else: cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i", w, h, fw, fh) cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR) xratio, yratio = float(w)/fw, float(h)/fh x, y = iround(x/xratio), iround(y/yratio) else: sx, sy, sw, sh = x, y, w, h #scale the cursors: if self.xscale!=1 or self.yscale!=1: sx, sy, sw, sh = self.srect(x, y, w, h) sw = max(1, sw) sh = max(1, sh) #ensure we honour the max size if there is one: if (cmaxw>0 and sw>cmaxw) or (cmaxh>0 and sh>cmaxh): ratio = 1.0 if cmaxw>0: ratio = max(ratio, float(w)/cmaxw) if cmaxh>0: ratio = max(ratio, float(h)/cmaxh) cursorlog("clamping cursor size to %ix%i using ratio=%s", cmaxw, cmaxh, ratio) sx, sy, sw, sh = iround(x/ratio), iround(y/ratio), min(cmaxw, iround(w/ratio)), min(cmaxh, iround(h/ratio)) if sw!=w or sh!=h: cursorlog("scaling cursor from %ix%i hotspot at %ix%i to %ix%i hotspot at %ix%i", w, h, x, y, sw, sh, sx, sy) cursor_pixbuf = pixbuf.scale_simple(sw, sh, INTERP_BILINEAR) x, y = sx, sy else: cursor_pixbuf = pixbuf #clamp to pixbuf size: w = cursor_pixbuf.get_width() h = cursor_pixbuf.get_height() x = max(0, min(x, w-1)) y = max(0, min(y, h-1)) try: c = new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y) except RuntimeError as e: log.error("Error: failed to create cursor:") log.error(" %s", e) log.error(" using %s of size %ix%i with hotspot at %ix%i", cursor_pixbuf, w, h, x, y) c = None return c
def send_initial_cursors(self, ss, _sharing=False): #cursors: get sizes and send: display = display_get_default() self.cursor_sizes = display.get_default_cursor_size(), display.get_maximal_cursor_size() cursorlog("send_initial_cursors() cursor_sizes=%s", self.cursor_sizes) ss.send_cursor()
def get_cursor_sizes(self): display = display_get_default() return display.get_default_cursor_size( ), display.get_maximal_cursor_size()
def __init__(self, alpha=False): display = display_get_default() screen = display.get_default_screen() bpc = 8 attrs = c_attrs({ GLX.GLX_RGBA: True, GLX.GLX_RED_SIZE: bpc, GLX.GLX_GREEN_SIZE: bpc, GLX.GLX_BLUE_SIZE: bpc, GLX.GLX_ALPHA_SIZE: int(alpha) * bpc, GLX.GLX_DOUBLEBUFFER: int(DOUBLE_BUFFERED), }) self.props = {} self.xdisplay = get_xdisplay() xvinfo = GLX.glXChooseVisual(self.xdisplay, screen.get_number(), attrs) def getconfig(attrib): value = c_int() r = GLX.glXGetConfig(self.xdisplay, xvinfo, attrib, byref(value)) assert r == 0, "glXGetConfig returned %i" % r return value.value assert getconfig( GLX.GLX_USE_GL), "OpenGL is not supported by this visual!" major = c_int() minor = c_int() assert GLX.glXQueryVersion(self.xdisplay, byref(major), byref(minor)) log("found GLX version %i.%i", major.value, minor.value) self.props["GLX"] = (major.value, minor.value) self.bit_depth = getconfig(GLX.GLX_RED_SIZE) + getconfig( GLX.GLX_GREEN_SIZE) + getconfig(GLX.GLX_BLUE_SIZE) + getconfig( GLX.GLX_ALPHA_SIZE) self.props["depth"] = self.bit_depth self.props["has-depth-buffer"] = getconfig(GLX.GLX_DEPTH_SIZE) > 0 self.props["has-stencil-buffer"] = getconfig(GLX.GLX_STENCIL_SIZE) > 0 self.props["has-alpha"] = getconfig(GLX.GLX_ALPHA_SIZE) > 0 for attrib, name in { GLX.GLX_ACCUM_RED_SIZE: "accum-red-size", GLX.GLX_ACCUM_GREEN_SIZE: "accum-green-size", GLX.GLX_ACCUM_BLUE_SIZE: "accum-blue-size", GLX.GLX_ACCUM_ALPHA_SIZE: "accum-alpha-size", GLX.GLX_RED_SIZE: "red-size", GLX.GLX_GREEN_SIZE: "green-size", GLX.GLX_BLUE_SIZE: "blue-size", GLX.GLX_ALPHA_SIZE: "alpha-size", GLX.GLX_DEPTH_SIZE: "depth-size", GLX.GLX_STENCIL_SIZE: "stencil-size", GLX.GLX_BUFFER_SIZE: "buffer-size", GLX.GLX_AUX_BUFFERS: "aux-buffers", GLX.GLX_DOUBLEBUFFER: "double-buffered", GLX.GLX_LEVEL: "level", GLX.GLX_STEREO: "stereo", GLX.GLX_RGBA: "rgba", }.items(): v = getconfig(attrib) if name in ("stereo", "double-buffered", "rgba"): v = bool(v) self.props[name] = v #attribute names matching gtkgl: display_mode = [] if getconfig(GLX.GLX_RGBA): #this particular context may not have alpha channel support... #but if we have RGBA then it's almost guaranteed that we can do ALPHA display_mode.append("ALPHA") if getconfig(GLX.GLX_DOUBLEBUFFER): display_mode.append("DOUBLE") else: display_mode.append("SINGLE") self.props["display_mode"] = display_mode self.context = GLX.glXCreateContext(self.xdisplay, xvinfo, None, True) self.props["direct"] = bool( GLX.glXIsDirect(self.xdisplay, self.context)) self.props["vendor"] = glGetString(GL_VENDOR) self.props["renderer"] = glGetString(GL_RENDERER) log("GLXContext(%s) context=%s, props=%s", alpha, self.context, self.props)
def _move_pointer(self, _wid, pos, *_args): x, y = pos display = display_get_default() display.warp_pointer(display.get_default_screen(), x, y)
def __init__(self, alpha=False): self.props = {} self.xdisplay = None self.context = None self.bit_depth = 0 display = display_get_default() if not display: log.warn("Warning: GLXContext: no default display") return screen = display.get_default_screen() bpc = 8 pyattrs = { GLX.GLX_RGBA: None, GLX.GLX_RED_SIZE: bpc, GLX.GLX_GREEN_SIZE: bpc, GLX.GLX_BLUE_SIZE: bpc, } if alpha: pyattrs[GLX.GLX_ALPHA_SIZE] = int(alpha) * bpc if DOUBLE_BUFFERED: pyattrs[GLX.GLX_DOUBLEBUFFER] = None attrs = c_attrs(pyattrs) self.xdisplay = get_xdisplay() xvinfo = GLX.glXChooseVisual(self.xdisplay, screen.get_number(), attrs) def getconfig(attrib): value = c_int() r = GLX.glXGetConfig(self.xdisplay, xvinfo, attrib, byref(value)) assert r == 0, "glXGetConfig returned %i" % r return value.value assert getconfig( GLX.GLX_USE_GL), "OpenGL is not supported by this visual!" major = c_int() minor = c_int() assert GLX.glXQueryVersion(self.xdisplay, byref(major), byref(minor)) log("found GLX version %i.%i", major.value, minor.value) self.props["GLX"] = (major.value, minor.value) self.bit_depth = sum( getconfig(x) for x in (GLX.GLX_RED_SIZE, GLX.GLX_GREEN_SIZE, GLX.GLX_BLUE_SIZE, GLX.GLX_ALPHA_SIZE)) self.props["depth"] = self.bit_depth self.props["has-depth-buffer"] = getconfig(GLX.GLX_DEPTH_SIZE) > 0 self.props["has-stencil-buffer"] = getconfig(GLX.GLX_STENCIL_SIZE) > 0 self.props["has-alpha"] = getconfig(GLX.GLX_ALPHA_SIZE) > 0 for attrib, name in GLX_ATTRIBUTES.items(): v = getconfig(attrib) if name in ("stereo", "double-buffered", "rgba"): v = bool(v) self.props[name] = v #attribute names matching gtkgl: display_mode = [] if getconfig(GLX.GLX_RGBA): #this particular context may not have alpha channel support... #but if we have RGBA then it's almost guaranteed that we can do ALPHA display_mode.append("ALPHA") if getconfig(GLX.GLX_DOUBLEBUFFER): display_mode.append("DOUBLE") else: display_mode.append("SINGLE") self.props["display_mode"] = display_mode self.context = GLX.glXCreateContext(self.xdisplay, xvinfo, None, True) self.props["direct"] = bool( GLX.glXIsDirect(self.xdisplay, self.context)) def getstr(k): try: return glGetString(k) except Exception as e: self.props["safe"] = False result = getattr(e, "result", None) if result and isinstance(result, str): return result raise self.props["vendor"] = getstr(GL_VENDOR) self.props["renderer"] = getstr(GL_RENDERER) log("GLXContext(%s) context=%s, props=%s", alpha, self.context, self.props)
def compute_modifier_map(self): self.modifier_map = grok_modifier_map(display_get_default(), self.xkbmap_mod_meanings) log("modifier_map(%s)=%s", self.xkbmap_mod_meanings, self.modifier_map)
def make_cursor(self, cursor_data): #if present, try cursor ny name: display = display_get_default() cursorlog( "make_cursor: has-name=%s, has-cursor-types=%s, xscale=%s, yscale=%s, USE_LOCAL_CURSORS=%s", len(cursor_data) >= 9, bool(cursor_types), self.xscale, self.yscale, USE_LOCAL_CURSORS) #named cursors cannot be scaled (round to 10 to compare so 0.95 and 1.05 are considered the same as 1.0, no scaling): if len(cursor_data) >= 9 and cursor_types and iround( self.xscale * 10) == 10 and iround(self.yscale * 10) == 10: cursor_name = bytestostr(cursor_data[8]) if cursor_name and USE_LOCAL_CURSORS: gdk_cursor = cursor_types.get(cursor_name.upper()) if gdk_cursor is not None: cursorlog("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return new_Cursor_for_display(display, gdk_cursor) else: global missing_cursor_names if cursor_name not in missing_cursor_names: cursorlog("cursor name '%s' not found", cursor_name) missing_cursor_names.add(cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels) < w * h * 4: import binascii cursorlog.warn( "not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w * h * 4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = get_pixbuf_from_data(pixels, True, w, h, w * 4) x = max(0, min(xhot, w - 1)) y = max(0, min(yhot, h - 1)) csize = display.get_default_cursor_size() cmaxw, cmaxh = display.get_maximal_cursor_size() if len(cursor_data) >= 11: ssize = cursor_data[9] smax = cursor_data[10] cursorlog("server cursor sizes: default=%s, max=%s", ssize, smax) cursorlog( "new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot, yhot, serial, w, h, len(pixels), csize, (cmaxw, cmaxh)) fw, fh = get_fixed_cursor_size() if fw > 0 and fh > 0 and (w != fw or h != fh): #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us) if w <= fw and h <= fh: cursorlog( "pasting cursor of size %ix%i onto clear pixbuf of size %ix%i", w, h, fw, fh) cursor_pixbuf = get_pixbuf_from_data("\0" * fw * fh * 4, True, fw, fh, fw * 4) pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0) else: cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i", w, h, fw, fh) cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR) xratio, yratio = float(w) / fw, float(h) / fh x, y = iround(x / xratio), iround(y / yratio) else: sx, sy, sw, sh = x, y, w, h #scale the cursors: if self.xscale != 1 or self.yscale != 1: sx, sy, sw, sh = self.srect(x, y, w, h) sw = max(1, sw) sh = max(1, sh) #ensure we honour the max size if there is one: if (cmaxw > 0 and sw > cmaxw) or (cmaxh > 0 and sh > cmaxh): ratio = 1.0 if cmaxw > 0: ratio = max(ratio, float(w) / cmaxw) if cmaxh > 0: ratio = max(ratio, float(h) / cmaxh) cursorlog("clamping cursor size to %ix%i using ratio=%s", cmaxw, cmaxh, ratio) sx, sy, sw, sh = iround(x / ratio), iround(y / ratio), min( cmaxw, iround(w / ratio)), min(cmaxh, iround(h / ratio)) if sw != w or sh != h: cursorlog( "scaling cursor from %ix%i hotspot at %ix%i to %ix%i hotspot at %ix%i", w, h, x, y, sw, sh, sx, sy) cursor_pixbuf = pixbuf.scale_simple(sw, sh, INTERP_BILINEAR) x, y = sx, sy else: cursor_pixbuf = pixbuf #clamp to pixbuf size: w = cursor_pixbuf.get_width() h = cursor_pixbuf.get_height() x = max(0, min(x, w - 1)) y = max(0, min(y, h - 1)) try: c = new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y) except RuntimeError as e: log.error("Error: failed to create cursor:") log.error(" %s", e) log.error(" using %s of size %ix%i with hotspot at %ix%i", cursor_pixbuf, w, h, x, y) c = None return c
def get_screen_sizes(self, xscale=1, yscale=1): def xs(v): return iround(v / xscale) def ys(v): return iround(v / yscale) def swork(*workarea): return xs(workarea[0]), ys(workarea[1]), xs(workarea[2]), ys( workarea[3]) display = display_get_default() i = 0 screen_sizes = [] n_screens = display.get_n_screens() screenlog("get_screen_sizes(%f, %f) found %s screens", xscale, yscale, n_screens) while i < n_screens: screen = display.get_screen(i) j = 0 monitors = [] workareas = [] #native "get_workareas()" is only valid for a single screen (but describes all the monitors) #and it is only implemented on win32 right now #other platforms only implement "get_workarea()" instead, which is reported against the screen n_monitors = screen.get_n_monitors() screenlog(" screen %s has %s monitors", i, n_monitors) if n_screens == 1: workareas = get_workareas() if len(workareas) != n_monitors: screenlog(" workareas: %s", workareas) screenlog( " number of monitors does not match number of workareas!" ) workareas = [] while j < screen.get_n_monitors(): geom = screen.get_monitor_geometry(j) plug_name = "" if hasattr(screen, "get_monitor_plug_name"): plug_name = screen.get_monitor_plug_name(j) or "" wmm = -1 if hasattr(screen, "get_monitor_width_mm"): wmm = screen.get_monitor_width_mm(j) hmm = -1 if hasattr(screen, "get_monitor_height_mm"): hmm = screen.get_monitor_height_mm(j) monitor = [ plug_name, xs(geom.x), ys(geom.y), xs(geom.width), ys(geom.height), wmm, hmm ] screenlog(" monitor %s: %s", j, monitor) if workareas: w = workareas[j] monitor += list(swork(*w)) monitors.append(tuple(monitor)) j += 1 work_x, work_y, work_width, work_height = swork( 0, 0, screen.get_width(), screen.get_height()) workarea = get_workarea() if workarea: work_x, work_y, work_width, work_height = swork(*workarea) screenlog(" workarea=%s", workarea) item = (screen.make_display_name(), xs(screen.get_width()), ys(screen.get_height()), screen.get_width_mm(), screen.get_height_mm(), monitors, work_x, work_y, work_width, work_height) screenlog(" screen %s: %s", i, item) screen_sizes.append(item) i += 1 return screen_sizes
def watch_keymap_changes(self): ### Set up keymap change notification: display = display_get_default() keymap = keymap_get_for_display(display) keymap.connect("keys-changed", self._keys_changed)
def __init__(self, replace_other_wm, wm_name, display=None): gobject.GObject.__init__(self) if display is None: display = display_get_default() self._display = display self._root = self._display.get_default_screen().get_root_window() self._wm_name = wm_name self._ewmh_window = None self._windows = {} # EWMH says we have to know the order of our windows oldest to # youngest... self._windows_in_order = [] # Become the Official Window Manager of this year's display: self._wm_selection = ManagerSelection(self._display, "WM_S0") self._cm_wm_selection = ManagerSelection(self._display, "_NET_WM_CM_S0") self._wm_selection.connect("selection-lost", self._lost_wm_selection) self._cm_wm_selection.connect("selection-lost", self._lost_wm_selection) # May throw AlreadyOwned: if replace_other_wm: mode = self._wm_selection.FORCE else: mode = self._wm_selection.IF_UNOWNED self._wm_selection.acquire(mode) self._cm_wm_selection.acquire(mode) # Set up the necessary EWMH properties on the root window. self._setup_ewmh_window() # Start with just one desktop: self.set_desktop_list((u"Main", )) self.set_current_desktop(0) # Start with the full display as workarea: root_w, root_h = get_default_root_window().get_geometry()[2:4] self.root_set("_NET_SUPPORTED", ["atom"], NET_SUPPORTED) self.set_workarea(0, 0, root_w, root_h) self.set_desktop_geometry(root_w, root_h) self.root_set("_NET_DESKTOP_VIEWPORT", ["u32"], [0, 0]) self.size_constraints = DEFAULT_SIZE_CONSTRAINTS # Load up our full-screen widget self._world_window = None if not is_gtk3(): self._world_window = WorldWindow( self._display.get_default_screen()) self.notify("toplevel") self._world_window.show_all() # Okay, ready to select for SubstructureRedirect and then load in all # the existing clients. add_event_receiver(self._root, self) add_fallback_receiver("xpra-client-message-event", self) #when reparenting, the events may get sent #to a window that is already destroyed #and we don't want to miss those events, so: add_fallback_receiver("child-map-request-event", self) rxid = get_xwindow(self._root) X11Window.substructureRedirect(rxid) for w in get_children(self._root): # Checking for FOREIGN here filters out anything that we've # created ourselves (like, say, the world window), and checking # for mapped filters out any withdrawn windows. xid = get_xwindow(w) if (w.get_window_type() == GDKWINDOW_FOREIGN and not X11Window.is_override_redirect(xid) and X11Window.is_mapped(xid)): log("Wm managing pre-existing child window %#x", xid) self._manage_client(w) # Also watch for focus change events on the root window X11Window.selectFocusChange(rxid) X11Keyboard.selectBellNotification(True)
def make_cursor(self, cursor_data): #if present, try cursor ny name: display = display_get_default() if len(cursor_data) >= 9 and cursor_types: cursor_name = bytestostr(cursor_data[8]) if cursor_name: gdk_cursor = cursor_types.get(cursor_name.upper()) if gdk_cursor is not None: cursorlog("setting new cursor by name: %s=%s", cursor_name, gdk_cursor) return new_Cursor_for_display(display, gdk_cursor) else: global missing_cursor_names if cursor_name not in missing_cursor_names: cursorlog("cursor name '%s' not found", cursor_name) missing_cursor_names.add(cursor_name) #create cursor from the pixel data: w, h, xhot, yhot, serial, pixels = cursor_data[2:8] if len(pixels) < w * h * 4: import binascii cursorlog.warn( "not enough pixels provided in cursor data: %s needed and only %s bytes found (%s)", w * h * 4, len(pixels), binascii.hexlify(pixels)[:100]) return pixbuf = get_pixbuf_from_data(pixels, True, w, h, w * 4) x = max(0, min(xhot, w - 1)) y = max(0, min(yhot, h - 1)) csize = display.get_default_cursor_size() cmaxw, cmaxh = display.get_maximal_cursor_size() if len(cursor_data) >= 11: ssize = cursor_data[9] smax = cursor_data[10] cursorlog("server cursor sizes: default=%s, max=%s", ssize, smax) cursorlog( "new cursor at %s,%s with serial=%s, dimensions: %sx%s, len(pixels)=%s, default cursor size is %s, maximum=%s", xhot, yhot, serial, w, h, len(pixels), csize, (cmaxw, cmaxh)) fw, fh = get_fixed_cursor_size() if fw > 0 and fh > 0 and (w != fw or h != fh): #OS wants a fixed cursor size! (win32 does, and GTK doesn't do this for us) if w <= fw and h <= fh: cursorlog( "pasting cursor of size %ix%i onto clear pixbuf of size %ix%i", w, h, fw, fh) cursor_pixbuf = get_pixbuf_from_data("\0" * fw * fh * 4, True, fw, fh, fw * 4) pixbuf.copy_area(0, 0, w, h, cursor_pixbuf, 0, 0) else: cursorlog("scaling cursor from %ix%i to fixed OS size %ix%i", w, h, fw, fh) cursor_pixbuf = pixbuf.scale_simple(fw, fh, INTERP_BILINEAR) xratio, yratio = float(w) / fw, float(h) / fh x, y = int(x / xratio), int(y / yratio) elif w > cmaxw or h > cmaxh or (csize > 0 and (csize < w or csize < h)): ratio = max( float(w) / cmaxw, float(h) / cmaxh, float(max(w, h)) / csize) x, y, w, h = int(x / ratio), int(y / ratio), int(w / ratio), int( h / ratio) cursorlog("downscaling cursor %s by %.2f: %sx%s", pixbuf, ratio, w, h) cursor_pixbuf = pixbuf.scale_simple(w, h, INTERP_BILINEAR) else: cursor_pixbuf = pixbuf #clamp to pixbuf size: w = cursor_pixbuf.get_width() h = cursor_pixbuf.get_height() x = max(0, min(x, w - 1)) y = max(0, min(y, h - 1)) return new_Cursor_from_pixbuf(display, cursor_pixbuf, x, y)