From 1dd7de95eee17f6fb2f7ecdcdc01720375d8ef7e Mon Sep 17 00:00:00 2001 From: piotr Date: Wed, 13 Mar 2024 03:07:27 +0100 Subject: [PATCH 01/16] module just started --- nwg_panel/modules/keyboard_layout.py | 144 +++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 nwg_panel/modules/keyboard_layout.py diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py new file mode 100644 index 0000000..87cd264 --- /dev/null +++ b/nwg_panel/modules/keyboard_layout.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 + +import os +import subprocess + +import gi +from gi.repository import GLib + +from nwg_panel.tools import check_key, update_image, eprint, hyprctl + +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk, Gdk + + +class KeyboardLayout(Gtk.EventBox): + def __init__(self, settings, icons_path, executor_name): + self.name = executor_name + self.settings = settings + self.icons_path = icons_path + Gtk.EventBox.__init__(self) + self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0) + self.add(self.box) + self.image = Gtk.Image() + self.label = Gtk.Label.new("") + self.icon_path = None + + self.kb_layout = self.get_kb_layout() + + check_key(settings, "root-css-name", "root-executor") + check_key(settings, "css-name", "") + check_key(settings, "icon-placement", "left") + check_key(settings, "icon-size", 16) + check_key(settings, "tooltip-text", "") + check_key(settings, "angle", 0.0) + + self.label.set_angle(settings["angle"]) + + if settings["angle"] != 0.0: + self.box.set_orientation(Gtk.Orientation.VERTICAL) + + update_image(self.image, "input-keyboard", self.settings["icon-size"], self.icons_path) + + self.set_property("name", settings["root-css-name"]) + + if settings["css-name"]: + self.label.set_property("name", settings["css-name"]) + else: + self.label.set_property("name", "executor-label") + + if settings["tooltip-text"]: + self.set_tooltip_text(settings["tooltip-text"]) + + self.connect('button-press-event', self.on_button_press) + + self.connect('enter-notify-event', self.on_enter_notify_event) + self.connect('leave-notify-event', self.on_leave_notify_event) + + self.build_box() + self.refresh() + + def get_kb_layout(self): + option = hyprctl("j/getoption input:kb_layout") + if option and "str" in option: + return option["str"] + return "" + + def update_widget(self, output): + # parse output + label = new_path = None + if output: + output = [o.strip() for o in output] + if len(output) == 1: + if os.path.splitext(output[0])[1] in ('.svg', '.png'): + new_path = output[0] + else: + label = output[0] + elif len(output) == 2: + new_path, label = output + + # update widget contents + if new_path and new_path != self.icon_path: + try: + update_image(self.image, + new_path, + self.settings["icon-size"], + self.icons_path, + fallback=False) + self.icon_path = new_path + except: + print("Failed setting image from {}".format(new_path)) + new_path = None + + if label: + self.label.set_markup(label) + + # update widget visibility + if new_path: + if not self.image.get_visible(): + self.image.show() + else: + if self.image.get_visible(): + self.image.hide() + + if label: + if not self.label.get_visible(): + self.label.show() + else: + if self.label.get_visible(): + self.label.hide() + + return False + + def refresh(self): + if "script" in self.settings and self.settings["script"]: + try: + output = subprocess.check_output(self.settings["script"].split()).decode("utf-8").splitlines() + GLib.idle_add(self.update_widget, output) + except Exception as e: + eprint(e) + + def build_box(self): + if self.settings["icon-placement"] == "left": + self.box.pack_start(self.image, False, False, 2) + self.box.pack_start(self.label, False, False, 2) + if self.settings["icon-placement"] != "left": + self.box.pack_start(self.image, False, False, 2) + + def on_enter_notify_event(self, widget, event): + widget.set_state_flags(Gtk.StateFlags.DROP_ACTIVE, clear=False) + widget.set_state_flags(Gtk.StateFlags.SELECTED, clear=False) + + def on_leave_notify_event(self, widget, event): + widget.unset_state_flags(Gtk.StateFlags.DROP_ACTIVE) + widget.unset_state_flags(Gtk.StateFlags.SELECTED) + + def on_button_press(self, widget, event): + if event.button == 1 and self.settings["on-left-click"]: + self.launch(self.settings["on-left-click"]) + elif event.button == 2 and self.settings["on-middle-click"]: + self.launch(self.settings["on-middle-click"]) + elif event.button == 3 and self.settings["on-right-click"]: + self.launch(self.settings["on-right-click"]) From 363bf00aed0024ab711b0a7496a922010fbe336e Mon Sep 17 00:00:00 2001 From: piotr Date: Thu, 14 Mar 2024 03:46:46 +0100 Subject: [PATCH 02/16] list & switch --- nwg_panel/main.py | 10 ++ nwg_panel/modules/keyboard_layout.py | 134 +++++++++++++-------------- 2 files changed, 74 insertions(+), 70 deletions(-) diff --git a/nwg_panel/main.py b/nwg_panel/main.py index 19f870c..5520a70 100644 --- a/nwg_panel/main.py +++ b/nwg_panel/main.py @@ -48,6 +48,7 @@ from nwg_panel.modules.dwl_tags import DwlTags from nwg_panel.modules.swaync import SwayNC from nwg_panel.modules.sway_mode import SwayMode +from nwg_panel.modules.keyboard_layout import KeyboardLayout try: from nwg_panel.modules.openweather import OpenWeather @@ -350,6 +351,15 @@ def instantiate_content(panel, container, content_list, icons_path=""): else: eprint("'hyprland-workspaces' ignored") + if item == "keyboard-layout": + if his: + if "keyboard-layout" not in panel: + panel["keyboard-layout"] = {} + kb_layout = KeyboardLayout(panel["keyboard-layout"], icons_path) + container.pack_start(kb_layout, False, False, panel["items-padding"]) + else: + eprint("KeyboardLayout module does not yet support sway") + if "button-" in item: if item in panel: button = CustomButton(panel[item], icons_path) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index 87cd264..0f1b76b 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -1,10 +1,8 @@ #!/usr/bin/env python3 - -import os -import subprocess +import json +import time import gi -from gi.repository import GLib from nwg_panel.tools import check_key, update_image, eprint, hyprctl @@ -14,9 +12,23 @@ from gi.repository import Gtk, Gdk +def get_kb_layout(): + o = hyprctl("j/getoption input:kb_layout") + option = json.loads(o) + if option and "str" in option: + return option["str"].split(",") + return [] + + +def list_keyboards(): + o = hyprctl("j/devices") + devices = json.loads(o) + keyboards = devices["keyboards"] if "keyboards" in devices else [] + return keyboards + + class KeyboardLayout(Gtk.EventBox): - def __init__(self, settings, icons_path, executor_name): - self.name = executor_name + def __init__(self, settings, icons_path): self.settings = settings self.icons_path = icons_path Gtk.EventBox.__init__(self) @@ -26,8 +38,16 @@ def __init__(self, settings, icons_path, executor_name): self.label = Gtk.Label.new("") self.icon_path = None - self.kb_layout = self.get_kb_layout() + print("KeyboardLayout module") + self.kb_layout = get_kb_layout() + print(f"kb_layout = {self.kb_layout}") + self.keyboards = list_keyboards() + self.keyboard_names = [] + for k in self.keyboards: + self.keyboard_names.append(k["name"]) + print(f"keyboard_names = {self.keyboard_names}") + check_key(settings, "device-name", "all") check_key(settings, "root-css-name", "root-executor") check_key(settings, "css-name", "") check_key(settings, "icon-placement", "left") @@ -59,66 +79,25 @@ def __init__(self, settings, icons_path, executor_name): self.build_box() self.refresh() - - def get_kb_layout(self): - option = hyprctl("j/getoption input:kb_layout") - if option and "str" in option: - return option["str"] - return "" - - def update_widget(self, output): - # parse output - label = new_path = None - if output: - output = [o.strip() for o in output] - if len(output) == 1: - if os.path.splitext(output[0])[1] in ('.svg', '.png'): - new_path = output[0] - else: - label = output[0] - elif len(output) == 2: - new_path, label = output - - # update widget contents - if new_path and new_path != self.icon_path: - try: - update_image(self.image, - new_path, - self.settings["icon-size"], - self.icons_path, - fallback=False) - self.icon_path = new_path - except: - print("Failed setting image from {}".format(new_path)) - new_path = None - - if label: - self.label.set_markup(label) - - # update widget visibility - if new_path: - if not self.image.get_visible(): - self.image.show() + self.show_all() + + def get_current_layout(self): + if self.settings["device-name"] != "all": + for k in self.keyboards: + if k["name"] == self.settings["device-name"]: + return k["active_keymap"] + return "unknown" else: - if self.image.get_visible(): - self.image.hide() - - if label: - if not self.label.get_visible(): - self.label.show() - else: - if self.label.get_visible(): - self.label.hide() - - return False + for k in self.keyboards: + if "keyboard" in k["name"]: + return k["active_keymap"] + return self.keyboards[0]["layout"] def refresh(self): - if "script" in self.settings and self.settings["script"]: - try: - output = subprocess.check_output(self.settings["script"].split()).decode("utf-8").splitlines() - GLib.idle_add(self.update_widget, output) - except Exception as e: - eprint(e) + self.keyboards = list_keyboards() + label = self.get_current_layout() + if label: + self.label.set_text(label) def build_box(self): if self.settings["icon-placement"] == "left": @@ -135,10 +114,25 @@ def on_leave_notify_event(self, widget, event): widget.unset_state_flags(Gtk.StateFlags.DROP_ACTIVE) widget.unset_state_flags(Gtk.StateFlags.SELECTED) + def on_left_click(self): + if self.settings["device-name"] != "all": + hyprctl(f"switchxkblayout {self.settings['device-name']} next") + else: + for name in self.keyboard_names: + hyprctl(f"switchxkblayout {name} next") + self.refresh() + + def on_right_click(self): + menu = Gtk.Menu() + for i in range(len(self.kb_layout)): + item = Gtk.MenuItem.new_with_label(self.kb_layout[i]) + menu.append(item) + menu.set_reserve_toggle_size(False) + menu.show_all() + menu.popup_at_widget(self.label, Gdk.Gravity.STATIC, Gdk.Gravity.STATIC, None) + def on_button_press(self, widget, event): - if event.button == 1 and self.settings["on-left-click"]: - self.launch(self.settings["on-left-click"]) - elif event.button == 2 and self.settings["on-middle-click"]: - self.launch(self.settings["on-middle-click"]) - elif event.button == 3 and self.settings["on-right-click"]: - self.launch(self.settings["on-right-click"]) + if event.button == 1: + self.on_left_click() + elif event.button == 3: + self.on_right_click() From b953d3daf03630effa7d9848ebe2f033e630697c Mon Sep 17 00:00:00 2001 From: piotr Date: Fri, 15 Mar 2024 00:53:41 +0100 Subject: [PATCH 03/16] cleanup; compositor detection --- nwg_panel/modules/keyboard_layout.py | 86 ++++++++++++++++------------ 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index 0f1b76b..7c1d032 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import json -import time +import os import gi @@ -39,47 +39,56 @@ def __init__(self, settings, icons_path): self.icon_path = None print("KeyboardLayout module") - self.kb_layout = get_kb_layout() - print(f"kb_layout = {self.kb_layout}") - self.keyboards = list_keyboards() - self.keyboard_names = [] - for k in self.keyboards: - self.keyboard_names.append(k["name"]) - print(f"keyboard_names = {self.keyboard_names}") + if os.getenv("SWAYSOCK"): + self.compositor = "sway" + elif os.getenv("HYPRLAND_INSTANCE_SIGNATURE"): + self.compositor = "hyprland" + else: + self.compositor = "" + eprint("Neither sway nor Hyprland detected, this won't work") - check_key(settings, "device-name", "all") - check_key(settings, "root-css-name", "root-executor") - check_key(settings, "css-name", "") - check_key(settings, "icon-placement", "left") - check_key(settings, "icon-size", 16) - check_key(settings, "tooltip-text", "") - check_key(settings, "angle", 0.0) + if self.compositor: + self.kb_layouts = get_kb_layout() + print(f"kb_layout = {self.kb_layouts}") - self.label.set_angle(settings["angle"]) + self.keyboards = list_keyboards() + self.keyboard_names = [] + for k in self.keyboards: + self.keyboard_names.append(k["name"]) + print(f"keyboard_names = {self.keyboard_names}") - if settings["angle"] != 0.0: - self.box.set_orientation(Gtk.Orientation.VERTICAL) + check_key(settings, "device-name", "all") + check_key(settings, "root-css-name", "root-executor") + check_key(settings, "css-name", "") + check_key(settings, "icon-placement", "left") + check_key(settings, "icon-size", 16) + check_key(settings, "tooltip-text", "LMB: Next layout, RMB: Menu") + check_key(settings, "angle", 0.0) - update_image(self.image, "input-keyboard", self.settings["icon-size"], self.icons_path) + self.label.set_angle(settings["angle"]) - self.set_property("name", settings["root-css-name"]) + if settings["angle"] != 0.0: + self.box.set_orientation(Gtk.Orientation.VERTICAL) - if settings["css-name"]: - self.label.set_property("name", settings["css-name"]) - else: - self.label.set_property("name", "executor-label") + update_image(self.image, "input-keyboard", self.settings["icon-size"], self.icons_path) - if settings["tooltip-text"]: - self.set_tooltip_text(settings["tooltip-text"]) + self.set_property("name", settings["root-css-name"]) + if settings["css-name"]: + self.label.set_property("name", settings["css-name"]) + else: + self.label.set_property("name", "executor-label") - self.connect('button-press-event', self.on_button_press) + if settings["tooltip-text"]: + self.set_tooltip_text(settings["tooltip-text"]) - self.connect('enter-notify-event', self.on_enter_notify_event) - self.connect('leave-notify-event', self.on_leave_notify_event) + self.connect('button-press-event', self.on_button_press) - self.build_box() - self.refresh() - self.show_all() + self.connect('enter-notify-event', self.on_enter_notify_event) + self.connect('leave-notify-event', self.on_leave_notify_event) + + self.build_box() + self.refresh() + self.show_all() def get_current_layout(self): if self.settings["device-name"] != "all": @@ -101,10 +110,10 @@ def refresh(self): def build_box(self): if self.settings["icon-placement"] == "left": - self.box.pack_start(self.image, False, False, 2) - self.box.pack_start(self.label, False, False, 2) + self.box.pack_start(self.image, False, False, 6) + self.box.pack_start(self.label, False, False, 6) if self.settings["icon-placement"] != "left": - self.box.pack_start(self.image, False, False, 2) + self.box.pack_start(self.image, False, False, 6) def on_enter_notify_event(self, widget, event): widget.set_state_flags(Gtk.StateFlags.DROP_ACTIVE, clear=False) @@ -115,17 +124,20 @@ def on_leave_notify_event(self, widget, event): widget.unset_state_flags(Gtk.StateFlags.SELECTED) def on_left_click(self): + # apply to selected device if self.settings["device-name"] != "all": hyprctl(f"switchxkblayout {self.settings['device-name']} next") + # apply to all devices else: for name in self.keyboard_names: hyprctl(f"switchxkblayout {name} next") + self.refresh() def on_right_click(self): menu = Gtk.Menu() - for i in range(len(self.kb_layout)): - item = Gtk.MenuItem.new_with_label(self.kb_layout[i]) + for i in range(len(self.kb_layouts)): + item = Gtk.MenuItem.new_with_label(self.kb_layouts[i]) menu.append(item) menu.set_reserve_toggle_size(False) menu.show_all() From fee60a3c5f65a1c501dff1eac052a1fba2bdcc03 Mon Sep 17 00:00:00 2001 From: piotr Date: Fri, 15 Mar 2024 00:58:37 +0100 Subject: [PATCH 04/16] cleanup --- nwg_panel/modules/keyboard_layout.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index 7c1d032..f3cac88 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -27,6 +27,16 @@ def list_keyboards(): return keyboards +def on_enter_notify_event(widget, event): + widget.set_state_flags(Gtk.StateFlags.DROP_ACTIVE, clear=False) + widget.set_state_flags(Gtk.StateFlags.SELECTED, clear=False) + + +def on_leave_notify_event(widget, event): + widget.unset_state_flags(Gtk.StateFlags.DROP_ACTIVE) + widget.unset_state_flags(Gtk.StateFlags.SELECTED) + + class KeyboardLayout(Gtk.EventBox): def __init__(self, settings, icons_path): self.settings = settings @@ -82,9 +92,8 @@ def __init__(self, settings, icons_path): self.set_tooltip_text(settings["tooltip-text"]) self.connect('button-press-event', self.on_button_press) - - self.connect('enter-notify-event', self.on_enter_notify_event) - self.connect('leave-notify-event', self.on_leave_notify_event) + self.connect('enter-notify-event', on_enter_notify_event) + self.connect('leave-notify-event', on_leave_notify_event) self.build_box() self.refresh() @@ -115,16 +124,8 @@ def build_box(self): if self.settings["icon-placement"] != "left": self.box.pack_start(self.image, False, False, 6) - def on_enter_notify_event(self, widget, event): - widget.set_state_flags(Gtk.StateFlags.DROP_ACTIVE, clear=False) - widget.set_state_flags(Gtk.StateFlags.SELECTED, clear=False) - - def on_leave_notify_event(self, widget, event): - widget.unset_state_flags(Gtk.StateFlags.DROP_ACTIVE) - widget.unset_state_flags(Gtk.StateFlags.SELECTED) - def on_left_click(self): - # apply to selected device + # apply to selected device, if any if self.settings["device-name"] != "all": hyprctl(f"switchxkblayout {self.settings['device-name']} next") # apply to all devices From 39c97ecfb3a5b45dc186f2fc3ac5916a3113cd06 Mon Sep 17 00:00:00 2001 From: piotr Date: Fri, 15 Mar 2024 02:41:22 +0100 Subject: [PATCH 05/16] add sway support --- nwg_panel/main.py | 2 +- nwg_panel/modules/keyboard_layout.py | 92 +++++++++++++++++++--------- 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/nwg_panel/main.py b/nwg_panel/main.py index 5520a70..9d52c50 100644 --- a/nwg_panel/main.py +++ b/nwg_panel/main.py @@ -352,7 +352,7 @@ def instantiate_content(panel, container, content_list, icons_path=""): eprint("'hyprland-workspaces' ignored") if item == "keyboard-layout": - if his: + if his or sway: if "keyboard-layout" not in panel: panel["keyboard-layout"] = {} kb_layout = KeyboardLayout(panel["keyboard-layout"], icons_path) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index f3cac88..8feae12 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -12,21 +12,6 @@ from gi.repository import Gtk, Gdk -def get_kb_layout(): - o = hyprctl("j/getoption input:kb_layout") - option = json.loads(o) - if option and "str" in option: - return option["str"].split(",") - return [] - - -def list_keyboards(): - o = hyprctl("j/devices") - devices = json.loads(o) - keyboards = devices["keyboards"] if "keyboards" in devices else [] - return keyboards - - def on_enter_notify_event(widget, event): widget.set_state_flags(Gtk.StateFlags.DROP_ACTIVE, clear=False) widget.set_state_flags(Gtk.StateFlags.SELECTED, clear=False) @@ -50,21 +35,26 @@ def __init__(self, settings, icons_path): print("KeyboardLayout module") if os.getenv("SWAYSOCK"): + from i3ipc import Connection + self.i3 = Connection() self.compositor = "sway" elif os.getenv("HYPRLAND_INSTANCE_SIGNATURE"): - self.compositor = "hyprland" + self.compositor = "Hyprland" else: self.compositor = "" eprint("Neither sway nor Hyprland detected, this won't work") if self.compositor: - self.kb_layouts = get_kb_layout() + self.kb_layouts = self.get_kb_layout() print(f"kb_layout = {self.kb_layouts}") - self.keyboards = list_keyboards() + self.keyboards = self.list_keyboards() self.keyboard_names = [] for k in self.keyboards: - self.keyboard_names.append(k["name"]) + if self.compositor == "Hyprland": + self.keyboard_names.append(k["name"]) + else: + self.keyboard_names.append(k.identifier) print(f"keyboard_names = {self.keyboard_names}") check_key(settings, "device-name", "all") @@ -72,7 +62,10 @@ def __init__(self, settings, icons_path): check_key(settings, "css-name", "") check_key(settings, "icon-placement", "left") check_key(settings, "icon-size", 16) - check_key(settings, "tooltip-text", "LMB: Next layout, RMB: Menu") + if self.compositor == "Hyprland": + check_key(settings, "tooltip-text", "LMB: Next layout, RMB: Menu") + else: + check_key(settings, "tooltip-text", "") check_key(settings, "angle", 0.0) self.label.set_angle(settings["angle"]) @@ -99,20 +92,52 @@ def __init__(self, settings, icons_path): self.refresh() self.show_all() + def get_kb_layout(self): + if self.compositor == "Hyprland": + o = hyprctl("j/getoption input:kb_layout") + option = json.loads(o) + if option and "str" in option: + return option["str"].split(",") + return [] + + def list_keyboards(self): + if self.compositor == "Hyprland": + o = hyprctl("j/devices") + devices = json.loads(o) + keyboards = devices["keyboards"] if "keyboards" in devices else [] + else: + inputs = self.i3.get_inputs() + keyboards = [] + for i in inputs: + if i.type == "keyboard": + keyboards.append(i) + + return keyboards + def get_current_layout(self): if self.settings["device-name"] != "all": for k in self.keyboards: - if k["name"] == self.settings["device-name"]: - return k["active_keymap"] + if self.compositor == "Hyprland": + if k["name"] == self.settings["device-name"]: + return k["active_keymap"] + else: + if k.name == self.settings["device-name"]: + return k.xkb_active_layout_name return "unknown" else: - for k in self.keyboards: - if "keyboard" in k["name"]: - return k["active_keymap"] - return self.keyboards[0]["layout"] + if self.compositor == "Hyprland": + for k in self.keyboards: + if "keyboard" in k["name"]: + return k["active_keymap"] + return self.keyboards[0]["layout"] + else: + for k in self.keyboards: + if "keyboard" in k.name: + return k.xkb_active_layout_name + return self.keyboards[0].xkb_active_layout_name def refresh(self): - self.keyboards = list_keyboards() + self.keyboards = self.list_keyboards() label = self.get_current_layout() if label: self.label.set_text(label) @@ -127,11 +152,18 @@ def build_box(self): def on_left_click(self): # apply to selected device, if any if self.settings["device-name"] != "all": - hyprctl(f"switchxkblayout {self.settings['device-name']} next") + if self.compositor == "Hyprland": + hyprctl(f"switchxkblayout {self.settings['device-name']} next") + else: + self.i3.command(f'input "{self.settings["device-name"]}" xkb_switch_layout next') # apply to all devices else: for name in self.keyboard_names: - hyprctl(f"switchxkblayout {name} next") + if self.compositor == "Hyprland": + hyprctl(f"switchxkblayout {name} next") + else: + cmd = f'input "{name}" xkb_switch_layout next' + self.i3.command(f'input "{name}" xkb_switch_layout next') self.refresh() @@ -147,5 +179,5 @@ def on_right_click(self): def on_button_press(self, widget, event): if event.button == 1: self.on_left_click() - elif event.button == 3: + elif event.button == 3 and self.compositor == "Hyprland": self.on_right_click() From 7438990e4ba3e27d7755b228fad01e97705031de Mon Sep 17 00:00:00 2001 From: piotr Date: Sat, 16 Mar 2024 02:38:18 +0100 Subject: [PATCH 06/16] add on_menu_item() --- nwg_panel/modules/keyboard_layout.py | 69 ++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index 8feae12..ddac5d0 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -44,10 +44,9 @@ def __init__(self, settings, icons_path): self.compositor = "" eprint("Neither sway nor Hyprland detected, this won't work") - if self.compositor: - self.kb_layouts = self.get_kb_layout() - print(f"kb_layout = {self.kb_layouts}") + self.device_name = None + if self.compositor: self.keyboards = self.list_keyboards() self.keyboard_names = [] for k in self.keyboards: @@ -57,7 +56,14 @@ def __init__(self, settings, icons_path): self.keyboard_names.append(k.identifier) print(f"keyboard_names = {self.keyboard_names}") - check_key(settings, "device-name", "all") + self.kb_layouts = self.get_kb_layouts() + print(f"kb_layouts = {self.kb_layouts}") + + check_key(settings, "keyboard-device-sway", "") + check_key(settings, "keyboard-device-hyprland", "") + self.device_name = settings["keyboard-device-sway"] if self.compositor == "sway" else settings[ + "keyboard-device-hyprland"] + check_key(settings, "root-css-name", "root-executor") check_key(settings, "css-name", "") check_key(settings, "icon-placement", "left") @@ -92,14 +98,6 @@ def __init__(self, settings, icons_path): self.refresh() self.show_all() - def get_kb_layout(self): - if self.compositor == "Hyprland": - o = hyprctl("j/getoption input:kb_layout") - option = json.loads(o) - if option and "str" in option: - return option["str"].split(",") - return [] - def list_keyboards(self): if self.compositor == "Hyprland": o = hyprctl("j/devices") @@ -114,14 +112,30 @@ def list_keyboards(self): return keyboards + def get_kb_layouts(self): + if self.compositor == "Hyprland": + o = hyprctl("j/getoption input:kb_layout") + option = json.loads(o) + if option and "str" in option: + return option["str"].split(",") + return [] + else: + layout_names = [] + if self.keyboards: + for k in self.keyboards: + for name in k.xkb_layout_names: + if name not in layout_names: + layout_names.append(name) + return layout_names + def get_current_layout(self): - if self.settings["device-name"] != "all": + if self.device_name: for k in self.keyboards: if self.compositor == "Hyprland": - if k["name"] == self.settings["device-name"]: + if k["name"] == self.device_name: return k["active_keymap"] else: - if k.name == self.settings["device-name"]: + if k.identifier == self.device_name: return k.xkb_active_layout_name return "unknown" else: @@ -132,7 +146,7 @@ def get_current_layout(self): return self.keyboards[0]["layout"] else: for k in self.keyboards: - if "keyboard" in k.name: + if "keyboard" in k.identifier: return k.xkb_active_layout_name return self.keyboards[0].xkb_active_layout_name @@ -151,26 +165,41 @@ def build_box(self): def on_left_click(self): # apply to selected device, if any - if self.settings["device-name"] != "all": + if self.device_name: if self.compositor == "Hyprland": hyprctl(f"switchxkblayout {self.settings['device-name']} next") else: - self.i3.command(f'input "{self.settings["device-name"]}" xkb_switch_layout next') + self.i3.command(f'input "{self.device_name}" xkb_switch_layout next') # apply to all devices else: for name in self.keyboard_names: if self.compositor == "Hyprland": hyprctl(f"switchxkblayout {name} next") else: - cmd = f'input "{name}" xkb_switch_layout next' self.i3.command(f'input "{name}" xkb_switch_layout next') self.refresh() + def on_menu_item(self, item, idx): + if self.device_name: + if self.compositor == "Hyprland": + hyprctl(f'switchxkblayout {self.device_name} {idx}') + else: + self.i3.command(f'input "{self.device_name}" xkb_switch_layout {idx}') + else: + for name in self.keyboard_names: + if self.compositor == "Hyprland": + hyprctl(f'switchxkblayout {name} {idx}') + else: + self.i3.command(f'input "{name}" xkb_switch_layout {idx}') + + self.refresh() + def on_right_click(self): menu = Gtk.Menu() for i in range(len(self.kb_layouts)): item = Gtk.MenuItem.new_with_label(self.kb_layouts[i]) + item.connect("activate", self.on_menu_item, i) menu.append(item) menu.set_reserve_toggle_size(False) menu.show_all() @@ -179,5 +208,5 @@ def on_right_click(self): def on_button_press(self, widget, event): if event.button == 1: self.on_left_click() - elif event.button == 3 and self.compositor == "Hyprland": + elif event.button == 3: self.on_right_click() From 762723faca571c87420c2ed1996d9dc9d2776cb0 Mon Sep 17 00:00:00 2001 From: piotr Date: Sat, 16 Mar 2024 03:15:14 +0100 Subject: [PATCH 07/16] comments; box spacing --- nwg_panel/modules/keyboard_layout.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index ddac5d0..a06709e 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -68,6 +68,7 @@ def __init__(self, settings, icons_path): check_key(settings, "css-name", "") check_key(settings, "icon-placement", "left") check_key(settings, "icon-size", 16) + check_key(settings, "show-icon", True) if self.compositor == "Hyprland": check_key(settings, "tooltip-text", "LMB: Next layout, RMB: Menu") else: @@ -157,21 +158,21 @@ def refresh(self): self.label.set_text(label) def build_box(self): - if self.settings["icon-placement"] == "left": - self.box.pack_start(self.image, False, False, 6) - self.box.pack_start(self.label, False, False, 6) - if self.settings["icon-placement"] != "left": - self.box.pack_start(self.image, False, False, 6) + if self.settings["show-icon"] and self.settings["icon-placement"] == "left": + self.box.pack_start(self.image, False, False, 3) + self.box.pack_start(self.label, False, False, 3) + if self.settings["show-icon"] and self.settings["icon-placement"] != "left": + self.box.pack_start(self.image, False, False, 3) def on_left_click(self): - # apply to selected device, if any if self.device_name: + # apply to selected device, if any if self.compositor == "Hyprland": hyprctl(f"switchxkblayout {self.settings['device-name']} next") else: self.i3.command(f'input "{self.device_name}" xkb_switch_layout next') - # apply to all devices else: + # apply to all devices for name in self.keyboard_names: if self.compositor == "Hyprland": hyprctl(f"switchxkblayout {name} next") @@ -182,11 +183,13 @@ def on_left_click(self): def on_menu_item(self, item, idx): if self.device_name: + # apply to selected device, if any if self.compositor == "Hyprland": hyprctl(f'switchxkblayout {self.device_name} {idx}') else: self.i3.command(f'input "{self.device_name}" xkb_switch_layout {idx}') else: + # apply to all devices for name in self.keyboard_names: if self.compositor == "Hyprland": hyprctl(f'switchxkblayout {name} {idx}') From d8aac5da8b53e5d64b22dc8d5c6ac6b2d31baa49 Mon Sep 17 00:00:00 2001 From: piotr Date: Sun, 17 Mar 2024 01:48:02 +0100 Subject: [PATCH 08/16] filter out doubled devices --- nwg_panel/langs/en_US.json | 3 +++ nwg_panel/langs/pl_PL.json | 3 +++ nwg_panel/modules/keyboard_layout.py | 18 ++++++++---------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/nwg_panel/langs/en_US.json b/nwg_panel/langs/en_US.json index a2f31e5..d907e53 100644 --- a/nwg_panel/langs/en_US.json +++ b/nwg_panel/langs/en_US.json @@ -4,6 +4,7 @@ "add-new": "Add new", "add-to": "Add to", "alerts": "Alerts", + "all": "All", "all-outputs": "All outputs", "all-workspaces": "All workspaces", "always-show-icon": "Always show icon", @@ -65,6 +66,7 @@ "database": "Database", "delete-file": "Delete file", "delete-from-database": "Delete from database", + "device": "Device", "dwl-tags": "Dwl tags", "edit-panel": "edit panel", "editing": "Editing", @@ -99,6 +101,7 @@ "icons-size": "Icons size", "invert-slider": "Invert slider", "item-padding": "Item padding", + "keyboard-layout": "Keyboard layout", "label": "Label", "label-css-name": "Label CSS name", "label-length": "Label length", diff --git a/nwg_panel/langs/pl_PL.json b/nwg_panel/langs/pl_PL.json index 7310985..face26e 100644 --- a/nwg_panel/langs/pl_PL.json +++ b/nwg_panel/langs/pl_PL.json @@ -4,6 +4,7 @@ "add-new": "Dodaj nowy", "add-to": "Dodaj do", "alerts": "Ostrzeżenia", + "all": "Wszystkie", "all-outputs": "Wszystkie wyjścia", "all-workspaces": "Wszyskie obszary robocze", "always-show-icon": "Zawsze pokazuj ikonę", @@ -65,6 +66,7 @@ "database": "Baza danych", "delete-file": "Usuń plik", "delete-from-database": "Usuń z bazy", + "device": "Urządzenie", "dwl-tags": "Tagi dwl", "edit-panel": "edytuj panel", "editing": "Edytujesz", @@ -99,6 +101,7 @@ "icons-size": "Rozmiar ikon", "invert-slider": "Odwróć suwak", "item-padding": "Wypełnienie elementu", + "keyboard-layout": "Układ klawiatury", "label": "Etykieta", "label-css-name": "Nazwa CSS etykiety", "label-length": "Długość etykiety", diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index a06709e..e8724b4 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -44,20 +44,19 @@ def __init__(self, settings, icons_path): self.compositor = "" eprint("Neither sway nor Hyprland detected, this won't work") - self.device_name = None - if self.compositor: self.keyboards = self.list_keyboards() self.keyboard_names = [] for k in self.keyboards: if self.compositor == "Hyprland": self.keyboard_names.append(k["name"]) - else: + # On sway some devices may be listed twice, let's add them just once + elif k.identifier not in self.keyboard_names: self.keyboard_names.append(k.identifier) - print(f"keyboard_names = {self.keyboard_names}") + # print(f"keyboard_names = {self.keyboard_names}") self.kb_layouts = self.get_kb_layouts() - print(f"kb_layouts = {self.kb_layouts}") + # print(f"kb_layouts = {self.kb_layouts}") check_key(settings, "keyboard-device-sway", "") check_key(settings, "keyboard-device-hyprland", "") @@ -69,10 +68,7 @@ def __init__(self, settings, icons_path): check_key(settings, "icon-placement", "left") check_key(settings, "icon-size", 16) check_key(settings, "show-icon", True) - if self.compositor == "Hyprland": - check_key(settings, "tooltip-text", "LMB: Next layout, RMB: Menu") - else: - check_key(settings, "tooltip-text", "") + check_key(settings, "tooltip-text", "LMB: Next layout, RMB: Menu") check_key(settings, "angle", 0.0) self.label.set_angle(settings["angle"]) @@ -168,8 +164,9 @@ def on_left_click(self): if self.device_name: # apply to selected device, if any if self.compositor == "Hyprland": - hyprctl(f"switchxkblayout {self.settings['device-name']} next") + hyprctl(f"switchxkblayout {self.device_name} next") else: + print(f'input "{self.device_name}" xkb_switch_layout next') self.i3.command(f'input "{self.device_name}" xkb_switch_layout next') else: # apply to all devices @@ -177,6 +174,7 @@ def on_left_click(self): if self.compositor == "Hyprland": hyprctl(f"switchxkblayout {name} next") else: + print(f'input "{name}" xkb_switch_layout next') self.i3.command(f'input "{name}" xkb_switch_layout next') self.refresh() From bbeac1059db356f55922d191fe8d08d77fbdcc7e Mon Sep 17 00:00:00 2001 From: piotr Date: Sun, 17 Mar 2024 01:53:20 +0100 Subject: [PATCH 09/16] remove verbose lines --- nwg_panel/modules/keyboard_layout.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index e8724b4..772c3b1 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -33,7 +33,6 @@ def __init__(self, settings, icons_path): self.label = Gtk.Label.new("") self.icon_path = None - print("KeyboardLayout module") if os.getenv("SWAYSOCK"): from i3ipc import Connection self.i3 = Connection() From 0f88051c46fefa2bc6d3a29e21ef5a3611e8e93d Mon Sep 17 00:00:00 2001 From: piotr Date: Mon, 18 Mar 2024 03:00:23 +0100 Subject: [PATCH 10/16] add keyboard layout config --- nwg_panel/config.py | 110 ++++++++- nwg_panel/glade/config_keyboard_layout.glade | 231 +++++++++++++++++++ nwg_panel/glade/config_main.glade | 23 ++ nwg_panel/langs/en_US.json | 1 + nwg_panel/langs/pl_PL.json | 1 + 5 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 nwg_panel/glade/config_keyboard_layout.glade diff --git a/nwg_panel/config.py b/nwg_panel/config.py index d24d2f6..694f62c 100644 --- a/nwg_panel/config.py +++ b/nwg_panel/config.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 +import json import os import signal import subprocess @@ -12,13 +13,14 @@ from gi.repository import Gtk, Gdk, GLib from nwg_panel.tools import get_config_dir, local_dir, load_json, save_json, load_string, list_outputs, check_key, \ - list_configs, update_gtk_entry, is_command, check_commands, cmd2string, eprint, temp_dir, load_shell_data + list_configs, update_gtk_entry, is_command, check_commands, cmd2string, eprint, temp_dir, load_shell_data, hyprctl from nwg_panel.__about__ import __version__ dir_name = os.path.dirname(__file__) sway = os.getenv('SWAYSOCK') is not None +hyprland = os.getenv("HYPRLAND_INSTANCE_SIGNATURE") config_dir = get_config_dir() data_home = os.getenv('XDG_DATA_HOME') if os.getenv('XDG_DATA_HOME') else os.path.join(os.getenv("HOME"), @@ -724,6 +726,7 @@ def __init__(self, parent, file, panel_idx, plugin_menu_start): builder.get_object("hyprland-taskbar").set_text(voc["hyprland-taskbar"]) builder.get_object("hyprland-workspaces").set_text(voc["hyprland-workspaces"]) builder.get_object("brightness-slider").set_text(voc["brightness-slider"]) + builder.get_object("keyboard-layout").set_text(voc["keyboard-layout"]) builder.get_object("executors").set_text(voc["executors"]) builder.get_object("buttons").set_text(voc["buttons"]) builder.get_object("menu-start").set_text(voc["menu-start"]) @@ -751,6 +754,7 @@ def __init__(self, parent, file, panel_idx, plugin_menu_start): "dwl-tags", "hyprland-taskbar", "hyprland-workspaces", + "keyboard-layout", "tray" ] @@ -788,6 +792,9 @@ def __init__(self, parent, file, panel_idx, plugin_menu_start): builder.get_object("eb-dwl-tags").connect("button-press-event", self.edit_dwl_tags) builder.get_object("eb-hyprland-taskbar").connect("button-press-event", self.edit_hyprland_taskbar) builder.get_object("eb-hyprland-workspaces").connect("button-press-event", self.edit_hyprland_workspaces) + + builder.get_object("eb-keyboard-layout").connect("button-press-event", self.edit_keyboard_layout) + builder.get_object("eb-executors").connect("button-press-event", self.select_executor) builder.get_object("eb-buttons").connect("button-press-event", self.select_button) @@ -1197,6 +1204,8 @@ def apply_changes(self, *args): self.update_hyprland_taskbar() elif self.edited == "hyprland-workspaces": self.update_hyprland_workspaces() + elif self.edited == "keyboard-layout": + self.update_keyboard_layout() elif self.edited == "openweather": self.update_openweather() elif self.edited == "brightness-slider": @@ -2178,6 +2187,105 @@ def update_hyprland_workspaces(self): save_json(self.config, self.file) + def edit_keyboard_layout(self, *args): + self.load_panel() + self.edited = "keyboard-layout" + check_key(self.panel, "keyboard-layout", {}) + settings = self.panel["keyboard-layout"] + defaults = { + "keyboard-device-sway": "", + "keyboard-device-hyprland": "", + "root-css-name": "root-executor", + "css-name": "executor", + "show-icon": True, + "icon-size": 16, + "icon-placement": "left", + "tooltip-text": "LMB: Next layout, RMB: Menu", + "angle": 0.0 + } + for key in defaults: + check_key(settings, key, defaults[key]) + + builder = Gtk.Builder.new_from_file(os.path.join(dir_name, "glade/config_keyboard_layout.glade")) + builder.get_object("lbl-device").set_text("{}:".format(voc["device"])) + builder.get_object("lbl-tooltip-text").set_text("{}:".format(voc["tooltip-text"])) + builder.get_object("lbl-root-css-name").set_text("{}:".format(voc["root-css-name"])) + builder.get_object("lbl-css-name").set_text("{}:".format(voc["css-name"])) + builder.get_object("lbl-icon-placement").set_text("{}:".format(voc["icon-placement"])) + builder.get_object("lbl-icon-size").set_text("{}:".format(voc["icon-size"])) + builder.get_object("show-icon").set_label("{}".format(voc["show-icon"])) + builder.get_object("lbl-angle").set_text("{}:".format(voc["angle"])) + + frame = builder.get_object("frame") + frame.set_label(" {}: KeyboardLayout ".format(voc["module"])) + + self.kl_combo_device = builder.get_object("device") + if sway: + from i3ipc import Connection + i3 = Connection() + inputs = i3.get_inputs() + self.kl_combo_device.append("", voc["all"]) + for i in inputs: + if i.type == "keyboard": + self.kl_combo_device.append(i, i) + self.kl_combo_device.set_active_id(settings["keyboard-device-sway"]) + else: + o = hyprctl("j/devices") + devices = json.loads(o) + keyboards = devices["keyboards"] if "keyboards" in devices else [] + self.kl_combo_device.append("", voc["all"]) + for k in keyboards: + self.kl_combo_device.append(k["name"], k["name"]) + self.kl_combo_device.set_active_id(settings["keyboard-device-hyprland"]) + + self.kl_tooltip_text = builder.get_object("tooltip-text") + self.kl_tooltip_text.set_text(settings["tooltip-text"]) + + self.kl_root_css_name = builder.get_object("root-css-name") + self.kl_root_css_name.set_text(settings["root-css-name"]) + + self.kl_css_name = builder.get_object("css-name") + self.kl_css_name.set_text(settings["css-name"]) + + self.kl_icon_placement = builder.get_object("icon-placement") + self.kl_icon_placement.set_active_id(settings["icon-placement"]) + + self.kl_icon_size = builder.get_object("icon-size") + self.kl_icon_size.set_numeric(True) + adj = Gtk.Adjustment(value=0, lower=8, upper=129, step_increment=1, page_increment=10, page_size=1) + self.kl_icon_size.configure(adj, 1, 0) + self.kl_icon_size.set_value(settings["icon-size"]) + + self.ws_angle = builder.get_object("angle") + self.ws_angle.set_tooltip_text(voc["angle-tooltip"]) + self.ws_angle.set_active_id(str(settings["angle"])) + + self.cb_show_icon = builder.get_object("show-icon") + self.cb_show_icon.set_active(settings["show-icon"]) + + for item in self.scrolled_window.get_children(): + item.destroy() + self.scrolled_window.add(frame) + + def update_keyboard_layout(self): + settings = self.panel["keyboard-layout"] + if sway: + settings["keyboard-device-sway"] = self.kl_combo_device.get_active_id() + elif hyprland: + settings["keyboard-device-hyprland"] = self.kl_combo_device.get_active_id() + settings["tooltip-text"] = self.kl_tooltip_text.get_text() + settings["root-css-name"] = self.kl_root_css_name.get_text() + settings["css-name"] = self.kl_css_name.get_text() + settings["icon-placement"] = self.kl_icon_placement.get_active_id() + settings["icon-size"] = self.kl_icon_size.get_value() + settings["show-icon"] = self.cb_show_icon.get_active() + try: + settings["angle"] = float(self.ws_angle.get_active_id()) + except: + settings["angle"] = 0.0 + + save_json(self.config, self.file) + def edit_menu_start(self, *args): self.load_panel() self.edited = "menu-start" diff --git a/nwg_panel/glade/config_keyboard_layout.glade b/nwg_panel/glade/config_keyboard_layout.glade new file mode 100644 index 0000000..14ef875 --- /dev/null +++ b/nwg_panel/glade/config_keyboard_layout.glade @@ -0,0 +1,231 @@ + + + + + + True + False + 0.5 + out + + + + True + False + 6 + 6 + 6 + 6 + 6 + 12 + + + True + False + start + <span size="small"><b>Note:</b> on sway switching lang for one keyboard device selects the same value for the others. +Either it's a bug or I don't understand 'man sway-input' ¯\_(•_•)_/¯</span> + True + + + 0 + 9 + 2 + + + + + True + True + + + 1 + 1 + + + + + True + False + end + Tooltip text: + + + 0 + 1 + + + + + True + True + + + 1 + 2 + + + + + True + False + end + Root CSS name: + + + 0 + 2 + + + + + True + True + + + 1 + 3 + + + + + True + False + end + CSS name: + + + 0 + 3 + + + + + True + False + + left + right + + + + 1 + 4 + + + + + True + False + end + Icon placement: + + + 0 + 4 + + + + + True + True + + + 1 + 5 + + + + + True + False + end + Icon size: + + + 0 + 5 + + + + + Show icon + True + True + False + True + + + 1 + 6 + + + + + True + False + + + 90° + 270° + + + + 1 + 7 + + + + + True + False + end + Angle: + + + 0 + 7 + + + + + True + False + end + Device: + + + 0 + 8 + + + + + True + False + + + 1 + 8 + + + + + + + + + + + + + + + + True + False + Module: Executor + + + + diff --git a/nwg_panel/glade/config_main.glade b/nwg_panel/glade/config_main.glade index 2547a30..fd27d9c 100644 --- a/nwg_panel/glade/config_main.glade +++ b/nwg_panel/glade/config_main.glade @@ -434,6 +434,29 @@ + + + True + True + False + + + True + False + + + True + False + start + 6 + 6 + Keyboard layout + + + + + + True diff --git a/nwg_panel/langs/en_US.json b/nwg_panel/langs/en_US.json index d907e53..0044d4f 100644 --- a/nwg_panel/langs/en_US.json +++ b/nwg_panel/langs/en_US.json @@ -253,6 +253,7 @@ "units": "Units", "use-signal": "Use signal", "user-menu": "User menu", + "values-in-widget":"Values in widget", "values-in-widget-tooltip": "Show value in the panel widget", "vertical-padding": "Vertical padding", "vertical-window-margin": "Vertical window margin", diff --git a/nwg_panel/langs/pl_PL.json b/nwg_panel/langs/pl_PL.json index face26e..af56e5a 100644 --- a/nwg_panel/langs/pl_PL.json +++ b/nwg_panel/langs/pl_PL.json @@ -253,6 +253,7 @@ "units": "Jednostki", "use-signal": "Używaj sygnału", "user-menu": "Menu użytkownika", + "values-in-widget":"Wartości w widgecie", "values-in-widget-tooltip": "Pokazuj wartość w widgecie panelu", "vertical-padding": "Wypełnienie pionowe", "vertical-window-margin": "Pionowy margines okna", From 0e276009ce6ffe30dc5f92cd27a9f232d2b88373 Mon Sep 17 00:00:00 2001 From: piotr Date: Tue, 19 Mar 2024 00:36:01 +0100 Subject: [PATCH 11/16] use device identifier --- nwg_panel/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nwg_panel/config.py b/nwg_panel/config.py index 694f62c..afdccaf 100644 --- a/nwg_panel/config.py +++ b/nwg_panel/config.py @@ -2227,7 +2227,7 @@ def edit_keyboard_layout(self, *args): self.kl_combo_device.append("", voc["all"]) for i in inputs: if i.type == "keyboard": - self.kl_combo_device.append(i, i) + self.kl_combo_device.append(i.identifier, i.identifier) self.kl_combo_device.set_active_id(settings["keyboard-device-sway"]) else: o = hyprctl("j/devices") From 2043436e09bcb43cc5740e0e7267646c5628c3ca Mon Sep 17 00:00:00 2001 From: piotr Date: Tue, 19 Mar 2024 01:09:11 +0100 Subject: [PATCH 12/16] change Note --- nwg_panel/glade/config_keyboard_layout.glade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nwg_panel/glade/config_keyboard_layout.glade b/nwg_panel/glade/config_keyboard_layout.glade index 14ef875..a6555bb 100644 --- a/nwg_panel/glade/config_keyboard_layout.glade +++ b/nwg_panel/glade/config_keyboard_layout.glade @@ -23,8 +23,8 @@ True False start - <span size="small"><b>Note:</b> on sway switching lang for one keyboard device selects the same value for the others. -Either it's a bug or I don't understand 'man sway-input' ¯\_(•_•)_/¯</span> + <span size="small"><b>Note:</b> on sway switching layouts on one keyboard device affects the others +on some random basis (tested on sway 1.9). Better use "All" devices ¯\_(•_•)_/¯</span> True From a0e1ff6ca28514ca8ef635c55616747c16f69e2c Mon Sep 17 00:00:00 2001 From: piotr Date: Tue, 19 Mar 2024 02:13:15 +0100 Subject: [PATCH 13/16] simplify sway side --- nwg_panel/config.py | 14 +++-- nwg_panel/glade/config_keyboard_layout.glade | 6 +- nwg_panel/modules/keyboard_layout.py | 65 +++++++++----------- 3 files changed, 40 insertions(+), 45 deletions(-) diff --git a/nwg_panel/config.py b/nwg_panel/config.py index afdccaf..32b2e25 100644 --- a/nwg_panel/config.py +++ b/nwg_panel/config.py @@ -2225,11 +2225,13 @@ def edit_keyboard_layout(self, *args): i3 = Connection() inputs = i3.get_inputs() self.kl_combo_device.append("", voc["all"]) - for i in inputs: - if i.type == "keyboard": - self.kl_combo_device.append(i.identifier, i.identifier) - self.kl_combo_device.set_active_id(settings["keyboard-device-sway"]) - else: + # for i in inputs: + # if i.type == "keyboard": + # self.kl_combo_device.append(i.identifier, i.identifier) + # self.kl_combo_device.set_active_id(settings["keyboard-device-sway"]) + self.kl_combo_device.set_active_id("") + self.kl_combo_device.set_sensitive(False) + elif hyprland: o = hyprctl("j/devices") devices = json.loads(o) keyboards = devices["keyboards"] if "keyboards" in devices else [] @@ -2238,6 +2240,8 @@ def edit_keyboard_layout(self, *args): self.kl_combo_device.append(k["name"], k["name"]) self.kl_combo_device.set_active_id(settings["keyboard-device-hyprland"]) + builder.get_object("note").hide() + self.kl_tooltip_text = builder.get_object("tooltip-text") self.kl_tooltip_text.set_text(settings["tooltip-text"]) diff --git a/nwg_panel/glade/config_keyboard_layout.glade b/nwg_panel/glade/config_keyboard_layout.glade index a6555bb..1d8c0b6 100644 --- a/nwg_panel/glade/config_keyboard_layout.glade +++ b/nwg_panel/glade/config_keyboard_layout.glade @@ -19,12 +19,12 @@ 6 12 - + True False start - <span size="small"><b>Note:</b> on sway switching layouts on one keyboard device affects the others -on some random basis (tested on sway 1.9). Better use "All" devices ¯\_(•_•)_/¯</span> + <span size="small"><b>Note:</b> on sway switching layouts for a certain keyboard device does not work. +We will be switching for just 'type:keyboard' ¯\_(•_•)_/¯</span> True diff --git a/nwg_panel/modules/keyboard_layout.py b/nwg_panel/modules/keyboard_layout.py index 772c3b1..86dabc1 100644 --- a/nwg_panel/modules/keyboard_layout.py +++ b/nwg_panel/modules/keyboard_layout.py @@ -115,7 +115,7 @@ def get_kb_layouts(self): if option and "str" in option: return option["str"].split(",") return [] - else: + elif self.compositor == "sway": layout_names = [] if self.keyboards: for k in self.keyboards: @@ -125,26 +125,23 @@ def get_kb_layouts(self): return layout_names def get_current_layout(self): - if self.device_name: - for k in self.keyboards: - if self.compositor == "Hyprland": + if self.compositor == "Hyprland": + if self.device_name: + for k in self.keyboards: if k["name"] == self.device_name: return k["active_keymap"] - else: - if k.identifier == self.device_name: - return k.xkb_active_layout_name - return "unknown" - else: - if self.compositor == "Hyprland": + return "unknown" + else: for k in self.keyboards: if "keyboard" in k["name"]: return k["active_keymap"] return self.keyboards[0]["layout"] - else: - for k in self.keyboards: - if "keyboard" in k.identifier: - return k.xkb_active_layout_name - return self.keyboards[0].xkb_active_layout_name + elif self.compositor == "sway": + for k in self.keyboards: + if "keyboard" in k.identifier: + return k.xkb_active_layout_name + return self.keyboards[0].xkb_active_layout_name + return "unknown" def refresh(self): self.keyboards = self.list_keyboards() @@ -160,38 +157,32 @@ def build_box(self): self.box.pack_start(self.image, False, False, 3) def on_left_click(self): - if self.device_name: - # apply to selected device, if any - if self.compositor == "Hyprland": + if self.compositor == "Hyprland": + if self.device_name: + # apply to selected device hyprctl(f"switchxkblayout {self.device_name} next") else: - print(f'input "{self.device_name}" xkb_switch_layout next') - self.i3.command(f'input "{self.device_name}" xkb_switch_layout next') - else: - # apply to all devices - for name in self.keyboard_names: - if self.compositor == "Hyprland": + # apply to all devices + for name in self.keyboard_names: hyprctl(f"switchxkblayout {name} next") - else: - print(f'input "{name}" xkb_switch_layout next') - self.i3.command(f'input "{name}" xkb_switch_layout next') + elif self.compositor == "sway": + # apply to all devices of type:keyboard + self.i3.command(f'input type:keyboard xkb_switch_layout next') self.refresh() def on_menu_item(self, item, idx): - if self.device_name: - # apply to selected device, if any - if self.compositor == "Hyprland": + if self.compositor == "Hyprland": + if self.device_name: + # apply to selected device hyprctl(f'switchxkblayout {self.device_name} {idx}') else: - self.i3.command(f'input "{self.device_name}" xkb_switch_layout {idx}') - else: - # apply to all devices - for name in self.keyboard_names: - if self.compositor == "Hyprland": + # apply to all devices + for name in self.keyboard_names: hyprctl(f'switchxkblayout {name} {idx}') - else: - self.i3.command(f'input "{name}" xkb_switch_layout {idx}') + elif self.compositor == "sway": + # apply to all devices of type:keyboard + self.i3.command(f'input type:keyboard xkb_switch_layout {idx}') self.refresh() From bd184344a0a21cadc3278cbdb1280e6f258fb40d Mon Sep 17 00:00:00 2001 From: piotr Date: Tue, 19 Mar 2024 02:21:27 +0100 Subject: [PATCH 14/16] simplify sway side --- nwg_panel/config.py | 11 ++++------- nwg_panel/glade/config_keyboard_layout.glade | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/nwg_panel/config.py b/nwg_panel/config.py index 32b2e25..5809848 100644 --- a/nwg_panel/config.py +++ b/nwg_panel/config.py @@ -2193,7 +2193,6 @@ def edit_keyboard_layout(self, *args): check_key(self.panel, "keyboard-layout", {}) settings = self.panel["keyboard-layout"] defaults = { - "keyboard-device-sway": "", "keyboard-device-hyprland": "", "root-css-name": "root-executor", "css-name": "executor", @@ -2221,9 +2220,9 @@ def edit_keyboard_layout(self, *args): self.kl_combo_device = builder.get_object("device") if sway: - from i3ipc import Connection - i3 = Connection() - inputs = i3.get_inputs() + # from i3ipc import Connection + # i3 = Connection() + # inputs = i3.get_inputs() self.kl_combo_device.append("", voc["all"]) # for i in inputs: # if i.type == "keyboard": @@ -2273,9 +2272,7 @@ def edit_keyboard_layout(self, *args): def update_keyboard_layout(self): settings = self.panel["keyboard-layout"] - if sway: - settings["keyboard-device-sway"] = self.kl_combo_device.get_active_id() - elif hyprland: + if hyprland: settings["keyboard-device-hyprland"] = self.kl_combo_device.get_active_id() settings["tooltip-text"] = self.kl_tooltip_text.get_text() settings["root-css-name"] = self.kl_root_css_name.get_text() diff --git a/nwg_panel/glade/config_keyboard_layout.glade b/nwg_panel/glade/config_keyboard_layout.glade index 1d8c0b6..0a6f710 100644 --- a/nwg_panel/glade/config_keyboard_layout.glade +++ b/nwg_panel/glade/config_keyboard_layout.glade @@ -24,7 +24,7 @@ False start <span size="small"><b>Note:</b> on sway switching layouts for a certain keyboard device does not work. -We will be switching for just 'type:keyboard' ¯\_(•_•)_/¯</span> +We will be switching for devices of 'type:keyboard' ¯\_(•_•)_/¯</span> True From d9f358f073b1ae8981c6c9756adb0cd8c2556486 Mon Sep 17 00:00:00 2001 From: piotr Date: Tue, 19 Mar 2024 02:22:20 +0100 Subject: [PATCH 15/16] bump to 0.9.26 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c6f7901..ddf8f55 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ def read(f_name): setup( name='nwg-panel', - version='0.9.25', + version='0.9.26', description='GTK3-based panel for sway and Hyprland Wayland compositors', packages=find_packages(), include_package_data=True, From 11e3d816786ef45db2406cf0998f3b582b3f4398 Mon Sep 17 00:00:00 2001 From: piotr Date: Wed, 20 Mar 2024 00:28:31 +0100 Subject: [PATCH 16/16] mention KeyboardLayout module --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 53707be..59c35e4 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ buttons - **Scratchpad**: displays info on current scratchpad content and allows to open scratchpad windows - **SwayMode**: a simple indicator of a sway mode other than "default" - **Tray**: SNI system tray module +- **KeyboardLayout**: keyboard layout switcher, between values defined as `xkb_layout` (sway) or `kb_layout` (Hyprland). +Use commas to separate values, e.g. `pl,us,de`. ## Installation