def __init__(self, name, text="", width=0, interval=None, function=None, enabled=True): self.name = name self.text = text self.width = width self.interval = interval self.function = function self.enabled = enabled if interval is not None and function is not None: self.rt_event = RepeatedTimer(interval, function) else: self.rt_event = None
class DeskbarItem(object): def __init__(self, name, text="", width=0, interval=None, function=None, enabled=True): self.name = name self.text = text self.width = width self.interval = interval self.function = function self.enabled = enabled if interval is not None and function is not None: self.rt_event = RepeatedTimer(interval, function) else: self.rt_event = None def set_rt_event(self, interval, function): self.interval = interval self.function = function self.rt_event = RepeatedTimer(interval, function) def unset_rt_event(self): if self.rt_event is not None: self.rt_event.stop() self.rt_event = None self.interval = None self.function = None def start(self): if self.rt_event is not None: self.rt_event.start() def stop(self): if self.rt_event is not None: self.rt_event.stop()
def __init__(self, prefs, session_info): self.prefs = prefs self.session_info = session_info self.ewmh = EWMH() self.dpy = display.Display() self.screen = self.dpy.screen() self.dpy_root = self.screen.root self.colormap = self.screen.default_colormap self.pixel_palette = PixelPalette(self.colormap) self.display_dimensions = self.get_display_geometry() self.window_resize_options = [ "center", "maximize", "left", "right", "top", "bottom" ] self.managed_windows = [] self.exposed_windows = [] self.last_raised_window = None self.active_window_title = self.session_info.session_name self.window_order = -1 self.key_alias = {} self.keys_down = set() self.start = None self.attr = None self.wm_window_type = self.dpy.intern_atom('_NET_WM_WINDOW_TYPE') self.wm_state = self.dpy.intern_atom('_NET_WM_STATE') self.wm_window_types = { "dock": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_DOCK'), "normal": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_NORMAL'), "dialog": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_DIALOG'), "utility": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_UTILITY'), "toolbar": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_TOOLBAR'), "menu": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_MENU'), "splash": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_SPLASH') } self.wm_window_status = { "active": self.dpy.intern_atom('_NET_ACTIVE_WINDOW'), "desktop": self.dpy.intern_atom('_NET_WM_DESKTOP'), "above": self.dpy.intern_atom('_NET_WM_STATE_ABOVE'), "skip_taskbar": self.dpy.intern_atom('_NET_WM_STATE_SKIP_TASKBAR'), "maximize_vertical": self.dpy.intern_atom('_NET_WM_STATE_MAXIMIZED_VERT'), "maximize_horizontal": self.dpy.intern_atom('_NET_WM_STATE_MAXIMIZED_HORIZ') } self.wm_window_cyclical = [ self.wm_window_types["normal"], self.wm_window_types["dialog"], self.wm_window_types["utility"], self.wm_window_types["toolbar"] ] self.deskbar = None self.display_corners = None self.update_active_window_title_rt = RepeatedTimer( interval=1, function=self.update_active_window_title) self.update_active_window_title_rt.stop() self.set_cursor(self.dpy_root) XK.load_keysym_group('xf86') self.set_key_aliases()
class WindowManager(object): def __init__(self, prefs, session_info): self.prefs = prefs self.session_info = session_info self.ewmh = EWMH() self.dpy = display.Display() self.screen = self.dpy.screen() self.dpy_root = self.screen.root self.colormap = self.screen.default_colormap self.pixel_palette = PixelPalette(self.colormap) self.display_dimensions = self.get_display_geometry() self.window_resize_options = [ "center", "maximize", "left", "right", "top", "bottom" ] self.managed_windows = [] self.exposed_windows = [] self.last_raised_window = None self.active_window_title = self.session_info.session_name self.window_order = -1 self.key_alias = {} self.keys_down = set() self.start = None self.attr = None self.wm_window_type = self.dpy.intern_atom('_NET_WM_WINDOW_TYPE') self.wm_state = self.dpy.intern_atom('_NET_WM_STATE') self.wm_window_types = { "dock": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_DOCK'), "normal": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_NORMAL'), "dialog": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_DIALOG'), "utility": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_UTILITY'), "toolbar": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_TOOLBAR'), "menu": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_MENU'), "splash": self.dpy.intern_atom('_NET_WM_WINDOW_TYPE_SPLASH') } self.wm_window_status = { "active": self.dpy.intern_atom('_NET_ACTIVE_WINDOW'), "desktop": self.dpy.intern_atom('_NET_WM_DESKTOP'), "above": self.dpy.intern_atom('_NET_WM_STATE_ABOVE'), "skip_taskbar": self.dpy.intern_atom('_NET_WM_STATE_SKIP_TASKBAR'), "maximize_vertical": self.dpy.intern_atom('_NET_WM_STATE_MAXIMIZED_VERT'), "maximize_horizontal": self.dpy.intern_atom('_NET_WM_STATE_MAXIMIZED_HORIZ') } self.wm_window_cyclical = [ self.wm_window_types["normal"], self.wm_window_types["dialog"], self.wm_window_types["utility"], self.wm_window_types["toolbar"] ] self.deskbar = None self.display_corners = None self.update_active_window_title_rt = RepeatedTimer( interval=1, function=self.update_active_window_title) self.update_active_window_title_rt.stop() self.set_cursor(self.dpy_root) XK.load_keysym_group('xf86') self.set_key_aliases() ### QUERY METHODS def get_display_geometry(self): return self.dpy_root.get_geometry() def window_list(self): return self.dpy_root.query_tree().children def is_managed_window(self, window): return window in self.managed_windows def is_alive_window(self, window): windows = self.dpy_root.query_tree().children return window in windows def is_dock(self, window): result = None try: result = window.get_full_property(self.wm_window_type, Xatom.ATOM) except error.BadWindow or RuntimeError: print("Failed to detect if window is dock") pass if result is not None and result.value[0] == self.wm_window_types[ "dock"]: return True return False def is_popup_window(self, window): result = None try: result = window.get_full_property(self.wm_window_type, Xatom.ATOM) except error.BadWindow or RuntimeError: print("Failed to detect if window is dock") pass if result is not None and ( result.value[0] == self.wm_window_types["menu"] or result.value[0] == self.wm_window_types["splash"]): return True return False def is_cyclical_window(self, window): result = None try: result = window.get_full_property(self.wm_window_type, Xatom.ATOM) except error.BadWindow or RuntimeError: print("Failed to detect if window is dock") pass if result is not None and result.value[0] in self.wm_window_cyclical: return True return False def is_active(self, atom): if atom == self.wm_window_status["active"]: return True return False def get_active_window(self): window = None try: window = self.dpy_root.get_full_property( self.wm_window_status["active"], Xatom.ATOM) except: print("Failed to get active window") pass return window def get_window_class(self, window): try: cmd, cls = window.get_wm_class() except: return '' if cls is not None: return cls else: return '' def get_window_geometry(self, window): try: return window.get_geometry() except: return None def get_maximum_available_geometry(self): window_width = self.display_dimensions.width window_height = self.display_dimensions.height if self.deskbar is not None: window_height -= self.deskbar.real_height return window_width, window_height, self.deskbar is not None def get_window_attributes(self, window): try: return window.get_attributes() except: return None def get_window_state(self, window): return self.ewmh.getWmState(window, str=True) def get_window_shortname(self, window): return '0x{:x} [{}]'.format(window.id, self.get_window_class(window)) def get_window_title(self, window): result = None try: result = window.get_wm_name() except: pass if result is None: return self.session_info.session_name return result def set_active_window_title(self, window=None, custom_title=None): window_title = None if window is not None: window_title = self.get_window_title(window) if window_title is None: self.active_window_title = self.session_info.session_name elif custom_title is not None: window_title = custom_title else: self.active_window_title = window_title if self.prefs.deskbar["enabled"] == 1: self.deskbar.set_active_window_title(self.active_window_title) def update_active_window_title(self): if self.last_raised_window is not None: self.set_active_window_title(self.last_raised_window) def update_window_count(self): if self.deskbar is not None: self.deskbar.set_window_count(len(self.managed_windows)) ### WINDOW CONTROLS def manage_window(self, window): attributes = self.get_window_attributes(window) if attributes is None: return if attributes.override_redirect: return if self.is_managed_window(window): return if self.prefs.dev["debug"] == 1: print("Found window: %s", self.get_window_shortname(window)) self.managed_windows.append(window) self.exposed_windows.append(window) self.window_order = len(self.managed_windows) - 1 self.update_window_count() window.map() mask = X.EnterWindowMask | X.LeaveWindowMask window.change_attributes(event_mask=mask) self.decorate_window(window) def unmanage_window(self, window): if self.is_managed_window(window): if self.prefs.dev["debug"] == 1: print("Unmanaging window: %s", self.get_window_shortname(window)) if window in self.managed_windows: self.managed_windows.remove(window) self.window_order = len(self.managed_windows) - 1 self.update_window_count() if window in self.exposed_windows: self.exposed_windows.remove(window) def destroy_window(self, window): if self.is_dock(window) is False: if self.prefs.dev["debug"] == 1: print("Destroy window: %s", self.get_window_shortname(window)) if self.is_managed_window(window): window.destroy() self.unmanage_window(window) def raise_window(self, window): if not self.is_dock(window): if not self.is_managed_window(window): return window.raise_window() self.last_raised_window = window self.set_active_window_title(window) if self.deskbar is not None: self.deskbar.update() def focus_window(self, window): if self.is_dock(window) or not self.is_managed_window( window) or not self.is_alive_window(window): return window.set_input_focus(X.RevertToParent, 0) self.set_focus_window_border(window) def cycle_windows(self): if len(self.managed_windows) > 0: self.window_order += 1 if self.window_order > len(self.managed_windows) - 1: self.window_order = 0 window = self.managed_windows[self.window_order] if self.is_cyclical_window(window) is False: if self.window_order >= len(self.managed_windows) - 1: self.window_order = 0 else: self.window_order += 1 window = self.managed_windows[self.window_order] self.focus_window(window) self.raise_window(window) else: self.window_order = -1 ### WINDOW DECORATION def is_window_maximized(self, window): states = self.get_window_state(window) print(states) def move_window(self, xdiff, ydiff): window_dimensions = self.get_window_geometry(self.start.child) if self.deskbar is not None and ydiff < 0 and window_dimensions.y <= self.deskbar.real_height: y = self.deskbar.real_height else: y = self.attr.y + (self.start.detail == 1 and ydiff or 0) self.start.child.configure( x=self.attr.x + (self.start.detail == 1 and xdiff or 0), y=y, width=max( 1, self.attr.width + (self.start.detail == 3 and xdiff or 0)), height=max( 1, self.attr.height + (self.start.detail == 3 and ydiff or 0))) def resize_window(self, window, position): if self.is_dock(window) is False: if self.prefs.dev["debug"] == 1: print("Triggered window resize") if position in self.window_resize_options: window_x, window_y, window_width, window_height = None, None, None, None if position == "center": window_dimensions = self.get_window_geometry(window) window_width, window_height = window_dimensions.width, window_dimensions.height window_x = (self.display_dimensions.width - window_width) // 2 window_y = (self.display_dimensions.height - window_height) // 2 elif position == "maximize": window_width, window_height, has_deskbar = self.get_maximum_available_geometry( ) window_x = -self.prefs.appearance["window_border_width"] window_y = -self.prefs.appearance[ "window_border_width"] if not has_deskbar else ( -self.prefs.appearance["window_border_width"] + self.deskbar.real_height) elif position == "left" or position == "right": window_width = self.display_dimensions.width // 2 window_height = self.display_dimensions.height + ( 0 if self.deskbar is None else self.deskbar.height) if position == "left": window_x = -self.prefs.appearance["window_border_width"] elif position == "right": window_x = window_width - self.prefs.appearance[ "window_border_width"] window_y = -self.prefs.appearance[ "window_border_width"] if self.deskbar is None else ( -self.prefs.appearance["window_border_width"] + self.deskbar.height + self.deskbar.border_width) elif position == "top" or position == "bottom": window_width = self.display_dimensions.width window_height = (self.display_dimensions.height + (0 if self.deskbar is None else self.deskbar.height)) // 2 if position == "top": window_y = -self.prefs.appearance["window_border_width"] elif position == "bottom": window_y = window_height + self.prefs.appearance[ "window_border_width"] window_x = -self.prefs.appearance["window_border_width"] if position == "maximize": self.ewmh.setWmState(window, 1, "_NET_WM_STATE_MAXIMIZED_VERT") self.ewmh.setWmState(window, 1, "_NET_WM_STATE_MAXIMIZED_HORIZ") else: self.ewmh.setWmState(window, 0, "_NET_WM_STATE_MAXIMIZED_VERT") self.ewmh.setWmState(window, 0, "_NET_WM_STATE_MAXIMIZED_HORIZ") window.configure(x=window_x, y=window_y, width=window_width, height=window_height) else: print("Invalid window position: " + position) def decorate_window(self, window): self.set_cursor(window) if self.is_dock(window) is False: window_dimensions = self.get_window_geometry(window) window_width, window_height = window_dimensions.width, window_dimensions.height window_x = 5 window_y = 25 if self.prefs.placement["auto_window_placement"] == 1: # Move new window out of the way of the deskbar if self.prefs.placement["auto_window_fit"] == 1: # Resize window to fit the screen if window_dimensions.width + window_x >= self.display_dimensions.width: window_width -= window_x * 2 if window_dimensions.height + window_y >= self.display_dimensions.height: window_height -= window_y * 2 if self.prefs.placement["center_window_placement"] == 1: window_x = (self.display_dimensions.width - window_width) // 2 window_y = (self.display_dimensions.height - window_height) // 2 window.configure(x=window_x, y=window_y, width=window_width, height=window_height) self.set_unfocus_window_border(window) def set_unfocus_window_border(self, window): if not self.is_dock(window): border_color = self.pixel_palette.get_named_pixel("lightgray") if self.prefs.appearance[ "inactive_window_border_color"] in self.pixel_palette.hex_map.keys( ): border_color = self.pixel_palette.get_named_pixel( self.prefs.appearance["inactive_window_border_color"]) elif self.pixel_palette.is_color_hex( self.prefs.appearance["inactive_window_border_color"] ) is True: border_color = self.pixel_palette.get_hex_pixel( self.prefs.appearance["inactive_window_border_color"]) window.configure( border_width=self.prefs.appearance["window_border_width"]) window.change_attributes(None, border_pixel=border_color) def set_focus_window_border(self, window): if not self.is_dock(window): border_color = self.pixel_palette.get_named_pixel("sienna") if self.prefs.appearance[ "active_window_border_color"] in self.pixel_palette.hex_map.keys( ): border_color = self.pixel_palette.get_named_pixel( self.prefs.appearance["active_window_border_color"]) elif self.pixel_palette.is_color_hex( self.prefs.appearance["active_window_border_color"] ) is True: border_color = self.pixel_palette.get_hex_pixel( self.prefs.appearance["active_window_border_color"]) window.change_attributes(None, border_pixel=border_color) def set_cursor(self, window): font = self.dpy.open_font('cursor') cursor = font.create_glyph_cursor(font, Xcursorfont.left_ptr, Xcursorfont.left_ptr + 1, (65535, 65535, 65535), (0, 0, 0)) window.change_attributes(cursor=cursor) def set_background_color(self): background_color = self.pixel_palette.hex_map["slategray"] if self.pixel_palette.is_color_hex( self.prefs.appearance["background_color"]) is True: background_color = self.prefs.appearance["background_color"] elif self.prefs.appearance[ "background_color"] in self.pixel_palette.hex_map.keys(): background_color = self.pixel_palette.hex_map[ self.prefs.appearance["background_color"]] os.system('xsetroot -solid "' + background_color + '"') # DEBUG def print_event_type(self, ev): if ev.type in recognised_events.keys(): print(recognised_events[ev.type] + " event") # SPECIAL def start_terminal(self): run_command('x-terminal-emulator') # EVENT HANDLING def keycode_to_string(self, detail): return XK.keysym_to_string(self.dpy.keycode_to_keysym(detail, 0)) # From: https://stackoverflow.com/a/43880743 def keycode_to_key(self, keycode, state): i = 0 if state & X.ShiftMask: i += 1 if state & X.Mod1Mask: i += 2 return self.dpy.keycode_to_keysym(keycode, i) # From: https://stackoverflow.com/a/43880743 def key_to_string(self, key): keys = [] for name in dir(XK): if name.startswith("XK_") and getattr(XK, name) == key: keys.append( name.lstrip("XK_").replace("_L", "").replace("_R", "")) if keys: return " or ".join(keys) return "[%d]" % key # From: https://stackoverflow.com/a/43880743 def keycode_to_string_mod(self, keycode, state): return self.key_to_string(self.keycode_to_key(keycode, state)) def set_key_aliases(self): keystrings = [ "x", "q", "minus", "equal", "bracketleft", "bracketright", "backslash", "slash", "F1", "Tab", "Escape", "space", "Return", "BackSpace" ] for keystring in keystrings: self.key_alias[keystring] = self.dpy.keysym_to_keycode( XK.string_to_keysym(keystring)) def launcher_bindings(self, ev): if ev.detail == self.key_alias["Escape"]: self.deskbar.toggle_launcher(state=False) elif ev.detail == self.key_alias["BackSpace"] and len( self.deskbar.command_string) > 0: self.deskbar.command_string = self.deskbar.command_string[:-1] self.deskbar.update() elif ev.detail == self.key_alias["Return"]: run_command(self.deskbar.command_string) self.deskbar.toggle_launcher(state=False) else: key_string = self.keycode_to_string(ev.detail) if key_string: self.deskbar.command_string += key_string self.deskbar.update() def action_bindings(self, ev): if ev.detail in self.key_alias.values(): if ev.child != X.NONE: if ev.detail == self.key_alias["q"]: self.destroy_window(ev.child) elif ev.detail == self.key_alias["minus"]: self.resize_window(ev.child, "center") elif ev.detail == self.key_alias["equal"]: self.resize_window(ev.child, "maximize") elif ev.detail == self.key_alias["bracketleft"]: self.resize_window(ev.child, "left") elif ev.detail == self.key_alias["bracketright"]: self.resize_window(ev.child, "right") elif ev.detail == self.key_alias["backslash"]: self.resize_window(ev.child, "top") elif ev.detail == self.key_alias["slash"]: self.resize_window(ev.child, "bottom") elif ev.detail == self.key_alias["F1"]: self.focus_window(ev.window) self.raise_window(ev.window) if ev.detail == self.key_alias["x"]: self.start_terminal() elif ev.detail == self.key_alias["Tab"]: self.cycle_windows() elif ev.detail == self.key_alias["space"]: if self.deskbar is not None: self.deskbar.toggle_launcher(state=True) self.deskbar.command_string = '' self.deskbar.update() self.launcher_bindings(ev) else: self.start_terminal() elif ev.detail == self.key_alias["Escape"]: self.end_session() def keypress_handler(self, ev): key_string = self.keycode_to_string_mod(ev.detail, ev.state) if key_string: try: # ev.state == 24 for Alt # ev.state == 25 for Alt + Shift self.keys_down.add(key_string) print("Pressed: " + key_string + " - " + str(self.keys_down)) except: print("Unable to add pressed key") def keyrelease_handler(self, ev): key_string = self.keycode_to_string_mod(ev.detail, ev.state) if key_string: print(ev.state) try: self.keys_down.remove(key_string) print("Released: " + key_string + " - " + str(self.keys_down)) except: print("Unable to remove released key") def event_handler(self): while 1: ev = self.dpy.next_event() if self.prefs.dev["debug"] == 1: self.print_event_type(ev) if ev.type in [X.EnterNotify, X.LeaveNotify, X.MapNotify]: self.set_active_window_title(ev.window) if ev.type == X.KeyPress: self.keypress_handler(ev) if self.deskbar is not None and self.deskbar.launcher_is_running( ) is True: self.launcher_bindings(ev) else: self.action_bindings(ev) elif ev.type == X.KeyRelease: self.keyrelease_handler(ev) elif ev.type == X.MapNotify: if self.is_cyclical_window(ev.window): try: self.manage_window(ev.window) self.focus_window(ev.window) self.raise_window(ev.window) except AttributeError: print("Unable to handle new window") pass elif ev.type == X.DestroyNotify: try: self.destroy_window(ev.window) except AttributeError: print("Unable to unhandle new window") pass elif ev.type == X.EnterNotify: self.focus_window(ev.window) if self.prefs.placement["auto_window_raise"] == 1: self.raise_window(ev.window) elif ev.type == X.LeaveNotify: self.set_unfocus_window_border(ev.window) elif ev.type == X.ButtonPress and ev.child != X.NONE: if not self.is_dock(ev.child): self.raise_window(ev.child) self.set_focus_window_border(ev.child) self.attr = ev.child.get_geometry() self.start = ev elif self.deskbar is not None and ev.child == self.deskbar.deskbar: if ev.detail == 1: self.cycle_windows() elif ev.detail == 3: self.deskbar.toggle_window_count() self.deskbar.update() elif ev.type == X.MotionNotify and self.start: xdiff = ev.root_x - self.start.root_x ydiff = ev.root_y - self.start.root_y self.move_window(xdiff, ydiff) elif ev.type == X.ButtonRelease: self.start = None self.attr = None if ev.child != X.NONE and self.is_dock(ev.child) is False: self.ewmh.setWmState(ev.window, 0, "_NET_WM_STATE_MAXIMIZED_VERT") self.ewmh.setWmState(ev.window, 0, "_NET_WM_STATE_MAXIMIZED_HORIZ") if self.display_corners is not None: self.display_corners.update() self.dpy.flush() # SESSION HANDLER def end_session(self): self.update_active_window_title_rt.stop() if self.prefs.deskbar["enabled"] == 1: self.deskbar.stop_repeated_events() if self.prefs.xround["enabled"] == 1: self.display_corners.stop() self.dpy.close() sys.exit(0) def main(self): # Register keyboard and mouse events self.dpy_root.grab_key(X.AnyKey, X.AnyModifier, 1, X.GrabModeAsync, X.GrabModeAsync) self.dpy_root.grab_button( 1, X.Mod1Mask | X.Mod2Mask, 1, X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask, X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE) self.dpy_root.grab_button( 3, X.Mod1Mask | X.Mod2Mask, 1, X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask, X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE) self.dpy_root.change_attributes(event_mask=X.SubstructureNotifyMask) self.set_background_color() children = self.window_list() for child in children: if child.get_attributes().map_state: self.manage_window(child) # Draw deskbar if self.prefs.deskbar["enabled"] == 1: self.deskbar = Deskbar(self.ewmh, self.dpy, self.dpy_root, self.screen, self.display_dimensions, self.wm_window_type, self.wm_window_types, self.wm_state, self.wm_window_status, self.prefs, self.session_info) self.deskbar.draw() # Draw display corners if self.prefs.xround["enabled"] == 1: self.display_corners = DisplayCorners( self.ewmh, self.dpy, self.dpy_root, self.screen, self.display_dimensions, self.wm_window_type, self.wm_window_types, self.wm_state, self.wm_window_status) self.display_corners.draw() try: self.event_handler() except KeyboardInterrupt or error.ConnectionClosedError: self.end_session() sys.exit(0)
def set_rt_event(self, interval, function): self.interval = interval self.function = function self.rt_event = RepeatedTimer(interval, function)
l_idx = 0 log.info("start reading lines") with open(config.loader_path, "r") as fdr: fdr.readline() for line in fdr: log.info("line {}: {}".format(l_idx, line)) l_idx += 1 try: doc = parse_line(line) publisher.send(doc) except: log.exception("{} {}".format(l_idx, line)) log.info("flushing and stopping publisher") publisher.flush() publisher.stop() if __name__ == "__main__": config_path = sys.argv[1] if len(sys.argv) > 1 else "config/config.yaml" config.create(config_path) logging.config.dictConfig(config.log_dict_config) log = logging.getLogger("loader") timer = RepeatedTimer(operation, config.interval_min * 60, start_immediately=True) timer.start() timer.join()
def __init__(self, ewmh, dpy, dpy_root, screen, display_dimensions, wm_window_type, wm_window_types, wm_state, wm_window_status, prefs, session_info): self.ewmh = ewmh self.dpy = dpy self.dpy_root = dpy_root self.screen = screen self.colormap = self.screen.default_colormap self.pixel_palette = PixelPalette(self.colormap) self.system_font = load_font(self.dpy, FONT_NAME) self.display_dimensions = display_dimensions self.wm_window_type = wm_window_type self.wm_window_types = wm_window_types self.wm_state = wm_state self.wm_window_status = wm_window_status self.prefs = prefs self.session_info = session_info self.time_command = self.set_get_current_time_command() self.border_width = 1 self.height = 20 self.real_height = self.height + self.border_width self.text_y_alignment = 15 self.padding_leading = 15 self.padding_between = 20 self.padding_trailing = 15 self.color_scheme = self.get_deskbar_color_scheme() self.command_string = "" self.deskbar = None self.deskbar_gc = None self.deskbar_items = { "leading": { "active_window_title": DeskbarItem("Window Title", text=self.session_info.session_name), "window_count": DeskbarItem("Window Count", text="0 windows", enabled=False), "launcher": DeskbarItem("Launcher", text=self.command_string, enabled=False) }, "trailing": { "memory_usage": DeskbarItem("Memory Usage", interval=10, function=self.set_memory_usage), "timestamp": DeskbarItem( "Clock", interval=1 if self.prefs.deskbar["clock"]["show_seconds"] == 1 else 30, function=self.set_timestamp, enabled=self.prefs.deskbar["clock"]["enabled"] == 1), }, } # Leading items drawn from left to right # Trailing items drawn from right to left self.deskbar_items_order = { "leading": ["window_count", "active_window_title", "launcher"], "trailing": ["timestamp", "memory_usage"] } self.deskbar_update_rt = RepeatedTimer(1, self.update)
class Deskbar(object): def __init__(self, ewmh, dpy, dpy_root, screen, display_dimensions, wm_window_type, wm_window_types, wm_state, wm_window_status, prefs, session_info): self.ewmh = ewmh self.dpy = dpy self.dpy_root = dpy_root self.screen = screen self.colormap = self.screen.default_colormap self.pixel_palette = PixelPalette(self.colormap) self.system_font = load_font(self.dpy, FONT_NAME) self.display_dimensions = display_dimensions self.wm_window_type = wm_window_type self.wm_window_types = wm_window_types self.wm_state = wm_state self.wm_window_status = wm_window_status self.prefs = prefs self.session_info = session_info self.time_command = self.set_get_current_time_command() self.border_width = 1 self.height = 20 self.real_height = self.height + self.border_width self.text_y_alignment = 15 self.padding_leading = 15 self.padding_between = 20 self.padding_trailing = 15 self.color_scheme = self.get_deskbar_color_scheme() self.command_string = "" self.deskbar = None self.deskbar_gc = None self.deskbar_items = { "leading": { "active_window_title": DeskbarItem("Window Title", text=self.session_info.session_name), "window_count": DeskbarItem("Window Count", text="0 windows", enabled=False), "launcher": DeskbarItem("Launcher", text=self.command_string, enabled=False) }, "trailing": { "memory_usage": DeskbarItem("Memory Usage", interval=10, function=self.set_memory_usage), "timestamp": DeskbarItem( "Clock", interval=1 if self.prefs.deskbar["clock"]["show_seconds"] == 1 else 30, function=self.set_timestamp, enabled=self.prefs.deskbar["clock"]["enabled"] == 1), }, } # Leading items drawn from left to right # Trailing items drawn from right to left self.deskbar_items_order = { "leading": ["window_count", "active_window_title", "launcher"], "trailing": ["timestamp", "memory_usage"] } self.deskbar_update_rt = RepeatedTimer(1, self.update) def launcher_is_running(self): return self.deskbar_items["leading"]["launcher"].enabled def toggle_launcher(self, state=False): print("Deskbar launcher mode: " + str(state)) self.deskbar_items["leading"]["launcher"].enabled = state self.command_string = "" self.update() def set_active_window_title(self, window_title): if window_title is None or len(window_title) == 0: window_title = self.session_info.session_name self.deskbar_items["leading"][ "active_window_title"].text = window_title self.deskbar_items["leading"][ "active_window_title"].width = self.get_string_physical_width( window_title) def set_window_count(self, window_count): suffix = " windows" if window_count == 1: suffix = " window" window_count_string = str(window_count) + suffix self.deskbar_items["leading"][ "window_count"].text = window_count_string self.deskbar_items["leading"][ "active_window_title"].width = self.get_string_physical_width( window_count_string) def set_memory_usage(self): self.deskbar_items["trailing"][ "memory_usage"].text = "MEM: " + self.get_memory_usage() + "%" self.deskbar_items["trailing"][ "memory_usage"].width = self.get_string_physical_width( self.deskbar_items["trailing"]["memory_usage"].text) def set_timestamp(self): self.deskbar_items["trailing"][ "timestamp"].text = self.get_current_time() self.deskbar_items["trailing"][ "timestamp"].width = self.get_string_physical_width( self.deskbar_items["trailing"]["timestamp"].text) def set_get_current_time_command(self): command = 'date +"' if self.prefs.deskbar["clock"]["show_day"] == 1: command += '%a ' if self.prefs.deskbar["clock"]["show_date"] == 1: command += '%d %b ' command += '%I:%M' if self.prefs.deskbar["clock"]["show_seconds"] == 1: command += ':%S' command += ' %P"' return command def get_string_physical_width(self, text): font = self.dpy.open_font(FONT_NAME) result = font.query_text_extents(text.encode()) return result.overall_width def get_memory_usage(self): return os.popen( "free -m | awk 'NR==2{printf $3*100/$2}' | xargs printf '%.2f'" ).read()[:-1] def get_current_time(self): return os.popen(self.time_command).read()[:-1] def start_repeated_events(self): for item in self.deskbar_items["leading"].values(): item.start() for item in self.deskbar_items["trailing"].values(): item.start() self.deskbar_update_rt.start() def stop_repeated_events(self): for item in self.deskbar_items["leading"].values(): item.stop() for item in self.deskbar_items["trailing"].values(): item.stop() self.deskbar_update_rt.stop() def get_deskbar_color_scheme(self): background_pixel = self.pixel_palette.get_named_pixel("white") foreground_pixel = self.pixel_palette.get_named_pixel("black") if self.prefs.deskbar[ "foreground_color"] in self.pixel_palette.hex_map.keys(): foreground_pixel = self.pixel_palette.get_named_pixel( self.prefs.deskbar["foreground_color"]) elif self.pixel_palette.is_color_hex( self.prefs.deskbar["foreground_color"]) is True: foreground_pixel = self.pixel_palette.get_hex_pixel( self.prefs.deskbar["foreground_color"]) if self.prefs.deskbar[ "background_color"] in self.pixel_palette.hex_map.keys(): background_pixel = self.pixel_palette.get_named_pixel( self.prefs.deskbar["background_color"]) elif self.pixel_palette.is_color_hex( self.prefs.deskbar["background_color"]) is True: background_pixel = self.pixel_palette.get_hex_pixel( self.prefs.deskbar["background_color"]) return {"bg": background_pixel, "fg": foreground_pixel} def draw(self): screen_width, screen_height = self.display_dimensions.width, self.display_dimensions.height background_pixel, foreground_pixel = self.color_scheme[ "bg"], self.color_scheme["fg"] self.deskbar = self.dpy_root.create_window( -self.border_width, -self.border_width, screen_width, self.height, self.border_width, self.screen.root_depth, background_pixel=background_pixel, event_mask=X.StructureNotifyMask | X.ExposureMask | X.ButtonPressMask | X.ButtonReleaseMask, ) self.deskbar_gc = self.deskbar.create_gc( font=self.system_font, foreground=foreground_pixel, background=background_pixel, ) self.deskbar.change_property(self.wm_window_type, Xatom.ATOM, 32, [self.wm_window_types["dock"]], X.PropModeReplace) self.ewmh.setWmState(self.deskbar, 1, "_NET_WM_DESKTOP") self.ewmh.setWmState(self.deskbar, 1, "_NET_WM_STATE_SKIP_TASKBAR") self.ewmh.setWmState(self.deskbar, 1, "_NET_WM_STATE_ABOVE") self.deskbar.map() # Draw deskbar self.set_timestamp() # Set initial timestamp self.set_memory_usage() # Set initial memory usage percentage self.update() # Initial update self.start_repeated_events() # Start deskbar updates def update(self): self.deskbar.clear_area() # Leading items if self.deskbar_items["leading"]["launcher"].enabled is False: for item_key in self.deskbar_items_order["leading"]: item = self.deskbar_items["leading"][item_key] if item.enabled is True: self.deskbar.draw_text(self.deskbar_gc, self.padding_leading, self.text_y_alignment, item.text.encode('utf-8')) else: # Launcher takes precedence self.deskbar.draw_text(self.deskbar_gc, self.padding_leading, self.text_y_alignment, (self.command_string + "|").encode('utf-8')) # Trailing items spacing_from_trailing_end = self.padding_trailing for item_key in self.deskbar_items_order["trailing"]: item = self.deskbar_items["trailing"][item_key] if item.enabled is True: self.deskbar.draw_text( self.deskbar_gc, self.display_dimensions.width - (item.width + spacing_from_trailing_end), self.text_y_alignment, item.text.encode('utf-8')) spacing_from_trailing_end += (item.width + self.padding_between) def toggle_window_count(self): self.deskbar_items["leading"][ "window_count"].enabled = not self.deskbar_items["leading"][ "window_count"].enabled self.deskbar_items["leading"][ "active_window_title"].enabled = not self.deskbar_items["leading"][ "window_count"].enabled