Use single preview container per taskbar

This commit is contained in:
Charles Gagnon
2019-05-12 23:03:48 -04:00
parent 018af512ba
commit 228bd3bed4
3 changed files with 108 additions and 109 deletions

View File

@@ -47,7 +47,6 @@ const Workspace = imports.ui.workspace;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Utils = Me.imports.utils;
const WindowPreview = Me.imports.windowPreview;
const Taskbar = Me.imports.taskbar;
const _ = imports.gettext.domain(Utils.TRANSLATION_DOMAIN).gettext;
@@ -99,7 +98,7 @@ var taskbarAppIcon = Utils.defineClass({
Extends: AppDisplay.AppIcon,
ParentConstrParams: [[1, 'app'], [3]],
_init: function(settings, appInfo, panelWrapper, iconParams) {
_init: function(settings, appInfo, panelWrapper, iconParams, previewMenu) {
// a prefix is required to avoid conflicting with the parent class variable
this._dtpSettings = settings;
@@ -107,6 +106,7 @@ var taskbarAppIcon = Utils.defineClass({
this._nWindows = 0;
this.window = appInfo.window;
this.isLauncher = appInfo.isLauncher;
this._previewMenu = previewMenu;
// Fix touchscreen issues before the listener is added by the parent constructor.
this._onTouchEvent = function(actor, event) {
@@ -202,6 +202,8 @@ var taskbarAppIcon = Utils.defineClass({
this._switchWorkspaceId = global.window_manager.connect('switch-workspace',
Lang.bind(this, this._onSwitchWorkspace));
this._hoverChangeId = this.actor.connect('notify::hover', () => this._onAppIconHoverChanged());
this._dtpSettingsSignalIds = [
this._dtpSettings.connect('changed::dot-position', Lang.bind(this, this._settingsChangeRefresh)),
@@ -234,23 +236,6 @@ var taskbarAppIcon = Utils.defineClass({
this.forcedOverview = false;
this._numberOverlay();
this._signalsHandler = new Utils.GlobalSignalsHandler();
},
enableWindowPreview: function() {
if (!this.windowPreview) {
this.windowPreview = new WindowPreview.PreviewMenu(this);
this.windowPreview.enable();
this._updateWindows();
}
},
disableWindowPreview: function() {
if (this.windowPreview) {
this.windowPreview.disable();
this.windowPreview = null;
}
},
shouldShowTooltip: function() {
@@ -261,7 +246,20 @@ var taskbarAppIcon = Utils.defineClass({
} else {
return this.actor.hover && !this.window &&
(!this._menu || !this._menu.isOpen) &&
(!this.windowPreview || !this.windowPreview.isOpen);
(this._previewMenu.getCurrentAppIcon() !== this);
}
},
_onAppIconHoverChanged: function() {
if (!this._dtpSettings.get_boolean('show-window-previews') ||
(!this.window && !this._nWindows)) {
return;
}
if (this.actor.hover) {
this._previewMenu.requestOpen(this);
} else {
this._previewMenu.requestClose();
}
},
@@ -292,6 +290,10 @@ var taskbarAppIcon = Utils.defineClass({
if(this._scaleFactorChangedId)
St.ThemeContext.get_for_stage(global.stage).disconnect(this._scaleFactorChangedId);
if (this._hoverChangeId) {
this.actor.disconnect(this._hoverChangeId);
}
for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) {
this._dtpSettings.disconnect(this._dtpSettingsSignalIds[i]);
}
@@ -516,8 +518,7 @@ var taskbarAppIcon = Utils.defineClass({
this.emit('menu-state-changed', true);
if (this.windowPreview)
this.windowPreview.close();
this._previewMenu.close(true);
this.actor.set_hover(true);
this._menu.actor.add_style_class_name('dashtopanelSecondaryMenu');
@@ -702,8 +703,8 @@ var taskbarAppIcon = Utils.defineClass({
}
let appCount = this.getAppIconInterestingWindows().length;
if (this.windowPreview && (!(buttonAction == "TOGGLE-SHOWPREVIEW") || (appCount <= 1)))
this.windowPreview.close();
if (!(buttonAction == "TOGGLE-SHOWPREVIEW") || (appCount <= 1))
this._previewMenu.close(true);
// We check if the app is running, and that the # of windows is > 0 in
// case we use workspace isolation,
@@ -863,9 +864,7 @@ var taskbarAppIcon = Utils.defineClass({
this.actor.add_style_class_name(className);
}
if (this.windowPreview) {
this.windowPreview.updateWindows(windows);
}
this._previewMenu.updateWindows(this, windows);
},
_getRunningIndicatorCount: function() {
@@ -1083,7 +1082,7 @@ var taskbarAppIcon = Utils.defineClass({
handleDragOver: function(source, actor, x, y, time) {
if (source == Main.xdndHandler) {
this.windowPreview.close();
this._previewMenu.close(true);
}
return DND.DragMotionResult.CONTINUE;

View File

@@ -238,6 +238,9 @@ var taskbar = Utils.defineClass({
coordinate: Clutter.BindCoordinate.HEIGHT
}));
this.previewMenu = new WindowPreview.PreviewMenu(settings, panelWrapper);
this.previewMenu.enable();
if (!this._dtpSettings.get_boolean('show-show-apps-button'))
this.hideShowAppsButton();
@@ -325,11 +328,6 @@ var taskbar = Utils.defineClass({
'notify::checked',
Lang.bind(this, this._syncShowAppsButtonToggled)
],
[
this._dtpSettings,
'changed::show-window-previews',
Lang.bind(this, this._toggleWindowPreview)
],
[
this._dtpSettings,
'changed::show-show-apps-button',
@@ -379,6 +377,7 @@ var taskbar = Utils.defineClass({
this._showAppsIconWrapper.destroy();
this._container.destroy();
this.previewMenu.disable();
this._disconnectWorkspaceSignals();
},
@@ -552,7 +551,8 @@ var taskbar = Utils.defineClass({
setSizeManually: true,
showLabel: false,
isDraggable: !this._dtpSettings.get_boolean('taskbar-locked'),
}
},
this.previewMenu
);
if (appIcon._draggable) {
@@ -622,27 +622,12 @@ var taskbar = Utils.defineClass({
return item;
},
_toggleWindowPreview: function() {
if (this._dtpSettings.get_boolean('show-window-previews'))
this._enableWindowPreview();
else
this._disableWindowPreview();
},
_enableWindowPreview: function() {
let appIcons = this._getAppIcons();
appIcons.filter(appIcon => !appIcon.isLauncher)
.forEach(function (appIcon) {
appIcon.enableWindowPreview();
});
this.previewMenu.enable();
},
_disableWindowPreview: function() {
let appIcons = this._getAppIcons();
appIcons.forEach(function (appIcon) {
appIcon.disableWindowPreview();
});
this.previewMenu.disable();
},
// Return an array with the "proper" appIcons currently in the taskbar
@@ -871,9 +856,6 @@ var taskbar = Utils.defineClass({
this._updateNumberOverlay();
}
// Connect windows previews to hover events
this._toggleWindowPreview();
this._shownInitially = true;
},

View File

@@ -26,6 +26,7 @@ const Taskbar = Me.imports.taskbar;
const Utils = Me.imports.utils;
const TRANSLATION_OFFSET = 50;
const MONITOR_PADDING = 10;
//timeout intervals
@@ -37,14 +38,16 @@ var PreviewMenu = Utils.defineClass({
Name: 'DashToPanel.PreviewMenu',
Extends: St.Widget,
_init: function(appIcon) {
_init: function(dtpSettings, panelWrapper) {
this.callParent('_init', { name: 'preview-menu', reactive: true });
this.isOpen = false;
this._dtpSettings = dtpSettings;
this._panelWrapper = panelWrapper;
this._appIcon = appIcon;
this._app = appIcon.app;
this._dtpSettings = appIcon._dtpSettings;
this._currentAppIcon = null;
this._position = Taskbar.getPosition();
this._translationProp = 'translation_' + (this._position == St.Side.LEFT || this._position == St.Side.RIGHT ? 'x' : 'y');
this[this._translationProp] = TRANSLATION_OFFSET;
@@ -65,47 +68,63 @@ var PreviewMenu = Utils.defineClass({
this.visible = false;
this.opacity = 0;
Main.uiGroup.insert_child_below(this, this._appIcon.panelWrapper.panelBox);
Main.uiGroup.insert_child_below(this, this._panelWrapper.panelBox);
this._signalsHandler.add(
[
this._appIcon.actor,
'notify::hover',
() => this._onAppIconHoverChanged()
],
);
// this._signalsHandler.add(
// [
// ],
// );
},
disable: function() {
this._signalsHandler.destroy();
this._timeoutsHandler.destroy();
this.close();
this.close(true);
Main.uiGroup.remove_child(this);
},
open: function() {
if (!this.isOpen) {
this.isOpen = true;
requestOpen: function(appIcon) {
this._endOpenCloseTimeouts();
this._updatePosition();
this.show();
this._animateOpenOrClose(true);
if (this._currentAppIcon) {
return this.open(appIcon);
}
this._timeoutsHandler.add([T1, this._dtpSettings.get_int('show-window-previews-timeout'), () => this.open(appIcon)]);
},
close: function() {
if (this.isOpen) {
this.isOpen = false;
requestClose: function() {
this._endOpenCloseTimeouts();
this._timeoutsHandler.add([T2, this._dtpSettings.get_int('leave-timeout'), () => this.close()]);
},
this._animateOpenOrClose(false, () => {
open: function(appIcon) {
this._currentAppIcon = appIcon;
this._updatePosition();
this.show();
this._animateOpenOrClose(true);
},
close: function(immediate) {
this._currentAppIcon = null;
if (this.visible) {
this._animateOpenOrClose(false, immediate, () => {
this.hide();
});
}
},
updateWindows: function(windows) {
updateWindows: function(appIcon, windows) {
if (this._currentAppIcon == appIcon) {
}
},
getCurrentAppIcon: function() {
return this._currentAppIcon;
},
vfunc_allocate: function(box, flags) {
@@ -120,63 +139,62 @@ var PreviewMenu = Utils.defineClass({
return [0, 200];
},
_onAppIconHoverChanged: function() {
if (this._appIcon.actor.hover) {
this._timeoutsHandler.remove(T2);
this._timeoutsHandler.add([T1, this._dtpSettings.get_int('show-window-previews-timeout'), () => this.open()]);
} else {
this._timeoutsHandler.remove(T1);
this._timeoutsHandler.add([T2, this._dtpSettings.get_int('leave-timeout'), () => this.close()]);
}
_endOpenCloseTimeouts: function() {
this._timeoutsHandler.remove(T1);
this._timeoutsHandler.remove(T2);
},
_updatePosition: function() {
let sourceNode = this._appIcon.actor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(this._appIcon.actor.get_allocation_box());
let sourceAllocation = Shell.util_get_transformed_allocation(this._appIcon.actor);
let sourceNode = this._currentAppIcon.actor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(this._currentAppIcon.actor.get_allocation_box());
let sourceAllocation = Shell.util_get_transformed_allocation(this._currentAppIcon.actor);
let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
let position = Taskbar.getPosition();
let isLeftOrRight = position == St.Side.LEFT || position == St.Side.RIGHT;
let x, y;
if (position == St.Side.TOP || position == St.Side.BOTTOM) {
if (this._position == St.Side.TOP || this._position == St.Side.BOTTOM) {
x = sourceAllocation.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * .5 - natWidth * .5;
} else if (position == St.Side.LEFT) {
} else if (this._position == St.Side.LEFT) {
x = sourceAllocation.x2;
} else { //St.Side.RIGHT
x = sourceAllocation.x1 - natWidth;
}
if (isLeftOrRight) {
if (this._position == St.Side.LEFT || this._position == St.Side.RIGHT) {
y = sourceAllocation.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * .5 - natHeight * .5;
} else if (position == St.Side.TOP) {
} else if (this._position == St.Side.TOP) {
y = sourceAllocation.y2;
} else { //St.Side.BOTTOM
y = sourceAllocation.y1 - natHeight;
}
x = Math.max(x, this._appIcon.panelWrapper.monitor.x);
y = Math.max(y, this._appIcon.panelWrapper.monitor.y);
x = Math.max(x, this._panelWrapper.monitor.x + MONITOR_PADDING);
y = Math.max(y, this._panelWrapper.monitor.y + MONITOR_PADDING);
this.set_position(x, y);
this._translationProp = 'translation_' + (isLeftOrRight ? 'x' : 'y');
this[this._translationProp] = TRANSLATION_OFFSET;
if (this[this._translationProp] > 0) {
this.set_position(x, y);
this[this._translationProp] = TRANSLATION_OFFSET;
} else {
Tweener.addTween(this, {
x: x, y: y,
time: Taskbar.DASH_ANIMATION_TIME,
transition: 'easeInOutQuad'
});
}
},
_animateOpenOrClose: function(show, onComplete) {
Tweener.removeTweens(this);
_animateOpenOrClose: function(show, immediate, onComplete) {
let tweenOpts = {
opacity: show ? 255 : 0,
time: Taskbar.DASH_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: () => {
(onComplete || (() => {}))();
}
time: immediate ? 0 : Taskbar.DASH_ANIMATION_TIME,
transition: show ? 'easeInOutQuad' : 'easeInCubic'
};
tweenOpts[this._translationProp] = show ? 0 : TRANSLATION_OFFSET;
if (onComplete) {
tweenOpts.onComplete = onComplete;
}
Tweener.addTween(this, tweenOpts);
},
});