def _set_wm_state(self, *states): # Set property net_wm_state = xlib.XInternAtom(self._x_display, '_NET_WM_STATE', False) atoms = [] for state in states: atoms.append(xlib.XInternAtom(self._x_display, state, False)) atom_type = xlib.XInternAtom(self._x_display, 'ATOM', False) if len(atoms): atoms_ar = (xlib.Atom * len(atoms))(*atoms) xlib.XChangeProperty(self._x_display, self._window, net_wm_state, atom_type, 32, xlib.PropModePrepend, cast(pointer(atoms_ar), POINTER(c_ubyte)), len(atoms)) else: xlib.XDeleteProperty(self._x_display, self._window, net_wm_state) # Nudge the WM e = xlib.XEvent() e.xclient.type = xlib.ClientMessage e.xclient.message_type = net_wm_state e.xclient.display = cast(self._x_display, POINTER(xlib.Display)) e.xclient.window = self._window e.xclient.format = 32 e.xclient.data.l[0] = xlib.PropModePrepend for i, atom in enumerate(atoms): e.xclient.data.l[i + 1] = atom xlib.XSendEvent(self._x_display, self._get_root(), False, xlib.SubstructureRedirectMask, byref(e))
def _set_atoms_property(self, name, values, mode=xlib.PropModeReplace): name_atom = xlib.XInternAtom(self._x_display, name, False) atoms = [] for value in values: atoms.append(xlib.XInternAtom(self._x_display, value, False)) atom_type = xlib.XInternAtom(self._x_display, 'ATOM', False) if len(atoms): atoms_ar = (xlib.Atom * len(atoms))(*atoms) xlib.XChangeProperty(self._x_display, self._window, name_atom, atom_type, 32, mode, cast(pointer(atoms_ar), POINTER(c_ubyte)), len(atoms)) else: xlib.XDeleteProperty(self._x_display, self._window, net_wm_state)
def set_icon(self, *images): # Careful! XChangeProperty takes an array of long when data type # is 32-bit (but long can be 64 bit!), so pad high bytes of format if # necessary. import sys format = { ('little', 4): 'BGRA', ('little', 8): 'BGRAAAAA', ('big', 4): 'ARGB', ('big', 8): 'AAAAARGB' }[(sys.byteorder, sizeof(c_ulong))] data = '' for image in images: image = image.image_data image.format = format image.pitch = -(image.width * len(image.format)) s = c_buffer(sizeof(c_ulong) * 2) memmove( s, cast((c_ulong * 2)(image.width, image.height), POINTER(c_ubyte)), len(s)) data += s.raw + image.data buffer = (c_ubyte * len(data))() memmove(buffer, data, len(data)) atom = xlib.XInternAtom(self._x_display, '_NET_WM_ICON', False) XA_CARDINAL = 6 # Xatom.h:14 xlib.XChangeProperty(self._x_display, self._window, atom, XA_CARDINAL, 32, xlib.PropModeReplace, buffer, len(data) / sizeof(c_ulong))
def _set_text_property(self, name, value, allow_utf8=True): atom = xlib.XInternAtom(self._x_display, name, False) if not atom: raise XlibException('Undefined atom "%s"' % name) assert type(value) in (str, unicode) property = xlib.XTextProperty() if _have_utf8 and allow_utf8: buf = create_string_buffer(value.encode('utf8')) result = xlib.Xutf8TextListToTextProperty( self._x_display, cast(pointer(buf), c_char_p), 1, xlib.XStdICCTextStyle, byref(property)) if result < 0: raise XlibException('Could not create UTF8 text property') else: buf = create_string_buffer(value.encode('ascii', 'ignore')) result = xlib.XStringListToTextProperty( cast(pointer(buf), c_char_p), 1, byref(property)) if result < 0: raise XlibException('Could not create text property') xlib.XSetTextProperty(self._x_display, self._window, byref(property), atom)
def _create(self): # Unmap existing window if necessary while we fiddle with it. if self._window and self._mapped: self._unmap() self.context.window = self self._x_display = self.config._display self._x_screen_id = self.screen._x_screen_id self._glx_context = self.context._context self._glx_1_3 = self.display.info.have_version(1, 3) self._have_SGI_video_sync = \ self.display.info.have_extension('GLX_SGI_video_sync') self._have_SGI_swap_control = \ self.display.info.have_extension('GLX_SGI_swap_control') self._have_MESA_swap_control = \ self.display.info.have_extension('GLX_MESA_swap_control') # In order of preference: # 1. GLX_MESA_swap_control (more likely to work where video_sync will # not) # 2. GLX_SGI_video_sync (does not work on Intel 945GM, but that has # MESA) # 3. GLX_SGI_swap_control (cannot be disabled once enabled). self._use_video_sync = (self._have_SGI_video_sync and not self._have_MESA_swap_control) # Create X window if not already existing. if not self._window: root = xlib.XRootWindow(self._x_display, self._x_screen_id) visual_info = self.config.get_visual_info() visual = visual_info.visual visual_id = xlib.XVisualIDFromVisual(visual) default_visual = xlib.XDefaultVisual(self._x_display, self._x_screen_id) default_visual_id = xlib.XVisualIDFromVisual(default_visual) window_attributes = xlib.XSetWindowAttributes() if visual_id != default_visual_id: window_attributes.colormap = xlib.XCreateColormap( self._x_display, root, visual, xlib.AllocNone) else: window_attributes.colormap = xlib.XDefaultColormap( self._x_display, self._x_screen_id) self._window = xlib.XCreateWindow(self._x_display, root, 0, 0, self._width, self._height, 0, visual_info.depth, xlib.InputOutput, visual, xlib.CWColormap, byref(window_attributes)) # Setting null background pixmap disables drawing the background, # preventing flicker while resizing (in theory). xlib.XSetWindowBackgroundPixmap(self._x_display, self._window, 0) # Enable WM_DELETE_WINDOW message wm_delete_window = xlib.XInternAtom(self._x_display, 'WM_DELETE_WINDOW', False) wm_delete_window = c_ulong(wm_delete_window) xlib.XSetWMProtocols(self._x_display, self._window, byref(wm_delete_window), 1) # Set window attributes attributes = xlib.XSetWindowAttributes() attributes_mask = 0 # Bypass the window manager in fullscreen. This is the only reliable # technique (over _NET_WM_STATE_FULLSCREEN, Motif, KDE and Gnome # hints) that is pretty much guaranteed to work. Unfortunately # we run into window activation and focus problems that require # attention. Search for "override_redirect" for all occurences. attributes.override_redirect = self._fullscreen attributes_mask |= xlib.CWOverrideRedirect if self._fullscreen: xlib.XMoveResizeWindow(self._x_display, self._window, self.screen.x, self.screen.y, self.screen.width, self.screen.height) else: xlib.XResizeWindow(self._x_display, self._window, self._width, self._height) xlib.XChangeWindowAttributes(self._x_display, self._window, attributes_mask, byref(attributes)) # Set style styles = { self.WINDOW_STYLE_DEFAULT: '_NET_WM_WINDOW_TYPE_NORMAL', self.WINDOW_STYLE_DIALOG: '_NET_WM_WINDOW_TYPE_DIALOG', self.WINDOW_STYLE_TOOL: '_NET_WM_WINDOW_TYPE_UTILITY', } if self._style in styles: self._set_atoms_property('_NET_WM_WINDOW_TYPE', (styles[self._style], )) elif self._style == self.WINDOW_STYLE_BORDERLESS: MWM_HINTS_DECORATIONS = 1 << 1 PROP_MWM_HINTS_ELEMENTS = 5 mwmhints = mwmhints_t() mwmhints.flags = MWM_HINTS_DECORATIONS mwmhints.decorations = 0 name = xlib.XInternAtom(self._x_display, '_MOTIF_WM_HINTS', False) xlib.XChangeProperty(self._x_display, self._window, name, name, 32, xlib.PropModeReplace, cast(pointer(mwmhints), POINTER(c_ubyte)), PROP_MWM_HINTS_ELEMENTS) # Set resizeable if not self._resizable: self.set_minimum_size(self._width, self._height) self.set_maximum_size(self._width, self._height) # Set caption self.set_caption(self._caption) self.switch_to() if self._visible: self.set_visible(True) # Create input context. A good but very outdated reference for this # is http://www.sbin.org/doc/Xlib/chapt_11.html if _have_utf8: self._x_im = xlib.XOpenIM(self._x_display, None, None, None) # TODO select best input style. self._x_ic = xlib.XCreateIC( self._x_im, 'inputStyle', xlib.XIMPreeditNothing | xlib.XIMStatusNothing, None) xlib.XSetICFocus(self._x_ic)
def _event_clientmessage(self, ev): wm_delete_window = xlib.XInternAtom(ev.xclient.display, 'WM_DELETE_WINDOW', False) if ev.xclient.data.l[0] == wm_delete_window: self.dispatch_event('on_close')