Skip to content

Commit

Permalink
[sway-workspaces] Improvement of dynamic workspaces
Browse files Browse the repository at this point in the history
- sort workspaces number from sway to show them in correct order
- fix configuration interface
- handle workspaces labels in config
- handle workspaces labels from sway if not defined in config
  • Loading branch information
mildred committed Mar 13, 2023
1 parent e3fc32a commit de94b6b
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 64 deletions.
30 changes: 23 additions & 7 deletions nwg_panel/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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])
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand All @@ -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())
Expand Down
41 changes: 26 additions & 15 deletions nwg_panel/glade/config_sway_workspaces.glade
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,6 @@
<property name="top-attach">8</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="hide-empty">
<property name="label" translatable="yes">Hide empty workspaces</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">8</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="angle">
<property name="visible">True</property>
Expand Down Expand Up @@ -240,7 +226,32 @@
</packing>
</child>
<child>
<placeholder/>
<object class="GtkCheckButton" id="hide-empty">
<property name="label" translatable="yes">Hide empty workspaces</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">10</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="hide-other-outputs">
<property name="label" translatable="yes">Hide workspaces in other outputs</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">10</property>
</packing>
</child>
<child>
<placeholder/>
Expand Down
1 change: 1 addition & 0 deletions nwg_panel/langs/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
16 changes: 12 additions & 4 deletions nwg_panel/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
123 changes: 85 additions & 38 deletions nwg_panel/modules/sway_workspaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand All @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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"]
Expand All @@ -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)
Expand All @@ -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()
Expand All @@ -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")
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit de94b6b

Please sign in to comment.