diff --git a/nwg_panel/config.py b/nwg_panel/config.py index 420ba35d..775bf613 100644 --- a/nwg_panel/config.py +++ b/nwg_panel/config.py @@ -1230,10 +1230,6 @@ def edit_sway_taskbar(self, *args): self.ckb_show_layout.set_label(voc["show-layout"]) self.ckb_show_layout.set_active(settings["show-layout"]) - self.ckb_hide_empty = builder.get_object("hide-empty") - self.ckb_hide_empty.set_label(voc["hide-empty"]) - self.ckb_hide_empty.set_active(settings["hide-empty"]) - self.workspace_buttons = builder.get_object("workspace-buttons") self.workspace_buttons.set_label(voc["workspaces-as-buttons"]) self.workspace_buttons.set_active(settings["workspace-buttons"]) @@ -1288,7 +1284,6 @@ def update_sway_taskbar(self): settings["show-app-icon"] = self.ckb_show_app_icon.get_active() settings["show-app-name"] = self.ckb_show_app_name.get_active() settings["show-layout"] = self.ckb_show_layout.get_active() - settings["hide-empty"] = self.ckb_hide_empty.get_active() settings["workspace-buttons"] = self.workspace_buttons.get_active() settings["all-workspaces"] = self.ckb_all_workspaces.get_active() settings["mark-autotiling"] = self.ckb_mark_autotiling.get_active() @@ -1752,7 +1747,9 @@ def edit_sway_workspaces(self, *args): "mark-autotiling": True, "mark-content": True, "show-layout": True, - "angle": 0.0 + "angle": 0.0, + "hide-empty": False, + "hide-other-outputs": False, } for key in defaults: check_key(settings, key, defaults[key]) @@ -1801,6 +1798,14 @@ def edit_sway_workspaces(self, *args): self.ws_show_name.set_label(voc["show-window-name"]) self.ws_show_name.set_active(settings["show-name"]) + self.ws_hide_empty = builder.get_object("hide-empty") + self.ws_hide_empty.set_label(voc["hide-empty"]) + self.ws_hide_empty.set_active(settings["hide-empty"]) + + self.ws_hide_other_outputs = builder.get_object("hide-other-outputs") + self.ws_hide_other_outputs.set_label(voc["hide-other-outputs"]) + self.ws_hide_other_outputs.set_active(settings["hide-other-outputs"]) + self.ws_image_size = builder.get_object("image-size") self.ws_image_size.set_numeric(True) adj = Gtk.Adjustment(value=0, lower=8, upper=129, step_increment=1, page_increment=10, page_size=1) @@ -1837,8 +1842,11 @@ def update_sway_workspaces(self): settings = self.panel["sway-workspaces"] val = self.eb_workspaces_menu.get_text() - if val: + if val is not None: + print('numbers', repr(settings["numbers"]), repr(val.split())) settings["numbers"] = val.split() + print('numbers', repr(settings["numbers"]), repr(val.split())) + val = self.ws_custom_labels.get_text() settings["custom-labels"] = val.split() @@ -1854,6 +1862,14 @@ def update_sway_workspaces(self): if val is not None: settings["show-name"] = val + val = self.ws_hide_other_outputs.get_active() + if val is not None: + settings["hide-other-outputs"] = val + + val = self.ws_hide_empty.get_active() + if val is not None: + settings["hide-empty"] = val + settings["image-size"] = int(self.ws_image_size.get_value()) settings["name-length"] = int(self.ws_name_length.get_value()) diff --git a/nwg_panel/glade/config_sway_workspaces.glade b/nwg_panel/glade/config_sway_workspaces.glade index 0923b8a7..9a9f29b4 100644 --- a/nwg_panel/glade/config_sway_workspaces.glade +++ b/nwg_panel/glade/config_sway_workspaces.glade @@ -154,20 +154,6 @@ 8 - - - Hide empty workspaces - True - True - False - start - True - - - 1 - 8 - - True @@ -240,7 +226,32 @@ - + + Hide empty workspaces + True + True + False + start + True + + + 0 + 10 + + + + + Hide workspaces in other outputs + True + True + False + start + True + + + 1 + 10 + diff --git a/nwg_panel/langs/en_US.json b/nwg_panel/langs/en_US.json index eeb59d50..9e947b49 100644 --- a/nwg_panel/langs/en_US.json +++ b/nwg_panel/langs/en_US.json @@ -82,6 +82,7 @@ "header-icon-size": "Header icon size", "height": "Height", "hide-empty": "Hide empty workspaces", + "hide-other-outputs": "Hide workspaces on other outputs", "homogeneous": "Homogeneous", "homogeneous-tooltip": "Sets equal columns width be default if 'Modules center' not empty.", "horizontal-padding": "Horizontal padding", diff --git a/nwg_panel/main.py b/nwg_panel/main.py index 33aa61d5..308b8a8f 100644 --- a/nwg_panel/main.py +++ b/nwg_panel/main.py @@ -207,12 +207,20 @@ def instantiate_content(panel, container, content_list, icons_path=""): if item == "sway-workspaces": if sway: - if "sway-workspaces" in panel: - workspaces = SwayWorkspaces(panel["sway-workspaces"], common.i3, icons_path=icons_path) + if "sway-workspaces" not in panel: + print("'sway-workspaces' not defined in this panel instance") + else: + output = None + if "output" in panel: + output = "{}".format(panel["output"]) + + workspaces = SwayWorkspaces(panel["sway-workspaces"], common.i3, + icons_path=icons_path, + output=output) + container.pack_start(workspaces, False, False, panel["items-padding"]) common.workspaces_list.append(workspaces) - else: - print("'sway-workspaces' not defined in this panel instance") + else: print("'sway-workspaces' ignored") diff --git a/nwg_panel/modules/sway_workspaces.py b/nwg_panel/modules/sway_workspaces.py index 42aa594f..af29d59f 100644 --- a/nwg_panel/modules/sway_workspaces.py +++ b/nwg_panel/modules/sway_workspaces.py @@ -7,10 +7,11 @@ class SwayWorkspaces(Gtk.Box): - def __init__(self, settings, i3, icons_path): + def __init__(self, settings, i3, icons_path, output): Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=0) self.settings = settings self.i3 = i3 + self.panel_output = output self.num_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0) self.ws_num2box = {} self.ws_num2lbl = {} @@ -34,6 +35,7 @@ def build_box(self): check_key(self.settings, "mark-autotiling", True) check_key(self.settings, "mark-content", True) check_key(self.settings, "hide-empty", False) + check_key(self.settings, "hide-other-outputs", False) check_key(self.settings, "show-layout", True) check_key(self.settings, "angle", 0.0) if self.settings["angle"] != 0.0: @@ -42,27 +44,17 @@ def build_box(self): # prevent from #142 ws_num = -1 if self.i3.get_tree().find_focused(): - ws_num, win_name, win_id, non_empty, win_layout, numbers = self.find_details() - - if len(self.settings["custom-labels"]) == 1 or len(self.settings["custom-labels"]) == len(self.settings["numbers"]): - self.settings["custom-labels"] *= len(self.settings["numbers"]) - else: - self.settings["custom-labels"] = [] - - if len(self.settings["focused-labels"]) == 1 or len(self.settings["focused-labels"]) == len(self.settings["numbers"]): - self.settings["focused-labels"] *= len(self.settings["numbers"]) - else: - self.settings["focused-labels"] = [] + ws_num, win_name, win_id, non_empty, win_layout, numbers, ws_defs = self.find_details() self.pack_start(self.num_box, False, False, 0) for idx, num in enumerate(self.settings["numbers"]): - if num == str(ws_num) and self.settings["focused-labels"]: - label = self.settings["focused-labels"][idx] - elif self.settings["custom-labels"]: - label = self.settings["custom-labels"][idx] - else: - label = str(num) + try: + int_num = int(num) + except: + int_num = 0 + + label = self.get_ws_label(int_num, focused = (str(num) == str(ws_num))) eb, lbl = self.build_number(num, label) self.num_box.pack_start(eb, False, False, 0) @@ -114,9 +106,47 @@ def build_number(self, num, label): return eb, lbl + def get_ws_label(self, num, idx = None, ws_defs = None, focused = False): + """ + Get the text to display for a workspace: + - num: the number of the workspace (as integer) + - idx: the index of the workspace in ws_defs (if defined) + - focused: if the workspace is currently focused + - ws_defs: as returned by find_details() + """ + + # config_idx is the index of the current workspace in the + # configuration. It is the index of the workspace in the + # numbers config field, or the an index based on the + # workspace number, first workspace being number 1 + config_idx = None + if num in self.settings["numbers"]: + config_idx = self.settings["numbers"].index(num) + elif len(self.settings["numbers"]) == 0: + config_idx = num - 1 + + if focused: + labels = self.settings["focused-labels"] + else: + labels = self.settings["custom-labels"] + + if labels and config_idx in range(len(labels)): + text = labels[config_idx] + elif labels and len(labels) == 1: + text = labels[0] + elif idx in range(len(ws_defs)): + text = ws_defs[idx]['name'] + else: + text = str(num) + + return text + def refresh(self): if self.i3.get_tree().find_focused(): - ws_num, win_name, win_id, non_empty, win_layout, numbers = self.find_details() + ws_num, win_name, win_id, non_empty, win_layout, numbers, ws_defs = self.find_details() + + custom_labels = self.settings["custom-labels"] + focused_labels = self.settings["focused-labels"] if len(self.settings["numbers"]) > 0: numbers = self.settings["numbers"] @@ -125,23 +155,15 @@ def refresh(self): for num in self.ws_num2lbl: self.ws_num2lbl[num].hide() - for _idx, num in enumerate(numbers): - idx = None - if num in self.settings["numbers"]: - idx = self.settings["numbers"].index(num) + for idx, num in enumerate(numbers): + focused = (str(num) == str(ws_num)) try: int_num = int(num) except: int_num = 0 - if idx is None: - text = str(num) - elif num == str(ws_num) and self.settings["focused-labels"]: - text = self.settings["focused-labels"][idx] - elif self.settings["custom-labels"]: - text = self.settings["custom-labels"][idx] - else: - text = str(num) + text = self.get_ws_label(int_num, idx, ws_defs, + focused = focused) if num not in self.ws_num2lbl: eb, lbl = self.build_number(num, text) @@ -150,7 +172,7 @@ def refresh(self): lbl = self.ws_num2lbl[num] - if not self.settings["hide-empty"] or int_num in non_empty or num == str(ws_num): + if not self.settings["hide-empty"] or int_num in non_empty or focused: lbl.show() else: lbl.hide() @@ -163,10 +185,10 @@ def refresh(self): else: if text.endswith("."): text = text[0:-1] - + lbl.set_text(text) - if num == str(ws_num): + if focused: self.ws_num2box[num].set_property("name", "task-box-focused") else: self.ws_num2box[num].set_property("name", "task-box") @@ -229,12 +251,30 @@ def find_details(self): win_id = "" # app_id if available, else window_class layout = None numbers = [] + ws_defs = [] for ws in workspaces: - numbers.append(str(ws.num)) + _, _, name = ws.name.partition(':') + if len(name) == 0: + name = str(ws.num) + + hide_other_outputs = self.settings["hide-other-outputs"] and self.panel_output is not None + if hide_other_outputs and ws.output != self.panel_output: + continue + + ws_defs.append({ + 'num': int(ws.num), + 'name': name + }) if ws.focused: ws_num = ws.num + # Sort ws_defs before constructing numbers and names to ensure + # dynamic workspaces always appear in sorted order + ws_defs.sort(key = lambda ws: ws['num']) + for _idx, ws in enumerate(ws_defs): + numbers.append(ws['num']) + non_empty = [] if self.settings["show-name"] or self.settings["show-icon"]: f = self.i3.get_tree().find_focused() @@ -273,16 +313,23 @@ def find_details(self): if not layout: layout = f.parent.layout - return ws_num, win_name, win_id, non_empty, layout, numbers + return ws_num, win_name, win_id, non_empty, layout, numbers, ws_defs def on_click(self, event_box, event_button, num): nwg_panel.common.i3.command("workspace number {}".format(num)) def on_scroll(self, event_box, event): + hide_other_outputs = self.settings["hide-other-outputs"] and self.panel_output is not None if event.direction == Gdk.ScrollDirection.UP: - nwg_panel.common.i3.command("workspace prev") + if hide_other_outputs: + nwg_panel.common.i3.command("workspace prev_on_output") + else: + nwg_panel.common.i3.command("workspace prev") elif event.direction == Gdk.ScrollDirection.DOWN: - nwg_panel.common.i3.command("workspace next") + if hide_other_outputs: + nwg_panel.common.i3.command("workspace next_on_output") + else: + nwg_panel.common.i3.command("workspace next") def on_enter_notify_event(self, widget, event): widget.set_state_flags(Gtk.StateFlags.DROP_ACTIVE, clear=False)