From 3226e97becdc096690f331cb2afdf37ee770091a Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:19:43 +0200 Subject: [PATCH 01/74] [Scale] Make workspace overview background themeable --- data/theme/cinnamon.css | 4 ++++ js/ui/overview.js | 26 +++++++++++--------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/data/theme/cinnamon.css b/data/theme/cinnamon.css index 8ad514b3a1..91d885ba8c 100644 --- a/data/theme/cinnamon.css +++ b/data/theme/cinnamon.css @@ -439,6 +439,10 @@ StScrollBar StButton#vhandle:hover { background-gradient-end: #AAA; background-gradient-direction: vertical } + +.workspace-overview-background-shade { + background-color: rgba(0,0,0,0.4); +} /* =================================================================== * ViewSelector * ===================================================================*/ diff --git a/js/ui/overview.js b/js/ui/overview.js index 78a281ed07..1454017153 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -105,14 +105,22 @@ Overview.prototype = { return; } + this._background = new Clutter.Group(); + this._background.hide(); + global.overlay_group.add_actor(this._background); + // The main BackgroundActor is inside global.window_group which is // hidden when displaying the overview, so we create a new // one. Instances of this class share a single CoglTexture behind the // scenes which allows us to show the background with different // rendering options without duplicating the texture data. - this._background = Meta.BackgroundActor.new_for_screen(global.screen); - this._background.hide(); - global.overlay_group.add_actor(this._background); + let desktopBackground = Meta.BackgroundActor.new_for_screen(global.screen); + this._background.add_actor(desktopBackground); + + let backgroundShade = new St.Bin({style_class: 'workspace-overview-background-shade'}); + this._background.add_actor(backgroundShade); + let porthole = Main.layoutManager.getPorthole(); + backgroundShade.set_size(porthole.width, porthole.height); this._desktopFade = new St.Bin(); global.overlay_group.add_actor(this._desktopFade); @@ -568,12 +576,6 @@ Overview.prototype = { onCompleteScope: this }); - Tweener.addTween(this._background, - { dim_factor: 0.4, - time: ANIMATION_TIME, - transition: 'easeOutQuad' - }); - this._coverPane.raise_top(); this._coverPane.show(); this.emit('showing'); @@ -705,12 +707,6 @@ Overview.prototype = { onCompleteScope: this }); - Tweener.addTween(this._background, - { dim_factor: 1.0, - time: ANIMATION_TIME, - transition: 'easeOutQuad' - }); - this._coverPane.raise_top(); this._coverPane.show(); this.emit('hiding'); From 5cca5c666932f23b04631e060cf4adc25f7cdcae Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:06:52 +0200 Subject: [PATCH 02/74] [Scale] Sort primarily on minimized-ness --- js/ui/workspace.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 27624fdd6e..1cf0e918c7 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1204,17 +1204,18 @@ Workspace.prototype = { syncStacking: function(stackIndices) { let clones = this._windows.slice(); - clones.sort(function (a, b) { return stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; }); + clones.sort(function (a, b) { + let minimizedA = a.metaWindow.minimized ? -1 : 0; + let minimizedB = b.metaWindow.minimized ? -1 : 0; + let minimizedDiff = minimizedA - minimizedB; + return minimizedDiff || stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; + }); + let below = this._dropRect; for (let i = 0; i < clones.length; i++) { let clone = clones[i]; - let metaWindow = clone.metaWindow; - if (i == 0) { - clone.setStackAbove(this._dropRect); - } else { - let previousClone = clones[i - 1]; - clone.setStackAbove(previousClone.actor); - } + clone.setStackAbove(below); + below = clone.actor; } }, From b79eeee4aeb90ec6fc83ab30594c8bbf04d01812 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:06:54 +0200 Subject: [PATCH 03/74] [Scale] Make sure clones and overlays never go out of sync. Sort array of clones in-place. Ensure correct keyboard focus. --- js/ui/workspace.js | 49 +++++++++++++++++++++-------------------- js/ui/workspacesView.js | 26 +++++----------------- 2 files changed, 31 insertions(+), 44 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 1cf0e918c7..7be3eb00d1 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -100,6 +100,7 @@ WindowClone.prototype = { this.realWindow = realWindow; this.metaWindow = realWindow.meta_window; this.metaWindow._delegate = this; + this.overlay = null; let [borderX, borderY] = this._getInvisibleBorderPadding(); this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(), @@ -723,17 +724,15 @@ Workspace.prototype = { this._dropRect._delegate = this; this.actor.add_actor(this._dropRect); - this.actor.add_actor(this._windowOverlaysGroup); + this.actor.add_actor(this._windowOverlaysGroup); this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); let windows = global.get_window_actors().filter(this._isMyWindow, this); - windows.reverse(); // we want the most-recently-used windows first // Create clones for windows that should be // visible in the Overview this._windows = []; - this._windowOverlays = []; for (let i = 0; i < windows.length; i++) { if (this._isOverviewWindow(windows[i])) { this._addWindowClone(windows[i]); @@ -759,7 +758,7 @@ Workspace.prototype = { }, selectAnotherWindow: function(symbol) { - let numWindows = this._windowOverlays.length; + let numWindows = this._windows.length; if (numWindows === 0) { return false; } @@ -829,13 +828,13 @@ Workspace.prototype = { if (currentIndex !== nextIndex) { if (currentIndex > -1 && currentIndex < numWindows) { - this._windowOverlays[currentIndex].setSelected(false); + this._windows[currentIndex].overlay.setSelected(false); } } this._kbWindowIndex = currentIndex = nextIndex; if (currentIndex > -1 && currentIndex < numWindows) { - this._windowOverlays[currentIndex].setSelected(true); + this._windows[currentIndex].overlay.setSelected(true); } return true; }, @@ -849,8 +848,8 @@ Workspace.prototype = { }, closeSelectedWindow: function() { - if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windowOverlays.length) { - this._windowOverlays[this._kbWindowIndex].closeWindow(); + if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { + this._windows[this._kbWindowIndex].overlay.closeWindow(); } }, @@ -1086,9 +1085,9 @@ Workspace.prototype = { let buttonOuterHeight, captionHeight; let buttonOuterWidth = 0; - if (this._windowOverlays[0]) { - [buttonOuterHeight, captionIconHeight] = this._windowOverlays[0].chromeHeights(); - buttonOuterWidth = this._windowOverlays[0].chromeWidth(); + if (this._windows.length) { + [buttonOuterHeight, captionIconHeight] = this._windows[0].overlay.chromeHeights(); + buttonOuterWidth = this._windows[0].overlay.chromeWidth(); } else { [buttonOuterHeight, captionIconHeight] = [0, 0]; } @@ -1151,7 +1150,7 @@ Workspace.prototype = { let clone = clones[i]; let metaWindow = clone.metaWindow; let mainIndex = this._lookupIndex(metaWindow); - let overlay = this._windowOverlays[mainIndex]; + let overlay = this._windows[mainIndex].overlay; // Positioning a window currently being dragged must be avoided; // we'll just leave a blank spot in the layout for it. @@ -1200,17 +1199,20 @@ Workspace.prototype = { this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); } } + if (this._kbWindowIndex < 0) { + this.selectAnotherWindow(Clutter.Home); + } }, syncStacking: function(stackIndices) { - let clones = this._windows.slice(); - clones.sort(function (a, b) { - let minimizedA = a.metaWindow.minimized ? -1 : 0; - let minimizedB = b.metaWindow.minimized ? -1 : 0; + this._windows.sort(function (a, b) { + let minimizedA = a.metaWindow.minimized ? 1 : 0; + let minimizedB = b.metaWindow.minimized ? 1 : 0; let minimizedDiff = minimizedA - minimizedB; return minimizedDiff || stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; }); + let clones = this._windows.slice().reverse(); let below = this._dropRect; for (let i = 0; i < clones.length; i++) { let clone = clones[i]; @@ -1247,7 +1249,7 @@ Workspace.prototype = { let currentWorkspace = global.screen.get_active_workspace(); for (let i = 0; i < this._windows.length; i++) { let clone = this._windows[i]; - let overlay = this._windowOverlays[i]; + let overlay = this._windows[i].overlay; this._showWindowOverlay(clone, overlay, this.metaWorkspace == null || this.metaWorkspace == currentWorkspace); } @@ -1302,7 +1304,6 @@ Workspace.prototype = { let clone = this._windows[index]; this._windows.splice(index, 1); - this._windowOverlays.splice(index, 1); // If metaWin.get_compositor_private() returned non-NULL, that // means the window still exists (and is just being moved to @@ -1320,11 +1321,11 @@ Workspace.prototype = { }; } if (index === this._kbWindowIndex) { - if (this._kbWindowIndex >= this._windowOverlays.length) { + if (this._kbWindowIndex >= this._windows.length) { this._kbWindowIndex = 0; } - if (this._kbWindowIndex < this._windowOverlays.length) { - this._windowOverlays[this._kbWindowIndex].setSelected(true); + if (this._kbWindowIndex < this._windows.length) { + this._windows[this._kbWindowIndex].overlay.setSelected(true); } } @@ -1577,14 +1578,14 @@ Workspace.prototype = { overlay.connect('show-close-button', Lang.bind(this, this._onShowOverlayClose)); this._windows.push(clone); - this._windowOverlays.push(overlay); + clone.overlay = overlay; return clone; }, _onShowOverlayClose: function (windowOverlay) { - for (let i = 0; i < this._windowOverlays.length; i++) { - let overlay = this._windowOverlays[i]; + for (let i = 0; i < this._windows.length; i++) { + let overlay = this._windows[i].overlay; if (overlay == windowOverlay) continue; overlay.hideCloseButton(); diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 442b453f4e..8269fdd4c3 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -83,13 +83,9 @@ WorkspacesView.prototype = { // workspaces have been created. This cannot be done first because // window movement depends on the Workspaces object being accessible // as an Overview member. - this._overviewShowingId = - Main.overview.connect('showing', - Lang.bind(this, function() { - for (let w = 0; w < this._workspaces.length; w++) - this._workspaces[w].zoomToOverview(); - for (let w = 0; w < this._extraWorkspaces.length; w++) - this._extraWorkspaces[w].zoomToOverview(); + this._overviewShowingId = Main.overview.connect('showing', Lang.bind(this, function() { + let activeWorkspaceIndex = global.screen.get_active_workspace_index(); + this._workspaces[activeWorkspaceIndex].zoomToOverview(); })); this._overviewShownId = Main.overview.connect('shown', @@ -132,10 +128,6 @@ WorkspacesView.prototype = { } })); - // this should select the last active window - if (this._workspaces.length > 0) { - this._workspaces[activeWorkspaceIndex].selectAnotherWindow(Clutter.Home); - } }, _onStageKeyPress: function(actor, event) { @@ -203,13 +195,8 @@ WorkspacesView.prototype = { let activeWorkspace = this._workspaces[activeWorkspaceIndex]; activeWorkspace.actor.raise_top(); - - this.actor.remove_clip(this._x, this._y, this._width, this._height); - - for (let w = 0; w < this._workspaces.length; w++) - this._workspaces[w].zoomFromOverview(); - for (let w = 0; w < this._extraWorkspaces.length; w++) - this._extraWorkspaces[w].zoomFromOverview(); + this.actor.remove_clip(this._x, this._y, this._width, this._height); + activeWorkspace.zoomFromOverview(); }, destroy: function() { @@ -742,7 +729,7 @@ WorkspacesDisplay.prototype = { }, _onRestacked: function() { - let stack = global.get_window_actors(); + let stack = global.get_window_actors().reverse(); let stackIndices = {}; for (let i = 0; i < stack.length; i++) { @@ -751,7 +738,6 @@ WorkspacesDisplay.prototype = { } this.workspacesView.syncStacking(stackIndices); - // this._thumbnailsBox.syncStacking(stackIndices); }, _workspacesChanged: function() { From 72ebb7ec4ee1a7898347e224aaa6a55eab44dc2f Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:06:56 +0200 Subject: [PATCH 04/74] [Scale] Some rework of pointer-event handling. --- js/ui/workspace.js | 56 +++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 7be3eb00d1..6ffd8555ea 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -150,7 +150,7 @@ WindowClone.prototype = { this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor.connect('leave-event', - Lang.bind(this, this._onLeave)); + Lang.bind(this, this._onPointerLeave)); this._draggable = DND.makeDraggable(this.actor, { restoreOnSuccess: true, @@ -248,7 +248,7 @@ WindowClone.prototype = { this.disconnectAll(); }, - _onLeave: function (actor, event) { + _onPointerLeave: function (actor, event) { if (this._zoomStep) this._zoomEnd(); }, @@ -443,6 +443,7 @@ WindowOverlay.prototype = { this._windowClone = windowClone; this._parentActor = parentActor; this._hidden = false; + this._hovering = false; let title = new St.Label({ style_class: 'window-caption', text: metaWindow.title }); @@ -479,10 +480,20 @@ WindowOverlay.prototype = { button.connect('clicked', Lang.bind(this, this.closeWindow)); windowClone.actor.connect('destroy', Lang.bind(this, this._onDestroy)); - windowClone.actor.connect('enter-event', - Lang.bind(this, this._onEnter)); - windowClone.actor.connect('leave-event', - Lang.bind(this, this._onLeave)); + + let motionEventsInstalled = false; + let installMotionEvents = Lang.bind(this, function() { + if (motionEventsInstalled) { + return; + } + windowClone.actor.connect('motion-event', Lang.bind(this, this._onPointerMotion)); + windowClone.actor.connect('leave-event', Lang.bind(this, this._onPointerLeave)); + motionEventsInstalled = true; + }); + // Let the animation settle before we start reacting on pointer motion. + Mainloop.idle_add(installMotionEvents); + // Since idle_add can be slow at times, set an ordinary timeout as a fallback. + Mainloop.timeout_add(1000, installMotionEvents); this._windowAddedId = 0; windowClone.connect('zoom-start', Lang.bind(this, this.hide)); @@ -511,7 +522,10 @@ WindowOverlay.prototype = { setSelected: function(selected) { this.title.name = selected ? 'selected' : ''; if (selected) { - this._onEnter(); + this._showCloseButton(); + } + else { + this.hideCloseButton(); } }, @@ -524,8 +538,7 @@ WindowOverlay.prototype = { show: function() { this._hidden = false; - if (this._windowClone.actor.has_pointer) - this.closeButton.show(); + this._hovering = false; this.title.show(); this._applicationIconBox.show(); }, @@ -643,28 +656,39 @@ WindowOverlay.prototype = { this._applicationIconBox.destroy(); }, - _onEnter: function() { - // We might get enter events on the clone while the overlay is + _onPointerMotion: function() { + // We might get motion events on the clone while the overlay is // hidden, e.g. during animations, we ignore these events, // as the close button will be shown as needed when the overlays // are shown again - if (this._hidden) - return; + if (this._hidden) return; + if (this._hovering) return; + + this._hovering = true; + this._showCloseButton(); + }, + + _showCloseButton: function() { this._parentActor.raise_top(); this.closeButton.show(); this.emit('show-close-button'); }, - _onLeave: function() { + _onPointerLeave: function() { + this._hovering = false; + this._idleHideCloseButton(); + }, + + _idleHideCloseButton: function() { if (this._idleToggleCloseId == 0) this._idleToggleCloseId = Mainloop.timeout_add(750, Lang.bind(this, this._idleToggleCloseButton)); }, _idleToggleCloseButton: function() { this._idleToggleCloseId = 0; - if (!this._windowClone.actor.has_pointer && - !this.closeButton.has_pointer) + if (!this._windowClone.actor.has_pointer && !this.closeButton.has_pointer) { this.closeButton.hide(); + } return false; }, From 316f84008602e0c66816bca313757d3cfaae6dc4 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:06:57 +0200 Subject: [PATCH 05/74] [Scale] Make sure the keyboard-focused window clone has a close button. --- js/ui/workspace.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 6ffd8555ea..387cb1940f 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1223,8 +1223,17 @@ Workspace.prototype = { this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); } } + // default-select the first window if (this._kbWindowIndex < 0) { this.selectAnotherWindow(Clutter.Home); + Mainloop.idle_add(Lang.bind(this, function() { + // if keyboard focus is at the default position, + // make sure that the close button is drawn, + // which must done a little bit later + if (this._kbWindowIndex === 0) { + this.selectAnotherWindow(Clutter.Home); + } + })); } }, From 2bb64247fc50356f6664fd54fc8614dafdc06fc7 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:06:59 +0200 Subject: [PATCH 06/74] [Scale] Improve window-caption-width calculation, taking into account all available horizontal space. --- js/ui/workspace.js | 49 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 387cb1940f..d16022ee98 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -505,7 +505,7 @@ WindowOverlay.prototype = { this.closeButton = button; this.icon = icon; - parentActor.add_actor(this._applicationIconBox); + parentActor.add_actor(this._applicationIconBox); parentActor.add_actor(this.title); parentActor.add_actor(this.closeButton); //parentActor.add_actor(this.icon); @@ -572,7 +572,7 @@ WindowOverlay.prototype = { // get_transformed_position() and get_transformed_size(), // as windowClone might be moving. // See Workspace._showWindowOverlay - updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight) { + updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, maxWidth) { let button = this.closeButton; let title = this.title; @@ -595,18 +595,16 @@ WindowOverlay.prototype = { buttonX = cloneX + (cloneWidth - button._overlap); button.set_position(Math.floor(buttonX), Math.floor(buttonY)); + let iconWidth = this._applicationIconBox.width + title._spacing; - if (!title.fullWidth) - title.fullWidth = title.width; - title.width = Math.min(title.fullWidth, cloneWidth); - - let titleX = cloneX + (cloneWidth - title.width) / 2; + title.width = Math.min(maxWidth - iconWidth, title.width); + let titleX = cloneX + (iconWidth + cloneWidth - title.width) / 2; let titleY = cloneY + cloneHeight + title._spacing + (WINDOWOVERLAY_ICON_SIZE/2) - (title.height/2); title.set_position(Math.floor(titleX), Math.floor(titleY)); let icon = this._applicationIconBox; - let iconX = titleX - WINDOWOVERLAY_ICON_SIZE - title._spacing; + let iconX = titleX - iconWidth; let iconY = cloneY + cloneHeight + title._spacing; icon.set_position(Math.floor(iconX), Math.floor(iconY)); @@ -734,6 +732,7 @@ Workspace.prototype = { this._y = 0; this._width = 0; this._height = 0; + this._slotWidth = 0; this.monitorIndex = monitorIndex; this._monitor = Main.layoutManager.monitors[this.monitorIndex]; @@ -1269,8 +1268,8 @@ Workspace.prototype = { cloneWidth = clone.actor.scale_x * cloneWidth; cloneHeight = clone.actor.scale_y * cloneHeight; - if (overlay) { - overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight); + if (overlay && this._slotWidth) { + overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight, this._slotWidth); if (fade) overlay.fadeIn(); else @@ -1625,26 +1624,28 @@ Workspace.prototype = { } }, - _computeWindowSlot : function(windowIndex, numberOfWindows) { - if (numberOfWindows in POSITIONS) - return POSITIONS[numberOfWindows][windowIndex]; - - // If we don't have a predefined scheme for this window count, - // arrange the windows in a grid pattern. + _computeAllWindowSlots: function(numberOfWindows) { + if (!numberOfWindows) return []; let gridWidth = Math.ceil(Math.sqrt(numberOfWindows)); let gridHeight = Math.ceil(numberOfWindows / gridWidth); - let fraction = 0.825 * (1. / gridWidth); + this._slotWidth = Math.floor(fraction * this._width); - let xCenter = (.5 / gridWidth) + ((windowIndex) % gridWidth) / gridWidth; - let yCenter = (.5 / gridHeight) + Math.floor((windowIndex / gridWidth)) / gridHeight; - return [xCenter, yCenter, fraction]; - }, + let computeWindowSlot = function(windowIndex, numberOfWindows) { + if (numberOfWindows in POSITIONS) + return POSITIONS[numberOfWindows][windowIndex]; + + // If we don't have a predefined scheme for this window count, + // arrange the windows in a grid pattern. - _computeAllWindowSlots: function(totalWindows) { + let xCenter = (.5 / gridWidth) + ((windowIndex) % gridWidth) / gridWidth; + let yCenter = (.5 / gridHeight) + Math.floor((windowIndex / gridWidth)) / gridHeight; + return [xCenter, yCenter, fraction]; + }; + let slots = []; - for (let i = 0; i < totalWindows; i++) { - slots.push(this._computeWindowSlot(i, totalWindows)); + for (let i = 0; i < numberOfWindows; i++) { + slots.push(computeWindowSlot(i, numberOfWindows)); } return slots; }, From 6ebbca8eae409da75cb2e44043a70b9561fb6581 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:01 +0200 Subject: [PATCH 07/74] [Scale] Make window-caption-width calculation adaptive as selection changes and titles are updated --- js/ui/workspace.js | 64 +++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index d16022ee98..9aec1aa615 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -445,11 +445,7 @@ WindowOverlay.prototype = { this._hidden = false; this._hovering = false; - let title = new St.Label({ style_class: 'window-caption', - text: metaWindow.title }); - title.clutter_text.ellipsize = Pango.EllipsizeMode.END; - title._spacing = 0; - + this.makeTitle(metaWindow.title); let tracker = Cinnamon.WindowTracker.get_default(); let app = tracker.get_window_app(metaWindow); let icon = null; @@ -470,7 +466,8 @@ WindowOverlay.prototype = { this._updateCaptionId = metaWindow.connect('notify::title', Lang.bind(this, function(w) { - this.title.text = w.title; + this.makeTitle(w.title); + this.updateIconCaptionWidth(); })); let button = new St.Button({ style_class: 'window-close' }); @@ -501,16 +498,12 @@ WindowOverlay.prototype = { button.hide(); - this.title = title; this.closeButton = button; this.icon = icon; parentActor.add_actor(this._applicationIconBox); - parentActor.add_actor(this.title); parentActor.add_actor(this.closeButton); - //parentActor.add_actor(this.icon); - title.connect('style-changed', - Lang.bind(this, this._onStyleChanged)); + button.connect('style-changed', Lang.bind(this, this._onStyleChanged)); // force a style change if we are already on a stage - otherwise @@ -519,8 +512,28 @@ WindowOverlay.prototype = { this._onStyleChanged(); }, + makeTitle: function(titleTextOpt) { + let titleText = typeof(titleTextOpt) !== "undefined" ? titleTextOpt : this.title.text; + if (this.title) { + this._parentActor.remove_actor(this.title); + } + let title = new St.Label({ style_class: 'window-caption', + text: titleText }); + this.title = title; + title.clutter_text.ellipsize = Pango.EllipsizeMode.END; + title._spacing = 0; + this._parentActor.add_actor(this.title); + title.connect('style-changed', + Lang.bind(this, this._onStyleChanged)); + }, + setSelected: function(selected) { + this.makeTitle(); this.title.name = selected ? 'selected' : ''; + if (this.updateIconCaptionWidth) { + this.updateIconCaptionWidth(); + } + if (selected) { this._showCloseButton(); } @@ -574,7 +587,6 @@ WindowOverlay.prototype = { // See Workspace._showWindowOverlay updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, maxWidth) { let button = this.closeButton; - let title = this.title; let settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA }); let layout = settings.get_string(BUTTON_LAYOUT_KEY); @@ -595,19 +607,23 @@ WindowOverlay.prototype = { buttonX = cloneX + (cloneWidth - button._overlap); button.set_position(Math.floor(buttonX), Math.floor(buttonY)); - let iconWidth = this._applicationIconBox.width + title._spacing; - title.width = Math.min(maxWidth - iconWidth, title.width); - let titleX = cloneX + (iconWidth + cloneWidth - title.width) / 2; - let titleY = cloneY + cloneHeight + title._spacing + (WINDOWOVERLAY_ICON_SIZE/2) - (title.height/2); - title.set_position(Math.floor(titleX), Math.floor(titleY)); - - let icon = this._applicationIconBox; - - let iconX = titleX - iconWidth; - let iconY = cloneY + cloneHeight + title._spacing; - - icon.set_position(Math.floor(iconX), Math.floor(iconY)); + this.updateIconCaptionWidth = Lang.bind(this, function() { + let title = this.title; + let iconWidth = this._applicationIconBox.width + title._spacing; + title.width = Math.min(maxWidth - iconWidth, title.width); + let titleX = cloneX + (iconWidth + cloneWidth - title.width) / 2; + let titleY = cloneY + cloneHeight + title._spacing + (WINDOWOVERLAY_ICON_SIZE/2) - (title.height/2); + title.set_position(Math.floor(titleX), Math.floor(titleY)); + + let icon = this._applicationIconBox; + + let iconX = titleX - iconWidth; + let iconY = cloneY + cloneHeight + title._spacing; + + icon.set_position(Math.floor(iconX), Math.floor(iconY)); + }); + this.updateIconCaptionWidth(); }, closeWindow: function() { From 14134a1a087789a6f0003251d5c5c9a40134716b Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:02 +0200 Subject: [PATCH 08/74] [Scale] Some overlay refactoring. --- js/ui/workspace.js | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 9aec1aa615..795d0055db 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -46,7 +46,7 @@ const POSITIONS = { }; // Used in _orderWindowsPermutations, 5! = 120 which is probably the highest we can go const POSITIONING_PERMUTATIONS_MAX = 5; - +const DEFAULT_SLOT_FRACTION = 0.825; const WINDOWOVERLAY_ICON_SIZE = 32; function _interpolate(start, end, step) { @@ -516,6 +516,7 @@ WindowOverlay.prototype = { let titleText = typeof(titleTextOpt) !== "undefined" ? titleTextOpt : this.title.text; if (this.title) { this._parentActor.remove_actor(this.title); + this.title.destroy(); } let title = new St.Label({ style_class: 'window-caption', text: titleText }); @@ -1189,7 +1190,7 @@ Workspace.prototype = { let clone = clones[i]; let metaWindow = clone.metaWindow; let mainIndex = this._lookupIndex(metaWindow); - let overlay = this._windows[mainIndex].overlay; + let overlay = clone.overlay; // Positioning a window currently being dragged must be avoided; // we'll just leave a blank spot in the layout for it. @@ -1229,13 +1230,13 @@ Workspace.prototype = { time: Overview.ANIMATION_TIME, transition: 'easeOutQuad', onComplete: Lang.bind(this, function() { - this._showWindowOverlay(clone, overlay, true); + this._showWindowOverlay(clone, true); }) }); } else { clone.actor.set_position(x, y); clone.actor.set_scale(scale, scale); - this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); + this._showWindowOverlay(clone, isOnCurrentWorkspace); } } // default-select the first window @@ -1269,27 +1270,27 @@ Workspace.prototype = { } }, - _showWindowOverlay: function(clone, overlay, fade) { + _showWindowOverlay: function(clone, fade) { if (clone.inDrag) return; - // This is a little messy and complicated because when we - // start the fade-in we may not have done the final positioning - // of the workspaces. (Tweener doesn't necessarily finish - // all animations before calling onComplete callbacks.) - // So we need to manually compute where the window will - // be after the workspace animation finishes. - let [cloneX, cloneY] = clone.actor.get_position(); - let [cloneWidth, cloneHeight] = clone.actor.get_size(); - cloneWidth = clone.actor.scale_x * cloneWidth; - cloneHeight = clone.actor.scale_y * cloneHeight; - - if (overlay && this._slotWidth) { - overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight, this._slotWidth); + if (this._slotWidth) { + // This is a little messy and complicated because when we + // start the fade-in we may not have done the final positioning + // of the workspaces. (Tweener doesn't necessarily finish + // all animations before calling onComplete callbacks.) + // So we need to manually compute where the window will + // be after the workspace animation finishes. + let [cloneX, cloneY] = clone.actor.get_position(); + let [cloneWidth, cloneHeight] = clone.actor.get_size(); + cloneWidth = clone.actor.scale_x * cloneWidth; + cloneHeight = clone.actor.scale_y * cloneHeight; + + clone.overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight, this._slotWidth); if (fade) - overlay.fadeIn(); + clone.overlay.fadeIn(); else - overlay.show(); + clone.overlay.show(); } }, @@ -1297,8 +1298,7 @@ Workspace.prototype = { let currentWorkspace = global.screen.get_active_workspace(); for (let i = 0; i < this._windows.length; i++) { let clone = this._windows[i]; - let overlay = this._windows[i].overlay; - this._showWindowOverlay(clone, overlay, + this._showWindowOverlay(clone, this.metaWorkspace == null || this.metaWorkspace == currentWorkspace); } }, @@ -1644,7 +1644,7 @@ Workspace.prototype = { if (!numberOfWindows) return []; let gridWidth = Math.ceil(Math.sqrt(numberOfWindows)); let gridHeight = Math.ceil(numberOfWindows / gridWidth); - let fraction = 0.825 * (1. / gridWidth); + let fraction = DEFAULT_SLOT_FRACTION * (1. / gridWidth); this._slotWidth = Math.floor(fraction * this._width); let computeWindowSlot = function(windowIndex, numberOfWindows) { From 4f94bc835d2dc4b5fa2f0aec7c1683a7ecee702a Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:04 +0200 Subject: [PATCH 09/74] [Scale] Tweak adaptive Window-caption-width calculation. --- js/ui/workspace.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 795d0055db..149fd6d2d7 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -445,7 +445,7 @@ WindowOverlay.prototype = { this._hidden = false; this._hovering = false; - this.makeTitle(metaWindow.title); + this.refreshTitle(metaWindow.title); let tracker = Cinnamon.WindowTracker.get_default(); let app = tracker.get_window_app(metaWindow); let icon = null; @@ -466,8 +466,7 @@ WindowOverlay.prototype = { this._updateCaptionId = metaWindow.connect('notify::title', Lang.bind(this, function(w) { - this.makeTitle(w.title); - this.updateIconCaptionWidth(); + this.refreshTitle(w.title); })); let button = new St.Button({ style_class: 'window-close' }); @@ -512,28 +511,30 @@ WindowOverlay.prototype = { this._onStyleChanged(); }, - makeTitle: function(titleTextOpt) { - let titleText = typeof(titleTextOpt) !== "undefined" ? titleTextOpt : this.title.text; + refreshTitle: function(titleText) { + let name = ''; if (this.title) { + name = this.title.name; this._parentActor.remove_actor(this.title); this.title.destroy(); } let title = new St.Label({ style_class: 'window-caption', text: titleText }); this.title = title; + title.name = name; title.clutter_text.ellipsize = Pango.EllipsizeMode.END; title._spacing = 0; - this._parentActor.add_actor(this.title); + this._parentActor.add_actor(title); title.connect('style-changed', Lang.bind(this, this._onStyleChanged)); + if (this._parentActor.get_stage()) { + this._onStyleChanged(); + } }, setSelected: function(selected) { - this.makeTitle(); this.title.name = selected ? 'selected' : ''; - if (this.updateIconCaptionWidth) { - this.updateIconCaptionWidth(); - } + this.refreshTitle(this.title.text); if (selected) { this._showCloseButton(); @@ -724,6 +725,9 @@ WindowOverlay.prototype = { this.closeButton._overlap = closeNode.get_length('-cinnamon-close-overlap'); this._parentActor.queue_relayout(); + if (this.updateIconCaptionWidth) { + this.updateIconCaptionWidth(); + } } }; Signals.addSignalMethods(WindowOverlay.prototype); From 916fe0e735be11a910b2bbeb3d59b8c492424695 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:05 +0200 Subject: [PATCH 10/74] [Scale] Reorder the steps in Overlay construction. --- js/ui/workspace.js | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 149fd6d2d7..9b84989370 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -445,7 +445,6 @@ WindowOverlay.prototype = { this._hidden = false; this._hovering = false; - this.refreshTitle(metaWindow.title); let tracker = Cinnamon.WindowTracker.get_default(); let app = tracker.get_window_app(metaWindow); let icon = null; @@ -457,26 +456,30 @@ WindowOverlay.prototype = { icon_type: St.IconType.FULLCOLOR, icon_size: WINDOWOVERLAY_ICON_SIZE }); } + this.icon = icon; icon.width = WINDOWOVERLAY_ICON_SIZE; icon.height = WINDOWOVERLAY_ICON_SIZE; this._applicationIconBox = new St.Bin({ style_class: 'window-iconbox' }); this._applicationIconBox.set_opacity(255); this._applicationIconBox.add_actor(icon); + parentActor.add_actor(this._applicationIconBox); + + let button = new St.Button({ style_class: 'window-close' }); + this.closeButton = button; + button._overlap = 0; + button.hide(); + parentActor.add_actor(button); + button.connect('style-changed', + Lang.bind(this, this._onStyleChanged)); + button.connect('clicked', Lang.bind(this, this.closeWindow)); + this.refreshTitle(metaWindow.title); this._updateCaptionId = metaWindow.connect('notify::title', Lang.bind(this, function(w) { this.refreshTitle(w.title); })); - let button = new St.Button({ style_class: 'window-close' }); - button._overlap = 0; - - this._idleToggleCloseId = 0; - button.connect('clicked', Lang.bind(this, this.closeWindow)); - - windowClone.actor.connect('destroy', Lang.bind(this, this._onDestroy)); - let motionEventsInstalled = false; let installMotionEvents = Lang.bind(this, function() { if (motionEventsInstalled) { @@ -491,20 +494,12 @@ WindowOverlay.prototype = { // Since idle_add can be slow at times, set an ordinary timeout as a fallback. Mainloop.timeout_add(1000, installMotionEvents); + this._idleToggleCloseId = 0; this._windowAddedId = 0; + windowClone.actor.connect('destroy', Lang.bind(this, this._onDestroy)); windowClone.connect('zoom-start', Lang.bind(this, this.hide)); windowClone.connect('zoom-end', Lang.bind(this, this.show)); - button.hide(); - - this.closeButton = button; - this.icon = icon; - - parentActor.add_actor(this._applicationIconBox); - parentActor.add_actor(this.closeButton); - - button.connect('style-changed', - Lang.bind(this, this._onStyleChanged)); // force a style change if we are already on a stage - otherwise // the signal will be emitted normally when we are added if (parentActor.get_stage()) From 2e759cdb82ed51c74cecbff00fb7872360162225 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:07 +0200 Subject: [PATCH 11/74] [Multi-monitor, Scale] Show all windows belonging to the current workspace together, regardless of which monitor they're on. --- js/ui/workspace.js | 29 ++--------------------------- js/ui/workspacesView.js | 20 -------------------- 2 files changed, 2 insertions(+), 47 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 9b84989370..59a876b7e1 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -785,10 +785,6 @@ Workspace.prototype = { this._windowRemovedId = this.metaWorkspace.connect('window-removed', Lang.bind(this, this._windowRemoved)); } - this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor', - Lang.bind(this, this._windowEnteredMonitor)); - this._windowLeftMonitorId = global.screen.connect('window-left-monitor', - Lang.bind(this, this._windowLeftMonitor)); this._repositionWindowsId = 0; this.leavingOverview = false; @@ -1456,18 +1452,6 @@ Workspace.prototype = { this._doRemoveWindow(metaWin); }, - _windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) { - if (monitorIndex == this.monitorIndex) { - this._doAddWindow(metaWin); - } - }, - - _windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) { - if (monitorIndex == this.monitorIndex) { - this._doRemoveWindow(metaWin); - } - }, - // check for maximized windows on the workspace hasMaximizedWindows: function() { for (let i = 0; i < this._windows.length; i++) { @@ -1552,8 +1536,6 @@ Workspace.prototype = { this.metaWorkspace.disconnect(this._windowAddedId); this.metaWorkspace.disconnect(this._windowRemovedId); } - global.screen.disconnect(this._windowEnteredMonitorId); - global.screen.disconnect(this._windowLeftMonitorId); if (this._repositionWindowsId > 0) Mainloop.source_remove(this._repositionWindowsId); @@ -1572,10 +1554,9 @@ Workspace.prototype = { this.leavingOverview = false; }, - // Tests if @win belongs to this workspaces and monitor + // Tests if @win belongs to this workspace _isMyWindow : function (win) { - return (this.metaWorkspace == null || Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index())) && - (!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex); + return (this.metaWorkspace == null || Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index())); }, // Tests if @win should be shown in the Overview @@ -1702,12 +1683,6 @@ Workspace.prototype = { let metaWindow = win.get_meta_window(); - // We need to move the window before changing the workspace, because - // the move itself could cause a workspace change if the window enters - // the primary monitor - if (metaWindow.get_monitor() != this.monitorIndex) - metaWindow.move_to_monitor(this.monitorIndex); - let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index(); metaWindow.change_workspace_by_index(index, false, // don't create workspace diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 8269fdd4c3..e73439c34f 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -67,18 +67,6 @@ WorkspacesView.prototype = { this._workspaces[w].actor.reparent(this.actor); this._workspaces[activeWorkspaceIndex].actor.raise_top(); - this._extraWorkspaces = []; - let monitors = Main.layoutManager.monitors; - let m = 0; - for (let i = 0; i < monitors.length; i++) { - if (i == Main.layoutManager.primaryIndex) - continue; - let ws = new Workspace.Workspace(null, i); - this._extraWorkspaces[m++] = ws; - ws.setGeometry(monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height); - global.overlay_group.add_actor(ws.actor); - } - // Position/scale the desktop windows and their children after the // workspaces have been created. This cannot be done first because // window movement depends on the Workspaces object being accessible @@ -206,8 +194,6 @@ WorkspacesView.prototype = { syncStacking: function(stackIndices) { for (let i = 0; i < this._workspaces.length; i++) this._workspaces[i].syncStacking(stackIndices); - for (let i = 0; i < this._extraWorkspaces.length; i++) - this._extraWorkspaces[i].syncStacking(stackIndices); }, updateWindowPositions: function() { @@ -332,8 +318,6 @@ WorkspacesView.prototype = { }, _onDestroy: function() { - for (let i = 0; i < this._extraWorkspaces.length; i++) - this._extraWorkspaces[i].destroy(); this._scrollAdjustment.run_dispose(); Main.overview.disconnect(this._overviewShowingId); Main.overview.disconnect(this._overviewShownId); @@ -396,8 +380,6 @@ WorkspacesView.prototype = { this._firstDragMotion = false; for (let i = 0; i < this._workspaces.length; i++) this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate); - for (let i = 0; i < this._extraWorkspaces.length; i++) - this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate); } return DND.DragMotionResult.CONTINUE; @@ -409,8 +391,6 @@ WorkspacesView.prototype = { for (let i = 0; i < this._workspaces.length; i++) this._workspaces[i].setReservedSlot(null); - for (let i = 0; i < this._extraWorkspaces.length; i++) - this._extraWorkspaces[i].setReservedSlot(null); }, _swipeScrollBegin: function() { From f9272941b8fcf8a9c767e29fa11ca0fbe3cd32b1 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:09 +0200 Subject: [PATCH 12/74] [Scale] Less intrusive keyboard handling. --- js/ui/workspacesView.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index e73439c34f..ee4536cf60 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -106,16 +106,8 @@ WorkspacesView.prototype = { this._swipeScrollBeginId = 0; this._swipeScrollEndId = 0; - this._stageKeyPressId = global.stage.connect('key-press-event', - Lang.bind(this, this._onStageKeyPress)); - Main.overview.connect('hiding', Lang.bind(this, - function () { - if (this._stageKeyPressId != 0) { - global.stage.disconnect(this._stageKeyPressId); - this._stageKeyPressId = 0; - } - })); - + this.actor.connect('key-press-event', Lang.bind(this, this._onStageKeyPress)); + global.stage.set_key_focus(this.actor); }, _onStageKeyPress: function(actor, event) { From 1a32bd32b860775b8a316d01f98e9dc20dd39c05 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:11 +0200 Subject: [PATCH 13/74] PopupComboMenu: Handle a scaled source actor better. --- js/ui/popupMenu.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js index c9805704a6..ac873b6d76 100644 --- a/js/ui/popupMenu.js +++ b/js/ui/popupMenu.js @@ -1554,12 +1554,13 @@ PopupComboMenu.prototype = { this.isOpen = true; + let activeItem = this._getMenuItems()[this._activeItemPos]; + let [sourceX, sourceY] = this.sourceActor.get_transformed_position(); - let items = this._getMenuItems(); - let activeItem = items[this._activeItemPos]; + this.actor.set_position(Math.round(sourceX), Math.round(sourceY - activeItem.actor.y)); + let [sourceWidth, sourceHeight] = this.sourceActor.get_transformed_size(); + this.actor.width = Math.max(this.actor.width, sourceWidth); - this.actor.set_position(sourceX, sourceY - activeItem.actor.y); - this.actor.width = Math.max(this.actor.width, this.sourceActor.width); this.actor.raise_top(); this.actor.opacity = 0; From 9c71a5598888d184c0e7088c68d2b645e4e3fb9f Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:12 +0200 Subject: [PATCH 14/74] Improve PopupComboMenu keyboard handling. --- js/ui/popupMenu.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js index ac873b6d76..d480ba1586 100644 --- a/js/ui/popupMenu.js +++ b/js/ui/popupMenu.js @@ -1571,6 +1571,8 @@ PopupComboMenu.prototype = { transition: 'linear', time: BoxPointer.POPUP_ANIMATION_TIME }); + this.savedFocusActor = global.stage.get_key_focus(); + global.stage.set_key_focus(this.actor); this.emit('open-state-changed', true); }, @@ -1590,6 +1592,7 @@ PopupComboMenu.prototype = { }); this.emit('open-state-changed', false); + global.stage.set_key_focus(this.savedFocusActor); }, setActiveItem: function(position) { From b61bc60ac588faabe5ab3853ce0f77f351e089a2 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:13 +0200 Subject: [PATCH 15/74] Let PopupComboMenu width not depend on source actor's width. --- js/ui/popupMenu.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js index d480ba1586..75f3c6aaa3 100644 --- a/js/ui/popupMenu.js +++ b/js/ui/popupMenu.js @@ -1558,8 +1558,6 @@ PopupComboMenu.prototype = { let [sourceX, sourceY] = this.sourceActor.get_transformed_position(); this.actor.set_position(Math.round(sourceX), Math.round(sourceY - activeItem.actor.y)); - let [sourceWidth, sourceHeight] = this.sourceActor.get_transformed_size(); - this.actor.width = Math.max(this.actor.width, sourceWidth); this.actor.raise_top(); From 657102c38e0aa02a6be774debe9e7c3d5eb1c1bd Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:15 +0200 Subject: [PATCH 16/74] [Scale] Add a window context menu. --- js/ui/popupMenu.js | 2 +- js/ui/workspace.js | 159 ++++++++++++++++++++++++++++++++++++++++ js/ui/workspacesView.js | 6 ++ 3 files changed, 166 insertions(+), 1 deletion(-) diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js index 75f3c6aaa3..ebf064fdea 100644 --- a/js/ui/popupMenu.js +++ b/js/ui/popupMenu.js @@ -1862,7 +1862,7 @@ PopupMenuManager.prototype = { if (hadFocus) focus.grab_key_focus(); - else +else menu.actor.grab_key_focus(); } else if (menu == this._activeMenu) { if (this.grabbed) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 59a876b7e1..753ea1136f 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -14,6 +14,7 @@ const DND = imports.ui.dnd; const Lightbox = imports.ui.lightbox; const Main = imports.ui.main; const Overview = imports.ui.overview; +const PopupMenu = imports.ui.popupMenu; const Tweener = imports.ui.tweener; const FOCUS_ANIMATION_TIME = 0.15; @@ -874,6 +875,16 @@ Workspace.prototype = { return true; }, + showMenuForSelectedWindow: function() { + if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { + let window = this._windows[this._kbWindowIndex]; + let menu = new AppMenuButtonRightClickMenu(window.actor, window.metaWindow, "top"); + menu.toggle(); + return true; + } + return false; + }, + activateSelectedWindow: function() { if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { this._onCloneSelected(this._windows[this._kbWindowIndex], global.get_current_time()); @@ -1699,3 +1710,151 @@ Workspace.prototype = { }; Signals.addSignalMethods(Workspace.prototype); + +function AppMenuButtonRightClickMenu(actor, metaWindow, orientation) { + this._init(actor, metaWindow, orientation); +} + +AppMenuButtonRightClickMenu.prototype = { + __proto__: PopupMenu.PopupComboMenu.prototype, + + _init: function(actor, metaWindow, orientation) { + //take care of menu initialization + PopupMenu.PopupComboMenu.prototype._init.call(this, actor); + Main.uiGroup.add_actor(this.actor); + this.actor.hide(); + actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress)); + this.connect('open-state-changed', Lang.bind(this, this._onToggled)); + + this.metaWindow = metaWindow; + + this.itemCloseWindow = new PopupMenu.PopupMenuItem(_("Close")); + this.itemCloseWindow.connect('activate', Lang.bind(this, this._onCloseWindowActivate)); + + if (metaWindow.minimized) + this.itemMinimizeWindow = new PopupMenu.PopupMenuItem(_("Restore")); + else + this.itemMinimizeWindow = new PopupMenu.PopupMenuItem(_("Minimize")); + this.itemMinimizeWindow.connect('activate', Lang.bind(this, this._onMinimizeWindowActivate)); + + this.itemMaximizeWindow = new PopupMenu.PopupMenuItem(_("Maximize")); + this.itemMaximizeWindow.connect('activate', Lang.bind(this, this._onMaximizeWindowActivate)); + + this.itemMoveToLeftWorkspace = new PopupMenu.PopupMenuItem(_("Move to left workspace")); + this.itemMoveToLeftWorkspace.connect('activate', Lang.bind(this, this._onMoveToLeftWorkspace)); + + this.itemMoveToRightWorkspace = new PopupMenu.PopupMenuItem(_("Move to right workspace")); + this.itemMoveToRightWorkspace.connect('activate', Lang.bind(this, this._onMoveToRightWorkspace)); + + this.itemOnAllWorkspaces = new PopupMenu.PopupMenuItem(_("Visible on all workspaces")); + this.itemOnAllWorkspaces.connect('activate', Lang.bind(this, this._toggleOnAllWorkspaces)); + + let items = [ + this.itemOnAllWorkspaces, + this.itemMoveToLeftWorkspace, + this.itemMoveToRightWorkspace, + new PopupMenu.PopupSeparatorMenuItem(), + this.itemMinimizeWindow, + this.itemMaximizeWindow, + this.itemCloseWindow + ]; + (orientation == St.Side.BOTTOM ? items : items.reverse()).forEach(function(item) { + this.addMenuItem(item); + }, this); + this.setActiveItem(0); + }, + + _onToggled: function(actor, event){ + if (!event) { + this.destroy(); + return; + } + + if (this.metaWindow.is_on_all_workspaces()) { + this.itemOnAllWorkspaces.label.set_text(_("Only on this workspace")); + this.itemMoveToLeftWorkspace.actor.hide(); + this.itemMoveToRightWorkspace.actor.hide(); + } else { + this.itemOnAllWorkspaces.label.set_text(_("Visible on all workspaces")); + if (this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.LEFT) != this.metaWindow.get_workspace()) + this.itemMoveToLeftWorkspace.actor.show(); + else + this.itemMoveToLeftWorkspace.actor.hide(); + + if (this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.RIGHT) != this.metaWindow.get_workspace()) + this.itemMoveToRightWorkspace.actor.show(); + else + this.itemMoveToRightWorkspace.actor.hide(); + } + if (this.metaWindow.get_maximized()) { + this.itemMaximizeWindow.label.set_text(_("Unmaximize")); + }else{ + this.itemMaximizeWindow.label.set_text(_("Maximize")); + } + }, + + _onWindowMinimized: function(actor, event){ + }, + + _onCloseWindowActivate: function(actor, event){ + this.metaWindow.delete(global.get_current_time()); + }, + + _onMinimizeWindowActivate: function(actor, event){ + if (this.metaWindow.minimized) { + this.metaWindow.unminimize(global.get_current_time()); + } + else { + this.metaWindow.minimize(global.get_current_time()); + } + }, + + _onMaximizeWindowActivate: function(actor, event){ + if (this.metaWindow.get_maximized()){ + this.metaWindow.unmaximize(Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL); + }else{ + this.metaWindow.maximize(Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL); + } + }, + + _onMoveToLeftWorkspace: function(actor, event){ + let workspace = this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.LEFT); + if (workspace) { + this.metaWindow.change_workspace(workspace); + Main._checkWorkspaces(); + } + }, + + _onMoveToRightWorkspace: function(actor, event){ + let workspace = this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.RIGHT); + if (workspace) { + this.metaWindow.change_workspace(workspace); + Main._checkWorkspaces(); + } + }, + + _toggleOnAllWorkspaces: function(actor, event) { + if (this.metaWindow.is_on_all_workspaces()) + this.metaWindow.unstick(); + else + this.metaWindow.stick(); + }, + + _onSourceKeyPress: function(actor, event) { + let symbol = event.get_key_symbol(); + if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) { + this.menu.toggle(); + return true; + } else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) { + this.menu.close(); + return true; + } else if (symbol == Clutter.KEY_Down) { + if (!this.menu.isOpen) + this.menu.toggle(); + this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false); + return true; + } else + return false; + } + +}; diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index ee4536cf60..c79d1974c9 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -116,6 +116,12 @@ WorkspacesView.prototype = { let modifiers = Cinnamon.get_event_state(event); let symbol = event.get_key_symbol(); + let ctrlAltMask = Clutter.ModifierType.CONTROL_MASK | Clutter.ModifierType.MOD1_MASK; + + if (symbol === Clutter.m && !(modifiers & ctrlAltMask)) { + activeWorkspace.showMenuForSelectedWindow(); + return true; + } if (symbol === Clutter.w && modifiers & Clutter.ModifierType.CONTROL_MASK) { activeWorkspace.closeSelectedWindow(); From f3b949c157fa72f4d484859588aebeca7e1886e1 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:16 +0200 Subject: [PATCH 17/74] [Scale] Syncstacking should only affect the permanent sort order the first time it's called. --- js/ui/workspace.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 753ea1136f..7bfe093d49 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1260,14 +1260,20 @@ Workspace.prototype = { }, syncStacking: function(stackIndices) { - this._windows.sort(function (a, b) { + // Only on the first invocation do we want to affect the + // permanent sort order. After that, we don't want major + // upheavals to the sort order. + let clones = !this._stackedOnce ? this._windows : this._windows.slice(); + this._stackedOnce = true; + + clones.sort(function (a, b) { let minimizedA = a.metaWindow.minimized ? 1 : 0; let minimizedB = b.metaWindow.minimized ? 1 : 0; let minimizedDiff = minimizedA - minimizedB; return minimizedDiff || stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; }); - let clones = this._windows.slice().reverse(); + let clones = clones.slice().reverse(); let below = this._dropRect; for (let i = 0; i < clones.length; i++) { let clone = clones[i]; From 813dd9514fab5fe0beeebcbcb06d11e1c5648d7e Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:17 +0200 Subject: [PATCH 18/74] [Scale] Split Scale into one view per monitor. --- js/ui/workspace.js | 229 ++++++++++++++++++++++++++++++++++------ js/ui/workspacesView.js | 33 +----- 2 files changed, 201 insertions(+), 61 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 7bfe093d49..9db991b6e4 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -733,15 +733,12 @@ const WindowPositionFlags = { ANIMATE: 1 << 1 }; -/** - * @metaWorkspace: a #Meta.Workspace, or null - */ -function Workspace(metaWorkspace, monitorIndex) { - this._init(metaWorkspace, monitorIndex); +function WorkspaceMonitor(metaWorkspace, monitorIndex, hasFocus) { + this._init(metaWorkspace, monitorIndex, hasFocus); } -Workspace.prototype = { - _init : function(metaWorkspace, monitorIndex) { +WorkspaceMonitor.prototype = { + _init : function(metaWorkspace, monitorIndex, hasFocus) { // When dragging a window, we use this slot for reserve space. this._reservedSlot = null; this.metaWorkspace = metaWorkspace; @@ -764,7 +761,7 @@ Workspace.prototype = { this._dropRect._delegate = this; this.actor.add_actor(this._dropRect); - this.actor.add_actor(this._windowOverlaysGroup); + this.actor.add_actor(this._windowOverlaysGroup); this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); @@ -786,11 +783,29 @@ Workspace.prototype = { this._windowRemovedId = this.metaWorkspace.connect('window-removed', Lang.bind(this, this._windowRemoved)); } + this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor', + Lang.bind(this, this._windowEnteredMonitor)); + this._windowLeftMonitorId = global.screen.connect('window-left-monitor', + Lang.bind(this, this._windowLeftMonitor)); this._repositionWindowsId = 0; this.leavingOverview = false; - this._kbWindowIndex = -1; // index of the current keyboard-selected window + this._kbWindowIndex = 0; // index of the current keyboard-selected window + if (hasFocus) { + this.onInitialPositionWindows = Lang.bind(this, function() { + // default-select the first window + this.selectAnotherWindow(Clutter.Home); + Mainloop.idle_add(Lang.bind(this, function() { + // if keyboard focus is at the default position, + // make sure that the close button is drawn, + // which must done a little bit later + if (this._kbWindowIndex === 0) { + this.selectAnotherWindow(Clutter.Home); + } + })); + }); + } }, selectAnotherWindow: function(symbol) { @@ -846,10 +861,10 @@ Workspace.prototype = { nextIndex = calcNewIndex(-1); } } - else if (symbol === Clutter.Left || symbol === Clutter.ISO_Left_Tab || symbol === Clutter.Up) { + else if (symbol === Clutter.Left || symbol === Clutter.Up) { nextIndex = (currentIndex < 1 ? numWindows : currentIndex) - 1; } - else if (symbol === Clutter.Right || symbol === Clutter.Tab || symbol === Clutter.Down) { + else if (symbol === Clutter.Right || symbol === Clutter.Down) { nextIndex = (currentIndex + 1) % numWindows; } else if (symbol === Clutter.Home) { @@ -863,18 +878,23 @@ Workspace.prototype = { } if (currentIndex !== nextIndex) { - if (currentIndex > -1 && currentIndex < numWindows) { - this._windows[currentIndex].overlay.setSelected(false); - } + this.showActiveSelection(false); } - this._kbWindowIndex = currentIndex = nextIndex; - if (currentIndex > -1 && currentIndex < numWindows) { - this._windows[currentIndex].overlay.setSelected(true); - } + this.showActiveSelection(true); return true; }, + get windowCount() { + return this._windows.length; + }, + + showActiveSelection: function(show) { + if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { + this._windows[this._kbWindowIndex].overlay.setSelected(show); + } + }, + showMenuForSelectedWindow: function() { if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { let window = this._windows[this._kbWindowIndex]; @@ -1245,17 +1265,9 @@ Workspace.prototype = { this._showWindowOverlay(clone, isOnCurrentWorkspace); } } - // default-select the first window - if (this._kbWindowIndex < 0) { - this.selectAnotherWindow(Clutter.Home); - Mainloop.idle_add(Lang.bind(this, function() { - // if keyboard focus is at the default position, - // make sure that the close button is drawn, - // which must done a little bit later - if (this._kbWindowIndex === 0) { - this.selectAnotherWindow(Clutter.Home); - } - })); + if (this.onInitialPositionWindows) { + this.onInitialPositionWindows(); + this.onInitialPositionWindows = null; } }, @@ -1469,6 +1481,18 @@ Workspace.prototype = { this._doRemoveWindow(metaWin); }, + _windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) { + if (monitorIndex == this.monitorIndex) { + this._doAddWindow(metaWin); + } + }, + + _windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) { + if (monitorIndex == this.monitorIndex) { + this._doRemoveWindow(metaWin); + } + }, + // check for maximized windows on the workspace hasMaximizedWindows: function() { for (let i = 0; i < this._windows.length; i++) { @@ -1553,6 +1577,8 @@ Workspace.prototype = { this.metaWorkspace.disconnect(this._windowAddedId); this.metaWorkspace.disconnect(this._windowRemovedId); } + global.screen.disconnect(this._windowEnteredMonitorId); + global.screen.disconnect(this._windowLeftMonitorId); if (this._repositionWindowsId > 0) Mainloop.source_remove(this._repositionWindowsId); @@ -1573,7 +1599,7 @@ Workspace.prototype = { // Tests if @win belongs to this workspace _isMyWindow : function (win) { - return (this.metaWorkspace == null || Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index())); + return (this.metaWorkspace == null || Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index()) && (!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex)); }, // Tests if @win should be shown in the Overview @@ -1715,7 +1741,7 @@ Workspace.prototype = { } }; -Signals.addSignalMethods(Workspace.prototype); +Signals.addSignalMethods(WorkspaceMonitor.prototype); function AppMenuButtonRightClickMenu(actor, metaWindow, orientation) { this._init(actor, metaWindow, orientation); @@ -1755,7 +1781,22 @@ AppMenuButtonRightClickMenu.prototype = { this.itemOnAllWorkspaces = new PopupMenu.PopupMenuItem(_("Visible on all workspaces")); this.itemOnAllWorkspaces.connect('activate', Lang.bind(this, this._toggleOnAllWorkspaces)); - let items = [ + let monitorItems = []; + if (Main.layoutManager.monitors.length > 1) { + Main.layoutManager.monitors.forEach(function(monitor, index) { + if (index !== metaWindow.get_monitor()) { + let itemChangeMonitor = new PopupMenu.PopupMenuItem( + _("Move to monitor %d").format(index + 1)); + itemChangeMonitor.connect('activate', Lang.bind(this, function() { + metaWindow.move_to_monitor(index); + })); + monitorItems.push(itemChangeMonitor); + } + }, this); + monitorItems.push(new PopupMenu.PopupSeparatorMenuItem()); + } + + let items = monitorItems.concat([ this.itemOnAllWorkspaces, this.itemMoveToLeftWorkspace, this.itemMoveToRightWorkspace, @@ -1763,7 +1804,7 @@ AppMenuButtonRightClickMenu.prototype = { this.itemMinimizeWindow, this.itemMaximizeWindow, this.itemCloseWindow - ]; + ]); (orientation == St.Side.BOTTOM ? items : items.reverse()).forEach(function(item) { this.addMenuItem(item); }, this); @@ -1864,3 +1905,125 @@ AppMenuButtonRightClickMenu.prototype = { } }; + +function Workspace(metaWorkspace) { + this._init(metaWorkspace); +} + +Workspace.prototype = { + _init : function(metaWorkspace) { + this.metaWorkspace = metaWorkspace; + this.actor = new Clutter.Group(); + this.actor.set_size(0, 0); + this._monitors = []; + let focusIndex = Main.layoutManager.focusIndex; + Main.layoutManager.monitors.forEach(function(monitor, monitorIndex) { + let m = new WorkspaceMonitor(metaWorkspace, monitorIndex, monitorIndex === focusIndex) + this._monitors.push(m); + this.actor.add_actor(m.actor); + }, this); + this.currentMonitorIndex = focusIndex; + }, + + _onKeyPress: function(actor, event) { + let modifiers = Cinnamon.get_event_state(event); + let symbol = event.get_key_symbol(); + let ctrlAltMask = Clutter.ModifierType.CONTROL_MASK | Clutter.ModifierType.MOD1_MASK; + + if ((symbol === Clutter.ISO_Left_Tab || symbol === Clutter.Tab) && !(modifiers & ctrlAltMask)) { + if (this._monitors.length < 2) return true; + + let previousIndex = this.currentMonitorIndex; + let increment = symbol === Clutter.ISO_Left_Tab ? -1 : 1; + for (let i = 0; i < this._monitors.length; ++i) { + this.currentMonitorIndex = (this._monitors.length + this.currentMonitorIndex + increment) % this._monitors.length; + if (this._monitors[this.currentMonitorIndex].windowCount > 0) { + break; + } + } + this._monitors[previousIndex].showActiveSelection(false); + this._monitors[this.currentMonitorIndex].showActiveSelection(true); + return true; + } + + let activeMonitor = this._monitors[this.currentMonitorIndex]; + + if (symbol === Clutter.m && !(modifiers & ctrlAltMask)) { + activeMonitor.showMenuForSelectedWindow(); + return true; + } + + if (symbol === Clutter.w && modifiers & Clutter.ModifierType.CONTROL_MASK) { + activeMonitor.closeSelectedWindow(); + return true; + } + + if (symbol === Clutter.Return || symbol === Clutter.KEY_space) { + if (activeMonitor.activateSelectedWindow()) { + return true; + } + Main.overview.hide(); + return true; + } + return activeMonitor.selectAnotherWindow(symbol); + }, + + destroy: function() { + this._monitors.forEach(function(monitor) { + monitor.destroy(); + }, this); + this.actor.destroy(); + }, + + setGeometry: function(x, y, width, height, spacing_unused) { + let primary = Main.layoutManager.primaryMonitor; + let spacing = (primary.width - width) / 2; + this._monitors.forEach(function(monitor, index) { + let mon = Main.layoutManager.monitors[index]; + monitor.setGeometry(mon.x + spacing, mon.y + spacing, mon.width - spacing, mon.height - spacing); + }, this); + }, + + selectAnotherWindow: function(symbol) { + this._monitors[this.currentMonitorIndex].selectAnotherWindow(symbol); + }, + + zoomFromOverview: function() { + this._monitors.forEach(function(monitor) { + monitor.zoomFromOverview(); + }, this); + }, + + zoomToOverview: function() { + this._monitors.forEach(function(monitor) { + monitor.zoomToOverview(); + }, this); + }, + + hasMaximizedWindows: function() { + let has = false; + this._monitors.forEach(function(monitor) { + has = has || monitor.hasMaximizedWindows(); + }, this); + return has; + }, + + showWindowsOverlays: function() { + this._monitors.forEach(function(monitor) { + monitor.showWindowsOverlays(); + }, this); + }, + + hideWindowsOverlays: function() { + this._monitors.forEach(function(monitor) { + monitor.hideWindowsOverlays(); + }, this); + }, + + syncStacking: function(arg1) { + this._monitors.forEach(function(monitor) { + monitor.syncStacking(arg1); + }, this); + } +}; +Signals.addSignalMethods(Workspace.prototype); diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index c79d1974c9..fdf612d676 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -78,8 +78,8 @@ WorkspacesView.prototype = { this._overviewShownId = Main.overview.connect('shown', Lang.bind(this, function() { - this.actor.set_clip(this._clipX, this._clipY, - this._clipWidth, this._clipHeight); + // this.actor.set_clip(this._clipX, this._clipY, + // this._clipWidth, this._clipHeight); })); this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, @@ -113,29 +113,7 @@ WorkspacesView.prototype = { _onStageKeyPress: function(actor, event) { let activeWorkspaceIndex = global.screen.get_active_workspace_index(); let activeWorkspace = this._workspaces[activeWorkspaceIndex]; - - let modifiers = Cinnamon.get_event_state(event); - let symbol = event.get_key_symbol(); - let ctrlAltMask = Clutter.ModifierType.CONTROL_MASK | Clutter.ModifierType.MOD1_MASK; - - if (symbol === Clutter.m && !(modifiers & ctrlAltMask)) { - activeWorkspace.showMenuForSelectedWindow(); - return true; - } - - if (symbol === Clutter.w && modifiers & Clutter.ModifierType.CONTROL_MASK) { - activeWorkspace.closeSelectedWindow(); - return true; - } - - if (symbol === Clutter.Return || symbol === Clutter.KEY_space) { - if (activeWorkspace.activateSelectedWindow()) { - return true; - } - Main.overview.hide(); - return true; - } - return activeWorkspace.selectAnotherWindow(symbol); + return activeWorkspace._onKeyPress(actor, event); }, setGeometry: function(x, y, width, height, spacing) { @@ -149,7 +127,7 @@ WorkspacesView.prototype = { this._workspaceRatioSpacing = spacing; for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].setGeometry(x, y, width, height); + this._workspaces[i].setGeometry(x, y, width, height, spacing); }, setClipRect: function(x, y, width, height) { @@ -298,7 +276,7 @@ WorkspacesView.prototype = { if (newNumWorkspaces > oldNumWorkspaces) { for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) { this._workspaces[w].setGeometry(this._x, this._y, - this._width, this._height); + this._width, this._height, this._workspaceRatioSpacing); this.actor.add_actor(this._workspaces[w].actor); } @@ -702,7 +680,6 @@ WorkspacesDisplay.prototype = { width = (fullWidth / fullHeight) * height; let difference = fullWidth - width; x += difference / 2; - this.workspacesView.setGeometry(x, y, width, height, difference); }, From b8d9a3e85e150fcf809c37bd150d96c2ccf50c2f Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:19 +0200 Subject: [PATCH 19/74] [Scale] Right-click on clone to show context menu. --- js/ui/overview.js | 4 ++- js/ui/workspace.js | 76 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index 1454017153..fc9cb8d9eb 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -298,9 +298,10 @@ Overview.prototype = { }, _onButtonPress: function(actor, event) { + this.emit('overview-background-button-press', actor, event); if (this._scrollDirection == SwipeScrollDirection.NONE || event.get_button() != 1) - return; + return false; let [stageX, stageY] = event.get_coords(); this._dragStartX = this._dragX = stageX; @@ -310,6 +311,7 @@ Overview.prototype = { this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); this.emit('swipe-scroll-begin'); + return true; }, _onCapturedEvent: function(actor, event) { diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 9db991b6e4..bda252085e 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -63,6 +63,16 @@ function ScaledPoint(x, y, scaleX, scaleY) { [this.x, this.y, this.scaleX, this.scaleY] = arguments; } +var menuShowing = null; +var menuClone = null; +function closeContextMenu(requestor) { + let requestorShowingMenu = menuClone && menuClone === requestor; + if (menuShowing) { + menuShowing.close(); + } + return requestorShowingMenu; +} + ScaledPoint.prototype = { getPosition : function() { return [this.x, this.y]; @@ -142,6 +152,7 @@ WindowClone.prototype = { //let clickAction = new Clutter.ClickAction(); this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease)); + this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); //clickAction.connect('long-press', Lang.bind(this, this._onLongPress)); //this.actor.add_action(clickAction); @@ -350,15 +361,30 @@ WindowClone.prototype = { this._zoomStep = undefined; }, + _onButtonPress: function(actor, event) { + // a button-press on a clone already showing a menu should + // not open a new-menu, only close the current menu. + this.menuCancelled = closeContextMenu(this); + }, + _onButtonRelease: function(actor, event) { if ( event.get_button()==1 ) { this._selected = true; this.emit('selected', global.get_current_time()); + return true; } if (event.get_button()==2){ this.emit('closed', global.get_current_time()); + return true; } - return true; + if (event.get_button()==3){ + if (!this.menuCancelled) { + this.emit('context-menu-requested', global.get_current_time()); + } + this.menuCancelled = false; + return true; + } + return false; }, _onLongPress: function(action, actor, state) { @@ -764,6 +790,9 @@ WorkspaceMonitor.prototype = { this.actor.add_actor(this._windowOverlaysGroup); this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); + Main.overview.connect('overview-background-button-press', function() { + closeContextMenu(); + }); let windows = global.get_window_actors().filter(this._isMyWindow, this); @@ -885,22 +914,24 @@ WorkspaceMonitor.prototype = { return true; }, - get windowCount() { - return this._windows.length; - }, - showActiveSelection: function(show) { if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { this._windows[this._kbWindowIndex].overlay.setSelected(show); } }, + + _onCloneContextMenuRequested: function(clone) { + menuShowing = new WindowContextMenu(clone.actor, clone.metaWindow, function() { + menuShowing = null; menuClone = null; + }); + menuClone = clone; + menuShowing.toggle(); + }, showMenuForSelectedWindow: function() { if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { let window = this._windows[this._kbWindowIndex]; - let menu = new AppMenuButtonRightClickMenu(window.actor, window.metaWindow, "top"); - menu.toggle(); - return true; + this._onCloneContextMenuRequested(window); } return false; }, @@ -1197,6 +1228,7 @@ WorkspaceMonitor.prototype = { this._repositionWindowsId = 0; } + closeContextMenu(); let clones = this._windows.slice(); if (this._reservedSlot) clones.push(this._reservedSlot); @@ -1567,6 +1599,7 @@ WorkspaceMonitor.prototype = { }, _onDestroy: function(actor) { + closeContextMenu(); if (this._overviewHiddenId) { Main.overview.disconnect(this._overviewHiddenId); this._overviewHiddenId = 0; @@ -1617,6 +1650,8 @@ WorkspaceMonitor.prototype = { Lang.bind(this, this._onCloneSelected)); clone.connect('closed', Lang.bind(this, this._onCloneClosed)); + clone.connect('context-menu-requested', + Lang.bind(this, this._onCloneContextMenuRequested)); clone.connect('drag-begin', Lang.bind(this, function(clone) { Main.overview.beginWindowDrag(); @@ -1743,18 +1778,20 @@ WorkspaceMonitor.prototype = { Signals.addSignalMethods(WorkspaceMonitor.prototype); -function AppMenuButtonRightClickMenu(actor, metaWindow, orientation) { - this._init(actor, metaWindow, orientation); +function WindowContextMenu(actor, metaWindow, onClose) { + this._init(actor, metaWindow, onClose); } -AppMenuButtonRightClickMenu.prototype = { +WindowContextMenu.prototype = { __proto__: PopupMenu.PopupComboMenu.prototype, - _init: function(actor, metaWindow, orientation) { + _init: function(actor, metaWindow, onClose) { //take care of menu initialization PopupMenu.PopupComboMenu.prototype._init.call(this, actor); Main.uiGroup.add_actor(this.actor); this.actor.hide(); + let orientation = St.Side.TOP; + this.onClose = onClose; actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress)); this.connect('open-state-changed', Lang.bind(this, this._onToggled)); @@ -1811,8 +1848,9 @@ AppMenuButtonRightClickMenu.prototype = { this.setActiveItem(0); }, - _onToggled: function(actor, event){ - if (!event) { + _onToggled: function(actor, opening){ + if (!opening) { + this.onClose(); this.destroy(); return; } @@ -1937,7 +1975,7 @@ Workspace.prototype = { let increment = symbol === Clutter.ISO_Left_Tab ? -1 : 1; for (let i = 0; i < this._monitors.length; ++i) { this.currentMonitorIndex = (this._monitors.length + this.currentMonitorIndex + increment) % this._monitors.length; - if (this._monitors[this.currentMonitorIndex].windowCount > 0) { + if (!this._monitors[this.currentMonitorIndex].isEmpty()) { break; } } @@ -2008,6 +2046,14 @@ Workspace.prototype = { return has; }, + isEmpty: function() { + let hasWindows = false; + this._monitors.forEach(function(monitor) { + hasWindows = hasWindows || !monitor.isEmpty(); + }, this); + return !hasWindows; + }, + showWindowsOverlays: function() { this._monitors.forEach(function(monitor) { monitor.showWindowsOverlays(); From e8a130b4f2f1fcfe8c7701d281b6020273c99cc0 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:20 +0200 Subject: [PATCH 20/74] [Scale, Multi-monitor] Turn off workspace-shift animation if more than one monitor is present. --- js/ui/workspacesView.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index fdf612d676..ec9e8fadc3 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -190,7 +190,9 @@ WorkspacesView.prototype = { _updateWorkspaceActors: function(showAnimation) { let active = global.screen.get_active_workspace_index(); - this._animating = showAnimation; + // Animation is turned off in a multi-manager scenario till we fix + // the animations so that they respect the monitor boundaries. + this._animating = Main.layoutManager.monitors.length < 2 && showAnimation; for (let w = 0; w < this._workspaces.length; w++) { let workspace = this._workspaces[w]; @@ -199,7 +201,7 @@ WorkspacesView.prototype = { let x = (w - active) * (this._width + this._spacing + this._workspaceRatioSpacing); - if (showAnimation) { + if (this._animating) { let params = { x: x, time: WORKSPACE_SWITCH_TIME, transition: 'easeOutQuad' From da0078cbae45eca3b398792d4f45ca89d47b48f8 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:21 +0200 Subject: [PATCH 21/74] [Scale] Always use the entire screen as the "porthole". --- js/ui/overview.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index fc9cb8d9eb..f817767529 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -119,8 +119,7 @@ Overview.prototype = { let backgroundShade = new St.Bin({style_class: 'workspace-overview-background-shade'}); this._background.add_actor(backgroundShade); - let porthole = Main.layoutManager.getPorthole(); - backgroundShade.set_size(porthole.width, porthole.height); + backgroundShade.set_size(global.screen_width, global.screen_height); this._desktopFade = new St.Bin(); global.overlay_group.add_actor(this._desktopFade); From 2d1559dc3f1ae045e6f9cbed9b4121d2b116e0ef Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:23 +0200 Subject: [PATCH 22/74] [Scale] Resize properly on monitor change. --- js/ui/overview.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index f817767529..be42f13272 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -117,9 +117,8 @@ Overview.prototype = { let desktopBackground = Meta.BackgroundActor.new_for_screen(global.screen); this._background.add_actor(desktopBackground); - let backgroundShade = new St.Bin({style_class: 'workspace-overview-background-shade'}); - this._background.add_actor(backgroundShade); - backgroundShade.set_size(global.screen_width, global.screen_height); + this._backgroundShade = new St.Bin({style_class: 'workspace-overview-background-shade'}); + this._background.add_actor(this._backgroundShade); this._desktopFade = new St.Bin(); global.overlay_group.add_actor(this._desktopFade); @@ -471,7 +470,8 @@ Overview.prototype = { this._group.set_size(primary.width, primary.height); this._coverPane.set_position(0, 0); - this._coverPane.set_size(primary.width, contentHeight); + this._coverPane.set_size(global.screen_width, global.screen_height); + this._backgroundShade.set_size(global.screen_width, global.screen_height); let viewWidth = primary.width - 2 * this._spacing; let viewHeight = contentHeight - this._spacing; From 0b9979d270c5f99d287d2ccc4980c2f70e36e80f Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:24 +0200 Subject: [PATCH 23/74] [Scale] Refactoring, get rid of ViewSelector. --- js/Makefile.am | 1 - js/perf/core.js | 9 -- js/ui/overview.js | 15 +- js/ui/viewSelector.js | 316 ---------------------------------------- js/ui/workspacesView.js | 8 + 5 files changed, 12 insertions(+), 337 deletions(-) delete mode 100644 js/ui/viewSelector.js diff --git a/js/Makefile.am b/js/Makefile.am index 690c04e0a6..90fb30255c 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -61,7 +61,6 @@ nobase_dist_js_DATA = \ ui/themeManager.js \ ui/tooltips.js \ ui/tweener.js \ - ui/viewSelector.js \ ui/windowAttentionHandler.js \ ui/windowManager.js \ ui/workspace.js \ diff --git a/js/perf/core.js b/js/perf/core.js index a23c66a1aa..c84d03fd09 100644 --- a/js/perf/core.js +++ b/js/perf/core.js @@ -110,15 +110,6 @@ function run() { Main.overview.show(); yield Scripting.waitLeisure(); - - for (let i = 0; i < 2; i++) { - Scripting.scriptEvent('applicationsShowStart'); - Main.overview._viewSelector.switchTab('applications'); - yield Scripting.waitLeisure(); - Scripting.scriptEvent('applicationsShowDone'); - Main.overview._viewSelector.switchTab('windows'); - yield Scripting.waitLeisure(); - } } let showingOverview = false; diff --git a/js/ui/overview.js b/js/ui/overview.js index be42f13272..d4c6a92691 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -15,7 +15,6 @@ const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; const Params = imports.misc.params; const Tweener = imports.ui.tweener; -const ViewSelector = imports.ui.viewSelector; const WorkspacesView = imports.ui.workspacesView; // Time for initial animation going into Overview mode @@ -192,22 +191,16 @@ Overview.prototype = { this._cinnamonInfo = new CinnamonInfo(); - this._viewSelector = new ViewSelector.ViewSelector(); - this._group.add_actor(this._viewSelector.actor); - this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay(); - this._viewSelector.addViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic'); - + this._group.add_actor(this._workspacesDisplay.actor); Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout)); this._relayout(); }, addSearchProvider: function(provider) { - this._viewSelector.addSearchProvider(provider); }, removeSearchProvider: function(provider) { - this._viewSelector.removeSearchProvider(provider); }, setMessage: function(text, undoCallback, undoLabel) { @@ -478,9 +471,9 @@ Overview.prototype = { let viewY = this._spacing; let viewX = rtl ? 0 : this._spacing; - this._viewSelector.actor.set_position(viewX, viewY); - this._viewSelector.actor.set_size(viewWidth, viewHeight); - this._viewSelector.actor.hide(); + this._workspacesDisplay.actor.set_position(viewX, viewY); + this._workspacesDisplay.actor.set_size(viewWidth, viewHeight); + this._workspacesDisplay.actor.hide(); }, //// Public methods //// diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js deleted file mode 100644 index c62bc032c3..0000000000 --- a/js/ui/viewSelector.js +++ /dev/null @@ -1,316 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -const Clutter = imports.gi.Clutter; -const Gtk = imports.gi.Gtk; -const Meta = imports.gi.Meta; -const Signals = imports.signals; -const Lang = imports.lang; -const Cinnamon = imports.gi.Cinnamon; -const St = imports.gi.St; - -const Main = imports.ui.main; -const Tweener = imports.ui.tweener; - -function BaseTab(titleActor, pageActor, name, a11yIcon) { - this._init(titleActor, pageActor, name, a11yIcon); -} - -BaseTab.prototype = { - _init: function(titleActor, pageActor, name, a11yIcon) { - this.title = titleActor; - this.page = new St.Bin({ child: pageActor, - x_align: St.Align.START, - y_align: St.Align.START, - x_fill: true, - y_fill: true, - style_class: 'view-tab-page' }); - - this.visible = false; - }, - - show: function(animate) { - this.visible = true; - this.page.show(); - - if (!animate) - return; - - this.page.opacity = 0; - Tweener.addTween(this.page, - { opacity: 255, - time: 0.1, - transition: 'easeOutQuad' }); - }, - - hide: function() { - this.visible = false; - Tweener.addTween(this.page, - { opacity: 0, - time: 0.1, - transition: 'easeOutQuad', - onComplete: Lang.bind(this, - function() { - this.page.hide(); - }) - }); - }, - - _a11yFocus: function() { - this._activate(); - this.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); - }, - - _activate: function() { - this.emit('activated'); - } -}; -Signals.addSignalMethods(BaseTab.prototype); - - -function ViewTab(id, label, pageActor, a11yIcon) { - this._init(id, label, pageActor, a11yIcon); -} - -ViewTab.prototype = { - __proto__: BaseTab.prototype, - - _init: function(id, label, pageActor, a11yIcon) { - this.id = id; - - let titleActor = new St.Button({ label: label, - style_class: 'view-tab-title' }); - titleActor.connect('clicked', Lang.bind(this, this._activate)); - - BaseTab.prototype._init.call(this, titleActor, pageActor, label, a11yIcon); - } -}; - -function ViewSelector() { - this._init(); -} - -ViewSelector.prototype = { - _init : function() { - this.actor = new St.BoxLayout({ name: 'viewSelector', - vertical: true }); - - // The tab bar is located at the top of the view selector and - // holds "normal" tab labels. - this._tabBar = new Cinnamon.GenericContainer(); - /* this._tabBar.connect('get-preferred-width', - Lang.bind(this, this._getPreferredTabBarWidth)); - this._tabBar.connect('get-preferred-height', - Lang.bind(this, this._getPreferredTabBarHeight)); - this._tabBar.connect('allocate', - Lang.bind(this, this._allocateTabBar));*/ - this.actor.add(this._tabBar); - - // Box to hold "normal" tab labels - this._tabBox = new St.BoxLayout({ name: 'viewSelectorTabBar' }); - this._tabBar.add_actor(this._tabBox); - - // The page area holds the tab pages. Every page is given the - // area's full allocation, so that the pages would appear on top - // of each other if the inactive ones weren't hidden. - this._pageArea = new Cinnamon.Stack(); - this.actor.add(this._pageArea, { x_fill: true, - y_fill: true, - expand: true }); - - this._tabs = []; - this._activeTab = null; - - Main.overview.connect('item-drag-begin', - Lang.bind(this, this._switchDefaultTab)); - - this._stageKeyPressId = 0; - Main.overview.connect('showing', Lang.bind(this, - function () { - this._switchDefaultTab(); - this._stageKeyPressId = global.stage.connect('key-press-event', - Lang.bind(this, this._onStageKeyPress)); - })); - Main.overview.connect('hiding', Lang.bind(this, - function () { - this._switchDefaultTab(); - if (this._stageKeyPressId != 0) { - global.stage.disconnect(this._stageKeyPressId); - this._stageKeyPressId = 0; - } - })); - - // Public constraints which may be used to tie actors' height or - // vertical position to the current tab's content; as the content's - // height and position depend on the view selector's style properties - // (e.g. font size, padding, spacing, ...) it would be extremely hard - // and ugly to get these from the outside. While it would be possible - // to use position and height properties directly, outside code would - // need to ensure that the content is properly allocated before - // accessing the properties. - this.constrainY = new Clutter.BindConstraint({ source: this._pageArea, - coordinate: Clutter.BindCoordinate.Y }); - this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea, - coordinate: Clutter.BindCoordinate.HEIGHT }); - }, - - _addTab: function(tab) { - tab.page.hide(); - this._pageArea.add_actor(tab.page); - tab.connect('activated', Lang.bind(this, function(tab) { - this._switchTab(tab); - })); - }, - - addViewTab: function(id, title, pageActor, a11yIcon) { - let viewTab = new ViewTab(id, title, pageActor, a11yIcon); - this._tabs.push(viewTab); - this._tabBox.add(viewTab.title); - this._addTab(viewTab); - }, - - _switchTab: function(tab) { - let firstSwitch = this._activeTab == null; - - if (this._activeTab && this._activeTab.visible) { - if (this._activeTab == tab) - return; - this._activeTab.title.remove_style_pseudo_class('selected'); - this._activeTab.hide(); - } - - - tab.title.add_style_pseudo_class('selected'); - this._activeTab = tab; - - // Only fade when switching between tabs, - // not when setting the initially selected one. - if (!tab.visible) - tab.show(!firstSwitch); - - // Pull a Meg Ryan: - if (!firstSwitch && Main.overview.workspaces) { - if (tab != this._tabs[0]) { - Tweener.addTween(Main.overview.workspaces.actor, - { opacity: 0, - time: 0.1, - transition: 'easeOutQuad', - onComplete: Lang.bind(this, - function() { - Main.overview.workspaces.actor.hide(); - Main.overview.workspaces.actor.opacity = 255; - }) - }); - } else { - Main.overview.workspaces.actor.opacity = 0; - Main.overview.workspaces.actor.show(); - Tweener.addTween(Main.overview.workspaces.actor, - { opacity: 255, - time: 0.1, - transition: 'easeOutQuad' }); - } - } - }, - - switchTab: function(id) { - for (let i = 0; i < this._tabs.length; i++) - if (this._tabs[i].id == id) { - this._switchTab(this._tabs[i]); - break; - } - }, - - _switchDefaultTab: function() { - if (this._tabs.length > 0) - this._switchTab(this._tabs[0]); - }, - - _nextTab: function() { - if (this._tabs.length == 0 || - this._tabs[this._tabs.length - 1] == this._activeTab) - return; - - for (let i = 0; i < this._tabs.length; i++) - if (this._tabs[i] == this._activeTab) { - this._switchTab(this._tabs[i + 1]); - return; - } - }, - - _prevTab: function() { - if (this._tabs.length == 0 || this._tabs[0] == this._activeTab) - return; - - for (let i = 0; i < this._tabs.length; i++) - if (this._tabs[i] == this._activeTab) { - this._switchTab(this._tabs[i - 1]); - return; - } - }, - - _getPreferredTabBarWidth: function(box, forHeight, alloc) { - let children = box.get_children(); - for (let i = 0; i < children.length; i++) { - let [childMin, childNat] = children[i].get_preferred_width(forHeight); - alloc.min_size += childMin; - alloc.natural_size += childNat; - } - }, - - _getPreferredTabBarHeight: function(box, forWidth, alloc) { - let children = box.get_children(); - for (let i = 0; i < children.length; i++) { - let [childMin, childNatural] = children[i].get_preferred_height(forWidth); - if (childMin > alloc.min_size) - alloc.min_size = childMin; - if (childNatural > alloc.natural_size) - alloc.natural_size = childNatural; - } - }, - - _allocateTabBar: function(container, box, flags) { - let allocWidth = box.x2 - box.x1; - let allocHeight = box.y2 - box.y1; - - let [barMinWidth, barNatWidth] = this._tabBox.get_preferred_width(-1); - let childBox = new Clutter.ActorBox(); - childBox.y1 = 0; - childBox.y2 = allocHeight; - if (this.actor.get_direction() == St.TextDirection.RTL) { - childBox.x1 = allocWidth - barNatWidth; - childBox.x2 = allocWidth; - } else { - childBox.x1 = 0; - childBox.x2 = barNatWidth; - } - this._tabBox.allocate(childBox, flags); - - Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, - function() { - this.constrainY.offset = this.actor.y; - })); - }, - - _onStageKeyPress: function(actor, event) { - let modifiers = Cinnamon.get_event_state(event); - let symbol = event.get_key_symbol(); - - if (symbol == Clutter.Escape) { - Main.overview.hide(); - return true; - } else if (modifiers & Clutter.ModifierType.CONTROL_MASK) { - if (symbol == Clutter.Page_Up) { - this._prevTab(); - return true; - } else if (symbol == Clutter.Page_Down) { - this._nextTab(); - return true; - } - } else if (Clutter.keysym_to_unicode(symbol)) { - - } - return false; - } - - -}; -Signals.addSignalMethods(ViewSelector.prototype); diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index ec9e8fadc3..c80f28cb95 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -111,6 +111,14 @@ WorkspacesView.prototype = { }, _onStageKeyPress: function(actor, event) { + let modifiers = Cinnamon.get_event_state(event); + let symbol = event.get_key_symbol(); + + if (symbol == Clutter.Escape) + { + Main.overview.hide(); + return true; + } let activeWorkspaceIndex = global.screen.get_active_workspace_index(); let activeWorkspace = this._workspaces[activeWorkspaceIndex]; return activeWorkspace._onKeyPress(actor, event); From 81141ffc29bcf75e899a371b167f7c1c8ef3bb05 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 08:07:25 +0200 Subject: [PATCH 24/74] [Scale] Refactoring, keep fewer objects alive all the time. --- js/ui/overview.js | 79 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index d4c6a92691..1bec967515 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -104,24 +104,6 @@ Overview.prototype = { return; } - this._background = new Clutter.Group(); - this._background.hide(); - global.overlay_group.add_actor(this._background); - - // The main BackgroundActor is inside global.window_group which is - // hidden when displaying the overview, so we create a new - // one. Instances of this class share a single CoglTexture behind the - // scenes which allows us to show the background with different - // rendering options without duplicating the texture data. - let desktopBackground = Meta.BackgroundActor.new_for_screen(global.screen); - this._background.add_actor(desktopBackground); - - this._backgroundShade = new St.Bin({style_class: 'workspace-overview-background-shade'}); - this._background.add_actor(this._backgroundShade); - - this._desktopFade = new St.Bin(); - global.overlay_group.add_actor(this._desktopFade); - this._spacing = 0; this._group = new St.Group({ name: 'overview', @@ -136,6 +118,8 @@ Overview.prototype = { this._relayout(); } })); + this._group.hide(); + global.overlay_group.add_actor(this._group); this._scrollDirection = SwipeScrollDirection.NONE; this._scrollAdjustment = null; @@ -151,19 +135,6 @@ Overview.prototype = { this.animationInProgress = false; this._hideInProgress = false; - // During transitions, we raise this to the top to avoid having the overview - // area be reactive; it causes too many issues such as mouseover handlers in the workspaces. - this._coverPane = new Clutter.Rectangle({ opacity: 0, - reactive: true }); - this._group.add_actor(this._coverPane); - this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; })); - - - this._group.hide(); - global.overlay_group.add_actor(this._group); - - this._coverPane.hide(); - // XDND this._dragMonitor = { dragMotion: Lang.bind(this, this._onDragMotion) @@ -442,9 +413,6 @@ Overview.prototype = { return null; let clone = new Clutter.Clone({ source: windows[0].get_texture() }); - clone.source.connect('destroy', Lang.bind(this, function() { - clone.destroy(); - })); return clone; }, @@ -461,10 +429,6 @@ Overview.prototype = { this._group.set_position(primary.x, primary.y); this._group.set_size(primary.width, primary.height); - - this._coverPane.set_position(0, 0); - this._coverPane.set_size(global.screen_width, global.screen_height); - this._backgroundShade.set_size(global.screen_width, global.screen_height); let viewWidth = primary.width - 2 * this._spacing; let viewHeight = contentHeight - this._spacing; @@ -525,9 +489,38 @@ Overview.prototype = { if (this.visible || this.animationInProgress) return; + // The main BackgroundActor is inside global.window_group which is + // hidden when displaying the overview, so we create a new + // one. Instances of this class share a single CoglTexture behind the + // scenes which allows us to show the background with different + // rendering options without duplicating the texture data. + this._background = new Clutter.Group(); + this._background.hide(); + global.overlay_group.add_actor(this._background); + + this._desktopBackground = Meta.BackgroundActor.new_for_screen(global.screen); + this._background.add_actor(this._desktopBackground); + + this._backgroundShade = new St.Bin({style_class: 'workspace-overview-background-shade'}); + this._background.add_actor(this._backgroundShade); + this._backgroundShade.set_size(global.screen_width, global.screen_height); + + this._desktopFade = new St.Bin(); + global.overlay_group.add_actor(this._desktopFade); + this.visible = true; this.animationInProgress = true; + // During transitions, we raise this to the top to avoid having the overview + // area be reactive; it causes too many issues such as mouseover handlers in the workspaces. + this._coverPane = new Clutter.Rectangle({ opacity: 0, + reactive: true }); + this._group.add_actor(this._coverPane); + this._coverPane.set_position(0, 0); + this._coverPane.set_size(global.screen_width, global.screen_height); + this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; })); + this._coverPane.hide(); + // All the the actors in the window group are completely obscured, // hiding the group holding them while the Overview is displayed greatly // increases performance of the Overview especially when there are many @@ -721,6 +714,13 @@ Overview.prototype = { }, _hideDone: function() { + global.overlay_group.remove_actor(this._desktopFade); + this._desktopFade.destroy(); + this._group.remove_actor(this._coverPane); + this._coverPane.destroy(); + global.overlay_group.remove_actor(this._background); + this._background.destroy(); + // Re-enable unredirection Meta.enable_unredirect_for_screen(global.screen); @@ -731,15 +731,12 @@ Overview.prototype = { this._workspacesDisplay.hide(); - this._desktopFade.hide(); - this._background.hide(); this._group.hide(); this.visible = false; this.animationInProgress = false; this._hideInProgress = false; - this._coverPane.hide(); this.emit('hidden'); // Handle any calls to show* while we were hiding From 8380ce987dcf6fc6ec7a1cd5b7ab915f2e27b739 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 26 Oct 2012 15:46:06 +0200 Subject: [PATCH 25/74] [Scale] Remove left-behind search-provider functions. --- js/ui/overview.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index 1bec967515..fb79a004f8 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -168,12 +168,6 @@ Overview.prototype = { this._relayout(); }, - addSearchProvider: function(provider) { - }, - - removeSearchProvider: function(provider) { - }, - setMessage: function(text, undoCallback, undoLabel) { if (this.isDummy) return; From 71c98d3456ce0da15983115fe7bc836f43d8ea56 Mon Sep 17 00:00:00 2001 From: autarkper Date: Sun, 28 Oct 2012 11:45:46 +0100 Subject: [PATCH 26/74] [Scale] Find first non-empty monitor. --- js/ui/workspace.js | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index bda252085e..168f875a64 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1960,7 +1960,29 @@ Workspace.prototype = { this._monitors.push(m); this.actor.add_actor(m.actor); }, this); - this.currentMonitorIndex = focusIndex; + }, + + findNextNonEmptyMonitor: function(start, increment) { + let pos = start; + for (let i = 0; i < this._monitors.length; ++i) { + pos = (this._monitors.length + pos + increment) % this._monitors.length; + if (!this._monitors[pos].isEmpty()) { + return pos; + } + } + return this.currentMonitorIndex || 0; + }, + + selectNextNonEmptyMonitor: function(start, increment) { + if (this._monitors.length === 1) { + this.currentMonitorIndex = 0; + this._monitors[this.currentMonitorIndex].showActiveSelection(true); + return; + } + let previousIndex = this.currentMonitorIndex || 0; + this.currentMonitorIndex = this.findNextNonEmptyMonitor(start || 0, increment); + this._monitors[previousIndex].showActiveSelection(false); + this._monitors[this.currentMonitorIndex].showActiveSelection(true); }, _onKeyPress: function(actor, event) { @@ -1969,18 +1991,8 @@ Workspace.prototype = { let ctrlAltMask = Clutter.ModifierType.CONTROL_MASK | Clutter.ModifierType.MOD1_MASK; if ((symbol === Clutter.ISO_Left_Tab || symbol === Clutter.Tab) && !(modifiers & ctrlAltMask)) { - if (this._monitors.length < 2) return true; - - let previousIndex = this.currentMonitorIndex; let increment = symbol === Clutter.ISO_Left_Tab ? -1 : 1; - for (let i = 0; i < this._monitors.length; ++i) { - this.currentMonitorIndex = (this._monitors.length + this.currentMonitorIndex + increment) % this._monitors.length; - if (!this._monitors[this.currentMonitorIndex].isEmpty()) { - break; - } - } - this._monitors[previousIndex].showActiveSelection(false); - this._monitors[this.currentMonitorIndex].showActiveSelection(true); + this.selectNextNonEmptyMonitor(this.currentMonitorIndex, increment); return true; } @@ -2036,6 +2048,7 @@ Workspace.prototype = { this._monitors.forEach(function(monitor) { monitor.zoomToOverview(); }, this); + this.selectNextNonEmptyMonitor(this.currentMonitorIndex - 1, 1); }, hasMaximizedWindows: function() { From 2e74b10b9bf2a6cd13d5d22aded8bce59a46a2ff Mon Sep 17 00:00:00 2001 From: autarkper Date: Sun, 28 Oct 2012 20:34:53 +0100 Subject: [PATCH 27/74] [Scale] Handle windows demanding attention or being marked urgent (needs support from muffin for full functionality). --- js/ui/workspace.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 168f875a64..50a89a2135 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -31,6 +31,8 @@ const DRAGGING_WINDOW_OPACITY = 100; const BUTTON_LAYOUT_SCHEMA = 'org.cinnamon.overrides'; const BUTTON_LAYOUT_KEY = 'button-layout'; +const DEMANDS_ATTENTION_CLASS_NAME = "window-list-item-demands-attention"; + // Define a layout scheme for small window counts. For larger // counts we fall back to an algorithm. We need more schemes here // unless we have a really good algorithm. @@ -527,12 +529,28 @@ WindowOverlay.prototype = { windowClone.connect('zoom-start', Lang.bind(this, this.hide)); windowClone.connect('zoom-end', Lang.bind(this, this.show)); + let attentionId = global.display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention)); + let urgentId = global.display.connect('window-marked-urgent', Lang.bind(this, this._onWindowDemandsAttention)); + this.disconnectAttentionSignals = function() { + global.display.disconnect(attentionId); + global.display.disconnect(urgentId); + }; + // force a style change if we are already on a stage - otherwise // the signal will be emitted normally when we are added if (parentActor.get_stage()) this._onStyleChanged(); }, + _onWindowDemandsAttention: function(display, metaWindow) { + if (metaWindow != this._windowClone.metaWindow) return; + + if (!this.title.has_style_class_name(DEMANDS_ATTENTION_CLASS_NAME)) { + this.title.add_style_class_name(DEMANDS_ATTENTION_CLASS_NAME); + this._applicationIconBox.add_style_class_name(DEMANDS_ATTENTION_CLASS_NAME); + } + }, + refreshTitle: function(titleText) { let name = ''; if (this.title) { @@ -547,6 +565,11 @@ WindowOverlay.prototype = { title.clutter_text.ellipsize = Pango.EllipsizeMode.END; title._spacing = 0; this._parentActor.add_actor(title); + let mw = this._windowClone.metaWindow + if (mw.is_urgent && (mw.is_demanding_attention() || mw.is_urgent())) { + this.title.add_style_class_name(DEMANDS_ATTENTION_CLASS_NAME); + this._applicationIconBox.add_style_class_name(DEMANDS_ATTENTION_CLASS_NAME); + } title.connect('style-changed', Lang.bind(this, this._onStyleChanged)); if (this._parentActor.get_stage()) { @@ -687,6 +710,7 @@ WindowOverlay.prototype = { Mainloop.source_remove(this._idleToggleCloseId); this._idleToggleCloseId = 0; } + this.disconnectAttentionSignals(); this._windowClone.metaWindow.disconnect(this._updateCaptionId); this.title.destroy(); this.closeButton.destroy();this._applicationIconBox.destroy(); From caf9b5cad25fed837c59447a9dedc7aae629ed6f Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 29 Oct 2012 09:03:27 +0100 Subject: [PATCH 28/74] [Scale] Some cleanup of complex window-close handling. --- js/ui/workspace.js | 47 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 50a89a2135..cb43dbb825 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -524,7 +524,6 @@ WindowOverlay.prototype = { Mainloop.timeout_add(1000, installMotionEvents); this._idleToggleCloseId = 0; - this._windowAddedId = 0; windowClone.actor.connect('destroy', Lang.bind(this, this._onDestroy)); windowClone.connect('zoom-start', Lang.bind(this, this.hide)); windowClone.connect('zoom-end', Lang.bind(this, this.show)); @@ -675,37 +674,33 @@ WindowOverlay.prototype = { closeWindow: function() { let metaWindow = this._windowClone.metaWindow; - this._workspace = metaWindow.get_workspace(); + let workspace = metaWindow.get_workspace(); + + if (this._disconnectWindowAdded) {this._disconnectWindowAdded();} + let windowAddedId = workspace.connect('window-added',Lang.bind(this, function(ws, win){ + if (this._disconnectWindowAdded) {this._disconnectWindowAdded();} + if (win.get_transient_for() == metaWindow) { + + // use an idle handler to avoid mapping problems - + // see comment in Workspace._windowAdded + Mainloop.idle_add(Lang.bind(this, + function() { + this._windowClone.emit('selected'); + return false; + })); + } + })); - this._windowAddedId = this._workspace.connect('window-added', - Lang.bind(this, - this._onWindowAdded)); + this._disconnectWindowAdded = Lang.bind(this, function() { + workspace.disconnect(windowAddedId); + this._disconnectWindowAdded = 0; + }); metaWindow.delete(global.get_current_time()); }, - _onWindowAdded: function(workspace, win) { - let metaWindow = this._windowClone.metaWindow; - - if (win.get_transient_for() == metaWindow) { - workspace.disconnect(this._windowAddedId); - this._windowAddedId = 0; - - // use an idle handler to avoid mapping problems - - // see comment in Workspace._windowAdded - Mainloop.idle_add(Lang.bind(this, - function() { - this._windowClone.emit('selected'); - return false; - })); - } - }, - _onDestroy: function() { - if (this._windowAddedId > 0) { - this._workspace.disconnect(this._windowAddedId); - this._windowAddedId = 0; - } + if (this._disconnectWindowAdded) {this._disconnectWindowAdded();} if (this._idleToggleCloseId > 0) { Mainloop.source_remove(this._idleToggleCloseId); this._idleToggleCloseId = 0; From 4619597d47944fadb48c93937dfbee526e5101a9 Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 29 Oct 2012 19:00:57 +0100 Subject: [PATCH 29/74] [Scale] Code shuffling. --- js/ui/workspace.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index cb43dbb825..6ccd53fed5 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -65,16 +65,6 @@ function ScaledPoint(x, y, scaleX, scaleY) { [this.x, this.y, this.scaleX, this.scaleY] = arguments; } -var menuShowing = null; -var menuClone = null; -function closeContextMenu(requestor) { - let requestorShowingMenu = menuClone && menuClone === requestor; - if (menuShowing) { - menuShowing.close(); - } - return requestorShowingMenu; -} - ScaledPoint.prototype = { getPosition : function() { return [this.x, this.y]; @@ -103,6 +93,15 @@ ScaledPoint.prototype = { } }; +var menuShowing = null; +var menuClone = null; +function closeContextMenu(requestor) { + let requestorShowingMenu = menuClone && menuClone === requestor; + if (menuShowing) { + menuShowing.close(); + } + return requestorShowingMenu; +} function WindowClone(realWindow) { this._init(realWindow); From b63c1bd97e42731b5b845aff2a66540a97cb930c Mon Sep 17 00:00:00 2001 From: autarkper Date: Wed, 31 Oct 2012 14:36:34 +0100 Subject: [PATCH 30/74] [Scale] Center grid more precisely. --- js/ui/workspace.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 6ccd53fed5..c40da2bfd4 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -790,6 +790,7 @@ WorkspaceMonitor.prototype = { this._y = 0; this._width = 0; this._height = 0; + this._margin = 0; this._slotWidth = 0; this.monitorIndex = monitorIndex; @@ -968,11 +969,12 @@ WorkspaceMonitor.prototype = { } }, - setGeometry: function(x, y, width, height) { + setGeometry: function(x, y, width, height, margin) { this._x = x; this._y = y; this._width = width; this._height = height; + this._margin = margin; // This is sometimes called during allocation, so we do this later Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, @@ -1175,11 +1177,11 @@ WorkspaceMonitor.prototype = { _getSlotGeometry: function(slot) { let [xCenter, yCenter, fraction] = slot; - let width = this._width * fraction; - let height = this._height * fraction; + let width = (this._width - this._margin * 2) * fraction; + let height = (this._height - this._margin * 2) * fraction; - let x = this._x + xCenter * this._width - width / 2 ; - let y = this._y + yCenter * this._height - height / 2; + let x = this._x + this._margin + xCenter * (this._width - this._margin * 2) - width / 2 ; + let y = this._y + this._margin + yCenter * (this._height - this._margin * 2) - height / 2; return [x, y, width, height]; }, @@ -2045,10 +2047,10 @@ Workspace.prototype = { setGeometry: function(x, y, width, height, spacing_unused) { let primary = Main.layoutManager.primaryMonitor; - let spacing = (primary.width - width) / 2; + let margin = (primary.width - width) / 2; this._monitors.forEach(function(monitor, index) { let mon = Main.layoutManager.monitors[index]; - monitor.setGeometry(mon.x + spacing, mon.y + spacing, mon.width - spacing, mon.height - spacing); + monitor.setGeometry(mon.x, mon.y, mon.width, mon.height, margin); }, this); }, From 02d1071809a7e2831fc21aae9956e037731d9618 Mon Sep 17 00:00:00 2001 From: autarkper Date: Wed, 31 Oct 2012 14:56:54 +0100 Subject: [PATCH 31/74] [Scale] Delete some left-over advanced positioning functions. --- js/ui/workspace.js | 166 +-------------------------------------------- 1 file changed, 1 insertion(+), 165 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index c40da2bfd4..2de4966979 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -47,8 +47,7 @@ const POSITIONS = { 5: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.25, 0.75, 0.32], [0.75, 0.75, 0.32]], 6: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.165, 0.75, 0.32], [0.495, 0.75, 0.32], [0.825, 0.75, 0.32]] }; -// Used in _orderWindowsPermutations, 5! = 120 which is probably the highest we can go -const POSITIONING_PERMUTATIONS_MAX = 5; + const DEFAULT_SLOT_FRACTION = 0.825; const WINDOWOVERLAY_ICON_SIZE = 32; @@ -1004,169 +1003,6 @@ WorkspaceMonitor.prototype = { return this._windows.length === 0; }, - // Only use this for n <= 20 say - _factorial: function(n) { - let result = 1; - for (let i = 2; i <= n; i++) - result *= i; - return result; - }, - - /** - * _permutation: - * @permutationIndex: An integer from [0, list.length!) - * @list: (inout): Array of objects to permute; will be modified in place - * - * Given an integer between 0 and length of array, re-order the array in-place - * into a permutation denoted by the index. - */ - _permutation: function(permutationIndex, list) { - for (let j = 2; j <= list.length; j++) { - let firstIndex = (permutationIndex % j); - let secondIndex = j - 1; - // Swap - let tmp = list[firstIndex]; - list[firstIndex] = list[secondIndex]; - list[secondIndex] = tmp; - permutationIndex = Math.floor(permutationIndex / j); - } - }, - - /** - * _forEachPermutations: - * @list: Array - * @func: Function which takes a single array argument - * - * Call @func with each permutation of @list as an argument. - */ - _forEachPermutations: function(list, func) { - let nCombinations = this._factorial(list.length); - for (let i = 0; i < nCombinations; i++) { - let listCopy = list.concat(); - this._permutation(i, listCopy); - func(listCopy); - } - }, - - /** - * _computeWindowMotion: - * @actor: A #WindowClone's #ClutterActor - * @slot: An element of #POSITIONS - * @slotGeometry: Layout of @slot - * - * Returns a number corresponding to how much perceived motion - * would be involved in moving the window to the given slot. - * Currently this is the square of the distance between the - * centers. - */ - _computeWindowMotion: function (actor, slot) { - let [xCenter, yCenter, fraction] = slot; - let xDelta, yDelta, distanceSquared; - let actorWidth, actorHeight; - - let x = actor.x; - let y = actor.y; - let scale = actor.scale_x; - - if (actor._delegate.inDrag) { - x = actor._delegate.dragOrigX; - y = actor._delegate.dragOrigY; - scale = actor._delegate.dragOrigScale; - } - - actorWidth = actor.width * scale; - actorHeight = actor.height * scale; - xDelta = x + actorWidth / 2.0 - xCenter * this._width - this._x; - yDelta = y + actorHeight / 2.0 - yCenter * this._height - this._y; - distanceSquared = xDelta * xDelta + yDelta * yDelta; - - return distanceSquared; - }, - - /** - * _orderWindowsPermutations: - * - * Iterate over all permutations of the windows, and determine the - * permutation which has the least total motion. - */ - _orderWindowsPermutations: function (clones, slots) { - let minimumMotionPermutation = null; - let minimumMotion = -1; - let permIndex = 0; - this._forEachPermutations(clones, Lang.bind(this, function (permutation) { - let motion = 0; - for (let i = 0; i < permutation.length; i++) { - let cloneActor = permutation[i].actor; - let slot = slots[i]; - - let delta = this._computeWindowMotion(cloneActor, slot); - - motion += delta; - - // Bail out early if we're already larger than the - // previous best - if (minimumMotionPermutation != null && - motion > minimumMotion) - continue; - } - - if (minimumMotionPermutation == null || motion < minimumMotion) { - minimumMotionPermutation = permutation; - minimumMotion = motion; - } - permIndex++; - })); - return minimumMotionPermutation; - }, - - /** - * _orderWindowsGreedy: - * - * Iterate over available slots in order, placing into each one the window - * we find with the smallest motion to that slot. - */ - _orderWindowsGreedy: function(clones, slots) { - let result = []; - let slotIndex = 0; - // Copy since we mutate below - let clonesCopy = clones.concat(); - for (let i = 0; i < slots.length; i++) { - let slot = slots[i]; - let minimumMotionIndex = -1; - let minimumMotion = -1; - for (let j = 0; j < clonesCopy.length; j++) { - let cloneActor = clonesCopy[j].actor; - let delta = this._computeWindowMotion(cloneActor, slot); - if (minimumMotionIndex == -1 || delta < minimumMotion) { - minimumMotionIndex = j; - minimumMotion = delta; - } - } - result.push(clonesCopy[minimumMotionIndex]); - clonesCopy.splice(minimumMotionIndex, 1); - } - return result; - }, - - /** - * _orderWindowsByMotionAndStartup: - * @windows: Array of #MetaWindow - * @slots: Array of slots - * - * Returns a copy of @windows, ordered in such a way that they require least motion - * to move to the final screen coordinates of @slots. Ties are broken in a stable - * fashion by the order in which the windows were created. - */ - _orderWindowsByMotionAndStartup: function(clones, slots) { - clones.sort(function(w1, w2) { - return w2.metaWindow.get_stable_sequence() - w1.metaWindow.get_stable_sequence(); - }); - if (clones.length <= POSITIONING_PERMUTATIONS_MAX) - return this._orderWindowsPermutations(clones, slots); - else - return this._orderWindowsGreedy(clones, slots); - }, - /** * _getSlotGeometry: * @slot: A layout slot From 1e22a55cb4f98f2cc368b4d1380f507759238687 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 2 Nov 2012 18:58:17 +0100 Subject: [PATCH 32/74] [Scale] Use Main.isInteresting. --- js/ui/workspace.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 2de4966979..70148730bd 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1494,7 +1494,7 @@ WorkspaceMonitor.prototype = { // Tests if @win should be shown in the Overview _isOverviewWindow : function (win) { let tracker = Cinnamon.WindowTracker.get_default(); - return tracker.is_window_interesting(win.get_meta_window()); + return Main.isInteresting(win.get_meta_window()); }, // Create a clone of a (non-desktop) window and add it to the window list From 8929090fc82025f2b3a65dbabb532bb15523dd98 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 2 Nov 2012 19:47:29 +0100 Subject: [PATCH 33/74] [Scale] Tell activated workspace to update. --- js/ui/workspacesView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index c80f28cb95..a9fa4ef1db 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -272,6 +272,8 @@ WorkspacesView.prototype = { this._scrollAdjustment.value = index; this._animatingScroll = false; } + let active = global.screen.get_active_workspace_index(); + this._workspaces[active].zoomToOverview(); }, updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) { From 111cd5585232ad17011d4a9b6f77ba927f591bf0 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 2 Nov 2012 21:26:50 +0100 Subject: [PATCH 34/74] [Scale] Check for Alt or Ctrl being pressed before handling keyboard symbol. --- js/ui/workspace.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 70148730bd..5700c12c10 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1871,6 +1871,9 @@ Workspace.prototype = { Main.overview.hide(); return true; } + if (modifiers & ctrlAltMask) { + return false; + } return activeMonitor.selectAnotherWindow(symbol); }, From 7144b0e6215dcb5528cf62e7acb960d8f92cdb3d Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 3 Nov 2012 09:52:00 +0100 Subject: [PATCH 35/74] [Scale] Auto-update after menu close and window-close. --- js/ui/workspace.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 5700c12c10..7aed8547d2 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -776,12 +776,13 @@ const WindowPositionFlags = { ANIMATE: 1 << 1 }; -function WorkspaceMonitor(metaWorkspace, monitorIndex, hasFocus) { - this._init(metaWorkspace, monitorIndex, hasFocus); +function WorkspaceMonitor() { + this._init.apply(this, arguments); } WorkspaceMonitor.prototype = { - _init : function(metaWorkspace, monitorIndex, hasFocus) { + _init : function(metaWorkspace, monitorIndex, workspace, hasFocus) { + this._myWorkspace = workspace; // When dragging a window, we use this slot for reserve space. this._reservedSlot = null; this.metaWorkspace = metaWorkspace; @@ -939,9 +940,10 @@ WorkspaceMonitor.prototype = { }, _onCloneContextMenuRequested: function(clone) { - menuShowing = new WindowContextMenu(clone.actor, clone.metaWindow, function() { + menuShowing = new WindowContextMenu(clone.actor, clone.metaWindow, Lang.bind(this, function() { menuShowing = null; menuClone = null; - }); + this._myWorkspace.emit('focus-refresh-required'); + })); menuClone = clone; menuShowing.toggle(); }, @@ -1233,6 +1235,7 @@ WorkspaceMonitor.prototype = { } this.positionWindows(WindowPositionFlags.ANIMATE); + this._myWorkspace.emit('focus-refresh-required'); return false; }, @@ -1359,6 +1362,7 @@ WorkspaceMonitor.prototype = { } this.positionWindows(WindowPositionFlags.ANIMATE); + this._myWorkspace.emit('focus-refresh-required'); }, _windowAdded : function(metaWorkspace, metaWin) { @@ -1812,10 +1816,13 @@ Workspace.prototype = { this._monitors = []; let focusIndex = Main.layoutManager.focusIndex; Main.layoutManager.monitors.forEach(function(monitor, monitorIndex) { - let m = new WorkspaceMonitor(metaWorkspace, monitorIndex, monitorIndex === focusIndex) + let m = new WorkspaceMonitor(metaWorkspace, monitorIndex, this, monitorIndex === focusIndex) this._monitors.push(m); this.actor.add_actor(m.actor); }, this); + this.connect('focus-refresh-required', Lang.bind(this, function() { + this.selectNextNonEmptyMonitor(this.currentMonitorIndex - 1, 1); + })); }, findNextNonEmptyMonitor: function(start, increment) { @@ -1907,7 +1914,7 @@ Workspace.prototype = { this._monitors.forEach(function(monitor) { monitor.zoomToOverview(); }, this); - this.selectNextNonEmptyMonitor(this.currentMonitorIndex - 1, 1); + this.emit('focus-refresh-required'); }, hasMaximizedWindows: function() { From 3e8e7550170f55d36853d64b903fa1f96837e8b1 Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 5 Nov 2012 08:14:09 +0100 Subject: [PATCH 36/74] [Scale] Delete obsolete ViewSelector styles. --- data/theme/cinnamon.css | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/data/theme/cinnamon.css b/data/theme/cinnamon.css index 91d885ba8c..94c44288d1 100644 --- a/data/theme/cinnamon.css +++ b/data/theme/cinnamon.css @@ -443,30 +443,6 @@ StScrollBar StButton#vhandle:hover { .workspace-overview-background-shade { background-color: rgba(0,0,0,0.4); } -/* =================================================================== - * ViewSelector - * ===================================================================*/ -#viewSelector { - spacing: 1em; - font-size: 12pt; -} -#viewSelectorTabBar { - padding: 1em; -} -.view-tab-title { - color: #888a85; - font-weight: bold; - padding: 0px 0.75em; - height: 1.5em; -} -.view-tab-title:hover { - color: #bbb; -} -.view-tab-title:selected { - color: #000000; - background-color: #c2c7cd; - border-radius: 0.25em; -} /* =================================================================== * Looking Glass * ===================================================================*/ From cf11ee6344e6891d4c027079514afe7388dcf485 Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 5 Nov 2012 08:20:37 +0100 Subject: [PATCH 37/74] [Scale] Remove reference to obsolete viewSelector.js. --- po/POTFILES.in | 1 - 1 file changed, 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index a4909ace4a..7d969c3e15 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -18,7 +18,6 @@ js/ui/popupMenu.js js/ui/runDialog.js js/ui/cinnamonEntry.js js/ui/cinnamonMountOperation.js -js/ui/viewSelector.js js/ui/windowAttentionHandler.js src/gvc/gvc-mixer-control.c src/main.c From 2deab826c930093a7544c1ec969fa40d9ec8ae1c Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 5 Nov 2012 15:51:43 +0100 Subject: [PATCH 38/74] [Scale] Cancel zoom on keyboard-selection change. [Scale] Keyboard support for zoom-scrolling selected window clone (Ctrl+'+'/'-'/'0'). --- js/ui/workspace.js | 48 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 7aed8547d2..a0a73801ba 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -102,12 +102,13 @@ function closeContextMenu(requestor) { return requestorShowingMenu; } -function WindowClone(realWindow) { - this._init(realWindow); +function WindowClone() { + this._init.apply(this, arguments); } WindowClone.prototype = { - _init : function(realWindow) { + _init : function(realWindow, myContainer) { + this.myContainer = myContainer; this.realWindow = realWindow; this.metaWindow = realWindow.meta_window; this.metaWindow._delegate = this; @@ -150,7 +151,8 @@ WindowClone.prototype = { this._realWindowDestroyId = this.realWindow.connect('destroy', Lang.bind(this, this._disconnectRealWindowSignals)); - //let clickAction = new Clutter.ClickAction(); + this.myContainer.connect('selection-changed', Lang.bind(this, this._zoomEnd)); + this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease)); this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); //clickAction.connect('long-press', Lang.bind(this, this._onLongPress)); @@ -265,25 +267,31 @@ WindowClone.prototype = { this._zoomEnd(); }, - _onScroll : function (actor, event) { - let direction = event.get_scroll_direction(); - if (direction == Clutter.ScrollDirection.UP) { + scrollZoom: function (direction) { + if (direction === Clutter.ScrollDirection.UP) { if (this._zoomStep == undefined) this._zoomStart(); if (this._zoomStep < 100) { this._zoomStep += SCROLL_SCALE_AMOUNT; this._zoomUpdate(); } - } else if (direction == Clutter.ScrollDirection.DOWN) { + } else if (direction === Clutter.ScrollDirection.DOWN) { if (this._zoomStep > 0) { this._zoomStep -= SCROLL_SCALE_AMOUNT; this._zoomStep = Math.max(0, this._zoomStep); this._zoomUpdate(); } - if (this._zoomStep <= 0.0) + if (this._zoomStep <= 0.0) { this._zoomEnd(); + } + } else if (direction < 0) { + this._zoomEnd(); } + }, + _onScroll : function (actor, event) { + let direction = event.get_scroll_direction(); + this.scrollZoom(direction); }, _zoomUpdate : function () { @@ -335,6 +343,7 @@ WindowClone.prototype = { }, _zoomEnd : function () { + if (!this._zooming) {return;} this._zooming = false; this.emit('zoom-end'); @@ -937,6 +946,7 @@ WorkspaceMonitor.prototype = { if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { this._windows[this._kbWindowIndex].overlay.setSelected(show); } + this.emit('selection-changed'); }, _onCloneContextMenuRequested: function(clone) { @@ -964,6 +974,12 @@ WorkspaceMonitor.prototype = { return false; }, + zoomSelectedWindow: function(direction) { + if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { + this._windows[this._kbWindowIndex].scrollZoom(direction); + } + }, + closeSelectedWindow: function() { if (this._kbWindowIndex > -1 && this._kbWindowIndex < this._windows.length) { this._windows[this._kbWindowIndex].overlay.closeWindow(); @@ -1503,7 +1519,7 @@ WorkspaceMonitor.prototype = { // Create a clone of a (non-desktop) window and add it to the window list _addWindowClone : function(win) { - let clone = new WindowClone(win); + let clone = new WindowClone(win, this); let overlay = new WindowOverlay(clone, this._windowOverlaysGroup); clone.connect('selected', @@ -1878,6 +1894,18 @@ Workspace.prototype = { Main.overview.hide(); return true; } + if (symbol === Clutter.plus && modifiers & Clutter.ModifierType.CONTROL_MASK) { + activeMonitor.zoomSelectedWindow(Clutter.ScrollDirection.UP); + return true; + } + if (symbol === Clutter.minus && modifiers & Clutter.ModifierType.CONTROL_MASK) { + activeMonitor.zoomSelectedWindow(Clutter.ScrollDirection.DOWN); + return true; + } + if (symbol - '48' === 0 && modifiers & Clutter.ModifierType.CONTROL_MASK) { + activeMonitor.zoomSelectedWindow(-1); // end zoom + return true; + } if (modifiers & ctrlAltMask) { return false; } From da51440bcf7a6c1ae2604e7aed545faf6a8b4740 Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 5 Nov 2012 20:39:05 +0100 Subject: [PATCH 39/74] [Scale] Remove dormant, outdated drag-and-drop support. --- js/ui/workspace.js | 153 +-------------------------------------------- 1 file changed, 3 insertions(+), 150 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index a0a73801ba..1443bcd783 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -26,8 +26,6 @@ const SCROLL_SCALE_AMOUNT = 100 / 5; const LIGHTBOX_FADE_TIME = 0.1; const CLOSE_BUTTON_FADE_TIME = 0.1; -const DRAGGING_WINDOW_OPACITY = 100; - const BUTTON_LAYOUT_SCHEMA = 'org.cinnamon.overrides'; const BUTTON_LAYOUT_KEY = 'button-layout'; @@ -155,9 +153,6 @@ WindowClone.prototype = { this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease)); this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); - //clickAction.connect('long-press', Lang.bind(this, this._onLongPress)); - - //this.actor.add_action(clickAction); this.actor.connect('scroll-event', Lang.bind(this, this._onScroll)); @@ -166,16 +161,6 @@ WindowClone.prototype = { this.actor.connect('leave-event', Lang.bind(this, this._onPointerLeave)); - this._draggable = DND.makeDraggable(this.actor, - { restoreOnSuccess: true, - manualMode: true, - dragActorMaxSize: WINDOW_DND_SIZE, - dragActorOpacity: DRAGGING_WINDOW_OPACITY }); - this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin)); - this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled)); - this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd)); - this.inDrag = false; - this._windowIsZooming = false; this._zooming = false; this._selected = false; @@ -183,8 +168,8 @@ WindowClone.prototype = { setStackAbove: function (actor) { this._stackAbove = actor; - if (this.inDrag || this._zooming) - // We'll fix up the stack after the drag/zooming + if (this._zooming) + // We'll fix up the stack after the zooming return; if (this._stackAbove == null) this.actor.lower_bottom(); @@ -254,11 +239,6 @@ WindowClone.prototype = { if (this._zoomLightbox) this._zoomLightbox.destroy(); - if (this.inDrag) { - this.emit('drag-end'); - this.inDrag = false; - } - this.disconnectAll(); }, @@ -394,70 +374,6 @@ WindowClone.prototype = { return true; } return false; - }, - - _onLongPress: function(action, actor, state) { - // Take advantage of the Clutter policy to consider - // a long-press canceled when the pointer movement - // exceeds dnd-drag-threshold to manually start the drag - if (state == Clutter.LongPressState.CANCEL) { - // A click cancels a long-press before any click handler is - // run - make sure to not start a drag in that case - Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, - function() { - if (this._selected) - return; - let [x, y] = action.get_coords(); - this._draggable.startDrag(x, y, global.get_current_time()); - })); - } - return true; - }, - - _onDragBegin : function (draggable, time) { - if (this._zooming) - this._zoomEnd(); - - [this.dragOrigX, this.dragOrigY] = this.actor.get_position(); - this.dragOrigScale = this.actor.scale_x; - this.inDrag = true; - this.emit('drag-begin'); - }, - - _getWorkspaceActor : function() { - let index = this.metaWindow.get_workspace().index(); - return Main.overview.workspaces.getWorkspaceByIndex(index); - }, - - handleDragOver : function(source, actor, x, y, time) { - let workspace = this._getWorkspaceActor(); - return workspace.handleDragOver(source, actor, x, y, time); - }, - - acceptDrop : function(source, actor, x, y, time) { - let workspace = this._getWorkspaceActor(); - workspace.acceptDrop(source, actor, x, y, time); - }, - - _onDragCancelled : function (draggable, time) { - this.emit('drag-cancelled'); - }, - - _onDragEnd : function (draggable, time, snapback) { - this.inDrag = false; - - // We may not have a parent if DnD completed successfully, in - // which case our clone will shortly be destroyed and replaced - // with a new one on the target workspace. - if (this.actor.get_parent() != null) { - if (this._stackAbove == null) - this.actor.lower_bottom(); - else - this.actor.raise(this._stackAbove); - } - - - this.emit('drag-end'); } }; Signals.addSignalMethods(WindowClone.prototype); @@ -792,8 +708,7 @@ function WorkspaceMonitor() { WorkspaceMonitor.prototype = { _init : function(metaWorkspace, monitorIndex, workspace, hasFocus) { this._myWorkspace = workspace; - // When dragging a window, we use this slot for reserve space. - this._reservedSlot = null; + this.metaWorkspace = metaWorkspace; this._x = 0; this._y = 0; @@ -1124,11 +1039,6 @@ WorkspaceMonitor.prototype = { let mainIndex = this._lookupIndex(metaWindow); let overlay = clone.overlay; - // Positioning a window currently being dragged must be avoided; - // we'll just leave a blank spot in the layout for it. - if (clone.inDrag) - continue; - let [x, y, scale] = this._computeWindowLayout(metaWindow, slot); if (overlay) @@ -1201,9 +1111,6 @@ WorkspaceMonitor.prototype = { }, _showWindowOverlay: function(clone, fade) { - if (clone.inDrag) - return; - if (this._slotWidth) { // This is a little messy and complicated because when we // start the fade-in we may not have done the final positioning @@ -1528,20 +1435,6 @@ WorkspaceMonitor.prototype = { Lang.bind(this, this._onCloneClosed)); clone.connect('context-menu-requested', Lang.bind(this, this._onCloneContextMenuRequested)); - clone.connect('drag-begin', - Lang.bind(this, function(clone) { - Main.overview.beginWindowDrag(); - overlay.hide(); - })); - clone.connect('drag-cancelled', - Lang.bind(this, function(clone) { - Main.overview.cancelledWindowDrag(); - })); - clone.connect('drag-end', - Lang.bind(this, function(clone) { - Main.overview.endWindowDrag(); - overlay.show(); - })); clone.connect('zoom-start', Lang.bind(this, function() { this._windowIsZooming = true; @@ -1609,46 +1502,6 @@ WorkspaceMonitor.prototype = { _onCloneClosed : function (clone, time) { clone.metaWindow.delete(global.get_current_time()); - }, - - // Draggable target interface - handleDragOver : function(source, actor, x, y, time) { - if (source.realWindow && !this._isMyWindow(source.realWindow)) - return DND.DragMotionResult.MOVE_DROP; - if (source.cinnamonWorkspaceLaunch) - return DND.DragMotionResult.COPY_DROP; - - return DND.DragMotionResult.CONTINUE; - }, - - acceptDrop : function(source, actor, x, y, time) { - if (source.realWindow) { - let win = source.realWindow; - if (this._isMyWindow(win)) - return false; - - // Set a hint on the Muffin.Window so its initial position - // in the new workspace will be correct - win._overviewHint = { - x: actor.x, - y: actor.y, - scale: actor.scale_x - }; - - let metaWindow = win.get_meta_window(); - - let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index(); - metaWindow.change_workspace_by_index(index, - false, // don't create workspace - time); - return true; - } else if (source.cinnamonWorkspaceLaunch) { - source.cinnamonWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1, - timestamp: time }); - return true; - } - - return false; } }; From 1475872fcd30ef81fe3b5a1737933ef6cb427cb3 Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 10 Nov 2012 19:24:10 +0100 Subject: [PATCH 40/74] [Misc] Add js/misc/pointerTracker.js, a small class that keeps track of the pointer position. --- js/Makefile.am | 1 + js/misc/pointerTracker.js | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 js/misc/pointerTracker.js diff --git a/js/Makefile.am b/js/Makefile.am index 90fb30255c..f60f5149fe 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -10,6 +10,7 @@ nobase_dist_js_DATA = \ misc/history.js \ misc/modemManager.js \ misc/params.js \ + misc/pointerTracker.js \ misc/screenSaver.js \ misc/util.js \ perf/core.js \ diff --git a/js/misc/pointerTracker.js b/js/misc/pointerTracker.js new file mode 100644 index 0000000000..c7dc6308c0 --- /dev/null +++ b/js/misc/pointerTracker.js @@ -0,0 +1,21 @@ +// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +const Lang = imports.lang; +const Gdk = imports.gi.Gdk; + +const PointerTracker = new Lang.Class({ + Name: 'PointerTracker', + _init: function() { + let display = Gdk.Display.get_default(); + let deviceManager = display.get_device_manager(); + let pointer = deviceManager.get_client_pointer(); + let [lastScreen, lastPointerX, lastPointerY] = pointer.get_position(); + this.hasMoved = function() { + let [screen, pointerX, pointerY] = pointer.get_position(); + try { + return !(screen == lastScreen && pointerX == lastPointerX && pointerY == lastPointerY); + } finally { + [lastScreen, lastPointerX, lastPointerY] = [screen, pointerX, pointerY]; + } + } + } +}); From 613565c79ff615f9bda7ed4aef7e3dce1e03bc99 Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 10 Nov 2012 19:31:15 +0100 Subject: [PATCH 41/74] [Scale] Use a PointerTracker to keep track of whether the pointer really has moved. --- js/ui/workspace.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 1443bcd783..7abae7a003 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -16,6 +16,7 @@ const Main = imports.ui.main; const Overview = imports.ui.overview; const PopupMenu = imports.ui.popupMenu; const Tweener = imports.ui.tweener; +const PointerTracker = imports.misc.pointerTracker; const FOCUS_ANIMATION_TIME = 0.15; @@ -432,19 +433,9 @@ WindowOverlay.prototype = { this.refreshTitle(w.title); })); - let motionEventsInstalled = false; - let installMotionEvents = Lang.bind(this, function() { - if (motionEventsInstalled) { - return; - } - windowClone.actor.connect('motion-event', Lang.bind(this, this._onPointerMotion)); - windowClone.actor.connect('leave-event', Lang.bind(this, this._onPointerLeave)); - motionEventsInstalled = true; - }); - // Let the animation settle before we start reacting on pointer motion. - Mainloop.idle_add(installMotionEvents); - // Since idle_add can be slow at times, set an ordinary timeout as a fallback. - Mainloop.timeout_add(1000, installMotionEvents); + this._pointerTracker = new PointerTracker.PointerTracker(); + windowClone.actor.connect('motion-event', Lang.bind(this, this._onPointerMotion)); + windowClone.actor.connect('leave-event', Lang.bind(this, this._onPointerLeave)); this._idleToggleCloseId = 0; windowClone.actor.connect('destroy', Lang.bind(this, this._onDestroy)); @@ -637,6 +628,7 @@ WindowOverlay.prototype = { }, _onPointerMotion: function() { + if (!this._pointerTracker.hasMoved()) {return;} // We might get motion events on the clone while the overlay is // hidden, e.g. during animations, we ignore these events, // as the close button will be shown as needed when the overlays @@ -655,6 +647,7 @@ WindowOverlay.prototype = { }, _onPointerLeave: function() { + if (!this._pointerTracker.hasMoved()) {return;} this._hovering = false; this._idleHideCloseButton(); }, From 8613914f65049e898e2e371115dc68386172cd4f Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 12 Nov 2012 08:45:02 +0100 Subject: [PATCH 42/74] [misc] Add new utility gridNavigator. --- js/Makefile.am | 1 + js/misc/gridNavigator.js | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 js/misc/gridNavigator.js diff --git a/js/Makefile.am b/js/Makefile.am index f60f5149fe..dae7a5ae75 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -7,6 +7,7 @@ nobase_dist_js_DATA = \ misc/fileUtils.js \ misc/format.js \ misc/gnomeSession.js \ + misc/gridNavigator.js \ misc/history.js \ misc/modemManager.js \ misc/params.js \ diff --git a/js/misc/gridNavigator.js b/js/misc/gridNavigator.js new file mode 100644 index 0000000000..871c9a0e5c --- /dev/null +++ b/js/misc/gridNavigator.js @@ -0,0 +1,64 @@ +// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +const Lang = imports.lang; +const Clutter = imports.gi.Clutter; + +function nextIndex(itemCount, numCols, currentIndex, symbol) { + let result = -1; + if (itemCount > 3 // grid navigation is not suited for a low item count + && (symbol === Clutter.Down || symbol === Clutter.Up)) + { + let numRows = Math.ceil(itemCount/numCols); + + let curRow = Math.floor(currentIndex/numCols); + let curCol = currentIndex % numCols; + + let calcNewIndex = function(rowDelta) { + let newIndex = (curRow + rowDelta) * numCols + curCol; + if (rowDelta >= 0) { // down + return newIndex < itemCount ? + newIndex : + curCol < numCols - 1 ? + // wrap to top row, one column to the right: + curCol + 1 : + // wrap to top row, left-most column: + 0; + } + else { // up + let numFullRows = Math.floor(itemCount/numCols); + let numIOILR = itemCount % numCols; //num Items on Incompl. Last Row + return newIndex >= 0 ? + newIndex : + curCol === 0 ? + // Wrap to the bottom of the right-most column, may not be on last row: + (numFullRows * numCols) - 1 : + /* If we're on the + top row but not in the first column, we want to move to the bottom of the + column to the left, even though that may not be the bottom of the grid. + */ + numIOILR && curCol > numIOILR ? + ((numFullRows - 1) * numCols) + curCol - 1: + ((numRows - 1) * numCols) + curCol - 1; + } + }; + + if (symbol === Clutter.Down) { + result = calcNewIndex(1); + } + if (symbol === Clutter.Up) { + result = calcNewIndex(-1); + } + } + else if (symbol === Clutter.Left || symbol === Clutter.Up) { + result = (currentIndex < 1 ? itemCount : currentIndex) - 1; + } + else if (symbol === Clutter.Right || symbol === Clutter.Down) { + result = (currentIndex + 1) % itemCount; + } + else if (symbol === Clutter.Home) { + result = 0; + } + else if (symbol === Clutter.End) { + result = itemCount - 1; + } + return result; +} From 66cb7ffbb37bc59438fac99b0c2151c031ef7d83 Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 12 Nov 2012 08:47:18 +0100 Subject: [PATCH 43/74] [Scale] Use GridNavigator for grid navigation. --- js/ui/workspace.js | 64 +++------------------------------------------- 1 file changed, 4 insertions(+), 60 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 7abae7a003..031acc4736 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -17,6 +17,7 @@ const Overview = imports.ui.overview; const PopupMenu = imports.ui.popupMenu; const Tweener = imports.ui.tweener; const PointerTracker = imports.misc.pointerTracker; +const GridNavigator = imports.misc.gridNavigator; const FOCUS_ANIMATION_TIME = 0.15; @@ -779,66 +780,9 @@ WorkspaceMonitor.prototype = { return false; } let currentIndex = this._kbWindowIndex; - let nextIndex = -1; - - if (numWindows > 3 // grid navigation is not suited for a low window count - && (symbol === Clutter.Down || symbol === Clutter.Up)) - { - let numCols = Math.ceil(Math.sqrt(numWindows)); - let numRows = Math.ceil(numWindows/numCols); - - let curRow = Math.floor(currentIndex/numCols); - let curCol = currentIndex % numCols; - - let calcNewIndex = function(rowDelta) { - let newIndex = (curRow + rowDelta) * numCols + curCol; - if (rowDelta >= 0) { // down - return newIndex < numWindows ? - newIndex : - curCol < numCols - 1 ? - // wrap to top row, one column to the right: - curCol + 1 : - // wrap to top row, left-most column: - 0; - } - else { // up - let numFullRows = Math.floor(numWindows/numCols); - let numWOILR = numWindows % numCols; //num Windows on Incompl. Last Row - return newIndex >= 0 ? - newIndex : - curCol === 0 ? - // Wrap to the bottom of the right-most column, may not be on last row: - (numFullRows * numCols) - 1 : - /* If we're on the - top row but not in the first column, we want to move to the bottom of the - column to the left, even though that may not be the bottom of the grid. - */ - numWOILR && curCol > numWOILR ? - ((numFullRows - 1) * numCols) + curCol - 1: - ((numRows - 1) * numCols) + curCol - 1; - } - }; - - if (symbol === Clutter.Down) { - nextIndex = calcNewIndex(1); - } - if (symbol === Clutter.Up) { - nextIndex = calcNewIndex(-1); - } - } - else if (symbol === Clutter.Left || symbol === Clutter.Up) { - nextIndex = (currentIndex < 1 ? numWindows : currentIndex) - 1; - } - else if (symbol === Clutter.Right || symbol === Clutter.Down) { - nextIndex = (currentIndex + 1) % numWindows; - } - else if (symbol === Clutter.Home) { - nextIndex = 0; - } - else if (symbol === Clutter.End) { - nextIndex = numWindows - 1; - } - else { + let numCols = Math.ceil(Math.sqrt(numWindows)); + let nextIndex = GridNavigator.nextIndex(numWindows, numCols, currentIndex, symbol); + if (nextIndex < 0) { return false; // not handled } From 01eb713f0b3c5386b905f12323bff81421c5bc15 Mon Sep 17 00:00:00 2001 From: autarkper Date: Tue, 13 Nov 2012 10:25:43 +0100 Subject: [PATCH 44/74] [Scale] Initially set primary monitor as the active monitor. --- js/ui/workspace.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 031acc4736..451d27ef5d 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1620,9 +1620,9 @@ Workspace.prototype = { this.actor = new Clutter.Group(); this.actor.set_size(0, 0); this._monitors = []; - let focusIndex = Main.layoutManager.focusIndex; - Main.layoutManager.monitors.forEach(function(monitor, monitorIndex) { - let m = new WorkspaceMonitor(metaWorkspace, monitorIndex, this, monitorIndex === focusIndex) + this.currentMonitorIndex = Main.layoutManager.primaryIndex; + Main.layoutManager.monitors.forEach(function(monitor, ix) { + let m = new WorkspaceMonitor(metaWorkspace, ix, this, ix === this.currentMonitorIndex) this._monitors.push(m); this.actor.add_actor(m.actor); }, this); @@ -1648,7 +1648,7 @@ Workspace.prototype = { this._monitors[this.currentMonitorIndex].showActiveSelection(true); return; } - let previousIndex = this.currentMonitorIndex || 0; + let previousIndex = this.currentMonitorIndex; this.currentMonitorIndex = this.findNextNonEmptyMonitor(start || 0, increment); this._monitors[previousIndex].showActiveSelection(false); this._monitors[this.currentMonitorIndex].showActiveSelection(true); From d33a12de6fe5eab2336b785db7e78ce3ceb6400e Mon Sep 17 00:00:00 2001 From: autarkper Date: Thu, 15 Nov 2012 18:33:46 +0100 Subject: [PATCH 45/74] [Scale] Remove some left-overs. --- js/ui/workspace.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 451d27ef5d..fb7b7cb8b8 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1452,7 +1452,6 @@ WindowContextMenu.prototype = { __proto__: PopupMenu.PopupComboMenu.prototype, _init: function(actor, metaWindow, onClose) { - //take care of menu initialization PopupMenu.PopupComboMenu.prototype._init.call(this, actor); Main.uiGroup.add_actor(this.actor); this.actor.hide(); @@ -1544,9 +1543,6 @@ WindowContextMenu.prototype = { } }, - _onWindowMinimized: function(actor, event){ - }, - _onCloseWindowActivate: function(actor, event){ this.metaWindow.delete(global.get_current_time()); }, @@ -1572,7 +1568,6 @@ WindowContextMenu.prototype = { let workspace = this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.LEFT); if (workspace) { this.metaWindow.change_workspace(workspace); - Main._checkWorkspaces(); } }, @@ -1580,7 +1575,6 @@ WindowContextMenu.prototype = { let workspace = this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.RIGHT); if (workspace) { this.metaWindow.change_workspace(workspace); - Main._checkWorkspaces(); } }, From 3edcb664216a29460c44df926c5fe57037fa2c06 Mon Sep 17 00:00:00 2001 From: autarkper Date: Thu, 15 Nov 2012 21:30:15 +0100 Subject: [PATCH 46/74] [Scale] Improve window-workspace handling (sticky, etc.) --- js/ui/workspace.js | 76 ++++++++++++++++++++++++----------------- js/ui/workspacesView.js | 2 +- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index fb7b7cb8b8..33055f02fe 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -146,10 +146,21 @@ WindowClone.prototype = { this._stackAbove = null; - this._sizeChangedId = this.realWindow.connect('size-changed', + let sizeChangedId = this.realWindow.connect('size-changed', Lang.bind(this, this._onRealWindowSizeChanged)); - this._realWindowDestroyId = this.realWindow.connect('destroy', - Lang.bind(this, this._disconnectRealWindowSignals)); + let workspaceChangedId = this.metaWindow.connect('workspace-changed', Lang.bind(this, function(w, oldws) { + this.emit('workspace-changed', oldws); + })); + let realWindowDestroyId = 0; + this._disconnectWindowSignals = function() { + this._disconnectWindowSignals = function() {}; + this.metaWindow.disconnect(workspaceChangedId); + this.realWindow.disconnect(sizeChangedId); + this.realWindow.disconnect(realWindowDestroyId); + }; + realWindowDestroyId = this.realWindow.connect('destroy', + Lang.bind(this, this._disconnectWindowSignals)); + this.myContainer.connect('selection-changed', Lang.bind(this, this._zoomEnd)); @@ -197,16 +208,6 @@ WindowClone.prototype = { } }, - _disconnectRealWindowSignals: function() { - if (this._sizeChangedId > 0) - this.realWindow.disconnect(this._sizeChangedId); - this._sizeChangedId = 0; - - if (this._realWindowDestroyId > 0) - this.realWindow.disconnect(this._realWindowDestroyId); - this._realWindowDestroyId = 0; - }, - _getInvisibleBorderPadding: function() { // We need to adjust the position of the actor because of the // consequences of invisible borders -- in reality, the texture @@ -234,7 +235,7 @@ WindowClone.prototype = { }, _onDestroy: function() { - this._disconnectRealWindowSignals(); + this._disconnectWindowSignals(); this.metaWindow._delegate = null; this.actor._delegate = null; @@ -731,6 +732,9 @@ WorkspaceMonitor.prototype = { closeContextMenu(); }); + workspace.myView.connect('sticky-detected', Lang.bind(this, function(box, metaWindow) { + this._doAddWindow(metaWindow); + })); let windows = global.get_window_actors().filter(this._isMyWindow, this); // Create clones for windows that should be @@ -1196,8 +1200,9 @@ WorkspaceMonitor.prototype = { // We might have the window in our list already if it was on all workspaces and // now was moved to this workspace - if (this._lookupIndex (metaWin) != -1) + if (this._lookupIndex (metaWin) != -1) { return; + } if (!this._isMyWindow(win) || !this._isOverviewWindow(win)){ return; @@ -1221,8 +1226,10 @@ WorkspaceMonitor.prototype = { clone.actor.set_position (this._x, this._y); } - this.positionWindows(WindowPositionFlags.ANIMATE); - this._myWorkspace.emit('focus-refresh-required'); + if (this.actor.get_stage()) { + this.positionWindows(WindowPositionFlags.ANIMATE); + this._myWorkspace.emit('focus-refresh-required'); + } }, _windowAdded : function(metaWorkspace, metaWin) { @@ -1366,6 +1373,13 @@ WorkspaceMonitor.prototype = { let clone = new WindowClone(win, this); let overlay = new WindowOverlay(clone, this._windowOverlaysGroup); + clone.connect('workspace-changed', Lang.bind(this, function() { + this._doRemoveWindow(clone.metaWindow); + if (clone.metaWindow.is_on_all_workspaces()) { + // Muffin appears not to broadcast when a window turns sticky + this._myWorkspace.myView.emit('sticky-detected', clone.metaWindow); + } + })); clone.connect('selected', Lang.bind(this, this._onCloneSelected)); clone.connect('closed', @@ -1522,20 +1536,19 @@ WindowContextMenu.prototype = { if (this.metaWindow.is_on_all_workspaces()) { this.itemOnAllWorkspaces.label.set_text(_("Only on this workspace")); - this.itemMoveToLeftWorkspace.actor.hide(); - this.itemMoveToRightWorkspace.actor.hide(); } else { this.itemOnAllWorkspaces.label.set_text(_("Visible on all workspaces")); - if (this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.LEFT) != this.metaWindow.get_workspace()) - this.itemMoveToLeftWorkspace.actor.show(); - else - this.itemMoveToLeftWorkspace.actor.hide(); - - if (this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.RIGHT) != this.metaWindow.get_workspace()) - this.itemMoveToRightWorkspace.actor.show(); - else - this.itemMoveToRightWorkspace.actor.hide(); } + if (this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.LEFT) != this.metaWindow.get_workspace()) + this.itemMoveToLeftWorkspace.actor.show(); + else + this.itemMoveToLeftWorkspace.actor.hide(); + + if (this.metaWindow.get_workspace().get_neighbor(Meta.MotionDirection.RIGHT) != this.metaWindow.get_workspace()) + this.itemMoveToRightWorkspace.actor.show(); + else + this.itemMoveToRightWorkspace.actor.hide(); + if (this.metaWindow.get_maximized()) { this.itemMaximizeWindow.label.set_text(_("Unmaximize")); }else{ @@ -1604,13 +1617,14 @@ WindowContextMenu.prototype = { }; -function Workspace(metaWorkspace) { - this._init(metaWorkspace); +function Workspace() { + this._init.apply(this, arguments); } Workspace.prototype = { - _init : function(metaWorkspace) { + _init : function(metaWorkspace, view) { this.metaWorkspace = metaWorkspace; + this.myView = view; this.actor = new Clutter.Group(); this.actor.set_size(0, 0); this._monitors = []; diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index a9fa4ef1db..611672f81d 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -519,7 +519,7 @@ WorkspacesDisplay.prototype = { this._workspaces = []; for (let i = 0; i < global.screen.n_workspaces; i++) { let metaWorkspace = global.screen.get_workspace_by_index(i); - this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this._monitorIndex); + this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this); } if (this.workspacesView) From 723ab91d5cc25be92de7c4a187b03f22bf740e34 Mon Sep 17 00:00:00 2001 From: autarkper Date: Thu, 15 Nov 2012 21:58:32 +0100 Subject: [PATCH 47/74] [Scale] Change the menu-activation hotkey to Alt+M/m. [Scale] Let Ctrl+space open window context menu. --- js/ui/workspace.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 33055f02fe..12c3fcba65 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1675,7 +1675,9 @@ Workspace.prototype = { let activeMonitor = this._monitors[this.currentMonitorIndex]; - if (symbol === Clutter.m && !(modifiers & ctrlAltMask)) { + if ((symbol === Clutter.m || symbol === Clutter.M || symbol === Clutter.KEY_space) && + (modifiers & Clutter.ModifierType.MOD1_MASK) && !(modifiers & Clutter.ModifierType.CONTROL_MASK)) + { activeMonitor.showMenuForSelectedWindow(); return true; } From 0d1059586e58c7be31b5c7ee111c1ccadbdcb21c Mon Sep 17 00:00:00 2001 From: autarkper Date: Thu, 15 Nov 2012 22:59:53 +0100 Subject: [PATCH 48/74] [Scale] Must disconnect from long-lived Scale view. --- js/ui/workspace.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 12c3fcba65..933f9be33e 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -732,7 +732,7 @@ WorkspaceMonitor.prototype = { closeContextMenu(); }); - workspace.myView.connect('sticky-detected', Lang.bind(this, function(box, metaWindow) { + this.stickyCallbackId = workspace.myView.connect('sticky-detected', Lang.bind(this, function(box, metaWindow) { this._doAddWindow(metaWindow); })); let windows = global.get_window_actors().filter(this._isMyWindow, this); @@ -1333,6 +1333,7 @@ WorkspaceMonitor.prototype = { } Tweener.removeTweens(actor); + this._myWorkspace.myView.disconnect(this.stickyCallbackId); if (this.metaWorkspace) { this.metaWorkspace.disconnect(this._windowAddedId); this.metaWorkspace.disconnect(this._windowRemovedId); From 8a1f94ebbada3fa75c626baad195264e06a6d106 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 09:29:29 +0100 Subject: [PATCH 49/74] [Scale] Refactoring (1). --- js/ui/workspacesView.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 611672f81d..59f085eb93 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -71,16 +71,11 @@ WorkspacesView.prototype = { // workspaces have been created. This cannot be done first because // window movement depends on the Workspaces object being accessible // as an Overview member. - this._overviewShowingId = Main.overview.connect('showing', Lang.bind(this, function() { + let overviewShowingId = Main.overview.connect('showing', Lang.bind(this, function() { + Main.overview.disconnect(overviewShowingId); let activeWorkspaceIndex = global.screen.get_active_workspace_index(); this._workspaces[activeWorkspaceIndex].zoomToOverview(); })); - this._overviewShownId = - Main.overview.connect('shown', - Lang.bind(this, function() { - // this.actor.set_clip(this._clipX, this._clipY, - // this._clipWidth, this._clipHeight); - })); this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, lower: 0, @@ -307,8 +302,6 @@ WorkspacesView.prototype = { _onDestroy: function() { this._scrollAdjustment.run_dispose(); - Main.overview.disconnect(this._overviewShowingId); - Main.overview.disconnect(this._overviewShownId); global.window_manager.disconnect(this._switchWorkspaceNotifyId); if (this._inDrag) From 869443338bdd478d5661d17b7ed107ae646da00a Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 09:34:27 +0100 Subject: [PATCH 50/74] [Scale] Refactoring (2): Remove drag-and-drop relics. --- js/ui/workspacesView.js | 164 +--------------------------------------- 1 file changed, 1 insertion(+), 163 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 59f085eb93..0d49249a28 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -7,7 +7,6 @@ const Cinnamon = imports.gi.Cinnamon; const St = imports.gi.St; const Signals = imports.signals; -const DND = imports.ui.dnd; const Main = imports.ui.main; const Overview = imports.ui.overview; const Tweener = imports.ui.tweener; @@ -57,7 +56,6 @@ WorkspacesView.prototype = { this._scrolling = false; // swipe-scrolling this._animatingScroll = false; // programatically updating the adjustment this._zoomOut = false; // zoom to a larger area - this._inDrag = false; // dragging a window let activeWorkspaceIndex = global.screen.get_active_workspace_index(); this._workspaces = workspaces; @@ -90,14 +88,6 @@ WorkspacesView.prototype = { global.window_manager.connect('switch-workspace', Lang.bind(this, this._activeWorkspaceChanged)); - this._itemDragBeginId = Main.overview.connect('item-drag-begin', - Lang.bind(this, this._dragBegin)); - this._itemDragEndId = Main.overview.connect('item-drag-end', - Lang.bind(this, this._dragEnd)); - this._windowDragBeginId = Main.overview.connect('window-drag-begin', - Lang.bind(this, this._dragBegin)); - this._windowDragEndId = Main.overview.connect('window-drag-end', - Lang.bind(this, this._dragEnd)); this._swipeScrollBeginId = 0; this._swipeScrollEndId = 0; @@ -239,10 +229,7 @@ WorkspacesView.prototype = { workspace.actor.show(); } else { workspace.showWindowsOverlays(); - if (this._inDrag) - workspace.actor.visible = (Math.abs(w - active) <= 1); - else - workspace.actor.visible = (w == active); + workspace.actor.visible = (w == active); } } }, @@ -303,26 +290,6 @@ WorkspacesView.prototype = { _onDestroy: function() { this._scrollAdjustment.run_dispose(); global.window_manager.disconnect(this._switchWorkspaceNotifyId); - - if (this._inDrag) - this._dragEnd(); - - if (this._itemDragBeginId > 0) { - Main.overview.disconnect(this._itemDragBeginId); - this._itemDragBeginId = 0; - } - if (this._itemDragEndId > 0) { - Main.overview.disconnect(this._itemDragEndId); - this._itemDragEndId = 0; - } - if (this._windowDragBeginId > 0) { - Main.overview.disconnect(this._windowDragBeginId); - this._windowDragBeginId = 0; - } - if (this._windowDragEndId > 0) { - Main.overview.disconnect(this._windowDragEndId); - this._windowDragEndId = 0; - } }, _onMappedChanged: function() { @@ -340,40 +307,6 @@ WorkspacesView.prototype = { } }, - _dragBegin: function() { - if (this._scrolling) - return; - - this._inDrag = true; - this._firstDragMotion = true; - - this._dragMonitor = { - dragMotion: Lang.bind(this, this._onDragMotion) - }; - DND.addDragMonitor(this._dragMonitor); - }, - - _onDragMotion: function(dragEvent) { - if (Main.overview.animationInProgress) - return DND.DragMotionResult.CONTINUE; - - if (this._firstDragMotion) { - this._firstDragMotion = false; - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate); - } - - return DND.DragMotionResult.CONTINUE; - }, - - _dragEnd: function() { - DND.removeDragMonitor(this._dragMonitor); - this._inDrag = false; - - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].setReservedSlot(null); - }, - _swipeScrollBegin: function() { this._scrolling = true; }, @@ -470,9 +403,6 @@ WorkspacesDisplay.prototype = { this.workspacesView = null; - this._inDrag = false; - this._cancelledDrag = false; - this._alwaysZoomOut = false; this._zoomOut = false; this._zoomFraction = 0; @@ -481,24 +411,8 @@ WorkspacesDisplay.prototype = { Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom)); - Main.xdndHandler.connect('drag-begin', Lang.bind(this, function(){ - this._alwaysZoomOut = true; - })); - - Main.xdndHandler.connect('drag-end', Lang.bind(this, function(){ - this._alwaysZoomOut = false; - this._updateAlwaysZoom(); - })); - this._switchWorkspaceNotifyId = 0; - this._nWorkspacesChangedId = 0; - this._itemDragBeginId = 0; - this._itemDragCancelledId = 0; - this._itemDragEndId = 0; - this._windowDragBeginId = 0; - this._windowDragCancelledId = 0; - this._windowDragEndId = 0; }, show: function() { @@ -527,25 +441,6 @@ WorkspacesDisplay.prototype = { if (this._nWorkspacesChangedId == 0) this._nWorkspacesChangedId = global.screen.connect('notify::n-workspaces', Lang.bind(this, this._workspacesChanged)); - if (this._itemDragBeginId == 0) - this._itemDragBeginId = Main.overview.connect('item-drag-begin', - Lang.bind(this, this._dragBegin)); - if (this._itemDragCancelledId == 0) - this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled', - Lang.bind(this, this._dragCancelled)); - if (this._itemDragEndId == 0) - this._itemDragEndId = Main.overview.connect('item-drag-end', - Lang.bind(this, this._dragEnd)); - if (this._windowDragBeginId == 0) - this._windowDragBeginId = Main.overview.connect('window-drag-begin', - Lang.bind(this, this._dragBegin)); - if (this._windowDragCancelledId == 0) - this._windowDragCancelledId = Main.overview.connect('window-drag-cancelled', - Lang.bind(this, this._dragCancelled)); - if (this._windowDragEndId == 0) - this._windowDragEndId = Main.overview.connect('window-drag-end', - Lang.bind(this, this._dragEnd)); - this._onRestacked(); }, @@ -557,30 +452,6 @@ WorkspacesDisplay.prototype = { global.screen.disconnect(this._restackedNotifyId); this._restackedNotifyId = 0; } - if (this._itemDragBeginId > 0) { - Main.overview.disconnect(this._itemDragBeginId); - this._itemDragBeginId = 0; - } - if (this._itemDragCancelledId > 0) { - Main.overview.disconnect(this._itemDragCancelledId); - this._itemDragCancelledId = 0; - } - if (this._itemDragEndId > 0) { - Main.overview.disconnect(this._itemDragEndId); - this._itemDragEndId = 0; - } - if (this._windowDragBeginId > 0) { - Main.overview.disconnect(this._windowDragBeginId); - this._windowDragBeginId = 0; - } - if (this._windowDragCancelledId > 0) { - Main.overview.disconnect(this._windowDragCancelledId); - this._windowDragCancelledId = 0; - } - if (this._windowDragEndId > 0) { - Main.overview.disconnect(this._windowDragEndId); - this._windowDragEndId = 0; - } this.workspacesView.destroy(); this.workspacesView = null; @@ -776,39 +647,6 @@ WorkspacesDisplay.prototype = { this._updateZoom(); }, - _dragBegin: function() { - this._inDrag = true; - this._cancelledDrag = false; - this._dragMonitor = { - dragMotion: Lang.bind(this, this._onDragMotion) - }; - DND.addDragMonitor(this._dragMonitor); - }, - - _dragCancelled: function() { - this._cancelledDrag = true; - DND.removeDragMonitor(this._dragMonitor); - }, - - _onDragMotion: function(dragEvent) { - let controlsHovered = this._controls.contains(dragEvent.targetActor); - this._controls.set_hover(controlsHovered); - - return DND.DragMotionResult.CONTINUE; - }, - - _dragEnd: function() { - this._inDrag = false; - - // We do this deferred because drag-end is emitted before dnd.js emits - // event/leave events that were suppressed during the drag. If we didn't - // defer this, we'd zoom out then immediately zoom in because of the - // enter event we received. That would normally be invisible but we - // might as well avoid it. - Meta.later_add(Meta.LaterType.BEFORE_REDRAW, - Lang.bind(this, this._updateZoom)); - }, - _onScrollEvent: function (actor, event) { switch ( event.get_scroll_direction() ) { case Clutter.ScrollDirection.UP: From f68121ebb9301100008d2e5c3582ec49309202a7 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 09:52:33 +0100 Subject: [PATCH 51/74] [Scale] Refactoring (3): Remove workspace-changed logic. --- js/ui/workspacesView.js | 75 +---------------------------------------- 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 0d49249a28..fcce93b7e2 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -258,28 +258,6 @@ WorkspacesView.prototype = { this._workspaces[active].zoomToOverview(); }, - updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) { - let active = global.screen.get_active_workspace_index(); - - Tweener.addTween(this._scrollAdjustment, - { upper: newNumWorkspaces, - time: WORKSPACE_SWITCH_TIME, - transition: 'easeOutQuad' - }); - - if (newNumWorkspaces > oldNumWorkspaces) { - for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) { - this._workspaces[w].setGeometry(this._x, this._y, - this._width, this._height, this._workspaceRatioSpacing); - this.actor.add_actor(this._workspaces[w].actor); - } - - this._updateWorkspaceActors(false); - } - - this._scrollToActive(true); - }, - _activeWorkspaceChanged: function(wm, from, to, direction) { if (this._scrolling) return; @@ -364,10 +342,6 @@ WorkspacesView.prototype = { this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; this._workspaces[i].actor.x += dx; } - }, - - _getWorkspaceIndexToRemove: function() { - return global.screen.get_active_workspace_index(); } }; Signals.addSignalMethods(WorkspacesView.prototype); @@ -572,54 +546,7 @@ WorkspacesDisplay.prototype = { }, _workspacesChanged: function() { - let oldNumWorkspaces = this._workspaces.length; - let newNumWorkspaces = global.screen.n_workspaces; - let active = global.screen.get_active_workspace_index(); - - if (oldNumWorkspaces == newNumWorkspaces) - return; - - this._updateAlwaysZoom(); - this._updateZoom(); - - if (this.workspacesView == null) - return; - - let lostWorkspaces = []; - if (newNumWorkspaces > oldNumWorkspaces) { - // Assume workspaces are only added at the end - for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) { - let metaWorkspace = global.screen.get_workspace_by_index(w); - this._workspaces[w] = new Workspace.Workspace(metaWorkspace, this._monitorIndex); - } - - // this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces); - } else { - // Assume workspaces are only removed sequentially - // (e.g. 2,3,4 - not 2,4,7) - let removedIndex; - let removedNum = oldNumWorkspaces - newNumWorkspaces; - for (let w = 0; w < oldNumWorkspaces; w++) { - let metaWorkspace = global.screen.get_workspace_by_index(w); - if (this._workspaces[w].metaWorkspace != metaWorkspace) { - removedIndex = w; - break; - } - } - - lostWorkspaces = this._workspaces.splice(removedIndex, - removedNum); - - for (let l = 0; l < lostWorkspaces.length; l++) { - lostWorkspaces[l].disconnectAll(); - lostWorkspaces[l].destroy(); - } - - // this._thumbnailsBox.removeThumbmails(removedIndex, removedNum); - } - - this.workspacesView.updateWorkspaces(oldNumWorkspaces, - newNumWorkspaces); + Main.overview.hide(); }, _updateZoom : function() { From 40a7fc3b756d62d1d7eef6273eb6d7bf698d6aa0 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 10:21:24 +0100 Subject: [PATCH 52/74] [Scale] Refactoring (4): _alwaysUpdateZoom removed. --- js/ui/workspacesView.js | 62 ++--------------------------------------- 1 file changed, 2 insertions(+), 60 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index fcce93b7e2..e7c27e967c 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -368,8 +368,6 @@ WorkspacesDisplay.prototype = { controls.reactive = true; controls.track_hover = true; - controls.connect('notify::hover', - Lang.bind(this, this._onControlsHoverChanged)); controls.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); @@ -377,25 +375,17 @@ WorkspacesDisplay.prototype = { this.workspacesView = null; - this._alwaysZoomOut = false; this._zoomOut = false; - this._zoomFraction = 0; + this._zoomFraction = 1; - this._updateAlwaysZoom(); - - Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom)); + Main.layoutManager.connect('monitors-changed', Main.overview.hide); this._switchWorkspaceNotifyId = 0; this._nWorkspacesChangedId = 0; }, show: function() { - this._zoomOut = this._alwaysZoomOut; - this._zoomFraction = this._alwaysZoomOut ? 1 : 0; - this._updateZoom(); - this._controls.show(); - // this._thumbnailsBox.show(); this._workspaces = []; for (let i = 0; i < global.screen.n_workspaces; i++) { @@ -420,7 +410,6 @@ WorkspacesDisplay.prototype = { hide: function() { this._controls.hide(); - // this._thumbnailsBox.hide(); if (this._restackedNotifyId > 0){ global.screen.disconnect(this._restackedNotifyId); @@ -445,28 +434,6 @@ WorkspacesDisplay.prototype = { return this._zoomFraction; }, - _updateAlwaysZoom: function() { - // Always show the pager if workspaces are actually used, - // e.g. there are windows on more than one - this._alwaysZoomOut = global.screen.n_workspaces > 2; - - if (this._alwaysZoomOut) - return; - - let monitors = Main.layoutManager.monitors; - let primary = Main.layoutManager.primaryMonitor; - - /* Look for any monitor to the right of the primary, if there is - * one, we always keep zoom out, otherwise its hard to reach - * the thumbnail area without passing into the next monitor. */ - for (let i = 0; i < monitors.length; i++) { - if (monitors[i].x >= primary.x + primary.width) { - this._alwaysZoomOut = true; - break; - } - } - }, - _getPreferredWidth: function (actor, forHeight, alloc) { // pass through the call in case the child needs it, but report 0x0 this._controls.get_preferred_width(forHeight); @@ -549,31 +516,6 @@ WorkspacesDisplay.prototype = { Main.overview.hide(); }, - _updateZoom : function() { - if (Main.overview.animationInProgress) - return; - - let shouldZoom = this._alwaysZoomOut || this._controls.hover; - if (shouldZoom != this._zoomOut) { - this._zoomOut = shouldZoom; - this._updateWorkspacesGeometry(); - - if (!this.workspacesView) - return; - - Tweener.addTween(this, - { zoomFraction: this._zoomOut ? 1 : 0, - time: WORKSPACE_SWITCH_TIME, - transition: 'easeOutQuad' }); - - this.workspacesView.updateWindowPositions(); - } - }, - - _onControlsHoverChanged: function() { - this._updateZoom(); - }, - _onScrollEvent: function (actor, event) { switch ( event.get_scroll_direction() ) { case Clutter.ScrollDirection.UP: From f61764b392f24db5fe40d6ea64f5e9dedbad636d Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 10:43:45 +0100 Subject: [PATCH 53/74] [Scale] Refactoring (5): Get rid of unused workspace controls. --- js/ui/workspacesView.js | 71 ++--------------------------------------- 1 file changed, 2 insertions(+), 69 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index e7c27e967c..08727e7f3f 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -17,9 +17,6 @@ const WORKSPACE_SWITCH_TIME = 0.25; const MAX_WORKSPACES = 16; -const CONTROLS_POP_IN_TIME = 0.1; - - function WorkspacesView(workspaces) { this._init(workspaces); } @@ -354,21 +351,10 @@ function WorkspacesDisplay() { WorkspacesDisplay.prototype = { _init: function() { this.actor = new Cinnamon.GenericContainer(); - this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); - this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight)); this.actor.connect('allocate', Lang.bind(this, this._allocate)); this.actor.set_clip_to_allocation(true); - let controls = new St.Bin({ style_class: 'workspace-controls', - request_mode: Clutter.RequestMode.HEIGHT_FOR_WIDTH, - x_align: St.Align.START, - x_fill: true }); - this._controls = controls; - this.actor.add_actor(controls); - - controls.reactive = true; - controls.track_hover = true; - controls.connect('scroll-event', + this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); this._monitorIndex = Main.layoutManager.primaryIndex; @@ -376,7 +362,6 @@ WorkspacesDisplay.prototype = { this.workspacesView = null; this._zoomOut = false; - this._zoomFraction = 1; Main.layoutManager.connect('monitors-changed', Main.overview.hide); @@ -385,8 +370,6 @@ WorkspacesDisplay.prototype = { }, show: function() { - this._controls.show(); - this._workspaces = []; for (let i = 0; i < global.screen.n_workspaces; i++) { let metaWorkspace = global.screen.get_workspace_by_index(i); @@ -409,8 +392,6 @@ WorkspacesDisplay.prototype = { }, hide: function() { - this._controls.hide(); - if (this._restackedNotifyId > 0){ global.screen.disconnect(this._restackedNotifyId); this._restackedNotifyId = 0; @@ -424,45 +405,7 @@ WorkspacesDisplay.prototype = { } }, - // zoomFraction property allows us to tween the controls sliding in and out - set zoomFraction(fraction) { - this._zoomFraction = fraction; - this.actor.queue_relayout(); - }, - - get zoomFraction() { - return this._zoomFraction; - }, - - _getPreferredWidth: function (actor, forHeight, alloc) { - // pass through the call in case the child needs it, but report 0x0 - this._controls.get_preferred_width(forHeight); - }, - - _getPreferredHeight: function (actor, forWidth, alloc) { - // pass through the call in case the child needs it, but report 0x0 - this._controls.get_preferred_height(forWidth); - }, - _allocate: function (actor, box, flags) { - let childBox = new Clutter.ActorBox(); - - let totalHeight = box.y2 - box.y1; - - // height of the controls - let [controlsMin, controlsNatural] = this._controls.get_preferred_height(box.x2 - box.x1); - - // Amount of space on the screen we reserve for the visible control - let controlsVisible = this._controls.get_theme_node().get_length('visible-height'); - let controlsReserved = controlsVisible * (1 - this._zoomFraction) + controlsNatural * this._zoomFraction; - - childBox.y1 = totalHeight - controlsReserved; - childBox.y2 = childBox.y1 + controlsNatural; - - childBox.x1 = 0; - childBox.x2 = box.x2- box.x1; - this._controls.allocate(childBox, flags); - this._updateWorkspacesGeometry(); }, @@ -475,25 +418,15 @@ WorkspacesDisplay.prototype = { let width = fullWidth; let height = fullHeight; - - let [controlsMin, controlsNatural] = this._controls.get_preferred_height(width); - let controlsVisible = this._controls.get_theme_node().get_length('visible-height'); - let [x, y] = this.actor.get_transformed_position(); - let clipHeight = height - controlsVisible; + let clipHeight = height; let clipWidth = (fullWidth / fullHeight) * clipHeight; let clipY = y; let clipX = x + (fullWidth - clipWidth) / 2; this.workspacesView.setClipRect(clipX, clipY, clipWidth, clipHeight); - if (this._zoomOut) { - height -= controlsNatural; - } else { - height -= controlsVisible; - } - width = (fullWidth / fullHeight) * height; let difference = fullWidth - width; x += difference / 2; From 0405db4a5cc01c81afca4cf5ef57cc575831dde6 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 10:58:07 +0100 Subject: [PATCH 54/74] [Scale] Refactoring (6): Move ownership of _workspaces to the view. --- js/ui/workspacesView.js | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 08727e7f3f..2265e94184 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -55,11 +55,12 @@ WorkspacesView.prototype = { this._zoomOut = false; // zoom to a larger area let activeWorkspaceIndex = global.screen.get_active_workspace_index(); - this._workspaces = workspaces; - - // Add workspace actors - for (let w = 0; w < global.screen.n_workspaces; w++) - this._workspaces[w].actor.reparent(this.actor); + this._workspaces = []; + for (let i = 0; i < global.screen.n_workspaces; i++) { + let metaWorkspace = global.screen.get_workspace_by_index(i); + this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this); + this.actor.add_actor(this._workspaces[i].actor); + } this._workspaces[activeWorkspaceIndex].actor.raise_top(); // Position/scale the desktop windows and their children after the @@ -154,6 +155,10 @@ WorkspacesView.prototype = { }, destroy: function() { + for (let w = 0; w < this._workspaces.length; w++) { + this._workspaces[w].disconnectAll(); + this._workspaces[w].destroy(); + } this.actor.destroy(); }, @@ -370,15 +375,7 @@ WorkspacesDisplay.prototype = { }, show: function() { - this._workspaces = []; - for (let i = 0; i < global.screen.n_workspaces; i++) { - let metaWorkspace = global.screen.get_workspace_by_index(i); - this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this); - } - - if (this.workspacesView) - this.workspacesView.destroy(); - this.workspacesView = new WorkspacesView(this._workspaces); + this.workspacesView = new WorkspacesView(); this._updateWorkspacesGeometry(); this._restackedNotifyId = @@ -399,10 +396,6 @@ WorkspacesDisplay.prototype = { this.workspacesView.destroy(); this.workspacesView = null; - for (let w = 0; w < this._workspaces.length; w++) { - this._workspaces[w].disconnectAll(); - this._workspaces[w].destroy(); - } }, _allocate: function (actor, box, flags) { From 4da562f2227eabaa39518fc47ae7c9ed61bff181 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 15:54:34 +0100 Subject: [PATCH 55/74] [Scale] Refactoring (7): Move more members from display to view. --- js/ui/workspacesView.js | 78 +++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 49 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 2265e94184..7713468159 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -52,7 +52,6 @@ WorkspacesView.prototype = { this._animating = false; // tweening this._scrolling = false; // swipe-scrolling this._animatingScroll = false; // programatically updating the adjustment - this._zoomOut = false; // zoom to a larger area let activeWorkspaceIndex = global.screen.get_active_workspace_index(); this._workspaces = []; @@ -82,13 +81,25 @@ WorkspacesView.prototype = { this._scrollAdjustment.connect('notify::value', Lang.bind(this, this._onScroll)); - this._switchWorkspaceNotifyId = - global.window_manager.connect('switch-workspace', - Lang.bind(this, this._activeWorkspaceChanged)); this._swipeScrollBeginId = 0; this._swipeScrollEndId = 0; + let restackedNotifyId = global.screen.connect('restacked', Lang.bind(this, this._onRestacked)); + let switchWorkspaceNotifyId = global.window_manager.connect('switch-workspace', + Lang.bind(this, this._activeWorkspaceChanged)); + + let nWorkspacesChangedId = global.screen.connect('notify::n-workspaces', Main.overview.hide); + let monitorsChangedId = Main.layoutManager.connect('monitors-changed', Main.overview.hide); + + this._disconnectHandlers = function() { + global.window_manager.disconnect(switchWorkspaceNotifyId); + Main.layoutManager.disconnect(monitorsChangedId); + global.screen.disconnect(nWorkspacesChangedId); + global.screen.disconnect(restackedNotifyId); + }; + + this._onRestacked(); this.actor.connect('key-press-event', Lang.bind(this, this._onStageKeyPress)); global.stage.set_key_focus(this.actor); }, @@ -162,11 +173,6 @@ WorkspacesView.prototype = { this.actor.destroy(); }, - syncStacking: function(stackIndices) { - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].syncStacking(stackIndices); - }, - updateWindowPositions: function() { for (let w = 0; w < this._workspaces.length; w++) this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE); @@ -269,7 +275,7 @@ WorkspacesView.prototype = { _onDestroy: function() { this._scrollAdjustment.run_dispose(); - global.window_manager.disconnect(this._switchWorkspaceNotifyId); + this._disconnectHandlers(); }, _onMappedChanged: function() { @@ -312,6 +318,19 @@ WorkspacesView.prototype = { this._updateVisibility(); }, + _onRestacked: function() { + let stack = global.get_window_actors().reverse(); + let stackIndices = {}; + + for (let i = 0; i < stack.length; i++) { + // Use the stable sequence for an integer to use as a hash key + stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i; + } + + for (let i = 0; i < this._workspaces.length; i++) + this._workspaces[i].syncStacking(stackIndices); + }, + // sync the workspaces' positions to the value of the scroll adjustment // and change the active workspace if appropriate _onScroll: function(adj) { @@ -362,38 +381,15 @@ WorkspacesDisplay.prototype = { this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); - this._monitorIndex = Main.layoutManager.primaryIndex; - this.workspacesView = null; - - this._zoomOut = false; - - Main.layoutManager.connect('monitors-changed', Main.overview.hide); - - this._switchWorkspaceNotifyId = 0; - this._nWorkspacesChangedId = 0; }, show: function() { this.workspacesView = new WorkspacesView(); this._updateWorkspacesGeometry(); - - this._restackedNotifyId = - global.screen.connect('restacked', - Lang.bind(this, this._onRestacked)); - - if (this._nWorkspacesChangedId == 0) - this._nWorkspacesChangedId = global.screen.connect('notify::n-workspaces', - Lang.bind(this, this._workspacesChanged)); - this._onRestacked(); }, hide: function() { - if (this._restackedNotifyId > 0){ - global.screen.disconnect(this._restackedNotifyId); - this._restackedNotifyId = 0; - } - this.workspacesView.destroy(); this.workspacesView = null; }, @@ -426,22 +422,6 @@ WorkspacesDisplay.prototype = { this.workspacesView.setGeometry(x, y, width, height, difference); }, - _onRestacked: function() { - let stack = global.get_window_actors().reverse(); - let stackIndices = {}; - - for (let i = 0; i < stack.length; i++) { - // Use the stable sequence for an integer to use as a hash key - stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i; - } - - this.workspacesView.syncStacking(stackIndices); - }, - - _workspacesChanged: function() { - Main.overview.hide(); - }, - _onScrollEvent: function (actor, event) { switch ( event.get_scroll_direction() ) { case Clutter.ScrollDirection.UP: From 723b16c04ebeffb40af82d98199846f6f5161eee Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 18:57:52 +0100 Subject: [PATCH 56/74] [Scale] Refactoring (8): Move even more members from display to view. --- js/ui/workspacesView.js | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 7713468159..9562e63aae 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -30,14 +30,16 @@ WorkspacesView.prototype = { this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); + // does not work: + // this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); + this.actor.connect('style-changed', Lang.bind(this, function() { let node = this.actor.get_theme_node(); this._spacing = node.get_length('spacing'); this._updateWorkspaceActors(false); })); - this.actor.connect('notify::mapped', - Lang.bind(this, this._onMappedChanged)); + this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedChanged)); this._width = 0; this._height = 0; @@ -363,6 +365,17 @@ WorkspacesView.prototype = { this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; this._workspaces[i].actor.x += dx; } + }, + + _onScrollEvent: function (actor, event) { + switch ( event.get_scroll_direction() ) { + case Clutter.ScrollDirection.UP: + Main.wm.actionMoveWorkspaceUp(); + break; + case Clutter.ScrollDirection.DOWN: + Main.wm.actionMoveWorkspaceDown(); + break; + } } }; Signals.addSignalMethods(WorkspacesView.prototype); @@ -375,13 +388,7 @@ function WorkspacesDisplay() { WorkspacesDisplay.prototype = { _init: function() { this.actor = new Cinnamon.GenericContainer(); - this.actor.connect('allocate', Lang.bind(this, this._allocate)); this.actor.set_clip_to_allocation(true); - - this.actor.connect('scroll-event', - Lang.bind(this, this._onScrollEvent)); - - this.workspacesView = null; }, show: function() { @@ -394,14 +401,7 @@ WorkspacesDisplay.prototype = { this.workspacesView = null; }, - _allocate: function (actor, box, flags) { - this._updateWorkspacesGeometry(); - }, - _updateWorkspacesGeometry: function() { - if (!this.workspacesView) - return; - let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1; let fullHeight = this.actor.allocation.y2 - this.actor.allocation.y1; @@ -420,17 +420,6 @@ WorkspacesDisplay.prototype = { let difference = fullWidth - width; x += difference / 2; this.workspacesView.setGeometry(x, y, width, height, difference); - }, - - _onScrollEvent: function (actor, event) { - switch ( event.get_scroll_direction() ) { - case Clutter.ScrollDirection.UP: - Main.wm.actionMoveWorkspaceUp(); - break; - case Clutter.ScrollDirection.DOWN: - Main.wm.actionMoveWorkspaceDown(); - break; - } } }; Signals.addSignalMethods(WorkspacesDisplay.prototype); From 729703cdfe6b9c8296e415467c7c6bf6ccadfc09 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 19:05:53 +0100 Subject: [PATCH 57/74] [Scale] Refactoring (9): Remove clip* members. --- js/ui/workspacesView.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 9562e63aae..e1e94827c8 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -45,10 +45,6 @@ WorkspacesView.prototype = { this._height = 0; this._x = 0; this._y = 0; - this._clipX = 0; - this._clipY = 0; - this._clipWidth = 0; - this._clipHeight = 0; this._workspaceRatioSpacing = 0; this._spacing = 0; this._animating = false; // tweening @@ -134,13 +130,6 @@ WorkspacesView.prototype = { this._workspaces[i].setGeometry(x, y, width, height, spacing); }, - setClipRect: function(x, y, width, height) { - this._clipX = x; - this._clipY = y; - this._clipWidth = width; - this._clipHeight = height; - }, - _lookupWorkspaceForMetaWindow: function (metaWindow) { for (let i = 0; i < this._workspaces.length; i++) { if (this._workspaces[i].containsMetaWindow(metaWindow)) @@ -163,7 +152,6 @@ WorkspacesView.prototype = { let activeWorkspace = this._workspaces[activeWorkspaceIndex]; activeWorkspace.actor.raise_top(); - this.actor.remove_clip(this._x, this._y, this._width, this._height); activeWorkspace.zoomFromOverview(); }, @@ -409,13 +397,6 @@ WorkspacesDisplay.prototype = { let height = fullHeight; let [x, y] = this.actor.get_transformed_position(); - let clipHeight = height; - let clipWidth = (fullWidth / fullHeight) * clipHeight; - let clipY = y; - let clipX = x + (fullWidth - clipWidth) / 2; - - this.workspacesView.setClipRect(clipX, clipY, clipWidth, clipHeight); - width = (fullWidth / fullHeight) * height; let difference = fullWidth - width; x += difference / 2; From d08d5def73b90ec383ea57126fa53cdbf443bede Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 19:16:01 +0100 Subject: [PATCH 58/74] [Scale] Refactoring (10): Remove a duplicate handler. --- js/ui/workspacesView.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index e1e94827c8..75b4c7ca87 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -88,11 +88,9 @@ WorkspacesView.prototype = { Lang.bind(this, this._activeWorkspaceChanged)); let nWorkspacesChangedId = global.screen.connect('notify::n-workspaces', Main.overview.hide); - let monitorsChangedId = Main.layoutManager.connect('monitors-changed', Main.overview.hide); this._disconnectHandlers = function() { global.window_manager.disconnect(switchWorkspaceNotifyId); - Main.layoutManager.disconnect(monitorsChangedId); global.screen.disconnect(nWorkspacesChangedId); global.screen.disconnect(restackedNotifyId); }; From ac5ea43b5c9b34de299d1c6b36ca797e1ca479ac Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 20:26:05 +0100 Subject: [PATCH 59/74] [Scale] Use all available screen space. --- js/ui/overview.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index fb79a004f8..27c29abaee 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -417,20 +417,11 @@ Overview.prototype = { this.hide(); let primary = Main.layoutManager.primaryMonitor; - let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL); - - let contentHeight = primary.height; - this._group.set_position(primary.x, primary.y); this._group.set_size(primary.width, primary.height); - let viewWidth = primary.width - 2 * this._spacing; - let viewHeight = contentHeight - this._spacing; - let viewY = this._spacing; - let viewX = rtl ? 0 : this._spacing; - - this._workspacesDisplay.actor.set_position(viewX, viewY); - this._workspacesDisplay.actor.set_size(viewWidth, viewHeight); + this._workspacesDisplay.actor.set_position(0, 0); + this._workspacesDisplay.actor.set_size(primary.width, primary.height); this._workspacesDisplay.actor.hide(); }, From 71d444010e5a84ae0904fcaee6c3c8927e17fa36 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 21:09:47 +0100 Subject: [PATCH 60/74] [Scale] Refactoring (11): Get rid of WorkspacesView.WorkspacesDisplay. --- js/ui/overview.js | 44 ++++++++-------------------------------- js/ui/workspace.js | 9 ++------- js/ui/workspacesView.js | 45 ++++------------------------------------- 3 files changed, 14 insertions(+), 84 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index 27c29abaee..f68c70f579 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -100,7 +100,6 @@ Overview.prototype = { if (this.isDummy) { this.animationInProgress = false; this.visible = false; - this.workspaces = null; return; } @@ -115,7 +114,6 @@ Overview.prototype = { let spacing = node.get_length('spacing'); if (spacing != this._spacing) { this._spacing = spacing; - this._relayout(); } })); this._group.hide(); @@ -126,8 +124,6 @@ Overview.prototype = { this._capturedEventId = 0; this._buttonPressId = 0; - this._workspacesDisplay = null; - this.visible = false; // animating to overview, in overview, animating out this._shown = false; // show() and not hide() this._shownTemporarily = false; // showTemporarily() and not hideTemporarily() @@ -148,8 +144,6 @@ Overview.prototype = { this._lastActiveWorkspaceIndex = -1; this._lastHoveredWindow = null; this._needsFakePointerEvent = false; - - this.workspaces = null; }, // The members we construct that are implemented in JS might @@ -162,10 +156,7 @@ Overview.prototype = { this._cinnamonInfo = new CinnamonInfo(); - this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay(); - this._group.add_actor(this._workspacesDisplay.actor); - Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout)); - this._relayout(); + Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.hide)); }, setMessage: function(text, undoCallback, undoLabel) { @@ -410,21 +401,6 @@ Overview.prototype = { return clone; }, - _relayout: function () { - // To avoid updating the position and size of the workspaces - // we just hide the overview. The positions will be updated - // when it is next shown. - this.hide(); - - let primary = Main.layoutManager.primaryMonitor; - this._group.set_position(primary.x, primary.y); - this._group.set_size(primary.width, primary.height); - - this._workspacesDisplay.actor.set_position(0, 0); - this._workspacesDisplay.actor.set_size(primary.width, primary.height); - this._workspacesDisplay.actor.hide(); - }, - //// Public methods //// beginItemDrag: function(source) { @@ -520,16 +496,14 @@ Overview.prototype = { this._group.show(); this._background.show(); - this._workspacesDisplay.show(); + this.workspacesView = new WorkspacesView.WorkspacesView(); + global.overlay_group.add_actor(this.workspacesView.actor); Main.disablePanels(); - this.workspaces = this._workspacesDisplay.workspacesView; - global.overlay_group.add_actor(this.workspaces.actor); - if (!this._desktopFade.child) this._desktopFade.child = this._getDesktopClone(); - if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) { + if (!this.workspacesView.getActiveWorkspace().hasMaximizedWindows()) { this._desktopFade.opacity = 255; this._desktopFade.show(); Tweener.addTween(this._desktopFade, @@ -659,7 +633,7 @@ Overview.prototype = { this._hideInProgress = true; Main.enablePanels(); - if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) { + if (!this.workspacesView.getActiveWorkspace().hasMaximizedWindows()) { this._desktopFade.opacity = 0; this._desktopFade.show(); Tweener.addTween(this._desktopFade, @@ -668,7 +642,7 @@ Overview.prototype = { transition: 'easeOutQuad' }); } - this.workspaces.hide(); + this.workspacesView.hide(); // Make other elements fade out. Tweener.addTween(this._group, @@ -711,10 +685,8 @@ Overview.prototype = { global.window_group.show(); - this.workspaces.destroy(); - this.workspaces = null; - - this._workspacesDisplay.hide(); + this.workspacesView.destroy(); + this.workspacesView = null; this._group.hide(); diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 933f9be33e..01e1320275 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -852,12 +852,9 @@ WorkspaceMonitor.prototype = { // This is sometimes called during allocation, so we do this later Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function () { - this._dropRect.set_position(x, y); - this._dropRect.set_size(width, height); this.positionWindows(WindowPositionFlags.ANIMATE); return false; })); - }, _lookupIndex: function (metaWindow) { @@ -1720,12 +1717,10 @@ Workspace.prototype = { this.actor.destroy(); }, - setGeometry: function(x, y, width, height, spacing_unused) { - let primary = Main.layoutManager.primaryMonitor; - let margin = (primary.width - width) / 2; + setGeometry: function() { this._monitors.forEach(function(monitor, index) { let mon = Main.layoutManager.monitors[index]; - monitor.setGeometry(mon.x, mon.y, mon.width, mon.height, margin); + monitor.setGeometry(mon.x, mon.y, mon.width, mon.height, 0); }, this); }, diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 75b4c7ca87..93eb10ecc2 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -98,6 +98,9 @@ WorkspacesView.prototype = { this._onRestacked(); this.actor.connect('key-press-event', Lang.bind(this, this._onStageKeyPress)); global.stage.set_key_focus(this.actor); + + let primary = Main.layoutManager.primaryMonitor; + this.setGeometry(primary.x, primary.y, primary.width, primary.height, 0); }, _onStageKeyPress: function(actor, event) { @@ -115,9 +118,6 @@ WorkspacesView.prototype = { }, setGeometry: function(x, y, width, height, spacing) { - if (this._x == x && this._y == y && - this._width == width && this._height == height) - return; this._width = width; this._height = height; this._x = x; @@ -125,7 +125,7 @@ WorkspacesView.prototype = { this._workspaceRatioSpacing = spacing; for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].setGeometry(x, y, width, height, spacing); + this._workspaces[i].setGeometry(); }, _lookupWorkspaceForMetaWindow: function (metaWindow) { @@ -365,40 +365,3 @@ WorkspacesView.prototype = { } }; Signals.addSignalMethods(WorkspacesView.prototype); - - -function WorkspacesDisplay() { - this._init(); -} - -WorkspacesDisplay.prototype = { - _init: function() { - this.actor = new Cinnamon.GenericContainer(); - this.actor.set_clip_to_allocation(true); - }, - - show: function() { - this.workspacesView = new WorkspacesView(); - this._updateWorkspacesGeometry(); - }, - - hide: function() { - this.workspacesView.destroy(); - this.workspacesView = null; - }, - - _updateWorkspacesGeometry: function() { - let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1; - let fullHeight = this.actor.allocation.y2 - this.actor.allocation.y1; - - let width = fullWidth; - let height = fullHeight; - let [x, y] = this.actor.get_transformed_position(); - - width = (fullWidth / fullHeight) * height; - let difference = fullWidth - width; - x += difference / 2; - this.workspacesView.setGeometry(x, y, width, height, difference); - } -}; -Signals.addSignalMethods(WorkspacesDisplay.prototype); From 81425edb2429ddce493fca15b9e9f89900220689 Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 21:21:08 +0100 Subject: [PATCH 61/74] [Scale] Refactoring (12): Avoid mutual import. --- js/ui/overview.js | 12 ++---------- js/ui/workspacesView.js | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index f68c70f579..ad13c5bbc2 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -22,17 +22,9 @@ const ANIMATION_TIME = 0.25; const DND_WINDOW_SWITCH_TIMEOUT = 1250; -const SwipeScrollDirection = { - NONE: 0, - HORIZONTAL: 1, - VERTICAL: 2 -}; +const SwipeScrollDirection = WorkspacesView.SwipeScrollDirection; -const SwipeScrollResult = { - CANCEL: 0, - SWIPE: 1, - CLICK: 2 -}; +const SwipeScrollResult = WorkspacesView.SwipeScrollResult; function CinnamonInfo() { this._init(); diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 93eb10ecc2..5aad9ab9e4 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -8,14 +8,22 @@ const St = imports.gi.St; const Signals = imports.signals; const Main = imports.ui.main; -const Overview = imports.ui.overview; const Tweener = imports.ui.tweener; const Workspace = imports.ui.workspace; const WORKSPACE_SWITCH_TIME = 0.25; -// Note that muffin has a compile-time limit of 36 -const MAX_WORKSPACES = 16; +const SwipeScrollDirection = { + NONE: 0, + HORIZONTAL: 1, + VERTICAL: 2 +}; + +const SwipeScrollResult = { + CANCEL: 0, + SWIPE: 1, + CLICK: 2 +}; function WorkspacesView(workspaces) { this._init(workspaces); @@ -268,7 +276,7 @@ WorkspacesView.prototype = { _onMappedChanged: function() { if (this.actor.mapped) { - let direction = Overview.SwipeScrollDirection.HORIZONTAL; + let direction = SwipeScrollDirection.HORIZONTAL; Main.overview.setScrollAdjustment(this._scrollAdjustment, direction); this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin', @@ -288,7 +296,7 @@ WorkspacesView.prototype = { _swipeScrollEnd: function(overview, result) { this._scrolling = false; - if (result == Overview.SwipeScrollResult.CLICK) { + if (result == SwipeScrollResult.CLICK) { let [x, y, mod] = global.get_pointer(); let actor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); From 9444fefe96f6d02ad9925514aa1826ecedcc2a7f Mon Sep 17 00:00:00 2001 From: autarkper Date: Fri, 16 Nov 2012 21:31:58 +0100 Subject: [PATCH 62/74] [Scale] Refactoring (13): Remove more drag-and-drop left-overs. --- js/ui/overview.js | 85 ----------------------------------------------- 1 file changed, 85 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index ad13c5bbc2..c5c056d7fe 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -10,7 +10,6 @@ const St = imports.gi.St; const Cinnamon = imports.gi.Cinnamon; const Gdk = imports.gi.Gdk; -const DND = imports.ui.dnd; const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; const Params = imports.misc.params; @@ -20,8 +19,6 @@ const WorkspacesView = imports.ui.workspacesView; // Time for initial animation going into Overview mode const ANIMATION_TIME = 0.25; -const DND_WINDOW_SWITCH_TIMEOUT = 1250; - const SwipeScrollDirection = WorkspacesView.SwipeScrollDirection; const SwipeScrollResult = WorkspacesView.SwipeScrollResult; @@ -123,14 +120,6 @@ Overview.prototype = { this.animationInProgress = false; this._hideInProgress = false; - // XDND - this._dragMonitor = { - dragMotion: Lang.bind(this, this._onDragMotion) - }; - - Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin)); - Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd)); - this._windowSwitchTimeoutId = 0; this._windowSwitchTimestamp = 0; this._lastActiveWorkspaceIndex = -1; @@ -158,26 +147,6 @@ Overview.prototype = { this._cinnamonInfo.setMessage(text, undoCallback, undoLabel); }, - _onDragBegin: function() { - DND.addDragMonitor(this._dragMonitor); - // Remember the workspace we started from - this._lastActiveWorkspaceIndex = global.screen.get_active_workspace_index(); - }, - - _onDragEnd: function(time) { - // In case the drag was canceled while in the overview - // we have to go back to where we started and hide - // the overview - if (this._shownTemporarily) { - global.screen.get_workspace_by_index(this._lastActiveWorkspaceIndex).activate(time); - this.hideTemporarily(); - } - this._resetWindowSwitchTimeout(); - this._lastHoveredWindow = null; - DND.removeDragMonitor(this._dragMonitor); - this.endItemDrag(); - }, - _resetWindowSwitchTimeout: function() { if (this._windowSwitchTimeoutId != 0) { Mainloop.source_remove(this._windowSwitchTimeoutId); @@ -195,36 +164,6 @@ Overview.prototype = { pointer.warp(screen, pointerX, pointerY); }, - _onDragMotion: function(dragEvent) { - let targetIsWindow = dragEvent.targetActor && - dragEvent.targetActor._delegate && - dragEvent.targetActor._delegate.metaWindow; - - this._windowSwitchTimestamp = global.get_current_time(); - - if (targetIsWindow && - dragEvent.targetActor._delegate.metaWindow == this._lastHoveredWindow) - return DND.DragMotionResult.CONTINUE; - - this._lastHoveredWindow = null; - - this._resetWindowSwitchTimeout(); - - if (targetIsWindow) { - this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow; - this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT, - Lang.bind(this, function() { - this._needsFakePointerEvent = true; - Main.activateWindow(dragEvent.targetActor._delegate.metaWindow, - this._windowSwitchTimestamp); - this.hideTemporarily(); - this._lastHoveredWindow = null; - })); - } - - return DND.DragMotionResult.CONTINUE; - }, - setScrollAdjustment: function(adjustment, direction) { if (this.isDummy) return; @@ -395,30 +334,6 @@ Overview.prototype = { //// Public methods //// - beginItemDrag: function(source) { - this.emit('item-drag-begin'); - }, - - cancelledItemDrag: function(source) { - this.emit('item-drag-cancelled'); - }, - - endItemDrag: function(source) { - this.emit('item-drag-end'); - }, - - beginWindowDrag: function(source) { - this.emit('window-drag-begin'); - }, - - cancelledWindowDrag: function(source) { - this.emit('window-drag-cancelled'); - }, - - endWindowDrag: function(source) { - this.emit('window-drag-end'); - }, - // show: // // Animates the overview visible and grabs mouse and keyboard input From 22d6c076319e4dad2169cbe5ceb47baeb776fdba Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 17 Nov 2012 10:33:26 +0100 Subject: [PATCH 63/74] [main.js] Keep internal workspace count in sync with reality. --- js/ui/main.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/ui/main.js b/js/ui/main.js index 6f790ce9e4..c7c23814f8 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -537,8 +537,10 @@ function _queueCheckWorkspaces() { } function _nWorkspacesChanged() { + nWorks = global.screen.n_workspaces; if (!dynamicWorkspaces) return false; + let oldNumWorkspaces = _workspaces.length; let newNumWorkspaces = global.screen.n_workspaces; From 7dbb410cd5f4a05027824417ffbde4d1b912c758 Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 17 Nov 2012 10:34:20 +0100 Subject: [PATCH 64/74] [main.js] Add a function to move a window to a new workspace. --- js/ui/main.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/js/ui/main.js b/js/ui/main.js index c7c23814f8..1004cf0c2b 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -416,6 +416,20 @@ function _removeWorkspace(workspace) { return true; } +function moveWindowToNewWorkspace(metaWindow, switchToNewWorkspace) { + if (switchToNewWorkspace) { + let targetCount = global.screen.n_workspaces + 1; + let nnwId = global.screen.connect('notify::n-workspaces', function() { + global.screen.disconnect(nnwId); + if (global.screen.n_workspaces === targetCount) { + let newWs = global.screen.get_workspace_by_index(global.screen.n_workspaces - 1); + newWs.activate(global.get_current_time()); + } + }); + } + metaWindow.change_workspace_by_index(global.screen.n_workspaces, true, global.get_current_time()); +} + function _staticWorkspaces() { let i; let dif = nWorks - global.screen.n_workspaces; From 848a925b47d5be37fc7a2be259b3f57441caf24d Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 17 Nov 2012 10:35:25 +0100 Subject: [PATCH 65/74] [Scale] Handle changes in workspace count dynamically. --- js/ui/workspace.js | 8 +------- js/ui/workspacesView.js | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 01e1320275..5edf1070fa 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1629,6 +1629,7 @@ Workspace.prototype = { this.currentMonitorIndex = Main.layoutManager.primaryIndex; Main.layoutManager.monitors.forEach(function(monitor, ix) { let m = new WorkspaceMonitor(metaWorkspace, ix, this, ix === this.currentMonitorIndex) + m.setGeometry(monitor.x, monitor.y, monitor.width, monitor.height, 0); this._monitors.push(m); this.actor.add_actor(m.actor); }, this); @@ -1717,13 +1718,6 @@ Workspace.prototype = { this.actor.destroy(); }, - setGeometry: function() { - this._monitors.forEach(function(monitor, index) { - let mon = Main.layoutManager.monitors[index]; - monitor.setGeometry(mon.x, mon.y, mon.width, mon.height, 0); - }, this); - }, - selectAnotherWindow: function(symbol) { this._monitors[this.currentMonitorIndex].selectAnotherWindow(symbol); }, diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 5aad9ab9e4..d1a74d762e 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -95,7 +95,7 @@ WorkspacesView.prototype = { let switchWorkspaceNotifyId = global.window_manager.connect('switch-workspace', Lang.bind(this, this._activeWorkspaceChanged)); - let nWorkspacesChangedId = global.screen.connect('notify::n-workspaces', Main.overview.hide); + let nWorkspacesChangedId = global.screen.connect('notify::n-workspaces', Lang.bind(this, this._workspacesChanged)); this._disconnectHandlers = function() { global.window_manager.disconnect(switchWorkspaceNotifyId); @@ -131,9 +131,6 @@ WorkspacesView.prototype = { this._x = x; this._y = y; this._workspaceRatioSpacing = spacing; - - for (let i = 0; i < this._workspaces.length; i++) - this._workspaces[i].setGeometry(); }, _lookupWorkspaceForMetaWindow: function (metaWindow) { @@ -262,6 +259,28 @@ WorkspacesView.prototype = { this._workspaces[active].zoomToOverview(); }, + _workspacesChanged: function() { + let removedCount = 0; + this._workspaces.slice().forEach(function(workspace, i) { + let metaWorkspace = global.screen.get_workspace_by_index(i-removedCount); + if (workspace.metaWorkspace != metaWorkspace) { + Tweener.removeTweens(workspace.actor); + workspace.destroy(); + this._workspaces.splice(i - removedCount, 1); + ++removedCount; + } + }, this); + + while (global.screen.n_workspaces > this._workspaces.length) { + let lastWs = global.screen.get_workspace_by_index(this._workspaces.length); + let workspace = new Workspace.Workspace(lastWs, this); + this._workspaces.push(workspace) + this.actor.add_actor(workspace.actor); + } + this._animating = false; + this._updateVisibility(); + }, + _activeWorkspaceChanged: function(wm, from, to, direction) { if (this._scrolling) return; From aa5d4e625b82e3d9983d3783e53091302eb8ac53 Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 17 Nov 2012 10:52:37 +0100 Subject: [PATCH 66/74] [Scale] Add a menu option to move a window to a new workspace. --- js/ui/workspace.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 5edf1070fa..e573a785b1 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1495,6 +1495,11 @@ WindowContextMenu.prototype = { this.itemOnAllWorkspaces = new PopupMenu.PopupMenuItem(_("Visible on all workspaces")); this.itemOnAllWorkspaces.connect('activate', Lang.bind(this, this._toggleOnAllWorkspaces)); + let itemMoveToNewWorkspace = new PopupMenu.PopupMenuItem(_("Move to a new workspace")); + itemMoveToNewWorkspace.connect('activate', Lang.bind(this, function() { + Main.moveWindowToNewWorkspace(metaWindow, true); + })); + let monitorItems = []; if (Main.layoutManager.monitors.length > 1) { Main.layoutManager.monitors.forEach(function(monitor, index) { @@ -1511,6 +1516,7 @@ WindowContextMenu.prototype = { } let items = monitorItems.concat([ + itemMoveToNewWorkspace, this.itemOnAllWorkspaces, this.itemMoveToLeftWorkspace, this.itemMoveToRightWorkspace, From 51fb25b5d8cac018dad408467b8c365d180a7082 Mon Sep 17 00:00:00 2001 From: autarkper Date: Sat, 17 Nov 2012 17:13:10 +0100 Subject: [PATCH 67/74] [Scale] Remove some more left-overs. --- js/ui/workspace.js | 22 ---------------------- js/ui/workspacesView.js | 8 -------- 2 files changed, 30 deletions(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index e573a785b1..e519e59122 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -866,10 +866,6 @@ WorkspaceMonitor.prototype = { return -1; }, - containsMetaWindow: function (metaWindow) { - return this._lookupIndex(metaWindow) >= 0; - }, - isEmpty: function() { return this._windows.length === 0; }, @@ -925,22 +921,6 @@ WorkspaceMonitor.prototype = { return [x, y, scale]; }, - setReservedSlot: function(clone) { - if (this._reservedSlot == clone) - return; - - if (clone && this.containsMetaWindow(clone.metaWindow)) { - this._reservedSlot = null; - this.positionWindows(WindowPositionFlags.ANIMATE); - return; - } - if (clone) - this._reservedSlot = clone; - else - this._reservedSlot = null; - this.positionWindows(WindowPositionFlags.ANIMATE); - }, - /** * positionWindows: * @flags: @@ -957,8 +937,6 @@ WorkspaceMonitor.prototype = { closeContextMenu(); let clones = this._windows.slice(); - if (this._reservedSlot) - clones.push(this._reservedSlot); let initialPositioning = flags & WindowPositionFlags.INITIAL; let animate = flags & WindowPositionFlags.ANIMATE; diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index d1a74d762e..74926ceaf8 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -133,14 +133,6 @@ WorkspacesView.prototype = { this._workspaceRatioSpacing = spacing; }, - _lookupWorkspaceForMetaWindow: function (metaWindow) { - for (let i = 0; i < this._workspaces.length; i++) { - if (this._workspaces[i].containsMetaWindow(metaWindow)) - return this._workspaces[i]; - } - return null; - }, - getActiveWorkspace: function() { let active = global.screen.get_active_workspace_index(); return this._workspaces[active]; From aea0d65ef4fe84a7d49d8b223d9785a641b34ec6 Mon Sep 17 00:00:00 2001 From: autarkper Date: Mon, 19 Nov 2012 10:14:35 +0100 Subject: [PATCH 68/74] [Scale] Give the window context menu an ID: 'scale-window-context-menu', for easier theming. --- js/ui/workspace.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index e519e59122..68056110a6 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1443,6 +1443,7 @@ WindowContextMenu.prototype = { _init: function(actor, metaWindow, onClose) { PopupMenu.PopupComboMenu.prototype._init.call(this, actor); + this.name = 'scale-window-context-menu'; Main.uiGroup.add_actor(this.actor); this.actor.hide(); let orientation = St.Side.TOP; From 3eec255c4e2fb808894a92b4d617c2e593702ac9 Mon Sep 17 00:00:00 2001 From: dalcde Date: Wed, 7 Nov 2012 20:40:40 +0800 Subject: [PATCH 69/74] Deprecate Overview.setMessage --- js/ui/overview.js | 110 ++++++++++++++++++++++------------------- js/ui/placesManager.js | 13 +++-- 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index c5c056d7fe..401ff3d864 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -1,5 +1,4 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - const Clutter = imports.gi.Clutter; const Gtk = imports.gi.Gtk; const Meta = imports.gi.Meta; @@ -23,57 +22,6 @@ const SwipeScrollDirection = WorkspacesView.SwipeScrollDirection; const SwipeScrollResult = WorkspacesView.SwipeScrollResult; -function CinnamonInfo() { - this._init(); -} - -CinnamonInfo.prototype = { - _init: function() { - this._source = null; - this._undoCallback = null; - }, - - _onUndoClicked: function() { - if (this._undoCallback) - this._undoCallback(); - this._undoCallback = null; - - if (this._source) - this._source.destroy(); - }, - - setMessage: function(text, undoCallback, undoLabel) { - if (this._source == null) { - this._source = new MessageTray.SystemNotificationSource(); - this._source.connect('destroy', Lang.bind(this, - function() { - this._source = null; - })); - if (Main.messageTray) Main.messageTray.add(this._source); - } - - let notification = null; - if (this._source.notifications.length == 0) { - notification = new MessageTray.Notification(this._source, text, null); - } else { - notification = this._source.notifications[0]; - notification.update(text, null, { clear: true }); - } - - notification.setTransient(true); - - this._undoCallback = undoCallback; - if (undoCallback) { - notification.addButton('system-undo', - undoLabel ? undoLabel : _("Undo")); - notification.connect('action-invoked', - Lang.bind(this, this._onUndoClicked)); - } - - this._source.notify(notification); - } -}; - function Overview() { this._init.apply(this, arguments); } @@ -140,10 +88,12 @@ Overview.prototype = { Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.hide)); }, + // Deprecated setMessage: function(text, undoCallback, undoLabel) { if (this.isDummy) return; + global.log("Overview.setMessage" + _(" is deprecated. Please do not use in newly written code")); this._cinnamonInfo.setMessage(text, undoCallback, undoLabel); }, @@ -619,3 +569,59 @@ Overview.prototype = { } }; Signals.addSignalMethods(Overview.prototype); + + +/******************************************** + * Deprecated code * + ********************************************/ + +function CinnamonInfo() { + this._init(); +} + +CinnamonInfo.prototype = { + _init: function() { + this._source = null; + this._undoCallback = null; + }, + + _onUndoClicked: function() { + if (this._undoCallback) + this._undoCallback(); + this._undoCallback = null; + + if (this._source) + this._source.destroy(); + }, + + setMessage: function(text, undoCallback, undoLabel) { + if (this._source == null) { + this._source = new MessageTray.SystemNotificationSource(); + this._source.connect('destroy', Lang.bind(this, + function() { + this._source = null; + })); + if (Main.messageTray) Main.messageTray.add(this._source); + } + + let notification = null; + if (this._source.notifications.length == 0) { + notification = new MessageTray.Notification(this._source, text, null); + } else { + notification = this._source.notifications[0]; + notification.update(text, null, { clear: true }); + } + + notification.setTransient(true); + + this._undoCallback = undoCallback; + if (undoCallback) { + notification.addButton('system-undo', + undoLabel ? undoLabel : _("Undo")); + notification.connect('action-invoked', + Lang.bind(this, this._onUndoClicked)); + } + + this._source.notify(notification); + } +}; diff --git a/js/ui/placesManager.js b/js/ui/placesManager.js index 3b3cd57e7c..a51b6896cc 100644 --- a/js/ui/placesManager.js +++ b/js/ui/placesManager.js @@ -117,9 +117,16 @@ PlaceDeviceInfo.prototype = { this._mount.unmount_finish(res); } catch (e) { let message = _("Failed to unmount '%s'").format(o.get_name()); - Main.overview.setMessage(message, - Lang.bind(this, this.remove), - _("Retry")); + let source = new MessageTray.SystemNotificationSource(); + if (Main.messageTray) { + Main.messageTray.add(source); + let notification = new MessageTray.Notification(source, message, null); + notification.setTransient(true); + + notification.addButton('system-undo', _("Retry")); + notification.connect('action-invoked', Lang.bind(this, this.remove)); + source.notify(notification); + } } } }; From d97547aa8a0b3e0513518500e973b1ad1cd28890 Mon Sep 17 00:00:00 2001 From: autarkper Date: Tue, 20 Nov 2012 08:42:38 +0100 Subject: [PATCH 70/74] [Scale] Remove last traces of CinnamonInfo. --- js/ui/overview.js | 76 ----------------------------------------------- 1 file changed, 76 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index 401ff3d864..2ea7a3b06e 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -83,20 +83,9 @@ Overview.prototype = { if (this.isDummy) return; - this._cinnamonInfo = new CinnamonInfo(); - Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.hide)); }, - // Deprecated - setMessage: function(text, undoCallback, undoLabel) { - if (this.isDummy) - return; - - global.log("Overview.setMessage" + _(" is deprecated. Please do not use in newly written code")); - this._cinnamonInfo.setMessage(text, undoCallback, undoLabel); - }, - _resetWindowSwitchTimeout: function() { if (this._windowSwitchTimeoutId != 0) { Mainloop.source_remove(this._windowSwitchTimeoutId); @@ -271,17 +260,6 @@ Overview.prototype = { return false; }, - _getDesktopClone: function() { - let windows = global.get_window_actors().filter(function(w) { - return w.meta_window.get_window_type() == Meta.WindowType.DESKTOP; - }); - if (windows.length == 0) - return null; - - let clone = new Clutter.Clone({ source: windows[0].get_texture() }); - return clone; - }, - //// Public methods //// // show: @@ -571,57 +549,3 @@ Overview.prototype = { Signals.addSignalMethods(Overview.prototype); -/******************************************** - * Deprecated code * - ********************************************/ - -function CinnamonInfo() { - this._init(); -} - -CinnamonInfo.prototype = { - _init: function() { - this._source = null; - this._undoCallback = null; - }, - - _onUndoClicked: function() { - if (this._undoCallback) - this._undoCallback(); - this._undoCallback = null; - - if (this._source) - this._source.destroy(); - }, - - setMessage: function(text, undoCallback, undoLabel) { - if (this._source == null) { - this._source = new MessageTray.SystemNotificationSource(); - this._source.connect('destroy', Lang.bind(this, - function() { - this._source = null; - })); - if (Main.messageTray) Main.messageTray.add(this._source); - } - - let notification = null; - if (this._source.notifications.length == 0) { - notification = new MessageTray.Notification(this._source, text, null); - } else { - notification = this._source.notifications[0]; - notification.update(text, null, { clear: true }); - } - - notification.setTransient(true); - - this._undoCallback = undoCallback; - if (undoCallback) { - notification.addButton('system-undo', - undoLabel ? undoLabel : _("Undo")); - notification.connect('action-invoked', - Lang.bind(this, this._onUndoClicked)); - } - - this._source.notify(notification); - } -}; From 92217901b9db65cd34d57bdcec385174320077bd Mon Sep 17 00:00:00 2001 From: autarkper Date: Tue, 20 Nov 2012 08:56:46 +0100 Subject: [PATCH 71/74] [Scale] Fewer window-zoom steps. --- js/ui/workspace.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 68056110a6..ba88e413c6 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -23,7 +23,7 @@ const FOCUS_ANIMATION_TIME = 0.15; const WINDOW_DND_SIZE = 256; -const SCROLL_SCALE_AMOUNT = 100 / 5; +const SCROLL_SCALE_AMOUNT = 50; const LIGHTBOX_FADE_TIME = 0.1; const CLOSE_BUTTON_FADE_TIME = 0.1; From d9132555215e18440a25a3e59252a8ca45a1ead1 Mon Sep 17 00:00:00 2001 From: autarkper Date: Tue, 20 Nov 2012 12:38:57 +0100 Subject: [PATCH 72/74] [Scale] Do away with the desktop-fade effect on entry/exit. --- js/ui/overview.js | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index 2ea7a3b06e..988f3e90f7 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -301,9 +301,6 @@ Overview.prototype = { this._background.add_actor(this._backgroundShade); this._backgroundShade.set_size(global.screen_width, global.screen_height); - this._desktopFade = new St.Bin(); - global.overlay_group.add_actor(this._desktopFade); - this.visible = true; this.animationInProgress = true; @@ -335,19 +332,6 @@ Overview.prototype = { global.overlay_group.add_actor(this.workspacesView.actor); Main.disablePanels(); - if (!this._desktopFade.child) - this._desktopFade.child = this._getDesktopClone(); - - if (!this.workspacesView.getActiveWorkspace().hasMaximizedWindows()) { - this._desktopFade.opacity = 255; - this._desktopFade.show(); - Tweener.addTween(this._desktopFade, - { opacity: 0, - time: ANIMATION_TIME, - transition: 'easeOutQuad' - }); - } - this._group.opacity = 0; Tweener.addTween(this._group, { opacity: 255, @@ -468,15 +452,6 @@ Overview.prototype = { this._hideInProgress = true; Main.enablePanels(); - if (!this.workspacesView.getActiveWorkspace().hasMaximizedWindows()) { - this._desktopFade.opacity = 0; - this._desktopFade.show(); - Tweener.addTween(this._desktopFade, - { opacity: 255, - time: ANIMATION_TIME, - transition: 'easeOutQuad' }); - } - this.workspacesView.hide(); // Make other elements fade out. @@ -495,7 +470,6 @@ Overview.prototype = { _showDone: function() { this.animationInProgress = false; - this._desktopFade.hide(); this._coverPane.hide(); this.emit('shown'); @@ -508,8 +482,6 @@ Overview.prototype = { }, _hideDone: function() { - global.overlay_group.remove_actor(this._desktopFade); - this._desktopFade.destroy(); this._group.remove_actor(this._coverPane); this._coverPane.destroy(); global.overlay_group.remove_actor(this._background); From a2c99a701c10f8bbcae53d0efce36065b48cc342 Mon Sep 17 00:00:00 2001 From: autarkper Date: Tue, 20 Nov 2012 15:46:59 +0100 Subject: [PATCH 73/74] [Scale] Remove isDummy left-overs. --- js/ui/main.js | 2 +- js/ui/overview.js | 35 +---------------------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/js/ui/main.js b/js/ui/main.js index 1004cf0c2b..85ff9a1d03 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -241,7 +241,7 @@ function start() { layoutManager = new Layout.LayoutManager(); xdndHandler = new XdndHandler.XdndHandler(); // This overview object is just a stub for non-user sessions - overview = new Overview.Overview({ isDummy: false }); + overview = new Overview.Overview(); expo = new Expo.Expo({ isDummy: false }); magnifier = new Magnifier.Magnifier(); statusIconDispatcher = new StatusIconDispatcher.StatusIconDispatcher(); diff --git a/js/ui/overview.js b/js/ui/overview.js index 988f3e90f7..e370f7af2b 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -11,7 +11,6 @@ const Gdk = imports.gi.Gdk; const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; -const Params = imports.misc.params; const Tweener = imports.ui.tweener; const WorkspacesView = imports.ui.workspacesView; @@ -27,19 +26,7 @@ function Overview() { } Overview.prototype = { - _init : function(params) { - params = Params.parse(params, { isDummy: false }); - - this.isDummy = params.isDummy; - - // We only have an overview in user sessions, so - // create a dummy overview in other cases - if (this.isDummy) { - this.animationInProgress = false; - this.visible = false; - return; - } - + _init : function() { this._spacing = 0; this._group = new St.Group({ name: 'overview', @@ -80,9 +67,6 @@ Overview.prototype = { // signal handlers and so forth. So we create them after // construction in this init() method. init: function() { - if (this.isDummy) - return; - Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.hide)); }, @@ -104,9 +88,6 @@ Overview.prototype = { }, setScrollAdjustment: function(adjustment, direction) { - if (this.isDummy) - return; - this._scrollAdjustment = adjustment; if (this._scrollAdjustment == null) this._scrollDirection = SwipeScrollDirection.NONE; @@ -266,8 +247,6 @@ Overview.prototype = { // // Animates the overview visible and grabs mouse and keyboard input show : function() { - if (this.isDummy) - return; if (this._shown) return; // Do this manually instead of using _syncInputMode, to handle failure @@ -353,9 +332,6 @@ Overview.prototype = { // will result in the overview not being hidden until hideTemporarily() is // called. showTemporarily: function() { - if (this.isDummy) - return; - if (this._shownTemporarily) return; @@ -368,9 +344,6 @@ Overview.prototype = { // // Reverses the effect of show() hide: function() { - if (this.isDummy) - return; - if (!this._shown) return; @@ -389,9 +362,6 @@ Overview.prototype = { // // Reverses the effect of showTemporarily() hideTemporarily: function() { - if (this.isDummy) - return; - if (!this._shownTemporarily) return; @@ -403,9 +373,6 @@ Overview.prototype = { }, toggle: function() { - if (this.isDummy) - return; - if (this._shown) this.hide(); else From 961dec4f019179b504edcf1cca56832404da70e7 Mon Sep 17 00:00:00 2001 From: autarkper Date: Tue, 20 Nov 2012 16:26:08 +0100 Subject: [PATCH 74/74] [Scale] Remove _fakePointerEvent left-overs. --- js/ui/overview.js | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index e370f7af2b..a425a04951 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -59,7 +59,6 @@ Overview.prototype = { this._windowSwitchTimestamp = 0; this._lastActiveWorkspaceIndex = -1; this._lastHoveredWindow = null; - this._needsFakePointerEvent = false; }, // The members we construct that are implemented in JS might @@ -70,23 +69,6 @@ Overview.prototype = { Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.hide)); }, - _resetWindowSwitchTimeout: function() { - if (this._windowSwitchTimeoutId != 0) { - Mainloop.source_remove(this._windowSwitchTimeoutId); - this._windowSwitchTimeoutId = 0; - this._needsFakePointerEvent = false; - } - }, - - _fakePointerEvent: function() { - let display = Gdk.Display.get_default(); - let deviceManager = display.get_device_manager(); - let pointer = deviceManager.get_client_pointer(); - let [screen, pointerX, pointerY] = pointer.get_position(); - - pointer.warp(screen, pointerX, pointerY); - }, - setScrollAdjustment: function(adjustment, direction) { this._scrollAdjustment = adjustment; if (this._scrollAdjustment == null) @@ -475,13 +457,6 @@ Overview.prototype = { this._animateVisible(); this._syncInputMode(); - - // Fake a pointer event if requested - if (this._needsFakePointerEvent) { - this._fakePointerEvent(); - this._needsFakePointerEvent = false; - } - Main.layoutManager._chrome.updateRegions(); } };