[gnome-shell-extensions] windowsNavigator: Allow keyboard selection of windows and workspaces in overlay mode
- From: Maxim Ermilov <mermilov src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell-extensions] windowsNavigator: Allow keyboard selection of windows and workspaces in overlay mode
- Date: Tue, 18 Jan 2011 21:48:48 +0000 (UTC)
commit 1f2b0d0ec51ad7dda4e1156eca32b71c642c584b
Author: Maxim Ermilov <zaspire rambler ru>
Date: Wed Jan 19 00:43:37 2011 +0300
windowsNavigator: Allow keyboard selection of windows and workspaces in overlay mode
Bind alt-[1,2,3..9] "switch window on current workspace"
Bind ctrl-[1,2,3..9] switch workspace
https://bugzilla.gnome.org/show_bug.cgi?id=601393
configure.ac | 3 +-
extensions/Makefile.am | 2 +-
extensions/windowsNavigator/Makefile.am | 3 +
extensions/windowsNavigator/extension.js | 203 ++++++++++++++++++++++++++++
extensions/windowsNavigator/metadata.json | 7 +
extensions/windowsNavigator/stylesheet.css | 9 ++
6 files changed, 225 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5a012ef..6ef5eb4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@ PKG_PROG_PKG_CONFIG([0.22])
ADDITIONAL_PACKAGES=
dnl keep this in sync with extensions/Makefile.am
-ALL_EXTENSIONS="example alternate-tab xrandr-indicator"
+ALL_EXTENSIONS="example alternate-tab xrandr-indicator windowsNavigator"
AC_ARG_ENABLE([extensions],
[AS_HELP_STRING([--enable-extensions],[Space separated list of extensions to enable. Default is that all extensions are built.])],
[],
@@ -54,6 +54,7 @@ AC_CONFIG_FILES([
extensions/Makefile
extensions/example/Makefile
extensions/alternate-tab/Makefile
+ extensions/windowsNavigator/Makefile
extensions/xrandr-indicator/Makefile
po/Makefile.in
])
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index b42f5d7..e2c5fba 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -1,3 +1,3 @@
-DIST_SUBDIRS = example alternate-tab xrandr-indicator
+DIST_SUBDIRS = example alternate-tab xrandr-indicator windowsNavigator
SUBDIRS = $(ENABLED_EXTENSIONS)
diff --git a/extensions/windowsNavigator/Makefile.am b/extensions/windowsNavigator/Makefile.am
new file mode 100644
index 0000000..adeb886
--- /dev/null
+++ b/extensions/windowsNavigator/Makefile.am
@@ -0,0 +1,3 @@
+EXTENSION_ID = windowsNavigator
+
+include ../../extension.mk
diff --git a/extensions/windowsNavigator/extension.js b/extensions/windowsNavigator/extension.js
new file mode 100644
index 0000000..7801e53
--- /dev/null
+++ b/extensions/windowsNavigator/extension.js
@@ -0,0 +1,203 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+const Clutter = imports.gi.Clutter;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const St = imports.gi.St;
+
+const Main = imports.ui.main;
+const Workspace = imports.ui.workspace;
+const WorkspacesView = imports.ui.workspacesView;
+
+function injectToFunction(parent, name, func) {
+ let origin = parent[name];
+ parent[name] = function() {
+ let ret;
+ ret = origin.apply(this, arguments);
+ if (ret === undefined)
+ ret = func.apply(this, arguments);
+ return ret;
+ }
+}
+
+function main() {
+ Workspace.WindowOverlay.prototype.setId = function(id) {
+ if (this._text.visible && id == null)
+ this._text.hide();
+ this._id = id;
+ if (id != null)
+ this._text.text = this._id.toString();
+ }
+ Workspace.WindowOverlay.prototype.getId = function() {
+ return this._id;
+ }
+ Workspace.WindowOverlay.prototype.showTooltip = function() {
+ if (this._id === null)
+ return;
+ this._text.raise_top();
+ this._text.show();
+ this._text.text = this._id.toString();
+ }
+ Workspace.WindowOverlay.prototype.hideTooltip = function() {
+ if (this._text.visible)
+ this._text.hide();
+ }
+
+ Workspace.Workspace.prototype.showTooltip = function() {
+ if (this._tip == null)
+ return;
+ if (this.parent)
+ return;
+ this.actor.add_actor(this._tip);
+ this._tip.raise_top();
+ }
+ Workspace.Workspace.prototype.hideTooltip = function() {
+ if (this._tip == null)
+ return;
+ if (!this._tip.get_parent())
+ return;
+ this.actor.remove_actor(this._tip);
+ }
+ Workspace.Workspace.prototype.getWindowWithTooltip = function(id) {
+ for (let i in this._windowOverlays) {
+ if (this._windowOverlays[i] == null)
+ continue;
+ if (this._windowOverlays[i].getId() === id)
+ return this._windowOverlays[i]._windowClone.metaWindow;
+ }
+ return null;
+ }
+ Workspace.Workspace.prototype.showWindowsTooltips = function() {
+ for (let i in this._windowOverlays) {
+ if (this._windowOverlays[i] != null)
+ this._windowOverlays[i].showTooltip();
+ }
+ }
+ Workspace.Workspace.prototype.hideWindowsTooltips = function() {
+ for (let i in this._windowOverlays) {
+ if (this._windowOverlays[i] != null)
+ this._windowOverlays[i].hideTooltip();
+ }
+ }
+
+ WorkspacesView.WorkspacesView.prototype._hideTooltips = function() {
+ global.stage.set_key_focus(this._prevFocusActor);
+ this._pickWindow = false;
+ for (let i = 0; i < this._workspaces.length; i++)
+ this._workspaces[i].hideWindowsTooltips();
+ }
+
+ WorkspacesView.WorkspacesView.prototype._hideWorkspacesTooltips = function() {
+ global.stage.set_key_focus(this._prevFocusActor);
+ this._pickWorkspace = false;
+ for (let i = 0; i < this._workspaces.length; i++)
+ this._workspaces[i].hideTooltip();
+ }
+
+ WorkspacesView.WorkspacesView.prototype._onKeyRelease = function(s, o) {
+ if (this._pickWindow && o.get_key_symbol() == Clutter.Alt_L)
+ this._hideTooltips();
+ if (this._pickWorkspace && o.get_key_symbol() == Clutter.Control_L)
+ this._hideWorkspacesTooltips();
+ }
+ WorkspacesView.WorkspacesView.prototype._onKeyPress = function(s, o) {
+ if (o.get_key_symbol() == Clutter.Alt_L && !this._pickWorkspace) {
+ this._prevFocusActor = global.stage.get_key_focus();
+ global.stage.set_key_focus(null);
+ this._active = global.screen.get_active_workspace_index();
+ this._pickWindow = true;
+ this._workspaces[global.screen.get_active_workspace_index()].showWindowsTooltips();
+ return true;
+ }
+ if (o.get_key_symbol() == Clutter.Control_L && !this._pickWindow) {
+ this._prevFocusActor = global.stage.get_key_focus();
+ global.stage.set_key_focus(null);
+ this._pickWorkspace = true;
+ for (let i = 0; i < this._workspaces.length; i++)
+ this._workspaces[i].showTooltip();
+ return true;
+ }
+
+ if (global.stage.get_key_focus() != global.stage)
+ return false;
+
+ if (this._pickWindow) {
+ if (this._active != global.screen.get_active_workspace_index()) {
+ this._hideTooltips();
+ return false;
+ }
+ let c = o.get_key_unicode();
+ if (c > '9'.charCodeAt(0) || c < '0'.charCodeAt(0)) {
+ this._hideTooltips();
+ return false;
+ }
+ let win = this._workspaces[this._active].getWindowWithTooltip(c - '0'.charCodeAt(0));
+ this._hideTooltips();
+ if (win)
+ Main.activateWindow(win, global.get_current_time());
+ return true;
+ }
+ if (this._pickWorkspace) {
+ let c = o.get_key_unicode();
+ if (c > '9'.charCodeAt(0) || c < '0'.charCodeAt(0)) {
+ this._hideWorkspacesTooltips();
+ return false;
+ }
+ let workspace = this._workspaces[c - '0'.charCodeAt(0) - 1];
+ if (workspace !== undefined)
+ workspace.metaWorkspace.activate(global.get_current_time());
+ this._hideWorkspacesTooltips();
+ return true;
+ }
+ return false;
+ }
+
+ injectToFunction(Workspace.WindowOverlay.prototype, '_init', function(windowClone, parentActor) {
+ this._id = null;
+ this._text = new St.Label({ style_class: 'window-tooltip' });
+ this._text.hide();
+ parentActor.add_actor(this._text);
+ });
+ injectToFunction(Workspace.WindowOverlay.prototype, 'updatePositions', function(cloneX, cloneY, cloneWidth, cloneHeight) {
+ let textX = cloneX - 2;
+ let textY = cloneY - 2;
+ this._text.set_position(Math.floor(textX), Math.floor(textY));
+ this._text.raise_top();
+ });
+ injectToFunction(Workspace.Workspace.prototype, '_init', function(metaWorkspace) {
+ if (metaWorkspace.index() < 9) {
+ this._tip = new St.Label({ style_class: 'window-tooltip',
+ text: (metaWorkspace.index() + 1).toString() });
+ this.actor.connect('notify::scale-x', Lang.bind(this, function() {
+ this._tip.set_scale(1 / this.actor.scale_x, 1 / this.actor.scale_x);
+ }));
+ } else
+ this._tip = null;
+ });
+ injectToFunction(Workspace.Workspace.prototype, 'positionWindows', function(flags) {
+ let visibleClones = this._getVisibleClones();
+ if (this._reservedSlot)
+ visibleClones.push(this._reservedSlot);
+
+ let slots = this._computeAllWindowSlots(visibleClones.length);
+ visibleClones = this._orderWindowsByMotionAndStartup(visibleClones, slots);
+ for (let i = 0; i < visibleClones.length; i++) {
+ let clone = visibleClones[i];
+ let metaWindow = clone.metaWindow;
+ let mainIndex = this._lookupIndex(metaWindow);
+ let overlay = this._windowOverlays[mainIndex];
+ if (overlay)
+ overlay.setId(i < 9 ? i + 1 : null);
+ }
+ });
+
+ injectToFunction(WorkspacesView.WorkspacesView.prototype, '_init', function(width, height, x, y, workspaces) {
+ this._pickWorkspace = false;
+ this._pickWindow = false;
+ this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._onKeyPress));
+ this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._onKeyRelease));
+ });
+ injectToFunction(WorkspacesView.WorkspacesView.prototype, '_onDestroy', function() {
+ global.stage.disconnect(this._keyPressEventId);
+ global.stage.disconnect(this._keyReleaseEventId);
+ });
+}
diff --git a/extensions/windowsNavigator/metadata.json b/extensions/windowsNavigator/metadata.json
new file mode 100644
index 0000000..50150ea
--- /dev/null
+++ b/extensions/windowsNavigator/metadata.json
@@ -0,0 +1,7 @@
+{
+ "shell-version": ["2.91.5"],
+ "uuid": "windowsNavigator gnome-shell-extensions gnome org",
+ "original-author": "zaspire rambler ru",
+ "name": "windowNavigator",
+ "description": "Allow keyboard selection of windows and workspaces in overlay mode"
+}
\ No newline at end of file
diff --git a/extensions/windowsNavigator/stylesheet.css b/extensions/windowsNavigator/stylesheet.css
new file mode 100644
index 0000000..6406652
--- /dev/null
+++ b/extensions/windowsNavigator/stylesheet.css
@@ -0,0 +1,9 @@
+.window-tooltip {
+ color: #ff0000;
+ background: rgba(0,0,0,0.8);
+ border: 1px solid rgba(128,128,128,0.40);
+ border-radius: 10px;
+ font-size: 16px;
+ padding: 2px 8px;
+ -shell-caption-spacing: 4px;
+}
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]