diff --git a/appIcons.js b/appIcons.js index c10fc24..f17f40c 100644 --- a/appIcons.js +++ b/appIcons.js @@ -145,7 +145,21 @@ const taskbarAppIcon = new Lang.Class({ this._dtpSettings.connect('changed::focus-highlight', Lang.bind(this, this._settingsChangeRefresh)); this._dtpSettings.connect('changed::appicon-margin', Lang.bind(this, this._setIconStyle)); - + + this.windowPreview = null; + + this.forcedOverview = false; + + this._numberOverlay(); + + this._signalsHandler = new Convenience.GlobalSignalsHandler(); + }, + + _createWindowPreview: function() { + // Abort if already activated + if (this.menuManagerWindowPreview) + return; + // Creating a new menu manager for window previews as adding it to the // using the secondary menu's menu manager (which uses the "ignoreRelease" // function) caused the extension to crash. @@ -177,10 +191,50 @@ const taskbarAppIcon = new Lang.Class({ this._grabHelper.ungrab({ actor: menu.actor }); } })); + }, - this.forcedOverview = false; + enableWindowPreview: function(appIcons) { + this._createWindowPreview(); - this._numberOverlay(); + // We first remove to ensure there are no duplicates + this._signalsHandler.removeWithLabel('window-preview'); + this._signalsHandler.addWithLabel('window-preview', [ + this.windowPreview, + 'menu-closed', + function(menu) { + // enter-event doesn't fire on an app icon when the popup menu from a previously + // hovered app icon is still open, so when a preview menu closes we need to + // see if a new app icon is hovered and open its preview menu now. + // also, for some reason actor doesn't report being hovered by get_hover() + // if the hover started when a popup was opened. So, look for the actor by mouse position. + let [x, y,] = global.get_pointer(); + let hoveredActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); + let appIconToOpen; + appIcons.forEach(function (appIcon) { + if(appIcon.actor == hoveredActor) { + appIconToOpen = appIcon; + } else if(appIcon.windowPreview && appIcon.windowPreview.isOpen) { + appIcon.windowPreview.close(); + } + }); + + if(appIconToOpen) { + appIconToOpen.actor.sync_hover(); + if(appIconToOpen.windowPreview && appIconToOpen.windowPreview != menu) + appIconToOpen.windowPreview._onEnter(); + } + return GLib.SOURCE_REMOVE; + + } + ]); + + this.windowPreview.enableWindowPreview(); + }, + + disableWindowPreview: function() { + this._signalsHandler.removeWithLabel('window-preview'); + if (this.windowPreview) + this.windowPreview.disableWindowPreview(); }, shouldShowTooltip: function() { @@ -331,7 +385,8 @@ const taskbarAppIcon = new Lang.Class({ this.emit('menu-state-changed', true); - this.windowPreview.close(); + if (this.windowPreview) + this.windowPreview.close(); this.actor.set_hover(true); this._menu.actor.add_style_class_name('dashtopanelSecondaryMenu'); @@ -451,7 +506,8 @@ const taskbarAppIcon = new Lang.Class({ }, activate: function(button) { - this.windowPreview.requestCloseMenu(); + if (this.windowPreview) + this.windowPreview.requestCloseMenu(); let event = Clutter.get_current_event(); let modifiers = event ? event.get_state() : 0; diff --git a/taskbar.js b/taskbar.js index 8d5bd92..593b79f 100644 --- a/taskbar.js +++ b/taskbar.js @@ -288,6 +288,11 @@ const taskbar = new Lang.Class({ Main.overview.viewSelector._showAppsButton, 'notify::checked', Lang.bind(this, this._syncShowAppsButtonToggled) + ], + [ + this._dtpSettings, + 'changed::show-window-previews', + Lang.bind(this, this._toggleWindowPreview) ] ); @@ -474,33 +479,6 @@ const taskbar = new Lang.Class({ } })); - appIcon.windowPreview.connect('menu-closed', Lang.bind(this, function(menu) { - let appIcons = this._getAppIcons(); - // enter-event doesn't fire on an app icon when the popup menu from a previously - // hovered app icon is still open, so when a preview menu closes we need to - // see if a new app icon is hovered and open its preview menu now. - // also, for some reason actor doesn't report being hovered by get_hover() - // if the hover started when a popup was opened. So, look for the actor by mouse position. - let [x, y,] = global.get_pointer(); - let hoveredActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); - let appIconToOpen; - appIcons.forEach(function (appIcon) { - if(appIcon.actor == hoveredActor) { - appIconToOpen = appIcon; - } else if(appIcon.windowPreview && appIcon.windowPreview.isOpen) { - appIcon.windowPreview.close(); - } - }); - - if(appIconToOpen) { - appIconToOpen.actor.sync_hover(); - if(appIconToOpen.windowPreview && appIconToOpen.windowPreview != menu) - appIconToOpen.windowPreview._onEnter(); - } - return GLib.SOURCE_REMOVE; - - })); - appIcon.actor.connect('clicked', Lang.bind(this, function(actor) { ensureActorVisibleInScrollView(this._scrollView, actor); @@ -528,6 +506,27 @@ const taskbar = new Lang.Class({ return item; }, + _toggleWindowPreview: function() { + if (this._dtpSettings.get_boolean('show-window-previews')) + this._enableWindowPreview(); + else + this._disableWindowPreview(); + }, + + _enableWindowPreview: function() { + let appIcons = this._getAppIcons(); + appIcons.forEach(function (appIcon) { + appIcon.enableWindowPreview(appIcons); + }); + }, + + _disableWindowPreview: function() { + let appIcons = this._getAppIcons(); + appIcons.forEach(function (appIcon) { + appIcon.disableWindowPreview(); + }); + }, + // Return an array with the "proper" appIcons currently in the taskbar _getAppIcons: function() { // Only consider children which are "proper" @@ -829,6 +828,9 @@ const taskbar = new Lang.Class({ // This will update the size, and the corresponding number for each icon this._updateNumberOverlay(); + + // Connect windows previews to hover events + this._toggleWindowPreview(); }, // Reset the displayed apps icon to mantain the correct order diff --git a/windowPreview.js b/windowPreview.js index b748381..eb76cf3 100644 --- a/windowPreview.js +++ b/windowPreview.js @@ -74,12 +74,6 @@ const thumbnailPreviewMenu = new Lang.Class({ Main.uiGroup.add_actor(this.actor); - this._enterSourceId = this._source.actor.connect('enter-event', Lang.bind(this, this._onEnter)); - this._leaveSourceId = this._source.actor.connect('leave-event', Lang.bind(this, this._onLeave)); - - this._enterMenuId = this.actor.connect('enter-event', Lang.bind(this, this._onMenuEnter)); - this._leaveMenuId = this.actor.connect('leave-event', Lang.bind(this, this._onMenuLeave)); - // Change the initialized side where required. this._arrowSide = side; this._boxPointer._arrowSide = side; @@ -101,6 +95,35 @@ const thumbnailPreviewMenu = new Lang.Class({ this._peekModeCurrentWorkspace = null; }, + enableWindowPreview: function() { + // Show window previews on mouse hover + this._enterSourceId = this._source.actor.connect('enter-event', Lang.bind(this, this._onEnter)); + this._leaveSourceId = this._source.actor.connect('leave-event', Lang.bind(this, this._onLeave)); + + this._enterMenuId = this.actor.connect('enter-event', Lang.bind(this, this._onMenuEnter)); + this._leaveMenuId = this.actor.connect('leave-event', Lang.bind(this, this._onMenuLeave)); + }, + + disableWindowPreview: function() { + if (this._enterSourceId) { + this._source.actor.disconnect(this._enterSourceId); + this._enterSourceId = 0; + } + if (this._leaveSourceId) { + this._source.actor.disconnect(this._leaveSourceId); + this._leaveSourceId = 0; + } + + if (this._enterMenuId) { + this.actor.disconnect(this._enterMenuId); + this._enterMenuId = 0; + } + if (this._leaveMenuId) { + this.actor.disconnect(this._leaveMenuId); + this._leaveMenuId = 0; + } + }, + requestCloseMenu: function() { // The "~0" argument makes the animation display. this.close(~0);