From d684a7d0f64d7c1d8e70eb2065727e35c579c4c1 Mon Sep 17 00:00:00 2001 From: Taegil Bae Date: Mon, 11 Jul 2016 03:15:14 +0900 Subject: [PATCH] Add an option setting the direction of switching workspace --- Makefile | 2 +- Settings.ui | 16 + docking.js | 64 ++- myWorkspaceSwitcherPopup.js | 401 ++++++++++++++++++ prefs.js | 4 + ....shell.extensions.dash-to-dock.gschema.xml | 5 + 6 files changed, 476 insertions(+), 16 deletions(-) create mode 100644 myWorkspaceSwitcherPopup.js diff --git a/Makefile b/Makefile index b31dc07d8..bdd0aab2a 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ UUID = dash-to-dock@micxgx.gmail.com BASE_MODULES = extension.js stylesheet.css metadata.json COPYING README.md -EXTRA_MODULES = convenience.js dash.js docking.js appIcons.js intellihide.js prefs.js theming.js Settings.ui +EXTRA_MODULES = convenience.js dash.js docking.js appIcons.js intellihide.js prefs.js theming.js Settings.ui myWorkspaceSwitcherPopup.js EXTRA_MEDIA = logo.svg TOLOCALIZE = prefs.js MSGSRC = $(wildcard po/*.po) diff --git a/Settings.ui b/Settings.ui index b624fbcff..1fbe34799 100644 --- a/Settings.ui +++ b/Settings.ui @@ -1186,6 +1186,22 @@ 2 + + + In horizontal direction + True + True + False + 12 + 0 + True + + + 0 + 2 + 2 + + diff --git a/docking.js b/docking.js index 18cf8cbae..8d939e2ba 100644 --- a/docking.js +++ b/docking.js @@ -28,6 +28,7 @@ const Convenience = Me.imports.convenience; const Intellihide = Me.imports.intellihide; const Theming = Me.imports.theming; const MyDash = Me.imports.dash; +const MyWorkspaceSwitcherPopup = Me.imports.myWorkspaceSwitcherPopup; const DOCK_DWELL_CHECK_INTERVAL = 100; @@ -515,6 +516,10 @@ const DockedDash = new Lang.Class({ this._optionalScrollWorkspaceSwitch(this._settings.get_boolean('scroll-switch-workspace')); })); + this._settings.connect('changed::switch-workspace-horizontal', Lang.bind(this, function() { + this._optionalScrollWorkspaceSwitch(this._settings.get_boolean('scroll-switch-workspace')); + })); + this._settings.connect('changed::dash-max-icon-size', Lang.bind(this, function() { this.dash.setIconSize(this._settings.get_int('dash-max-icon-size')); })); @@ -1290,6 +1295,13 @@ const DockedDash = new Lang.Class({ Lang.bind(this, disable)(); })); + this._settings.connect('changed::switch-workspace-horizontal', Lang.bind(this, function() { + if (this._settings.get_boolean('switch-workspace-horizontal')) + this._horizontalWorkspace = true; + else + this._horizontalWorkspace = false; + })); + if (this._settings.get_boolean('scroll-switch-workspace')) Lang.bind(this, enable)(); @@ -1303,6 +1315,11 @@ const DockedDash = new Lang.Class({ ]); this._optionalScrollWorkspaceSwitchDeadTimeId = 0; + + if (this._settings.get_boolean('switch-workspace-horizontal')) + this._horizontalWorkspace = true; + else + this._horizontalWorkspace = false; } function disable() { @@ -1325,17 +1342,30 @@ const DockedDash = new Lang.Class({ switch (event.get_scroll_direction()) { case Clutter.ScrollDirection.UP: - direction = Meta.MotionDirection.UP; + if (this._horizontalWorkspace) + direction = Meta.MotionDirection.LEFT; + else + direction = Meta.MotionDirection.UP; break; case Clutter.ScrollDirection.DOWN: - direction = Meta.MotionDirection.DOWN; + if (this._horizontalWorkspace) + direction = Meta.MotionDirection.RIGHT; + else + direction = Meta.MotionDirection.DOWN; break; case Clutter.ScrollDirection.SMOOTH: let [dx, dy] = event.get_scroll_delta(); - if (dy < 0) - direction = Meta.MotionDirection.UP; - else if (dy > 0) - direction = Meta.MotionDirection.DOWN; + if (this._horizontalWorkspace) { + if (dx < 0) + direction = Meta.MotionDirection.LEFT; + else if (dx > 0) + direction = Meta.MotionDirection.RIGHT; + } else { + if (dy < 0) + direction = Meta.MotionDirection.UP; + else if (dy > 0) + direction = Meta.MotionDirection.DOWN; + } break; } @@ -1356,16 +1386,20 @@ const DockedDash = new Lang.Class({ ws = activeWs.get_neighbor(direction) - if (Main.wm._workspaceSwitcherPopup == null) - Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup(); - // Set the actor non reactive, so that it doesn't prevent the - // clicks events from reaching the dash actor. I can't see a reason - // why it should be reactive. - Main.wm._workspaceSwitcherPopup.actor.reactive = false; - Main.wm._workspaceSwitcherPopup.connect('destroy', function() { - Main.wm._workspaceSwitcherPopup = null; - }); + if (Main.wm._workspaceSwitcherPopup == null) { + if (this._horizontalWorkspace) + Main.wm._workspaceSwitcherPopup = new MyWorkspaceSwitcherPopup.myWorkspaceSwitcherPopup(); + else + Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup(); + } + // Set the actor non reactive, so that it doesn't prevent the + // clicks events from reaching the dash actor. I can't see a reason + // why it should be reactive. + Main.wm._workspaceSwitcherPopup.actor.reactive = false; + Main.wm._workspaceSwitcherPopup.connect('destroy', function() { + Main.wm._workspaceSwitcherPopup = null; + }); // Do not show wokspaceSwithcer in overview if (!Main.overview.visible) Main.wm._workspaceSwitcherPopup.display(direction, ws.index()); diff --git a/myWorkspaceSwitcherPopup.js b/myWorkspaceSwitcherPopup.js new file mode 100644 index 000000000..519523f27 --- /dev/null +++ b/myWorkspaceSwitcherPopup.js @@ -0,0 +1,401 @@ +/* ======================================================================================================== + * myWorkspaceSwitchPopup.js - + * -------------------------------------------------------------------------------------------------------- + * CREDITS: + * * This code was copied from the Workspace to dock extension + * https://github.com/passingthru67/workspaces-to-dock + * * This code was copied from the Frippery Bottom Panel extension + * http://frippery.org/extensions/ and modified to create a workspaces switcher popup. + * Copyright (C) 2011-2015 R M Yorston. + * * Part of this code also comes from gnome-shell-extensions: + * http://git.gnome.org/browse/gnome-shell-extensions/ + * ======================================================================================================== + */ + + +const Clutter = imports.gi.Clutter; +const Mainloop = imports.mainloop; +const Lang = imports.lang; +const Meta = imports.gi.Meta; +const St = imports.gi.St; +const Shell = imports.gi.Shell; + +const Main = imports.ui.main; +const WorkspacesView = imports.ui.workspacesView; +const WindowManager = imports.ui.windowManager; +const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup; +const Tweener = imports.ui.tweener; + +let GSFunctions = {}; + +const DISPLAY_TIMEOUT = 600; +let myShowWorkspaceSwitcher, origShowWorkspaceSwitcher; +let nrows = 1; + +function get_ncols() { + let ncols = Math.floor(global.screen.n_workspaces/nrows); + if ( global.screen.n_workspaces%nrows != 0 ) + ++ncols + + return ncols; +} + +const myWorkspaceSwitcherPopup = new Lang.Class({ + Name: 'workspcestodockWorkspaceSwitcherPopup', + Extends: WorkspaceSwitcherPopup.WorkspaceSwitcherPopup, + + _getPreferredHeight : function (actor, forWidth, alloc) { + let children = this._list.get_children(); + let workArea = Main.layoutManager.getWorkAreaForMonitor( + Main.layoutManager.primaryIndex); + + let availHeight = workArea.height; + availHeight -= this.actor.get_theme_node().get_vertical_padding(); + availHeight -= this._container.get_theme_node().get_vertical_padding(); + availHeight -= this._list.get_theme_node().get_vertical_padding(); + + let height = 0; + for (let i = 0; i < children.length; i++) { + let [childMinHeight, childNaturalHeight] = + children[i].get_preferred_height(-1); + height = Math.max(height, childNaturalHeight); + } + + height = nrows * height; + + let spacing = this._itemSpacing * (nrows - 1); + height += spacing; + height = Math.min(height, availHeight); + + this._childHeight = (height - spacing) / nrows; + + alloc.min_size = height; + alloc.natural_size = height; + }, + + _getPreferredWidth : function (actor, forHeight, alloc) { + let children = this._list.get_children(); + let workArea = Main.layoutManager.getWorkAreaForMonitor( + Main.layoutManager.primaryIndex); + + let availWidth = workArea.width; + availWidth -= this.actor.get_theme_node().get_horizontal_padding(); + availWidth -= this._container.get_theme_node().get_horizontal_padding(); + availWidth -= this._list.get_theme_node().get_horizontal_padding(); + + let ncols = get_ncols(); + let height = 0; + for (let i = 0; i < children.length; i++) { + let [childMinHeight, childNaturalHeight] = + children[i].get_preferred_height(-1); + height = Math.max(height, childNaturalHeight); + } + + let width = ncols * height * workArea.width/workArea.height; + + let spacing = this._itemSpacing * (ncols - 1); + width += spacing; + width = Math.min(width, availWidth); + + this._childWidth = (width - spacing) / ncols; + + alloc.min_size = width; + alloc.natural_size = width; + }, + + _allocate : function (actor, box, flags) { + let children = this._list.get_children(); + let childBox = new Clutter.ActorBox(); + + let ncols = get_ncols(); + + for ( let ir=0; ir 0) { + target--; + newWs = screen.get_workspace_by_index(target); + + if (screen.get_active_workspace().index() > target) + direction = Meta.MotionDirection.LEFT; + else + direction = Meta.MotionDirection.RIGHT; + } + + if (direction != Meta.MotionDirection.LEFT && + direction != Meta.MotionDirection.RIGHT) + return; + + if (action == 'switch') + this.actionMoveWorkspace(newWs); + else + this.actionMoveWindow(window, newWs); + + if (!Main.overview.visible) { + if (this._workspaceSwitcherPopup == null) { + this._workspaceSwitcherPopup = new myWorkspaceSwitcherPopup(); + this._workspaceSwitcherPopup.connect('destroy', + Lang.bind(this, function() { + this._workspaceSwitcherPopup = null; + })); + } + this._workspaceSwitcherPopup.display(direction, newWs.index()); + } + }; + + // Override updateWorkspaceActors for horizontal animation of overview windows + GSFunctions['WorkspacesView_updateWorkspaceActors'] = WorkspacesView.WorkspacesView.prototype._updateWorkspaceActors; + WorkspacesView.WorkspacesView.prototype._updateWorkspaceActors = function(showAnimation) { + let active = global.screen.get_active_workspace_index(); + + this._animating = showAnimation; + + for (let w = 0; w < this._workspaces.length; w++) { + let workspace = this._workspaces[w]; + + Tweener.removeTweens(workspace.actor); + + let x = (w - active) * this._fullGeometry.width; + + if (showAnimation) { + let params = { x: x, + time: WorkspacesView.WORKSPACE_SWITCH_TIME, + transition: 'easeOutQuad' + }; + // we have to call _updateVisibility() once before the + // animation and once afterwards - it does not really + // matter which tween we use, so we pick the first one ... + if (w == 0) { + this._updateVisibility(); + params.onComplete = Lang.bind(this, + function() { + this._animating = false; + this._updateVisibility(); + }); + } + Tweener.addTween(workspace.actor, params); + } else { + workspace.actor.set_position(x, 0); + if (w == 0) + this._updateVisibility(); + } + } + }; + + // Override overview scroll event for horizontal scrolling of workspaces + GSFunctions['WorkspacesDisplay_onScrollEvent'] = WorkspacesView.WorkspacesDisplay.prototype._onScrollEvent; + WorkspacesView.WorkspacesDisplay.prototype._onScrollEvent = function(actor, event) { + if (!this.actor.mapped) + return Clutter.EVENT_PROPAGATE; + let activeWs = global.screen.get_active_workspace(); + let ws; + switch (event.get_scroll_direction()) { + case Clutter.ScrollDirection.UP: + ws = activeWs.get_neighbor(Meta.MotionDirection.LEFT); + break; + case Clutter.ScrollDirection.DOWN: + ws = activeWs.get_neighbor(Meta.MotionDirection.RIGHT); + break; + default: + return Clutter.EVENT_PROPAGATE; + } + Main.wm.actionMoveWorkspace(ws); + return Clutter.EVENT_STOP; + }; + + }, + + _restoreGnomeShellFunctions: function() { + // Restore showWorkspacesSwitcher to show normal workspace switcher popup + WindowManager.WindowManager.prototype._showWorkspaceSwitcher = GSFunctions['WindowManager_showWorkspaceSwitcher']; + + // Restore updateWorkspaceActors to original vertical animation of overview windows + WorkspacesView.WorkspacesView.prototype._updateWorkspaceActors = GSFunctions['WorkspacesView_updateWorkspaceActors']; + + // Restore onScrollEvent to original vertical scrolling of workspaces + WorkspacesView.WorkspacesDisplay.prototype._onScrollEvent = GSFunctions['WorkspacesDisplay_onScrollEvent'] + }, + + _resetBindings: function() { + // Reset bindings to active showWorkspaceSwitcher function + let wm = Main.wm; + Meta.keybindings_set_custom_handler('switch-to-workspace-left', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-right', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-up', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-down', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-1', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-2', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-3', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-4', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-5', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-6', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-7', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-8', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-9', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-10', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-11', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-12', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('switch-to-workspace-last', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + + Meta.keybindings_set_custom_handler('move-to-workspace-left', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-right', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-up', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-down', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-1', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-2', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-3', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-4', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-5', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-6', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-7', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-8', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-9', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-10', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-11', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-12', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + Meta.keybindings_set_custom_handler('move-to-workspace-last', + Lang.bind(wm, wm._showWorkspaceSwitcher)); + + wm._workspaceSwitcherPopup = null; + } +}); diff --git a/prefs.js b/prefs.js index 2bd2e6c51..359d7c2c9 100644 --- a/prefs.js +++ b/prefs.js @@ -337,6 +337,10 @@ const Settings = new Lang.Class({ this._settings.bind('scroll-switch-workspace', this._builder.get_object('switch_workspace_switch'), 'active', Gio.SettingsBindFlags.DEFAULT); + this._settings.bind('switch-workspace-horizontal', this._builder.get_object('switch_workspace_horizontal_button'), 'active', Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('scroll-switch-workspace', this._builder.get_object('switch_workspace_horizontal_button'), 'sensitive', Gio.SettingsBindFlags.DEFAULT); + // Appearance Panel this._settings.bind('apply-custom-theme', this._builder.get_object('customize_theme'), 'sensitive', Gio.SettingsBindFlags.INVERT_BOOLEAN | Gio.SettingsBindFlags.GET); diff --git a/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml b/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml index df94d9474..297214bcb 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml @@ -100,6 +100,11 @@ Switch workspace by scrolling over the dock Add the possibility to switch workspace by mouse scrolling over the dock. + + false + Switch workspace in horizontal direction + Some extensions can lay workspaces in horizontal direction. In this case, this option should be turned on. + 48 Maximum dash icon size