"""Shared base for NexusOS popup menus — override_redirect window, no WM placement.""" # PyGObject (gi.repository) is dynamically generated and its API is Optional-heavy # (e.g. Gdk.Display.get_default() is typed Display|None). These are fine at runtime, # so silence the type-checker noise for this GTK desktop script. # pyright: reportMissingModuleSource=false, reportOptionalMemberAccess=false, reportArgumentType=false, reportCallIssue=false, reportAttributeAccessIssue=false import gi, fcntl, os, sys, signal, subprocess gi.require_version('Gtk', '3.0') gi.require_version('Gdk', '3.0') from gi.repository import Gtk, Gdk, GdkPixbuf, GLib NEXUS_CSS = b""" * { font-family: sans-serif; } window { background-color: #2a1d33; color: #f2f2f2; border: 1px solid #4d3461; border-radius: 6px; } notebook { background-color: #2a1d33; } notebook > header { background-color: #1e1526; border-bottom: 1px solid #4d3461; border-radius: 6px 6px 0 0; } notebook > header > tabs > tab { color: #a8a8a8; padding: 6px 16px; border: none; background-color: transparent; border-bottom: 2px solid transparent; } notebook > header > tabs > tab:checked { color: #8cc63f; border-bottom: 2px solid #8cc63f; } notebook > header > tabs > tab:hover:not(:checked) { color: #f2f2f2; background-color: rgba(140,198,63,0.10); } notebook stack { background-color: #2a1d33; } treeview { background-color: #1e1526; color: #f2f2f2; } treeview:selected { background-color: #88008f; color: #ffffff; } treeview:hover { background-color: rgba(140,198,63,0.14); } treeview header button { background-color: #1e1526; color: #a8a8a8; border: none; border-bottom: 1px solid #4d3461; box-shadow: none; } label { color: #f2f2f2; } button { background-color: #2e3236; color: #f2f2f2; border: 1px solid #3a3d41; border-radius: 4px; padding: 5px 14px; box-shadow: none; text-shadow: none; -gtk-icon-shadow: none; } button:hover { background-color: rgba(140,198,63,0.18); border-color: #8cc63f; color: #8cc63f; } button:active { background-color: #8cc63f; color: #0a0a00; } scale trough { background-color: #1e1526; border: 1px solid #4d3461; border-radius: 4px; min-height: 6px; } scale trough highlight { background-color: #8cc63f; border-radius: 4px; } scale slider { background-color: #8cc63f; border: none; border-radius: 50%; min-width: 16px; min-height: 16px; } separator { background-color: #4d3461; min-height: 1px; } scrolledwindow { background-color: #1e1526; } .section-header { color: #a8a8a8; font-size: 0.8em; padding: 4px 8px 2px 8px; } .action-row { padding: 6px 12px; border-radius: 4px; } .action-row:hover { background-color: rgba(140,198,63,0.14); color: #8cc63f; } .dim { color: #a8a8a8; } """ def apply_css(): provider = Gtk.CssProvider() provider.load_from_data(NEXUS_CSS) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION, ) def make_popup_window(width, height): """Create an override_redirect popup window — bypasses WM placement entirely.""" win = Gtk.Window(type=Gtk.WindowType.POPUP) win.set_type_hint(Gdk.WindowTypeHint.POPUP_MENU) win.set_decorated(False) win.set_skip_taskbar_hint(True) win.set_skip_pager_hint(True) win.set_keep_above(True) win.set_default_size(width, height) win.set_resizable(False) win.connect('key-press-event', lambda w, e: w.destroy() if e.keyval == Gdk.KEY_Escape else None) def on_button_press(w, event): wx, wy = w.get_position() ww = w.get_allocated_width() wh = w.get_allocated_height() rx, ry = int(event.x_root), int(event.y_root) if rx < wx or rx >= wx + ww or ry < wy or ry >= wy + wh: w.destroy() return False win.connect('button-press-event', on_button_press) def on_map(w, _event): def do_grab(): gdk_win = w.get_window() if gdk_win: seat = Gdk.Display.get_default().get_default_seat() seat.grab(gdk_win, Gdk.SeatCapabilities.ALL, True, None, None, None) return False # don't repeat GLib.timeout_add(150, do_grab) return False win.connect('map-event', on_map) def on_destroy(w): Gdk.Display.get_default().get_default_seat().ungrab() win.connect('destroy', on_destroy) return win def get_mouse_position(): display = Gdk.Display.get_default() seat = display.get_default_seat() _, x, y = seat.get_pointer().get_position() return x, y def get_panel_bottom(): """Return y-coordinate just below the top panel via _NET_WORKAREA.""" try: out = subprocess.check_output( ['xprop', '-root', '_NET_WORKAREA'], text=True, stderr=subprocess.DEVNULL ) nums = [int(n.strip()) for n in out.split('=')[1].split(',')] return nums[1] # workarea y = where usable area begins (= panel height) except Exception: return 40 def position_window(win, width, height): """Position popup just below the panel, horizontally centered on click.""" mx, _ = get_mouse_position() screen = Gdk.Screen.get_default() sw, sh = screen.get_width(), screen.get_height() panel_bottom = get_panel_bottom() x = mx - width // 2 y = panel_bottom + 2 x = max(4, min(x, sw - width - 4)) if height > 0: y = min(y, sh - height - 4) win.move(x, y) def single_instance(lockfile, pidfile): """flock-based single instance. Returns lock_fd on success, exits on collision.""" fd = open(lockfile, 'w') try: fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: try: with open(pidfile) as f: os.kill(int(f.read().strip()), signal.SIGTERM) except Exception: pass sys.exit(0) with open(pidfile, 'w') as f: f.write(str(os.getpid())) return fd def load_icon(path, size=16): try: return GdkPixbuf.Pixbuf.new_from_file_at_size(path, size, size) except Exception: return None