diff --git a/js/ui/overview.js b/js/ui/overview.js index 042e80a0a..72bf82061 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -8,21 +8,14 @@ const Signals = imports.signals; // this is defined here to make it available in imports. var ANIMATION_TIME = 250; -const Background = imports.ui.background; const DND = imports.ui.dnd; const LayoutManager = imports.ui.layout; -const Lightbox = imports.ui.lightbox; const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; const OverviewControls = imports.ui.overviewControls; const Params = imports.misc.params; const WorkspaceThumbnail = imports.ui.workspaceThumbnail; -// Must be less than ANIMATION_TIME, since we switch to -// or from the overview completely after ANIMATION_TIME, -// and don't want the shading animation to get cut off -var SHADE_ANIMATION_TIME = 240; - var DND_WINDOW_SWITCH_TIMEOUT = 750; var OVERVIEW_ACTIVATION_TIMEOUT = 0.5; @@ -177,15 +170,6 @@ var Overview = class { if (this.isDummy) return; - // The main Background actors are inside global.window_group which are - // 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._backgroundGroup = new Meta.BackgroundGroup({ reactive: true }); - Main.layoutManager.overviewGroup.add_child(this._backgroundGroup); - this._bgManagers = []; - this._desktopFade = new St.Widget(); Main.layoutManager.overviewGroup.add_child(this._desktopFade); @@ -228,50 +212,6 @@ var Overview = class { this.init(); } - _updateBackgrounds() { - for (let i = 0; i < this._bgManagers.length; i++) - this._bgManagers[i].destroy(); - - this._bgManagers = []; - - for (let i = 0; i < Main.layoutManager.monitors.length; i++) { - let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup, - monitorIndex: i, - vignette: true }); - this._bgManagers.push(bgManager); - } - } - - _unshadeBackgrounds() { - let backgrounds = this._backgroundGroup.get_children(); - for (let i = 0; i < backgrounds.length; i++) { - backgrounds[i].ease_property('@content.brightness', 1.0, { - duration: SHADE_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - backgrounds[i].ease_property('@content.vignette-sharpness', 0.0, { - duration: SHADE_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - } - - _shadeBackgrounds() { - let backgrounds = this._backgroundGroup.get_children(); - for (let i = 0; i < backgrounds.length; i++) { - backgrounds[i].ease_property('@content.brightness', - Lightbox.VIGNETTE_BRIGHTNESS, { - duration: SHADE_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - backgrounds[i].ease_property('@content.vignette-sharpness', - Lightbox.VIGNETTE_SHARPNESS, { - duration: SHADE_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - } - _sessionUpdated() { const { hasOverview } = Main.sessionMode; if (!hasOverview) @@ -395,13 +335,6 @@ var Overview = class { return Clutter.EVENT_PROPAGATE; } - addAction(action) { - if (this.isDummy) - return; - - this._backgroundGroup.add_action(action); - } - _getDesktopClone() { let windows = global.get_window_actors().filter( w => w.meta_window.get_window_type() === Meta.WindowType.DESKTOP); @@ -425,8 +358,6 @@ var Overview = class { this._coverPane.set_position(0, 0); this._coverPane.set_size(global.screen_width, global.screen_height); - - this._updateBackgrounds(); } _onRestacked() { @@ -588,7 +519,6 @@ var Overview = class { duration: ANIMATION_TIME, onComplete: () => this._showDone(), }); - this._shadeBackgrounds(); Main.layoutManager.overviewGroup.set_child_above_sibling( this._coverPane, null); @@ -652,7 +582,6 @@ var Overview = class { duration: ANIMATION_TIME, onComplete: () => this._hideDone(), }); - this._unshadeBackgrounds(); Main.layoutManager.overviewGroup.set_child_above_sibling( this._coverPane, null); diff --git a/js/ui/workspace.js b/js/ui/workspace.js index de1ce2d31..a87283b33 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1,8 +1,9 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- /* exported Workspace */ -const { Clutter, GLib, GObject, St } = imports.gi; +const { Clutter, GLib, GObject, Meta, St } = imports.gi; +const Background = imports.ui.background; const DND = imports.ui.dnd; const Main = imports.ui.main; const Overview = imports.ui.overview; @@ -406,6 +407,7 @@ var WorkspaceLayout = GObject.registerClass({ this._container = null; this._windows = new Map(); this._sortedWindows = []; + this._background = null; this._lastBox = null; this._windowSlots = []; this._layout = null; @@ -588,6 +590,9 @@ var WorkspaceLayout = GObject.registerClass({ this._windowSlots = this._getWindowSlots(box.copy()); } + if (this._background) + this._background.allocate(box); + const allocationScale = containerBox.get_width() / this._workarea.width; const workspaceBox = new Clutter.ActorBox(); @@ -595,7 +600,7 @@ var WorkspaceLayout = GObject.registerClass({ let childBox = new Clutter.ActorBox(); for (const child of container) { - if (!child.visible) + if (!child.visible || child === this._background) continue; // The fifth element in the slot array is the WindowPreview @@ -747,6 +752,16 @@ var WorkspaceLayout = GObject.registerClass({ this.layout_changed(); } + setBackground(background) { + if (this._background) + this._container.remove_child(this._background); + + this._background = background; + + if (this._background) + this._container.add_child(this._background); + } + syncStacking(stackIndices) { const windows = [...this._windows.keys()]; windows.sort((a, b) => { @@ -756,7 +771,7 @@ var WorkspaceLayout = GObject.registerClass({ return stackIndices[seqA] - stackIndices[seqB]; }); - let lastWindow = null; + let lastWindow = this._background; for (const window of windows) { window.setStackAbove(lastWindow); lastWindow = window; @@ -830,6 +845,42 @@ var WorkspaceLayout = GObject.registerClass({ } }); +var WorkspaceBackground = GObject.registerClass( +class WorkspaceBackground extends St.Widget { + _init(monitorIndex) { + super._init({ + style_class: 'workspace-background', + layout_manager: new Clutter.BinLayout(), + }); + + this._monitorIndex = monitorIndex; + + this._backgroundGroup = new Meta.BackgroundGroup({ + x_expand: true, + y_expand: true, + reactive: false, + layout_manager: new Clutter.BinLayout(), + }); + this.add_child(this._backgroundGroup); + + this._bgManager = new Background.BackgroundManager({ + container: this._backgroundGroup, + monitorIndex: this._monitorIndex, + controlPosition: false, + useContentSize: false, + }); + + this.connect('destroy', this._onDestroy.bind(this)); + } + + _onDestroy() { + if (this._bgManager) { + this._bgManager.destroy(); + this._bgManager = null; + } + } +}); + /** * @metaWorkspace: a #Meta.Workspace, or null */ @@ -839,6 +890,7 @@ class Workspace extends St.Widget { super._init({ style_class: 'window-picker', layout_manager: new WorkspaceLayout(metaWorkspace, monitorIndex), + reactive: true, }); this.metaWorkspace = metaWorkspace; @@ -849,6 +901,22 @@ class Workspace extends St.Widget { if (monitorIndex != Main.layoutManager.primaryIndex) this.add_style_class_name('external-monitor'); + // Background + this._background = new WorkspaceBackground(monitorIndex); + this.layout_manager.setBackground(this._background); + + const clickAction = new Clutter.ClickAction(); + clickAction.connect('clicked', action => { + // Only switch to the workspace when there's no application + // windows open. The problem is that it's too easy to miss + // an app window and get the wrong one focused. + if ((action.get_button() === 1 || action.get_button() === 0) && + this.isEmpty()) + Main.overview.hide(); + }); + this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); + this.add_action(clickAction); + this.connect('style-changed', this._onStyleChanged.bind(this)); this.connect('destroy', this._onDestroy.bind(this)); @@ -1269,7 +1337,7 @@ class Workspace extends St.Widget { this.layout_manager.addWindow(clone, metaWindow); if (this._windows.length == 0) - clone.setStackAbove(null); + clone.setStackAbove(this._background); else clone.setStackAbove(this._windows[this._windows.length - 1]); diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index 9e1dccb0f..ef3e5f68c 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -371,21 +371,6 @@ class WorkspacesDisplay extends St.Widget { workspaceManager.connect('workspaces-reordered', this._workspacesReordered.bind(this)); - let clickAction = new Clutter.ClickAction(); - clickAction.connect('clicked', action => { - // Only switch to the workspace when there's no application - // windows open. The problem is that it's too easy to miss - // an app window and get the wrong one focused. - let event = Clutter.get_current_event(); - let index = this._getMonitorIndexForEvent(event); - if ((action.get_button() == 1 || action.get_button() == 0) && - this._workspacesViews[index].getActiveWorkspace().isEmpty()) - Main.overview.hide(); - }); - Main.overview.addAction(clickAction); - this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); - this._clickAction = clickAction; - this._swipeTracker = new SwipeTracker.SwipeTracker( Main.layoutManager.overviewGroup, Shell.ActionMode.OVERVIEW); this._swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this)); @@ -545,8 +530,6 @@ class WorkspacesDisplay extends St.Widget { } _switchWorkspaceEnd(tracker, duration, endProgress) { - this._clickAction.release(); - let workspaceManager = global.workspace_manager; let newWs = workspaceManager.get_workspace_by_index(endProgress);