🔧 chore(dock): add system tray and update tray visibility in DockComponents
This commit is contained in:
7 files changed
+377
-113
No files matched your search
@@ -51,6 +51,7 @@
|
||||
"dock_battery_visible": true,
|
||||
"dock_controls_visible": true,
|
||||
"dock_indicators_visible": true,
|
||||
"dock_tray_visible": true,
|
||||
"metrics_visible": {
|
||||
"cpu": true,
|
||||
"ram": true,
|
||||
|
||||
+3
-1
@@ -7,7 +7,7 @@ import gi
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
|
||||
APP_NAME = "modus"
|
||||
APP_NAME = "modusv1"
|
||||
APP_NAME_CAP = "Modus"
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ if os.path.exists(CONFIG_FILE):
|
||||
"date_time": config.get("dock_date_time_visible", True),
|
||||
"controls": config.get("dock_controls_visible", True),
|
||||
"indicators": config.get("dock_indicators_visible", True),
|
||||
"tray": config.get("dock_tray_visible", True),
|
||||
}
|
||||
|
||||
METRICS_DISKS = config.get("metrics_disks", ["/"])
|
||||
@@ -96,6 +97,7 @@ else:
|
||||
"date_time": True,
|
||||
"controls": True,
|
||||
"indicators": True,
|
||||
"tray": True,
|
||||
}
|
||||
|
||||
METRICS_DISKS = ["/"]
|
||||
|
||||
+76
-2
@@ -1,3 +1,77 @@
|
||||
{
|
||||
"pinned_apps": []
|
||||
}
|
||||
2
|
||||
"pinned_apps": [
|
||||
{
|
||||
"name": "Advanced Network Configuration",
|
||||
"display_name": "Advanced Network Configuration",
|
||||
"executable": "nm-connection-editor",
|
||||
"command_line": "nm-connection-editor",
|
||||
"icon_name": "preferences-system-network"
|
||||
},
|
||||
{
|
||||
"name": "Avahi SSH Server Browser",
|
||||
"display_name": "Avahi SSH Server Browser",
|
||||
"executable": "/usr/bin/bssh",
|
||||
"command_line": "/usr/bin/bssh",
|
||||
"icon_name": "network-wired"
|
||||
},
|
||||
{
|
||||
"name": "Avahi VNC Server Browser",
|
||||
"display_name": "Avahi VNC Server Browser",
|
||||
"executable": "/usr/bin/bvnc",
|
||||
"command_line": "/usr/bin/bvnc",
|
||||
"icon_name": "network-wired"
|
||||
},
|
||||
{
|
||||
"name": "Avahi Zeroconf Browser",
|
||||
"display_name": "Avahi Zeroconf Browser",
|
||||
"executable": "/usr/bin/avahi-discover",
|
||||
"command_line": "/usr/bin/avahi-discover",
|
||||
"icon_name": "network-wired"
|
||||
},
|
||||
{
|
||||
"name": "Bluetooth Manager",
|
||||
"display_name": "Bluetooth Manager",
|
||||
"executable": "blueman-manager",
|
||||
"command_line": "blueman-manager",
|
||||
"icon_name": "blueman"
|
||||
},
|
||||
{
|
||||
"name": "Brave",
|
||||
"display_name": "Brave",
|
||||
"window_class": "brave-browser",
|
||||
"executable": "brave",
|
||||
"command_line": "brave %U",
|
||||
"icon_name": "brave-desktop"
|
||||
},
|
||||
{
|
||||
"name": "btop++",
|
||||
"display_name": "btop++",
|
||||
"executable": "btop",
|
||||
"command_line": "btop",
|
||||
"icon_name": "btop"
|
||||
},
|
||||
{
|
||||
"name": "Bulk Rename",
|
||||
"display_name": "Bulk Rename",
|
||||
"executable": "thunar",
|
||||
"command_line": "thunar --bulk-rename %F",
|
||||
"icon_name": "org.xfce.thunar"
|
||||
},
|
||||
{
|
||||
"name": "CMake",
|
||||
"display_name": "CMake",
|
||||
"executable": "cmake-gui",
|
||||
"command_line": "cmake-gui %f",
|
||||
"icon_name": "CMakeSetup"
|
||||
},
|
||||
{
|
||||
"name": "Cursor",
|
||||
"display_name": "Cursor",
|
||||
"window_class": "cursor",
|
||||
"executable": "/usr/bin/cursor",
|
||||
"command_line": "/usr/bin/cursor --no-sandbox %U",
|
||||
"icon_name": "cursor"
|
||||
}
|
||||
]
|
||||
}
|
||||
+22
-20
@@ -1,21 +1,24 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
import json
|
||||
import config.data as data
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.datetime import DateTime
|
||||
from fabric.system_tray.widgets import SystemTray
|
||||
from modules.dock.battery import Battery
|
||||
from modules.dock.controls import Controls
|
||||
from modules.dock.indicators import Indicators
|
||||
from modules.dock.metrics import Metrics
|
||||
from modules.dock.workspaces import create_workspace_widget
|
||||
from modules.dock.controls import Controls
|
||||
from modules.dock.workspaces import workspace
|
||||
from modules.dock.indicators import Indicators
|
||||
|
||||
|
||||
class DockComponents(Box):
|
||||
def __init__(self, orientation_val="h", **kwargs):
|
||||
super().__init__(
|
||||
name="dock-components", orientation=orientation_val, spacing=4, **kwargs
|
||||
name="system-tray",
|
||||
orientation=orientation_val,
|
||||
spacing=4,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
# Initialize component visibility from data
|
||||
@@ -23,7 +26,7 @@ class DockComponents(Box):
|
||||
|
||||
# Create components
|
||||
self.workspaces = Button(
|
||||
child=create_workspace_widget(),
|
||||
child=workspace,
|
||||
name="workspaces",
|
||||
)
|
||||
self.metrics = Metrics()
|
||||
@@ -38,6 +41,9 @@ class DockComponents(Box):
|
||||
)
|
||||
self.controls = Controls()
|
||||
self.indicators = Indicators()
|
||||
self.systray = SystemTray(
|
||||
icon_size=16, name="tray", orientation="h" if not data.VERTICAL else "v"
|
||||
)
|
||||
|
||||
# Add components based on position
|
||||
if data.DOCK_POSITION == "Right":
|
||||
@@ -47,6 +53,7 @@ class DockComponents(Box):
|
||||
self.add(self.battery)
|
||||
self.add(self.metrics)
|
||||
self.add(self.workspaces)
|
||||
self.add(self.systray)
|
||||
else: # Bottom or Left position
|
||||
self.add(self.workspaces)
|
||||
self.add(self.metrics)
|
||||
@@ -54,6 +61,7 @@ class DockComponents(Box):
|
||||
self.add(self.indicators)
|
||||
self.add(self.battery)
|
||||
self.add(self.date_time)
|
||||
self.add(self.systray)
|
||||
|
||||
# Apply initial visibility
|
||||
self.apply_component_props()
|
||||
@@ -66,6 +74,7 @@ class DockComponents(Box):
|
||||
"date_time": self.date_time,
|
||||
"controls": self.controls,
|
||||
"indicators": self.indicators,
|
||||
"systray": self.systray,
|
||||
}
|
||||
|
||||
for component_name, widget in components.items():
|
||||
@@ -80,27 +89,20 @@ class DockComponents(Box):
|
||||
"date_time": self.date_time,
|
||||
"controls": self.controls,
|
||||
"indicators": self.indicators,
|
||||
"systray": self.systray,
|
||||
}
|
||||
|
||||
if component_name in components and component_name in self.component_visibility:
|
||||
self.component_visibility[component_name] = not self.component_visibility[
|
||||
component_name
|
||||
]
|
||||
components[component_name].set_visible(
|
||||
self.component_visibility[component_name]
|
||||
)
|
||||
self.component_visibility[component_name] = not self.component_visibility[component_name]
|
||||
components[component_name].set_visible(self.component_visibility[component_name])
|
||||
|
||||
config_file = os.path.expanduser(
|
||||
f"~/.config/{data.APP_NAME}/config/config.json"
|
||||
)
|
||||
config_file = os.path.expanduser(f"~/.config/{data.APP_NAME}/config/config.json")
|
||||
if os.path.exists(config_file):
|
||||
try:
|
||||
with open(config_file, "r") as f:
|
||||
config = json.load(f)
|
||||
|
||||
config[f"dock_{component_name}_visible"] = (
|
||||
self.component_visibility[component_name]
|
||||
)
|
||||
config[f"dock_{component_name}_visible"] = self.component_visibility[component_name]
|
||||
|
||||
with open(config_file, "w") as f:
|
||||
json.dump(config, f, indent=4)
|
||||
@@ -109,4 +111,4 @@ class DockComponents(Box):
|
||||
|
||||
return self.component_visibility[component_name]
|
||||
|
||||
return None
|
||||
return None
|
||||
+95
-80
@@ -19,10 +19,10 @@ from fabric.widgets.image import Image
|
||||
from fabric.widgets.revealer import Revealer
|
||||
from gi.repository import Gdk, GLib, Gtk
|
||||
from modules.corners import MyCorner
|
||||
from modules.dock.components import DockComponents
|
||||
from utils.icon_resolver import IconResolver
|
||||
from utils.occlusion import check_occlusion
|
||||
from utils.wayland import WaylandWindow as Window
|
||||
from modules.dock.components import DockComponents
|
||||
|
||||
|
||||
def read_config():
|
||||
@@ -91,7 +91,7 @@ class Dock(Window):
|
||||
layer="top",
|
||||
anchor=anchor_to_set,
|
||||
margin="0px 0px 0px 0px",
|
||||
exclusivity="auto" if not data.DOCK_AUTO_HIDE else "none",
|
||||
exclusivity="none",
|
||||
**kwargs,
|
||||
)
|
||||
Dock._instances.append(self)
|
||||
@@ -146,20 +146,25 @@ class Dock(Window):
|
||||
self.dock_eventbox.connect("enter-notify-event", self._on_dock_enter)
|
||||
self.dock_eventbox.connect("leave-notify-event", self._on_dock_leave)
|
||||
|
||||
# Create components section
|
||||
# Define separator orientation
|
||||
separator_orientation = (
|
||||
Gtk.Orientation.VERTICAL
|
||||
if self.view.get_orientation() == Gtk.Orientation.HORIZONTAL
|
||||
else Gtk.Orientation.HORIZONTAL
|
||||
)
|
||||
|
||||
# Initialize components with proper orientation
|
||||
self.components = DockComponents(orientation_val=dock_wrapper_orientation_val)
|
||||
# Create components using DockComponents
|
||||
self.components = DockComponents(orientation_val="h" if not data.VERTICAL else "v")
|
||||
|
||||
# Initialize components with proper orientation
|
||||
self.components = DockComponents(orientation_val=dock_wrapper_orientation_val)
|
||||
# Add components based on position
|
||||
if self.actual_dock_is_horizontal: # Bottom dock
|
||||
self.view.add(self.components)
|
||||
elif data.DOCK_POSITION == "Left":
|
||||
self.view.add(self.components)
|
||||
else: # Right position
|
||||
self.view.add(self.components)
|
||||
|
||||
# Add components to dock
|
||||
# Add system tray to dock
|
||||
if data.DOCK_POSITION == "Right":
|
||||
self.view.add(
|
||||
Box(
|
||||
@@ -171,9 +176,7 @@ class Dock(Window):
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
self.view.add(self.components)
|
||||
else:
|
||||
self.view.pack_start(self.components, False, False, 0)
|
||||
self.view.add(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
@@ -563,7 +566,6 @@ class Dock(Window):
|
||||
not self.is_mouse_over_dock_area
|
||||
and not self._drag_in_progress
|
||||
and not self._prevent_occlusion
|
||||
and data.DOCK_AUTO_HIDE
|
||||
):
|
||||
if self.always_occluded:
|
||||
self.dock_revealer.set_reveal_child(False)
|
||||
@@ -582,7 +584,6 @@ class Dock(Window):
|
||||
self.is_mouse_over_dock_area
|
||||
or self._drag_in_progress
|
||||
or self._prevent_occlusion
|
||||
or not data.DOCK_AUTO_HIDE
|
||||
):
|
||||
return
|
||||
|
||||
@@ -736,33 +737,7 @@ class Dock(Window):
|
||||
)
|
||||
|
||||
# Add components based on position
|
||||
if data.DOCK_POSITION == "Right":
|
||||
children.extend(pinned_buttons)
|
||||
if pinned_buttons and open_buttons:
|
||||
children.append(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
v_expand=False,
|
||||
h_expand=False,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
children.extend(open_buttons)
|
||||
if pinned_buttons or open_buttons:
|
||||
children.append(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
v_expand=False,
|
||||
h_expand=False,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
children.append(self.components)
|
||||
else: # Bottom or Left position
|
||||
if self.actual_dock_is_horizontal: # Bottom dock
|
||||
children.append(self.components)
|
||||
if pinned_buttons or open_buttons:
|
||||
children.append(
|
||||
@@ -788,6 +763,58 @@ class Dock(Window):
|
||||
)
|
||||
)
|
||||
children.extend(open_buttons)
|
||||
elif data.DOCK_POSITION == "Left":
|
||||
children.append(self.components)
|
||||
if pinned_buttons or open_buttons:
|
||||
children.append(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
v_expand=False,
|
||||
h_expand=False,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
children.extend(pinned_buttons)
|
||||
if pinned_buttons and open_buttons:
|
||||
children.append(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
v_expand=False,
|
||||
h_expand=False,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
children.extend(open_buttons)
|
||||
else: # Right position
|
||||
children.extend(pinned_buttons)
|
||||
if pinned_buttons and open_buttons:
|
||||
children.append(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
v_expand=False,
|
||||
h_expand=False,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
children.extend(open_buttons)
|
||||
if pinned_buttons or open_buttons:
|
||||
children.append(
|
||||
Box(
|
||||
orientation=separator_orientation,
|
||||
v_expand=False,
|
||||
h_expand=False,
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
name="dock-separator",
|
||||
)
|
||||
)
|
||||
children.append(self.components)
|
||||
|
||||
self.view.children = children
|
||||
idle_add(self._update_size)
|
||||
@@ -821,7 +848,6 @@ class Dock(Window):
|
||||
self.is_mouse_over_dock_area
|
||||
or self._drag_in_progress
|
||||
or self._prevent_occlusion
|
||||
or not data.DOCK_AUTO_HIDE
|
||||
):
|
||||
if not self.dock_revealer.get_reveal_child():
|
||||
self.dock_revealer.set_reveal_child(True)
|
||||
@@ -908,51 +934,40 @@ class Dock(Window):
|
||||
return
|
||||
|
||||
def process_drag_end():
|
||||
# Check if dropped outside the dock by checking the pointer position
|
||||
display = self.get_display()
|
||||
seat = display.get_default_seat()
|
||||
pointer = seat.get_pointer()
|
||||
window = self.get_window()
|
||||
if self.get_mapped():
|
||||
display = Gdk.Display.get_default()
|
||||
_, x, y, _ = display.get_pointer()
|
||||
window = self.get_window()
|
||||
|
||||
# Only proceed if pointer is outside dock window
|
||||
if window:
|
||||
win_x, win_y, width, height = window.get_geometry()
|
||||
if not (win_x <= x <= win_x + width and win_y <= y <= win_y + height):
|
||||
app_id_dragged = widget.app_identifier
|
||||
instances_dragged = widget.instances
|
||||
|
||||
if window:
|
||||
screen, x, y = pointer.get_position() # Fix: Unpack all three values
|
||||
win_x, win_y = window.get_position()
|
||||
win_w = window.get_width()
|
||||
win_h = window.get_height()
|
||||
|
||||
# If pointer is outside dock window bounds
|
||||
if x < win_x or x > win_x + win_w or y < win_y or y > win_y + win_h:
|
||||
app_id_dragged = widget.app_identifier
|
||||
instances_dragged = widget.instances
|
||||
|
||||
app_index_dragged = -1
|
||||
for i, pinned_app_item in enumerate(self.pinned):
|
||||
if isinstance(app_id_dragged, dict) and isinstance(
|
||||
pinned_app_item, dict
|
||||
):
|
||||
if app_id_dragged.get("name") == pinned_app_item.get(
|
||||
"name"
|
||||
):
|
||||
# Remove pinned app
|
||||
app_index_dragged = -1
|
||||
for i, pinned_app_item in enumerate(self.pinned):
|
||||
if isinstance(app_id_dragged, dict) and isinstance(pinned_app_item, dict):
|
||||
if app_id_dragged.get("name") == pinned_app_item.get("name"):
|
||||
app_index_dragged = i
|
||||
break
|
||||
elif app_id_dragged == pinned_app_item:
|
||||
app_index_dragged = i
|
||||
break
|
||||
elif app_id_dragged == pinned_app_item:
|
||||
app_index_dragged = i
|
||||
break
|
||||
|
||||
if app_index_dragged >= 0:
|
||||
self.pinned.pop(app_index_dragged)
|
||||
self.config["pinned_apps"] = self.pinned
|
||||
self.update_pinned_apps_file()
|
||||
self.update_dock()
|
||||
elif instances_dragged:
|
||||
address = instances_dragged[0].get("address")
|
||||
if address:
|
||||
exec_shell_command(
|
||||
f"hyprctl dispatch focuswindow address:{address}"
|
||||
)
|
||||
|
||||
if app_index_dragged >= 0:
|
||||
self.pinned.pop(app_index_dragged)
|
||||
self.config["pinned_apps"] = self.pinned
|
||||
self.update_pinned_apps_file()
|
||||
self.update_dock()
|
||||
elif instances_dragged:
|
||||
address = instances_dragged[0].get("address")
|
||||
if address:
|
||||
exec_shell_command(f"hyprctl dispatch focuswindow address:{address}")
|
||||
|
||||
self._drag_in_progress = False
|
||||
self.check_occlusion_state()
|
||||
|
||||
GLib.idle_add(process_drag_end)
|
||||
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
import config.data as data
|
||||
from gi.repository import Gdk, GdkPixbuf, GLib, Gray, Gtk
|
||||
from fabric.widgets.box import Box
|
||||
import logging
|
||||
import gi
|
||||
|
||||
gi.require_version("Gray", "0.1")
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SystemTray(Box):
|
||||
def __init__(
|
||||
self, pixel_size: int = 20, refresh_interval: int = 1, **kwargs
|
||||
) -> None:
|
||||
orientation = (
|
||||
Gtk.Orientation.HORIZONTAL
|
||||
if not data.VERTICAL
|
||||
else Gtk.Orientation.VERTICAL
|
||||
)
|
||||
super().__init__(name="tray", orientation=orientation, spacing=8, **kwargs)
|
||||
self.enabled = True
|
||||
super().set_visible(False)
|
||||
self.pixel_size = pixel_size
|
||||
self.refresh_interval = refresh_interval
|
||||
|
||||
self.buttons_by_id = {}
|
||||
self.items_by_id = {}
|
||||
|
||||
self.watcher = Gray.Watcher()
|
||||
self.watcher.connect("item-added", self.on_watcher_item_added)
|
||||
|
||||
GLib.timeout_add_seconds(self.refresh_interval, self._refresh_all_items)
|
||||
|
||||
def set_visible(self, visible: bool):
|
||||
self.enabled = visible
|
||||
self._update_visibility()
|
||||
|
||||
def _update_visibility(self):
|
||||
has = len(self.get_children()) > 0
|
||||
super().set_visible(self.enabled and has)
|
||||
|
||||
def _get_item_pixbuf(self, item: Gray.Item) -> GdkPixbuf.Pixbuf:
|
||||
try:
|
||||
pm = Gray.get_pixmap_for_pixmaps(item.get_icon_pixmaps(), self.pixel_size)
|
||||
if pm:
|
||||
return pm.as_pixbuf(self.pixel_size, GdkPixbuf.InterpType.HYPER)
|
||||
|
||||
name = item.get_icon_name()
|
||||
theme = Gtk.IconTheme.new()
|
||||
path = item.get_icon_theme_path()
|
||||
if path:
|
||||
theme.prepend_search_path(path)
|
||||
return theme.load_icon(
|
||||
name, self.pixel_size, Gtk.IconLookupFlags.FORCE_SIZE
|
||||
)
|
||||
except GLib.Error as e:
|
||||
logger.debug(f"Icon load error {e}")
|
||||
return Gtk.IconTheme.get_default().load_icon(
|
||||
"image-missing", self.pixel_size, Gtk.IconLookupFlags.FORCE_SIZE
|
||||
)
|
||||
|
||||
def _refresh_item_ui(self, identifier: str, item: Gray.Item, button: Gtk.Button):
|
||||
pixbuf = self._get_item_pixbuf(item)
|
||||
img = button.get_image()
|
||||
if isinstance(img, Gtk.Image):
|
||||
img.set_from_pixbuf(pixbuf)
|
||||
else:
|
||||
new = Gtk.Image.new_from_pixbuf(pixbuf)
|
||||
button.set_image(new)
|
||||
new.show()
|
||||
tip = None
|
||||
if hasattr(item, "get_tooltip_text"):
|
||||
tip = item.get_tooltip_text()
|
||||
elif hasattr(item, "get_title"):
|
||||
tip = item.get_title()
|
||||
if tip:
|
||||
button.set_tooltip_text(tip)
|
||||
else:
|
||||
button.set_has_tooltip(False)
|
||||
|
||||
def _refresh_all_items(self) -> bool:
|
||||
for ident, item in self.items_by_id.items():
|
||||
btn = self.buttons_by_id.get(ident)
|
||||
if btn:
|
||||
self._refresh_item_ui(ident, item, btn)
|
||||
return True
|
||||
|
||||
def on_watcher_item_added(self, _, identifier: str):
|
||||
item = self.watcher.get_item_for_identifier(identifier)
|
||||
if not item:
|
||||
return
|
||||
|
||||
if identifier in self.buttons_by_id:
|
||||
self.buttons_by_id[identifier].destroy()
|
||||
del self.buttons_by_id[identifier]
|
||||
del self.items_by_id[identifier]
|
||||
|
||||
btn = self.do_bake_item_button(item)
|
||||
self.buttons_by_id[identifier] = btn
|
||||
self.items_by_id[identifier] = item
|
||||
|
||||
item.connect(
|
||||
"notify::icon-pixmaps",
|
||||
lambda itm, pspec: self._refresh_item_ui(identifier, itm, btn),
|
||||
)
|
||||
item.connect(
|
||||
"notify::icon-name",
|
||||
lambda itm, pspec: self._refresh_item_ui(identifier, itm, btn),
|
||||
)
|
||||
|
||||
try:
|
||||
item.connect(
|
||||
"updated", lambda itm: self._refresh_item_ui(identifier, itm, btn)
|
||||
)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
item.connect(
|
||||
"removed", lambda itm: self.on_item_instance_removed(identifier, itm)
|
||||
)
|
||||
|
||||
self.add(btn)
|
||||
btn.show_all()
|
||||
self._update_visibility()
|
||||
|
||||
def do_bake_item_button(self, item: Gray.Item) -> Gtk.Button:
|
||||
btn = Gtk.Button()
|
||||
btn.connect("button-press-event", lambda b, e: self.on_button_click(b, item, e))
|
||||
img = Gtk.Image.new_from_pixbuf(self._get_item_pixbuf(item))
|
||||
btn.set_image(img)
|
||||
tip = (
|
||||
item.get_tooltip_text()
|
||||
if hasattr(item, "get_tooltip_text")
|
||||
else getattr(item, "get_title", lambda: None)()
|
||||
)
|
||||
if tip:
|
||||
btn.set_tooltip_text(tip)
|
||||
return btn
|
||||
|
||||
def on_item_instance_removed(self, identifier: str, removed_item: Gray.Item):
|
||||
if self.items_by_id.get(identifier) is removed_item:
|
||||
btn = self.buttons_by_id.pop(identifier, None)
|
||||
self.items_by_id.pop(identifier, None)
|
||||
if btn:
|
||||
btn.destroy()
|
||||
self._update_visibility()
|
||||
|
||||
def on_button_click(
|
||||
self, button: Gtk.Button, item: Gray.Item, event: Gdk.EventButton
|
||||
):
|
||||
if event.button == Gdk.BUTTON_PRIMARY:
|
||||
try:
|
||||
item.activate(int(event.x_root), int(event.y_root))
|
||||
except Exception as e:
|
||||
logger.error(f"Activate error: {e}")
|
||||
elif event.button == Gdk.BUTTON_SECONDARY:
|
||||
menu = getattr(item, "get_menu", lambda: None)()
|
||||
if isinstance(menu, Gtk.Menu):
|
||||
menu.popup_at_widget(
|
||||
button, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, event
|
||||
)
|
||||
else:
|
||||
cm = getattr(item, "context_menu", None)
|
||||
if cm:
|
||||
try:
|
||||
cm(int(event.x_root), int(event.y_root))
|
||||
except Exception as e:
|
||||
logger.error(f"ContextMenu error: {e}")
|
||||
+10
-10
@@ -5,15 +5,15 @@ from fabric.widgets.label import Label
|
||||
|
||||
connection = Hyprland()
|
||||
|
||||
def create_workspace_widget():
|
||||
workspaceData = connection.send_command("j/activeworkspace").reply
|
||||
activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"]
|
||||
workspace_label = Label(label=f"{activeWorkspace}")
|
||||
workspaceData = connection.send_command("j/activeworkspace").reply
|
||||
activeWorkspace = json.loads(workspaceData.decode("utf-8"))["name"]
|
||||
workspace = Label(label=f"{activeWorkspace}")
|
||||
|
||||
def on_workspace(obj, signal):
|
||||
nonlocal workspace_label
|
||||
activeWorkspace = json.loads(signal.data[0])
|
||||
workspace_label.set_label(f"{activeWorkspace}")
|
||||
|
||||
connection.connect("event::workspace", on_workspace)
|
||||
return workspace_label
|
||||
def on_workspace(obj, signal):
|
||||
global activeWorkspace
|
||||
activeWorkspace = json.loads(signal.data[0])
|
||||
workspace.set_label(f"{activeWorkspace}")
|
||||
|
||||
|
||||
connection.connect("event::workspace", on_workspace)
|
||||
Reference in new issue
Block a user