def set_background(ctx, window, background): with InfiniteGlass.Display() as display: @glass_action.window_tools.str_to_win(display, window) def set_background(window): if background: background_path = background[0] else: import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk as gtk dlg = gtk.FileChooserDialog( title="Change background (SVG files only)", action=gtk.FileChooserAction.OPEN, buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL, gtk.STOCK_OPEN, gtk.ResponseType.OK)) filter = gtk.FileFilter() filter.add_pattern("*.svg") dlg.set_filter(filter) response = dlg.run() background_path = dlg.get_filename() dlg.destroy() if response != gtk.ResponseType.OK: sys.exit(0) return window["IG_CONTENT"] = ("IG_SVG", "file://" + background_path) display.flush() sys.exit(0)
def main(): manager = None try: with InfiniteGlass.Display() as display: overlay = display.root.composite_get_overlay_window().overlay_window overlay_geom = overlay.get_geometry() gc = overlay.create_gc( foreground = display.screen().black_pixel, background = display.screen().white_pixel) overlay.rectangle(gc, 0, 0, overlay_geom.width, overlay_geom.height, onerror = None) manager = glass_ghosts.manager.GhostManager(display) sys.stdout.write("%s\n" % manager.session.listen_address()) sys.stdout.flush() InfiniteGlass.DEBUG("init", "Session manager listening to %s\n" % manager.session.listen_address()) manager.components.shutdown() except Exception as e: print("Ghost manager systemic failure, restarting: %s" % (e,)) traceback.print_exc() try: if manager is not None and hasattr(manager, "components") and hasattr(manager.components, "components_by_pid"): for pid in manager.components.components_by_pid.keys(): os.kill(pid, signal.SIGINT) except Exception as e: print(e) traceback.print_exc() os.execlp(sys.argv[0], *sys.argv) print("END")
def stop(ctx, name): with InfiniteGlass.Display() as display: key = "IG_COMPONENT_%s" % name spec = json.loads(display.root[key].decode("utf-8")) spec["run"] = False display.root[key] = json.dumps(spec).encode("utf-8") display.flush()
def set(ctx, window, name, value): """Name is the property atom name as a string. Value is the property value as a JSON value, parsed using InfiniteGlass.fromjson (so any __jsonclass__ values supported by it are supported). In particular, strings are interpreted as atom names, actual string values need to use the __jsonclass__ encoding. Usage examples: \b glass-action window set --window 1234567 IG_COORDS "[1.0, 1.0, 1.0, 1.0]" """ with InfiniteGlass.Display() as display: @glass_action.window_tools.str_to_win(display, window) def set(win): v = value try: v = json.loads(v) except: pass properties = json.loads( json.dumps({name: v}), object_hook=InfiniteGlass.fromjson(display)) for k, v in properties.items(): win[k] = v display.flush() sys.exit(0)
def start(ctx, name, command): with InfiniteGlass.Display() as display: key = "IG_COMPONENT_%s" % name display.root[key] = json.dumps({ "command": command, "name": name }).encode("utf-8") display.flush()
def main2(*arg, **kw): mode.load_config() with InfiniteGlass.Display() as display: # extension_info = display.query_extension('XInputExtension') # xinput_major = extension_info.major_opcode version_info = display.xinput_query_version() print('Found XInput version %u.%u' % ( version_info.major_version, version_info.minor_version, )) font = display.open_font('cursor') display.input_cursor = font.create_glyph_cursor( font, Xlib.Xcursorfont.box_spiral, Xlib.Xcursorfont.box_spiral + 1, (65535, 65535, 65535), (0, 0, 0)) display.animate_window = -1 @display.root.require("IG_ANIMATE") def animate_window(root, win): display.animate_window = win # Do not allow setting the input focus to None as that makes our keygrabs break... @display.root.on() def FocusIn(win, event): if event.detail == Xlib.X.NotifyDetailNone: display.root.set_input_focus(Xlib.X.RevertToNone, Xlib.X.CurrentTime) @display.root.on(mask="SubstructureNotifyMask", client_type="IG_INPUT_ACTION") def ClientMessage(win, event): win, atom = event.parse("WINDOW", "ATOM") action = json.loads(win[atom]) InfiniteGlass.DEBUG("message", "RECEIVED INPUT ACTION %s" % (action, )) sys.stderr.flush() event.window = win display.input_stack[-1].last_event = event display.input_stack[-1].action(None, action, event) @display.eventhandlers.append def handle(event): if display.animate_window == -1: return False return mode.handle_event(display, event) mode.push_by_name(display, "base_mode") display.root.xinput_select_events([ (Xlib.ext.xinput.AllDevices, Xlib.ext.xinput.RawMotionMask), ]) InfiniteGlass.DEBUG("init", "Input handler started\n")
def list(ctx): with InfiniteGlass.Display() as display: for key in display.root.keys(): if key.startswith("IG_COMPONENT_"): name = key[len("IG_COMPONENT_"):] pidkey = "IG_COMPONENTPID_" + name pid = "not running" if pidkey in display.root: pid = str(display.root[pidkey]) print("%s (%s)" % (name, pid))
def expression(ctx, value): with InfiniteGlass.Display() as display: try: value = json.loads(value, object_hook=InfiniteGlass.fromjson(display)) except: pass itemtype, items, fmt = InfiniteGlass.parse_value(display, value) print("%s(%s): %s" % (itemtype, fmt, items)) sys.exit(0)
def setUp(self): self.renderer = subprocess.Popen(["build/glass-renderer"]) while True: try: self.display = InfiniteGlass.Display() break except: time.sleep(0.5) self.theme = Theme(self.display) self.display.flush() self.test_done = False
def props(ctx, window, limit): with InfiniteGlass.Display() as display: @glass_action.window_tools.str_to_win(display, window) def inspect(win): for key, value in win.items(): value = str(value) if limit > 0: value = value[:limit] print("%s=%s" % (key, value)) sys.exit(0)
def send(ctx, window, mask, event): """Usage examples: \b glass-action window send --mask SubstructureNotifyMask --window root IG_DEBUG_PICKING glass-action window send --mask StructureNotifyMask --window root IG_GHOSTS_EXIT glass-action window send --mask SubstructureNotifyMask --window root IG_EXIT """ with InfiniteGlass.Display() as display: @glass_action.window_tools.send_msg(display, window, mask, event) def done(): sys.exit(0)
def animate(ctx, name, animation): with InfiniteGlass.Display() as display: anim = display.root["IG_ANIMATE"] name += "_SEQUENCE" display.root[name] = json.loads(animation) anim.send(anim, "IG_ANIMATE", display.root, name, 0.0, event_mask=Xlib.X.PropertyChangeMask) display.flush() sys.exit(0)
def key(ctx, window): with InfiniteGlass.Display() as display: @glass_action.window_tools.str_to_win(display, window) def inspect(win): import glass_ghosts.helpers configpath = os.path.expanduser( os.environ.get("GLASS_GHOSTS_CONFIG", "~/.config/glass/ghosts.yml")) with open(configpath) as f: config = yaml.load(f, Loader=yaml.SafeLoader) print(glass_ghosts.helpers.ghost_key(win, config["match"])) sys.exit(0)
def main(*arg, **kw): with InfiniteGlass.Display() as display: configpath = os.path.expanduser( os.environ.get("GLASS_THEME_CONFIG", "~/.config/glass/theme.json")) with open(configpath) as f: config = yaml.load(f, Loader=yaml.SafeLoader) module_name, cls_name = config["name"].rsplit(".", 1) module = importlib.import_module(module_name) importlib.reload(module) cls = getattr(module, cls_name) cls(display, **config.get("args", {})) display.flush() InfiniteGlass.DEBUG("init", "Theme started: %s\n" % config["name"])
def main(*arg, **kw): with InfiniteGlass.Display() as display: @display.mainloop.add_interval(0.1) def animator(timestamp, idx): animate(display) w = display.root.create_window(map=False) display.root["IG_ANIMATE"] = w @w.on(client_type="IG_ANIMATE", mask="PropertyChangeMask") def ClientMessage(win, event): window, atom, timeframe = event.parse("WINDOW", "ATOM", "FLOAT") animationid = (window.__window__(), atom) start_animation( animationid, animate_anything(display, window=window, atom=atom, timeframe=timeframe)) InfiniteGlass.DEBUG("init", "Animator started\n")
def list(ctx): with InfiniteGlass.Display() as display: for key in display.root.keys(): if key.startswith("IG_COMPONENT_"): print(key[len("IG_COMPONENT_"):])
def main(*arg, **kw): configpath = os.path.expanduser( os.environ.get("GLASS_WIDGET_CONFIG", "~/.config/glass/widgets.json")) with open(configpath) as f: config = yaml.load(f, Loader=yaml.SafeLoader) with InfiniteGlass.Display() as display: for widget_type, widgets in config.items(): for name, widget in widgets.items(): w = display.root.create_window() properties = { "WM_CLASS": "data://glass-widget", "WM_NAME": "data://" + name, "_NET_WM_WINDOW_TYPE": "_NET_WM_WINDOW_TYPE_DESKTOP" } if widget_type == "widgets": properties["IG_LAYER"] = "IG_LAYER_OVERLAY" elif widget_type == "window-decorations": properties["IG_LAYER"] = "IG_LAYER_NONE" properties["IG_ITEM_LAYER"] = "IG_LAYER_DESKTOP" properties["IG_SHADER"] = "IG_SHADER_DECORATION" display.root["IG_WINDOW_DECORATION_" + name.upper()] = ("IG_ITEM", w) elif widget_type == "island-decorations": properties["IG_LAYER"] = "IG_LAYER_NONE" properties["IG_ITEM_LAYER"] = "IG_LAYER_ISLAND" properties["IG_SHADER"] = "IG_SHADER_DECORATION" display.root["IG_ISLAND_DECORATION_" + name.upper()] = ("IG_ITEM", w) properties.update(widget["properties"]) properties = json.loads( json.dumps(properties), object_hook=InfiniteGlass.fromjson(display)) for key, value in properties.items(): w[key] = value w.widget = widget @w.on() def ButtonPress(win, event): parent = win.get("IG_PARENT_WINDOW", None) def n(w): return w and w.get("WM_NAME", str( w.__window__())) or "none" print("%s/%s.%s()" % (n(parent), n(win), win.widget["action"])) target = parent or win target["IG_INPUT_ACTION"] = json.dumps( win.widget["action"]).encode("utf-8") display.root.send(display.root, "IG_INPUT_ACTION", target, "IG_INPUT_ACTION", event_mask=Xlib.X.SubstructureNotifyMask | Xlib.X.SubstructureRedirectMask) display.flush() InfiniteGlass.DEBUG("init", "Widgets started\n")
def __init__(self, argv): self.argv = argv options = {} for idx, arg in enumerate(argv): if not arg.startswith("--"): execargs = argv[idx:] break arg = arg[2:] value = True if "=" in arg: arg, value = arg.split("=", 1) options[arg] = value if "help" in options or not self.argv: print("""glass-session-wrapper OPTIONS COMMAND ARG1 ARG2... Wraps applications that do not support the session manager protocol but that support saving their state on exit to a session directory, The application needs to set the WM_CLIENT_MACHINE and _NET_WM_PID properties on its windows. Where COMMAND and ARGx is the program to start and its arguments. The command and arguments can contain tokens to be replaced on the form %(NAME)s. Available tokens: %(sessionid)s The current session id string. Guaranteed to not contain a '/' character. Available options: --sessionid=SESSIONID Specify a previously used session id to reuse. Mainly used when the application is restarted by the session manager. Example: glass-session-wrapper \ chromium-browser \ --user-data-dir=chrome-sessions/%(sessionid)s """) sys.exit(0) previous_id = None if "sessionid" in options: previous_id = options["sessionid"].encode("utf-8") self.conn = MyConnection(self, previous_id=previous_id) self.client_id = self.conn.client_id.decode("utf-8") print("Session ID: ", self.client_id) if "sessionid" not in options: self.argv[0:0] = ["--sessionid=%s" % self.client_id] options["sessionid"] = self.client_id self.status_r, self.status_w = os.pipe() signal.signal(signal.SIGCHLD, self.sig_child) self.machine = socket.gethostname() execargs = [arg % options for arg in execargs] print("Session wrapper executing: %s" % " ".join(repr(item) for item in execargs)) self.pid = os.fork() if self.pid == 0: os.close(self.status_r) os.close(self.status_w) os.execvp(execargs[0], execargs) os._exit(127) # This shouldn't happen... else: with InfiniteGlass.Display() as self.display: self.display.mainloop.add(self.status_r, self.child_done) self.display.mainloop.add( self.conn.iceconn.IceConnectionNumber(), lambda fd: self.conn.iceconn.IceProcessMessages()) @self.display.root.on(mask="SubstructureNotifyMask") def MapNotify(win, event): self.match(event.window) print("Waiting for application windows to open...")
import InfiniteGlass; d = InfiniteGlass.Display() import time import sys name = sys.argv[1] l = float(sys.argv[2]) h = float(sys.argv[3]) t = float(sys.argv[4]) anim = d.root["IG_ANIMATE"] d.root[name] = l d.root[name + "_ANIMATE"] = h anim.send(anim, "IG_ANIMATE", d.root, name, t) while True: time.sleep(1) print(d.root[name])
def show(ctx, name): with InfiniteGlass.Display() as display: key = "IG_COMPONENT_%s" % name print(" ".join( json.loads(display.root[key].decode("utf-8"))["command"]))
import InfiniteGlass import Xlib.Xcursorfont import Xlib.X import pkg_resources current_win_start = None current_win = None current_coord = None with InfiniteGlass.Display() as display: font = display.open_font('cursor') display.input_cursor = font.create_glyph_cursor( font, Xlib.Xcursorfont.diamond_cross, Xlib.Xcursorfont.diamond_cross + 1, (65535, 65535, 65535), (0, 0, 0)) display.notify_motion_window = -1 @display.root.require("IG_NOTIFY_MOTION") def notify_motion(root, win): display.notify_motion_window = win @win.on() def PropertyNotify(win, event): global current_coord, current_win_start name = display.get_atom_name(event.atom) if name != "IG_NOTIFY_MOTION": return current_coord = win[name] if current_win is not None: x = min(current_coord[0], current_win_start[0]) y = max(current_coord[1], current_win_start[1]) w = abs(current_coord[0] - current_win_start[0])
def restart(ctx, name): with InfiniteGlass.Display() as display: key = "IG_COMPONENT_%s" % name display.root[key] = display.root[key] display.flush()
def main(): with InfiniteGlass.Display() as display: island_manager = manager.IslandManager(display)