commit 473ae4e008941959e2669e545275f9da2fb72eb5 Author: chatlanin Date: Mon Oct 10 17:27:09 2022 +0300 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..9491817 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# workspaces-bar +GNOME Shell extension that shows workspaces buttons in top panel diff --git a/extension.js b/extension.js new file mode 100644 index 0000000..5e096c5 --- /dev/null +++ b/extension.js @@ -0,0 +1,147 @@ +/* + Workspaces Bar + Copyright Francois Thirioux 2021 + GitHub contributors: @fthx + License GPL v3 +*/ + + +const { Clutter, Gio, GObject, Shell, St } = imports.gi; + +const Main = imports.ui.main; +const PanelMenu = imports.ui.panelMenu; + +var WORKSPACES_SCHEMA = "org.gnome.desktop.wm.preferences"; +var WORKSPACES_KEY = "workspace-names"; + + +var WorkspacesBar = GObject.registerClass( +class WorkspacesBar extends PanelMenu.Button { + _init() { + super._init(0.0, 'Workspaces bar'); + this.track_hover = false; + + // define gsettings schema for workspaces names, get workspaces names, signal for settings key changed + this.workspaces_settings = new Gio.Settings({ schema: WORKSPACES_SCHEMA }); + this.workspaces_names_changed = this.workspaces_settings.connect(`changed::${WORKSPACES_KEY}`, this._update_workspaces_names.bind(this)); + + // hide Activities button + this._show_activities(false); + + // bar creation + this.ws_bar = new St.BoxLayout({}); + this._update_workspaces_names(); + this.add_child(this.ws_bar); + + // signals for workspaces state: active workspace, number of workspaces + this._ws_active_changed = global.workspace_manager.connect('active-workspace-changed', this._update_ws.bind(this)); + this._ws_number_changed = global.workspace_manager.connect('notify::n-workspaces', this._update_ws.bind(this)); + this._restacked = global.display.connect('restacked', this._update_ws.bind(this)); + this._windows_changed = Shell.WindowTracker.get_default().connect('tracked-windows-changed', this._update_ws.bind(this)); + } + + // remove signals, restore Activities button, destroy workspaces bar + _destroy() { + this._show_activities(true); + if (this._ws_active_changed) { + global.workspace_manager.disconnect(this._ws_active_changed); + } + if (this._ws_number_changed) { + global.workspace_manager.disconnect(this._ws_number_changed); + } + if (this._restacked) { + global.display.disconnect(this._restacked); + } + if (this._windows_changed) { + Shell.WindowTracker.get_default().disconnect(this._windows_changed); + } + if (this.workspaces_names_changed) { + this.workspaces_settings.disconnect(this.workspaces_names_changed); + } + this.ws_bar.destroy(); + super.destroy(); + } + + // hide Activities button + _show_activities(show) { + this.activities_button = Main.panel.statusArea['activities']; + if (this.activities_button) { + if (show && !Main.sessionMode.isLocked) { + this.activities_button.container.show(); + } else { + this.activities_button.container.hide(); + } + } + } + + // update workspaces names + _update_workspaces_names() { + this.workspaces_names = this.workspaces_settings.get_strv(WORKSPACES_KEY); + this._update_ws(); + } + + // update the workspaces bar + _update_ws() { + // destroy old workspaces bar buttons + this.ws_bar.destroy_all_children(); + + // get number of workspaces + this.ws_count = global.workspace_manager.get_n_workspaces(); + this.active_ws_index = global.workspace_manager.get_active_workspace_index(); + + // display all current workspaces buttons + for (let ws_index = 0; ws_index < this.ws_count; ++ws_index) { + this.ws_box = new St.Bin({visible: true, reactive: true, can_focus: true, track_hover: true}); + this.ws_box.label = new St.Label({y_align: Clutter.ActorAlign.CENTER}); + if (ws_index == this.active_ws_index) { + if (global.workspace_manager.get_workspace_by_index(ws_index).n_windows > 0) { + this.ws_box.label.style_class = 'desktop-label-nonempty-active'; + } else { + this.ws_box.label.style_class = 'desktop-label-empty-active'; + } + } else { + if (global.workspace_manager.get_workspace_by_index(ws_index).n_windows > 0) { + this.ws_box.label.style_class = 'desktop-label-nonempty-inactive'; + } else { + this.ws_box.label.style_class = 'desktop-label-empty-inactive'; + } + } + if (this.workspaces_names[ws_index]) { + this.ws_box.label.set_text(" " + this.workspaces_names[ws_index] + " "); + } else { + this.ws_box.label.set_text(" " + (ws_index + 1) + " "); + } + this.ws_box.set_child(this.ws_box.label); + this.ws_box.connect('button-release-event', () => this._toggle_ws(ws_index) ); + this.ws_bar.add_actor(this.ws_box); + } + } + + // activate workspace or show overview + _toggle_ws(ws_index) { + if (global.workspace_manager.get_active_workspace_index() == ws_index) { + Main.overview.toggle(); + } else { + global.workspace_manager.get_workspace_by_index(ws_index).activate(global.get_current_time()); + } + } +}); + +class Extension { + constructor() { + } + + enable() { + this.workspaces_bar = new WorkspacesBar(); + Main.panel.addToStatusArea('workspaces-bar', this.workspaces_bar, 0, 'left'); + } + + disable() { + this.workspaces_bar._destroy(); + } +} + +function init() { + return new Extension(); +} + diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..d6649b4 --- /dev/null +++ b/metadata.json @@ -0,0 +1,15 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Replace 'Activities' button by all current workspaces buttons. Switch workspace or toggle overview by clicking on these buttons.\n\n You can use names for workspaces: there are two ways for that. 1) Edit the string array 'org.gnome.desktop.wm.preferences.workspace-names' gsettings key (through dconf editor, e.g.). 2) Use official GNOME extension Workspaces Indicator's settings. You don't have to write a long enough list: numbers are displayed if no workspace name is defined.", + "name": "Workspaces Bar", + "shell-version": [ + "3.36", + "3.38", + "40", + "41", + "42" + ], + "url": "https://gitcast.ru", + "uuid": "workspaces-bar@chatlanin", + "version": 1 +} diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 0000000..b43000b --- /dev/null +++ b/stylesheet.css @@ -0,0 +1,68 @@ +/* framed version */ + +/*.desktop-label-nonempty-active { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(128, 128, 128, 0.7); + color: rgba(207, 207, 207, 1); + border: 1px solid rgba(207, 207, 207, 0.7); + border-radius: 4px; +} + +.desktop-label-nonempty-inactive { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(76, 76, 76, 0.7); + color: rgba(207, 207, 207, 0.7); + border: 1px solid rgba(207, 207, 207, 0.7); + border-radius: 4px; +} + +.desktop-label-empty-active { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(128, 128, 128, 0.7); + color: rgba(207, 207, 207, 1); + border: 1px solid rgba(207, 207, 207, 0); + border-radius: 4px; +} + +.desktop-label-empty-inactive { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(76, 76, 76, 0.7); + color: rgba(207, 207, 207, 0.7); + border: 1px solid rgba(207, 207, 207, 0); + border-radius: 4px; +}*/ + +/* non-framed version */ + +.desktop-label-nonempty-active { + margin-left: 0px; + margin-right: 8px; + background-color: transparent !important + border-radius: 2px; + border-color: rgba(27, 56, 143, 1); +} + +.desktop-label-nonempty-inactive { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(96, 96, 96, 0.7); + border-radius: 2px; +} + +.desktop-label-empty-active { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(154, 154, 154, 0.7); + border-radius: 2px; +} + +.desktop-label-empty-inactive { + margin-left: 0px; + margin-right: 8px; + background-color: rgba(0, 0, 0, 0.0); + border-radius: 2px; +}