summaryrefslogtreecommitdiffstats
path: root/extensions/vertical-workspaces/lib/windowPreview.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--extensions/vertical-workspaces/lib/windowPreview.js (renamed from extensions/vertical-workspaces/windowPreview.js)220
1 files changed, 132 insertions, 88 deletions
diff --git a/extensions/vertical-workspaces/windowPreview.js b/extensions/vertical-workspaces/lib/windowPreview.js
index 013f48c..5d2bd61 100644
--- a/extensions/vertical-workspaces/windowPreview.js
+++ b/extensions/vertical-workspaces/lib/windowPreview.js
@@ -1,7 +1,7 @@
/**
- * Vertical Workspaces
+ * V-Shell (Vertical Workspaces)
* windowPreview.js
- *
+ *
* @author GdH <G-dH@github.com>
* @copyright 2022 - 2023
* @license GPL-3.0
@@ -10,7 +10,7 @@
'use strict';
-const { Clutter, GLib, Graphene, Meta, Shell, St } = imports.gi;
+const { Clutter, GLib, GObject, Graphene, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const WindowPreview = imports.ui.windowPreview;
@@ -18,40 +18,54 @@ const WindowPreview = imports.ui.windowPreview;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
-const _Util = Me.imports.util;
+const _Util = Me.imports.lib.util;
+const shellVersion = _Util.shellVersion;
+
let _overrides;
const WINDOW_SCALE_TIME = imports.ui.windowPreview.WINDOW_SCALE_TIME;
const WINDOW_ACTIVE_SIZE_INC = imports.ui.windowPreview.WINDOW_ACTIVE_SIZE_INC;
const WINDOW_OVERLAY_FADE_TIME = imports.ui.windowPreview.WINDOW_OVERLAY_FADE_TIME;
-const SEARCH_WINDOWS_PREFIX = Me.imports.windowSearchProvider.prefix;
+const SEARCH_WINDOWS_PREFIX = Me.imports.lib.windowSearchProvider.prefix;
const ControlsState = imports.ui.overviewControls.ControlsState;
-var opt = null;
+let opt;
+let _firstRun = true;
function update(reset = false) {
- if (_overrides) {
+ opt = Me.imports.lib.settings.opt;
+ const moduleEnabled = opt.get('windowPreviewModule', true);
+ reset = reset || !moduleEnabled;
+
+ // don't even touch this module if disabled
+ if (_firstRun && reset)
+ return;
+
+ _firstRun = false;
+
+ if (_overrides)
_overrides.removeAll();
- }
+
if (reset) {
_overrides = null;
opt = null;
+ WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
return;
}
- opt = Me.imports.settings.opt;
_overrides = new _Util.Overrides();
_overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon);
- // move titles into window previews
- _overrides.addInjection('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewInjections);
+ // A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer
+ if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
+ WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
}
-//----- WindowPreview ------------------------------------------------------------------
-var WindowPreviewInjections = {
- _init: function() {
+const WindowPreviewCommon = {
+ // injection to _init()
+ after__init() {
const ICON_OVERLAP = 0.7;
if (opt.WIN_PREVIEW_ICON_SIZE < 64) {
@@ -91,7 +105,7 @@ var WindowPreviewInjections = {
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
const iconOverlap = opt.WIN_PREVIEW_ICON_SIZE * ICON_OVERLAP;
// we cannot get proper title height before it gets to the stage, so 35 is estimated height + spacing
- this._title.get_constraints()[1].offset = scaleFactor * (- iconOverlap - 35);
+ this._title.get_constraints()[1].offset = scaleFactor * (-iconOverlap - 35);
this.set_child_above_sibling(this._title, null);
// if window is created while the overview is shown, icon and title should be visible immediately
if (Main.overview._overview._controls._stateAdjustment.value < 1) {
@@ -100,34 +114,23 @@ var WindowPreviewInjections = {
this._title.opacity = 0;
}
- if (opt.ALWAYS_SHOW_WIN_TITLES) {
+ if (opt.ALWAYS_SHOW_WIN_TITLES)
this._title.show();
- this._stateConId = this._workspace._background._stateAdjustment.connect('notify::value', (adj) => {
- this._title.opacity = Math.floor(adj.value) * 255;
- });
-
- }
if (opt.OVERVIEW_MODE === 1) {
// spread windows on hover
this._wsStateConId = this.connect('enter-event', () => {
// don't spread windows if user don't use pointer device at this moment
- if (global.get_pointer()[0] === opt.showingPointerX)
+ if (global.get_pointer()[0] === opt.showingPointerX || Main.overview._overview._controls._stateAdjustment.value < 1)
return;
const adjustment = this._workspace._background._stateAdjustment;
- if (!adjustment.value && !Main.overview._animationInProgress) {
- opt.WORKSPACE_MODE = 1;
- if (adjustment.value === 0) {
- adjustment.value = 0;
- adjustment.ease(1, {
- duration: 200,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD
- });
- }
- }
+ opt.WORKSPACE_MODE = 1;
+ _Util.exposeWindows(adjustment, false);
+ this.disconnect(this._wsStateConId);
});
}
+
if (opt.OVERVIEW_MODE) {
// show window icon and title on ws windows spread
this._stateAdjustmentSigId = this._workspace.stateAdjustment.connect('notify::value', this._updateIconScale.bind(this));
@@ -135,37 +138,52 @@ var WindowPreviewInjections = {
// replace click action with custom one
const action = this.get_actions()[0];
- this.remove_action(action);
- const clickAction = new Clutter.ClickAction();
- clickAction.connect('clicked', (action) => {
- const button = action.get_button();
+ const handlerId = GObject.signal_handler_find(action, { signalId: 'clicked' });
+ if (handlerId)
+ action.disconnect(handlerId);
+
+ action.connect('clicked', act => {
+ const button = act.get_button();
if (button === Clutter.BUTTON_PRIMARY) {
this._activate();
+ return Clutter.EVENT_STOP;
} else if (button === Clutter.BUTTON_SECONDARY) {
// this action cancels long-press event and the 'long-press-cancel' event is used by the Shell to actually initiate DnD
// so the dnd initiation needs to be removed
if (this._longPressLater) {
- Meta.later_remove(this._longPressLater);
- delete this._longPressLater;
+ if (shellVersion >= 44) {
+ const laters = global.compositor.get_laters();
+ laters.remove(this._longPressLater);
+ } else {
+ Meta.later_remove(this._longPressLater);
+ delete this._longPressLater;
+ }
}
const tracker = Shell.WindowTracker.get_default();
const appName = tracker.get_window_app(this.metaWindow).get_name();
_Util.activateSearchProvider(`${SEARCH_WINDOWS_PREFIX} ${appName}`);
return Clutter.EVENT_STOP;
}
+ return Clutter.EVENT_PROPAGATE;
});
- clickAction.connect('long-press', this._onLongPress.bind(this));
- this.add_action(clickAction);
-
- this.connect('destroy', () => this._workspace.stateAdjustment.disconnect(this._stateConId));
- }
-}
+ if (opt.WINDOW_ICON_CLICK_SEARCH) {
+ const iconClickAction = new Clutter.ClickAction();
+ iconClickAction.connect('clicked', act => {
+ if (act.get_button() === Clutter.BUTTON_PRIMARY) {
+ const tracker = Shell.WindowTracker.get_default();
+ const appName = tracker.get_window_app(this.metaWindow).get_name();
+ _Util.activateSearchProvider(`${SEARCH_WINDOWS_PREFIX} ${appName}`);
+ return Clutter.EVENT_STOP;
+ }
+ return Clutter.EVENT_PROPAGATE;
+ });
+ this._icon.add_action(iconClickAction);
+ }
+ },
-// WindowPreview
-var WindowPreviewCommon = {
- _updateIconScale: function() {
+ _updateIconScale() {
let { currentState, initialState, finalState } =
this._overviewAdjustment.getStateTransitionParams();
@@ -173,46 +191,60 @@ var WindowPreviewCommon = {
const primaryMonitor = this.metaWindow.get_monitor() === global.display.get_primary_monitor();
const visible =
- (initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN)
- && !(finalState === ControlsState.APP_GRID && primaryMonitor);
+ (initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN) &&
+ !(finalState === ControlsState.APP_GRID && primaryMonitor);
- let scale = visible
- ? (currentState >= 1 ? 1 : currentState % 1) : 0;
- if (!primaryMonitor &&
+ let scale = 0;
+ if (visible)
+ scale = currentState >= 1 ? 1 : currentState % 1;
+
+ if (!primaryMonitor && opt.WORKSPACE_MODE &&
((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
(initialState === ControlsState.APP_GRID && finalState === ControlsState.WINDOW_PICKER))
- ) {
+ )
scale = 1;
- /*} else if (primaryMonitor && ((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
+ else if (!primaryMonitor && opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE)
+ scale = 0;
+ /* } else if (primaryMonitor && ((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
initialState === ControlsState.APP_GRID && finalState === ControlsState.HIDDEN)) {*/
- } else if (primaryMonitor && currentState > ControlsState.WINDOW_PICKER) {
+ else if (primaryMonitor && currentState > ControlsState.WINDOW_PICKER)
scale = 0;
- }
- // in static workspace mode show icon and title on ws windows spread
+
+ // in static workspace mode show icon and title on windows expose
if (opt.OVERVIEW_MODE) {
- const windowsSpread = this._workspace.stateAdjustment.value;
- if (currentState === 1) {
- scale = windowsSpread;
- } else if (finalState === 1 || (finalState === 0 && !windowsSpread)) {
+ if (currentState === 1)
+ scale = opt.WORKSPACE_MODE;
+ else if (finalState === 1 || (finalState === 0 && !opt.WORKSPACE_MODE))
return;
- }
}
- this._icon.set({
- scale_x: scale,
- scale_y: scale,
- });
+ if (scale === 1) {
+ this._icon.ease({
+ duration: 50,
+ scale_x: scale,
+ scale_y: scale,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ this._title.ease({
+ duration: 100,
+ opacity: 255,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ } else if (this._icon.scale_x !== 0) {
+ this._icon.set({
+ scale_x: 0,
+ scale_y: 0,
+ });
+ this._title.opacity = 0;
+ }
// if titles are in 'always show' mode, we need to add transition between visible/invisible state
// but the transition is quite expensive,
// showing the titles at the end of the transition is good enough and workspace preview transition is much smoother
- this._title.set({
- opacity: Math.floor(scale) * 255,
- });
},
- showOverlay: function(animate) {
+ showOverlay(animate) {
if (!this._overlayEnabled)
return;
@@ -220,7 +252,8 @@ var WindowPreviewCommon = {
return;
this._overlayShown = true;
- //this._restack();
+ if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
+ this._restack();
// If we're supposed to animate and an animation in our direction
// is already happening, let that one continue
@@ -234,9 +267,9 @@ var WindowPreviewCommon = {
? [this._closeButton]
: [];
- if (!opt.ALWAYS_SHOW_WIN_TITLES) {
+ if (!opt.ALWAYS_SHOW_WIN_TITLES)
toShow.push(this._title);
- }
+
toShow.forEach(a => {
a.opacity = 0;
@@ -264,11 +297,17 @@ var WindowPreviewCommon = {
this.emit('show-chrome');
},
- hideOverlay: function(animate) {
+ hideOverlay(animate) {
if (!this._overlayShown)
return;
this._overlayShown = false;
- //this._restack();
+ if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW && Main.overview._overview.controls._stateAdjustment.value < 1) {
+ this.get_parent()?.set_child_above_sibling(this, null);
+ this._activateSelected = true;
+ }
+
+ if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
+ this._restack();
// If we're supposed to animate and an animation in our direction
// is already happening, let that one continue
@@ -280,9 +319,9 @@ var WindowPreviewCommon = {
const toHide = [this._closeButton];
- if (!opt.ALWAYS_SHOW_WIN_TITLES) {
+ if (!opt.ALWAYS_SHOW_WIN_TITLES)
toHide.push(this._title);
- }
+
toHide.forEach(a => {
a.opacity = 255;
a.ease({
@@ -304,18 +343,24 @@ var WindowPreviewCommon = {
},
_onDestroy() {
- // fix for upstream bug - hideOverlay is called after windowPreview is destroyed, from the leave event callback
- // but it still throws:
- // clutter_actor_get_preferred_width: assertion 'CLUTTER_IS_ACTOR (self)' failed
- // clutter_actor_get_preferred_height: assertion 'CLUTTER_IS_ACTOR (self)' failed
- this.hideOverlay(false);
+ // workaround for upstream bug - hideOverlay is called after windowPreview is destroyed, from the leave event callback
+ // hiding the preview now avoids firing the post-mortem leave event
+ this.hide();
+ if (this._activateSelected)
+ this._activate();
this.metaWindow._delegate = null;
this._delegate = null;
if (this._longPressLater) {
- Meta.later_remove(this._longPressLater);
- delete this._longPressLater;
+ if (shellVersion >= 44) {
+ const laters = global.compositor.get_laters();
+ laters.remove(this._longPressLater);
+ delete this._longPressLater;
+ } else {
+ Meta.later_remove(this._longPressLater);
+ delete this._longPressLater;
+ }
}
if (this._idleHideOverlayId > 0) {
@@ -328,8 +373,7 @@ var WindowPreviewCommon = {
this.inDrag = false;
}
- if (this._stateAdjustmentSigId) {
+ if (this._stateAdjustmentSigId)
this._workspace.stateAdjustment.disconnect(this._stateAdjustmentSigId);
- }
- }
-}
+ },
+};