1084 lines
44 KiB
JavaScript
1084 lines
44 KiB
JavaScript
|
|
const GLib = imports.gi.GLib;
|
|
const Gio = imports.gi.Gio;
|
|
const Clutter = imports.gi.Clutter;
|
|
const Lang = imports.lang;
|
|
const Meta = imports.gi.Meta;
|
|
const Shell = imports.gi.Shell;
|
|
const Signals = imports.signals;
|
|
const St = imports.gi.St;
|
|
|
|
const Main = imports.ui.main;
|
|
const WorkspacesView = imports.ui.workspacesView;
|
|
const Workspace = imports.ui.workspace;
|
|
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
|
const Overview = imports.ui.overview;
|
|
const IconGrid = imports.ui.iconGrid;
|
|
const PopupMenu = imports.ui.popupMenu;
|
|
const DND = imports.ui.dnd;
|
|
|
|
const Util = imports.misc.util;
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
const Me = ExtensionUtils.getCurrentExtension();
|
|
const Convenience = Me.imports.convenience;
|
|
const MyWorkspaceThumbnail = Me.imports.myWorkspaceThumbnail;
|
|
|
|
const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']);
|
|
const _ = Gettext.gettext;
|
|
|
|
var CAPTION_APP_ICON_ZOOM = 8;
|
|
let TASKBAR_TOOLTIP_SHOW_TIME = 150;
|
|
let TASKBAR_TOOLTIP_HIDE_TIME = 100;
|
|
let TASKBAR_TOOLTIP_HOVER_TIMEOUT = 10;
|
|
|
|
const WindowAppsUpdateAction = {
|
|
ADD: 0,
|
|
REMOVE: 1,
|
|
CLEARALL: 2
|
|
};
|
|
|
|
const CaptionPosition = {
|
|
BOTTOM: 0,
|
|
TOP: 1
|
|
};
|
|
|
|
/* Return the actual position reverseing left and right in rtl */
|
|
function getPosition(settings) {
|
|
let position = settings.get_enum('dock-position');
|
|
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
|
|
if (position == St.Side.LEFT)
|
|
position = St.Side.RIGHT;
|
|
else if (position == St.Side.RIGHT)
|
|
position = St.Side.LEFT;
|
|
}
|
|
return position;
|
|
}
|
|
|
|
var TaskbarIcon = class WorkspacesToDock_TaskbarIcon {
|
|
constructor(app, metaWin, caption) {
|
|
this._caption = caption;
|
|
this._mySettings = caption._mySettings;
|
|
this._app = app;
|
|
this._metaWin = metaWin;
|
|
|
|
if (this._mySettings.get_enum('workspace-caption-position') == CaptionPosition.TOP) {
|
|
this._captionYAlign = Clutter.ActorAlign.START;
|
|
} else {
|
|
this._captionYAlign = Clutter.ActorAlign.END;
|
|
}
|
|
|
|
let iconParams = {setSizeManually: true, showLabel: false};
|
|
iconParams['createIcon'] = (iconSize) => { return app.create_icon_texture(iconSize);};
|
|
|
|
this._icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
|
|
this._icon.add_style_class_name('workspacestodock-caption-windowapps-button-icon');
|
|
this._iconSize = this._mySettings.get_double('workspace-caption-taskbar-icon-size');
|
|
this._icon.setIconSize(this._mySettings.get_double('workspace-caption-taskbar-icon-size'));
|
|
|
|
this.actor = new St.Button({
|
|
style_class:'workspacestodock-caption-windowapps-button',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: this._captionYAlign
|
|
});
|
|
this.actor.set_child(this._icon);
|
|
this.actor._delegate = this;
|
|
|
|
// this._tooltipText = this._app.get_name();
|
|
this._tooltipHoverTimeoutId = 0;
|
|
this._tooltipText = this._metaWin.title;
|
|
this.tooltip = new St.Label({ style_class: 'dash-label workspacestodock-caption-windowapps-button-tooltip'});
|
|
this.tooltip.hide();
|
|
Main.layoutManager.addChrome(this.tooltip);
|
|
Main.layoutManager.uiGroup.set_child_below_sibling(this.tooltip, Main.layoutManager.modalDialogGroup);
|
|
this.tooltip_actor = this.tooltip;
|
|
|
|
// Connect signals
|
|
this.actor.connect('button-release-event', this._onButtonRelease.bind(this));
|
|
this.actor.connect('enter-event', this._onButtonEnter.bind(this));
|
|
this.actor.connect('leave-event', this._onButtonLeave.bind(this));
|
|
this.actor.connect('destroy', this._onDestroy.bind(this));
|
|
|
|
// Make actor draggable
|
|
this._draggable = DND.makeDraggable(this.actor);
|
|
}
|
|
|
|
_onDestroy() {
|
|
this.tooltip.hide();
|
|
this.tooltip.destroy();
|
|
}
|
|
|
|
_onButtonEnter(actor, event) {
|
|
let icon = actor._delegate._icon;
|
|
let zoomSize = this._mySettings.get_double('workspace-caption-taskbar-icon-size') + CAPTION_APP_ICON_ZOOM;
|
|
icon.setIconSize(zoomSize);
|
|
|
|
if (this._mySettings.get_boolean('workspace-caption-taskbar-tooltips')) {
|
|
if (this._tooltipHoverTimeoutId > 0) {
|
|
GLib.source_remove(this._tooltipHoverTimeoutId);
|
|
this._tooltipHoverTimeoutId = 0;
|
|
}
|
|
this._tooltipHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, TASKBAR_TOOLTIP_HOVER_TIMEOUT, this.showTooltip.bind(this));
|
|
}
|
|
}
|
|
|
|
_onButtonLeave(actor, event) {
|
|
let icon = actor._delegate._icon;
|
|
icon.setIconSize(this._mySettings.get_double('workspace-caption-taskbar-icon-size'));
|
|
|
|
this.hideTooltip();
|
|
}
|
|
|
|
_onButtonRelease(actor, event) {
|
|
let mouseButton = event.get_button();
|
|
if (mouseButton == 1) {
|
|
if (this._caption._menu.isOpen) {
|
|
this._caption._menu.close();
|
|
}
|
|
this._caption.activateMetaWindow(this._metaWin);
|
|
}
|
|
if (mouseButton == 2) {
|
|
this._caption.closeMetaWindow(this._metaWin);
|
|
}
|
|
|
|
this.hideTooltip();
|
|
return Clutter.EVENT_PROPAGATE;
|
|
}
|
|
|
|
getDragActor() {
|
|
this.hideTooltip();
|
|
return this._app.create_icon_texture(this._iconSize);
|
|
}
|
|
|
|
// Returns the original actor that should align with the actor
|
|
// we show as the item is being dragged.
|
|
getDragActorSource() {
|
|
this.hideTooltip();
|
|
return this._icon;
|
|
}
|
|
|
|
showTooltip() {
|
|
if (this._tooltipHoverTimeoutId > 0) {
|
|
GLib.source_remove(this._tooltipHoverTimeoutId);
|
|
this._tooltipHoverTimeoutId = 0;
|
|
}
|
|
|
|
if (!this._tooltipText)
|
|
return;
|
|
|
|
this._tooltipText = this._metaWin.title;
|
|
this.tooltip.set_text(this._tooltipText);
|
|
this.tooltip.opacity = 0;
|
|
this.tooltip.show();
|
|
|
|
let [buttonStageX, buttonStageY] = this.actor.get_transformed_position();
|
|
let labelWidth = this.tooltip.get_width();
|
|
let buttonWidth = this.actor.get_width();
|
|
let x = buttonStageX + (buttonWidth / 2) - (labelWidth / 2);
|
|
let labelHeight = this.tooltip.get_height();
|
|
let y = buttonStageY - labelHeight;
|
|
|
|
// Get monitor screen info
|
|
let preferredMonitorIndex = this._mySettings.get_int('preferred-monitor');
|
|
let monitorIndex = (Main.layoutManager.primaryIndex + preferredMonitorIndex) % Main.layoutManager.monitors.length ;
|
|
let monitor = Main.layoutManager.monitors[monitorIndex];
|
|
|
|
// Check that tooltip is not off screen
|
|
// Correct tooltip position if necessary
|
|
let position = getPosition(this._mySettings);
|
|
if (position == St.Side.LEFT) {
|
|
if (x < monitor.x)
|
|
x = monitor.x;
|
|
}
|
|
if (position == St.Side.RIGHT) {
|
|
if ((x + labelWidth) > (monitor.x + monitor.width))
|
|
x = (monitor.x + monitor.width) - labelWidth;
|
|
}
|
|
if (position == St.Side.TOP || position == St.Side.BOTTOM) {
|
|
if (x < monitor.x)
|
|
x = monitor.x;
|
|
|
|
if ((x + labelWidth) > (monitor.x + monitor.width))
|
|
x = (monitor.x + monitor.width) - labelWidth;
|
|
}
|
|
|
|
this.tooltip.set_position(x, y);
|
|
this.tooltip.ease({
|
|
opacity: 255,
|
|
duration: TASKBAR_TOOLTIP_SHOW_TIME,
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD
|
|
});
|
|
}
|
|
|
|
hideTooltip() {
|
|
if (this._tooltipHoverTimeoutId > 0) {
|
|
GLib.source_remove(this._tooltipHoverTimeoutId);
|
|
this._tooltipHoverTimeoutId = 0;
|
|
}
|
|
|
|
this.tooltip.ease({
|
|
opacity: 0,
|
|
duration: TASKBAR_TOOLTIP_HIDE_TIME,
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
onComplete: () => {
|
|
this.tooltip.hide();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
var MenuTaskListItem = class WorkspacesToDock_MenuTaskListItem {
|
|
constructor(app, metaWin, caption) {
|
|
this._metaWin = metaWin;
|
|
this._caption = caption;
|
|
this._mySettings = caption._mySettings;
|
|
|
|
let iconParams = {setSizeManually: true, showLabel: false};
|
|
iconParams['createIcon'] = (iconSize) => { return app.create_icon_texture(iconSize);};
|
|
|
|
this._icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
|
|
this._icon.add_style_class_name('workspacestodock-caption-windowapps-menu-icon');
|
|
this._icon.setIconSize(this._mySettings.get_double('workspace-caption-menu-icon-size'));
|
|
// this._label = new St.Label({ text: app.get_name(), style_class: 'workspacestodock-caption-windowapps-menu-label' });
|
|
this._label = new St.Label({
|
|
text: this._metaWin.title,
|
|
style_class: 'workspacestodock-caption-windowapps-menu-label',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
x_expand: true
|
|
});
|
|
|
|
this._buttonBox = new St.BoxLayout({
|
|
style_class:'workspacestodock-caption-windowapps-menu-button',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
x_expand: true
|
|
});
|
|
this._buttonBox.add_actor(this._icon);
|
|
this._buttonBox.add_actor(this._label);
|
|
|
|
this._closeButton = new St.Button({
|
|
style_class:'workspacestodock-caption-windowapps-menu-close',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: Clutter.ActorAlign.CENTER
|
|
});
|
|
// this._closeButton.add_style_class_name('window-close');
|
|
this._closeIcon = new St.Icon({ icon_name: 'window-close-symbolic', style_class: 'popup-menu-icon' });
|
|
this._closeButton.set_size(this._mySettings.get_double('workspace-caption-menu-icon-size'), this._mySettings.get_double('workspace-caption-menu-icon-size'));
|
|
this._closeButton.set_child(this._closeIcon);
|
|
|
|
this.actor = new St.BoxLayout({
|
|
reactive: true,
|
|
style_class: 'popup-menu-item workspacestodock-caption-windowapps-menu-item'
|
|
});
|
|
this.actor._delegate = this;
|
|
|
|
this._ornament = 0;
|
|
this._ornamentLabel = new St.Label({ style_class: 'popup-menu-ornament' });
|
|
this.actor.add_actor(this._ornamentLabel);
|
|
this.actor.add_actor(this._buttonBox);
|
|
this.actor.add_actor(this._closeButton);
|
|
|
|
// Connect signals
|
|
this._closeButton.connect('button-release-event', this._onCloseButtonRelease.bind(this));
|
|
this.actor.connect('button-release-event', this._onButtonRelease.bind(this));
|
|
this.actor.connect('enter-event', this._onItemEnter.bind(this));
|
|
this.actor.connect('leave-event', this._onItemLeave.bind(this));
|
|
}
|
|
|
|
_onItemEnter(actor, event) {
|
|
this.actor.add_style_pseudo_class('active');
|
|
}
|
|
|
|
_onItemLeave(actor, event) {
|
|
this.actor.remove_style_pseudo_class('active');
|
|
}
|
|
|
|
_onButtonRelease(actor, event) {
|
|
let mouseButton = event.get_button();
|
|
if (mouseButton == 1) {
|
|
this._caption.activateMetaWindow(this._metaWin);
|
|
}
|
|
return Clutter.EVENT_PROPAGATE;
|
|
}
|
|
|
|
_onCloseButtonRelease(actor, event) {
|
|
let mouseButton = event.get_button();
|
|
if (mouseButton == 1) {
|
|
this._caption.closeMetaWindow(this._metaWin);
|
|
}
|
|
return Clutter.EVENT_PROPAGATE;
|
|
}
|
|
};
|
|
|
|
var ThumbnailCaption = class WorkspacesToDock_ThumbnailCaption {
|
|
constructor(thumbnail) {
|
|
this._thumbnail = thumbnail;
|
|
this._settings = new Gio.Settings({ schema: MyWorkspaceThumbnail.MUTTER_SCHEMA });
|
|
this._mySettings = Convenience.getSettings('org.gnome.shell.extensions.workspaces-to-dock');
|
|
this._position = getPosition(this._mySettings);
|
|
this._isHorizontal = (this._position == St.Side.TOP ||
|
|
this._position == St.Side.BOTTOM);
|
|
|
|
if (this._mySettings.get_enum('workspace-caption-position') == CaptionPosition.TOP) {
|
|
this._captionYAlign = Clutter.ActorAlign.START;
|
|
} else {
|
|
this._captionYAlign = Clutter.ActorAlign.END;
|
|
}
|
|
|
|
this.actor = new St.Bin({
|
|
name: 'workspacestodockCaptionContainer',
|
|
reactive: false,
|
|
style_class: 'workspacestodock-workspace-caption-container',
|
|
x_fill: true,
|
|
y_align: this._captionYAlign,
|
|
x_align: Clutter.ActorAlign.START
|
|
});
|
|
|
|
this._wsCaptionBackground = new St.Bin({
|
|
name: 'workspacestodockCaptionBackground',
|
|
reactive: false,
|
|
style_class: 'workspacestodock-workspace-caption-background'
|
|
});
|
|
|
|
if (this._mySettings.get_enum('workspace-caption-position') == CaptionPosition.TOP)
|
|
this._wsCaptionBackground.add_style_class_name('caption-top');
|
|
|
|
this._taskBar = [];
|
|
this._taskBarBox = null;
|
|
this._menuTaskListBox = null;
|
|
this._thumbnailShowId = 0;
|
|
|
|
this._afterWindowAddedId = this._thumbnail.metaWorkspace.connect_after('window-added',
|
|
this._onAfterWindowAdded.bind(this));
|
|
this._afterWindowRemovedId = this._thumbnail.metaWorkspace.connect_after('window-removed',
|
|
this._onAfterWindowRemoved.bind(this));
|
|
|
|
this._switchWorkspaceNotifyId =
|
|
global.window_manager.connect('switch-workspace',
|
|
this.activeWorkspaceChanged.bind(this));
|
|
|
|
this._menuManager = new PopupMenu.PopupMenuManager(this.actor);
|
|
|
|
this._initCaption();
|
|
this._thumbnailShowId = this._thumbnail.connect("show", this._initTaskbar.bind(this));
|
|
}
|
|
|
|
destroy() {
|
|
this.workspaceRemoved();
|
|
if (this._taskBarBox) {
|
|
this._taskBarBox.destroy_all_children();
|
|
this._taskBarBox = null;
|
|
}
|
|
if (this._menu) {
|
|
this._menu.close();
|
|
this._menu.destroy();
|
|
}
|
|
}
|
|
|
|
workspaceRemoved() {
|
|
if (this._afterWindowAddedId > 0) {
|
|
this._thumbnail.metaWorkspace.disconnect(this._afterWindowAddedId);
|
|
this._afterWindowAddedId = 0;
|
|
}
|
|
|
|
if (this._afterWindowRemovedId > 0) {
|
|
this._thumbnail.metaWorkspace.disconnect(this._afterWindowRemovedId);
|
|
this._afterWindowRemovedId = 0;
|
|
}
|
|
|
|
if (this._switchWorkspaceNotifyId > 0) {
|
|
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
|
this._switchWorkspaceNotifyId = 0;
|
|
}
|
|
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
this._taskBar[i].metaWin.disconnect(this._taskBar[i].signalFocusedId);
|
|
}
|
|
this._taskBar = [];
|
|
}
|
|
|
|
// Tests if @actor belongs to this workspace and monitor
|
|
_isMyWindow(actor, isMetaWin) {
|
|
let win;
|
|
if (isMetaWin) {
|
|
win = actor;
|
|
} else {
|
|
win = actor.meta_window;
|
|
}
|
|
return win.located_on_workspace(this._thumbnail.metaWorkspace) &&
|
|
(win.get_monitor() == this._thumbnail.monitorIndex);
|
|
}
|
|
|
|
// Tests if @win should be shown in the Overview
|
|
_isOverviewWindow(window, isMetaWin) {
|
|
let win;
|
|
if (isMetaWin) {
|
|
win = window;
|
|
} else {
|
|
win = window.get_meta_window();
|
|
}
|
|
return !win.skip_taskbar &&
|
|
win.showing_on_its_workspace();
|
|
}
|
|
|
|
// Tests if window app should be shown on this workspace
|
|
_isMinimizedWindow(actor, isMetaWin) {
|
|
let win;
|
|
if (isMetaWin) {
|
|
win = actor;
|
|
} else {
|
|
win = actor.meta_window;
|
|
}
|
|
return (!win.skip_taskbar && win.minimized);
|
|
}
|
|
|
|
// Tests if window app should be shown on this workspace
|
|
_showWindowAppOnThisWorkspace(actor, isMetaWin) {
|
|
let win;
|
|
if (isMetaWin) {
|
|
win = actor;
|
|
} else {
|
|
win = actor.meta_window;
|
|
}
|
|
let workspaceManager = global.workspace_manager;
|
|
let activeWorkspace = workspaceManager.get_active_workspace();
|
|
if (this._settings.get_boolean('workspaces-only-on-primary')) {
|
|
return (this._thumbnail.metaWorkspace == activeWorkspace && !win.skip_taskbar && win.is_on_all_workspaces());
|
|
} else {
|
|
return (win.located_on_workspace(this._thumbnail.metaWorkspace) && !win.skip_taskbar && win.showing_on_its_workspace());
|
|
}
|
|
}
|
|
|
|
_initCaption() {
|
|
if (this._mySettings.get_boolean('workspace-captions')) {
|
|
|
|
this._wsCaption = new St.BoxLayout({
|
|
name: 'workspacestodockCaption',
|
|
reactive: false,
|
|
style_class: 'workspacestodock-workspace-caption',
|
|
pack_start: true
|
|
});
|
|
|
|
let currentItems = this._mySettings.get_strv('workspace-caption-items');
|
|
|
|
for (let i = 0; i < currentItems.length; i++) {
|
|
let elements = currentItems[i].split(':');
|
|
let item = elements[0]
|
|
let expandState = (elements[1] == "true"? true: false);
|
|
|
|
switch (item) {
|
|
case "number":
|
|
this._wsNumber = new St.Label({
|
|
name: 'workspacestodockCaptionNumber',
|
|
text: '',
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
y_align: Clutter.ActorAlign.CENTER
|
|
});
|
|
this._wsNumberBox = new St.BoxLayout({
|
|
name: 'workspacestodockCaptionNumberBox',
|
|
style_class: 'workspacestodock-caption-number',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: this._captionYAlign,
|
|
x_expand: expandState,
|
|
y_expand: expandState
|
|
});
|
|
this._wsNumberBox.add_actor(this._wsNumber);
|
|
this._wsCaption.add_actor(this._wsNumberBox);
|
|
break;
|
|
case "name":
|
|
this._wsName = new St.Label({
|
|
name: 'workspacestodockCaptionName',
|
|
text: '',
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
y_align: Clutter.ActorAlign.CENTER
|
|
});
|
|
this._wsNameBox = new St.BoxLayout({
|
|
name: 'workspacestodockCaptionNameBox',
|
|
style_class: 'workspacestodock-caption-name',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: this._captionYAlign,
|
|
x_expand: expandState
|
|
});
|
|
this._wsNameBox.add_actor(this._wsName);
|
|
this._wsCaption.add_actor(this._wsNameBox);
|
|
break;
|
|
case "windowcount":
|
|
this._wsWindowCount = new St.Label({
|
|
name: 'workspacestodockCaptionWindowCount',
|
|
text: '',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: Clutter.ActorAlign.CENTER
|
|
});
|
|
this._wsWindowCountBox = new St.BoxLayout({
|
|
name: 'workspacestodockCaptionWindowCountBox',
|
|
style_class: 'workspacestodock-caption-windowcount',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: this._captionYAlign,
|
|
x_expand: expandState
|
|
});
|
|
if (this._mySettings.get_boolean('workspace-caption-windowcount-image')) {
|
|
this._wsWindowCountBox.remove_style_class_name("workspacestodock-caption-windowcount");
|
|
this._wsWindowCountBox.add_style_class_name("workspacestodock-caption-windowcount-image");
|
|
}
|
|
this._wsWindowCountBox.add_actor(this._wsWindowCount);
|
|
this._wsCaption.add_actor(this._wsWindowCountBox);
|
|
break;
|
|
case "windowapps":
|
|
this._taskBarBox = new St.BoxLayout({
|
|
name: 'workspacestodockCaptionWindowApps',
|
|
reactive: false,
|
|
style_class: 'workspacestodock-caption-windowapps',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: this._captionYAlign,
|
|
x_expand: expandState,
|
|
y_expand: expandState
|
|
});
|
|
this._wsCaption.add_actor(this._taskBarBox);
|
|
break;
|
|
case "spacer":
|
|
this._wsSpacer = new St.Label({
|
|
name: 'workspacestodockCaptionSpacer',
|
|
text: '',
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
y_align: Clutter.ActorAlign.CENTER,
|
|
x_expand: expandState,
|
|
y_expand: expandState
|
|
});
|
|
this._wsSpacerBox = new St.BoxLayout({
|
|
name: 'workspacestodockCaptionSpacerBox',
|
|
style_class: 'workspacestodock-caption-spacer',
|
|
x_align: Clutter.ActorAlign.START,
|
|
y_align: this._captionYAlign,
|
|
x_expand: expandState,
|
|
y_expand: expandState
|
|
});
|
|
this._wsSpacerBox.add_actor(this._wsSpacer);
|
|
this._wsCaption.add_actor(this._wsSpacerBox);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// Add caption to thumbnail actor
|
|
this.actor.add_actor(this._wsCaption);
|
|
this._thumbnail.add_actor(this._wsCaptionBackground);
|
|
this._thumbnail.add_actor(this.actor);
|
|
|
|
// Make thumbnail background transparent so that it doesn't show through
|
|
// on edges where border-radius is set on caption
|
|
this._thumbnail.set_style("background-color: rgba(0,0,0,0.0)");
|
|
|
|
// Create menu and menuitems
|
|
let side = this._position;
|
|
this._menu = new PopupMenu.PopupMenu(this._wsCaption, 0.5, side);
|
|
|
|
// Set popup menu boxpointer point to center vertically on caption background
|
|
// Otherwise the point lands at the top of the caption background because
|
|
// the caption actually extends up another 18px.
|
|
if (!this._isHorizontal)
|
|
this._menu.setSourceAlignment(.8);
|
|
|
|
this._menu.actor.add_style_class_name('workspacestodock-caption-windowapps-menu');
|
|
this._menu.connect('open-state-changed', (menu, open) => {
|
|
if (open) {
|
|
// Set popup menu flag so that dock knows not to hide
|
|
this._thumbnail._thumbnailsBox.setPopupMenuFlag(true);
|
|
|
|
// Set windowAppsBox icons back to normal (not zoomed)
|
|
if (this._taskBarBox) {
|
|
let children = this._taskBarBox.get_children();
|
|
for (let i=0; i < children.length; i++) {
|
|
children[i]._delegate._icon.setIconSize(this._mySettings.get_double('workspace-caption-taskbar-icon-size'));
|
|
}
|
|
}
|
|
} else {
|
|
// Unset popup menu flag
|
|
this._thumbnail._thumbnailsBox.setPopupMenuFlag(false);
|
|
}
|
|
});
|
|
|
|
let item = new PopupMenu.PopupMenuItem(_("Extension Preferences"));
|
|
item.connect('activate', this._showExtensionPreferences.bind(this));
|
|
this._menu.addMenuItem(item);
|
|
|
|
// Add to chrome and hide
|
|
//Main.layoutManager.addChrome(this._menu.actor);
|
|
Main.uiGroup.add_actor(this._menu.actor);
|
|
this._menu.actor.hide();
|
|
|
|
// Add menu to menu manager
|
|
this._menuManager.addMenu(this._menu);
|
|
}
|
|
|
|
}
|
|
|
|
// function initializes the taskbar icons
|
|
_initTaskbar() {
|
|
if(this._thumbnailShowId > 0){
|
|
this._thumbnail.disconnect(this._thumbnailShowId);
|
|
this._thumbnailShowId = 0;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
// Create initial task icons for app windows on workspace
|
|
let windows = global.get_window_actors();
|
|
for (let i = 0; i < windows.length; i++) {
|
|
let metaWin = windows[i].get_meta_window();
|
|
if (!metaWin)
|
|
continue;
|
|
|
|
let tracker = Shell.WindowTracker.get_default();
|
|
let app = tracker.get_window_app(metaWin);
|
|
if (app) {
|
|
let button = new TaskbarIcon(app, metaWin, this);
|
|
if (metaWin.has_focus()) {
|
|
button.actor.add_style_class_name('workspacestodock-caption-windowapps-button-active');
|
|
}
|
|
|
|
if ((this._isMyWindow(windows[i]) && this._isOverviewWindow(windows[i])) ||
|
|
(this._isMyWindow(windows[i]) && this._isMinimizedWindow(windows[i])) ||
|
|
this._showWindowAppOnThisWorkspace(windows[i])) {
|
|
button.actor.visible = true;
|
|
} else {
|
|
button.actor.visible = false;
|
|
}
|
|
|
|
if (this._taskBarBox) {
|
|
this._taskBarBox.add_actor(button.actor);
|
|
}
|
|
|
|
let winInfo = {};
|
|
winInfo.app = app;
|
|
winInfo.metaWin = metaWin;
|
|
winInfo.signalFocusedId = metaWin.connect('notify::appears-focused', this._onWindowChanged.bind(this, metaWin));
|
|
this._taskBar.push(winInfo);
|
|
}
|
|
}
|
|
|
|
// Update window count
|
|
this._updateWindowCount();
|
|
}
|
|
|
|
// function called when the active workspace is changed
|
|
// windows visible on all workspaces are moved to active workspace
|
|
activeWorkspaceChanged() {
|
|
let windows = global.get_window_actors();
|
|
let workspaceManager = global.workspace_manager;
|
|
let activeWorkspace = workspaceManager.get_active_workspace();
|
|
for (let i = 0; i < windows.length; i++) {
|
|
let metaWin = windows[i].get_meta_window();
|
|
if (!metaWin)
|
|
continue;
|
|
|
|
if ((this._isMyWindow(windows[i]) && this._isOverviewWindow(windows[i])) ||
|
|
(this._isMyWindow(windows[i]) && this._isMinimizedWindow(windows[i])) ||
|
|
this._showWindowAppOnThisWorkspace(windows[i])) {
|
|
|
|
// Show taskbar icon if already present
|
|
let index = -1;
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
if (this._taskBar[i].metaWin == metaWin) {
|
|
index = i;
|
|
if (this._taskBarBox) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(index);
|
|
buttonActor.visible = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (index > -1)
|
|
continue;
|
|
|
|
} else {
|
|
// Hide taskbar icon
|
|
let index = -1;
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
if (this._taskBar[i].metaWin == metaWin) {
|
|
index = i;
|
|
if (this._taskBarBox) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(index);
|
|
buttonActor.visible = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update window count
|
|
this._updateWindowCount();
|
|
}
|
|
|
|
_onAfterWindowAdded(metaWorkspace, metaWin) {
|
|
this._doAfterWindowAdded(metaWin);
|
|
}
|
|
|
|
_doAfterWindowAdded(metaWin) {
|
|
let win = metaWin.get_compositor_private();
|
|
if (!win) {
|
|
// Newly-created windows are added to a workspace before
|
|
// the compositor finds out about them...
|
|
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
|
|
if (this.actor &&
|
|
metaWin.get_compositor_private())
|
|
this._doAfterWindowAdded(metaWin);
|
|
return GLib.SOURCE_REMOVE;
|
|
});
|
|
GLib.Source.set_name_by_id(id, '[gnome-shell] this._doAfterWindowAdded');
|
|
return;
|
|
}
|
|
|
|
this._thumbnail._thumbnailsBox.updateTaskbars(metaWin, WindowAppsUpdateAction.ADD);
|
|
}
|
|
|
|
_onAfterWindowRemoved(metaWorkspace, metaWin) {
|
|
this._thumbnail._thumbnailsBox.updateTaskbars(metaWin, WindowAppsUpdateAction.REMOVE);
|
|
}
|
|
|
|
_onWindowChanged(metaWin) {
|
|
if (!this._taskBarBox)
|
|
return;
|
|
|
|
let index = -1;
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
if (this._taskBar[i].metaWin == metaWin) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (index > -1) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(index);
|
|
if (metaWin.appears_focused) {
|
|
buttonActor.add_style_class_name('workspacestodock-caption-windowapps-button-active');
|
|
} else {
|
|
buttonActor.remove_style_class_name('workspacestodock-caption-windowapps-button-active');
|
|
}
|
|
}
|
|
}
|
|
|
|
// NOTE: The caption popup menu is now called from the thumbnailsbox button release event.
|
|
// This allows us to keep the caption boxlayout non-reactive so that thumbnail window clones
|
|
// are draggable.
|
|
showCaptionMenu() {
|
|
if (this._menu.isOpen) {
|
|
this._menu.close();
|
|
return Clutter.EVENT_STOP;
|
|
}
|
|
|
|
this._menu.removeAll();
|
|
|
|
this._menuTaskListBox = new St.BoxLayout({vertical: true});
|
|
let menuTaskListItemCount = 0;
|
|
if (this._taskBarBox) {
|
|
for (let i=0; i < this._taskBar.length; i++) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(i);
|
|
let metaWin = this._taskBar[i].metaWin;
|
|
let app = this._taskBar[i].app;
|
|
let item = new MenuTaskListItem(app, metaWin, this);
|
|
if (buttonActor.visible) {
|
|
menuTaskListItemCount ++;
|
|
} else {
|
|
item.actor.visible = false;
|
|
}
|
|
this._menuTaskListBox.add_actor(item.actor);
|
|
}
|
|
}
|
|
|
|
let windowAppsListsection = new PopupMenu.PopupMenuSection();
|
|
windowAppsListsection.actor.add_actor(this._menuTaskListBox);
|
|
|
|
let appsArray = this._menuTaskListBox.get_children();
|
|
if (menuTaskListItemCount > 0) {
|
|
this._menu.addMenuItem(windowAppsListsection);
|
|
if (menuTaskListItemCount > 1) {
|
|
let item1 = new PopupMenu.PopupMenuItem(_('Close All Applications'));
|
|
item1.connect('activate', this._closeAllMetaWindows.bind(this));
|
|
this._menu.addMenuItem(item1);
|
|
}
|
|
this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
}
|
|
|
|
let item2 = new PopupMenu.PopupMenuItem(_("Extension Preferences"));
|
|
item2.connect('activate', this._showExtensionPreferences.bind(this));
|
|
this._menu.addMenuItem(item2);
|
|
|
|
this._menu.open();
|
|
return Clutter.EVENT_STOP;
|
|
}
|
|
|
|
activateMetaWindow(metaWin) {
|
|
let workspaceManager = global.workspace_manager;
|
|
let activeWorkspace = workspaceManager.get_active_workspace();
|
|
if (activeWorkspace != this._thumbnail.metaWorkspace) {
|
|
this._thumbnail.activate(global.get_current_time());
|
|
metaWin.activate(global.get_current_time());
|
|
} else {
|
|
if (!metaWin.has_focus()) {
|
|
metaWin.activate(global.get_current_time());
|
|
} else {
|
|
metaWin.minimize();
|
|
}
|
|
}
|
|
}
|
|
|
|
_showExtensionPreferences(menuItem, event) {
|
|
if (typeof ExtensionUtils.openPrefs === 'function') {
|
|
ExtensionUtils.openPrefs();
|
|
} else {
|
|
Util.spawn(["gnome-shell-extension-prefs", Me.metadata.uuid]);
|
|
}
|
|
}
|
|
|
|
closeMetaWindow(metaWin) {
|
|
let metaWindow = metaWin;
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
if (this._taskBar[i].metaWin == metaWindow) {
|
|
// Delete metaWindow
|
|
metaWindow.delete(global.get_current_time());
|
|
}
|
|
}
|
|
}
|
|
|
|
_closeAllMetaWindows(menuItem, event) {
|
|
if (this._taskBarBox) {
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(i);
|
|
if (buttonActor.visible) {
|
|
// Delete metaWindow
|
|
this._taskBar[i].metaWin.delete(global.get_current_time());
|
|
}
|
|
|
|
// NOTE: bug quiting all GIMP windows
|
|
// even tried this _taskBar[i].app.request_quit();
|
|
// Gnome Shell has same issue .. selecting quit from panel app menu only closes current Gimp window
|
|
// Unity has same issue .. https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1123593
|
|
}
|
|
}
|
|
}
|
|
|
|
updateTaskbar(metaWin, action) {
|
|
if (action == WindowAppsUpdateAction.ADD) {
|
|
let index = -1;
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
if (this._taskBar[i].metaWin == metaWin) {
|
|
index = i;
|
|
if (this._taskBarBox) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(index);
|
|
if ((this._isMyWindow(metaWin, true) && this._isOverviewWindow(metaWin, true)) ||
|
|
(this._isMyWindow(metaWin, true) && this._isMinimizedWindow(metaWin, true)) ||
|
|
this._showWindowAppOnThisWorkspace(metaWin, true)) {
|
|
buttonActor.visible = true;
|
|
} else {
|
|
buttonActor.visible = false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (index < 0) {
|
|
let tracker = Shell.WindowTracker.get_default();
|
|
if (!metaWin.skip_taskbar) {
|
|
|
|
let app = tracker.get_window_app(metaWin);
|
|
if (app) {
|
|
let button = new TaskbarIcon(app, metaWin, this);
|
|
if (metaWin.has_focus()) {
|
|
button.actor.add_style_class_name('workspacestodock-caption-windowapps-button-active');
|
|
}
|
|
|
|
if ((this._isMyWindow(metaWin, true) && this._isOverviewWindow(metaWin, true)) ||
|
|
(this._isMyWindow(metaWin, true) && this._isMinimizedWindow(metaWin, true)) ||
|
|
this._showWindowAppOnThisWorkspace(metaWin, true)) {
|
|
button.actor.visible = true;
|
|
} else {
|
|
button.actor.visible = false;
|
|
}
|
|
|
|
if (this._taskBarBox) {
|
|
this._taskBarBox.add_actor(button.actor);
|
|
}
|
|
|
|
let winInfo = {};
|
|
winInfo.app = app;
|
|
winInfo.metaWin = metaWin;
|
|
winInfo.signalFocusedId = metaWin.connect('notify::appears-focused', this._onWindowChanged.bind(this, metaWin));
|
|
this._taskBar.push(winInfo);
|
|
}
|
|
}
|
|
}
|
|
} else if (action == WindowAppsUpdateAction.REMOVE) {
|
|
let index = -1;
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
if (this._taskBar[i].metaWin == metaWin) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (index > -1) {
|
|
// Disconnect window focused signal
|
|
metaWin.disconnect(this._taskBar[index].signalFocusedId);
|
|
|
|
// Remove button from windowApps list and windowAppsBox container
|
|
this._taskBar.splice(index, 1);
|
|
if (this._taskBarBox) {
|
|
let buttonActor = this._taskBarBox.get_child_at_index(index);
|
|
this._taskBarBox.remove_actor(buttonActor);
|
|
buttonActor.destroy();
|
|
}
|
|
|
|
// Remove menuItem
|
|
if (this._menuTaskListBox) {
|
|
let menuItemActor = this._menuTaskListBox.get_child_at_index(index);
|
|
if (menuItemActor) {
|
|
this._menuTaskListBox.remove_actor(menuItemActor);
|
|
menuItemActor.destroy();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update window count
|
|
this._updateWindowCount();
|
|
}
|
|
|
|
_updateWindowCount() {
|
|
if (!this._wsWindowCountBox)
|
|
return;
|
|
|
|
let className = "";
|
|
let winCount = 0;
|
|
let winMax = 4;
|
|
|
|
for (let i = 0; i < this._taskBar.length; i++) {
|
|
let metaWin = this._taskBar[i].metaWin;
|
|
if ((this._isMyWindow(metaWin, true) && this._isOverviewWindow(metaWin, true)) ||
|
|
(this._isMyWindow(metaWin, true) && this._isMinimizedWindow(metaWin, true)) ||
|
|
this._showWindowAppOnThisWorkspace(metaWin, true)) {
|
|
winCount ++;
|
|
}
|
|
}
|
|
|
|
if (!this._mySettings.get_boolean('workspace-caption-windowcount-image')) {
|
|
// clear box images
|
|
for(let i = 1; i <= winMax; i++){
|
|
let className = 'workspacestodock-caption-windowcount-image-'+i;
|
|
this._wsWindowCountBox.remove_style_class_name(className);
|
|
}
|
|
|
|
// Set label text
|
|
if (winCount > 0) {
|
|
this._wsWindowCount.set_text(""+winCount);
|
|
} else {
|
|
this._wsWindowCount.set_text("");
|
|
}
|
|
|
|
} else {
|
|
// clear label text
|
|
this._wsWindowCount.set_text("");
|
|
|
|
// Set background image class
|
|
if (winCount > winMax)
|
|
winCount = winMax;
|
|
|
|
for(let i = 1; i <= winMax; i++){
|
|
let className = 'workspacestodock-caption-windowcount-image-'+i;
|
|
if (i != winCount) {
|
|
this._wsWindowCountBox.remove_style_class_name(className);
|
|
} else {
|
|
this._wsWindowCountBox.add_style_class_name(className);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
updateCaption(i, captionHeight, captionBackgroundHeight) {
|
|
let unscale = 1/this._thumbnail._thumbnailsBox._scale;
|
|
let containerWidth = this._thumbnail._thumbnailsBox._porthole.width * this._thumbnail._thumbnailsBox._scale;
|
|
let containerHeight = this._thumbnail._thumbnailsBox._porthole.height * this._thumbnail._thumbnailsBox._scale;
|
|
|
|
if (!this._wsCaptionBackground)
|
|
return;
|
|
|
|
this._wsCaptionBackground.set_scale(unscale, unscale);
|
|
|
|
// ISSUE: Gnome uses monitor screen to create background actor
|
|
// passingthru67: Reposition background to match workspace desktop porthole
|
|
let px = this._thumbnail._thumbnailsBox._porthole.x - Main.layoutManager.monitors[this._thumbnail.monitorIndex].x;
|
|
let py = this._thumbnail._thumbnailsBox._porthole.y - Main.layoutManager.monitors[this._thumbnail.monitorIndex].y;
|
|
if (this._mySettings.get_enum('workspace-caption-position') == CaptionPosition.TOP) {
|
|
this._wsCaptionBackground.set_position(0, 0);
|
|
this._thumbnail._contents.set_position(-this._thumbnail._thumbnailsBox._porthole.x, -this._thumbnail._thumbnailsBox._porthole.y + (captionBackgroundHeight * unscale));
|
|
} else {
|
|
this._wsCaptionBackground.set_position(0, this._thumbnail._thumbnailsBox._porthole.height);
|
|
this._thumbnail._contents.set_position(-this._thumbnail._thumbnailsBox._porthole.x, -this._thumbnail._thumbnailsBox._porthole.y);
|
|
}
|
|
this._thumbnail._bgManager.backgroundActor.set_clip(px, py, this._thumbnail._thumbnailsBox._porthole.width, this._thumbnail._thumbnailsBox._porthole.height);
|
|
this._wsCaptionBackground.set_size(containerWidth, captionBackgroundHeight);
|
|
|
|
if (!this.actor)
|
|
return;
|
|
|
|
this.actor.set_scale(unscale, unscale);
|
|
this.actor.set_size(containerWidth, containerHeight + captionBackgroundHeight);
|
|
|
|
|
|
if (!this._wsCaption)
|
|
return;
|
|
|
|
this._wsCaption.height = captionHeight; // constrains height to caption height
|
|
|
|
if (this._wsNumber)
|
|
this._wsNumber.set_text(""+(i+1));
|
|
|
|
if (this._wsNumberBox)
|
|
this._wsNumberBox.height = captionBackgroundHeight - 2;
|
|
|
|
if (this._wsName)
|
|
this._wsName.set_text(Meta.prefs_get_workspace_name(i));
|
|
|
|
if (this._wsNameBox)
|
|
this._wsNameBox.height = captionBackgroundHeight - 2;
|
|
|
|
if (this._wsWindowCountBox)
|
|
this._wsWindowCountBox.height = captionBackgroundHeight - 2;
|
|
|
|
if (this._taskBarBox)
|
|
this._taskBarBox.height = captionHeight;
|
|
|
|
|
|
let workspaceManager = global.workspace_manager;
|
|
if (i == workspaceManager.get_active_workspace_index()) {
|
|
if (this._wsCaptionBackground) {
|
|
this._wsCaptionBackground.add_style_class_name('workspacestodock-workspace-caption-background-current');
|
|
if (this._mySettings.get_enum('workspace-caption-position') == CaptionPosition.TOP)
|
|
this._wsCaptionBackground.add_style_class_name('caption-top');
|
|
}
|
|
if (this._wsCaption) this._wsCaption.add_style_class_name('workspacestodock-workspace-caption-current');
|
|
if (this._wsNumberBox) this._wsNumberBox.add_style_class_name('workspacestodock-caption-number-current');
|
|
if (this._wsNameBox) this._wsNameBox.add_style_class_name('workspacestodock-caption-name-current');
|
|
if (this._wsWindowCountBox) {
|
|
if (this._mySettings.get_boolean('workspace-caption-windowcount-image')) {
|
|
this._wsWindowCountBox.add_style_class_name('workspacestodock-caption-windowcount-image-current');
|
|
} else {
|
|
this._wsWindowCountBox.add_style_class_name('workspacestodock-caption-windowcount-current');
|
|
}
|
|
}
|
|
if (this._wsSpacerBox) this._wsSpacerBox.add_style_class_name('workspacestodock-caption-spacer-current');
|
|
} else {
|
|
if (this._wsCaptionBackground) this._wsCaptionBackground.remove_style_class_name('workspacestodock-workspace-caption-background-current');
|
|
if (this._wsCaption) this._wsCaption.remove_style_class_name('workspacestodock-workspace-caption-current');
|
|
if (this._wsNumberBox) this._wsNumberBox.remove_style_class_name('workspacestodock-caption-number-current');
|
|
if (this._wsNameBox) this._wsNameBox.remove_style_class_name('workspacestodock-caption-name-current');
|
|
if (this._wsWindowCountBox) {
|
|
if (this._mySettings.get_boolean('workspace-caption-windowcount-image')) {
|
|
this._wsWindowCountBox.remove_style_class_name('workspacestodock-caption-windowcount-image-current');
|
|
} else {
|
|
this._wsWindowCountBox.remove_style_class_name('workspacestodock-caption-windowcount-current');
|
|
}
|
|
}
|
|
if (this._wsSpacerBox) this._wsSpacerBox.remove_style_class_name('workspacestodock-caption-spacer-current');
|
|
}
|
|
}
|
|
};
|