def change_workspace(name): print(f"Changing to {name}", flush=True) display = Xlib.display.Display() screen = display.screen() root = screen.root w, h = screen.width_in_pixels, screen.height_in_pixels try: hue = int(name)/10+1/3 except: hue = mkrand(name).random() if name not in colors: colors[name] = gen_colors(hue) proc = subprocess.Popen(["xrdb", "-merge"], stdin=subprocess.PIPE) proc.communicate(input=colors[name].encode()) proc.wait() i3.command("reload") if (name, w, h) not in backgrounds: backgrounds[name, w, h] = root.create_pixmap(w, h, screen.root_depth) gen_bg(backgrounds[name, w, h], hue, name) id = backgrounds[name, w, h].id root.change_property(display.get_atom("_XROOTPMAP_ID"), Xatom.PIXMAP, 32, [id]) root.change_property(display.get_atom("ESETROOT_PMAP_ID"), Xatom.PIXMAP, 32, [id]) root.change_attributes(background_pixmap=id) root.clear_area(0, 0, w, h) display.sync()
def set_wm_state(window, action, data): # Function to set window states via Xlib # Thanks parkouss for help with this (https://github.com/parkouss/pyewmh/blob/master/ewmh/ewmh.py) if action == "_NET_WM_STATE": data[1] = display.get_atom( data[1], 1 ) # Get the int for associated action, as X wants this in data array, not a string event = protocol.event.ClientMessage(window=window, client_type=display.get_atom(action), data=(32, data)) screen.root.send_event(event, event_mask=(X.SubstructureRedirectMask))
def pager_auto_detect(display, screen, root): '''Auto-detects pager to use.''' pager = None grid = root.get_full_property(display.get_atom('_NET_DESKTOP_LAYOUT'), 0) size = root.get_full_property(display.get_atom("_NET_DESKTOP_GEOMETRY"), 0) if (grid != None and grid.value[2] > 1 and grid.value[1] > 1): return VirtualDesktopPager(display, screen, root) elif (hasattr(size, 'value') and (size.value[1]>screen.height_in_pixels or size.value[0]>screen.width_in_pixels)): return ViewportPager(display, screen, root) else: # defaults to VirtualDesktop return VirtualDesktopPager(display, screen, root)
def pager_auto_detect(display, screen, root): '''Auto-detects pager to use.''' pager = None grid = root.get_full_property(display.get_atom('_NET_DESKTOP_LAYOUT'), 0) size = root.get_full_property(display.get_atom("_NET_DESKTOP_GEOMETRY"), 0) if (grid != None and grid.value[2] > 1 and grid.value[1] > 1): return VirtualDesktopPager(display, screen, root) elif (hasattr(size, 'value') and (size.value[1] > screen.height_in_pixels or size.value[0] > screen.width_in_pixels)): return ViewportPager(display, screen, root) else: # defaults to VirtualDesktop return VirtualDesktopPager(display, screen, root)
def get_window_pid(window: Window) -> str: atom = display.get_atom("_NET_WM_PID") pid_property = window.get_full_property(atom, X.AnyPropertyType) if pid_property: pid = pid_property.value[-1] return pid else: # TODO: Needed? raise Exception("pid_property was None")
def change_workspace(name): display = Xlib.display.Display() screen = display.screen() root = screen.root w, h = screen.width_in_pixels, screen.height_in_pixels if (name, w, h) not in background_cache: background_cache[name, w, h] = gen_bg( root.create_pixmap(w, h, screen.root_depth), name) id = background_cache[name, w, h].id root.change_property(display.get_atom("_XROOTPMAP_ID"), Xatom.PIXMAP, 32, [id]) root.change_property(display.get_atom("ESETROOT_PMAP_ID"), Xatom.PIXMAP, 32, [id]) root.change_attributes(background_pixmap=id) root.clear_area() display.sync()
def _get_current_window_id() -> Optional[int]: atom = display.get_atom("_NET_ACTIVE_WINDOW") window_prop = screen.root.get_full_property(atom, X.AnyPropertyType) if window_prop is None: logger.warning("window_prop was None") return None # window_prop may contain more than one value, but it seems that it's always the first we want. # The second has in my attempts always been 0 or rubbish. window_id = window_prop.value[0] return window_id if window_id != 0 else None
def __update_focus_cb(self, command, sync=False): # Check FocusIn/FocusOut events if self.focus: focus_in = None focus_out = None for i in range(display.pending_events()): event = display.next_event() if event.type == Xlib.X.FocusIn: focus_in = event.window elif event.type == Xlib.X.FocusOut: focus_out = event.window if focus_in == self.focus: if focus_out != self.focus: # This is ugly workaround, but necessary to avoid a # problem that the language bar doesn't appear after # moving to other workspace in Ubuntu Unity desktop. # If old version of ibus.el which doesn't define # `ibus-redo-focus-in-cb' is running on Emacs, the # following message will just be ignored and take no effect. print_command('ibus_redo_focus_in_cb') if sync: print_command(command, focus_in.id) return True # Main part focus = self.display.get_input_focus().focus try: # get_input_focus() may return an integer 0 that query_tree() # causes AttributeError when X session is going to logout. tree = focus.query_tree() # In Ubuntu's Unity desktop, get_input_focus() often returns root # window incorrectly after changing workspace. if focus != tree.root: if not (focus.get_wm_class() or focus.get_wm_name()): focus = tree.parent if focus != self.focus or sync: print_command(command, focus.id) focus.change_attributes(event_mask=Xlib.X.FocusChangeMask) self.focus = focus return True except AttributeError: if sync: print_command(command, 0) return True # Fallback atom = display.get_atom("_NET_ACTIVE_WINDOW", True) focus_id = tree.root.get_property(atom, Xlib.Xatom.WINDOW, 0, 1).value[0] focus = display.create_resource_object("window", focus_id) if focus != self.focus or sync: print_command(command, focus_id) focus.change_attributes(event_mask=Xlib.X.FocusChangeMask) self.focus = focus return True
def _guess_active_window(): display = Xlib.display.Display() wm = ewmh.EWMH(display) active_win = wm.getActiveWindow() if not active_win: debug('no active window from ewmh') return None, None window_names = [] window_names.append(wm.getWmName(active_win)) wm_name = active_win.get_full_property(display.get_atom('WM_NAME'), X.AnyPropertyType) debug('WM_NAME original %s' % wm_name.value) wm_name = _from_compound_text(wm_name.value) debug('WM_NAME decoded %s' % wm_name) if wm_name not in window_names: window_names.append(wm_name) gdk_display = Gdk.Display.get_default() gdk_window = GdkX11.X11Window.foreign_new_for_display(gdk_display, active_win.id) gdk_frame_rect = gdk_window.get_frame_extents() gdk_frame_rect = (gdk_frame_rect.x, gdk_frame_rect.y, gdk_frame_rect.width, gdk_frame_rect.height) gdk_geom_rect = gdk_window.get_geometry() debug('active window %s' % (window_names,)) debug('active window id %s' % active_win.id) match = [] for win in _atspi_windows(): atspi_name = str(win) matched_names = [name for name in window_names if atspi_name.endswith('| %s]' % name)] debug('win with name %s, matched %s' % (atspi_name, matched_names)) if matched_names and _geometry_match(win, gdk_frame_rect, gdk_geom_rect): match.append(win) if not match: debug('no atspi window matching "%s"' % window_names) return None, None if len(match) > 1: debug('too many atspi windows matching "%s"' % window_names) return None, None return match[0], gdk_window
def atom_s2i(string): i = display.get_atom(string, only_if_exists=True) if i == Xlib.X.NONE: raise ValueError('No Atom interned with that name.') else: return i
def atom_s2i(string): i = display.get_atom(string, only_if_exists=False) if i == Xlib.X.NONE: raise ValueError('No Atom interned with that name.') else: return i
def _guess_active_window(): display = Xlib.display.Display() root = display.screen().root active_win = None active_win_atom = root.get_full_property( display.get_atom('_NET_ACTIVE_WINDOW'), X.AnyPropertyType) if active_win_atom and active_win_atom.value: active_win = display.create_resource_object('window', active_win_atom.value[0]) if not active_win: debug('no active window found by properties') return None, None window_names = [] atom = active_win.get_full_property( display.get_atom('_NET_WM_VISIBLE_NAME'), X.AnyPropertyType) if atom: window_names.append(atom.value) wm_name = active_win.get_full_property(display.get_atom('WM_NAME'), X.AnyPropertyType) debug('WM_NAME original %s' % wm_name.value) wm_name = _from_compound_text(wm_name.value) debug('WM_NAME decoded %s' % wm_name) if wm_name not in window_names: window_names.append(wm_name) gdk_display = Gdk.Display.get_default() gdk_window = GdkX11.X11Window.foreign_new_for_display( gdk_display, active_win.id) gdk_frame_rect = gdk_window.get_frame_extents() gdk_frame_rect = (gdk_frame_rect.x, gdk_frame_rect.y, gdk_frame_rect.width, gdk_frame_rect.height) gdk_geom_rect = gdk_window.get_geometry() debug('active window %s' % (window_names, )) debug('active window id %s' % active_win.id) match = [] for win in _atspi_windows(): atspi_name = str(win) matched_names = [ name for name in window_names if atspi_name.endswith('| %s]' % name) ] debug('win with name %s, matched %s' % (atspi_name, matched_names)) if matched_names and _geometry_match(win, gdk_frame_rect, gdk_geom_rect): match.append(win) if not match: debug('no atspi window matching "%s"' % window_names) return None, None if len(match) > 1: debug('too many atspi windows matching "%s"' % window_names) return None, None return match[0], gdk_window