1
0
Fork 0

Updating 44/vertical-workspaces to version 37+20231208 [0d82192].

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-03-24 19:42:07 +01:00
parent 975b88c6bb
commit 07381ac119
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
37 changed files with 9559 additions and 4338 deletions

View file

@ -1,4 +1,100 @@
## Changelog: ## Changelog:
### v45.2 for GNOME 45.2+, v44.10 for GNOME 42-44 (2023-12-02)
**Added:**
- *Dash* option *Isolate Workspaces* on *Behavior* tab
- *Brightness for Search View* option allows adjusting background wallpaper brightness in overview search view
- *Extensions Search Provider* module allows to search for extensions from the overview, open their settings and enable or disable them
### v45.1 for GNOME 45.1+ (EGO 2023-11-25) v44.9 for GNOME 42-44 (not released)
**Added:**
- *Window Thumbnail - PIP* option in app icon menu and as an click actions for Window Preview
- Workspace switcher options *Wraparound* and *Ignore Last (empty)*
- *Overlay key (Super)* and *Hot Corner* actions offer different overview modes independent on global *Overview Mode*
- Workspace thumbnails background without wallpaper is now semi-transparent to match other overview elements
- App Grid sorting options allow alphabetical order with folders
**Fixed:**
- App grid has less rows than it should
- Many minor fixes that reflect gnome-shell development and backports
- Centered app folder position on multi-monitor system
- Window can't be activated using touchscreen
- Setting background wallpaper too early on startup can crash Wayland session
**Other changes:**
- Since GNOME 45 V-Shell has 2 versions - one for GS 45 and the second for GS 42-44. Versioning no longer depends on EGO's upload counter
- Dash light style background opacity is not limited
- Refactored Recent Files Search Provider and other modules
- Settings window - ComboBox replaced with (finally fixed) DropDown
### v37 (2023-07-01)
**Fixed:**
- False detections of conflicting extensions
### v36 (2023-07-01) (35/34/33/32/31 skipped due to issues with extensions.gnome.org)
**Added:**
- Option *Fix New Windows Not In Focus* on *Misc* tab
**Fixed:**
- Improved compatibility with Dash to Dock extension - hidden dock in the overview, broken layout after startup
- Compatibility with Hide Top Bar extension
- App search provider ignores non-localized app names
- App folders grid dimensions wrong if set to *Adaptive* and folder icon is set to a fixed size
- Dash and active app folder icons running indicator position
- Blur/Brightness transitions in static overview mode
- Hot corner edge barrier can be active even if hot corner is disabled
- Disabling dash module does not reset dash position to default
**Other changes:**
- Removed css class reducing Quick Settings buttons height in GNOME 44
### v30 (2023-06-09)
**Added:**
- Dash option - Click Behavior: *Prefer Current Workspace* - opens a new window if app not present on the active workspace
- Window search provider sorting options
- Esc key behavior options
- Window preview - middle and secondary mouse button behavior options, close button can be hidden
- GNOME 3 vertical dash style is now optional
- Window preview title position option
- Light dash background option
- Remove app folder button in folder dialog
- *Updating V-Shell* banner appears during updating V-Shell settings when settings window is irresponsive
- Dutch translation by @Vistaus
**Fixed:**
- Dash icon scroll action conflicts with Dash to Dock
- Open new window by middle click on app icon or Ctrl+Enter doesn't work
- Dash icon label can extend to the adjacent display
- WindowPreview module not updated when "always-activate-selected-window" changed
- App folder dialog position if secondary monitor connected
- App folder dialog sizing and positioning
- Background brightness in search view reduced independently to avoid unreadable text and consistent style
- Compatibility with Burn My Windows - freeze after screen unlocked, or extensions re-enabled
- Window and Recent files search providers modes not isolated well from results of other providers
- Recent file search provider results sorting
- App grid icons with multi-line label move on hover when label expands
- Search view animation skipped id triggered from app grid state
- DING desktop icons not visible during static background workspace animation
**Other changes:**
- Added `unlock-dialog` session mode to avoid unnecessary system load when using screen lock
- App Grid refactored, added transparent app folder dialogs on clean background
- Search view transparency and fixed background brightness in classic overview
- Search view in static workspace overview with full opacity and close to default style
- Settings window - Profiles tab moved at first position, Dash icons position options moved back to layout
- Updated default profiles
### v29 (2023-04-11)
**Fixed:**
- Window switcher/highlighter logic when scrolling over an dash icon
- Unhandled promise rejection warnings on GS 43+
### v28 (2023-04-06) ### v28 (2023-04-06)
**Added:** **Added:**
- App Grid - vertical app folder orientation - App Grid - vertical app folder orientation

View file

@ -2,7 +2,7 @@
A GNOME Shell extension that lets you customize your GNOME Shell UX to suit your workflow, whether you like horizontally or vertically stacked workspaces. A GNOME Shell extension that lets you customize your GNOME Shell UX to suit your workflow, whether you like horizontally or vertically stacked workspaces.
Currently supported GNOME versions: 42, 43, 44 Currently supported GNOME versions: 42 - 45
[<img alt="" height="100" src="https://raw.githubusercontent.com/andyholmes/gnome-shell-extensions-badge/master/get-it-on-ego.svg?sanitize=true">](https://extensions.gnome.org/extension/5177/vertical-workspaces/) [<img alt="" height="100" src="https://raw.githubusercontent.com/andyholmes/gnome-shell-extensions-badge/master/get-it-on-ego.svg?sanitize=true">](https://extensions.gnome.org/extension/5177/vertical-workspaces/)
@ -17,6 +17,7 @@ Currently supported GNOME versions: 42, 43, 44
- Support for secondary monitors, workspace thumbnails can be placed on the opposite side than on the primary monitor - Support for secondary monitors, workspace thumbnails can be placed on the opposite side than on the primary monitor
- Wallpaper background with adjustable blur effect and brightness in the overview - Wallpaper background with adjustable blur effect and brightness in the overview
- Custom Dash icon size and on-click/scroll behavior - Custom Dash icon size and on-click/scroll behavior
- Optional workspace isolated Dash
- Dash background transparency and corner radius adjustments - Dash background transparency and corner radius adjustments
- Adjustable app grid icon size, number of columns and rows, content, optional active and draggable icons in folder preview in optional 3x3 grid - Adjustable app grid icon size, number of columns and rows, content, optional active and draggable icons in folder preview in optional 3x3 grid
- Custom search view width, app results icons size and number of result lists rows, improved app search - Custom search view width, app results icons size and number of result lists rows, improved app search
@ -26,12 +27,14 @@ Currently supported GNOME versions: 42, 43, 44
- Control over transition animations, including speed - Control over transition animations, including speed
- Window search provider with *Space* hotkey allows quick window navigation - Window search provider with *Space* hotkey allows quick window navigation
- Recent files search provider with *Ctrl + Space* hotkey - Recent files search provider with *Ctrl + Space* hotkey
- Extensions search provider with *Ctrl + Shift + Space* hotkey allows to search for extensions, open their settings and enable or disable them
- Reorder workspaces in overview using *Shift + Scroll* or *Shift + Page Up/Down* - Reorder workspaces in overview using *Shift + Scroll* or *Shift + Page Up/Down*
- Adds *Force Quit*, *Close Windows on Current Workspace* and *Move Windows to Current Workspace* items to app icon menu. The latter action can be activated using *Shift + click* on app icon - Adds *Force Quit*, *Close Windows on Current Workspace* and *Move Windows to Current Workspace* items to app icon menu. The latter action can be activated using *Shift + click* on app icon
- Change notification banners and OSD popups position - Change notification banners and OSD popups position
- Window attention handler options can activate the attention-demanding window immediately or silence its notification - Window attention handler options can activate the attention-demanding window immediately or silence its notification
- Optional position of the hot corner that can follow the dash and expand to hot edge - Optional position of the hot corner that can follow the dash and expand to hot edge
- Super key double-press options - Super key double-press options
- Window thumbnail (PIP) options allows you to create scaled down clone of the window by clicking on its preview in the overview (secondary mouse buttons or window preview icon)
## Changelog ## Changelog
[CHANGELOG.md](CHANGELOG.md) [CHANGELOG.md](CHANGELOG.md)
@ -51,14 +54,23 @@ Install the extension (`--force` switch needs to be used only if some version of
gnome-extensions install --force vertical-workspaces@G-dH.github.com.zip gnome-extensions install --force vertical-workspaces@G-dH.github.com.zip
### Installation from GitHub repository ### Installation from GitHub repository
The most recent version in the repository is the one I'm currently using and developing on my own systems, problems may occur, but usually nothing serious. The repository version may change often and doesn't updates automatically on your system, but once the stable release shows up on extensions.gnome.org, it should be updated automatically from there. If you want to help me, use this latest version and report bugs. The most recent version in the repository is the one I'm currently using and developing on my own systems, problems may occur, but usually nothing serious. The repository version may change often and doesn't updates automatically on your system. If you want to help me, use this latest version and report bugs.
You may need to install `git`, `gettext` and `glib2.0` for successful installation. You may need to install `git`, `make`, `gettext` and `glib2.0` for successful installation.
Navigate to the directory you want to download the source code and execute following commands in the terminal: Navigate to the directory you want to download the source code and execute following commands in the terminal:
GNOME 45:
git clone https://github.com/G-dH/vertical-workspaces.git git clone https://github.com/G-dH/vertical-workspaces.git
cd vertical-workspaces cd vertical-workspaces
make install make install
GNOME 42 - 44:
git clone https://github.com/G-dH/vertical-workspaces.git
cd vertical-workspaces
git checkout gnome-42-44
make install
If you get `Can't recursively copy directory` error, take a look at issue #51. If you get `Can't recursively copy directory` error, take a look at issue #51.
### Enabling the extension ### Enabling the extension

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,45 +10,63 @@
'use strict'; 'use strict';
const { Shell } = imports.gi;
const AppFavorites = imports.ui.appFavorites; const AppFavorites = imports.ui.appFavorites;
const Main = imports.ui.main;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const _Util = Me.imports.lib.util;
let Me;
let opt; let opt;
let _overrides;
let _firstRun = true;
function update(reset = false) { var AppFavoritesModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('appFavoritesModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
// don't even touch this module if disabled this._firstActivation = true;
if (_firstRun && reset) this.moduleEnabled = false;
return; this._overrides = null;
_firstRun = false;
if (_overrides)
_overrides.removeAll();
// if notifications are enabled no override is needed
if (reset || opt.SHOW_FAV_NOTIFICATION) {
_overrides = null;
opt = null;
return;
} }
_overrides = new _Util.Overrides(); cleanGlobals() {
Me = null;
opt = null;
}
// AppFavorites.AppFavorites is const, first access returns undefined update(reset) {
const dummy = AppFavorites.AppFavorites; this.moduleEnabled = opt.get('appFavoritesModule');
_overrides.addOverride('AppFavorites', AppFavorites.AppFavorites.prototype, AppFavoritesCommon);
} // if notifications are enabled no override is needed
reset = reset || !this.moduleEnabled || opt.SHOW_FAV_NOTIFICATION;
// don't touch original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation) {
this.moduleEnabled = false;
console.debug(' AppFavoritesModule - Keeping untouched');
}
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
// use actual instance instead of prototype
this._overrides.addOverride('AppFavorites', AppFavorites.getAppFavorites(), AppFavoritesCommon);
console.debug(' AppFavoritesModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
console.debug(' AppFavoritesModule - Deactivated');
}
};
const AppFavoritesCommon = { const AppFavoritesCommon = {
addFavoriteAtPos(appId, pos) { addFavoriteAtPos(appId, pos) {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,423 @@
/**
* V-Shell (Vertical Workspaces)
* extensionsSearchProvider.js
*
* @author GdH <G-dH@github.com>
* @copyright 2022 - 2023
* @license GPL-3.0
*/
'use strict';
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Main = imports.ui.main;
const ExtensionState = {
1: 'ENABLED',
2: 'DISABLED',
3: 'ERROR',
4: 'INCOMPATIBLE',
5: 'DOWNLOADING',
6: 'INITIALIZED',
7: 'DISABLING',
8: 'ENABLING',
};
let Me;
let opt;
// gettext
let _;
let _toggleTimeout;
// prefix helps to eliminate results from other search providers
// so it needs to be something less common
// needs to be accessible from vw module
const PREFIX = 'eq//';
var ExtensionsSearchProviderModule = class {
// export for other modules
static _PREFIX = PREFIX;
constructor(me) {
Me = me;
opt = Me.opt;
_ = Me.gettext;
this._firstActivation = true;
this.moduleEnabled = false;
this._extensionsSearchProvider = null;
this._enableTimeoutId = 0;
}
cleanGlobals() {
Me = null;
opt = null;
_ = null;
}
update(reset) {
if (_toggleTimeout)
GLib.source_remove(_toggleTimeout);
this.moduleEnabled = opt.get('extensionsSearchProviderModule');
reset = reset || !this.moduleEnabled;
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' ExtensionsSearchProviderModule - Keeping untouched');
}
_activateModule() {
// delay because Fedora had problem to register a new provider soon after Shell restarts
this._enableTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
2000,
() => {
if (!this._extensionsSearchProvider) {
this._extensionsSearchProvider = new extensionsSearchProvider(opt);
this._getOverviewSearchResult()._registerProvider(this._extensionsSearchProvider);
}
this._enableTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
);
console.debug(' ExtensionsSearchProviderModule - Activated');
}
_disableModule() {
if (this._enableTimeoutId) {
GLib.source_remove(this._enableTimeoutId);
this._enableTimeoutId = 0;
}
if (this._extensionsSearchProvider) {
this._getOverviewSearchResult()._unregisterProvider(this._extensionsSearchProvider);
this._extensionsSearchProvider = null;
}
console.debug(' ExtensionsSearchProviderModule - Disabled');
}
_getOverviewSearchResult() {
return Main.overview._overview.controls._searchController._searchResults;
}
};
class extensionsSearchProvider {
constructor() {
this.id = 'extensions';
const appSystem = Shell.AppSystem.get_default();
let appInfo = appSystem.lookup_app('com.matjakeman.ExtensionManager.desktop')?.get_app_info();
if (!appInfo)
appInfo = appSystem.lookup_app('org.gnome.Extensions.desktop')?.get_app_info();
if (!appInfo)
appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/gnome-extensions-app', 'Extensions', null);
appInfo.get_description = () => _('Search extensions');
appInfo.get_name = () => _('Extensions');
appInfo.get_id = () => 'org.gnome.Extensions.desktop';
appInfo.get_icon = () => Gio.icon_new_for_string('application-x-addon');
appInfo.should_show = () => true;
this.appInfo = appInfo;
this.canLaunchSearch = true;
this.isRemoteProvider = false;
}
getInitialResultSet(terms, callback /* , cancellable = null*/) {
// In GS 43 callback arg has been removed
/* if (Me.shellVersion >= 43)
cancellable = callback; */
const extensions = {};
Main.extensionManager._extensions.forEach(
e => {
extensions[e.uuid] = e;
}
);
this.extensions = extensions;
if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(this._getResultSet(terms)));
else
callback(this._getResultSet(terms));
return null;
}
_getResultSet(terms) {
// do not modify original terms
let termsCopy = [...terms];
// search for terms without prefix
termsCopy[0] = termsCopy[0].replace(PREFIX, '');
const candidates = this.extensions;
const _terms = [].concat(termsCopy);
const term = _terms.join(' ');
const results = [];
let m;
for (let id in candidates) {
const extension = this.extensions[id];
const text = extension.metadata.name + (extension.state === 1 ? 'enabled' : '') + ([6, 2].includes(extension.state) ? 'disabled' : '');
if (opt.SEARCH_FUZZY)
m = Me.Util.fuzzyMatch(term, text);
else
m = Me.Util.strictMatch(term, text);
if (m !== -1)
results.push({ weight: m, id });
}
// sort alphabetically
results.sort((a, b) => this.extensions[a.id].metadata.name.localeCompare(this.extensions[b.id].metadata.name));
// enabled first
// results.sort((a, b) => this.extensions[a.id].state !== 1 && this.extensions[b.id].state === 1);
// incompatible last
results.sort((a, b) => this.extensions[a.id].state === 4 && this.extensions[b.id].state !== 4);
this.resultIds = results.map(item => item.id);
return this.resultIds;
}
getResultMetas(resultIds, callback = null) {
const metas = resultIds.map(id => this.getResultMeta(id));
if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(metas));
else if (callback)
callback(metas);
return null;
}
getResultMeta(resultId) {
const result = this.extensions[resultId];
const versionName = result.metadata['version-name'] ?? '';
let version = result.metadata['version'] ?? '';
version = versionName && version ? `/${version}` : version;
const versionStr = `${versionName}${version}`;
return {
'id': resultId,
'name': `${result.metadata.name}`,
'version': versionStr,
'description': versionStr, // description will be updated in result object
'createIcon': size => {
let icon = this.getIcon(result, size);
return icon;
},
};
}
getIcon(extension, size) {
let opacity = 0;
let iconName = 'process-stop-symbolic';
switch (extension.state) {
case 1:
if (extension.hasUpdate)
iconName = 'software-update-available'; // 'software-update-available-symbolic';
else
iconName = 'object-select';// 'object-select-symbolic';
opacity = 255;
break;
case 3:
if (Main.extensionManager._enabledExtensions.includes(extension.uuid))
iconName = 'emblem-ok-symbolic';
else
iconName = 'dialog-error';
opacity = 100;
break;
case 4:
iconName = 'software-update-urgent'; // 'software-update-urgent-symbolic';
opacity = 100;
break;
}
if (extension.hasUpdate) {
iconName = 'software-update-available'; // 'software-update-available-symbolic';
opacity = 100;
}
const icon = new St.Icon({ icon_name: iconName, icon_size: size });
icon.set({
reactive: true,
opacity,
});
return icon;
}
createResultObject(meta) {
return new ListSearchResult(this, meta, this.extensions[meta.id]);
}
launchSearch(terms, timeStamp) {
this.appInfo.launch([], global.create_app_launch_context(timeStamp, -1), null);
}
activateResult(resultId/* terms, timeStamp*/) {
const extension = this.extensions[resultId];
if (Me.Util.isShiftPressed())
this._toggleExtension(extension);
else if (extension.hasPrefs)
Me.Util.openPreferences(extension.metadata);
}
filterResults(results /* , maxResults*/) {
// return results.slice(0, maxResults);
return results;
}
getSubsearchResultSet(previousResults, terms, callback) {
if (Me.shellVersion < 43) {
this.getSubsearchResultSet42(terms, callback);
return null;
}
return this.getInitialResultSet(terms);
}
getSubsearchResultSet42(terms, callback) {
callback(this._getResultSet(terms));
}
}
const ListSearchResult = GObject.registerClass(
class ListSearchResult extends St.Button {
_init(provider, metaInfo, extension) {
this.provider = provider;
this.metaInfo = metaInfo;
this.extension = extension;
super._init({
reactive: true,
can_focus: true,
track_hover: true,
});
this.style_class = 'list-search-result';
let content = new St.BoxLayout({
style_class: 'list-search-result-content',
vertical: false,
x_align: Clutter.ActorAlign.START,
x_expand: true,
y_expand: true,
});
this.set_child(content);
let titleBox = new St.BoxLayout({
style_class: 'list-search-result-title',
y_align: Clutter.ActorAlign.CENTER,
});
content.add_child(titleBox);
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
let iconBox = new St.Button();
iconBox.set_child(icon);
titleBox.add(iconBox);
iconBox.set_style('border: 1px solid rgba(200,200,200,0.2); padding: 2px; border-radius: 8px;');
this._iconBox = iconBox;
this.icon = icon;
iconBox.connect('clicked', () => {
this._toggleExtension();
return Clutter.EVENT_STOP;
});
let title = new St.Label({
text: this.metaInfo['name'],
y_align: Clutter.ActorAlign.CENTER,
opacity: extension.hasPrefs ? 255 : 150,
});
titleBox.add_child(title);
this.label_actor = title;
this._descriptionLabel = new St.Label({
style_class: 'list-search-result-description',
y_align: Clutter.ActorAlign.CENTER,
});
content.add_child(this._descriptionLabel);
this._highlightTerms();
this.connect('destroy', () => {
if (_toggleTimeout) {
GLib.source_remove(_toggleTimeout);
_toggleTimeout = 0;
}
});
}
_toggleExtension() {
const state = this.extension.state;
if (![1, 2, 6, 3].includes(state) || this.extension.metadata.uuid.includes('vertical-workspaces'))
return;
if ([2, 6].includes(state))
Main.extensionManager.enableExtension(this.extension.uuid);
else if ([1, 3].includes(state))
Main.extensionManager.disableExtension(this.extension.uuid);
if (_toggleTimeout)
GLib.source_remove(_toggleTimeout);
_toggleTimeout = GLib.timeout_add(GLib.PRIORITY_LOW, 200,
() => {
if ([7, 8].includes(this.extension.state))
return GLib.SOURCE_CONTINUE;
this.icon?.destroy();
this.icon = this.metaInfo['createIcon'](this.ICON_SIZE);
this._iconBox.set_child(this.icon);
this._highlightTerms();
_toggleTimeout = 0;
return GLib.SOURCE_REMOVE;
}
);
}
get ICON_SIZE() {
return 24;
}
_highlightTerms() {
const extension = this.extension;
const state = extension.state === 4 ? ExtensionState[this.extension.state] : '';
const error = extension.state === 3 ? ` ERROR: ${this.extension.error}` : '';
const update = extension.hasUpdate ? ' | UPDATE PENDING' : '';
const text = `${this.metaInfo.version} ${state}${error}${update}`;
let markup = text;// this.metaInfo['description'].split('\n')[0];
this._descriptionLabel.clutter_text.set_markup(markup);
}
vfunc_clicked() {
this.activate();
}
activate() {
this.provider.activateResult(this.metaInfo.id);
if (this.metaInfo.clipboardText) {
St.Clipboard.get_default().set_text(
St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
}
Main.overview.toggle();
}
});

View file

@ -9,11 +9,13 @@
*/ */
'use strict'; 'use strict';
const { GLib, St, Meta } = imports.gi;
const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const _Util = Me.imports.lib.util; let Me;
const shellVersion = _Util.shellVersion; let opt;
// added sizes for better scaling // added sizes for better scaling
const IconSize = { const IconSize = {
@ -29,47 +31,58 @@ const IconSize = {
LARGE: 96, LARGE: 96,
80: 80, 80: 80,
64: 64, 64: 64,
48: 48, TINY: 48,
TINY: 32,
}; };
const PAGE_WIDTH_CORRECTION = 100; const PAGE_WIDTH_CORRECTION = 100;
let opt; var IconGridModule = class {
let _overrides; constructor(me) {
let _firstRun = true; Me = me;
opt = Me.opt;
function update(reset = false) { this._firstActivation = true;
opt = Me.imports.lib.settings.opt; this.moduleEnabled = false;
const moduleEnabled = opt.get('appDisplayModule', true); this._overrides = null;
reset = reset || !moduleEnabled; }
// don't even touch this module if disabled cleanGlobals() {
if (_firstRun && reset) Me = null;
return;
_firstRun = false;
if (_overrides)
_overrides.removeAll();
if (reset) {
_overrides = null;
opt = null; opt = null;
return;
} }
_overrides = new _Util.Overrides(); update(reset) {
this.moduleEnabled = opt.get('appDisplayModule');
// if notifications are enabled no override is needed
reset = reset || !this.moduleEnabled;
if (shellVersion < 43 && IconGridCommon._findBestModeForSize) { // don't touch original code if module disabled
IconGridCommon['findBestModeForSize'] = IconGridCommon._findBestModeForSize; if (reset && !this._firstActivation) {
IconGridCommon['_findBestModeForSize'] = undefined; this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
} }
_overrides.addOverride('IconGrid', IconGrid.IconGrid.prototype, IconGridCommon);
_overrides.addOverride('IconGridLayout', IconGrid.IconGridLayout.prototype, IconGridLayoutCommon); _activateModule() {
} if (!this._overrides)
// workaround - silence page -2 error on gnome 43 while cleaning app grid this._overrides = new Me.Util.Overrides();
if (Me.shellVersion < 43 && IconGridCommon._findBestModeForSize) {
IconGridCommon['findBestModeForSize'] = IconGridCommon._findBestModeForSize;
delete IconGridCommon['_findBestModeForSize'];
}
this._overrides.addOverride('IconGrid', IconGrid.IconGrid.prototype, IconGridCommon);
this._overrides.addOverride('IconGridLayout', IconGrid.IconGridLayout.prototype, IconGridLayoutCommon);
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
}
};
const IconGridCommon = { const IconGridCommon = {
getItemsAtPage(page) { getItemsAtPage(page) {
@ -87,7 +100,7 @@ const IconGridCommon = {
return; return;
const { pagePadding } = this.layout_manager; const { pagePadding } = this.layout_manager;
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage); const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
const iconPadding = 53 * scaleFactor; const iconPadding = 51 * scaleFactor;
// provided width is usually about 100px wider in horizontal orientation with prev/next page indicators // provided width is usually about 100px wider in horizontal orientation with prev/next page indicators
const pageIndicatorCompensation = opt.ORIENTATION ? 0 : PAGE_WIDTH_CORRECTION; const pageIndicatorCompensation = opt.ORIENTATION ? 0 : PAGE_WIDTH_CORRECTION;
@ -99,8 +112,13 @@ const IconGridCommon = {
this.layoutManager._gridWidth = width; this.layoutManager._gridWidth = width;
this.layoutManager._gridHeight = height; this.layoutManager._gridHeight = height;
width -= 80; // compensation for default padding
height -= 80;
const spacing = opt.APP_GRID_SPACING; const spacing = opt.APP_GRID_SPACING;
const iconSize = (opt.APP_GRID_ICON_SIZE > 0 ? opt.APP_GRID_ICON_SIZE : opt.APP_GRID_ICON_SIZE_DEFAULT) * scaleFactor; // set the icon size as fixed to avoid changes in size later
const iconSize = opt.APP_GRID_ICON_SIZE > 0 ? opt.APP_GRID_ICON_SIZE : opt.APP_GRID_ICON_SIZE_DEFAULT;
const itemSize = iconSize * scaleFactor + iconPadding;
// if this._gridModes.length === 1, custom grid should be used // if this._gridModes.length === 1, custom grid should be used
// if (iconSize > 0 && this._gridModes.length > 1) { // if (iconSize > 0 && this._gridModes.length > 1) {
let columns = opt.APP_GRID_COLUMNS; let columns = opt.APP_GRID_COLUMNS;
@ -109,17 +127,20 @@ const IconGridCommon = {
let unusedSpaceH = -1; let unusedSpaceH = -1;
let unusedSpaceV = -1; let unusedSpaceV = -1;
if (!columns) { if (!columns) {
columns = Math.floor(width / (iconSize + iconPadding)) + 1; // calculate #columns + 1 without spacing
columns = Math.floor(width / itemSize) + 1;
// check if columns with spacing fits the available width
// and reduce the number until it fits
while (unusedSpaceH < 0) { while (unusedSpaceH < 0) {
columns -= 1; columns -= 1;
unusedSpaceH = width - columns * (iconSize + iconPadding) - (columns - 1) * spacing; unusedSpaceH = width - columns * itemSize - (columns - 1) * spacing;
} }
} }
if (!rows) { if (!rows) {
rows = Math.floor(height / (iconSize + iconPadding)) + 1; rows = Math.floor(height / itemSize) + 1;
while (unusedSpaceV < 0) { while (unusedSpaceV < 0) {
rows -= 1; rows -= 1;
unusedSpaceV = height - rows * (iconSize + iconPadding) - (rows - 1) * spacing; unusedSpaceV = height - rows * itemSize - ((rows - 1) * spacing);
} }
} }
@ -135,9 +156,16 @@ const IconGridLayoutCommon = {
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage); const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
const nColumns = this.columnsPerPage; const nColumns = this.columnsPerPage;
const nRows = this.rowsPerPage; const nRows = this.rowsPerPage;
// if grid is not defined return default icon size
if (nColumns < 1 && nRows < 1) {
return this._isFolder
? opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT : opt.APP_GRID_ICON_SIZE_DEFAULT;
}
const columnSpacingPerPage = opt.APP_GRID_SPACING * (nColumns - 1); const columnSpacingPerPage = opt.APP_GRID_SPACING * (nColumns - 1);
const rowSpacingPerPage = opt.APP_GRID_SPACING * (nRows - 1); const rowSpacingPerPage = opt.APP_GRID_SPACING * (nRows - 1);
const iconPadding = 53 * scaleFactor; const iconPadding = 55 * scaleFactor;
const paddingH = this._isFolder ? this.pagePadding.left + this.pagePadding.right : 0; const paddingH = this._isFolder ? this.pagePadding.left + this.pagePadding.right : 0;
const paddingV = this._isFolder ? this.pagePadding.top + this.pagePadding.bottom : 0; const paddingV = this._isFolder ? this.pagePadding.top + this.pagePadding.bottom : 0;
@ -156,10 +184,14 @@ const IconGridLayoutCommon = {
return opt.APP_GRID_ICON_SIZE_DEFAULT;*/ return opt.APP_GRID_ICON_SIZE_DEFAULT;*/
let iconSizes = Object.values(IconSize).sort((a, b) => b - a); let iconSizes = Object.values(IconSize).sort((a, b) => b - a);
// limit max icon size for folders and fully adaptive folder grids, the whole range is for the main grid with active folders
// limit max icon size for folders, the whole range is for the main grid with active folders if (this._isFolder && opt.APP_GRID_FOLDER_ADAPTIVE && opt.APP_GRID_FOLDER_ICON_SIZE < 0)
if (this._isFolder) iconSizes = iconSizes.slice(iconSizes.indexOf(opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT), -1);
else if (this._isFolder)
iconSizes = iconSizes.slice(iconSizes.indexOf(IconSize.LARGE), -1); iconSizes = iconSizes.slice(iconSizes.indexOf(IconSize.LARGE), -1);
else if (opt.APP_GRID_ADAPTIVE && opt.APP_GRID_ICON_SIZE < 0)
iconSizes = iconSizes.slice(iconSizes.indexOf(opt.APP_GRID_ICON_SIZE_DEFAULT), -1);
let sizeInvalid = false; let sizeInvalid = false;
for (const size of iconSizes) { for (const size of iconSizes) {
@ -167,10 +199,9 @@ const IconGridLayoutCommon = {
if (firstItem) { if (firstItem) {
firstItem.icon.setIconSize(size); firstItem.icon.setIconSize(size);
const [firstItemWidth, firstItemHeight] = const [firstItemWidth] = firstItem.get_preferred_size();
firstItem.get_preferred_size();
const itemSize = Math.max(firstItemWidth, firstItemHeight); const itemSize = firstItemWidth;
if (itemSize < size) if (itemSize < size)
sizeInvalid = true; sizeInvalid = true;
@ -199,7 +230,7 @@ const IconGridLayoutCommon = {
removeItem(item) { removeItem(item) {
if (!this._items.has(item)) { if (!this._items.has(item)) {
log(`Item ${item} is not part of the IconGridLayout`); console.error(`Item ${item} is not part of the IconGridLayout`);
return; return;
// throw new Error(`Item ${item} is not part of the IconGridLayout`); // throw new Error(`Item ${item} is not part of the IconGridLayout`);
} }
@ -215,13 +246,13 @@ const IconGridLayoutCommon = {
addItem(item, page = -1, index = -1) { addItem(item, page = -1, index = -1) {
if (this._items.has(item)) { if (this._items.has(item)) {
log(`iconGrid: Item ${item} already added to IconGridLayout`); console.error(`iconGrid: Item ${item} already added to IconGridLayout`);
return; return;
// throw new Error(`Item ${item} already added to IconGridLayout`); // throw new Error(`Item ${item} already added to IconGridLayout`);
} }
if (page > this._pages.length) { if (page > this._pages.length) {
log(`iconGrid: Cannot add ${item} to page ${page}`); console.error(`iconGrid: Cannot add ${item} to page ${page}`);
page = -1; page = -1;
index = -1; index = -1;
// throw new Error(`Cannot add ${item} to page ${page}`); // throw new Error(`Cannot add ${item} to page ${page}`);
@ -240,7 +271,7 @@ const IconGridLayoutCommon = {
moveItem(item, newPage, newPosition) { moveItem(item, newPage, newPosition) {
if (!this._items.has(item)) { if (!this._items.has(item)) {
log(`iconGrid: Item ${item} is not part of the IconGridLayout`); console.error(`iconGrid: Item ${item} is not part of the IconGridLayout`);
return; return;
// throw new Error(`Item ${item} is not part of the IconGridLayout`); // throw new Error(`Item ${item} is not part of the IconGridLayout`);
} }

View file

@ -10,67 +10,107 @@
'use strict'; 'use strict';
const { Meta, GLib, Shell, Clutter, GObject } = imports.gi; const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const Gio = imports.gi.Gio;
const Main = imports.ui.main;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Ripples = imports.ui.ripples; const Main = imports.ui.main;
const DND = imports.ui.dnd;
const Me = imports.misc.extensionUtils.getCurrentExtension(); let Me;
const _Util = Me.imports.lib.util;
let _overrides;
let _timeouts;
let opt; let opt;
let _firstRun = true;
let _originalUpdateHotCorners;
function update(reset = false) { let _timeouts;
opt = Me.imports.lib.settings.opt;
const moduleEnabled = opt.get('layoutModule', true);
const conflict = _Util.getEnabledExtensions('custom-hot-corners').length ||
_Util.getEnabledExtensions('dash-to-panel').length;
reset = reset || !moduleEnabled;
// don't even touch this module if disabled or in conflict var LayoutModule = class {
if (_firstRun && (reset || conflict)) constructor(me) {
return; Me = me;
opt = Me.opt;
_timeouts = {};
_firstRun = false; this._firstActivation = true;
this.moduleEnabled = false;
if (!_originalUpdateHotCorners) this._overrides = null;
_originalUpdateHotCorners = Layout.LayoutManager.prototype._updateHotCorners; this._originalUpdateHotCorners = null;
if (_overrides)
_overrides.removeAll();
if (_timeouts) {
Object.values(_timeouts).forEach(t => {
if (t)
GLib.source_remove(t);
});
} }
if (reset) { cleanGlobals() {
_overrides = null; Me = null;
opt = null; opt = null;
_timeouts = null;
Main.layoutManager._updateHotCorners = _originalUpdateHotCorners;
Main.layoutManager._updateHotCorners();
return;
} }
_timeouts = {}; update(reset) {
this._removeTimeouts();
_overrides = new _Util.Overrides(); this.moduleEnabled = opt.get('layoutModule');
_overrides.addOverride('LayoutManager', Layout.LayoutManager.prototype, LayoutManagerCommon); const conflict = Me.Util.getEnabledExtensions('custom-hot-corners').length ||
Me.Util.getEnabledExtensions('dash-to-panel').length;
Main.layoutManager._updateHotCorners = LayoutManagerCommon._updateHotCorners.bind(Main.layoutManager); if (conflict && !reset)
console.warn(`[${Me.metadata.name}] Warning: "Layout" module disabled due to potential conflict with another extension`);
Main.layoutManager._updatePanelBarrier(); reset = reset || !this.moduleEnabled || conflict;
Main.layoutManager._updateHotCorners();
} // don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' LayoutModule - Keeping untouched');
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
_timeouts = {};
this._overrides.addOverride('LayoutManager', Main.layoutManager, LayoutManagerCommon);
this._overrides.addOverride('HotCorner', Layout.HotCorner.prototype, HotCornerCommon);
Main.layoutManager._updatePanelBarrier();
Main.layoutManager._updateHotCorners();
if (!this._hotCornersEnabledConId) {
this._interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface',
});
this._hotCornersEnabledConId = this._interfaceSettings.connect('changed::enable-hot-corners',
() => Main.layoutManager._updateHotCorners());
}
console.debug(' LayoutModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
Main.layoutManager._updateHotCorners();
if (this._hotCornersEnabledConId) {
this._interfaceSettings.disconnect(this._hotCornersEnabledConId);
this._hotCornersEnabledConId = 0;
this._interfaceSettings = null;
}
console.debug(' LayoutModule - Disabled');
}
_removeTimeouts() {
if (_timeouts) {
Object.values(_timeouts).forEach(t => {
if (t)
GLib.source_remove(t);
});
_timeouts = null;
}
}
};
const LayoutManagerCommon = { const LayoutManagerCommon = {
_updatePanelBarrier() { _updatePanelBarrier() {
@ -84,7 +124,7 @@ const LayoutManagerCommon = {
this._leftPanelBarrier = null; this._leftPanelBarrier = null;
} }
if (!this.primaryMonitor || !opt) if (!this.primaryMonitor || !opt || Me.Util.getEnabledExtensions('hidetopbar'))
return; return;
if (this.panelBox.height) { if (this.panelBox.height) {
@ -113,6 +153,7 @@ const LayoutManagerCommon = {
// avoid errors if called from foreign override // avoid errors if called from foreign override
if (!opt) if (!opt)
return; return;
// destroy old hot corners // destroy old hot corners
this.hotCorners.forEach(corner => corner?.destroy()); this.hotCorners.forEach(corner => corner?.destroy());
this.hotCorners = []; this.hotCorners = [];
@ -122,7 +163,7 @@ const LayoutManagerCommon = {
return; return;
} }
let size = this.panelBox.height; let size = this.panelBox.height ? this.panelBox.height : 27;
// position 0 - default, 1-TL, 2-TR, 3-BL, 4-BR // position 0 - default, 1-TL, 2-TR, 3-BL, 4-BR
const position = opt.HOT_CORNER_POSITION; const position = opt.HOT_CORNER_POSITION;
@ -181,8 +222,8 @@ const LayoutManagerCommon = {
} }
if (haveCorner) { if (haveCorner) {
let corner = new HotCorner(this, monitor, cornerX, cornerY); let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY);
corner.setBarrierSize(size); corner.setBarrierSize(size, false);
this.hotCorners.push(corner); this.hotCorners.push(corner);
} else { } else {
this.hotCorners.push(null); this.hotCorners.push(null);
@ -193,11 +234,8 @@ const LayoutManagerCommon = {
}, },
}; };
var HotCorner = GObject.registerClass( const HotCornerCommon = {
class HotCorner extends Layout.HotCorner { after__init() {
_init(layoutManager, monitor, x, y) {
super._init(layoutManager, monitor, x, y);
let angle = 0; let angle = 0;
switch (opt.HOT_CORNER_POSITION) { switch (opt.HOT_CORNER_POSITION) {
case 2: case 2:
@ -214,9 +252,14 @@ class HotCorner extends Layout.HotCorner {
this._ripples._ripple1.rotation_angle_z = angle; this._ripples._ripple1.rotation_angle_z = angle;
this._ripples._ripple2.rotation_angle_z = angle; this._ripples._ripple2.rotation_angle_z = angle;
this._ripples._ripple3.rotation_angle_z = angle; this._ripples._ripple3.rotation_angle_z = angle;
} },
setBarrierSize(size, notMyCall = true) {
// ignore calls from the original _updateHotCorners() callback to avoid building barriers outside screen
if (notMyCall && size > 0) {
return;
}
setBarrierSize(size) {
if (this._verticalBarrier) { if (this._verticalBarrier) {
this._pressureBarrier.removeBarrier(this._verticalBarrier); this._pressureBarrier.removeBarrier(this._verticalBarrier);
this._verticalBarrier.destroy(); this._verticalBarrier.destroy();
@ -232,8 +275,8 @@ class HotCorner extends Layout.HotCorner {
if (size > 0) { if (size > 0) {
const primaryMonitor = global.display.get_primary_monitor(); const primaryMonitor = global.display.get_primary_monitor();
const monitor = this._monitor; const monitor = this._monitor;
const extendV = opt && opt.HOT_CORNER_EDGE && opt.DASH_VERTICAL && monitor.index === primaryMonitor; const extendV = opt && opt.HOT_CORNER_ACTION && opt.HOT_CORNER_EDGE && opt.DASH_VERTICAL && monitor.index === primaryMonitor;
const extendH = opt && opt.HOT_CORNER_EDGE && !opt.DASH_VERTICAL && monitor.index === primaryMonitor; const extendH = opt && opt.HOT_CORNER_ACTION && opt.HOT_CORNER_EDGE && !opt.DASH_VERTICAL && monitor.index === primaryMonitor;
if (opt.HOT_CORNER_POSITION <= 1) { if (opt.HOT_CORNER_POSITION <= 1) {
this._verticalBarrier = new Meta.Barrier({ this._verticalBarrier = new Meta.Barrier({
@ -284,25 +327,52 @@ class HotCorner extends Layout.HotCorner {
this._pressureBarrier.addBarrier(this._verticalBarrier); this._pressureBarrier.addBarrier(this._verticalBarrier);
this._pressureBarrier.addBarrier(this._horizontalBarrier); this._pressureBarrier.addBarrier(this._horizontalBarrier);
} }
} },
_toggleOverview() { _toggleOverview() {
if (!opt.HOT_CORNER_ACTION || (!opt.HOT_CORNER_FULLSCREEN && this._monitor.inFullscreen && !Main.overview.visible)) if (!opt.HOT_CORNER_ACTION || (!opt.HOT_CORNER_FULLSCREEN && this._monitor.inFullscreen && !Main.overview.visible))
return; return;
if (Main.overview.shouldToggleByCornerOrButton()) { if (Main.overview.shouldToggleByCornerOrButton()) {
if ((opt.HOT_CORNER_ACTION === 1 && !_Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 2 && _Util.isCtrlPressed())) if (Main.overview._shown) {
this._toggleWindowPicker(true); this._toggleWindowPicker(true);
else if ((opt.HOT_CORNER_ACTION === 2 && !_Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 1 && _Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 3 && _Util.isCtrlPressed())) } else if ((opt.HOT_CORNER_ACTION === 2 && !Me.Util.isCtrlPressed()) || ([3, 4, 5, 6].includes(opt.HOT_CORNER_ACTION) && Me.Util.isCtrlPressed())) {
// Default overview
opt.OVERVIEW_MODE = 0;
opt.OVERVIEW_MODE2 = false;
opt.WORKSPACE_MODE = 1;
this._toggleWindowPicker(true, true);
} else if (opt.HOT_CORNER_ACTION === 1) {
Main.overview.resetOverviewMode();
this._toggleWindowPicker(true, true);
} else if ((opt.HOT_CORNER_ACTION === 3 && !Me.Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 2 && Me.Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 6 && Me.Util.isCtrlPressed())) {
// Applications
this._toggleApplications(true); this._toggleApplications(true);
else if (opt.HOT_CORNER_ACTION === 3 && !_Util.isCtrlPressed()) } else if (opt.HOT_CORNER_ACTION === 4 && !Me.Util.isCtrlPressed()) {
// Overview - static ws preview
opt.OVERVIEW_MODE = 1;
opt.OVERVIEW_MODE2 = false;
opt.WORKSPACE_MODE = 0;
this._toggleWindowPicker(true, true);
} else if (opt.HOT_CORNER_ACTION === 5 && !Me.Util.isCtrlPressed()) {
// Overview - static ws
opt.OVERVIEW_MODE = 2;
opt.OVERVIEW_MODE2 = true;
opt.WORKSPACE_MODE = 0;
this._toggleWindowPicker(true, true);
} else if (opt.HOT_CORNER_ACTION === 6 && !Me.Util.isCtrlPressed()) {
// Window search provider
opt.OVERVIEW_MODE = 2;
opt.OVERVIEW_MODE2 = true;
opt.WORKSPACE_MODE = 0;
this._toggleWindowSearchProvider(); this._toggleWindowSearchProvider();
}
if (opt.HOT_CORNER_RIPPLES && Main.overview.animationInProgress) if (opt.HOT_CORNER_RIPPLES && Main.overview.animationInProgress)
this._ripples.playAnimation(this._x, this._y); this._ripples.playAnimation(this._x, this._y);
} }
} },
_toggleWindowPicker(leaveOverview = false) { _toggleWindowPicker(leaveOverview = false, customOverviewMode = false) {
if (Main.overview._shown && (leaveOverview || !Main.overview.dash.showAppsButton.checked)) { if (Main.overview._shown && (leaveOverview || !Main.overview.dash.showAppsButton.checked)) {
Main.overview.hide(); Main.overview.hide();
} else if (Main.overview.dash.showAppsButton.checked) { } else if (Main.overview.dash.showAppsButton.checked) {
@ -320,17 +390,17 @@ class HotCorner extends Layout.HotCorner {
// delay cannot be too short // delay cannot be too short
200, 200,
() => { () => {
Main.overview.show(); Main.overview.show(1, customOverviewMode);
_timeouts.releaseKeyboardTimeoutId = 0; _timeouts.releaseKeyboardTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} }
); );
} else { } else {
Main.overview.show(); Main.overview.show(1, customOverviewMode);
} }
} }
} },
_toggleApplications(leaveOverview = false) { _toggleApplications(leaveOverview = false) {
if ((leaveOverview && Main.overview._shown) || Main.overview.dash.showAppsButton.checked) { if ((leaveOverview && Main.overview._shown) || Main.overview.dash.showAppsButton.checked) {
@ -360,12 +430,15 @@ class HotCorner extends Layout.HotCorner {
Main.overview.show(2); // 2 for App Grid Main.overview.show(2); // 2 for App Grid
} }
} }
} },
_toggleWindowSearchProvider() { _toggleWindowSearchProvider() {
if (!Main.overview._overview._controls._searchController._searchActive) { if (!Main.overview._overview._controls._searchController._searchActive) {
this._toggleWindowPicker(); opt.OVERVIEW_MODE = 2;
const prefix = 'wq// '; opt.OVERVIEW_MODE2 = true;
opt.WORKSPACE_MODE = 0;
this._toggleWindowPicker(false, true);
const prefix = Me.WSP_PREFIX;
const position = prefix.length; const position = prefix.length;
const searchEntry = Main.overview.searchEntry; const searchEntry = Main.overview.searchEntry;
searchEntry.set_text(prefix); searchEntry.set_text(prefix);
@ -376,5 +449,5 @@ class HotCorner extends Layout.HotCorner {
// Main.overview.searchEntry.text = ''; // Main.overview.searchEntry.text = '';
Main.overview.hide(); Main.overview.hide();
} }
} },
}); };

View file

@ -10,58 +10,82 @@
'use strict'; 'use strict';
const { Clutter } = imports.gi; const Clutter = imports.gi.Clutter;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Main = imports.ui.main; const Main = imports.ui.main;
let Me;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { var MessageTrayModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('messageTrayModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
// don't even touch this module if disabled this._firstActivation = true;
if (_firstRun && reset) this.moduleEnabled = false;
return; }
_firstRun = false; cleanGlobals() {
Me = null;
if (reset) {
opt = null; opt = null;
setNotificationPosition(1);
return;
} }
setNotificationPosition(opt.NOTIFICATION_POSITION); update(reset) {
} this.moduleEnabled = opt.get('messageTrayModule');
const conflict = false;
function setNotificationPosition(position) { reset = reset || !this.moduleEnabled || conflict;
switch (position) {
case 0: // don't touch the original code if module disabled
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START; if (reset && !this._firstActivation) {
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START; this._disableModule();
break; } else if (!reset) {
case 1: this._firstActivation = false;
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER; this._activateModule();
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START; }
break; if (reset && this._firstActivation)
case 2: console.debug(' MessageTrayModule - Keeping untouched');
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
break;
case 3:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
break;
case 4:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
break;
case 5:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
break;
} }
}
_activateModule() {
this._setNotificationPosition(opt.NOTIFICATION_POSITION);
console.debug(' MessageTrayModule - Activated');
}
_disableModule() {
this._setNotificationPosition(1);
console.debug(' MessageTrayModule - Disabled');
}
_setNotificationPosition(position) {
switch (position) {
case 0:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
break;
case 1:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
break;
case 2:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
break;
case 3:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
break;
case 4:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
break;
case 5:
Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
break;
}
}
};

View file

@ -9,41 +9,35 @@
'use strict'; 'use strict';
const { Gtk, Gio, GObject } = imports.gi; const Adw = imports.gi.Adw;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const ExtensionUtils = imports.misc.extensionUtils; let Me;
const Me = ExtensionUtils.getCurrentExtension();
const Settings = Me.imports.lib.settings;
const shellVersion = Settings.shellVersion;
// gettext // gettext
const _ = Settings._; let _; // = Settings._;
const ProfileNames = [ function init(me) {
_('GNOME 3'), Me = me;
_('GNOME 40+ - Bottom Hot Edge'), _ = Me.gettext;
_('Hot Corner Centric - Top Left Hot Corner'), }
_('Dock Overview - Bottom Hot Edge'),
];
// libadwaita is available starting with GNOME Shell 42. function cleanGlobals() {
let Adw = null; Me = null;
try { _ = null;
Adw = imports.gi.Adw; }
} catch (e) {}
function _newImageFromIconName(name) { function _newImageFromIconName(name) {
return Gtk.Image.new_from_icon_name(name); return Gtk.Image.new_from_icon_name(name);
} }
var ItemFactory = class ItemFactory { var ItemFactory = class ItemFactory {
constructor(gOptions) { constructor() {
this._gOptions = gOptions; this._settings = Me.Opt._gsettings;
this._settings = this._gOptions._gsettings;
} }
getRowWidget(text, caption, widget, variable, options = []) { getRowWidget(text, caption, widget, variable, options = [], dependsOn) {
let item = []; let item = [];
let label; let label;
if (widget) { if (widget) {
@ -81,8 +75,8 @@ var ItemFactory = class ItemFactory {
let key; let key;
if (variable && this._gOptions.options[variable]) { if (variable && Me.Opt.options[variable]) {
const opt = this._gOptions.options[variable]; const opt = Me.Opt.options[variable];
key = opt[1]; key = opt[1];
} }
@ -95,6 +89,11 @@ var ItemFactory = class ItemFactory {
this._connectComboBox(widget, key, variable, options); this._connectComboBox(widget, key, variable, options);
else if (widget._isDropDown) else if (widget._isDropDown)
this._connectDropDown(widget, key, variable, options); this._connectDropDown(widget, key, variable, options);
if (dependsOn) {
const dKey = Me.Opt.options[dependsOn][1];
this._settings.bind(dKey, widget, 'sensitive', Gio.SettingsBindFlags.GET);
}
} }
return item; return item;
@ -111,7 +110,7 @@ var ItemFactory = class ItemFactory {
_connectComboBox(widget, key, variable, options) { _connectComboBox(widget, key, variable, options) {
let model = widget.get_model(); let model = widget.get_model();
widget._comboMap = {}; widget._comboMap = {};
const currentValue = this._gOptions.get(variable); const currentValue = Me.Opt.get(variable);
for (const [label, value] of options) { for (const [label, value] of options) {
let iter; let iter;
model.set(iter = model.append(), [0, 1], [label, value]); model.set(iter = model.append(), [0, 1], [label, value]);
@ -120,8 +119,8 @@ var ItemFactory = class ItemFactory {
widget._comboMap[value] = iter; widget._comboMap[value] = iter;
} }
this._gOptions.connect(`changed::${key}`, () => { Me.Opt.connect(`changed::${key}`, () => {
widget.set_active_iter(widget._comboMap[this._gOptions.get(variable, true)]); widget.set_active_iter(widget._comboMap[Me.Opt.get(variable, true)]);
}); });
widget.connect('changed', () => { widget.connect('changed', () => {
const [success, iter] = widget.get_active_iter(); const [success, iter] = widget.get_active_iter();
@ -129,17 +128,17 @@ var ItemFactory = class ItemFactory {
if (!success) if (!success)
return; return;
this._gOptions.set(variable, model.get_value(iter, 1)); Me.Opt.set(variable, model.get_value(iter, 1));
}); });
} }
_connectDropDown(widget, key, variable, options) { _connectDropDown(widget, key, variable, options) {
const model = widget.get_model(); const model = widget.get_model();
const currentValue = this._gOptions.get(variable); const currentValue = Me.Opt.get(variable);
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
const text = options[i][0]; const text = options[i][0];
const id = options[i][1]; const id = options[i][1];
model.append(new DropDownItem({ text, id })); model.append(new DropDownItemVW({ text, id }));
if (id === currentValue) if (id === currentValue)
widget.set_selected(i); widget.set_selected(i);
} }
@ -157,11 +156,11 @@ var ItemFactory = class ItemFactory {
widget.connect('notify::selected-item', dropDown => { widget.connect('notify::selected-item', dropDown => {
const item = dropDown.get_selected_item(); const item = dropDown.get_selected_item();
this._gOptions.set(variable, item.id); Me.Opt.set(variable, item.id);
}); });
this._gOptions.connect(`changed::${key}`, () => { Me.Opt.connect(`changed::${key}`, () => {
const newId = this._gOptions.get(variable, true); const newId = Me.Opt.get(variable, true);
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
const id = options[i][1]; const id = options[i][1];
if (id === newId) if (id === newId)
@ -214,7 +213,7 @@ var ItemFactory = class ItemFactory {
newDropDown() { newDropDown() {
const dropDown = new Gtk.DropDown({ const dropDown = new Gtk.DropDown({
model: new Gio.ListStore({ model: new Gio.ListStore({
item_type: DropDownItem, item_type: DropDownItemVW,
}), }),
halign: Gtk.Align.END, halign: Gtk.Align.END,
valign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER,
@ -255,11 +254,11 @@ var ItemFactory = class ItemFactory {
newLinkButton(uri) { newLinkButton(uri) {
const linkBtn = new Gtk.LinkButton({ const linkBtn = new Gtk.LinkButton({
label: shellVersion < 42 ? 'Click Me!' : '',
uri, uri,
halign: Gtk.Align.END, halign: Gtk.Align.END,
valign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER,
hexpand: true, hexpand: true,
icon_name: 'emblem-symbolic-link',
}); });
return linkBtn; return linkBtn;
} }
@ -298,18 +297,23 @@ var ItemFactory = class ItemFactory {
entry.set_text(opt.get(`profileName${profileIndex}`)); entry.set_text(opt.get(`profileName${profileIndex}`));
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'edit-clear-symbolic'); entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'edit-clear-symbolic');
entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, true); entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, true);
entry.connect('icon-press', e => e.set_text(''));
entry.connect('changed', e => opt.set(`profileName${profileIndex}`, e.get_text()));
const resetProfile = this.newButton(); const resetProfile = this.newButton();
resetProfile.set({ resetProfile.set({
tooltip_text: _('Reset profile to defaults'), tooltip_text: _('Reset profile to defaults'),
icon_name: 'edit-delete-symbolic', icon_name: 'document-revert-symbolic',
hexpand: false, hexpand: false,
css_classes: ['destructive-action'], css_classes: ['destructive-action'],
}); });
function setName() { function setName() {
const ProfileNames = [
_('GNOME 3'),
_('GNOME 40+ - Bottom Hot Edge'),
_('Hot Corner Centric - Top Left Hot Corner'),
_('Dock Overview - Bottom Hot Edge'),
];
let name = opt.get(`profileName${profileIndex}`, true); let name = opt.get(`profileName${profileIndex}`, true);
if (!name) if (!name)
name = ProfileNames[profileIndex - 1]; name = ProfileNames[profileIndex - 1];
@ -317,6 +321,10 @@ var ItemFactory = class ItemFactory {
} }
setName(); setName();
entry.connect('icon-press', e => e.set_text(''));
entry.connect('changed', e => opt.set(`profileName${profileIndex}`, e.get_text()));
resetProfile.connect('clicked', () => { resetProfile.connect('clicked', () => {
reset(profileIndex); reset(profileIndex);
setName(); setName();
@ -366,7 +374,7 @@ var ItemFactory = class ItemFactory {
valign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER,
hexpand: true, hexpand: true,
css_classes: ['destructive-action'], css_classes: ['destructive-action'],
icon_name: 'edit-delete-symbolic', icon_name: 'document-revert-symbolic',
}); });
btn.connect('clicked', () => { btn.connect('clicked', () => {
@ -382,7 +390,7 @@ var ItemFactory = class ItemFactory {
var AdwPrefs = class { var AdwPrefs = class {
constructor(gOptions) { constructor(gOptions) {
this._gOptions = gOptions; Me.Opt = gOptions;
} }
getFilledWindow(window, pages) { getFilledWindow(window, pages) {
@ -457,158 +465,9 @@ var AdwPrefs = class {
} }
}; };
var LegacyPrefs = class { const { GObject } = imports.gi;
constructor(gOptions) { const DropDownItemVW = GObject.registerClass({
this._gOptions = gOptions; GTypeName: 'DropDownItemVW',
}
getPrefsWidget(pages) {
const prefsWidget = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
});
const stack = new Gtk.Stack({
hexpand: true,
});
const stackSwitcher = new Gtk.StackSwitcher({
halign: Gtk.Align.CENTER,
hexpand: true,
});
const context = stackSwitcher.get_style_context();
context.add_class('caption');
stackSwitcher.set_stack(stack);
stack.set_transition_duration(300);
stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT);
const pageProperties = {
hscrollbar_policy: Gtk.PolicyType.NEVER,
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
vexpand: true,
hexpand: true,
visible: true,
};
const pagesBtns = [];
for (let page of pages) {
const name = page.name;
const title = page.title;
const iconName = page.iconName;
const optionList = page.optionList;
stack.add_named(this._getLegacyPage(optionList, pageProperties), name);
pagesBtns.push(
[new Gtk.Label({ label: title }), _newImageFromIconName(iconName, Gtk.IconSize.BUTTON)]
);
}
let stBtn = stackSwitcher.get_first_child ? stackSwitcher.get_first_child() : null;
for (let i = 0; i < pagesBtns.length; i++) {
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 6, visible: true });
const icon = pagesBtns[i][1];
icon.margin_start = 30;
icon.margin_end = 30;
box.append(icon);
box.append(pagesBtns[i][0]);
if (stackSwitcher.get_children) {
stBtn = stackSwitcher.get_children()[i];
stBtn.add(box);
} else {
stBtn.set_child(box);
stBtn.visible = true;
stBtn = stBtn.get_next_sibling();
}
}
if (stack.show_all)
stack.show_all();
if (stackSwitcher.show_all)
stackSwitcher.show_all();
prefsWidget.append(stack);
if (prefsWidget.show_all)
prefsWidget.show_all();
prefsWidget._stackSwitcher = stackSwitcher;
return prefsWidget;
}
_getLegacyPage(optionList, pageProperties) {
const page = new Gtk.ScrolledWindow(pageProperties);
const mainBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 5,
homogeneous: false,
margin_start: 30,
margin_end: 30,
margin_top: 12,
margin_bottom: 12,
});
let context = page.get_style_context();
context.add_class('background');
let frame;
let frameBox;
for (let item of optionList) {
// label can be plain text for Section Title
// or GtkBox for Option
const option = item[0];
const widget = item[1];
if (!widget) {
const lbl = new Gtk.Label({
label: option,
xalign: 0,
margin_bottom: 4,
});
context = lbl.get_style_context();
context.add_class('heading');
mainBox.append(lbl);
frame = new Gtk.Frame({
margin_bottom: 16,
});
frameBox = new Gtk.ListBox({
selection_mode: null,
});
mainBox.append(frame);
frame.set_child(frameBox);
continue;
}
const grid = new Gtk.Grid({
column_homogeneous: false,
column_spacing: 20,
margin_start: 8,
margin_end: 8,
margin_top: 8,
margin_bottom: 8,
hexpand: true,
});
grid.attach(option, 0, 0, 5, 1);
if (widget)
grid.attach(widget, 5, 0, 2, 1);
frameBox.append(grid);
}
page.set_child(mainBox);
return page;
}
};
const DropDownItem = GObject.registerClass({
GTypeName: 'DropdownItem',
Properties: { Properties: {
'text': GObject.ParamSpec.string( 'text': GObject.ParamSpec.string(
'text', 'text',
@ -622,10 +481,11 @@ const DropDownItem = GObject.registerClass({
'Id', 'Id',
'Item id stored in settings', 'Item id stored in settings',
GObject.ParamFlags.READWRITE, GObject.ParamFlags.READWRITE,
0, 100, 0 // min, max, default
-2147483648, 2147483647, 0
), ),
}, },
}, class DropDownItem extends GObject.Object { }, class DropDownItemVW extends GObject.Object {
get text() { get text() {
return this._text; return this._text;
} }
@ -641,5 +501,4 @@ const DropDownItem = GObject.registerClass({
set id(id) { set id(id) {
this._id = id; this._id = id;
} }
} });
);

View file

@ -10,79 +10,104 @@
'use strict'; 'use strict';
const { Clutter } = imports.gi; const Clutter = imports.gi.Clutter;
const Main = imports.ui.main; const Main = imports.ui.main;
const OsdWindow = imports.ui.osdWindow; const OsdWindow = imports.ui.osdWindow;
const Me = imports.misc.extensionUtils.getCurrentExtension(); let Me;
const _Util = Me.imports.lib.util;
const OsdPositions = {
1: {
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.START,
},
2: {
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.START,
},
3: {
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START,
},
4: {
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
},
5: {
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END,
},
6: {
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
},
7: {
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
},
};
let _overrides;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { let OsdPositions;
opt = Me.imports.lib.settings.opt;
const moduleEnabled = opt.get('osdWindowModule', true);
reset = reset || !moduleEnabled;
// don't even touch this module if disabled var OsdWindowModule = class {
if (_firstRun && reset) constructor(me) {
return; Me = me;
opt = Me.opt;
_firstRun = false; this._firstActivation = true;
this.moduleEnabled = false;
this._overrides = null;
if (_overrides) OsdPositions = {
_overrides.removeAll(); 1: {
x_align: Clutter.ActorAlign.START,
if (reset || !moduleEnabled) { y_align: Clutter.ActorAlign.START,
updateExistingOsdWindows(6); },
_overrides = null; 2: {
opt = null; x_align: Clutter.ActorAlign.CENTER,
return; y_align: Clutter.ActorAlign.START,
},
3: {
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START,
},
4: {
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
},
5: {
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END,
},
6: {
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
},
7: {
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
},
};
} }
_overrides = new _Util.Overrides(); cleanGlobals() {
_overrides.addOverride('osdWindow', OsdWindow.OsdWindow.prototype, OsdWindowCommon); Me = null;
} opt = null;
OsdPositions = null;
}
function updateExistingOsdWindows(position) { update(reset) {
position = position ? position : opt.OSD_POSITION; this.moduleEnabled = opt.get('osdWindowModule');
Main.osdWindowManager._osdWindows.forEach(osd => { const conflict = false;
osd.set(OsdPositions[position]);
}); reset = reset || !this.moduleEnabled || conflict;
}
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' OsdWindowModule - Keeping untouched');
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
this._overrides.addOverride('osdWindow', OsdWindow.OsdWindow.prototype, OsdWindowCommon);
console.debug(' OsdWindowModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
this._updateExistingOsdWindows(6);
console.debug(' WorkspaceSwitcherPopupModule - Disabled');
}
_updateExistingOsdWindows(position) {
position = position ? position : opt.OSD_POSITION;
Main.osdWindowManager._osdWindows.forEach(osd => {
osd.set(OsdPositions[position]);
});
}
};
const OsdWindowCommon = { const OsdWindowCommon = {
after_show() { after_show() {

View file

@ -9,81 +9,94 @@
*/ */
'use strict'; 'use strict';
const { GObject, Gio, GLib, Meta, St } = imports.gi;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const Me = imports.misc.extensionUtils.getCurrentExtension(); let Me;
const _Util = Me.imports.lib.util;
const _ = Me.imports.lib.settings._;
const shellVersion = _Util.shellVersion;
const WIN_SEARCH_PREFIX = Me.imports.lib.windowSearchProvider.prefix;
const RECENT_FILES_PREFIX = Me.imports.lib.recentFilesSearchProvider.prefix;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
let opt; let opt;
let _firstRun = true;
let _originalOverlayKeyHandlerId; var OverlayKeyModule = class {
let _overlayKeyHandlerId; constructor(me) {
Me = me;
opt = Me.opt;
function update(reset = false) { this._firstActivation = true;
opt = Me.imports.lib.settings.opt; this.moduleEnabled = false;
const moduleEnabled = opt.get('overlayKeyModule', true); this._originalOverlayKeyHandlerId = 0;
reset = reset || (!_firstRun && !moduleEnabled); this._overlayKeyHandlerId = 0;
}
// don't even touch this module if disabled cleanGlobals() {
if (_firstRun && !moduleEnabled) Me = null;
return;
_firstRun = false;
if (reset) {
_updateOverlayKey(reset);
opt = null; opt = null;
return;
} }
_updateOverlayKey(); update(reset) {
} this.moduleEnabled = opt.get('overlayKeyModule');
const conflict = false;
function _updateOverlayKey(reset = false) { reset = reset || !this.moduleEnabled || conflict;
if (reset) {
_restoreOverlayKeyHandler();
} else if (!_originalOverlayKeyHandlerId) {
_originalOverlayKeyHandlerId = GObject.signal_handler_find(global.display, { signalId: 'overlay-key' });
if (_originalOverlayKeyHandlerId !== null)
global.display.block_signal_handler(_originalOverlayKeyHandlerId);
_connectOverlayKey.bind(Main.overview._overview.controls)();
}
}
function _restoreOverlayKeyHandler() { if (reset && !this._firstActivation) {
// Disconnect modified overlay key handler this._disableModule();
if (_overlayKeyHandlerId !== null) { } else if (!reset) {
global.display.disconnect(_overlayKeyHandlerId); this._firstActivation = false;
_overlayKeyHandlerId = null; this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' OverlayKeyModule - Keeping untouched');
} }
// Unblock original overlay key handler _activateModule() {
if (_originalOverlayKeyHandlerId !== null) { if (!this._originalOverlayKeyHandlerId) {
global.display.unblock_signal_handler(_originalOverlayKeyHandlerId); this._originalOverlayKeyHandlerId = GObject.signal_handler_find(global.display, { signalId: 'overlay-key' });
_originalOverlayKeyHandlerId = null; if (this._originalOverlayKeyHandlerId !== null) {
global.display.block_signal_handler(this._originalOverlayKeyHandlerId);
this._connectOverlayKey();
}
}
console.debug(' OverlayKeyModule - Activated');
} }
}
function _connectOverlayKey() { _disableModule() {
this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA }); this._restoreOverlayKeyHandler();
this._lastOverlayKeyTime = 0; console.debug(' OverlayKeyModule - Disabled');
_overlayKeyHandlerId = global.display.connect('overlay-key', () => { }
_restoreOverlayKeyHandler() {
// Disconnect modified overlay key handler
if (this._overlayKeyHandlerId) {
global.display.disconnect(this._overlayKeyHandlerId);
this._overlayKeyHandlerId = 0;
}
// Unblock original overlay key handler
if (this._originalOverlayKeyHandlerId) {
global.display.unblock_signal_handler(this._originalOverlayKeyHandlerId);
this._originalOverlayKeyHandlerId = 0;
}
}
_connectOverlayKey() {
if (this._overlayKeyHandlerId)
return;
this._overlayKeyHandlerId = global.display.connect('overlay-key', this._onOverlayKeyPressed.bind(Main.overview._overview.controls));
}
_onOverlayKeyPressed() {
if (this._a11ySettings.get_boolean('stickykeys-enable')) if (this._a11ySettings.get_boolean('stickykeys-enable'))
return; return;
const { initialState, finalState, transitioning } = const { initialState, finalState, transitioning } =
this._stateAdjustment.getStateTransitionParams(); this._stateAdjustment.getStateTransitionParams();
const time = GLib.get_monotonic_time() / 1000; const time = GLib.get_monotonic_time() / 1000;
const timeDiff = time - this._lastOverlayKeyTime; const timeDiff = time - this._lastOverlayKeyTime;
@ -95,14 +108,61 @@ function _connectOverlayKey() {
const mode = opt.OVERLAY_KEY_SECONDARY; const mode = opt.OVERLAY_KEY_SECONDARY;
if (shouldShift) { if (shouldShift) {
if (mode === 1) Me.Util.activateSearchProvider('');
if (mode === 1) {
this._shiftState(Meta.MotionDirection.UP); this._shiftState(Meta.MotionDirection.UP);
else if (mode === 2) } else if (mode === 2) {
_Util.activateSearchProvider(WIN_SEARCH_PREFIX); Me.Util.activateSearchProvider(Me.WSP_PREFIX);
else if (mode === 3) } else if (mode === 3) {
_Util.activateSearchProvider(RECENT_FILES_PREFIX); // Changing the overview mode automatically changes the overview transition
opt.OVERVIEW_MODE = 0;
opt.OVERVIEW_MODE2 = false;
opt.WORKSPACE_MODE = 1;
}
} else { } else {
Main.overview.toggle(); if (Main.overview._shown) {
Main.overview.hide();
return;
}
switch (opt.OVERLAY_KEY_PRIMARY) {
case 0: // Disabled
return;
case 1: // Follow global overview mode
Main.overview.resetOverviewMode();
break;
case 2: // Default overview
opt.OVERVIEW_MODE = 0;
opt.OVERVIEW_MODE2 = false;
opt.WORKSPACE_MODE = 1;
break;
case 3: // Default overview
if (Main.overview._shown)
Main.overview.hide();
else
Main.overview.show(2);
return;
case 4: // Static WS preview
opt.OVERVIEW_MODE = 1;
opt.OVERVIEW_MODE2 = false;
if (!Main.overview._shown)
opt.WORKSPACE_MODE = 0;
break;
case 5: // Static WS
opt.OVERVIEW_MODE = 2;
opt.OVERVIEW_MODE2 = true;
opt.WORKSPACE_MODE = 0;
break;
case 6: // Window Search
opt.OVERVIEW_MODE = 2;
opt.OVERVIEW_MODE2 = true;
if (!Main.overview._shown)
opt.WORKSPACE_MODE = 0;
break;
}
const customOverviewMode = !Main.overview._shown;
Main.overview.toggle(customOverviewMode);
if (opt.OVERLAY_KEY_PRIMARY === 6)
Me.Util.activateSearchProvider(Me.WSP_PREFIX);
} }
}); }
} };

View file

@ -10,43 +10,113 @@
'use strict'; 'use strict';
const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const OverviewControls = imports.ui.overviewControls;
const Me = imports.misc.extensionUtils.getCurrentExtension(); let Me;
const _Util = Me.imports.lib.util;
let _overrides;
let opt; let opt;
function update(reset = false) { var OverviewModule = class {
if (_overrides) constructor(me) {
_overrides.removeAll(); Me = me;
opt = Me.opt;
this._firstActivation = true;
if (reset) { this.moduleEnabled = false;
_overrides = null; this._overrides = null;
opt = null;
return;
} }
opt = Me.imports.lib.settings.opt; cleanGlobals() {
_overrides = new _Util.Overrides(); Me = null;
opt = null;
}
_overrides.addOverride('Overview', Overview.Overview.prototype, OverviewCommon); update(reset) {
} this.moduleEnabled = true;
const conflict = false;
reset = reset || !this.moduleEnabled || conflict;
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' OverviewModule - Keeping untouched');
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
this._overrides.addOverride('Overview', Overview.Overview.prototype, OverviewCommon);
console.debug(' OverviewModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
console.debug(' OverviewModule - Disabled');
}
};
const OverviewCommon = { const OverviewCommon = {
show(state = OverviewControls.ControlsState.WINDOW_PICKER, customOverviewMode) {
if (!customOverviewMode)
this.resetOverviewMode();
if (state === OverviewControls.ControlsState.HIDDEN)
throw new Error('Invalid state, use hide() to hide');
if (this.isDummy)
return;
if (this._shown)
return;
this._shown = true;
if (!this._syncGrab())
return;
Main.layoutManager.showOverview();
this._animateVisible(state);
},
toggle(customOverviewMode) {
if (this.isDummy)
return;
if (this._visible)
this.hide();
else
this.show(OverviewControls.ControlsState.WINDOW_PICKER, customOverviewMode);
},
resetOverviewMode() {
// reset Overview Mode do default
opt.OVERVIEW_MODE = opt.get('overviewMode');
opt.OVERVIEW_MODE2 = opt.OVERVIEW_MODE === 2;
opt.WORKSPACE_MODE = opt.OVERVIEW_MODE > 0 ? 0 : 1;
},
_showDone() { _showDone() {
this._animationInProgress = false; this._animationInProgress = false;
this._coverPane.hide(); this._coverPane.hide();
this.emit('shown'); if (Me.shellVersion < 44)
this.emit('shown');
else if (this._shownState !== 'SHOWN')
this._changeShownState('SHOWN');
// Handle any calls to hide* while we were showing // Handle any calls to hide* while we were showing
if (!this._shown) if (!this._shown)
this._animateNotVisible(); this._animateNotVisible();
this._syncGrab();
// if user activates overview during startup animation, transition needs to be shifted to the state 2 here // if user activates overview during startup animation, transition needs to be shifted to the state 2 here
const controls = this._overview._controls; const controls = this._overview._controls;
if (controls._searchController._searchActive && controls._stateAdjustment.value === 1) { if (controls._searchController._searchActive && controls._stateAdjustment.value === 1) {
@ -55,5 +125,41 @@ const OverviewCommon = {
else if (!opt.OVERVIEW_MODE2) else if (!opt.OVERVIEW_MODE2)
controls._stateAdjustment.value = 2; controls._stateAdjustment.value = 2;
} }
this._syncGrab();
},
// Workaround - should probably be fixed elsewhere in the upstream code
// If a new window is opened from the overview
// and is realized before the overview animation is complete,
// the new window will not get focus
after__hideDone() {
if (!opt.FIX_NEW_WINDOW_FOCUS)
return;
const workspace = global.workspace_manager.get_active_workspace();
const recentDesktopWin = global.display.get_tab_list(1, workspace)[0];
let recentNormalWin = null;
const tabList = global.display.get_tab_list(0, workspace);
for (let i = 0; i < tabList.length; i++) {
if (tabList[i].minimized === false) {
recentNormalWin = tabList[i];
break;
}
}
let recentWin = recentNormalWin;
if (recentNormalWin && recentDesktopWin) {
recentWin = recentNormalWin.get_user_time() > recentDesktopWin.get_user_time()
? recentNormalWin
: recentDesktopWin;
}
const focusedWin = global.display.focus_window;
if (recentWin && focusedWin !== recentWin)
recentWin.activate(global.get_current_time());
}, },
}; };

File diff suppressed because it is too large Load diff

View file

@ -10,188 +10,247 @@
'use strict'; 'use strict';
const { GLib } = imports.gi; const Clutter = imports.gi.Clutter;
const Main = imports.ui.main; const Main = imports.ui.main;
const Me = imports.misc.extensionUtils.getCurrentExtension(); const Overview = imports.ui.overview;
const _Util = Me.imports.lib.util; const Panel = imports.ui.panel;
const ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
let Me;
let opt; let opt;
let _firstRun = true;
let _showingOverviewConId; const ANIMATION_TIME = Overview.ANIMATION_TIME;
let _hidingOverviewConId;
let _styleChangedConId;
function update(reset = false) { var PanelModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('panelModule', true); Me = me;
// Avoid conflict with other extensions opt = Me.opt;
const conflict = _Util.getEnabledExtensions('dash-to-panel').length ||
_Util.getEnabledExtensions('hidetopbar').length;
reset = reset || (!_firstRun && !moduleEnabled);
// don't even touch this module if disabled or in potential conflict this._firstActivation = true;
if (_firstRun && (reset || conflict)) this.moduleEnabled = false;
return; this._overrides = null;
_firstRun = false; this._showingOverviewConId = 0;
this._hidingOverviewConId = 0;
const panelBox = Main.layoutManager.panelBox; this._styleChangedConId = 0;
if (reset || !moduleEnabled) {
// _disconnectPanel();
reset = true;
_setPanelPosition(reset);
_updateOverviewConnection(reset);
_reparentPanel(false);
_updateStyleChangedConnection(reset);
panelBox.translation_y = 0;
Main.panel.opacity = 255;
_setPanelStructs(true);
return;
} }
_setPanelPosition(); cleanGlobals() {
_updateStyleChangedConnection(); Me = null;
opt = null;
}
if (opt.PANEL_MODE === 0) { update(reset) {
_updateOverviewConnection(true); this.moduleEnabled = opt.get('panelModule');
_reparentPanel(false); const conflict = Me.Util.getEnabledExtensions('dash-to-panel').length ||
panelBox.translation_y = 0; Me.Util.getEnabledExtensions('hidetopbar').length;
Main.panel.opacity = 255;
_setPanelStructs(true); if (conflict && !reset)
} else if (opt.PANEL_MODE === 1) { console.warn(`[${Me.metadata.name}] Warning: "Panel" module disabled due to potential conflict with another extension`);
if (opt.SHOW_WS_PREVIEW_BG) {
_reparentPanel(true); reset = reset || !this.moduleEnabled || conflict || Main.sessionMode.isLocked;
if (opt.OVERVIEW_MODE2) {
// in OM2 if the panel has been moved to the overviewGroup move panel above all // don't touch original code if module disabled
Main.layoutManager.overviewGroup.set_child_above_sibling(panelBox, null); if (reset && !this._firstActivation) {
_updateOverviewConnection(); this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' PanelModule - Keeping untouched');
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
const panelBox = Main.layoutManager.panelBox;
this._setPanelPosition();
this._updateStyleChangedConnection();
if (opt.PANEL_MODE === 0) {
this._updateOverviewConnection(true);
this._reparentPanel(false);
panelBox.translation_y = 0;
Main.panel.opacity = 255;
this._setPanelStructs(true);
} else if (opt.PANEL_MODE === 1) {
if (opt.SHOW_WS_PREVIEW_BG) {
this._reparentPanel(true);
if (opt.OVERVIEW_MODE2) {
// in OM2 if the panel has been moved to the overviewGroup move panel above all
Main.layoutManager.overviewGroup.set_child_above_sibling(panelBox, null);
this._updateOverviewConnection();
} else {
// otherwise move the panel below overviewGroup so it can get below workspacesDisplay
Main.layoutManager.overviewGroup.set_child_below_sibling(panelBox, Main.overview._overview);
this._updateOverviewConnection(true);
}
this._showPanel(true);
} else { } else {
// otherwise move the panel below overviewGroup so it can get below workspacesDisplay // if ws preview bg is disabled, panel can stay in uiGroup
Main.layoutManager.overviewGroup.set_child_below_sibling(panelBox, Main.overview._overview); this._reparentPanel(false);
_updateOverviewConnection(true); this._showPanel(false);
this._updateOverviewConnection();
} }
_showPanel(true); // _connectPanel();
} else { } else if (opt.PANEL_MODE === 2) {
// if ws preview bg is disabled, panel can stay in uiGroup this._updateOverviewConnection(true);
_reparentPanel(false); this._reparentPanel(false);
_showPanel(false); this._showPanel(false);
_updateOverviewConnection(); // _connectPanel();
} }
// _connectPanel(); this._setPanelStructs(opt.PANEL_MODE === 0);
} else if (opt.PANEL_MODE === 2) { Main.layoutManager._updateHotCorners();
_updateOverviewConnection(true);
_reparentPanel(false); this._overrides.addOverride('ActivitiesButton', Panel.ActivitiesButton.prototype, ActivitiesButton);
_showPanel(false);
// _connectPanel(); console.debug(' PanelModule - Activated');
} }
_setPanelStructs(opt.PANEL_MODE === 0);
Main.layoutManager._updateHotCorners();
}
function _setPanelPosition(reset = false) { _disableModule() {
const geometry = global.display.get_monitor_geometry(global.display.get_primary_monitor()); const reset = true;
const panelBox = Main.layoutManager.panelBox; this._setPanelPosition(reset);
const panelHeight = Main.panel.height; // panelBox height can be 0 after shell start this._updateOverviewConnection(reset);
this._reparentPanel(false);
if (opt.PANEL_POSITION_TOP || reset) this._updateStyleChangedConnection(reset);
panelBox.set_position(geometry.x, geometry.y);
else
panelBox.set_position(geometry.x, geometry.y + geometry.height - panelHeight);
}
function _updateStyleChangedConnection(reset = false) { const panelBox = Main.layoutManager.panelBox;
if (reset) { panelBox.translation_y = 0;
if (_styleChangedConId) {
Main.panel.disconnect(_styleChangedConId);
_styleChangedConId = 0;
}
} else if (!_styleChangedConId) {
Main.panel.connect('style-changed', () => {
if (opt.PANEL_MODE === 1)
Main.panel.add_style_pseudo_class('overview');
else if (opt.OVERVIEW_MODE2)
Main.panel.remove_style_pseudo_class('overview');
});
}
}
function _updateOverviewConnection(reset = false) {
if (reset) {
if (_hidingOverviewConId) {
Main.overview.disconnect(_hidingOverviewConId);
_hidingOverviewConId = 0;
}
if (_showingOverviewConId) {
Main.overview.disconnect(_showingOverviewConId);
_showingOverviewConId = 0;
}
} else {
if (!_hidingOverviewConId) {
_hidingOverviewConId = Main.overview.connect('hiding', () => {
if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2)
_showPanel(false);
});
}
if (!_showingOverviewConId) {
_showingOverviewConId = Main.overview.connect('showing', () => {
if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2 || Main.layoutManager.panelBox.translation_y)
_showPanel(true);
});
}
}
}
function _reparentPanel(reparent = false) {
const panel = Main.layoutManager.panelBox;
if (reparent && panel.get_parent() === Main.layoutManager.uiGroup) {
Main.layoutManager.uiGroup.remove_child(panel);
Main.layoutManager.overviewGroup.add_child(panel);
} else if (!reparent && panel.get_parent() === Main.layoutManager.overviewGroup) {
Main.layoutManager.overviewGroup.remove_child(panel);
// return the panel at default position, panel shouldn't cover objects that should be above
Main.layoutManager.uiGroup.insert_child_at_index(panel, 4);
}
}
function _setPanelStructs(state) {
Main.layoutManager._trackedActors.forEach(a => {
if (a.actor === Main.layoutManager.panelBox)
a.affectsStruts = state;
});
// workaround to force maximized windows to resize after removing affectsStruts
// simulation of minimal swipe gesture to the opposite direction
// todo - needs better solution!!!!!!!!!!!
// const direction = _getAppGridAnimationDirection() === 2 ? 1 : -1;
// Main.overview._swipeTracker._beginTouchSwipe(null, global.get_current_time(), 1, 1);
// Main.overview._swipeTracker._updateGesture(null, global.get_current_time(), direction, 1);
// GLib.timeout_add(0, 50, () => Main.overview._swipeTracker._endGesture(global.get_current_time(), 1, true));*/
}
function _showPanel(show = true) {
if (show) {
Main.panel.opacity = 255; Main.panel.opacity = 255;
Main.layoutManager.panelBox.ease({ this._setPanelStructs(true);
duration: ANIMATION_TIME, if (this._overrides)
translation_y: 0, this._overrides.removeAll();
onComplete: () => { this._overrides = null;
_setPanelStructs(opt.PANEL_MODE === 0);
}, console.debug(' PanelModule - Disabled');
});
} else {
const panelHeight = Main.panel.height;
Main.layoutManager.panelBox.ease({
duration: ANIMATION_TIME,
translation_y: opt.PANEL_POSITION_TOP ? -panelHeight + 1 : panelHeight - 1,
onComplete: () => {
Main.panel.opacity = 0;
_setPanelStructs(opt.PANEL_MODE === 0);
},
});
} }
}
_setPanelPosition(reset = false) {
const geometry = global.display.get_monitor_geometry(global.display.get_primary_monitor());
const panelBox = Main.layoutManager.panelBox;
const panelHeight = Main.panel.height; // panelBox height can be 0 after shell start
if (opt.PANEL_POSITION_TOP || reset)
panelBox.set_position(geometry.x, geometry.y);
else
panelBox.set_position(geometry.x, geometry.y + geometry.height - panelHeight);
}
_updateStyleChangedConnection(reset = false) {
if (reset) {
if (this._styleChangedConId) {
Main.panel.disconnect(this._styleChangedConId);
this._styleChangedConId = 0;
}
} else if (!this._styleChangedConId) {
this._styleChangedConId = Main.panel.connect('style-changed', () => {
if (opt.PANEL_MODE === 1 && !opt.OVERVIEW_MODE2)
Main.panel.add_style_pseudo_class('overview');
else if (opt.OVERVIEW_MODE2)
Main.panel.remove_style_pseudo_class('overview');
});
}
}
_updateOverviewConnection(reset = false) {
if (reset) {
if (this._hidingOverviewConId) {
Main.overview.disconnect(this._hidingOverviewConId);
this._hidingOverviewConId = 0;
}
if (this._showingOverviewConId) {
Main.overview.disconnect(this._showingOverviewConId);
this._showingOverviewConId = 0;
}
} else {
if (!this._hidingOverviewConId) {
this._hidingOverviewConId = Main.overview.connect('hiding', () => {
if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2)
this._showPanel(false);
});
}
if (!this._showingOverviewConId) {
this._showingOverviewConId = Main.overview.connect('showing', () => {
if (Main.layoutManager._startingUp)
return;
if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2 || Main.layoutManager.panelBox.translation_y)
this._showPanel(true);
});
}
}
}
_reparentPanel(reparent = false) {
const panel = Main.layoutManager.panelBox;
if (reparent && panel.get_parent() === Main.layoutManager.uiGroup) {
Main.layoutManager.uiGroup.remove_child(panel);
Main.layoutManager.overviewGroup.add_child(panel);
} else if (!reparent && panel.get_parent() === Main.layoutManager.overviewGroup) {
Main.layoutManager.overviewGroup.remove_child(panel);
// return the panel at default position, panel shouldn't cover objects that should be above
Main.layoutManager.uiGroup.insert_child_at_index(panel, 4);
}
}
_setPanelStructs(state) {
Main.layoutManager._trackedActors.forEach(a => {
if (a.actor === Main.layoutManager.panelBox)
a.affectsStruts = state;
});
// workaround to force maximized windows to resize after removing affectsStruts
// simulation of minimal swipe gesture to the opposite direction
// todo - needs better solution!!!!!!!!!!!
// const direction = _getAppGridAnimationDirection() === 2 ? 1 : -1;
// Main.overview._swipeTracker._beginTouchSwipe(null, global.get_current_time(), 1, 1);
// Main.overview._swipeTracker._updateGesture(null, global.get_current_time(), direction, 1);
// GLib.timeout_add(0, 50, () => Main.overview._swipeTracker._endGesture(global.get_current_time(), 1, true));*/
}
_showPanel(show = true) {
if (show) {
Main.panel.opacity = 255;
Main.layoutManager.panelBox.ease({
duration: ANIMATION_TIME,
translation_y: 0,
onComplete: () => {
this._setPanelStructs(opt.PANEL_MODE === 0);
},
});
} else {
const panelHeight = Main.panel.height;
Main.layoutManager.panelBox.ease({
duration: ANIMATION_TIME,
translation_y: opt.PANEL_POSITION_TOP ? -panelHeight + 1 : panelHeight - 1,
onComplete: () => {
Main.panel.opacity = 0;
this._setPanelStructs(opt.PANEL_MODE === 0);
},
});
}
}
};
const ActivitiesButton = {
vfunc_event(event) {
if (event.type() === Clutter.EventType.TOUCH_END ||
event.type() === Clutter.EventType.BUTTON_RELEASE) {
if (Main.overview.shouldToggleByCornerOrButton()) {
if (event.get_button() === Clutter.BUTTON_SECONDARY && !Main.overview.dash.showAppsButton.checked) {
Main.overview.show(2);
Main.overview.dash.showAppsButton.checked = true;
} else {
Main.overview.toggle();
}
}
} else if (event.type() === Clutter.EventType.SCROLL) {
Main.wm.handleWorkspaceScroll(event);
}
return Clutter.EVENT_PROPAGATE;
},
};

View file

@ -1,5 +1,5 @@
/** /**
* Vertical Workspaces * V-Shell (Vertical Workspaces)
* recentFilesSearchProvider.js * recentFilesSearchProvider.js
* *
* @author GdH <G-dH@github.com> * @author GdH <G-dH@github.com>
@ -9,116 +9,146 @@
'use strict'; 'use strict';
const { GLib, Gio, Meta, St, Shell, Gtk } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const RecentManager = imports.gi.Gtk.RecentManager;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Main = imports.ui.main; const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Settings = Me.imports.lib.settings;
const _Util = Me.imports.lib.util;
let Me;
let opt;
// gettext // gettext
const _ = Settings._; let _;
const shellVersion = Settings.shellVersion;
const ModifierType = imports.gi.Clutter.ModifierType;
let recentFilesSearchProvider;
let _enableTimeoutId = 0;
// prefix helps to eliminate results from other search providers // prefix helps to eliminate results from other search providers
// so it needs to be something less common // so it needs to be something less common
// needs to be accessible from vw module // needs to be accessible from vw module
var prefix = 'fq//'; const PREFIX = 'fq//';
var opt; var RecentFilesSearchProviderModule = class {
// export for other modules
static _PREFIX = PREFIX;
constructor(me) {
Me = me;
opt = Me.opt;
_ = Me.gettext;
function getOverviewSearchResult() { this._firstActivation = true;
return Main.overview._overview.controls._searchController._searchResults; this.moduleEnabled = false;
} this._recentFilesSearchProvider = null;
this._enableTimeoutId = 0;
}
cleanGlobals() {
function update(reset = false) { Me = null;
opt = Me.imports.lib.settings.opt;
if (!reset && opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED && !recentFilesSearchProvider) {
enable();
} else if (reset || !opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED) {
disable();
opt = null; opt = null;
_ = null;
} }
}
function enable() { update(reset) {
// delay because Fedora had problem to register a new provider soon after Shell restarts this.moduleEnabled = opt.get('recentFilesSearchProviderModule');
_enableTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, reset = reset || !this.moduleEnabled;
2000,
() => { if (reset && !this._firstActivation) {
if (!recentFilesSearchProvider) { this._disableModule();
recentFilesSearchProvider = new RecentFilesSearchProvider(opt); } else if (!reset) {
getOverviewSearchResult()._registerProvider(recentFilesSearchProvider); this._firstActivation = false;
} this._activateModule();
_enableTimeoutId = 0;
return GLib.SOURCE_REMOVE;
} }
); if (reset && this._firstActivation)
} console.debug(' RecentFilesSearchProviderModule - Keeping untouched');
function disable() {
if (recentFilesSearchProvider) {
getOverviewSearchResult()._unregisterProvider(recentFilesSearchProvider);
recentFilesSearchProvider = null;
} }
if (_enableTimeoutId) {
GLib.source_remove(_enableTimeoutId); _activateModule() {
_enableTimeoutId = 0; // delay because Fedora had problem to register a new provider soon after Shell restarts
this._enableTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
2000,
() => {
if (!this._recentFilesSearchProvider) {
this._recentFilesSearchProvider = new RecentFilesSearchProvider(opt);
this._getOverviewSearchResult()._registerProvider(this._recentFilesSearchProvider);
}
this._enableTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
);
console.debug(' RecentFilesSearchProviderModule - Activated');
} }
}
function makeResult(window, i) { _disableModule() {
const app = Shell.WindowTracker.get_default().get_window_app(window); if (this._recentFilesSearchProvider) {
const appName = app ? app.get_name() : 'Unknown'; this._getOverviewSearchResult()._unregisterProvider(this._recentFilesSearchProvider);
const windowTitle = window.get_title(); this._recentFilesSearchProvider = null;
const wsIndex = window.get_workspace().index(); }
if (this._enableTimeoutId) {
GLib.source_remove(this._enableTimeoutId);
this._enableTimeoutId = 0;
}
return { console.debug(' RecentFilesSearchProviderModule - Disabled');
'id': i, }
// convert all accented chars to their basic form and lower case for search
'name': `${wsIndex + 1}: ${windowTitle} ${appName}`.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(),
appName,
windowTitle,
window,
};
}
const closeSelectedRegex = /^\/x!$/; _getOverviewSearchResult() {
const closeAllResultsRegex = /^\/xa!$/; return Main.overview._overview.controls._searchController._searchResults;
const moveToWsRegex = /^\/m[0-9]+$/; }
const moveAllToWsRegex = /^\/ma[0-9]+$/; };
const RecentFilesSearchProvider = class RecentFilesSearchProvider { class RecentFilesSearchProvider {
constructor() { constructor() {
this.id = 'org.gnome.Nautilus.desktop'; this.id = 'recent-files';
this.appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -ws recent:///', 'Recent Files', null); const appSystem = Shell.AppSystem.get_default();
// this.appInfo = Shell.AppSystem.get_default().lookup_app('org.gnome.Nautilus.desktop').appInfo; let appInfo = appSystem.lookup_app('org.gnome.Nautilus.desktop')?.get_app_info();
this.appInfo.get_description = () => _('Search recent files'); if (!appInfo)
this.appInfo.get_name = () => _('Recent Files'); appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -w', _('Recent Files'), null);
this.appInfo.get_id = () => this.id; appInfo.get_description = () => _('Search recent files');
this.appInfo.get_icon = () => Gio.icon_new_for_string('document-open-recent-symbolic'); appInfo.get_name = () => _('Recent Files');
this.appInfo.should_show = () => true; appInfo.get_id = () => 'org.gnome.Nautilus.desktop';
appInfo.get_icon = () => Gio.icon_new_for_string('document-open-recent-symbolic');
appInfo.should_show = () => true;
this.appInfo = appInfo;
this.canLaunchSearch = true; this.canLaunchSearch = true;
this.isRemoteProvider = false; this.isRemoteProvider = false;
} }
getInitialResultSet(terms, callback /* , cancellable = null*/) {
// In GS 43 callback arg has been removed
/* if (Me.shellVersion >= 43)
cancellable = callback; */
const filesDict = {};
let files = [];
if (terms[0].startsWith(PREFIX))
files = RecentManager.get_default().get_items();
// Detect whether time stamps are in int, or in GLib.DateTime object
this._timeNeedsConversion = files[0]?.get_modified().to_unix;
for (let file of files)
filesDict[file.get_uri()] = file;
this.files = filesDict;
if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(this._getResultSet(terms)));
else
callback(this._getResultSet(terms));
return null;
}
_getResultSet(terms) { _getResultSet(terms) {
if (!terms[0].startsWith(prefix)) if (!terms[0].startsWith(PREFIX))
return []; return [];
// do not modify original terms // do not modify original terms
let termsCopy = [...terms]; let termsCopy = [...terms];
// search for terms without prefix // search for terms without prefix
termsCopy[0] = termsCopy[0].replace(prefix, ''); termsCopy[0] = termsCopy[0].replace(PREFIX, '');
const candidates = this.files; const candidates = this.files;
const _terms = [].concat(termsCopy); const _terms = [].concat(termsCopy);
@ -135,15 +165,18 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
const file = this.files[id]; const file = this.files[id];
const name = `${file.get_age()}d: ${file.get_display_name()} ${file.get_uri_display().replace(`/${file.get_display_name()}`, '')}`; const name = `${file.get_age()}d: ${file.get_display_name()} ${file.get_uri_display().replace(`/${file.get_display_name()}`, '')}`;
if (opt.SEARCH_FUZZY) if (opt.SEARCH_FUZZY)
m = _Util.fuzzyMatch(term, name); m = Me.Util.fuzzyMatch(term, name);
else else
m = _Util.strictMatch(term, name); m = Me.Util.strictMatch(term, name);
if (m !== -1) if (m !== -1)
results.push({ weight: m, id }); results.push({ weight: m, id });
} }
results.sort((a, b) => this.files[a.id].get_visited() < this.files[b.id].get_visited()); if (this._timeNeedsConversion)
results.sort((a, b) => this.files[a.id].get_modified().to_unix() < this.files[b.id].get_modified().to_unix());
else
results.sort((a, b) => this.files[a.id].get_modified() < this.files[b.id].get_modified());
this.resultIds = results.map(item => item.id); this.resultIds = results.map(item => item.id);
return this.resultIds; return this.resultIds;
@ -151,7 +184,7 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
getResultMetas(resultIds, callback = null) { getResultMetas(resultIds, callback = null) {
const metas = resultIds.map(id => this.getResultMeta(id)); const metas = resultIds.map(id => this.getResultMeta(id));
if (shellVersion >= 43) if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(metas)); return new Promise(resolve => resolve(metas));
else if (callback) else if (callback)
callback(metas); callback(metas);
@ -172,89 +205,54 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
} }
getIcon(result, size) { getIcon(result, size) {
let file = Gio.File.new_for_uri(result.get_uri());
let info = file.query_info(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH,
Gio.FileQueryInfoFlags.NONE, null);
let path = info.get_attribute_byte_string(
Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH);
let icon, gicon; let icon, gicon;
if (path) { const appInfo = Gio.AppInfo.get_default_for_type(result.get_mime_type(), false);
gicon = Gio.FileIcon.new(Gio.File.new_for_path(path)); if (appInfo)
} else { gicon = appInfo.get_icon();
const appInfo = Gio.AppInfo.get_default_for_type(result.get_mime_type(), false);
if (appInfo)
gicon = appInfo.get_icon();
}
if (gicon) if (gicon)
icon = new St.Icon({ gicon, icon_size: size }); icon = new St.Icon({ gicon, icon_size: size });
else else
icon = new St.Icon({ icon_name: 'icon-missing', icon_size: size }); icon = new St.Icon({ icon_name: 'icon-missing', icon_size: size });
return icon; return icon;
} }
launchSearch(/* terms, timeStamp */) { launchSearch(terms, timeStamp) {
this._openNautilus('recent:///'); const appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -w recent:///', 'Nautilus', null);
appInfo.launch([], global.create_app_launch_context(timeStamp, -1));
} }
_openNautilus(uri) { activateResult(resultId, terms, timeStamp) {
try { const uri = resultId;
GLib.spawn_command_line_async(`nautilus -ws ${uri}`); const context = global.create_app_launch_context(timeStamp, -1);
} catch (e) { if (Me.Util.isShiftPressed()) {
log(e);
}
}
activateResult(resultId /* , terms, timeStamp */) {
const file = this.files[resultId];
if (_Util.isShiftPressed()) {
Main.overview.toggle(); Main.overview.toggle();
this._openNautilus(file.get_uri()); this.appInfo.launch_uris([uri], context);
} else if (Gio.app_info_launch_default_for_uri(uri, context)) {
// update recent list after (hopefully) successful activation
const recentManager = RecentManager.get_default();
recentManager.add_item(resultId);
} else { } else {
const appInfo = Gio.AppInfo.get_default_for_type(file.get_mime_type(), false); this.appInfo.launch_uris([uri], context);
if (!(appInfo && appInfo.launch_uris([file.get_uri()], null)))
this._openNautilus(file.get_uri());
} }
} }
getInitialResultSet(terms, callback /* , cancellable = null*/) { filterResults(results /* , maxResults*/) {
// In GS 43 callback arg has been removed
/* if (shellVersion >= 43)
cancellable = callback; */
const filesDict = {};
const files = Gtk.RecentManager.get_default().get_items().filter(f => f.exists());
for (let file of files)
filesDict[file.get_uri()] = file;
this.files = filesDict;
if (shellVersion >= 43)
return new Promise(resolve => resolve(this._getResultSet(terms)));
else
callback(this._getResultSet(terms));
return null;
}
filterResults(results, maxResults) {
return results.slice(0, 20);
// return results.slice(0, maxResults); // return results.slice(0, maxResults);
return results.slice(0, 20);
} }
getSubsearchResultSet(previousResults, terms, callback /* , cancellable*/) { getSubsearchResultSet(previousResults, terms, callback) {
// if we return previous results, quick typers get non-actual results if (Me.shellVersion < 43) {
this.getSubsearchResultSet42(terms, callback);
return null;
}
return this.getInitialResultSet(terms);
}
getSubsearchResultSet42(terms, callback) {
callback(this._getResultSet(terms)); callback(this._getResultSet(terms));
} }
}
/* createResultObject(resultMeta) {
return this.files[resultMeta.id];
}*/
};

View file

@ -9,92 +9,137 @@
*/ */
'use strict'; 'use strict';
const { Shell, Gio, St, Clutter } = imports.gi;
const Main = imports.ui.main; const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Search = imports.ui.search; const Search = imports.ui.search;
const Me = imports.misc.extensionUtils.getCurrentExtension(); let Me;
const _Util = Me.imports.lib.util; // gettext
let _;
const _ = Me.imports.lib.settings._;
const shellVersion = _Util.shellVersion;
let opt; let opt;
let _overrides;
let _firstRun = true;
let SEARCH_MAX_WIDTH; let SEARCH_MAX_WIDTH;
function update(reset = false) { var SearchModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('searchModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
_ = Me.gettext;
// don't even touch this module if disabled this._firstActivation = true;
if (_firstRun && reset) this.moduleEnabled = false;
return; this._overrides = null;
}
_firstRun = false; cleanGlobals() {
Me = null;
if (_overrides)
_overrides.removeAll();
_updateSearchViewWidth(reset);
if (reset) {
Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
opt = null; opt = null;
_overrides = null; _ = null;
return;
} }
_overrides = new _Util.Overrides(); update(reset) {
this.moduleEnabled = opt.get('searchModule');
const conflict = false;
_overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider); reset = reset || !this.moduleEnabled || conflict;
_overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
_overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
// Don't expand the search view vertically and align it to the top // don't touch the original code if module disabled
// this is important in the static workspace mode when the search view bg is not transparent if (reset && !this._firstActivation) {
// also the "Searching..." and "No Results" notifications will be closer to the search entry, with the distance given by margin-top in the stylesheet this._disableModule();
Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.START; } else if (!reset) {
} this._firstActivation = false;
this._activateModule();
function _updateSearchViewWidth(reset = false) { }
const searchContent = Main.overview._overview._controls.layoutManager._searchController._searchResults._content; if (reset && this._firstActivation)
if (!SEARCH_MAX_WIDTH) { // just store original value; console.debug(' SearchModule - Keeping untouched');
const themeNode = searchContent.get_theme_node();
const width = themeNode.get_max_width();
SEARCH_MAX_WIDTH = width;
} }
if (reset) { _activateModule() {
searchContent.set_style(''); this._updateSearchViewWidth();
} else {
let width = Math.round(SEARCH_MAX_WIDTH * opt.SEARCH_VIEW_SCALE); if (!this._overrides)
searchContent.set_style(`max-width: ${width}px;`); this._overrides = new Me.Util.Overrides();
this._overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider);
this._overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
this._overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
this._overrides.addOverride('ProviderInfo', Search.ProviderInfo.prototype, ProviderInfo);
// Don't expand the search view vertically and align it to the top
// this is important in the static workspace mode when the search view bg is not transparent
// also the "Searching..." and "No Results" notifications will be closer to the search entry, with the distance given by margin-top in the stylesheet
Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.START;
console.debug(' SearchModule - Activated');
} }
}
_disableModule() {
const reset = true;
this._updateSearchViewWidth(reset);
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
console.debug(' WorkspaceSwitcherPopupModule - Disabled');
}
_updateSearchViewWidth(reset = false) {
const searchContent = Main.overview._overview._controls.layoutManager._searchController._searchResults._content;
if (!SEARCH_MAX_WIDTH) { // just store original value;
const themeNode = searchContent.get_theme_node();
const width = themeNode.get_max_width();
SEARCH_MAX_WIDTH = width;
}
if (reset) {
searchContent.set_style('');
} else {
let width = Math.round(SEARCH_MAX_WIDTH * opt.SEARCH_VIEW_SCALE);
searchContent.set_style(`max-width: ${width}px;`);
}
}
};
// AppDisplay.AppSearchProvider // AppDisplay.AppSearchProvider
const AppSearchProvider = { const AppSearchProvider = {
getInitialResultSet(terms, callback, _cancellable) { getInitialResultSet(terms, callback, cancellable) {
// Defer until the parental controls manager is initialized, so the // Defer until the parental controls manager is initialized, so the
// results can be filtered correctly. // results can be filtered correctly.
if (!this._parentalControlsManager.initialized) { if (!this._parentalControlsManager.initialized) {
let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => { if (Me.shellVersion < 43) {
if (this._parentalControlsManager.initialized) { let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
this._parentalControlsManager.disconnect(initializedId); if (this._parentalControlsManager.initialized) {
this.getInitialResultSet(terms, callback, _cancellable); this._parentalControlsManager.disconnect(initializedId);
} this.getInitialResultSet(terms, callback, cancellable);
}); }
return; });
return null;
} else {
// callback has been removed in 43
cancellable = callback;
return new Promise(resolve => {
let initializedId = this._parentalControlsManager.connect('app-filter-changed', async () => {
if (this._parentalControlsManager.initialized) {
this._parentalControlsManager.disconnect(initializedId);
resolve(await this.getInitialResultSet(terms, cancellable));
}
});
});
}
} }
const pattern = terms.join(' '); const pattern = terms.join(' ');
let appInfoList = Shell.AppSystem.get_default().get_installed(); let appInfoList = Shell.AppSystem.get_default().get_installed();
let weightList = {}; let weightList = {};
@ -113,22 +158,25 @@ const AppSearchProvider = {
shouldShow = appInfo.should_show() && this._parentalControlsManager.shouldShowApp(appInfo); shouldShow = appInfo.should_show() && this._parentalControlsManager.shouldShowApp(appInfo);
if (shouldShow) { if (shouldShow) {
let id = appInfo.get_id().split('.');
id = id[id.length - 2] || '';
let baseName = appInfo.get_string('Name') || '';
let dispName = appInfo.get_display_name() || ''; let dispName = appInfo.get_display_name() || '';
let gName = appInfo.get_generic_name() || ''; let gName = appInfo.get_generic_name() || '';
let description = appInfo.get_description() || ''; let description = appInfo.get_description() || '';
let categories = appInfo.get_string('Categories') || ''; let categories = appInfo.get_string('Categories') || '';
let keywords = appInfo.get_string('Keywords') || ''; let keywords = appInfo.get_string('Keywords') || '';
name = dispName; name = `${dispName} ${id}`;
string = `${dispName} ${gName} ${description} ${categories} ${keywords}`; string = `${dispName} ${gName} ${baseName} ${description} ${categories} ${keywords} ${id}`;
} }
} }
let m = -1; let m = -1;
if (shouldShow && opt.SEARCH_FUZZY) { if (shouldShow && opt.SEARCH_FUZZY) {
m = _Util.fuzzyMatch(pattern, name); m = Me.Util.fuzzyMatch(pattern, name);
m = (m + _Util.strictMatch(pattern, string)) / 2; m = (m + Me.Util.strictMatch(pattern, string)) / 2;
} else if (shouldShow) { } else if (shouldShow) {
m = _Util.strictMatch(pattern, string); m = Me.Util.strictMatch(pattern, string);
} }
if (m !== -1) if (m !== -1)
@ -143,16 +191,18 @@ const AppSearchProvider = {
// sort apps by usage list // sort apps by usage list
appInfoList.sort((a, b) => usage.compare(a.get_id(), b.get_id())); appInfoList.sort((a, b) => usage.compare(a.get_id(), b.get_id()));
// prefer apps where any word in their name starts with the pattern // prefer apps where any word in their name starts with the pattern
appInfoList.sort((a, b) => _Util.isMoreRelevant(a.get_display_name(), b.get_display_name(), pattern)); appInfoList.sort((a, b) => Me.Util.isMoreRelevant(a.get_display_name(), b.get_display_name(), pattern));
let results = appInfoList.map(app => app.get_id()); let results = appInfoList.map(app => app.get_id());
results = results.concat(this._systemActions.getMatchingActions(terms)); results = results.concat(this._systemActions.getMatchingActions(terms));
if (shellVersion < 43) if (Me.shellVersion < 43) {
callback(results); callback(results);
else return null;
} else {
return new Promise(resolve => resolve(results)); return new Promise(resolve => resolve(results));
}
}, },
// App search result size // App search result size
@ -181,12 +231,69 @@ const SearchResult = {
St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText); St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
} }
// don't close overview if Shift key is pressed - Shift moves windows to the workspace // don't close overview if Shift key is pressed - Shift moves windows to the workspace
if (!_Util.isShiftPressed()) if (!Me.Util.isShiftPressed())
Main.overview.toggle(); Main.overview.toggle();
}, },
}; };
const SearchResultsView = { const SearchResultsView = {
_doSearch() {
if (!this._doProviderSearch) {
this._doSearchLegacy();
return;
}
this._startingSearch = false;
let previousResults = this._results;
this._results = {};
this._providers.forEach(provider => {
const onlyVShellProviders = this._terms.includes('wq//') || this._terms.includes('fq//');
if (!onlyVShellProviders || (onlyVShellProviders && (provider.id.includes('open-windows') || provider.id.includes('recent-files')))) {
let previousProviderResults = previousResults[provider.id];
this._doProviderSearch(provider, previousProviderResults);
}
});
this._updateSearchProgress();
this._clearSearchTimeout();
},
_doSearchLegacy() {
this._startingSearch = false;
let previousResults = this._results;
this._results = {};
this._providers.forEach(provider => {
const onlyVShellProviders = this._terms.includes('wq//') || this._terms.includes('fq//');
if (!onlyVShellProviders || (onlyVShellProviders && (provider.id.includes('open-windows') || provider.id.includes('recent-files')))) {
provider.searchInProgress = true;
let previousProviderResults = previousResults[provider.id];
if (this._isSubSearch && previousProviderResults) {
provider.getSubsearchResultSet(previousProviderResults,
this._terms,
results => {
this._gotResults(results, provider);
},
this._cancellable);
} else {
provider.getInitialResultSet(this._terms,
results => {
this._gotResults(results, provider);
},
this._cancellable);
}
}
});
this._updateSearchProgress();
this._clearSearchTimeout();
},
_updateSearchProgress() { _updateSearchProgress() {
let haveResults = this._providers.some(provider => { let haveResults = this._providers.some(provider => {
let display = provider.display; let display = provider.display;
@ -204,3 +311,13 @@ const SearchResultsView = {
} }
}, },
}; };
// fixes app is null error if search provider id is not a desktop app id.
const ProviderInfo = {
animateLaunch() {
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app(this.provider.appInfo.get_id());
if (app && app.state === Shell.AppState.STOPPED)
IconGrid.zoomOutActor(this._content);
},
};

View file

@ -0,0 +1,94 @@
/**
* V-Shell (Vertical Workspaces)
* searchController.js
*
* @author GdH <G-dH@github.com>
* @copyright 2022 - 2023
* @license GPL-3.0
*
*/
'use strict';
const Clutter = imports.gi.Clutter;
const Main = imports.ui.main;
let Me;
let opt;
var SearchControllerModule = class {
constructor(me) {
Me = me;
opt = Me.opt;
this._firstActivation = true;
this.moduleEnabled = false;
this._originalOnStageKeyPress = null;
}
cleanGlobals() {
Me = null;
opt = null;
}
update(reset) {
this.moduleEnabled = opt.get('searchControllerModule');
const conflict = false;
reset = reset || !this.moduleEnabled || conflict;
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' SearchControllerModule - Keeping untouched');
}
_activateModule() {
if (!this._originalOnStageKeyPress)
this._originalOnStageKeyPress = Main.overview._overview.controls._searchController._onStageKeyPress;
Main.overview._overview.controls._searchController._onStageKeyPress = SearchControllerCommon._onStageKeyPress;
console.debug(' SearchControllerModule - Activated');
}
_disableModule() {
if (this._originalOnStageKeyPress)
Main.overview._overview.controls._searchController._onStageKeyPress = this._originalOnStageKeyPress;
this._originalOnStageKeyPress = null;
console.debug(' SearchControlerModule - Disabled');
}
};
// if opt.ESC_BEHAVIOR > 0 force close the overview
const SearchControllerCommon = {
_onStageKeyPress(actor, event) {
// Ignore events while anything but the overview has
// pushed a modal (system modals, looking glass, ...)
if (Main.modalCount > 1)
return Clutter.EVENT_PROPAGATE;
let symbol = event.get_key_symbol();
if (symbol === Clutter.KEY_Escape) {
if (this._searchActive && !opt.ESC_BEHAVIOR) {
this.reset();
} else if (this._showAppsButton.checked && !opt.ESC_BEHAVIOR) {
this._showAppsButton.checked = false;
} else {
this.reset();
Main.overview.hide();
}
return Clutter.EVENT_STOP;
} else if (this._shouldTriggerSearch(symbol)) {
this.startSearch(event);
}
return Clutter.EVENT_PROPAGATE;
},
};

View file

@ -9,25 +9,15 @@
'use strict'; 'use strict';
const { GLib } = imports.gi; const GLib = imports.gi.GLib;
const Config = imports.misc.config; let Me;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
var shellVersion = parseFloat(Config.PACKAGE_VERSION);
const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']);
var _ = Gettext.gettext;
const _schema = Me.metadata['settings-schema'];
// common instance of Options accessible from all modules
var opt;
var Options = class Options { var Options = class Options {
constructor() { constructor(me) {
this._gsettings = ExtensionUtils.getSettings(_schema); Me = me;
this._gsettings = Me.gSettings;
this._connectionIds = []; this._connectionIds = [];
this._writeTimeoutId = 0; this._writeTimeoutId = 0;
this._gsettings.delay(); this._gsettings.delay();
@ -51,8 +41,8 @@ var Options = class Options {
wsMaxSpacing: ['int', 'ws-max-spacing'], wsMaxSpacing: ['int', 'ws-max-spacing'],
wsPreviewScale: ['int', 'ws-preview-scale'], wsPreviewScale: ['int', 'ws-preview-scale'],
secWsPreviewScale: ['int', 'secondary-ws-preview-scale'], secWsPreviewScale: ['int', 'secondary-ws-preview-scale'],
secWsPreviewShift: ['bool', 'secondary-ws-preview-shift'], secWsPreviewShift: ['boolean', 'secondary-ws-preview-shift'],
wsThumbnailsFull: ['bool', 'ws-thumbnails-full'], wsThumbnailsFull: ['boolean', 'ws-thumbnails-full'],
secWsThumbnailsPosition: ['int', 'secondary-ws-thumbnails-position'], secWsThumbnailsPosition: ['int', 'secondary-ws-thumbnails-position'],
dashPosition: ['int', 'dash-position'], dashPosition: ['int', 'dash-position'],
dashPositionAdjust: ['int', 'dash-position-adjust'], dashPositionAdjust: ['int', 'dash-position-adjust'],
@ -64,6 +54,7 @@ var Options = class Options {
dashMaxIconSize: ['int', 'dash-max-icon-size'], dashMaxIconSize: ['int', 'dash-max-icon-size'],
dashShowWindowsIcon: ['int', 'dash-show-windows-icon'], dashShowWindowsIcon: ['int', 'dash-show-windows-icon'],
dashShowRecentFilesIcon: ['int', 'dash-show-recent-files-icon'], dashShowRecentFilesIcon: ['int', 'dash-show-recent-files-icon'],
dashShowExtensionsIcon: ['int', 'dash-show-extensions-icon'],
centerDashToWs: ['boolean', 'center-dash-to-ws'], centerDashToWs: ['boolean', 'center-dash-to-ws'],
showAppsIconPosition: ['int', 'show-app-icon-position'], showAppsIconPosition: ['int', 'show-app-icon-position'],
wsThumbnailScale: ['int', 'ws-thumbnail-scale'], wsThumbnailScale: ['int', 'ws-thumbnail-scale'],
@ -73,13 +64,17 @@ var Options = class Options {
centerSearch: ['boolean', 'center-search'], centerSearch: ['boolean', 'center-search'],
centerAppGrid: ['boolean', 'center-app-grid'], centerAppGrid: ['boolean', 'center-app-grid'],
dashBgOpacity: ['int', 'dash-bg-opacity'], dashBgOpacity: ['int', 'dash-bg-opacity'],
dashBgColor: ['int', 'dash-bg-color'],
dashBgRadius: ['int', 'dash-bg-radius'], dashBgRadius: ['int', 'dash-bg-radius'],
dashBgGS3Style: ['boolean', 'dash-bg-gs3-style'],
runningDotStyle: ['int', 'running-dot-style'],
enablePageShortcuts: ['boolean', 'enable-page-shortcuts'], enablePageShortcuts: ['boolean', 'enable-page-shortcuts'],
showWsSwitcherBg: ['boolean', 'show-ws-switcher-bg'], showWsSwitcherBg: ['boolean', 'show-ws-switcher-bg'],
showWsPreviewBg: ['boolean', 'show-ws-preview-bg'], showWsPreviewBg: ['boolean', 'show-ws-preview-bg'],
wsPreviewBgRadius: ['int', 'ws-preview-bg-radius'], wsPreviewBgRadius: ['int', 'ws-preview-bg-radius'],
showBgInOverview: ['boolean', 'show-bg-in-overview'], showBgInOverview: ['boolean', 'show-bg-in-overview'],
overviewBgBrightness: ['int', 'overview-bg-brightness'], overviewBgBrightness: ['int', 'overview-bg-brightness'],
searchBgBrightness: ['int', 'search-bg-brightness'],
overviewBgBlurSigma: ['int', 'overview-bg-blur-sigma'], overviewBgBlurSigma: ['int', 'overview-bg-blur-sigma'],
appGridBgBlurSigma: ['int', 'app-grid-bg-blur-sigma'], appGridBgBlurSigma: ['int', 'app-grid-bg-blur-sigma'],
smoothBlurTransitions: ['boolean', 'smooth-blur-transitions'], smoothBlurTransitions: ['boolean', 'smooth-blur-transitions'],
@ -87,9 +82,8 @@ var Options = class Options {
searchViewAnimation: ['int', 'search-view-animation'], searchViewAnimation: ['int', 'search-view-animation'],
workspaceAnimation: ['int', 'workspace-animation'], workspaceAnimation: ['int', 'workspace-animation'],
animationSpeedFactor: ['int', 'animation-speed-factor'], animationSpeedFactor: ['int', 'animation-speed-factor'],
fixUbuntuDock: ['boolean', 'fix-ubuntu-dock'],
winPreviewIconSize: ['int', 'win-preview-icon-size'], winPreviewIconSize: ['int', 'win-preview-icon-size'],
alwaysShowWinTitles: ['boolean', 'always-show-win-titles'], winTitlePosition: ['int', 'win-title-position'],
startupState: ['int', 'startup-state'], startupState: ['int', 'startup-state'],
overviewMode: ['int', 'overview-mode'], overviewMode: ['int', 'overview-mode'],
workspaceSwitcherAnimation: ['int', 'workspace-switcher-animation'], workspaceSwitcherAnimation: ['int', 'workspace-switcher-animation'],
@ -105,17 +99,18 @@ var Options = class Options {
appGridContent: ['int', 'app-grid-content'], appGridContent: ['int', 'app-grid-content'],
appGridIncompletePages: ['boolean', 'app-grid-incomplete-pages'], appGridIncompletePages: ['boolean', 'app-grid-incomplete-pages'],
appGridOrder: ['int', 'app-grid-order'], appGridOrder: ['int', 'app-grid-order'],
appFolderOrder: ['int', 'app-folder-order'],
appGridNamesMode: ['int', 'app-grid-names'], appGridNamesMode: ['int', 'app-grid-names'],
appGridActivePreview: ['boolean', 'app-grid-active-preview'], appGridActivePreview: ['boolean', 'app-grid-active-preview'],
appGridFolderCenter: ['boolean', 'app-grid-folder-center'], appGridFolderCenter: ['boolean', 'app-grid-folder-center'],
appGridPageWidthScale: ['int', 'app-grid-page-width-scale'], appGridPageWidthScale: ['int', 'app-grid-page-width-scale'],
appGridSpacing: ['int', 'app-grid-spacing'], appGridSpacing: ['int', 'app-grid-spacing'],
searchWindowsEnable: ['boolean', 'search-windows-enable'], searchWindowsOrder: ['int', 'search-windows-order'],
searchRecentFilesEnable: ['boolean', 'search-recent-files-enable'],
searchFuzzy: ['boolean', 'search-fuzzy'], searchFuzzy: ['boolean', 'search-fuzzy'],
searchMaxResultsRows: ['int', 'search-max-results-rows'], searchMaxResultsRows: ['int', 'search-max-results-rows'],
dashShowWindowsBeforeActivation: ['int', 'dash-show-windows-before-activation'], dashShowWindowsBeforeActivation: ['int', 'dash-show-windows-before-activation'],
dashIconScroll: ['int', 'dash-icon-scroll'], dashIconScroll: ['int', 'dash-icon-scroll'],
dashIsolateWorkspaces: ['boolean', 'dash-isolate-workspaces'],
searchWindowsIconScroll: ['int', 'search-windows-icon-scroll'], searchWindowsIconScroll: ['int', 'search-windows-icon-scroll'],
panelVisibility: ['int', 'panel-visibility'], panelVisibility: ['int', 'panel-visibility'],
panelPosition: ['int', 'panel-position'], panelPosition: ['int', 'panel-position'],
@ -123,6 +118,8 @@ var Options = class Options {
wsSwPopupHPosition: ['int', 'ws-sw-popup-h-position'], wsSwPopupHPosition: ['int', 'ws-sw-popup-h-position'],
wsSwPopupVPosition: ['int', 'ws-sw-popup-v-position'], wsSwPopupVPosition: ['int', 'ws-sw-popup-v-position'],
wsSwPopupMode: ['int', 'ws-sw-popup-mode'], wsSwPopupMode: ['int', 'ws-sw-popup-mode'],
wsSwitcherWraparound: ['boolean', 'ws-switcher-wraparound'],
wsSwitcherIgnoreLast: ['boolean', 'ws-switcher-ignore-last'],
favoritesNotify: ['int', 'favorites-notify'], favoritesNotify: ['int', 'favorites-notify'],
notificationPosition: ['int', 'notification-position'], notificationPosition: ['int', 'notification-position'],
osdPosition: ['int', 'osd-position'], osdPosition: ['int', 'osd-position'],
@ -131,17 +128,26 @@ var Options = class Options {
hotCornerFullscreen: ['boolean', 'hot-corner-fullscreen'], hotCornerFullscreen: ['boolean', 'hot-corner-fullscreen'],
hotCornerRipples: ['boolean', 'hot-corner-ripples'], hotCornerRipples: ['boolean', 'hot-corner-ripples'],
alwaysActivateSelectedWindow: ['boolean', 'always-activate-selected-window'], alwaysActivateSelectedWindow: ['boolean', 'always-activate-selected-window'],
windowIconClickSearch: ['boolean', 'window-icon-click-search'], winPreviewSecBtnAction: ['int', 'win-preview-sec-mouse-btn-action'],
winPreviewMidBtnAction: ['int', 'win-preview-mid-mouse-btn-action'],
winPreviewShowCloseButton: ['boolean', 'win-preview-show-close-button'],
windowIconClickAction: ['int', 'window-icon-click-action'],
overlayKeyPrimary: ['int', 'overlay-key-primary'],
overlayKeySecondary: ['int', 'overlay-key-secondary'], overlayKeySecondary: ['int', 'overlay-key-secondary'],
overviewEscBehavior: ['int', 'overview-esc-behavior'],
newWindowFocusFix: ['boolean', 'new-window-focus-fix'],
appGridPerformance: ['boolean', 'app-grid-performance'],
windowThumbnailScale: ['int', 'window-thumbnail-scale'],
workspaceThumbnailsModule: ['boolean', 'workspace-thumbnails-module'],
workspaceSwitcherPopupModule: ['boolean', 'workspace-switcher-popup-module'], workspaceSwitcherPopupModule: ['boolean', 'workspace-switcher-popup-module'],
workspaceAnimationModule: ['boolean', 'workspace-animation-module'], workspaceAnimationModule: ['boolean', 'workspace-animation-module'],
workspaceModule: ['boolean', 'workspace-module'], workspaceModule: ['boolean', 'workspace-module'],
windowManagerModule: ['boolean', 'window-manager-module'], windowManagerModule: ['boolean', 'window-manager-module'],
windowPreviewModule: ['boolean', 'window-preview-module'], windowPreviewModule: ['boolean', 'window-preview-module'],
winAttentionHandlerModule: ['boolean', 'win-attention-handler-module'], windowAttentionHandlerModule: ['boolean', 'win-attention-handler-module'],
windowThumbnailModule: ['boolean', 'window-thumbnail-module'],
swipeTrackerModule: ['boolean', 'swipe-tracker-module'], swipeTrackerModule: ['boolean', 'swipe-tracker-module'],
searchControllerModule: ['boolean', 'search-controller-module'],
searchModule: ['boolean', 'search-module'], searchModule: ['boolean', 'search-module'],
panelModule: ['boolean', 'panel-module'], panelModule: ['boolean', 'panel-module'],
overlayKeyModule: ['boolean', 'overlay-key-module'], overlayKeyModule: ['boolean', 'overlay-key-module'],
@ -151,6 +157,9 @@ var Options = class Options {
dashModule: ['boolean', 'dash-module'], dashModule: ['boolean', 'dash-module'],
appFavoritesModule: ['boolean', 'app-favorites-module'], appFavoritesModule: ['boolean', 'app-favorites-module'],
appDisplayModule: ['boolean', 'app-display-module'], appDisplayModule: ['boolean', 'app-display-module'],
windowSearchProviderModule: ['boolean', 'window-search-provider-module'],
recentFilesSearchProviderModule: ['boolean', 'recent-files-search-provider-module'],
extensionsSearchProviderModule: ['boolean', 'extensions-search-provider-module'],
profileName1: ['string', 'profile-name-1'], profileName1: ['string', 'profile-name-1'],
profileName2: ['string', 'profile-name-2'], profileName2: ['string', 'profile-name-2'],
@ -158,9 +167,10 @@ var Options = class Options {
profileName4: ['string', 'profile-name-4'], profileName4: ['string', 'profile-name-4'],
}; };
this.cachedOptions = {}; this.cachedOptions = {};
}
this.shellVersion = shellVersion; cleanGlobals() {
// this.storeProfile(0); Me = null;
} }
connect(name, callback) { connect(name, callback) {
@ -183,7 +193,7 @@ var Options = class Options {
get(option, updateCache = false) { get(option, updateCache = false) {
if (!this.options[option]) { if (!this.options[option]) {
log(`[${Me.metadata.name}] Error: Option ${option} is undefined.`); console.error(`[${Me.metadata.name}] Error: Option ${option} is undefined.`);
return null; return null;
} }
@ -195,7 +205,6 @@ var Options = class Options {
else else
gSettings = this._gsettings; gSettings = this._gsettings;
this.cachedOptions[option] = gSettings.get_value(key).deep_unpack(); this.cachedOptions[option] = gSettings.get_value(key).deep_unpack();
} }
@ -242,7 +251,8 @@ var Options = class Options {
storeProfile(index) { storeProfile(index) {
const profile = {}; const profile = {};
Object.keys(this.options).forEach(v => { Object.keys(this.options).forEach(v => {
profile[v] = this.get(v).toString(); if (!v.startsWith('profileName'))
profile[v] = this.get(v).toString();
}); });
this._gsettings.set_value(`profile-data-${index}`, new GLib.Variant('a{ss}', profile)); this._gsettings.set_value(`profile-data-${index}`, new GLib.Variant('a{ss}', profile));
@ -250,8 +260,14 @@ var Options = class Options {
loadProfile(index) { loadProfile(index) {
const options = this._gsettings.get_value(`profile-data-${index}`).deep_unpack(); const options = this._gsettings.get_value(`profile-data-${index}`).deep_unpack();
// set the aaa-loading-data so extension.js doesn't reset V-Shell after each profile item
// delayed gsettings writes are processed alphabetically, so this key will be processed first
this._gsettings.set_boolean('aaa-loading-profile', !this._gsettings.get_boolean('aaa-loading-profile')); this._gsettings.set_boolean('aaa-loading-profile', !this._gsettings.get_boolean('aaa-loading-profile'));
for (let o of Object.keys(options)) { for (let o of Object.keys(options)) {
if (!this.options[o]) {
console.error(`[${Me.metadata.name}] Error: "${o}" is not a valid profile key -> Update your profile`);
continue;
}
const [type] = this.options[o]; const [type] = this.options[o];
let value = options[o]; let value = options[o];
switch (type) { switch (type) {
@ -275,7 +291,14 @@ var Options = class Options {
} }
_updateSettings() { _updateSettings() {
this.DASH_POSITION = this.get('dashPosition', true); this._updateCachedSettings();
this.DASH_BG_ALPHA = this.get('dashBgOpacity') / 100;
this.DASH_BG_OPACITY = this.get('dashBgOpacity') * 2.5;
this.DASH_BG_COLOR = this.get('dashBgColor');
this.DASH_BG_RADIUS = this.get('dashBgRadius');
this.DASH_BG_LIGHT = this.DASH_BG_COLOR === 1;
this.DASH_BG_GS3_STYLE = this.get('dashBgGS3Style');
this.DASH_POSITION = this.get('dashModule') ? this.get('dashPosition') : 2;
this.DASH_TOP = this.DASH_POSITION === 0; this.DASH_TOP = this.DASH_POSITION === 0;
this.DASH_RIGHT = this.DASH_POSITION === 1; this.DASH_RIGHT = this.DASH_POSITION === 1;
this.DASH_BOTTOM = this.DASH_POSITION === 2; this.DASH_BOTTOM = this.DASH_POSITION === 2;
@ -284,26 +307,35 @@ var Options = class Options {
this.DASH_VISIBLE = this.DASH_POSITION !== 4; // 4 - disable this.DASH_VISIBLE = this.DASH_POSITION !== 4; // 4 - disable
this.DASH_FOLLOW_RECENT_WIN = false; this.DASH_FOLLOW_RECENT_WIN = false;
this.DASH_CLICK_ACTION = this.get('dashShowWindowsBeforeActivation', true); this.DASH_ISOLATE_WS = this.get('dashIsolateWorkspaces');
this.DASH_ICON_SCROLL = this.get('dashIconScroll', true);
this.DASH_CLICK_ACTION = this.get('dashShowWindowsBeforeActivation');
this.DASH_CLICK_SWITCH_BEFORE_ACTIVATION = this.DASH_CLICK_ACTION === 1;
this.DASH_CLICK_OPEN_NEW_WIN = this.DASH_CLICK_ACTION === 2;
this.DASH_CLICK_PREFER_WORKSPACE = this.DASH_CLICK_ACTION === 3;
this.DASH_ICON_SCROLL = this.get('dashIconScroll');
this.DASH_SHIFT_CLICK_MV = true; this.DASH_SHIFT_CLICK_MV = true;
this.SEARCH_WINDOWS_ICON_SCROLL = this.get('searchWindowsIconScroll', true); this.RUNNING_DOT_STYLE = this.get('runningDotStyle');
this.DASH_POSITION_ADJUSTMENT = this.get('dashPositionAdjust', true); this.SEARCH_WINDOWS_ICON_SCROLL = this.get('searchWindowsIconScroll');
this.DASH_POSITION_ADJUSTMENT = this.get('dashPositionAdjust');
this.DASH_POSITION_ADJUSTMENT = this.DASH_POSITION_ADJUSTMENT * -1 / 100; // range 1 to -1 this.DASH_POSITION_ADJUSTMENT = this.DASH_POSITION_ADJUSTMENT * -1 / 100; // range 1 to -1
this.CENTER_DASH_WS = this.get('centerDashToWs', true); this.CENTER_DASH_WS = this.get('centerDashToWs');
this.MAX_ICON_SIZE = 64; // updates from main module this.MAX_ICON_SIZE = this.get('dashMaxIconSize');
this.SHOW_WINDOWS_ICON = this.get('dashShowWindowsIcon', true); this.SHOW_WINDOWS_ICON = this.get('dashShowWindowsIcon');
this.SHOW_RECENT_FILES_ICON = this.get('dashShowRecentFilesIcon', true); this.SHOW_RECENT_FILES_ICON = this.get('dashShowRecentFilesIcon');
this.SHOW_EXTENSIONS_ICON = this.get('dashShowExtensionsIcon');
this.WS_TMB_POSITION = this.get('workspaceThumbnailsPosition', true); this.WS_TMB_POSITION = this.get('workspaceThumbnailsPosition');
this.ORIENTATION = this.WS_TMB_POSITION > 4 ? 0 : 1; this.ORIENTATION = this.WS_TMB_POSITION > 4 ? 0 : 1;
this.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing', true); this.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing');
// ORIENTATION || DASH_LEFT || DASH_RIGHT ? 350 : 80; // ORIENTATION || DASH_LEFT || DASH_RIGHT ? 350 : 80;
this.SHOW_WS_TMB = ![4, 9].includes(this.WS_TMB_POSITION); // 4, 9 - disable this.SHOW_WS_TMB = ![4, 9].includes(this.WS_TMB_POSITION); // 4, 9 - disable
this.WS_TMB_FULL = this.get('wsThumbnailsFull', true); this.WS_TMB_FULL = this.get('wsThumbnailsFull');
// translate ws tmb position to 0 top, 1 right, 2 bottom, 3 left // translate ws tmb position to 0 top, 1 right, 2 bottom, 3 left
// 0L 1R, 2LF, 3RF, 4DV, 5T, 6B, 7TF, 8BF, 9DH // 0L 1R, 2LF, 3RF, 4DV, 5T, 6B, 7TF, 8BF, 9DH
this.WS_TMB_POSITION = [3, 1, 3, 1, 4, 0, 2, 0, 2, 8][this.WS_TMB_POSITION]; this.WS_TMB_POSITION = [3, 1, 3, 1, 4, 0, 2, 0, 2, 8][this.WS_TMB_POSITION];
@ -311,81 +343,104 @@ var Options = class Options {
this.WS_TMB_RIGHT = this.WS_TMB_POSITION === 1; this.WS_TMB_RIGHT = this.WS_TMB_POSITION === 1;
this.WS_TMB_BOTTOM = this.WS_TMB_POSITION === 2; this.WS_TMB_BOTTOM = this.WS_TMB_POSITION === 2;
this.WS_TMB_LEFT = this.WS_TMB_POSITION === 3; this.WS_TMB_LEFT = this.WS_TMB_POSITION === 3;
this.WS_TMB_POSITION_ADJUSTMENT = this.get('wsTmbPositionAdjust', true) * -1 / 100; // range 1 to -1 this.WS_TMB_POSITION_ADJUSTMENT = this.get('wsTmbPositionAdjust') * -1 / 100; // range 1 to -1
this.SEC_WS_TMB_POSITION = this.get('secWsThumbnailsPosition', true); this.SEC_WS_TMB_POSITION = this.get('secWsThumbnailsPosition');
this.SHOW_SEC_WS_TMB = this.SEC_WS_TMB_POSITION !== 3 && this.SHOW_WS_TMB; this.SHOW_SEC_WS_TMB = this.SEC_WS_TMB_POSITION !== 3 && this.SHOW_WS_TMB;
this.SEC_WS_TMB_TOP = (this.SEC_WS_TMB_POSITION === 0 && !this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_TOP); this.SEC_WS_TMB_TOP = (this.SEC_WS_TMB_POSITION === 0 && !this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_TOP);
this.SEC_WS_TMB_RIGHT = (this.SEC_WS_TMB_POSITION === 1 && this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_RIGHT); this.SEC_WS_TMB_RIGHT = (this.SEC_WS_TMB_POSITION === 1 && this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_RIGHT);
this.SEC_WS_TMB_BOTTOM = (this.SEC_WS_TMB_POSITION === 1 && !this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_BOTTOM); this.SEC_WS_TMB_BOTTOM = (this.SEC_WS_TMB_POSITION === 1 && !this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_BOTTOM);
this.SEC_WS_TMB_LEFT = (this.SEC_WS_TMB_POSITION === 0 && this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_LEFT); this.SEC_WS_TMB_LEFT = (this.SEC_WS_TMB_POSITION === 0 && this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_LEFT);
this.SEC_WS_TMB_POSITION_ADJUSTMENT = this.get('secWsTmbPositionAdjust', true) * -1 / 100; // range 1 to -1 this.SEC_WS_TMB_POSITION_ADJUSTMENT = this.get('secWsTmbPositionAdjust') * -1 / 100; // range 1 to -1
this.SEC_WS_PREVIEW_SHIFT = this.get('secWsPreviewShift', true); this.SEC_WS_PREVIEW_SHIFT = this.get('secWsPreviewShift');
this.SHOW_WST_LABELS = this.get('showWsTmbLabels', true); this.SHOW_WST_LABELS = this.get('showWsTmbLabels');
this.SHOW_WST_LABELS_ON_HOVER = this.get('showWsTmbLabelsOnHover', true); this.SHOW_WST_LABELS_ON_HOVER = this.get('showWsTmbLabelsOnHover');
this.CLOSE_WS_BUTTON_MODE = this.get('closeWsButtonMode', true); this.CLOSE_WS_BUTTON_MODE = this.get('closeWsButtonMode');
this.MAX_THUMBNAIL_SCALE = this.get('wsThumbnailScale', true) / 100; this.MAX_THUMBNAIL_SCALE = this.get('wsThumbnailScale') / 100;
this.MAX_THUMBNAIL_SCALE_APPGRID = this.get('wsThumbnailScaleAppGrid', true) / 100; if (this.MAX_THUMBNAIL_SCALE === 0) {
if (this.MAX_THUMBNAIL_SCALE_APPGRID === 0) this.MAX_THUMBNAIL_SCALE = 0.01;
this.MAX_THUMBNAIL_SCALE_APPGRID = this.MAX_THUMBNAIL_SCALE; this.SHOW_WS_TMB = false;
}
this.MAX_THUMBNAIL_SCALE_APPGRID = this.get('wsThumbnailScaleAppGrid') / 100;
this.SHOW_WS_TMB_APPGRID = true;
if (this.MAX_THUMBNAIL_SCALE_APPGRID === 0) {
this.MAX_THUMBNAIL_SCALE_APPGRID = 0.01;
this.SHOW_WS_TMB_APPGRID = false;
}
this.MAX_THUMBNAIL_SCALE_STABLE = this.MAX_THUMBNAIL_SCALE === this.MAX_THUMBNAIL_SCALE_APPGRID; this.MAX_THUMBNAIL_SCALE_STABLE = this.MAX_THUMBNAIL_SCALE === this.MAX_THUMBNAIL_SCALE_APPGRID;
this.SEC_MAX_THUMBNAIL_SCALE = this.get('secWsThumbnailScale', true) / 100;
this.WS_PREVIEW_SCALE = this.get('wsPreviewScale', true) / 100; this.SEC_MAX_THUMBNAIL_SCALE = this.get('secWsThumbnailScale') / 100;
this.SEC_WS_PREVIEW_SCALE = this.get('secWsPreviewScale', true) / 100; if (this.SEC_MAX_THUMBNAIL_SCALE === 0) {
this.SEC_MAX_THUMBNAIL_SCALE = 0.01;
this.SHOW_SEC_WS_TMB = false;
}
this.WS_PREVIEW_SCALE = this.get('wsPreviewScale') / 100;
this.SEC_WS_PREVIEW_SCALE = this.get('secWsPreviewScale') / 100;
// calculate number of possibly visible neighbor previews according to ws scale // calculate number of possibly visible neighbor previews according to ws scale
this.NUMBER_OF_VISIBLE_NEIGHBORS = Math.round(1 + (1 - this.WS_PREVIEW_SCALE) / 4); this.NUMBER_OF_VISIBLE_NEIGHBORS = Math.round(1 + (1 - this.WS_PREVIEW_SCALE) / 4);
this.SHOW_WS_TMB_BG = this.get('showWsSwitcherBg', true) && this.SHOW_WS_TMB; this.SHOW_WS_TMB_BG = this.get('showWsSwitcherBg') && this.SHOW_WS_TMB;
this.WS_PREVIEW_BG_RADIUS = this.get('wsPreviewBgRadius', true); this.WS_PREVIEW_BG_RADIUS = this.get('wsPreviewBgRadius');
this.SHOW_WS_PREVIEW_BG = this.get('showWsPreviewBg', true); this.SHOW_WS_PREVIEW_BG = this.get('showWsPreviewBg');
this.CENTER_APP_GRID = this.get('centerAppGrid', true); this.CENTER_APP_GRID = this.get('centerAppGrid');
this.SHOW_SEARCH_ENTRY = this.get('showSearchEntry', true); this.SHOW_SEARCH_ENTRY = this.get('showSearchEntry');
this.CENTER_SEARCH_VIEW = this.get('centerSearch', true); this.CENTER_SEARCH_VIEW = this.get('centerSearch');
this.APP_GRID_ANIMATION = this.get('appGridAnimation', true); this.APP_GRID_ANIMATION = this.get('appGridAnimation');
if (this.APP_GRID_ANIMATION === 4) if (this.APP_GRID_ANIMATION === 4)
this.APP_GRID_ANIMATION = this._getAnimationDirection(); this.APP_GRID_ANIMATION = this._getAnimationDirection();
this.SEARCH_VIEW_ANIMATION = this.get('searchViewAnimation', true); this.SEARCH_VIEW_ANIMATION = this.get('searchViewAnimation');
if (this.SEARCH_VIEW_ANIMATION === 4) if (this.SEARCH_VIEW_ANIMATION === 4)
this.SEARCH_VIEW_ANIMATION = 3; this.SEARCH_VIEW_ANIMATION = 3;
this.WS_ANIMATION = this.get('workspaceAnimation', true); this.WS_ANIMATION = this.get('workspaceAnimation');
this.WIN_PREVIEW_ICON_SIZE = [64, 48, 32, 22, 8][this.get('winPreviewIconSize', true)]; this.WIN_PREVIEW_ICON_SIZE = [64, 48, 32, 22, 8][this.get('winPreviewIconSize')];
this.ALWAYS_SHOW_WIN_TITLES = this.get('alwaysShowWinTitles', true); this.WIN_TITLES_POSITION = this.get('winTitlePosition');
this.ALWAYS_SHOW_WIN_TITLES = this.WIN_TITLES_POSITION === 1;
this.STARTUP_STATE = this.get('startupState', true); this.STARTUP_STATE = this.get('startupState');
this.SHOW_BG_IN_OVERVIEW = this.get('showBgInOverview', true); this.SHOW_BG_IN_OVERVIEW = this.get('showBgInOverview');
this.OVERVIEW_BG_BRIGHTNESS = this.get('overviewBgBrightness', true) / 100; this.OVERVIEW_BG_BRIGHTNESS = this.get('overviewBgBrightness') / 100;
this.OVERVIEW_BG_BLUR_SIGMA = this.get('overviewBgBlurSigma', true); this.SEARCH_BG_BRIGHTNESS = this.get('searchBgBrightness') / 100;
this.APP_GRID_BG_BLUR_SIGMA = this.get('appGridBgBlurSigma', true); this.OVERVIEW_BG_BLUR_SIGMA = this.get('overviewBgBlurSigma');
this.SMOOTH_BLUR_TRANSITIONS = this.get('smoothBlurTransitions', true); this.APP_GRID_BG_BLUR_SIGMA = this.get('appGridBgBlurSigma');
this.SMOOTH_BLUR_TRANSITIONS = this.get('smoothBlurTransitions');
this.OVERVIEW_MODE = this.get('overviewMode', true); this.OVERVIEW_MODE = this.get('overviewMode');
this.OVERVIEW_MODE2 = this.OVERVIEW_MODE === 2; this.OVERVIEW_MODE2 = this.OVERVIEW_MODE === 2;
this.WORKSPACE_MODE = this.OVERVIEW_MODE ? 0 : 1; this.WORKSPACE_MODE = this.OVERVIEW_MODE ? 0 : 1;
this.STATIC_WS_SWITCHER_BG = this.get('workspaceSwitcherAnimation', true); this.STATIC_WS_SWITCHER_BG = this.get('workspaceSwitcherAnimation');
this.ANIMATION_TIME_FACTOR = this.get('animationSpeedFactor', true) / 100; this.ANIMATION_TIME_FACTOR = this.get('animationSpeedFactor') / 100;
this.SEARCH_ICON_SIZE = this.get('searchIconSize', true); this.SEARCH_ICON_SIZE = this.get('searchIconSize');
this.SEARCH_VIEW_SCALE = this.get('searchViewScale', true) / 100; this.SEARCH_VIEW_SCALE = this.get('searchViewScale') / 100;
this.SEARCH_MAX_ROWS = this.get('searchMaxResultsRows', true); this.SEARCH_MAX_ROWS = this.get('searchMaxResultsRows');
this.SEARCH_FUZZY = this.get('searchFuzzy', true); this.SEARCH_FUZZY = this.get('searchFuzzy');
this.APP_GRID_ALLOW_INCOMPLETE_PAGES = this.get('appGridIncompletePages', true); this.APP_GRID_ALLOW_INCOMPLETE_PAGES = this.get('appGridIncompletePages');
this.APP_GRID_ICON_SIZE = this.get('appGridIconSize', true); this.APP_GRID_ICON_SIZE = this.get('appGridIconSize');
this.APP_GRID_COLUMNS = this.get('appGridColumns', true); this.APP_GRID_COLUMNS = this.get('appGridColumns');
this.APP_GRID_ROWS = this.get('appGridRows', true); this.APP_GRID_ROWS = this.get('appGridRows');
this.APP_GRID_ADAPTIVE = !this.APP_GRID_COLUMNS && !this.APP_GRID_ROWS; this.APP_GRID_ADAPTIVE = !this.APP_GRID_COLUMNS && !this.APP_GRID_ROWS;
this.APP_GRID_ORDER = this.get('appGridOrder', true);
this.APP_GRID_INCLUDE_DASH = this.get('appGridContent', true); this.APP_GRID_ORDER = this.get('appGridOrder');
this.APP_GRID_ALPHABET = [1, 2].includes(this.APP_GRID_ORDER);
this.APP_GRID_FOLDERS_FIRST = this.APP_GRID_ORDER === 1;
this.APP_GRID_FOLDERS_LAST = this.APP_GRID_ORDER === 2;
this.APP_GRID_USAGE = this.APP_GRID_ORDER === 3;
this.APP_FOLDER_ORDER = this.get('appFolderOrder');
this.APP_FOLDER_ALPHABET = this.APP_FOLDER_ORDER === 1;
this.APP_FOLDER_USAGE = this.APP_FOLDER_ORDER === 2;
this.APP_GRID_INCLUDE_DASH = this.get('appGridContent');
/* APP_GRID_INCLUDE_DASH /* APP_GRID_INCLUDE_DASH
0 - Include All 0 - Include All
1 - Include All - Favorites and Runnings First 1 - Include All - Favorites and Runnings First
@ -397,46 +452,50 @@ var Options = class Options {
this.APP_GRID_EXCLUDE_RUNNING = this.APP_GRID_INCLUDE_DASH === 3 || this.APP_GRID_INCLUDE_DASH === 4; this.APP_GRID_EXCLUDE_RUNNING = this.APP_GRID_INCLUDE_DASH === 3 || this.APP_GRID_INCLUDE_DASH === 4;
this.APP_GRID_DASH_FIRST = this.APP_GRID_INCLUDE_DASH === 1; this.APP_GRID_DASH_FIRST = this.APP_GRID_INCLUDE_DASH === 1;
this.APP_GRID_NAMES_MODE = this.get('appGridNamesMode', true); this.APP_GRID_NAMES_MODE = this.get('appGridNamesMode');
this.APP_GRID_FOLDER_ICON_SIZE = this.get('appGridFolderIconSize', true); this.APP_GRID_FOLDER_ICON_SIZE = this.get('appGridFolderIconSize');
this.APP_GRID_FOLDER_ICON_GRID = this.get('appGridFolderIconGrid', true); this.APP_GRID_FOLDER_ICON_GRID = this.get('appGridFolderIconGrid');
this.APP_GRID_FOLDER_COLUMNS = this.get('appGridFolderColumns', true); this.APP_GRID_FOLDER_COLUMNS = this.get('appGridFolderColumns');
this.APP_GRID_FOLDER_ROWS = this.get('appGridFolderRows', true); this.APP_GRID_FOLDER_ROWS = this.get('appGridFolderRows');
this.APP_GRID_SPACING = this.get('appGridSpacing', true); this.APP_GRID_SPACING = this.get('appGridSpacing');
this.APP_GRID_FOLDER_DEFAULT = this.APP_GRID_FOLDER_ROWS === 3 && this.APP_GRID_FOLDER_COLUMNS === 3; this.APP_GRID_FOLDER_DEFAULT = this.APP_GRID_FOLDER_ROWS === 3 && this.APP_GRID_FOLDER_COLUMNS === 3;
this.APP_GRID_ACTIVE_PREVIEW = this.get('appGridActivePreview', true); this.APP_GRID_FOLDER_ADAPTIVE = !this.APP_GRID_FOLDER_COLUMNS && !this.APP_GRID_FOLDER_ROWS;
this.APP_GRID_FOLDER_CENTER = this.get('appGridFolderCenter', true); this.APP_GRID_ACTIVE_PREVIEW = this.get('appGridActivePreview');
this.APP_GRID_PAGE_WIDTH_SCALE = this.get('appGridPageWidthScale', true) / 100; this.APP_GRID_FOLDER_CENTER = this.get('appGridFolderCenter');
this.APP_GRID_PAGE_WIDTH_SCALE = this.get('appGridPageWidthScale') / 100;
this.APP_GRID_ICON_SIZE_DEFAULT = this.APP_GRID_ACTIVE_PREVIEW && !this.APP_GRID_ORDER ? 176 : 96; this.APP_GRID_ICON_SIZE_DEFAULT = this.APP_GRID_ACTIVE_PREVIEW && !this.APP_GRID_USAGE ? 176 : 96;
this.APP_GRID_FOLDER_ICON_SIZE_DEFAULT = 96; this.APP_GRID_FOLDER_ICON_SIZE_DEFAULT = 96;
this.WINDOW_SEARCH_PROVIDER_ENABLED = this.get('searchWindowsEnable', true); this.APP_GRID_PERFORMANCE = this.get('appGridPerformance');
this.RECENT_FILES_SEARCH_PROVIDER_ENABLED = this.get('searchRecentFilesEnable', true);
this.PANEL_POSITION_TOP = this.get('panelPosition', true) === 0; this.WINDOW_SEARCH_ORDER = this.get('searchWindowsOrder');
this.PANEL_MODE = this.get('panelVisibility', true);
this.PANEL_POSITION_TOP = this.get('panelPosition') === 0;
this.PANEL_MODE = this.get('panelVisibility');
this.PANEL_DISABLED = this.PANEL_MODE === 2; this.PANEL_DISABLED = this.PANEL_MODE === 2;
this.PANEL_OVERVIEW_ONLY = this.PANEL_MODE === 1; this.PANEL_OVERVIEW_ONLY = this.PANEL_MODE === 1;
this.START_Y_OFFSET = 0; // set from main module this.START_Y_OFFSET = 0; // set from main module
this.FIX_UBUNTU_DOCK = this.get('fixUbuntuDock', true);
this.WINDOW_ATTENTION_MODE = this.get('windowAttentionMode', true); this.WINDOW_ATTENTION_MODE = this.get('windowAttentionMode');
this.WINDOW_ATTENTION_DISABLE_NOTIFICATIONS = this.WINDOW_ATTENTION_MODE === 1; this.WINDOW_ATTENTION_DISABLE_NOTIFICATIONS = this.WINDOW_ATTENTION_MODE === 1;
this.WINDOW_ATTENTION_FOCUS_IMMEDIATELY = this.WINDOW_ATTENTION_MODE === 2; this.WINDOW_ATTENTION_FOCUS_IMMEDIATELY = this.WINDOW_ATTENTION_MODE === 2;
this.WS_SW_POPUP_H_POSITION = this.get('wsSwPopupHPosition', true) / 100; this.WS_SW_POPUP_H_POSITION = this.get('wsSwPopupHPosition') / 100;
this.WS_SW_POPUP_V_POSITION = this.get('wsSwPopupVPosition', true) / 100; this.WS_SW_POPUP_V_POSITION = this.get('wsSwPopupVPosition') / 100;
this.WS_SW_POPUP_MODE = this.get('wsSwPopupMode', true); this.WS_SW_POPUP_MODE = this.get('wsSwPopupMode');
this.SHOW_FAV_NOTIFICATION = this.get('favoritesNotify', true); this.WS_WRAPAROUND = this.get('wsSwitcherWraparound');
this.NOTIFICATION_POSITION = this.get('notificationPosition', true); this.WS_IGNORE_LAST = this.get('wsSwitcherIgnoreLast');
this.OSD_POSITION = this.get('osdPosition', true); this.SHOW_FAV_NOTIFICATION = this.get('favoritesNotify');
this.NOTIFICATION_POSITION = this.get('notificationPosition');
this.HOT_CORNER_ACTION = this.get('hotCornerAction', true); this.OSD_POSITION = this.get('osdPosition');
this.HOT_CORNER_POSITION = this.get('hotCornerPosition', true);
this.HOT_CORNER_ACTION = this.get('hotCornerAction');
this.HOT_CORNER_POSITION = this.get('hotCornerPosition');
if (this.HOT_CORNER_POSITION === 6 && this.DASH_VISIBLE) if (this.HOT_CORNER_POSITION === 6 && this.DASH_VISIBLE)
this.HOT_CORNER_EDGE = true; this.HOT_CORNER_EDGE = true;
else else
@ -451,13 +510,24 @@ var Options = class Options {
else else
this.HOT_CORNER_POSITION = 0; this.HOT_CORNER_POSITION = 0;
} }
this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen', true); this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen');
this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples', true); this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples');
this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow', true); this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow');
this.WINDOW_ICON_CLICK_SEARCH = this.get('windowIconClickSearch', true); this.WIN_PREVIEW_SEC_BTN_ACTION = this.get('winPreviewSecBtnAction');
this.WIN_PREVIEW_MID_BTN_ACTION = this.get('winPreviewMidBtnAction');
this.SHOW_CLOSE_BUTTON = this.get('winPreviewShowCloseButton');
this.WINDOW_ICON_CLICK_ACTION = this.get('windowIconClickAction');
this.OVERLAY_KEY_SECONDARY = this.get('overlayKeySecondary', true); this.OVERLAY_KEY_PRIMARY = this.get('overlayKeyPrimary');
this.OVERLAY_KEY_SECONDARY = this.get('overlayKeySecondary');
this.ESC_BEHAVIOR = this.get('overviewEscBehavior');
this.WINDOW_THUMBNAIL_ENABLED = this.get('windowThumbnailModule');
this.WINDOW_THUMBNAIL_SCALE = this.get('windowThumbnailScale') / 100;
this.FIX_NEW_WINDOW_FOCUS = this.get('newWindowFocusFix');
} }
_getAnimationDirection() { _getAnimationDirection() {

View file

@ -10,61 +10,90 @@
'use strict'; 'use strict';
const { Clutter, GObject } = imports.gi; const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Main = imports.ui.main; const Main = imports.ui.main;
const SwipeTracker = imports.ui.swipeTracker; const SwipeTracker = imports.ui.swipeTracker;
const Me = imports.misc.extensionUtils.getCurrentExtension(); let Me;
let opt; let opt;
let _firstRun = true;
let _vwGestureUpdateId; var SwipeTrackerModule = class {
let _originalGestureUpdateId; constructor(me) {
Me = me;
opt = Me.opt;
function update(reset = false) { this._firstActivation = true;
opt = Me.imports.lib.settings.opt; this.moduleEnabled = false;
const moduleEnabled = opt.get('swipeTrackerModule', true);
reset = reset || !moduleEnabled;
// don't even touch this module if disabled
if (_firstRun && reset)
return;
_firstRun = false;
if (reset || !opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
// original swipeTrackers' orientation and updateGesture function
Main.overview._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
Main.overview._swipeTracker._updateGesture = SwipeTracker.SwipeTracker.prototype._updateGesture;
if (_vwGestureUpdateId) {
Main.overview._swipeTracker._touchpadGesture.disconnect(_vwGestureUpdateId);
_vwGestureUpdateId = 0;
}
if (_originalGestureUpdateId) {
Main.overview._swipeTracker._touchpadGesture.unblock_signal_handler(_originalGestureUpdateId);
_originalGestureUpdateId = 0;
}
opt = null;
return;
} }
if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL cleanGlobals() {
Me = null;
opt = null;
}
update(reset) {
this.moduleEnabled = opt.get('swipeTrackerModule');
const conflict = false;
reset = reset || !this.moduleEnabled || conflict;
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' SwipeTrackerModule - Keeping untouched');
}
_activateModule() {
if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
this._setVertical();
} else {
this._setHorizontal();
}
console.debug(' SwipeTrackerModule - Activated');
}
_disableModule() {
this._setHorizontal();
console.debug(' SwipeTrackerModule - Disabled');
}
_setVertical() {
// reverse swipe gestures for enter/leave overview and ws switching // reverse swipe gestures for enter/leave overview and ws switching
Main.overview._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL; Main.overview._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.VERTICAL; Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
// overview's updateGesture() function should reflect ws tmb position to match appGrid/ws animation direction // overview's updateGesture() function should reflect ws tmb position to match appGrid/ws animation direction
// function in connection cannot be overridden in prototype of its class because connected is actually another copy of the original function // function in connection cannot be overridden in prototype of its class because connected is actually another copy of the original function
if (!_originalGestureUpdateId) { if (!this._originalGestureUpdateId) {
_originalGestureUpdateId = GObject.signal_handler_find(Main.overview._swipeTracker._touchpadGesture, { signalId: 'update' }); this._originalGestureUpdateId = GObject.signal_handler_find(Main.overview._swipeTracker._touchpadGesture, { signalId: 'update' });
Main.overview._swipeTracker._touchpadGesture.block_signal_handler(_originalGestureUpdateId); Main.overview._swipeTracker._touchpadGesture.block_signal_handler(this._originalGestureUpdateId);
Main.overview._swipeTracker._updateGesture = SwipeTrackerVertical._updateGesture; Main.overview._swipeTracker._updateGesture = SwipeTrackerVertical._updateGesture;
_vwGestureUpdateId = Main.overview._swipeTracker._touchpadGesture.connect('update', SwipeTrackerVertical._updateGesture.bind(Main.overview._swipeTracker)); this._vwGestureUpdateId = Main.overview._swipeTracker._touchpadGesture.connect('update', SwipeTrackerVertical._updateGesture.bind(Main.overview._swipeTracker));
} }
} }
}
_setHorizontal() {
// original swipeTrackers' orientation and updateGesture function
Main.overview._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
Main.overview._swipeTracker._updateGesture = SwipeTracker.SwipeTracker.prototype._updateGesture;
if (this._vwGestureUpdateId) {
Main.overview._swipeTracker._touchpadGesture.disconnect(this._vwGestureUpdateId);
this._vwGestureUpdateId = 0;
}
if (this._originalGestureUpdateId) {
Main.overview._swipeTracker._touchpadGesture.unblock_signal_handler(this._originalGestureUpdateId);
this._originalGestureUpdateId = 0;
}
}
};
const SwipeTrackerVertical = { const SwipeTrackerVertical = {
_updateGesture(gesture, time, delta, distance) { _updateGesture(gesture, time, delta, distance) {

View file

@ -10,16 +10,27 @@
'use strict'; 'use strict';
const Clutter = imports.gi.Clutter;
const Meta = imports.gi.Meta;
const Gi = imports._gi; const Gi = imports._gi;
const { Shell, Meta, Clutter } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Shell = imports.gi.Shell;
const Config = imports.misc.config; const Main = imports.ui.main;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils; let Me;
const Me = ExtensionUtils.getCurrentExtension();
var shellVersion = parseFloat(Config.PACKAGE_VERSION); let _installedExtensions;
function init(me) {
Me = me;
}
function cleanGlobals() {
Me = null;
_installedExtensions = null;
}
var Overrides = class { var Overrides = class {
constructor() { constructor() {
@ -27,8 +38,13 @@ var Overrides = class {
} }
addOverride(name, prototype, overrideList) { addOverride(name, prototype, overrideList) {
const backup = this.overrideProto(prototype, overrideList, name);
// don't update originals when override's just refreshing, keep initial content
let originals = this._overrides[name]?.originals;
if (!originals)
originals = backup;
this._overrides[name] = { this._overrides[name] = {
originals: this.overrideProto(prototype, overrideList), originals,
prototype, prototype,
}; };
} }
@ -38,15 +54,15 @@ var Overrides = class {
if (!override) if (!override)
return false; return false;
this.overrideProto(override.prototype, override.originals); this.overrideProto(override.prototype, override.originals, name);
this._overrides[name] = undefined; delete this._overrides[name];
return true; return true;
} }
removeAll() { removeAll() {
for (let name in this._overrides) { for (let name in this._overrides) {
this.removeOverride(name); this.removeOverride(name);
this._overrides[name] = undefined; delete this._overrides[name];
} }
} }
@ -54,13 +70,17 @@ var Overrides = class {
proto[Gi.hook_up_vfunc_symbol](symbol, func); proto[Gi.hook_up_vfunc_symbol](symbol, func);
} }
overrideProto(proto, overrides) { overrideProto(proto, overrides, name) {
const backup = {}; const backup = {};
const originals = this._overrides[name]?.originals;
for (let symbol in overrides) { for (let symbol in overrides) {
if (symbol.startsWith('after_')) { if (symbol.startsWith('after_')) {
const actualSymbol = symbol.slice('after_'.length); const actualSymbol = symbol.slice('after_'.length);
const fn = proto[actualSymbol]; let fn;
if (originals && originals[actualSymbol])
fn = originals[actualSymbol];
else
fn = proto[actualSymbol];
const afterFn = overrides[symbol]; const afterFn = overrides[symbol];
proto[actualSymbol] = function (...args) { proto[actualSymbol] = function (...args) {
args = Array.prototype.slice.call(args); args = Array.prototype.slice.call(args);
@ -72,11 +92,11 @@ var Overrides = class {
} else { } else {
backup[symbol] = proto[symbol]; backup[symbol] = proto[symbol];
if (symbol.startsWith('vfunc')) { if (symbol.startsWith('vfunc')) {
if (shellVersion < 42) if (Me.shellVersion < 42)
this.hookVfunc(proto, symbol.slice(6), overrides[symbol]); this.hookVfunc(proto, symbol.slice(6), overrides[symbol]);
else else
this.hookVfunc(proto[Gi.gobject_prototype_symbol], symbol.slice(6), overrides[symbol]); this.hookVfunc(proto[Gi.gobject_prototype_symbol], symbol.slice(6), overrides[symbol]);
} else { } else if (overrides[symbol] !== null) {
proto[symbol] = overrides[symbol]; proto[symbol] = overrides[symbol];
} }
} }
@ -85,87 +105,21 @@ var Overrides = class {
} }
}; };
function getOverviewTranslations(opt, dash, tmbBox, searchEntryBin) { function openPreferences(metadata) {
// const tmbBox = Main.overview._overview._controls._thumbnailsBox; if (!metadata)
let searchTranslationY = 0; metadata = Me.metadata;
if (searchEntryBin.visible) {
const offset = (dash.visible && (!opt.DASH_VERTICAL ? dash.height + 12 : 0)) +
(opt.WS_TMB_TOP ? tmbBox.height + 12 : 0);
searchTranslationY = -searchEntryBin.height - offset - 30;
}
let tmbTranslationX = 0;
let tmbTranslationY = 0;
let offset;
if (tmbBox.visible) {
switch (opt.WS_TMB_POSITION) {
case 3: // left
offset = 10 + (dash?.visible && opt.DASH_LEFT ? dash.width : 0);
tmbTranslationX = -tmbBox.width - offset;
tmbTranslationY = 0;
break;
case 1: // right
offset = 10 + (dash?.visible && opt.DASH_RIGHT ? dash.width : 0);
tmbTranslationX = tmbBox.width + offset;
tmbTranslationY = 0;
break;
case 0: // top
offset = 10 + (dash?.visible && opt.DASH_TOP ? dash.height : 0) + Main.panel.height;
tmbTranslationX = 0;
tmbTranslationY = -tmbBox.height - offset;
break;
case 2: // bottom
offset = 10 + (dash?.visible && opt.DASH_BOTTOM ? dash.height : 0) + Main.panel.height; // just for case the panel is at bottom
tmbTranslationX = 0;
tmbTranslationY = tmbBox.height + offset;
break;
}
}
let dashTranslationX = 0;
let dashTranslationY = 0;
let position = opt.DASH_POSITION;
// if DtD replaced the original Dash, read its position
if (dashIsDashToDock())
position = dash._position;
if (dash?.visible) {
switch (position) {
case 0: // top
dashTranslationX = 0;
dashTranslationY = -dash.height - dash.margin_bottom - Main.panel.height;
break;
case 1: // right
dashTranslationX = dash.width;
dashTranslationY = 0;
break;
case 2: // bottom
dashTranslationX = 0;
dashTranslationY = dash.height + dash.margin_bottom + Main.panel.height;
break;
case 3: // left
dashTranslationX = -dash.width;
dashTranslationY = 0;
break;
}
}
return [tmbTranslationX, tmbTranslationY, dashTranslationX, dashTranslationY, searchTranslationY];
}
function openPreferences() {
const windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null); const windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null);
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
let metaWin, isVW = null; let metaWin, isVW = null;
for (let win of windows) { for (let win of windows) {
const app = tracker.get_window_app(win); const app = tracker.get_window_app(win);
if (win.get_title().includes(Me.metadata.name) && app.get_name() === 'Extensions') { if (win.get_title()?.includes(metadata.name) && app.get_name() === 'Extensions') {
// this is our existing window // this is our existing window
metaWin = win; metaWin = win;
isVW = true; isVW = true;
break; break;
} else if (win.wm_class.includes('org.gnome.Shell.Extensions')) { } else if (win.wm_class?.includes('org.gnome.Shell.Extensions')) {
// this is prefs window of another extension // this is prefs window of another extension
metaWin = win; metaWin = win;
isVW = false; isVW = false;
@ -182,17 +136,20 @@ function openPreferences() {
} }
if (!metaWin || (metaWin && !isVW)) { if (!metaWin || (metaWin && !isVW)) {
try { GLib.idle_add(GLib.PRIORITY_LOW, () => {
Main.extensionManager.openExtensionPrefs(Me.metadata.uuid, '', {}); try {
} catch (e) { Main.extensionManager.openExtensionPrefs(metadata.uuid, '', {});
log(e); } catch (e) {
} console.error(e);
}
});
} }
} }
function activateSearchProvider(prefix = '') { function activateSearchProvider(prefix = '') {
const searchEntry = Main.overview.searchEntry; const searchEntry = Main.overview.searchEntry;
if (!searchEntry.get_text() || !searchEntry.get_text().startsWith(prefix)) { const searchEntryText = searchEntry.get_text();
if (!searchEntryText || (searchEntryText && !searchEntry.get_text().startsWith(prefix))) {
prefix = `${prefix} `; prefix = `${prefix} `;
const position = prefix.length; const position = prefix.length;
searchEntry.set_text(prefix); searchEntry.set_text(prefix);
@ -220,9 +177,16 @@ function reorderWorkspace(direction = 0) {
global.workspace_manager.reorder_workspace(activeWs, targetIdx); global.workspace_manager.reorder_workspace(activeWs, targetIdx);
} }
function activateKeyboardForWorkspaceView() {
Main.ctrlAltTabManager._items.forEach(i => {
if (i.sortGroup === 1 && i.name === 'Windows')
Main.ctrlAltTabManager.focusGroup(i);
});
}
function exposeWindows(adjustment, activateKeyboard) { function exposeWindows(adjustment, activateKeyboard) {
// expose windows for static overview modes // expose windows for static overview modes
if (!adjustment.value && !Main.overview._animationInProgress) { if (!adjustment.value/* && !Main.overview._animationInProgress*/) {
if (adjustment.value === 0) { if (adjustment.value === 0) {
adjustment.value = 0; adjustment.value = 0;
adjustment.ease(1, { adjustment.ease(1, {
@ -330,13 +294,48 @@ function isMoreRelevant(stringA, stringB, pattern) {
return !aAny && bAny; return !aAny && bAny;
} }
function getEnabledExtensions(uuid = '') { function getEnabledExtensions(pattern = '') {
let extensions = []; let result = [];
Main.extensionManager._extensions.forEach(e => { // extensionManager is unreliable at startup (if not all extensions were loaded)
if (e.state === 1 && e.uuid.includes(uuid)) // but gsettings key can contain removed extensions...
extensions.push(e); // therefore we have to look into filesystem, what's really installed
}); if (!_installedExtensions) {
return extensions; const extensionFiles = [...collectFromDatadirs('extensions', true)];
_installedExtensions = extensionFiles.map(({ info }) => {
let fileType = info.get_file_type();
if (fileType !== Gio.FileType.DIRECTORY)
return null;
const uuid = info.get_name();
return uuid;
});
}
const enabled = Main.extensionManager._enabledExtensions;
result = _installedExtensions.filter(ext => enabled.includes(ext));
return result.filter(uuid => uuid !== null && uuid.includes(pattern));
}
function* collectFromDatadirs(subdir, includeUserDir) {
let dataDirs = GLib.get_system_data_dirs();
if (includeUserDir)
dataDirs.unshift(GLib.get_user_data_dir());
for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
let dir = Gio.File.new_for_path(path);
let fileEnum;
try {
fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
fileEnum = null;
}
if (fileEnum !== null) {
let info;
while ((info = fileEnum.next_file(null)))
yield { dir: fileEnum.get_child(info), info };
}
}
} }
function getScrollDirection(event) { function getScrollDirection(event) {

View file

@ -0,0 +1,525 @@
/**
* V-Shell (Vertical Workspaces)
* WinTmb
*
* @author GdH <G-dH@github.com>
* @copyright 2021-2023
* @license GPL-3.0
*/
'use strict';
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const AltTab = imports.ui.altTab;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
let Me;
let opt;
const SCROLL_ICON_OPACITY = 240;
const DRAG_OPACITY = 200;
const CLOSE_BTN_OPACITY = 240;
var WinTmbModule = class {
constructor(me) {
Me = me;
opt = Me.opt;
this._firstActivation = true;
this.moduleEnabled = false;
}
cleanGlobals() {
Me = null;
opt = null;
}
update(reset) {
this._removeTimeouts();
this.moduleEnabled = opt.get('windowThumbnailModule');
reset = reset || !this.moduleEnabled;
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' WinTmb - Keeping untouched');
}
_activateModule() {
this._timeouts = {};
if (!this._windowThumbnails)
this._windowThumbnails = [];
Main.overview.connectObject('hidden', () => this.showThumbnails(), this);
console.debug(' WinTmb - Activated');
}
_disableModule() {
Main.overview.disconnectObject(this);
this._disconnectStateAdjustment();
this.removeAllThumbnails();
console.debug(' WinTmb - Disabled');
}
_removeTimeouts() {
if (this._timeouts) {
Object.values(this._timeouts).forEach(t => {
if (t)
GLib.source_remove(t);
});
this._timeouts = null;
}
}
createThumbnail(metaWin) {
const thumbnail = new WindowThumbnail(metaWin, {
'height': Math.floor(opt.WINDOW_THUMBNAIL_SCALE * global.display.get_monitor_geometry(global.display.get_current_monitor()).height),
'thumbnailsOnScreen': this._windowThumbnails.length,
});
this._windowThumbnails.push(thumbnail);
thumbnail.connect('removed', tmb => {
this._windowThumbnails.splice(this._windowThumbnails.indexOf(tmb), 1);
tmb.destroy();
if (!this._windowThumbnails.length)
this._disconnectStateAdjustment();
});
if (!this._stateAdjustmentConId) {
this._stateAdjustmentConId = Main.overview._overview.controls._stateAdjustment.connectObject('notify::value', () => {
if (!this._thumbnailsHidden && (!opt.OVERVIEW_MODE2 || opt.WORKSPACE_MODE))
this.hideThumbnails();
}, this);
}
}
hideThumbnails() {
this._windowThumbnails.forEach(tmb => {
tmb.ease({
opacity: 0,
duration: 200,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => tmb.hide(),
});
});
this._thumbnailsHidden = true;
}
showThumbnails() {
this._windowThumbnails.forEach(tmb => {
tmb.show();
tmb.ease({
opacity: 255,
duration: 100,
mode: Clutter.AnimationMode.LINEAR,
});
});
this._thumbnailsHidden = false;
}
removeAllThumbnails() {
this._windowThumbnails.forEach(tmb => tmb.remove());
this._windowThumbnails = [];
}
_disconnectStateAdjustment() {
Main.overview._overview.controls._stateAdjustment.disconnectObject(this);
}
};
const WindowThumbnail = GObject.registerClass({
Signals: { 'removed': {} },
}, class WindowThumbnail extends St.Widget {
_init(metaWin, args) {
this._hoverShowsPreview = false;
this._customOpacity = 255;
this._initTmbHeight = args.height;
this._minimumHeight = Math.floor(5 / 100 * global.display.get_monitor_geometry(global.display.get_current_monitor()).height);
this._scrollTimeout = 100;
this._positionOffset = args.thumbnailsOnScreen;
this._reverseTmbWheelFunc = false;
this._click_count = 1;
this._prevBtnPressTime = 0;
this.w = metaWin;
super._init({
layout_manager: new Clutter.BinLayout(),
visible: true,
reactive: true,
can_focus: true,
track_hover: true,
});
this.connect('button-release-event', this._onBtnReleased.bind(this));
this.connect('scroll-event', this._onScrollEvent.bind(this));
// this.connect('motion-event', this._onMouseMove.bind(this)); // may be useful in the future..
this._delegate = this;
this._draggable = DND.makeDraggable(this, { dragActorOpacity: DRAG_OPACITY });
this._draggable.connect('drag-end', this._end_drag.bind(this));
this._draggable.connect('drag-cancelled', this._end_drag.bind(this));
this._draggable._animateDragEnd = eventTime => {
this._draggable._animationInProgress = true;
this._draggable._onAnimationComplete(this._draggable._dragActor, eventTime);
this.opacity = this._customOpacity;
};
this.clone = new Clutter.Clone({ reactive: true });
Main.layoutManager.addChrome(this);
this.window = this.w.get_compositor_private();
this.clone.set_source(this.window);
this.add_child(this.clone);
this._addCloseButton();
this._addScrollModeIcon();
this.connect('enter-event', () => {
global.display.set_cursor(Meta.Cursor.POINTING_HAND);
this._closeButton.opacity = CLOSE_BTN_OPACITY;
this._scrollModeBin.opacity = SCROLL_ICON_OPACITY;
if (this._hoverShowsPreview && !Main.overview._shown) {
this._closeButton.opacity = 50;
this._showWindowPreview(false, true);
}
});
this.connect('leave-event', () => {
global.display.set_cursor(Meta.Cursor.DEFAULT);
this._closeButton.opacity = 0;
this._scrollModeBin.opacity = 0;
if (this._winPreview)
this._destroyWindowPreview();
});
this._setSize(true);
this.set_position(...this._getInitialPosition());
this.show();
this.window_id = this.w.get_id();
this.tmbRedrawDirection = true;
// remove thumbnail content and hide thumbnail if its window is destroyed
this.windowConnect = this.window.connect('destroy', () => {
if (this)
this.remove();
});
}
_getInitialPosition() {
const offset = 20;
let monitor = Main.layoutManager.monitors[global.display.get_current_monitor()];
let x = Math.min(monitor.x + monitor.width - (this.window.width * this.scale) - offset);
let y = Math.min(monitor.y + monitor.height - (this.window.height * this.scale) - offset - ((this._positionOffset * this._initTmbHeight) % (monitor.height - this._initTmbHeight)));
return [x, y];
}
_setSize(resetScale = false) {
if (resetScale)
this.scale = Math.min(1.0, this._initTmbHeight / this.window.height);
const width = this.window.width * this.scale;
const height = this.window.height * this.scale;
this.set_size(width, height);
if (this.icon) {
this.icon.scale_x = this.scale;
this.icon.scale_y = this.scale;
}
// when the scale of this. actor change, this.clone resize accordingly,
// but the reactive area of the actor doesn't change until the actor is redrawn
// this updates the actor's input region area:
Main.layoutManager._queueUpdateRegions();
}
/* _onMouseMove(actor, event) {
let [pos_x, pos_y] = event.get_coords();
let state = event.get_state();
if (this._ctrlPressed(state)) {
}
}*/
_onBtnReleased(actor, event) {
// Clutter.Event.click_count property in no longer available, since GS42
if ((event.get_time() - this._prevBtnPressTime) < Clutter.Settings.get_default().double_click_time)
this._click_count += 1;
else
this._click_count = 1;
this._prevBtnPressTime = event.get_time();
if (this._click_count === 2 && event.get_button() === Clutter.BUTTON_PRIMARY)
this.w.activate(global.get_current_time());
const button = event.get_button();
const state = event.get_state();
switch (button) {
case Clutter.BUTTON_PRIMARY:
if (this._ctrlPressed(state)) {
this._setSize();
} else {
this._reverseTmbWheelFunc = !this._reverseTmbWheelFunc;
this._scrollModeBin.set_child(this._reverseTmbWheelFunc ? this._scrollModeSourceIcon : this._scrollModeResizeIcon);
}
return Clutter.EVENT_STOP;
case Clutter.BUTTON_SECONDARY:
if (this._ctrlPressed(state)) {
this.remove();
} else {
this._hoverShowsPreview = !this._hoverShowsPreview;
this._showWindowPreview();
}
return Clutter.EVENT_STOP;
case Clutter.BUTTON_MIDDLE:
if (this._ctrlPressed(state))
this.w.delete(global.get_current_time());
return Clutter.EVENT_STOP;
default:
return Clutter.EVENT_PROPAGATE;
}
}
_onScrollEvent(actor, event) {
let direction = Me.Util.getScrollDirection(event);
if (this._actionTimeoutActive())
return Clutter.EVENT_PROPAGATE;
let state = event.get_state();
switch (direction) {
case Clutter.ScrollDirection.UP:
if (this._shiftPressed(state)) {
this.opacity = Math.min(255, this.opacity + 24);
this._customOpacity = this.opacity;
} else if (this._reverseTmbWheelFunc !== this._ctrlPressed(state)) {
this._switchSourceWin(-1);
} else if (this._reverseTmbWheelFunc === this._ctrlPressed(state)) {
this.scale = Math.max(0.05, this.scale - 0.025);
}
break;
case Clutter.ScrollDirection.DOWN:
if (this._shiftPressed(state)) {
this.opacity = Math.max(48, this.opacity - 24);
this._customOpacity = this.opacity;
} else if (this._reverseTmbWheelFunc !== this._ctrlPressed(state)) {
this._switchSourceWin(+1);
} else if (this._reverseTmbWheelFunc === this._ctrlPressed(state)) {
this.scale = Math.min(1, this.scale + 0.025);
}
break;
default:
return Clutter.EVENT_PROPAGATE;
}
this._setSize();
return Clutter.EVENT_STOP;
}
remove() {
if (this.clone) {
this.window.disconnect(this.windowConnect);
this.clone.set_source(null);
}
if (this._winPreview)
this._destroyWindowPreview();
this.emit('removed');
}
_end_drag() {
this.set_position(this._draggable._dragOffsetX + this._draggable._dragX, this._draggable._dragOffsetY + this._draggable._dragY);
this._setSize();
}
_ctrlPressed(state) {
return (state & Clutter.ModifierType.CONTROL_MASK) !== 0;
}
_shiftPressed(state) {
return (state & Clutter.ModifierType.SHIFT_MASK) !== 0;
}
_switchSourceWin(direction) {
let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null);
windows = windows.filter(w => !(w.skip_taskbar || w.minimized));
let idx = -1;
for (let i = 0; i < windows.length; i++) {
if (windows[i] === this.w) {
idx = i + direction;
break;
}
}
idx = idx >= windows.length ? 0 : idx;
idx = idx < 0 ? windows.length - 1 : idx;
let w = windows[idx];
let win = w.get_compositor_private();
this.clone.set_source(win);
this.window.disconnect(this.windowConnect);
// the new thumbnail should be the same height as the previous one
this.scale = (this.scale * this.window.height) / win.height;
this.window = win;
this.windowConnect = this.window.connect('destroy', () => {
if (this)
this.remove();
});
this.w = w;
if (this._winPreview)
this._showWindowPreview(true);
}
_actionTimeoutActive() {
const timeout = this._reverseTmbWheelFunc ? this._scrollTimeout : this._scrollTimeout / 4;
if (!this._lastActionTime || Date.now() - this._lastActionTime > timeout) {
this._lastActionTime = Date.now();
return false;
}
return true;
}
/* _setIcon() {
let tracker = Shell.WindowTracker.get_default();
let app = tracker.get_window_app(this.w);
let icon = app
? app.create_icon_texture(this.height)
: new St.Icon({ icon_name: 'icon-missing', icon_size: this.height });
icon.x_expand = icon.y_expand = true;
if (this.icon)
this.icon.destroy();
this.icon = icon;
}*/
_addCloseButton() {
const closeButton = new St.Button({
opacity: 0,
style_class: 'window-close',
child: new St.Icon({ icon_name: 'preview-close-symbolic' }),
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START,
x_expand: true,
y_expand: true,
});
closeButton.set_style(`
margin: 3px;
background-color: rgba(200, 0, 0, 0.9);
`);
closeButton.connect('clicked', () => {
this.remove();
return Clutter.EVENT_STOP;
});
this._closeButton = closeButton;
this.add_child(this._closeButton);
}
_addScrollModeIcon() {
this._scrollModeBin = new St.Bin({
x_expand: true,
y_expand: true,
});
this._scrollModeResizeIcon = new St.Icon({
icon_name: 'view-fullscreen-symbolic',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true,
opacity: SCROLL_ICON_OPACITY,
style_class: 'icon-dropshadow',
scale_x: 0.5,
scale_y: 0.5,
});
this._scrollModeResizeIcon.set_style(`
margin: 13px;
color: rgb(255, 255, 255);
box-shadow: 0 0 40px 40px rgba(0,0,0,0.7);
`);
this._scrollModeSourceIcon = new St.Icon({
icon_name: 'media-skip-forward-symbolic',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true,
opacity: SCROLL_ICON_OPACITY,
style_class: 'icon-dropshadow',
scale_x: 0.5,
scale_y: 0.5,
});
this._scrollModeSourceIcon.set_style(`
margin: 13px;
color: rgb(255, 255, 255);
box-shadow: 0 0 40px 40px rgba(0,0,0,0.7);
`);
this._scrollModeBin.set_child(this._scrollModeResizeIcon);
this.add_child(this._scrollModeBin);
this._scrollModeBin.opacity = 0;
}
_showWindowPreview(update = false, dontDestroy = false) {
if (this._winPreview && !dontDestroy) {
this._destroyWindowPreview();
this._previewCreationTime = 0;
this._closeButton.opacity = CLOSE_BTN_OPACITY;
if (!update)
return;
}
if (!this._winPreview) {
this._winPreview = new AltTab.CyclerHighlight();
global.window_group.add_actor(this._winPreview);
[this._winPreview._xPointer, this._winPreview._yPointer] = global.get_pointer();
}
if (!update) {
this._winPreview.opacity = 0;
this._winPreview.ease({
opacity: 255,
duration: 70,
mode: Clutter.AnimationMode.LINEAR,
/* onComplete: () => {
this._closeButton.opacity = 50;
},*/
});
this.ease({
opacity: Math.min(50, this._customOpacity),
duration: 70,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
},
});
} else {
this._winPreview.opacity = 255;
}
this._winPreview.window = this.w;
this._winPreview._window = this.w;
global.window_group.set_child_above_sibling(this._winPreview, null);
}
_destroyWindowPreview() {
if (this._winPreview) {
this._winPreview.ease({
opacity: 0,
duration: 100,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this._winPreview.destroy();
this._winPreview = null;
this.opacity = this._customOpacity;
},
});
}
}
});

View file

@ -11,47 +11,69 @@
'use strict'; 'use strict';
const Main = imports.ui.main; const Main = imports.ui.main;
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const ExtensionUtils = imports.misc.extensionUtils; const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const Me = ExtensionUtils.getCurrentExtension();
const _Util = Me.imports.lib.util;
let Me;
let opt; let opt;
let _firstRun = false;
function update(reset = false) { var WindowAttentionHandlerModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('winAttentionHandlerModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
if (_firstRun && reset) this._firstActivation = true;
return; this.moduleEnabled = false;
this._overrides = null;
_firstRun = false;
if (reset) {
reset = true;
_updateConnections(reset);
opt = null;
return;
} }
_updateConnections(); cleanGlobals() {
} Me = null;
opt = null;
}
function _updateConnections(reset) { update(reset) {
global.display.disconnectObject(Main.windowAttentionHandler); this.moduleEnabled = opt.get('windowAttentionHandlerModule');
const conflict = false;
const handlerFnc = reset reset = reset || !this.moduleEnabled || conflict;
? Main.windowAttentionHandler._onWindowDemandsAttention
: WindowAttentionHandlerCommon._onWindowDemandsAttention;
global.display.connectObject( // don't touch the original code if module disabled
'window-demands-attention', handlerFnc.bind(Main.windowAttentionHandler), if (reset && !this._firstActivation) {
'window-marked-urgent', handlerFnc.bind(Main.windowAttentionHandler), this._disableModule();
Main.windowAttentionHandler); } else if (!reset) {
} this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' WindowAttentionHandlerModule - Keeping untouched');
}
_activateModule() {
this._updateConnections();
console.debug(' WindowAttentionHandlerModule - Activated');
}
_disableModule() {
const reset = true;
this._updateConnections(reset);
console.debug(' WindowAttentionHandlerModule - Disabled');
}
_updateConnections(reset) {
global.display.disconnectObject(Main.windowAttentionHandler);
const handlerFnc = reset
? Main.windowAttentionHandler._onWindowDemandsAttention
: WindowAttentionHandlerCommon._onWindowDemandsAttention;
global.display.connectObject(
'window-demands-attention', handlerFnc.bind(Main.windowAttentionHandler),
'window-marked-urgent', handlerFnc.bind(Main.windowAttentionHandler),
Main.windowAttentionHandler);
}
};
const WindowAttentionHandlerCommon = { const WindowAttentionHandlerCommon = {
_onWindowDemandsAttention(display, window) { _onWindowDemandsAttention(display, window) {

View file

@ -10,81 +10,101 @@
'use strict'; 'use strict';
const { GObject, Clutter, Meta } = imports.gi; const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Meta = imports.gi.Meta;
const Main = imports.ui.main; const Main = imports.ui.main;
const WindowManager = imports.ui.windowManager; const WindowManager = imports.ui.windowManager;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const _Util = Me.imports.lib.util;
let _overrides;
const MINIMIZE_WINDOW_ANIMATION_TIME = WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME;
const MINIMIZE_WINDOW_ANIMATION_MODE = WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE;
let Me;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { var WindowManagerModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('windowManagerModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
// don't even touch this module if disabled this._firstActivation = true;
if (_firstRun && reset) this.moduleEnabled = false;
return; this._overrides = null;
_firstRun = false; this._originalMinimizeSigId = 0;
this._minimizeSigId = 0;
this._originalUnminimizeSigId = 0;
this._unminimizeSigId = 0;
}
if (_overrides) cleanGlobals() {
_overrides.removeAll(); Me = null;
_replaceMinimizeFunction(reset);
if (reset) {
_overrides = null;
opt = null; opt = null;
return;
} }
_overrides = new _Util.Overrides(); update(reset) {
this.moduleEnabled = opt.get('windowManagerModule');
const conflict = false;
_overrides.addOverride('WindowManager', WindowManager.WindowManager.prototype, WindowManagerCommon); reset = reset || !this.moduleEnabled || conflict;
}
// ------------- Fix and adapt minimize/unminimize animations -------------------------------------- // don't even touch the original code if module disabled
if (reset && !this._firstActivation) {
let _originalMinimizeSigId; this._disableModule();
let _minimizeSigId; } else if (!reset) {
let _originalUnminimizeSigId; this._firstActivation = false;
let _unminimizeSigId; this._activateModule();
function _replaceMinimizeFunction(reset = false) {
if (reset) {
Main.wm._shellwm.disconnect(_minimizeSigId);
_minimizeSigId = 0;
Main.wm._shellwm.unblock_signal_handler(_originalMinimizeSigId);
_originalMinimizeSigId = 0;
Main.wm._shellwm.disconnect(_unminimizeSigId);
_unminimizeSigId = 0;
Main.wm._shellwm.unblock_signal_handler(_originalUnminimizeSigId);
_originalUnminimizeSigId = 0;
} else if (!_minimizeSigId) {
_originalMinimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'minimize' });
if (_originalMinimizeSigId) {
Main.wm._shellwm.block_signal_handler(_originalMinimizeSigId);
_minimizeSigId = Main.wm._shellwm.connect('minimize', WindowManagerCommon._minimizeWindow.bind(Main.wm));
}
_originalUnminimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'unminimize' });
if (_originalUnminimizeSigId) {
Main.wm._shellwm.block_signal_handler(_originalUnminimizeSigId);
_unminimizeSigId = Main.wm._shellwm.connect('unminimize', WindowManagerCommon._unminimizeWindow.bind(Main.wm));
} }
if (reset && this._firstActivation)
console.debug(' WindowManagerModule - Keeping untouched');
} }
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
this._overrides.addOverride('WindowManager', WindowManager.WindowManager.prototype, WindowManagerCommon);
if (!this._minimizeSigId) {
this._originalMinimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'minimize' });
if (this._originalMinimizeSigId) {
Main.wm._shellwm.block_signal_handler(this._originalMinimizeSigId);
this._minimizeSigId = Main.wm._shellwm.connect('minimize', WindowManagerCommon._minimizeWindow.bind(Main.wm));
}
this._originalUnminimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'unminimize' });
if (this._originalUnminimizeSigId) {
Main.wm._shellwm.block_signal_handler(this._originalUnminimizeSigId);
this._unminimizeSigId = Main.wm._shellwm.connect('unminimize', WindowManagerCommon._unminimizeWindow.bind(Main.wm));
}
}
console.debug(' WindowManagerModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
if (this._minimizeSigId) {
Main.wm._shellwm.disconnect(this._minimizeSigId);
this._minimizeSigId = 0;
}
if (this._originalMinimizeSigId) {
Main.wm._shellwm.unblock_signal_handler(this._originalMinimizeSigId);
this._originalMinimizeSigId = 0;
}
if (this._unminimizeSigId) {
Main.wm._shellwm.disconnect(this._unminimizeSigId);
this._unminimizeSigId = 0;
}
if (this._originalUnminimizeSigId) {
Main.wm._shellwm.unblock_signal_handler(this._originalUnminimizeSigId);
this._originalUnminimizeSigId = 0;
}
console.debug(' WindowManagerModule - Disabled');
}
};
// fix for mainstream bug - fullscreen windows should minimize using opacity transition // fix for mainstream bug - fullscreen windows should minimize using opacity transition
// but its being applied directly on window actor and that doesn't work // but its being applied directly on window actor and that doesn't work
@ -109,8 +129,8 @@ const WindowManagerCommon = {
/* if (actor.meta_window.is_monitor_sized()) { /* if (actor.meta_window.is_monitor_sized()) {
actor.get_first_child().ease({ actor.get_first_child().ease({
opacity: 0, opacity: 0,
duration: MINIMIZE_WINDOW_ANIMATION_TIME, duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
mode: MINIMIZE_WINDOW_ANIMATION_MODE, mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._minimizeWindowDone(shellwm, actor), onStopped: () => this._minimizeWindowDone(shellwm, actor),
}); });
} else { */ } else { */
@ -140,8 +160,8 @@ const WindowManagerCommon = {
scale_y: yScale, scale_y: yScale,
x: xDest, x: xDest,
y: yDest, y: yDest,
duration: MINIMIZE_WINDOW_ANIMATION_TIME, duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
mode: MINIMIZE_WINDOW_ANIMATION_MODE, mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._minimizeWindowDone(shellwm, actor), onStopped: () => this._minimizeWindowDone(shellwm, actor),
}); });
// } // }
@ -176,8 +196,8 @@ const WindowManagerCommon = {
actor.set_scale(1.0, 1.0); actor.set_scale(1.0, 1.0);
actor.ease({ actor.ease({
opacity: 255, opacity: 255,
duration: MINIMIZE_WINDOW_ANIMATION_TIME, duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
mode: MINIMIZE_WINDOW_ANIMATION_MODE, mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._unminimizeWindowDone(shellwm, actor), onStopped: () => this._unminimizeWindowDone(shellwm, actor),
}); });
} else { */ } else { */
@ -208,8 +228,8 @@ const WindowManagerCommon = {
scale_y: 1, scale_y: 1,
x: xDest, x: xDest,
y: yDest, y: yDest,
duration: MINIMIZE_WINDOW_ANIMATION_TIME, duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
mode: MINIMIZE_WINDOW_ANIMATION_MODE, mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._unminimizeWindowDone(shellwm, actor), onStopped: () => this._unminimizeWindowDone(shellwm, actor),
}); });
// } // }

View file

@ -10,103 +10,372 @@
'use strict'; 'use strict';
const { Clutter, GLib, GObject, Graphene, Meta, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Atk = imports.gi.Atk;
const GLib = imports.gi.GLib;
const Graphene = imports.gi.Graphene;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const DND = imports.ui.dnd;
const Main = imports.ui.main; const Main = imports.ui.main;
const OverviewControls = imports.ui.overviewControls;
const WindowPreview = imports.ui.windowPreview; const WindowPreview = imports.ui.windowPreview;
const ExtensionUtils = imports.misc.extensionUtils; let Me;
const Me = ExtensionUtils.getCurrentExtension();
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.lib.windowSearchProvider.prefix;
const ControlsState = imports.ui.overviewControls.ControlsState;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { const WINDOW_SCALE_TIME = 200;
opt = Me.imports.lib.settings.opt; const WINDOW_ACTIVE_SIZE_INC = 5;
const moduleEnabled = opt.get('windowPreviewModule', true); const WINDOW_OVERLAY_FADE_TIME = 200;
reset = reset || !moduleEnabled; const WINDOW_DND_SIZE = 256;
const DRAGGING_WINDOW_OPACITY = 100;
// don't even touch this module if disabled const ControlsState = OverviewControls.ControlsState;
if (_firstRun && reset)
return;
_firstRun = false; var WindowPreviewModule = class {
constructor(me) {
Me = me;
opt = Me.opt;
if (_overrides) this._firstActivation = true;
_overrides.removeAll(); this.moduleEnabled = false;
this._overrides = null;
if (reset) {
_overrides = null;
opt = null;
WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
return;
} }
_overrides = new _Util.Overrides(); cleanGlobals() {
Me = null;
opt = null;
}
_overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon); update(reset) {
// A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer this.moduleEnabled = opt.get('windowPreviewModule');
if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW) const conflict = false;
WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
}
const WindowPreviewCommon = { reset = reset || !this.moduleEnabled || conflict;
// injection to _init()
after__init() {
const ICON_OVERLAP = 0.7;
if (opt.WIN_PREVIEW_ICON_SIZE < 64) { // don't touch the original code if module disabled
this.remove_child(this._icon); if (reset && !this._firstActivation) {
this._icon.destroy(); this._disableModule();
const tracker = Shell.WindowTracker.get_default(); } else if (!reset) {
const app = tracker.get_window_app(this.metaWindow); this._firstActivation = false;
this._icon = app.create_icon_texture(opt.WIN_PREVIEW_ICON_SIZE); this._activateModule();
this._icon.add_style_class_name('icon-dropshadow'); }
this._icon.set({ if (reset && this._firstActivation)
reactive: true, console.debug(' WindowPreviewModule - Keeping untouched');
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), }
});
this._icon.add_constraint(new Clutter.BindConstraint({ _activateModule() {
source: this.windowContainer, if (!this._overrides)
coordinate: Clutter.BindCoordinate.POSITION, this._overrides = new Me.Util.Overrides();
}));
this._icon.add_constraint(new Clutter.AlignConstraint({ this._overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon);
source: this.windowContainer, // A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer
align_axis: Clutter.AlignAxis.X_AXIS, if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
factor: 0.5, WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
})); console.debug(' WindowPreviewModule - Activated');
this._icon.add_constraint(new Clutter.AlignConstraint({ }
source: this.windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS, _disableModule() {
pivot_point: new Graphene.Point({ x: -1, y: ICON_OVERLAP }), // If WindowPreview._init was injected by another extension (like Burn My Windows)
factor: 1, // which enables/disables before V-Shell
})); // don't restore the original if it's not injected,
this.add_child(this._icon); // because it would restore injected _init and recursion would freeze GS when extensions are enabled again.
if (opt.WIN_PREVIEW_ICON_SIZE < 22) { // This can happen when all extension re-enabled, not only when screen is locked/unlocked
// disable app icon // If _init doesn't include "fn.apply(this, args)" when reset === true, some extension already restored the original
this._icon.hide(); const skipReset = WindowPreview.WindowPreview.prototype._init.toString().includes('fn.apply(this, args)');
} if (this._overrides && skipReset) {
this._iconSize = opt.WIN_PREVIEW_ICON_SIZE; // skip restoring original _init()
this._overrides['_init'] = null;
} }
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
console.debug(' WindowPreviewModule - Disabled');
}
};
const WindowPreviewCommon = {
_init(metaWindow, workspace, overviewAdjustment) {
this.metaWindow = metaWindow;
this.metaWindow._delegate = this;
this._windowActor = metaWindow.get_compositor_private();
this._workspace = workspace;
this._overviewAdjustment = overviewAdjustment;
const ICON_SIZE = opt.WIN_PREVIEW_ICON_SIZE;
const ICON_OVERLAP = 0.7;
Shell.WindowPreview.prototype._init.bind(this)({
reactive: true,
can_focus: true,
accessible_role: Atk.Role.PUSH_BUTTON,
offscreen_redirect: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY,
});
const windowContainer = new Clutter.Actor({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
});
this.window_container = windowContainer;
windowContainer.connect('notify::scale-x',
() => this._adjustOverlayOffsets());
// gjs currently can't handle setting an actors layout manager during
// the initialization of the actor if that layout manager keeps track
// of its container, so set the layout manager after creating the
// container
windowContainer.layout_manager = new Shell.WindowPreviewLayout();
this.add_child(windowContainer);
this._addWindow(metaWindow);
this._delegate = this;
this._stackAbove = null;
this._cachedBoundingBox = {
x: windowContainer.layout_manager.bounding_box.x1,
y: windowContainer.layout_manager.bounding_box.y1,
width: windowContainer.layout_manager.bounding_box.get_width(),
height: windowContainer.layout_manager.bounding_box.get_height(),
};
windowContainer.layout_manager.connect(
'notify::bounding-box', layout => {
this._cachedBoundingBox = {
x: layout.bounding_box.x1,
y: layout.bounding_box.y1,
width: layout.bounding_box.get_width(),
height: layout.bounding_box.get_height(),
};
// A bounding box of 0x0 means all windows were removed
if (layout.bounding_box.get_area() > 0)
this.emit('size-changed');
});
this._windowActor.connectObject('destroy', () => this.destroy(), this);
this._updateAttachedDialogs();
let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', act => {
const button = act.get_button();
if (button === Clutter.BUTTON_SECONDARY) {
if (opt.WIN_PREVIEW_SEC_BTN_ACTION === 1) {
this._closeWinAction();
return Clutter.EVENT_STOP;
} else if (opt.WIN_PREVIEW_SEC_BTN_ACTION === 2) {
this._searchAppWindowsAction();
return Clutter.EVENT_STOP;
} else if (opt.WIN_PREVIEW_SEC_BTN_ACTION === 3 && opt.WINDOW_THUMBNAIL_ENABLED) {
this._removeLaters();
Me.Modules.winTmbModule.createThumbnail(metaWindow);
return Clutter.EVENT_STOP;
}
} else if (button === Clutter.BUTTON_MIDDLE) {
if (opt.WIN_PREVIEW_MID_BTN_ACTION === 1) {
this._closeWinAction();
return Clutter.EVENT_STOP;
} else if (opt.WIN_PREVIEW_MID_BTN_ACTION === 2) {
this._searchAppWindowsAction();
return Clutter.EVENT_STOP;
} else if (opt.WIN_PREVIEW_MID_BTN_ACTION === 3 && opt.WINDOW_THUMBNAIL_ENABLED) {
this._removeLaters();
Me.Modules.winTmbModule.createThumbnail(metaWindow);
return Clutter.EVENT_STOP;
}
}
return this._activate();
});
if (this._onLongPress) {
clickAction.connect('long-press', this._onLongPress.bind(this));
} else {
clickAction.connect('long-press', (action, actor, state) => {
if (state === Clutter.LongPressState.ACTIVATE)
this.showOverlay(true);
return true;
});
}
this.connect('destroy', this._onDestroy.bind(this));
this._draggable = DND.makeDraggable(this, {
restoreOnSuccess: true,
manualMode: !!this._onLongPress,
dragActorMaxSize: WINDOW_DND_SIZE,
dragActorOpacity: DRAGGING_WINDOW_OPACITY,
});
// _draggable.addClickAction is new in GS45
if (this._draggable.addClickAction)
this._draggable.addClickAction(clickAction);
else
this.add_action(clickAction);
this._draggable.connect('drag-begin', this._onDragBegin.bind(this));
this._draggable.connect('drag-cancelled', this._onDragCancelled.bind(this));
this._draggable.connect('drag-end', this._onDragEnd.bind(this));
this.inDrag = false;
this._selected = false;
this._overlayEnabled = true;
this._overlayShown = false;
this._closeRequested = false;
this._idleHideOverlayId = 0;
const tracker = Shell.WindowTracker.get_default();
const app = tracker.get_window_app(this.metaWindow);
this._icon = app.create_icon_texture(ICON_SIZE);
this._icon.add_style_class_name('icon-dropshadow');
this._icon.set({
reactive: true,
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
});
this._icon.add_constraint(new Clutter.BindConstraint({
source: windowContainer,
coordinate: Clutter.BindCoordinate.POSITION,
}));
this._icon.add_constraint(new Clutter.AlignConstraint({
source: windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
factor: 0.5,
}));
this._icon.add_constraint(new Clutter.AlignConstraint({
source: windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({ x: -1, y: ICON_OVERLAP }),
factor: 1,
}));
if (opt.WINDOW_ICON_CLICK_ACTION) {
const iconClickAction = new Clutter.ClickAction();
iconClickAction.connect('clicked', act => {
if (act.get_button() === Clutter.BUTTON_PRIMARY) {
if (opt.WINDOW_ICON_CLICK_ACTION === 1) {
this._searchAppWindowsAction();
return Clutter.EVENT_STOP;
} else if (opt.WINDOW_ICON_CLICK_ACTION === 2 && opt.WINDOW_THUMBNAIL_ENABLED) {
this._removeLaters();
Me.Modules.winTmbModule.createThumbnail(metaWindow);
return Clutter.EVENT_STOP;
}
} /* else if (act.get_button() === Clutter.BUTTON_SECONDARY) {
return Clutter.EVENT_STOP;
}*/
return Clutter.EVENT_PROPAGATE;
});
this._icon.add_action(iconClickAction);
}
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage); const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
const iconOverlap = opt.WIN_PREVIEW_ICON_SIZE * ICON_OVERLAP; this._title = new St.Label({
// we cannot get proper title height before it gets to the stage, so 35 is estimated height + spacing visible: false,
this._title.get_constraints()[1].offset = scaleFactor * (-iconOverlap - 35); style_class: 'window-caption',
this.set_child_above_sibling(this._title, null); text: this._getCaption(),
reactive: true,
});
this._title.clutter_text.single_line_mode = true;
this._title.add_constraint(new Clutter.BindConstraint({
source: windowContainer,
coordinate: Clutter.BindCoordinate.X,
}));
let offset;
if (opt.WIN_TITLES_POSITION < 2) {
// we cannot get proper title height before it gets to the stage, so 35 is estimated height + spacing
offset = -scaleFactor * (ICON_SIZE * ICON_OVERLAP + 35);
} else {
offset = scaleFactor * (ICON_SIZE * (1 - ICON_OVERLAP) + 4);
}
this._title.add_constraint(new Clutter.BindConstraint({
source: windowContainer,
coordinate: Clutter.BindCoordinate.Y,
offset,
}));
this._title.add_constraint(new Clutter.AlignConstraint({
source: windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
factor: 0.5,
}));
this._title.add_constraint(new Clutter.AlignConstraint({
source: windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({ x: -1, y: 0 }),
factor: 1,
}));
this._title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
this.label_actor = this._title;
this.metaWindow.connectObject(
'notify::title', () => (this._title.text = this._getCaption()),
this);
const layout = Meta.prefs_get_button_layout();
this._closeButtonSide =
layout.left_buttons.includes(Meta.ButtonFunction.CLOSE)
? St.Side.LEFT : St.Side.RIGHT;
if (Me.shellVersion < 43) {
this._closeButton = new St.Button({
visible: false,
style_class: 'window-close',
child: new St.Icon({ icon_name: 'preview-close-symbolic' }),
});
} else {
this._closeButton = new St.Button({
visible: false,
style_class: 'window-close',
icon_name: 'preview-close-symbolic',
});
}
this._closeButton.add_constraint(new Clutter.BindConstraint({
source: windowContainer,
coordinate: Clutter.BindCoordinate.POSITION,
}));
this._closeButton.add_constraint(new Clutter.AlignConstraint({
source: windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
pivot_point: new Graphene.Point({ x: 0.5, y: -1 }),
factor: this._closeButtonSide === St.Side.LEFT ? 0 : 1,
}));
this._closeButton.add_constraint(new Clutter.AlignConstraint({
source: windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({ x: -1, y: 0.5 }),
factor: 0,
}));
this._closeButton.connect('clicked', () => this._deleteAll());
this.add_child(this._title);
this.add_child(this._icon);
this.add_child(this._closeButton);
this._overviewAdjustment.connectObject(
'notify::value', () => this._updateIconScale(), this);
this._updateIconScale();
this.connect('notify::realized', () => {
if (!this.realized)
return;
this._title.ensure_style();
this._icon.ensure_style();
});
if (ICON_SIZE < 22) {
// disable app icon
this._icon.hide();
} else {
this._updateIconScale();
}
// if window is created while the overview is shown, icon and title should be visible immediately // if window is created while the overview is shown, icon and title should be visible immediately
if (Main.overview._overview._controls._stateAdjustment.value < 1) { if (Main.overview._overview._controls._stateAdjustment.value < 1) {
this._icon.scale_x = 0; this._icon.scale_x = 0;
@ -124,9 +393,9 @@ const WindowPreviewCommon = {
if (global.get_pointer()[0] === opt.showingPointerX || Main.overview._overview._controls._stateAdjustment.value < 1) if (global.get_pointer()[0] === opt.showingPointerX || Main.overview._overview._controls._stateAdjustment.value < 1)
return; return;
const adjustment = this._workspace._background._stateAdjustment;
opt.WORKSPACE_MODE = 1; opt.WORKSPACE_MODE = 1;
_Util.exposeWindows(adjustment, false); const view = this._workspace.get_parent();
view.exposeWindows(this._workspace.metaWorkspace.index());
this.disconnect(this._wsStateConId); this.disconnect(this._wsStateConId);
}); });
} }
@ -136,53 +405,39 @@ const WindowPreviewCommon = {
this._stateAdjustmentSigId = this._workspace.stateAdjustment.connect('notify::value', this._updateIconScale.bind(this)); this._stateAdjustmentSigId = this._workspace.stateAdjustment.connect('notify::value', this._updateIconScale.bind(this));
} }
// replace click action with custom one const metaWin = this.metaWindow;
const action = this.get_actions()[0]; if (opt.DASH_ISOLATE_WS && !metaWin._wsChangedConId) {
metaWin._wsChangedConId = metaWin.connect('workspace-changed',
const handlerId = GObject.signal_handler_find(action, { signalId: 'clicked' }); () => Main.overview.dash._queueRedisplay());
if (handlerId) } else if (!opt.DASH_ISOLATE_WS && metaWin._wsChangedConId) {
action.disconnect(handlerId); metaWin.disconnect(metaWin._wsChangedConId);
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) {
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;
});
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);
} }
}, },
_closeWinAction() {
this.hide();
this._deleteAll();
},
_removeLaters() {
// 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) {
if (Meta.later_remove)
Meta.later_remove(this._longPressLater);
else
global.compositor.get_laters().remove(this._longPressLater);
delete this._longPressLater;
}
},
_searchAppWindowsAction() {
this._removeLaters();
const tracker = Shell.WindowTracker.get_default();
const appName = tracker.get_window_app(this.metaWindow).get_name();
Me.Util.activateSearchProvider(`${Me.WSP_PREFIX} ${appName}`);
},
_updateIconScale() { _updateIconScale() {
let { currentState, initialState, finalState } = let { currentState, initialState, finalState } =
this._overviewAdjustment.getStateTransitionParams(); this._overviewAdjustment.getStateTransitionParams();
@ -192,7 +447,7 @@ const WindowPreviewCommon = {
const visible = const visible =
(initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN) && (initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN) &&
!(finalState === ControlsState.APP_GRID && primaryMonitor); !(finalState === ControlsState.APP_GRID && opt.WS_ANIMATION && primaryMonitor);
let scale = 0; let scale = 0;
if (visible) if (visible)
@ -210,7 +465,6 @@ const WindowPreviewCommon = {
else if (primaryMonitor && currentState > ControlsState.WINDOW_PICKER) else if (primaryMonitor && currentState > ControlsState.WINDOW_PICKER)
scale = 0; scale = 0;
// in static workspace mode show icon and title on windows expose // in static workspace mode show icon and title on windows expose
if (opt.OVERVIEW_MODE) { if (opt.OVERVIEW_MODE) {
if (currentState === 1) if (currentState === 1)
@ -219,29 +473,32 @@ const WindowPreviewCommon = {
return; return;
} }
if (!opt.WS_ANIMATION && (Main.overview._overview.controls._searchController.searchActive ||
((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
(initialState === ControlsState.APP_GRID && finalState === ControlsState.WINDOW_PICKER)))
)
return;
// 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
if (scale === 1) { if (scale === 1) {
this._icon.ease({ this._icon.set({
duration: 50, scale_x: 1,
scale_x: scale, scale_y: 1,
scale_y: scale,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
}); });
this._title.ease({ this._title.ease({
duration: 100, duration: 100,
opacity: 255, opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
}); });
} else if (this._icon.scale_x !== 0) { } else {
this._icon.set({
scale_x: 0,
scale_y: 0,
});
this._title.opacity = 0; this._title.opacity = 0;
this._icon.set({
scale_x: scale,
scale_y: scale,
});
} }
// 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
}, },
showOverlay(animate) { showOverlay(animate) {
@ -252,7 +509,7 @@ const WindowPreviewCommon = {
return; return;
this._overlayShown = true; this._overlayShown = true;
if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW) if (opt.WIN_TITLES_POSITION === 2)
this._restack(); this._restack();
// If we're supposed to animate and an animation in our direction // If we're supposed to animate and an animation in our direction
@ -263,7 +520,7 @@ const WindowPreviewCommon = {
ongoingTransition.get_interval().peek_final_value() === 255) ongoingTransition.get_interval().peek_final_value() === 255)
return; return;
const toShow = this._windowCanClose() const toShow = this._windowCanClose() && opt.SHOW_CLOSE_BUTTON
? [this._closeButton] ? [this._closeButton]
: []; : [];
@ -301,12 +558,12 @@ const WindowPreviewCommon = {
if (!this._overlayShown) if (!this._overlayShown)
return; return;
this._overlayShown = false; this._overlayShown = false;
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) if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW && Main.overview._overview.controls._stateAdjustment.value < 1)
this._activateSelected = true;
if (opt.WIN_TITLES_POSITION === 2)
this._restack(); this._restack();
// If we're supposed to animate and an animation in our direction // If we're supposed to animate and an animation in our direction
@ -353,14 +610,11 @@ const WindowPreviewCommon = {
this._delegate = null; this._delegate = null;
if (this._longPressLater) { if (this._longPressLater) {
if (shellVersion >= 44) { if (Meta.later_add)
const laters = global.compositor.get_laters(); Meta.later_add(Meta.LaterType.BEFORE_REDRAW, this._longPressLater);
laters.remove(this._longPressLater); else
delete this._longPressLater; global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, this._longPressLater);
} else { delete this._longPressLater;
Meta.later_remove(this._longPressLater);
delete this._longPressLater;
}
} }
if (this._idleHideOverlayId > 0) { if (this._idleHideOverlayId > 0) {

View file

@ -9,30 +9,23 @@
'use strict'; 'use strict';
const { GLib, Gio, Meta, St, Shell } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Settings = Me.imports.lib.settings;
const _Util = Me.imports.lib.util;
let Me;
let opt;
// gettext // gettext
const _ = Settings._; let _;
const shellVersion = Settings.shellVersion;
const ModifierType = imports.gi.Clutter.ModifierType;
let windowSearchProvider;
let _enableTimeoutId = 0;
// prefix helps to eliminate results from other search providers // prefix helps to eliminate results from other search providers
// so it needs to be something less common // so it needs to be something less common
// needs to be accessible from vw module // needs to be accessible from vw module
var prefix = 'wq//'; const PREFIX = 'wq//';
let opt;
const Action = { const Action = {
NONE: 0, NONE: 0,
@ -42,66 +35,77 @@ const Action = {
MOVE_ALL_TO_WS: 4, MOVE_ALL_TO_WS: 4,
}; };
function getOverviewSearchResult() { var WindowSearchProviderModule = class {
return Main.overview._overview.controls._searchController._searchResults; // export for other modules
} static _PREFIX = PREFIX;
constructor(me) {
Me = me;
opt = Me.opt;
_ = Me.gettext;
function update(reset = false) { this._firstActivation = true;
opt = Me.imports.lib.settings.opt; this.moduleEnabled = false;
if (!reset && opt.WINDOW_SEARCH_PROVIDER_ENABLED && !windowSearchProvider) { // export for other modules
enable();
} else if (reset || !opt.WINDOW_SEARCH_PROVIDER_ENABLED) { this._windowSearchProvider = null;
disable(); this._enableTimeoutId = 0;
}
cleanGlobals() {
Me = null;
opt = null; opt = null;
_ = null;
} }
}
function enable() { update(reset) {
// delay because Fedora had problem to register a new provider soon after Shell restarts this.moduleEnabled = opt.get('windowSearchProviderModule');
_enableTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, reset = reset || !this.moduleEnabled;
2000,
() => { if (reset && !this._firstActivation) {
if (!windowSearchProvider) { this._disableModule();
windowSearchProvider = new WindowSearchProvider(opt); } else if (!reset) {
getOverviewSearchResult()._registerProvider( this._firstActivation = false;
windowSearchProvider this._activateModule();
);
}
_enableTimeoutId = 0;
return GLib.SOURCE_REMOVE;
} }
); if (reset && this._firstActivation)
} console.debug(' WindowSearchProviderModule - Keeping untouched');
}
function disable() { _activateModule() {
if (windowSearchProvider) { // delay because Fedora had problem to register a new provider soon after Shell restarts
getOverviewSearchResult()._unregisterProvider( this._enableTimeoutId = GLib.timeout_add(
windowSearchProvider GLib.PRIORITY_DEFAULT,
2000,
() => {
if (!this._windowSearchProvider) {
this._windowSearchProvider = new WindowSearchProvider(opt);
this._getOverviewSearchResult()._registerProvider(this._windowSearchProvider);
}
this._enableTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
); );
windowSearchProvider = null; console.debug(' WindowSearchProviderModule - Activated');
} }
if (_enableTimeoutId) {
GLib.source_remove(_enableTimeoutId); _disableModule() {
_enableTimeoutId = 0; if (this._windowSearchProvider) {
this._getOverviewSearchResult()._unregisterProvider(this._windowSearchProvider);
this._windowSearchProvider = null;
}
if (this._enableTimeoutId) {
GLib.source_remove(this._enableTimeoutId);
this._enableTimeoutId = 0;
}
console.debug(' WindowSearchProviderModule - Disabled');
} }
}
function makeResult(window, i) { _getOverviewSearchResult() {
const app = Shell.WindowTracker.get_default().get_window_app(window); return Main.overview._overview.controls._searchController._searchResults;
const appName = app ? app.get_name() : 'Unknown'; }
const windowTitle = window.get_title(); };
const wsIndex = window.get_workspace().index();
return {
'id': i,
// convert all accented chars to their basic form and lower case for search
'name': `${wsIndex + 1}: ${windowTitle} ${appName}`.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(),
appName,
windowTitle,
window,
};
}
const closeSelectedRegex = /^\/x!$/; const closeSelectedRegex = /^\/x!$/;
const closeAllResultsRegex = /^\/xa!$/; const closeAllResultsRegex = /^\/xa!$/;
@ -110,15 +114,22 @@ const moveAllToWsRegex = /^\/ma[0-9]+$/;
const WindowSearchProvider = class WindowSearchProvider { const WindowSearchProvider = class WindowSearchProvider {
constructor() { constructor() {
this.id = `open-windows@${Me.metadata.uuid}`; this.id = 'open-windows';
this.appInfo = Gio.AppInfo.create_from_commandline('true', _('Open Windows'), null); const appSystem = Shell.AppSystem.get_default();
this.appInfo.get_description = () => _('List of open windows'); // use arbitrary app to get complete appInfo object
this.appInfo.get_name = () => _('Open Windows'); let appInfo = appSystem.lookup_app('com.matjakeman.ExtensionManager.desktop')?.get_app_info();
this.appInfo.get_id = () => this.id; if (!appInfo)
this.appInfo.get_icon = () => Gio.icon_new_for_string('focus-windows-symbolic'); appInfo = appSystem.lookup_app('org.gnome.Extensions.desktop')?.get_app_info();
this.appInfo.should_show = () => true; if (!appInfo)
appInfo = Gio.AppInfo.create_from_commandline('true', _('Open Windows'), null);
appInfo.get_description = () => _('Search open windows');
appInfo.get_name = () => _('Open Windows');
appInfo.get_id = () => this.id;
appInfo.get_icon = () => Gio.icon_new_for_string('focus-windows-symbolic');
appInfo.should_show = () => true;
this.canLaunchSearch = true; this.appInfo = appInfo;
this.canLaunchSearch = false;
this.isRemoteProvider = false; this.isRemoteProvider = false;
this.action = 0; this.action = 0;
@ -128,7 +139,7 @@ const WindowSearchProvider = class WindowSearchProvider {
// do not modify original terms // do not modify original terms
let termsCopy = [...terms]; let termsCopy = [...terms];
// search for terms without prefix // search for terms without prefix
termsCopy[0] = termsCopy[0].replace(prefix, ''); termsCopy[0] = termsCopy[0].replace(PREFIX, '');
/* if (gOptions.get('searchWindowsCommands')) { /* if (gOptions.get('searchWindowsCommands')) {
this.action = 0; this.action = 0;
@ -167,9 +178,9 @@ const WindowSearchProvider = class WindowSearchProvider {
let m; let m;
for (let key in candidates) { for (let key in candidates) {
if (opt.SEARCH_FUZZY) if (opt.SEARCH_FUZZY)
m = _Util.fuzzyMatch(term, candidates[key].name); m = Me.Util.fuzzyMatch(term, candidates[key].name);
else else
m = _Util.strictMatch(term, candidates[key].name); m = Me.Util.strictMatch(term, candidates[key].name);
if (m !== -1) if (m !== -1)
results.push({ weight: m, id: key }); results.push({ weight: m, id: key });
@ -178,7 +189,19 @@ const WindowSearchProvider = class WindowSearchProvider {
results.sort((a, b) => a.weight > b.weight); results.sort((a, b) => a.weight > b.weight);
const currentWs = global.workspace_manager.get_active_workspace_index(); const currentWs = global.workspace_manager.get_active_workspace_index();
// prefer current workspace // prefer current workspace
results.sort((a, b) => (this.windows[a.id].window.get_workspace().index() !== currentWs) && (this.windows[b.id].window.get_workspace().index() === currentWs)); switch (opt.WINDOW_SEARCH_ORDER) {
case 1: // MRU - current ws first
results.sort((a, b) => (this.windows[a.id].window.get_workspace().index() !== currentWs) && (this.windows[b.id].window.get_workspace().index() === currentWs));
break;
case 2: // MRU - by workspace
results.sort((a, b) => this.windows[a.id].window.get_workspace().index() > this.windows[b.id].window.get_workspace().index());
break;
case 3: // Stable sequence - by workspace
results.sort((a, b) => this.windows[a.id].window.get_stable_sequence() > this.windows[b.id].window.get_stable_sequence());
results.sort((a, b) => this.windows[a.id].window.get_workspace().index() > this.windows[b.id].window.get_workspace().index());
break;
}
results.sort((a, b) => (_terms !== ' ') && (a.weight > 0 && b.weight === 0)); results.sort((a, b) => (_terms !== ' ') && (a.weight > 0 && b.weight === 0));
this.resultIds = results.map(item => item.id); this.resultIds = results.map(item => item.id);
@ -187,7 +210,7 @@ const WindowSearchProvider = class WindowSearchProvider {
getResultMetas(resultIds, callback = null) { getResultMetas(resultIds, callback = null) {
const metas = resultIds.map(id => this.getResultMeta(id)); const metas = resultIds.map(id => this.getResultMeta(id));
if (shellVersion >= 43) if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(metas)); return new Promise(resolve => resolve(metas));
else else
callback(metas); callback(metas);
@ -210,12 +233,29 @@ const WindowSearchProvider = class WindowSearchProvider {
}; };
} }
makeResult(window, i) {
const app = Shell.WindowTracker.get_default().get_window_app(window);
const appName = app ? app.get_name() : 'Unknown';
const windowTitle = window.get_title();
const wsIndex = window.get_workspace().index();
return {
'id': i,
// convert all accented chars to their basic form and lower case for search
'name': `${wsIndex + 1}: ${windowTitle} ${appName}`.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(),
appName,
windowTitle,
window,
};
}
launchSearch(/* terms, timeStamp*/) { launchSearch(/* terms, timeStamp*/) {
} }
activateResult(resultId/* , terms, timeStamp*/) { activateResult(resultId/* , terms, timeStamp*/) {
const isCtrlPressed = _Util.isCtrlPressed(); const isCtrlPressed = Me.Util.isCtrlPressed();
const isShiftPressed = _Util.isShiftPressed(); const isShiftPressed = Me.Util.isShiftPressed();
this.action = 0; this.action = 0;
this.targetWs = 0; this.targetWs = 0;
@ -276,15 +316,16 @@ const WindowSearchProvider = class WindowSearchProvider {
this.windows = windows = {}; this.windows = windows = {};
global.display.get_tab_list(Meta.TabList.NORMAL, null).filter(w => w.get_workspace() !== null).map( global.display.get_tab_list(Meta.TabList.NORMAL, null).filter(w => w.get_workspace() !== null).map(
(v, i) => { (v, i) => {
windows[`${i}-${v.get_id()}`] = makeResult(v, `${i}-${v.get_id()}`); windows[`${i}-${v.get_id()}`] = this.makeResult(v, `${i}-${v.get_id()}`);
return windows[`${i}-${v.get_id()}`]; return windows[`${i}-${v.get_id()}`];
} }
); );
if (shellVersion >= 43) if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(this._getResultSet(terms))); return new Promise(resolve => resolve(this._getResultSet(terms)));
else else
callback(this._getResultSet(terms)); callback(this._getResultSet(terms));
return null; return null;
} }
@ -293,13 +334,15 @@ const WindowSearchProvider = class WindowSearchProvider {
return results; return results;
} }
getSubsearchResultSet(previousResults, terms, callback/* , cancellable*/) { getSubsearchResultSet(previousResults, terms, callback) {
// if we return previous results, quick typers get non-actual results if (Me.shellVersion < 43) {
callback(this._getResultSet(terms)); this.getSubsearchResultSet42(terms, callback);
return null;
}
return this.getInitialResultSet(terms);
} }
/* createResultObject(resultMeta) { getSubsearchResultSet42(terms, callback) {
const app = Shell.WindowTracker.get_default().get_window_app(resultMeta.id); callback(this._getResultSet(terms));
return new AppIcon(app); }
}*/
}; };

View file

@ -10,51 +10,68 @@
'use strict'; 'use strict';
const { St, Graphene } = imports.gi; const Graphene = imports.gi.Graphene;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const Util = imports.misc.util;
const Workspace = imports.ui.workspace; const Workspace = imports.ui.workspace;
const Util = imports.misc.util;
const ExtensionUtils = imports.misc.extensionUtils; let Me;
const Me = ExtensionUtils.getCurrentExtension();
const _Util = Me.imports.lib.util;
let _overrides;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { var WorkspaceModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('workspaceModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
// don't even touch this module if disabled this._firstActivation = true;
if (_firstRun && reset) this.moduleEnabled = false;
return; this._overrides = null;
_firstRun = false;
if (_overrides)
_overrides.removeAll();
if (reset) {
Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
_overrides = null;
opt = null;
return;
} }
_overrides = new _Util.Overrides(); cleanGlobals() {
Me = null;
opt = null;
}
_overrides.addOverride('WorkspaceBackground', Workspace.WorkspaceBackground.prototype, WorkspaceBackground); update(reset) {
this.moduleEnabled = opt.get('workspaceModule');
const conflict = false;
// fix overlay base for Vertical Workspaces reset = reset || !this.moduleEnabled || conflict;
_overrides.addOverride('WorkspaceLayout', Workspace.WorkspaceLayout.prototype, WorkspaceLayout);
}
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' WorkspaceModule - Keeping untouched');
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
this._overrides.addOverride('WorkspaceBackground', Workspace.WorkspaceBackground.prototype, WorkspaceBackground);
// fix overlay base for Vertical Workspaces
this._overrides.addOverride('WorkspaceLayout', Workspace.WorkspaceLayout.prototype, WorkspaceLayout);
console.debug(' WorkspaceModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
console.debug(' WorkspaceModule - Disabled');
}
};
// workaround for upstream bug (that is not that invisible in default shell) // workaround for upstream bug (that is not that invisible in default shell)
// smaller window cannot be scaled below 0.95 (WINDOW_PREVIEW_MAXIMUM_SCALE) // smaller window cannot be scaled below 0.95 (WINDOW_PREVIEW_MAXIMUM_SCALE)

View file

@ -9,81 +9,147 @@
*/ */
'use strict'; 'use strict';
const Main = imports.ui.main; const Main = imports.ui.main;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const WorkspaceAnimation = imports.ui.workspaceAnimation; const WorkspaceAnimation = imports.ui.workspaceAnimation;
const Me = imports.misc.extensionUtils.getCurrentExtension(); const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const _Util = Me.imports.lib.util;
// first reference to constant defined using const in other module returns undefined, the MonitorGroup const will remain empty and unused let Me;
let MonitorGroupDummy = WorkspaceAnimation.MonitorGroup;
MonitorGroupDummy = null;
let _origBaseDistance;
let _wsAnimationSwipeBeginId;
let _wsAnimationSwipeUpdateId;
let _wsAnimationSwipeEndId;
let _overrides;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { var WorkspaceAnimationModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('workspaceAnimationModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
// don't even touch this module if disabled // first reference to constant defined using const in other module returns undefined, the MonitorGroup const will remain empty and unused
if (_firstRun && reset) this.dummy = WorkspaceAnimation.MonitorGroup;
return;
_firstRun = false; this._firstActivation = true;
this.moduleEnabled = false;
this._overrides = null;
this._origBaseDistance = null;
this._wsAnimationSwipeBeginId = 0;
this._wsAnimationSwipeUpdateId = 0;
this._wsAnimationSwipeEndId = 0;
}
if (_overrides) cleanGlobals() {
_overrides.removeAll(); Me = null;
if (reset || !moduleEnabled) {
_connectWsAnimationSwipeTracker(true);
_overrideMonitorGroupProperty(true);
_overrides = null;
opt = null; opt = null;
return;
} }
if (opt.STATIC_WS_SWITCHER_BG) { update(reset) {
_overrides = new _Util.Overrides(); this.moduleEnabled = opt.get('workspaceAnimationModule');
_overrideMonitorGroupProperty(); const conflict = false;
_overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
reset = reset || !this.moduleEnabled || conflict;
// don't touch the original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' WorkspaceAnimationModule - Keeping untouched');
} }
_connectWsAnimationSwipeTracker(); _activateModule() {
} if (!this._overrides)
this._overrides = new Me.Util.Overrides();
// remove spacing between workspaces during transition to remove flashing wallpaper between workspaces with maximized windows if (opt.STATIC_WS_SWITCHER_BG) {
function _overrideMonitorGroupProperty(reset = false) { this._overrideMonitorGroupProperty();
if (!_origBaseDistance) this._overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
_origBaseDistance = Object.getOwnPropertyDescriptor(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance').get; }
let getter; this._connectWsAnimationSwipeTracker();
if (reset) { console.debug(' WorkspaceAnimationModule - Activated');
if (_origBaseDistance)
getter = { get: _origBaseDistance };
} else {
getter = {
get() {
// const spacing = 100 * imports.gi.St.ThemeContext.get_for_stage(global.stage).scale_factor;
const spacing = 0;
if (global.workspace_manager.layout_rows === -1)
return this._monitor.height + spacing + (opt.PANEL_MODE ? Main.panel.height : 0); // compensation for hidden panel
else
return this._monitor.width + spacing;
},
};
} }
if (getter) _disableModule() {
Object.defineProperty(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance', getter); if (this._overrides)
} this._overrides.removeAll();
this._overrides = null;
const reset = true;
this._connectWsAnimationSwipeTracker(reset);
this._overrideMonitorGroupProperty(reset);
console.debug(' WorkspaceAnimationModule - Disabled');
}
_overrideMonitorGroupProperty(reset = false) {
if (!this._origBaseDistance)
this._origBaseDistance = Object.getOwnPropertyDescriptor(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance').get;
let getter;
if (reset) {
if (this._origBaseDistance)
getter = { get: this._origBaseDistance };
} else {
getter = {
get() {
// const spacing = 100 * imports.gi.St.ThemeContext.get_for_stage(global.stage).scale_factor;
const spacing = 0;
if (global.workspace_manager.layout_rows === -1)
return this._monitor.height + spacing + (opt.PANEL_MODE ? Main.panel.height : 0); // compensation for hidden panel
else
return this._monitor.width + spacing;
},
};
}
if (getter)
Object.defineProperty(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance', getter);
}
_connectWsAnimationSwipeTracker(reset = false) {
if (reset) {
if (this._wsAnimationSwipeBeginId) {
Main.wm._workspaceAnimation._swipeTracker.disconnect(this._wsAnimationSwipeBeginId);
this._wsAnimationSwipeBeginId = 0;
}
if (this._wsAnimationSwipeEndId) {
Main.wm._workspaceAnimation._swipeTracker.disconnect(this._wsAnimationSwipeEndId);
this._wsAnimationSwipeEndId = 0;
}
} else if (!this._wsAnimationSwipeBeginId) {
// display ws switcher popup when gesture begins and connect progress
this._wsAnimationSwipeBeginId = Main.wm._workspaceAnimation._swipeTracker.connect('begin', () => this._connectWsAnimationProgress(true));
// we want to be sure that popup with the final ws index show up when gesture ends
this._wsAnimationSwipeEndId = Main.wm._workspaceAnimation._swipeTracker.connect('end', (tracker, duration, endProgress) => this._connectWsAnimationProgress(false, endProgress));
}
}
_connectWsAnimationProgress(connect, endProgress = null) {
if (Main.overview.visible)
return;
if (connect && !this._wsAnimationSwipeUpdateId) {
this._wsAnimationSwipeUpdateId = Main.wm._workspaceAnimation._swipeTracker.connect('update', (tracker, progress) => this._showWsSwitcherPopup(progress));
} else if (!connect && this._wsAnimationSwipeUpdateId) {
Main.wm._workspaceAnimation._swipeTracker.disconnect(this._wsAnimationSwipeUpdateId);
this._wsAnimationSwipeUpdateId = 0;
this._showWsSwitcherPopup(Math.round(endProgress));
}
}
_showWsSwitcherPopup(progress) {
if (Main.overview.visible)
return;
const wsIndex = Math.round(progress);
if (Main.wm._workspaceSwitcherPopup === null) {
Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
Main.wm._workspaceSwitcherPopup.connect('destroy', () => {
Main.wm._workspaceSwitcherPopup = null;
});
}
Main.wm._workspaceSwitcherPopup.display(wsIndex);
}
};
const MonitorGroup = { const MonitorGroup = {
// injection to _init() // injection to _init()
@ -119,7 +185,9 @@ const MonitorGroup = {
// hide (scale to 0) all non-sticky windows, their clones will be animated // hide (scale to 0) all non-sticky windows, their clones will be animated
global.get_window_actors().forEach(actor => { global.get_window_actors().forEach(actor => {
const metaWin = actor.metaWindow; const metaWin = actor.metaWindow;
if (metaWin?.get_monitor() === this._monitor.index && !(metaWin?.wm_class === 'conky' && metaWin?.is_on_all_workspaces())) { //* && !w.is_on_all_workspaces()*/) { if (metaWin?.get_monitor() === this._monitor.index &&
!(metaWin?.wm_class === 'conky' && metaWin?.is_on_all_workspaces()) &&
!(metaWin?.wm_class === 'Gjs' && metaWin?.is_on_all_workspaces())) { // DING extension uses window with Gjs class
// hide original window. we cannot use opacity since it also affects clones. // hide original window. we cannot use opacity since it also affects clones.
// scaling them to 0 works well // scaling them to 0 works well
actor.scale_x = 0; actor.scale_x = 0;
@ -136,49 +204,3 @@ const MonitorGroup = {
}); });
}, },
}; };
function _connectWsAnimationSwipeTracker(reset = false) {
if (reset) {
if (_wsAnimationSwipeBeginId) {
Main.wm._workspaceAnimation._swipeTracker.disconnect(_wsAnimationSwipeBeginId);
_wsAnimationSwipeBeginId = 0;
}
if (_wsAnimationSwipeEndId) {
Main.wm._workspaceAnimation._swipeTracker.disconnect(_wsAnimationSwipeEndId);
_wsAnimationSwipeEndId = 0;
}
} else if (!_wsAnimationSwipeBeginId) {
// display ws switcher popup when gesture begins and connect progress
_wsAnimationSwipeBeginId = Main.wm._workspaceAnimation._swipeTracker.connect('begin', () => _connectWsAnimationProgress(true));
// we want to be sure that popup with the final ws index show up when gesture ends
_wsAnimationSwipeEndId = Main.wm._workspaceAnimation._swipeTracker.connect('end', (tracker, duration, endProgress) => _connectWsAnimationProgress(false, endProgress));
}
}
function _connectWsAnimationProgress(connect, endProgress = null) {
if (Main.overview.visible)
return;
if (connect && !_wsAnimationSwipeUpdateId) {
_wsAnimationSwipeUpdateId = Main.wm._workspaceAnimation._swipeTracker.connect('update', (tracker, progress) => _showWsSwitcherPopup(progress));
} else if (!connect && _wsAnimationSwipeUpdateId) {
Main.wm._workspaceAnimation._swipeTracker.disconnect(_wsAnimationSwipeUpdateId);
_wsAnimationSwipeUpdateId = 0;
_showWsSwitcherPopup(Math.round(endProgress));
}
}
function _showWsSwitcherPopup(progress) {
if (Main.overview.visible)
return;
const wsIndex = Math.round(progress);
if (Main.wm._workspaceSwitcherPopup === null) {
Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
Main.wm._workspaceSwitcherPopup.connect('destroy', () => {
Main.wm._workspaceSwitcherPopup = null;
});
}
Main.wm._workspaceSwitcherPopup.display(wsIndex);
}

View file

@ -13,52 +13,71 @@
const Main = imports.ui.main; const Main = imports.ui.main;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup; const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const ExtensionUtils = imports.misc.extensionUtils; let Me;
const Me = ExtensionUtils.getCurrentExtension();
const _Util = Me.imports.lib.util;
let _overrides;
let opt; let opt;
let _firstRun = true;
function update(reset = false) { var WorkspaceSwitcherPopupModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
const moduleEnabled = opt.get('workspaceSwitcherPopupModule', true); Me = me;
reset = reset || !moduleEnabled; opt = Me.opt;
// don't even touch this module if disabled this._firstActivation = true;
if (_firstRun && reset) this.moduleEnabled = false;
return; this._overrides = null;
}
_firstRun = false; cleanGlobals() {
Me = null;
if (_overrides)
_overrides.removeAll();
if (reset) {
_overrides = null;
opt = null; opt = null;
return;
} }
_overrides = new _Util.Overrides(); update(reset) {
this.moduleEnabled = opt.get('workspaceSwitcherPopupModule');
const conflict = Me.Util.getEnabledExtensions('workspace-switcher-manager').length ||
Me.Util.getEnabledExtensions('WsSwitcherPopupManager').length;
const enabled = global.settings.get_strv('enabled-extensions'); if (conflict && !reset)
const allowWsPopupInjection = !(enabled.includes('workspace-switcher-manager@G-dH.github.com') || enabled.includes('WsSwitcherPopupManager@G-dH.github.com-dev')); console.warn(`[${Me.metadata.name}] Warning: "WorkspaceSwitcherPopup" module disabled due to potential conflict with another extension`);
if (allowWsPopupInjection) { // 1-VERTICAL, 0-HORIZONTAL
_overrides.addOverride('WorkspaceSwitcherPopup', WorkspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype, WorkspaceSwitcherPopupOverride); reset = reset || !this.moduleEnabled || conflict;
// don't touch original code if module disabled
if (reset && !this._firstActivation) {
this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' WorkspaceSwitcherPopupModule - Keeping untouched');
} }
}
const WorkspaceSwitcherPopupOverride = { _activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
this._overrides.addOverride('WorkspaceSwitcherPopup', WorkspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype, WorkspaceSwitcherPopupCommon);
console.debug(' WorkspaceSwitcherPopupModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
console.debug(' WorkspaceSwitcherPopupModule - Disabled');
}
};
const WorkspaceSwitcherPopupCommon = {
// injection to _init() // injection to _init()
after__init() { after__init() {
if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
this._list.vertical = true; this._list.vertical = true;
} }
this._list.set_style('margin: 0;'); this._list.set_style('margin: 0;');
this.remove_constraint(this.get_constraints()[0]); if (this.get_constraints()[0])
this.remove_constraint(this.get_constraints()[0]);
}, },
// injection to display() // injection to display()

View file

@ -10,56 +10,90 @@
'use strict'; 'use strict';
const { GLib, Clutter, Graphene, Meta, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const AppDisplay = imports.ui.appDisplay;
const Background = imports.ui.background;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const Main = imports.ui.main; const Main = imports.ui.main;
const Background = imports.ui.background; const OverviewControls = imports.ui.overviewControls;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail; const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
let Me;
let opt;
const ThumbnailState = WorkspaceThumbnail.ThumbnailState; const ThumbnailState = WorkspaceThumbnail.ThumbnailState;
const ControlsState = OverviewControls.ControlsState;
const ControlsState = imports.ui.overviewControls.ControlsState;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
// gettext
const _ = Me.imports.lib.settings._;
const _Util = Me.imports.lib.util;
const shellVersion = _Util.shellVersion;
let _overrides;
const WORKSPACE_CUT_SIZE = 10; const WORKSPACE_CUT_SIZE = 10;
const _originalMaxThumbnailScale = WorkspaceThumbnail.MAX_THUMBNAIL_SCALE;
let opt = null; var WorkspaceThumbnailModule = class {
constructor(me) {
Me = me;
opt = Me.opt;
function update(reset = false) { this._firstActivation = true;
if (_overrides) this.moduleEnabled = false;
_overrides.removeAll(); this._overrides = null;
if (reset) {
if (_originalMaxThumbnailScale)
WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = _originalMaxThumbnailScale;
_overrides = null;
opt = null;
return;
} }
opt = Me.imports.lib.settings.opt; cleanGlobals() {
_overrides = new _Util.Overrides(); Me = null;
opt = null;
}
// don't limit max thumbnail scale for other clients than overview, for example AATWS. update(reset) {
WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = 1; this.moduleEnabled = true;
const conflict = false;
_overrides.addOverride('WorkspaceThumbnail', WorkspaceThumbnail.WorkspaceThumbnail.prototype, WorkspaceThumbnailCommon); reset = reset || !this.moduleEnabled || conflict;
_overrides.addOverride('ThumbnailsBoxCommon', WorkspaceThumbnail.ThumbnailsBox.prototype, ThumbnailsBoxCommon);
// replacing opt.ORIENTATION local constant with boxOrientation internal variable allows external customers such as the AATWS extension to control the box orientation. // don't touch the original code if module disabled
Main.overview._overview.controls._thumbnailsBox._boxOrientation = opt.ORIENTATION; if (reset && !this._firstActivation) {
} this._disableModule();
} else if (!reset) {
this._firstActivation = false;
this._activateModule();
}
if (reset && this._firstActivation)
console.debug(' WorkspaceThumbnailModule - Keeping untouched');
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
if (!this._originalMaxThumbnailScale)
this._originalMaxThumbnailScale = WorkspaceThumbnail.MAX_THUMBNAIL_SCALE;
// don't limit max thumbnail scale for other clients than overview, specifically AATWS.
WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = 1;
// WorkspaceThumbnail.ThumbnailsBox._MAX_THUMBNAIL_SCALE = 1;
this._overrides.addOverride('WorkspaceThumbnail', WorkspaceThumbnail.WorkspaceThumbnail.prototype, WorkspaceThumbnailCommon);
this._overrides.addOverride('ThumbnailsBoxCommon', WorkspaceThumbnail.ThumbnailsBox.prototype, ThumbnailsBoxCommon);
// replacing opt.ORIENTATION local constant with boxOrientation internal variable allows external customers such as the AATWS extension to control the box orientation.
Main.overview._overview.controls._thumbnailsBox._boxOrientation = opt.ORIENTATION;
console.debug(' WorkspaceThumbnailModule - Activated');
}
_disableModule() {
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = this._originalMaxThumbnailScale;
console.debug(' WorkspaceThumbnailModule - Disabled');
}
};
const WorkspaceThumbnailCommon = { const WorkspaceThumbnailCommon = {
// injection to _init() // injection to _init()
@ -70,6 +104,8 @@ const WorkspaceThumbnailCommon = {
// unless border is removed // unless border is removed
if (opt.SHOW_WS_TMB_BG) if (opt.SHOW_WS_TMB_BG)
this.add_style_class_name('ws-tmb-labeled'); this.add_style_class_name('ws-tmb-labeled');
else
this.add_style_class_name('ws-tmb-transparent');
// add workspace thumbnails labels if enabled // add workspace thumbnails labels if enabled
if (opt.SHOW_WST_LABELS) { // 0 - disable if (opt.SHOW_WST_LABELS) { // 0 - disable
@ -77,7 +113,7 @@ const WorkspaceThumbnailCommon = {
const wsIndex = this.metaWorkspace.index(); const wsIndex = this.metaWorkspace.index();
let label = `${wsIndex + 1}`; let label = `${wsIndex + 1}`;
if (opt.SHOW_WST_LABELS === 2) { // 2 - index + workspace name if (opt.SHOW_WST_LABELS === 2) { // 2 - index + workspace name
const settings = ExtensionUtils.getSettings('org.gnome.desktop.wm.preferences'); const settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
const wsLabels = settings.get_strv('workspace-names'); const wsLabels = settings.get_strv('workspace-names');
if (wsLabels.length > wsIndex && wsLabels[wsIndex]) if (wsLabels.length > wsIndex && wsLabels[wsIndex])
label += `: ${wsLabels[wsIndex]}`; label += `: ${wsLabels[wsIndex]}`;
@ -129,7 +165,9 @@ const WorkspaceThumbnailCommon = {
} }
}); });
this._nWindowsConId = this.metaWorkspace.connect('notify::n-windows', () => { this._nWindowsConId = this.metaWorkspace.connect('notify::n-windows', () => {
// wait for new information if (this._updateLabelTimeout)
return;
// wait for new data
this._updateLabelTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { this._updateLabelTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => {
const newLabel = getLabel(); const newLabel = getLabel();
this._wsLabel.text = newLabel; this._wsLabel.text = newLabel;
@ -168,7 +206,7 @@ const WorkspaceThumbnailCommon = {
closeButton.opacity = 255; closeButton.opacity = 255;
if (!Meta.prefs_get_dynamic_workspaces() || (Meta.prefs_get_dynamic_workspaces() && global.workspace_manager.get_n_workspaces() - 1 !== this.metaWorkspace.index())) { if (!Meta.prefs_get_dynamic_workspaces() || (Meta.prefs_get_dynamic_workspaces() && global.workspace_manager.get_n_workspaces() - 1 !== this.metaWorkspace.index())) {
// color the button red if ready to react on clicks // color the button red if ready to react on clicks
if (opt.CLOSE_WS_BUTTON_MODE < 3 || (opt.CLOSE_WS_BUTTON_MODE === 3 && _Util.isCtrlPressed())) if (opt.CLOSE_WS_BUTTON_MODE < 3 || (opt.CLOSE_WS_BUTTON_MODE === 3 && Me.Util.isCtrlPressed()))
closeButton.add_style_class_name('workspace-close-button-hover'); closeButton.add_style_class_name('workspace-close-button-hover');
} }
}); });
@ -220,12 +258,6 @@ const WorkspaceThumbnailCommon = {
this._viewport.set_child_below_sibling(this._bgManager.backgroundActor, null); this._viewport.set_child_below_sibling(this._bgManager.backgroundActor, null);
this.connect('destroy', () => {
if (this._bgManager)
this._bgManager.destroy();
this._bgManager = null;
});
// full brightness of the thumbnail bg draws unnecessary attention // full brightness of the thumbnail bg draws unnecessary attention
// there is a grey bg under the wallpaper // there is a grey bg under the wallpaper
this._bgManager.backgroundActor.opacity = 220; this._bgManager.backgroundActor.opacity = 220;
@ -256,7 +288,7 @@ const WorkspaceThumbnailCommon = {
this._lastCloseClickTime = Date.now(); this._lastCloseClickTime = Date.now();
return; return;
} }
} else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !_Util.isCtrlPressed()) { } else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !Me.Util.isCtrlPressed()) {
return; return;
} }
@ -335,7 +367,7 @@ const WorkspaceThumbnailCommon = {
if (!source.app && source.shellWorkspaceLaunch) if (!source.app && source.shellWorkspaceLaunch)
return DND.DragMotionResult.COPY_DROP; return DND.DragMotionResult.COPY_DROP;
if (source instanceof imports.ui.appDisplay.FolderIcon) if (source instanceof AppDisplay.FolderIcon)
return DND.DragMotionResult.COPY_DROP; return DND.DragMotionResult.COPY_DROP;
@ -369,8 +401,8 @@ const WorkspaceThumbnailCommon = {
timestamp: time, timestamp: time,
}); });
return true; return true;
} else if (source instanceof imports.ui.appDisplay.FolderIcon) { } else if (source instanceof AppDisplay.FolderIcon) {
if (shellVersion >= 44) { if (Me.shellVersion >= 44) {
for (let app of source.view._apps) { for (let app of source.view._apps) {
// const app = Shell.AppSystem.get_default().lookup_app(id); // const app = Shell.AppSystem.get_default().lookup_app(id);
app.open_new_window(this.metaWorkspace.index()); app.open_new_window(this.metaWorkspace.index());
@ -419,7 +451,7 @@ const ThumbnailsBoxCommon = {
if (!source.metaWindow && if (!source.metaWindow &&
(!source.app || !source.app.can_open_new_window()) && (!source.app || !source.app.can_open_new_window()) &&
(source.app || !source.shellWorkspaceLaunch) && (source.app || !source.shellWorkspaceLaunch) &&
!(source instanceof imports.ui.appDisplay.FolderIcon)) !(source instanceof AppDisplay.FolderIcon))
return false; return false;
@ -448,8 +480,8 @@ const ThumbnailsBoxCommon = {
workspace: newWorkspaceIndex, workspace: newWorkspaceIndex,
timestamp: time, timestamp: time,
}); });
} else if (source instanceof imports.ui.appDisplay.FolderIcon) { } else if (source instanceof AppDisplay.FolderIcon) {
if (shellVersion >= 44) { if (Me.shellVersion >= 44) {
for (let app of source.view._apps) { for (let app of source.view._apps) {
// const app = Shell.AppSystem.get_default().lookup_app(id); // const app = Shell.AppSystem.get_default().lookup_app(id);
app.open_new_window(newWorkspaceIndex); app.open_new_window(newWorkspaceIndex);
@ -495,7 +527,7 @@ const ThumbnailsBoxCommon = {
if (!source.metaWindow && if (!source.metaWindow &&
(!source.app || !source.app.can_open_new_window()) && (!source.app || !source.app.can_open_new_window()) &&
(source.app || !source.shellWorkspaceLaunch) && (source.app || !source.shellWorkspaceLaunch) &&
source !== Main.xdndHandler && !(source instanceof imports.ui.appDisplay.FolderIcon)) source !== Main.xdndHandler && !(source instanceof AppDisplay.FolderIcon))
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL; const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
@ -551,18 +583,18 @@ const ThumbnailsBoxCommon = {
return ThumbnailsBoxHorizontal._withinWorkspace.bind(this)(...args); return ThumbnailsBoxHorizontal._withinWorkspace.bind(this)(...args);
}, },
get_preferred_custom_width(...args) { vfunc_get_preferred_width(...args) {
if (this._boxOrientation) if (this._boxOrientation)
return ThumbnailsBoxVertical.get_preferred_custom_width.bind(this)(...args); return ThumbnailsBoxVertical.vfunc_get_preferred_width.bind(this)(...args);
else else
return ThumbnailsBoxHorizontal.get_preferred_custom_width.bind(this)(...args); return ThumbnailsBoxHorizontal.vfunc_get_preferred_width.bind(this)(...args);
}, },
get_preferred_custom_height(...args) { vfunc_get_preferred_height(...args) {
if (this._boxOrientation) if (this._boxOrientation)
return ThumbnailsBoxVertical.get_preferred_custom_height.bind(this)(...args); return ThumbnailsBoxVertical.vfunc_get_preferred_height.bind(this)(...args);
else else
return ThumbnailsBoxHorizontal.get_preferred_custom_height.bind(this)(...args); return ThumbnailsBoxHorizontal.vfunc_get_preferred_height.bind(this)(...args);
}, },
vfunc_allocate(...args) { vfunc_allocate(...args) {
@ -632,14 +664,9 @@ const ThumbnailsBoxVertical = {
return y > workspaceY1 && y <= workspaceY2; return y > workspaceY1 && y <= workspaceY2;
}, },
// vfunc_get_preferred_width: function(forHeight) { vfunc_get_preferred_width(forHeight) {
// override of this vfunc doesn't work for some reason (tested on Ubuntu and Fedora), it's not reachable if (forHeight < 10)
get_preferred_custom_width(forHeight) { return [this._porthole.width, this._porthole.width];
if (!this.visible)
return [0, 0];
if (forHeight === -1)
return this.get_preferred_custom_height(forHeight);
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@ -652,19 +679,14 @@ const ThumbnailsBoxVertical = {
const avail = forHeight - totalSpacing; const avail = forHeight - totalSpacing;
let scale = (avail / nWorkspaces) / this._porthole.height; let scale = (avail / nWorkspaces) / this._porthole.height;
// scale = Math.min(scale, opt.MAX_THUMBNAIL_SCALE);
const width = Math.round(this._porthole.width * scale); const width = Math.round(this._porthole.width * scale);
return themeNode.adjust_preferred_height(width, width); return themeNode.adjust_preferred_height(width, width);
}, },
get_preferred_custom_height(_forWidth) { vfunc_get_preferred_height(forWidth) {
if (!this.visible) if (forWidth < 10)
return [0, 0]; return [0, this._porthole.height];
// Note that for getPreferredHeight/Width we cheat a bit and skip propagating
// the size request to our children because we know how big they are and know
// that the actors aren't depending on the virtual functions being called.
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let spacing = themeNode.get_length('spacing'); let spacing = themeNode.get_length('spacing');
@ -674,15 +696,14 @@ const ThumbnailsBoxVertical = {
let totalSpacing = (nWorkspaces - 3) * spacing; let totalSpacing = (nWorkspaces - 3) * spacing;
const ratio = this._porthole.width / this._porthole.height; const ratio = this._porthole.width / this._porthole.height;
const tmbHeight = themeNode.adjust_for_width(_forWidth) / ratio; const tmbHeight = themeNode.adjust_for_width(forWidth) / ratio;
const naturalheight = this._thumbnails.reduce((accumulator, thumbnail/* , index*/) => { const naturalheight = this._thumbnails.reduce((accumulator, thumbnail/* , index*/) => {
const progress = 1 - thumbnail.collapse_fraction; const progress = 1 - thumbnail.collapse_fraction;
const height = tmbHeight * progress; const height = tmbHeight * progress;
return accumulator + height; return accumulator + height;
}, 0); }, 0);
return themeNode.adjust_preferred_width(totalSpacing, Math.round(naturalheight));
return themeNode.adjust_preferred_width(totalSpacing, naturalheight);
}, },
// removes extra space (extraWidth in the original function), we need the box as accurate as possible // removes extra space (extraWidth in the original function), we need the box as accurate as possible
@ -759,16 +780,11 @@ const ThumbnailsBoxVertical = {
this._dropPlaceholder.allocate_preferred_size( this._dropPlaceholder.allocate_preferred_size(
...this._dropPlaceholder.get_position()); ...this._dropPlaceholder.get_position());
if (shellVersion >= 44) { const laterFunc = () => this._dropPlaceholder.hide();
const laters = global.compositor.get_laters(); if (Meta.later_add)
laters.add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
this._dropPlaceholder.hide(); else
}); global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
} else {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.hide();
});
}
} }
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
@ -796,16 +812,11 @@ const ThumbnailsBoxVertical = {
this._dropPlaceholder.allocate(childBox); this._dropPlaceholder.allocate(childBox);
if (shellVersion >= 44) { const laterFunc = () => this._dropPlaceholder.show();
const laters = global.compositor.get_laters(); if (Meta.later_add)
laters.add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
this._dropPlaceholder.show(); else
}); global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
} else {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.show();
});
}
y += placeholderHeight + spacing; y += placeholderHeight + spacing;
} }
@ -925,7 +936,10 @@ const ThumbnailsBoxHorizontal = {
return x > workspaceX1 && x <= workspaceX2; return x > workspaceX1 && x <= workspaceX2;
}, },
get_preferred_custom_height(forWidth) { vfunc_get_preferred_height(forWidth) {
if (forWidth < 10)
return [this._porthole.height, this._porthole.height];
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
forWidth = themeNode.adjust_for_width(forWidth); forWidth = themeNode.adjust_for_width(forWidth);
@ -937,18 +951,15 @@ const ThumbnailsBoxHorizontal = {
const avail = forWidth - totalSpacing; const avail = forWidth - totalSpacing;
let scale = (avail / nWorkspaces) / this._porthole.width; let scale = (avail / nWorkspaces) / this._porthole.width;
// scale = Math.min(scale, opt.MAX_THUMBNAIL_SCALE);
const height = Math.round(this._porthole.height * scale); const height = Math.round(this._porthole.height * scale);
return themeNode.adjust_preferred_height(height, height); return themeNode.adjust_preferred_height(height, height);
}, },
get_preferred_custom_width(_forHeight) { vfunc_get_preferred_width(forHeight) {
// Note that for getPreferredHeight/Width we cheat a bit and skip propagating if (forHeight < 10)
// the size request to our children because we know how big they are and know return [0, this._porthole.width];
// that the actors aren't depending on the virtual functions being called.
if (!this.visible)
return [0, 0];
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@ -959,13 +970,14 @@ const ThumbnailsBoxHorizontal = {
const ratio = this._porthole.height / this._porthole.width; const ratio = this._porthole.height / this._porthole.width;
const tmbWidth = themeNode.adjust_for_height(_forHeight) / ratio; const tmbWidth = themeNode.adjust_for_height(forHeight) / ratio;
const naturalWidth = this._thumbnails.reduce((accumulator, thumbnail) => { const naturalWidth = this._thumbnails.reduce((accumulator, thumbnail) => {
const progress = 1 - thumbnail.collapse_fraction; const progress = 1 - thumbnail.collapse_fraction;
const width = tmbWidth * progress; const width = tmbWidth * progress;
return accumulator + width; return accumulator + width;
}, 0); }, 0);
return themeNode.adjust_preferred_width(totalSpacing, naturalWidth); return themeNode.adjust_preferred_width(totalSpacing, naturalWidth);
}, },
@ -1041,16 +1053,11 @@ const ThumbnailsBoxHorizontal = {
this._dropPlaceholder.allocate_preferred_size( this._dropPlaceholder.allocate_preferred_size(
...this._dropPlaceholder.get_position()); ...this._dropPlaceholder.get_position());
if (shellVersion >= 44) { const laterFunc = () => this._dropPlaceholder.hide();
const laters = global.compositor.get_laters(); if (Meta.later_add)
laters.add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
this._dropPlaceholder.hide(); else
}); global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
} else {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.hide();
});
}
} }
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
@ -1078,16 +1085,11 @@ const ThumbnailsBoxHorizontal = {
this._dropPlaceholder.allocate(childBox); this._dropPlaceholder.allocate(childBox);
if (shellVersion >= 44) { const laterFunc = () => this._dropPlaceholder.show();
const laters = global.compositor.get_laters(); if (Meta.later_add)
laters.add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
this._dropPlaceholder.show(); else
}); global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
} else {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._dropPlaceholder.show();
});
}
x += placeholderWidth + spacing; x += placeholderWidth + spacing;
} }

View file

@ -10,62 +10,92 @@
'use strict'; 'use strict';
const { GObject, Clutter, Meta, St } = imports.gi; const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const Util = imports.misc.util; const OverviewControls = imports.ui.overviewControls;
const WorkspacesView = imports.ui.workspacesView; const WorkspacesView = imports.ui.workspacesView;
// first reference to constant defined using const in other module returns undefined, the SecondaryMonitorDisplay const will remain empty and unused const Util = imports.misc.util;
const SecondaryMonitorDisplay = WorkspacesView.SecondaryMonitorDisplay;
const ControlsState = imports.ui.overviewControls.ControlsState;
const FitMode = imports.ui.workspacesView.FitMode;
const SIDE_CONTROLS_ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const SEARCH_WINDOWS_PREFIX = Me.imports.lib.windowSearchProvider.prefix;
const SEARCH_RECENT_FILES_PREFIX = Me.imports.lib.recentFilesSearchProvider.prefix;
const _Util = Me.imports.lib.util;
let _overrides;
let Me;
let opt; let opt;
const ControlsState = OverviewControls.ControlsState;
const FitMode = WorkspacesView.FitMode;
function update(reset = false) { var WorkspacesViewModule = class {
opt = Me.imports.lib.settings.opt; constructor(me) {
opt.DESKTOP_CUBE_ENABLED = Main.extensionManager._enabledExtensions.includes('desktop-cube@schneegans.github.com'); // first reference to constant defined using const in other module returns undefined, the SecondaryMonitorDisplay const will remain empty and unused
const cubeSupported = opt.DESKTOP_CUBE_ENABLED && !opt.ORIENTATION && !opt.OVERVIEW_MODE; this.dummy = WorkspacesView.SecondaryMonitorDisplay;
// if desktop cube extension is enabled while V-Shell is loaded, removeAll() would override its code Me = me;
if (_overrides && !cubeSupported) { opt = Me.opt;
_overrides.removeAll();
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1); this._firstActivation = true;
this.moduleEnabled = false;
this._overrides = null;
} }
if (reset) { cleanGlobals() {
_overrides = null; Me = null;
opt = null; opt = null;
return;
} }
update(reset) {
this.moduleEnabled = true;
const conflict = false;
_overrides = new _Util.Overrides(); reset = reset || !this.moduleEnabled || conflict;
if (!cubeSupported) // don't touch the original code if module disabled
_overrides.addOverride('WorkspacesView', WorkspacesView.WorkspacesView.prototype, WorkspacesViewCommon); if (reset && !this._firstActivation) {
this._disableModule();
_overrides.addOverride('WorkspacesDisplay', WorkspacesView.WorkspacesDisplay.prototype, WorkspacesDisplay); } else if (!reset) {
_overrides.addOverride('ExtraWorkspaceView', WorkspacesView.ExtraWorkspaceView.prototype, ExtraWorkspaceView); this._firstActivation = false;
this._activateModule();
if (opt.ORIENTATION) { }
// switch internal workspace orientation in GS if (reset && this._firstActivation)
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, -1, 1); console.debug(' WorkspacesViewModule - Keeping untouched');
_overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayVertical);
} else {
_overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayHorizontal);
} }
}
_activateModule() {
if (!this._overrides)
this._overrides = new Me.Util.Overrides();
const desktopCubeEnabled = Me.Util.getEnabledExtensions('desktop-cube@schneegans.github.com').length;
const desktopCubeConflict = desktopCubeEnabled && !opt.ORIENTATION && !opt.OVERVIEW_MODE;
if (!desktopCubeConflict)
this._overrides.addOverride('WorkspacesView', WorkspacesView.WorkspacesView.prototype, WorkspacesViewCommon);
this._overrides.addOverride('WorkspacesDisplay', WorkspacesView.WorkspacesDisplay.prototype, WorkspacesDisplayCommon);
this._overrides.addOverride('ExtraWorkspaceView', WorkspacesView.ExtraWorkspaceView.prototype, ExtraWorkspaceViewCommon);
this._overrides.addOverride('SecondaryMonitorDisplayCommon', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayCommon);
if (opt.ORIENTATION) {
// switch internal workspace orientation in GS
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, -1, 1);
this._overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayVertical);
} else {
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1);
this._overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayHorizontal);
}
console.debug(' WorkspacesViewModule - Activated');
}
_disableModule() {
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1);
if (this._overrides)
this._overrides.removeAll();
this._overrides = null;
console.debug(' WorkspacesViewModule - Disabled');
}
};
const WorkspacesViewCommon = { const WorkspacesViewCommon = {
_getFirstFitSingleWorkspaceBox(box, spacing, vertical) { _getFirstFitSingleWorkspaceBox(box, spacing, vertical) {
@ -91,7 +121,6 @@ const WorkspacesViewCommon = {
} }
const fitSingleBox = new Clutter.ActorBox({ x1, y1 }); const fitSingleBox = new Clutter.ActorBox({ x1, y1 });
fitSingleBox.set_size(workspaceWidth, workspaceHeight); fitSingleBox.set_size(workspaceWidth, workspaceHeight);
return fitSingleBox; return fitSingleBox;
@ -143,21 +172,7 @@ const WorkspacesViewCommon = {
}, },
_updateVisibility() { _updateVisibility() {
// replaced in _updateWorkspacesState // visibility handles _updateWorkspacesState()
/* let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
const fitMode = this._fitModeAdjustment.value;
const singleFitMode = fitMode === FitMode.SINGLE;
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
if (this._animating || this._gestureActive || !singleFitMode)
workspace.show();
else
workspace.visible = Math.abs(w - active) <= opt.NUMBER_OF_VISIBLE_NEIGHBORS;
}*/
}, },
// disable scaling and hide inactive workspaces // disable scaling and hide inactive workspaces
@ -175,27 +190,21 @@ const WorkspacesViewCommon = {
const primaryMonitor = Main.layoutManager.primaryMonitor.index; const primaryMonitor = Main.layoutManager.primaryMonitor.index;
// define the transition values here to save time in each ws
let scaleX, scaleY;
if (opt.ORIENTATION) { // vertical 1 / horizontal 0
scaleX = 1;
scaleY = 0.1;
} else {
scaleX = 0.1;
scaleY = 1;
}
const wsScrollProgress = adj.value % 1; const wsScrollProgress = adj.value % 1;
const secondaryMonitor = this._monitorIndex !== global.display.get_primary_monitor(); const secondaryMonitor = this._monitorIndex !== global.display.get_primary_monitor();
const blockSecondaryAppGrid = opt.OVERVIEW_MODE && currentState > 1; const blockSecondaryAppGrid = opt.OVERVIEW_MODE && currentState > 1;
// Hide inactive workspaces // Hide inactive workspaces
this._workspaces.forEach((w, index) => { this._workspaces.forEach((w, index) => {
if (!(blockSecondaryAppGrid && secondaryMonitor)) if (!(blockSecondaryAppGrid && secondaryMonitor))
w.stateAdjustment.value = workspaceMode; w.stateAdjustment.value = workspaceMode;
const distanceToCurrentWorkspace = Math.abs(adj.value - index); let distance = adj.value - index;
const distanceToCurrentWorkspace = Math.abs(distance);
const scaleProgress = 1 - Math.clamp(distanceToCurrentWorkspace, 0, 1); const scaleProgress = 1 - Math.clamp(distanceToCurrentWorkspace, 0, 1);
// const scale = Util.lerp(0.94, 1, scaleProgress);
// w.set_scale(scale, scale);
// if we disable workspaces that we can't or don't need to see, transition animations will be noticeably smoother // if we disable workspaces that we can't or don't need to see, transition animations will be noticeably smoother
// only the current ws needs to be visible during overview transition animations // only the current ws needs to be visible during overview transition animations
@ -210,22 +219,28 @@ const WorkspacesViewCommon = {
// after transition from APP_GRID to WINDOW_PICKER state, // after transition from APP_GRID to WINDOW_PICKER state,
// adjacent workspaces are hidden and we need them to show up // adjacent workspaces are hidden and we need them to show up
// make them visible during animation can impact smoothness of the animation // make them visible during animation can impact smoothness of the animation
// so we show them after the animation finished, scaling animation will make impression that they move in from outside the monitor // so we show them after the animation finished, move them to their position from outside of the monitor
if (!w.visible && distanceToCurrentWorkspace === 1 && initialState === ControlsState.APP_GRID && currentState === ControlsState.WINDOW_PICKER) { if (!w.visible && distanceToCurrentWorkspace === 1 && initialState === ControlsState.APP_GRID && currentState === ControlsState.WINDOW_PICKER) {
w.scale_x = scaleX;
w.scale_y = scaleY;
w.visible = true; w.visible = true;
const directionNext = distance > 0;
if (!opt.ORIENTATION) {
const width = w.width * 0.6 * opt.WS_PREVIEW_SCALE;
w.translation_x = directionNext ? -width : width;
}
if (opt.ORIENTATION) {
const height = w.height * 0.6 * opt.WS_PREVIEW_SCALE;
w.translation_y = directionNext ? -height : height;
}
w.opacity = 10;
w.get_parent().set_child_below_sibling(w, null);
w.ease({ w.ease({
duration: 100, duration: 300,
scale_x: 1, translation_x: 0,
scale_y: 1, translation_y: 0,
opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
}); });
} else if (!w.visible && distanceToCurrentWorkspace <= opt.NUMBER_OF_VISIBLE_NEIGHBORS && currentState === ControlsState.WINDOW_PICKER) {
w.set({
scale_x: 1,
scale_y: 1,
});
} }
// force ws preview bg corner radiuses where GS doesn't do it // force ws preview bg corner radiuses where GS doesn't do it
@ -238,9 +253,40 @@ const WorkspacesViewCommon = {
w._background.opacity = 0; w._background.opacity = 0;
}); });
}, },
exposeWindows(workspaceIndex = null, callback) {
let adjustments = [];
if (workspaceIndex === null) {
this._workspaces.forEach(ws => {
adjustments.push(ws._background._stateAdjustment);
});
} else {
adjustments.push(this._workspaces[workspaceIndex]._background._stateAdjustment);
}
adjustments.forEach(adj => {
if (adj.value === 0) {
adj.value = 0;
adj.ease(1, {
duration: 200,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
opt.WORKSPACE_MODE = 1;
if (callback)
callback();
},
});
}
});
},
};
const SecondaryMonitorDisplayCommon = {
exposeWindows(...args) {
this._workspacesView.exposeWindows(...args);
},
}; };
// SecondaryMonitorDisplay Vertical
const SecondaryMonitorDisplayVertical = { const SecondaryMonitorDisplayVertical = {
_getThumbnailParamsForState(state) { _getThumbnailParamsForState(state) {
@ -270,24 +316,6 @@ const SecondaryMonitorDisplayVertical = {
return { opacity, scale, translationX }; return { opacity, scale, translationX };
}, },
_getThumbnailsWidth(box, spacing) {
if (opt.SEC_WS_TMB_HIDDEN)
return 0;
const [width, height] = box.get_size();
const { expandFraction } = this._thumbnails;
const [, thumbnailsWidth] = this._thumbnails.get_preferred_custom_width(height - 2 * spacing);
let scaledWidth;
if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED)
scaledWidth = ((height - Main.panel.height) * opt.SEC_MAX_THUMBNAIL_SCALE) * (width / height);
else
scaledWidth = width * opt.SEC_MAX_THUMBNAIL_SCALE;
return Math.min(
thumbnailsWidth * expandFraction,
Math.round(scaledWidth));
},
_getWorkspacesBoxForState(state, box, padding, thumbnailsWidth, spacing) { _getWorkspacesBoxForState(state, box, padding, thumbnailsWidth, spacing) {
// const { ControlsState } = OverviewControls; // const { ControlsState } = OverviewControls;
const workspaceBox = box.copy(); const workspaceBox = box.copy();
@ -303,7 +331,7 @@ const SecondaryMonitorDisplayVertical = {
break; break;
yShift = 0; yShift = 0;
if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED) { if (opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible) {
if (opt.PANEL_POSITION_TOP) if (opt.PANEL_POSITION_TOP)
yShift = Main.panel.height; yShift = Main.panel.height;
else else
@ -341,26 +369,40 @@ const SecondaryMonitorDisplayVertical = {
const spacing = themeNode.get_length('spacing') * expandFraction; const spacing = themeNode.get_length('spacing') * expandFraction;
const padding = Math.round(0.1 * height); const padding = Math.round(0.1 * height);
let thumbnailsWidth = this._getThumbnailsWidth(contentBox, spacing); let thumbnailsWidth = 0;
let [, thumbnailsHeight] = this._thumbnails.get_preferred_custom_height(thumbnailsWidth); let thumbnailsHeight = 0;
thumbnailsHeight = Math.min(thumbnailsHeight, height - 2 * spacing);
this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN; this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
if (this._thumbnails.visible) { if (this._thumbnails.visible) {
const reduceBoxHeight = opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible ? Main.panel.height : 0;
thumbnailsWidth = width * opt.SEC_MAX_THUMBNAIL_SCALE;
let totalTmbSpacing;
[totalTmbSpacing, thumbnailsHeight] = this._thumbnails.get_preferred_height(thumbnailsWidth);
thumbnailsHeight = Math.round(thumbnailsHeight + totalTmbSpacing);
const thumbnailsHeightMax = height - spacing - reduceBoxHeight;
if (thumbnailsHeight > thumbnailsHeightMax) {
thumbnailsHeight = thumbnailsHeightMax;
thumbnailsWidth = Math.round(this._thumbnails.get_preferred_width(thumbnailsHeight)[1]);
}
let wsTmbX; let wsTmbX;
if (opt.SEC_WS_TMB_LEFT) { // left if (opt.SEC_WS_TMB_LEFT) { // left
wsTmbX = Math.round(spacing / 4); wsTmbX = spacing / 2;
this._thumbnails._positionLeft = true; this._thumbnails._positionLeft = true;
} else { } else {
wsTmbX = Math.round(width - spacing / 4 - thumbnailsWidth); wsTmbX = width - spacing / 2 - thumbnailsWidth;
this._thumbnails._positionLeft = false; this._thumbnails._positionLeft = false;
} }
const childBox = new Clutter.ActorBox(); const childBox = new Clutter.ActorBox();
const availSpace = height - thumbnailsHeight - 2 * spacing; const availSpace = height - thumbnailsHeight;
let wsTmbY = availSpace / 2; let wsTmbY = availSpace / 2;
wsTmbY -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbY - spacing; wsTmbY -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbY;
wsTmbY += opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible ? Main.panel.height : 0;
childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY)); childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY));
childBox.set_size(thumbnailsWidth, thumbnailsHeight); childBox.set_size(thumbnailsWidth, thumbnailsHeight);
@ -390,22 +432,14 @@ const SecondaryMonitorDisplayVertical = {
if (opt.OVERVIEW_MODE2) if (opt.OVERVIEW_MODE2)
this.set_child_above_sibling(this._thumbnails, null); this.set_child_above_sibling(this._thumbnails, null);
const visible = !opt.SEC_WS_TMB_HIDDEN; const visible = !opt.SEC_WS_TMB_HIDDEN;
if (this._thumbnails.visible === visible) if (this._thumbnails.visible === visible)
return; return;
this._thumbnails.show(); this._thumbnails.show();
this._thumbnails.visible = visible;
this._updateThumbnailParams(); this._updateThumbnailParams();
this._thumbnails.ease_property('expand-fraction', visible ? 1 : 0, {
duration: SIDE_CONTROLS_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._thumbnails.visible = visible;
this._thumbnails._indicator.visible = visible;
},
});
}, },
_updateThumbnailParams() { _updateThumbnailParams() {
@ -417,7 +451,6 @@ const SecondaryMonitorDisplayVertical = {
if (!this._thumbnails._thumbnails.length) if (!this._thumbnails._thumbnails.length)
this._thumbnails._createThumbnails(); this._thumbnails._createThumbnails();
const { initialState, finalState, progress } = const { initialState, finalState, progress } =
this._overviewAdjustment.getStateTransitionParams(); this._overviewAdjustment.getStateTransitionParams();
@ -474,7 +507,6 @@ const SecondaryMonitorDisplayVertical = {
}, },
}; };
// SecondaryMonitorDisplay Horizontal
const SecondaryMonitorDisplayHorizontal = { const SecondaryMonitorDisplayHorizontal = {
_getThumbnailParamsForState(state) { _getThumbnailParamsForState(state) {
// const { ControlsState } = OverviewControls; // const { ControlsState } = OverviewControls;
@ -520,7 +552,7 @@ const SecondaryMonitorDisplayHorizontal = {
break; break;
yShift = 0; yShift = 0;
if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED) { if (opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible) {
if (opt.PANEL_POSITION_TOP) if (opt.PANEL_POSITION_TOP)
yShift = Main.panel.height; yShift = Main.panel.height;
else else
@ -571,24 +603,36 @@ const SecondaryMonitorDisplayHorizontal = {
const spacing = themeNode.get_length('spacing') * expandFraction; const spacing = themeNode.get_length('spacing') * expandFraction;
const padding = Math.round(0.1 * height); const padding = Math.round(0.1 * height);
let thumbnailsHeight = this._getThumbnailsHeight(contentBox); let thumbnailsWidth = 0;
let [, thumbnailsWidth] = this._thumbnails.get_preferred_custom_width(thumbnailsHeight); let thumbnailsHeight = 0;
thumbnailsWidth = Math.min(thumbnailsWidth, width - 2 * spacing);
this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN; this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
if (this._thumbnails.visible) { if (this._thumbnails.visible) {
const reservedHeight = opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible ? Main.panel.height : 0;
thumbnailsHeight = height * opt.SEC_MAX_THUMBNAIL_SCALE;
let totalTmbSpacing;
[totalTmbSpacing, thumbnailsWidth] = this._thumbnails.get_preferred_width(thumbnailsHeight);
thumbnailsWidth = Math.round(thumbnailsWidth + totalTmbSpacing);
const thumbnailsWidthMax = width - spacing;
if (thumbnailsWidth > thumbnailsWidthMax) {
thumbnailsWidth = thumbnailsWidthMax;
thumbnailsHeight = Math.round(this._thumbnails.get_preferred_height(thumbnailsWidth)[1]);
}
let wsTmbY; let wsTmbY;
if (opt.SEC_WS_TMB_TOP) if (opt.SEC_WS_TMB_TOP)
wsTmbY = Math.round(spacing / 4); wsTmbY = spacing / 2 + reservedHeight;
else else
wsTmbY = Math.round(height - spacing / 4 - thumbnailsHeight); wsTmbY = height - spacing / 2 - thumbnailsHeight;
const childBox = new Clutter.ActorBox(); const childBox = new Clutter.ActorBox();
const availSpace = width - thumbnailsWidth - 2 * spacing; const availSpace = width - thumbnailsWidth;
let wsTmbX = availSpace / 2; let wsTmbX = availSpace / 2;
wsTmbX -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbX - spacing; wsTmbX -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbX;
childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY)); childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY));
childBox.set_size(thumbnailsWidth, thumbnailsHeight); childBox.set_size(thumbnailsWidth, thumbnailsHeight);
@ -625,7 +669,6 @@ const SecondaryMonitorDisplayHorizontal = {
if (!this._thumbnails._thumbnails.length) if (!this._thumbnails._thumbnails.length)
this._thumbnails._createThumbnails(); this._thumbnails._createThumbnails();
const { initialState, finalState, progress } = const { initialState, finalState, progress } =
this._overviewAdjustment.getStateTransitionParams(); this._overviewAdjustment.getStateTransitionParams();
@ -682,7 +725,7 @@ const SecondaryMonitorDisplayHorizontal = {
}, },
}; };
const ExtraWorkspaceView = { const ExtraWorkspaceViewCommon = {
_updateWorkspaceMode() { _updateWorkspaceMode() {
const overviewState = this._overviewAdjustment.value; const overviewState = this._overviewAdjustment.value;
@ -701,9 +744,23 @@ const ExtraWorkspaceView = {
if (!opt.SHOW_WS_PREVIEW_BG && this._workspace._background.opacity) if (!opt.SHOW_WS_PREVIEW_BG && this._workspace._background.opacity)
this._workspace._background.opacity = 0; this._workspace._background.opacity = 0;
}, },
exposeWindows() {
const adjustment = this._workspace._background._stateAdjustment;
if (adjustment.value === 0) {
adjustment.value = 0;
adjustment.ease(1, {
duration: 200,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
opt.WORKSPACE_MODE = 1;
},
});
}
},
}; };
const WorkspacesDisplay = { const WorkspacesDisplayCommon = {
_updateWorkspacesViews() { _updateWorkspacesViews() {
for (let i = 0; i < this._workspacesViews.length; i++) for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy(); this._workspacesViews[i].destroy();
@ -761,8 +818,8 @@ const WorkspacesDisplay = {
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
if (_Util.isShiftPressed()) { if (Me.Util.isShiftPressed()) {
let direction = _Util.getScrollDirection(event); let direction = Me.Util.getScrollDirection(event);
if (direction === null || (Date.now() - this._lastScrollTime) < 150) if (direction === null || (Date.now() - this._lastScrollTime) < 150)
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
this._lastScrollTime = Date.now(); this._lastScrollTime = Date.now();
@ -775,11 +832,11 @@ const WorkspacesDisplay = {
else else
direction = 0; direction = 0;
if (direction) { if (direction) {
_Util.reorderWorkspace(direction); Me.Util.reorderWorkspace(direction);
// make all workspaces on primary monitor visible for case the new position is hidden // make all workspaces on primary monitor visible for case the new position is hidden
Main.overview._overview._controls._workspacesDisplay._workspacesViews[0]._workspaces.forEach(w => { const primaryMonitorIndex = global.display.get_primary_monitor();
Main.overview._overview._controls._workspacesDisplay._workspacesViews[primaryMonitorIndex]._workspaces.forEach(w => {
w.visible = true; w.visible = true;
}); });
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
@ -806,7 +863,7 @@ const WorkspacesDisplay = {
switch (symbol) { switch (symbol) {
case Clutter.KEY_Return: case Clutter.KEY_Return:
case Clutter.KEY_KP_Enter: case Clutter.KEY_KP_Enter:
if (_Util.isCtrlPressed()) { if (Me.Util.isCtrlPressed()) {
Main.ctrlAltTabManager._items.forEach(i => { Main.ctrlAltTabManager._items.forEach(i => {
if (i.sortGroup === 1 && i.name === 'Dash') if (i.sortGroup === 1 && i.name === 'Dash')
Main.ctrlAltTabManager.focusGroup(i); Main.ctrlAltTabManager.focusGroup(i);
@ -836,17 +893,17 @@ const WorkspacesDisplay = {
which = workspaceManager.n_workspaces - 1; which = workspaceManager.n_workspaces - 1;
break; break;
case Clutter.KEY_space: case Clutter.KEY_space:
if (_Util.isCtrlPressed() && _Util.isShiftPressed()) { if (Me.Util.isCtrlPressed() && Me.Util.isShiftPressed()) {
_Util.openPreferences(); Me.Util.activateSearchProvider(Me.ESP_PREFIX);
} else if (_Util.isAltPressed()) { } else if (Me.Util.isAltPressed()) {
Main.ctrlAltTabManager._items.forEach(i => { Main.ctrlAltTabManager._items.forEach(i => {
if (i.sortGroup === 1 && i.name === 'Dash') if (i.sortGroup === 1 && i.name === 'Dash')
Main.ctrlAltTabManager.focusGroup(i); Main.ctrlAltTabManager.focusGroup(i);
}); });
} else if (opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED && _Util.isCtrlPressed()) { } else if (opt.get('recentFilesSearchProviderModule') && Me.Util.isCtrlPressed()) {
_Util.activateSearchProvider(SEARCH_RECENT_FILES_PREFIX); Me.Util.activateSearchProvider(Me.RFSP_PREFIX);
} else if (opt.WINDOW_SEARCH_PROVIDER_ENABLED) { } else if (opt.get('windowSearchProviderModule')) {
_Util.activateSearchProvider(SEARCH_WINDOWS_PREFIX); Me.Util.activateSearchProvider(Me.WSP_PREFIX);
} }
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
@ -867,16 +924,18 @@ const WorkspacesDisplay = {
}); });
} else if (opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE && state === 1) { } else if (opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE && state === 1) {
// expose windows for OVERVIEW_MODE 1 // expose windows for OVERVIEW_MODE 1
const adjustment = this._workspacesViews[0]._workspaces[global.workspace_manager.get_active_workspace().index()]._background._stateAdjustment; const wsIndex = global.workspace_manager.get_active_workspace().index();
opt.WORKSPACE_MODE = 1; // after expose animation activate keyboard for window selection
_Util.exposeWindows(adjustment, true); const callback = Me.Util.activateKeyboardForWorkspaceView;
this._workspacesViews.forEach(
view => {
view.exposeWindows(wsIndex, callback);
}
);
} else { } else {
if (state === 2) if (state === 2)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
Main.ctrlAltTabManager._items.forEach(i => { Me.Util.activateKeyboardForWorkspaceView();
if (i.sortGroup === 1 && i.name === 'Windows')
Main.ctrlAltTabManager.focusGroup(i);
});
} }
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
@ -895,14 +954,14 @@ const WorkspacesDisplay = {
// Otherwise it is a workspace index // Otherwise it is a workspace index
ws = workspaceManager.get_workspace_by_index(which); ws = workspaceManager.get_workspace_by_index(which);
if (_Util.isShiftPressed()) { if (Me.Util.isShiftPressed()) {
let direction; let direction;
if (which === Meta.MotionDirection.UP || which === Meta.MotionDirection.LEFT) if (which === Meta.MotionDirection.UP || which === Meta.MotionDirection.LEFT)
direction = -1; direction = -1;
else if (which === Meta.MotionDirection.DOWN || which === Meta.MotionDirection.RIGHT) else if (which === Meta.MotionDirection.DOWN || which === Meta.MotionDirection.RIGHT)
direction = 1; direction = 1;
if (direction) if (direction)
_Util.reorderWorkspace(direction); Me.Util.reorderWorkspace(direction);
// make all workspaces on primary monitor visible for case the new position is hidden // make all workspaces on primary monitor visible for case the new position is hidden
Main.overview._overview._controls._workspacesDisplay._workspacesViews[0]._workspaces.forEach(w => { Main.overview._overview._controls._workspacesDisplay._workspacesViews[0]._workspaces.forEach(w => {
w.visible = true; w.visible = true;

View file

@ -7,8 +7,16 @@
"43", "43",
"44" "44"
], ],
"session-modes": [
"user",
"unlock-dialog"
],
"url": "https://github.com/G-dH/vertical-workspaces", "url": "https://github.com/G-dH/vertical-workspaces",
"donations": {
"buymeacoffee": "georgdh"
},
"gettext-domain": "vertical-workspaces", "gettext-domain": "vertical-workspaces",
"settings-schema": "org.gnome.shell.extensions.vertical-workspaces", "settings-schema": "org.gnome.shell.extensions.vertical-workspaces",
"version": 28 "version-name": "44.10"
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,7 @@
<default>350</default> <default>350</default>
</key> </key>
<key type="i" name="ws-preview-scale"> <key type="i" name="ws-preview-scale">
<default>100</default> <default>95</default>
</key> </key>
<key type="i" name="secondary-ws-preview-scale"> <key type="i" name="secondary-ws-preview-scale">
<default>100</default> <default>100</default>
@ -23,7 +23,7 @@
<default>false</default> <default>false</default>
</key> </key>
<key type="i" name="dash-position"> <key type="i" name="dash-position">
<default>0</default> <default>2</default>
</key> </key>
<key type="i" name="dash-position-adjust"> <key type="i" name="dash-position-adjust">
<default>0</default> <default>0</default>
@ -37,6 +37,9 @@
<key type="i" name="dash-show-recent-files-icon"> <key type="i" name="dash-show-recent-files-icon">
<default>1</default> <default>1</default>
</key> </key>
<key type="i" name="dash-show-extensions-icon">
<default>1</default>
</key>
<key type="i" name="wst-position-adjust"> <key type="i" name="wst-position-adjust">
<default>0</default> <default>0</default>
</key> </key>
@ -77,10 +80,19 @@
<default>48</default> <default>48</default>
</key> </key>
<key type="i" name="dash-bg-opacity"> <key type="i" name="dash-bg-opacity">
<default>80</default> <default>85</default>
</key>
<key type="i" name="dash-bg-color">
<default>0</default>
</key> </key>
<key type="i" name="dash-bg-radius"> <key type="i" name="dash-bg-radius">
<default>17</default> <default>18</default>
</key>
<key type="b" name="dash-bg-gs3-style">
<default>true</default>
</key>
<key type="i" name="running-dot-style">
<default>1</default>
</key> </key>
<key type="b" name="enable-page-shortcuts"> <key type="b" name="enable-page-shortcuts">
<default>false</default> <default>false</default>
@ -104,7 +116,10 @@
<default>40</default> <default>40</default>
</key> </key>
<key type="i" name="overview-bg-brightness"> <key type="i" name="overview-bg-brightness">
<default>95</default> <default>60</default>
</key>
<key type="i" name="search-bg-brightness">
<default>30</default>
</key> </key>
<key type="b" name="smooth-blur-transitions"> <key type="b" name="smooth-blur-transitions">
<default>false</default> <default>false</default>
@ -113,7 +128,7 @@
<default>4</default> <default>4</default>
</key> </key>
<key type="i" name="search-view-animation"> <key type="i" name="search-view-animation">
<default>4</default> <default>0</default>
</key> </key>
<key type="i" name="workspace-animation"> <key type="i" name="workspace-animation">
<default>1</default> <default>1</default>
@ -124,14 +139,11 @@
<key type="i" name="animation-speed-factor"> <key type="i" name="animation-speed-factor">
<default>100</default> <default>100</default>
</key> </key>
<key type="b" name="fix-ubuntu-dock">
<default>true</default>
</key>
<key type="i" name="win-preview-icon-size"> <key type="i" name="win-preview-icon-size">
<default>1</default> <default>1</default>
</key> </key>
<key type="b" name="always-show-win-titles"> <key type="i" name="win-title-position">
<default>true</default> <default>0</default>
</key> </key>
<key type="i" name="startup-state"> <key type="i" name="startup-state">
<default>2</default> <default>2</default>
@ -157,6 +169,9 @@
<key type="i" name="app-grid-order"> <key type="i" name="app-grid-order">
<default>0</default> <default>0</default>
</key> </key>
<key type="i" name="app-folder-order">
<default>0</default>
</key>
<key type="i" name="app-grid-content"> <key type="i" name="app-grid-content">
<default>2</default> <default>2</default>
</key> </key>
@ -176,7 +191,7 @@
<default>true</default> <default>true</default>
</key> </key>
<key type="i" name="app-grid-names"> <key type="i" name="app-grid-names">
<default>0</default> <default>1</default>
</key> </key>
<key type="i" name="app-grid-folder-icon-grid"> <key type="i" name="app-grid-folder-icon-grid">
<default>3</default> <default>3</default>
@ -196,14 +211,17 @@
<key type="i" name="dash-icon-scroll"> <key type="i" name="dash-icon-scroll">
<default>1</default> <default>1</default>
</key> </key>
<key type="b" name="dash-isolate-workspaces">
<default>false</default>
</key>
<key type="i" name="search-windows-icon-scroll"> <key type="i" name="search-windows-icon-scroll">
<default>1</default> <default>1</default>
</key> </key>
<key type="b" name="search-windows-enable"> <key type="b" name="search-windows-enable">
<default>true</default> <default>true</default>
</key> </key>
<key type="b" name="search-recent-files-enable"> <key type="i" name="search-windows-order">
<default>true</default> <default>1</default>
</key> </key>
<key type="b" name="search-fuzzy"> <key type="b" name="search-fuzzy">
<default>false</default> <default>false</default>
@ -229,6 +247,12 @@
<key type="i" name="ws-sw-popup-mode"> <key type="i" name="ws-sw-popup-mode">
<default>1</default> <default>1</default>
</key> </key>
<key type="b" name="ws-switcher-wraparound">
<default>false</default>
</key>
<key type="b" name="ws-switcher-ignore-last">
<default>false</default>
</key>
<key type="i" name="favorites-notify"> <key type="i" name="favorites-notify">
<default>1</default> <default>1</default>
</key> </key>
@ -242,10 +266,10 @@
<default>1</default> <default>1</default>
</key> </key>
<key type="i" name="hot-corner-position"> <key type="i" name="hot-corner-position">
<default>0</default> <default>6</default>
</key> </key>
<key type="b" name="hot-corner-fullscreen"> <key type="b" name="hot-corner-fullscreen">
<default>false</default> <default>true</default>
</key> </key>
<key type="b" name="hot-corner-ripples"> <key type="b" name="hot-corner-ripples">
<default>true</default> <default>true</default>
@ -253,19 +277,37 @@
<key type="b" name="always-activate-selected-window"> <key type="b" name="always-activate-selected-window">
<default>false</default> <default>false</default>
</key> </key>
<key type="b" name="window-icon-click-search"> <key type="i" name="win-preview-sec-mouse-btn-action">
<default>2</default>
</key>
<key type="i" name="win-preview-mid-mouse-btn-action">
<default>0</default>
</key>
<key type="b" name="win-preview-show-close-button">
<default>true</default> <default>true</default>
</key> </key>
<key type="i" name="window-icon-click-action">
<default>1</default>
</key>
<key type="i" name="overlay-key-primary"> <key type="i" name="overlay-key-primary">
<default>1</default> <default>1</default>
</key> </key>
<key type="i" name="overlay-key-secondary"> <key type="i" name="overlay-key-secondary">
<default>1</default> <default>1</default>
</key> </key>
<key type="i" name="overview-esc-behavior">
<key type="b" name="workspace-thumbnails-module"> <default>0</default>
</key>
<key type="b" name="new-window-focus-fix">
<default>false</default>
</key>
<key type="b" name="app-grid-performance">
<default>true</default> <default>true</default>
</key> </key>
<key type="i" name="window-thumbnail-scale">
<default>15</default>
</key>
<key type="b" name="workspace-switcher-popup-module"> <key type="b" name="workspace-switcher-popup-module">
<default>true</default> <default>true</default>
</key> </key>
@ -284,9 +326,15 @@
<key type="b" name="win-attention-handler-module"> <key type="b" name="win-attention-handler-module">
<default>true</default> <default>true</default>
</key> </key>
<key type="b" name="window-thumbnail-module">
<default>true</default>
</key>
<key type="b" name="swipe-tracker-module"> <key type="b" name="swipe-tracker-module">
<default>true</default> <default>true</default>
</key> </key>
<key type="b" name="search-controller-module">
<default>true</default>
</key>
<key type="b" name="search-module"> <key type="b" name="search-module">
<default>true</default> <default>true</default>
</key> </key>
@ -314,6 +362,15 @@
<key type="b" name="app-favorites-module"> <key type="b" name="app-favorites-module">
<default>true</default> <default>true</default>
</key> </key>
<key type="b" name="window-search-provider-module">
<default>true</default>
</key>
<key type="b" name="recent-files-search-provider-module">
<default>true</default>
</key>
<key type="b" name="extensions-search-provider-module">
<default>true</default>
</key>
<key type="b" name="aaa-loading-profile"> <key type="b" name="aaa-loading-profile">
<default>false</default> <default>false</default>
@ -323,28 +380,28 @@
<default>""</default> <default>""</default>
</key> </key>
<key type="a{ss}" name="profile-data-1"> <key type="a{ss}" name="profile-data-1">
<default>{'workspaceThumbnailsPosition': '1', 'wsMaxSpacing': '350', 'wsPreviewScale': '95', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '3', 'dashPositionAdjust': '0', 'wsTmbPositionAdjust': '-80', 'showWsTmbLabels': '3', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '-80', 'dashMaxIconSize': '64', 'dashShowWindowsIcon': '2', 'dashShowRecentFilesIcon': '2', 'centerDashToWs': 'false', 'showAppsIconPosition': '1', 'wsThumbnailScale': '13', 'wsThumbnailScaleAppGrid': '0', 'secWsThumbnailScale': '13', 'showSearchEntry': 'true', 'centerSearch': 'true', 'centerAppGrid': 'true', 'appGridPageWidthScale': '100', 'dashBgOpacity': '80', 'dashBgRadius': '17', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'true', 'showWsPreviewBg': 'false', 'showBgInOverview': 'true', 'overviewBgBrightness': '30', 'overviewBgBlurSigma': '0', 'appGridBgBlurSigma': '0', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'fixUbuntuDock': 'true', 'winPreviewIconSize': '1', 'alwaysShowWinTitles': 'false', 'startupState': '0', 'overviewMode': '0', 'workspaceSwitcherAnimation': '1', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '4', 'appGridFolderRows': '3', 'appGridSpacing': '12', 'appGridFolderIconGrid': '2', 'appGridContent': '2', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appGridNamesMode': '0', 'appGridActivePreview': 'false', 'appGridFolderCenter': 'false', 'searchWindowsEnable': 'true', 'searchRecentFilesEnable': 'true', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '0', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '50', 'wsSwPopupMode': '1', 'favoritesNotify': '1', 'notificationPosition': '1', 'hotCornerAction': '1', 'hotCornerPosition': '0', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'true', 'alwaysActivateSelectedWindow': 'false', 'workspaceThumbnailsModule': 'true', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'winAttentionHandlerModule': 'true', 'swipeTrackerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true'}</default> <default>{'workspaceThumbnailsPosition': '1', 'wsMaxSpacing': '350', 'wsPreviewScale': '95', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '3', 'dashPositionAdjust': '0', 'wsTmbPositionAdjust': '-80', 'showWsTmbLabels': '3', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '-80', 'dashMaxIconSize': '64', 'dashShowWindowsIcon': '2', 'dashShowRecentFilesIcon': '2', 'dashShowExtensionsIcon': '2', 'centerDashToWs': 'false', 'showAppsIconPosition': '1', 'wsThumbnailScale': '13', 'wsThumbnailScaleAppGrid': '13', 'secWsThumbnailScale': '13', 'showSearchEntry': 'true', 'centerSearch': 'true', 'centerAppGrid': 'true', 'dashBgOpacity': '80', 'dashBgColor': '0', 'dashBgRadius': '0', 'dashBgGS3Style': 'true', 'runningDotStyle': '1', 'enablePageShortcuts': 'false', 'showWsSwitcherBg': 'true', 'showWsPreviewBg': 'false', 'wsPreviewBgRadius': '30', 'showBgInOverview': 'true', 'overviewBgBrightness': '30', 'searchBgBrightness': '30', 'overviewBgBlurSigma': '0', 'appGridBgBlurSigma': '40', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '0', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'winPreviewIconSize': '1', 'winTitlePosition': '0', 'startupState': '0', 'overviewMode': '0', 'workspaceSwitcherAnimation': '1', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '0', 'appGridFolderRows': '0', 'appGridFolderIconGrid': '2', 'appGridContent': '2', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appFolderOrder': '0', 'appGridNamesMode': '1', 'appGridActivePreview': 'false', 'appGridFolderCenter': 'false', 'appGridPageWidthScale': '100', 'appGridSpacing': '12', 'searchWindowsOrder': '1', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'dashIconScroll': '1', 'dashIsolateWorkspaces': 'false', 'searchWindowsIconScroll': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '0', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'wsSwitcherWraparound': 'false', 'wsSwitcherIgnoreLast': 'false', 'favoritesNotify': '1', 'notificationPosition': '1', 'osdPosition': '6', 'hotCornerAction': '1', 'hotCornerPosition': '0', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'true', 'alwaysActivateSelectedWindow': 'false', 'winPreviewSecBtnAction': '3', 'winPreviewMidBtnAction': '1', 'winPreviewShowCloseButton': 'true', 'windowIconClickAction': '1', 'overlayKeyPrimary': '1', 'overlayKeySecondary': '1', 'overviewEscBehavior': '0', 'newWindowFocusFix': 'false', 'appGridPerformance': 'true', 'windowThumbnailScale': '20', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'windowAttentionHandlerModule': 'true', 'windowThumbnailModule': 'true', 'swipeTrackerModule': 'true', 'searchControllerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'overlayKeyModule': 'true', 'osdWindowModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true', 'windowSearchProviderModule': 'true', 'extensionsSearchProviderModule': 'true'}</default>
</key> </key>
<key type="s" name="profile-name-2"> <key type="s" name="profile-name-2">
<default>""</default> <default>""</default>
</key> </key>
<key type="a{ss}" name="profile-data-2"> <key type="a{ss}" name="profile-data-2">
<default>{'workspaceThumbnailsPosition': '5', 'wsMaxSpacing': '80', 'wsPreviewScale': '100', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '2', 'dashPositionAdjust': '0', 'wsTmbPositionAdjust': '0', 'showWsTmbLabels': '0', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '0', 'dashMaxIconSize': '64', 'dashShowWindowsIcon': '2', 'dashShowRecentFilesIcon': '2', 'centerDashToWs': 'false', 'showAppsIconPosition': '1', 'wsThumbnailScale': '5', 'wsThumbnailScaleAppGrid': '15', 'secWsThumbnailScale': '13', 'showSearchEntry': 'true', 'centerSearch': 'true', 'centerAppGrid': 'true', 'appGridPageWidthScale': '80', 'dashBgOpacity': '100', 'dashBgRadius': '17', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'true', 'showWsPreviewBg': 'true', 'showBgInOverview': 'false', 'overviewBgBrightness': '30', 'overviewBgBlurSigma': '0', 'appGridBgBlurSigma': '0', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'fixUbuntuDock': 'true', 'winPreviewIconSize': '0', 'alwaysShowWinTitles': 'false', 'startupState': '0', 'overviewMode': '0', 'workspaceSwitcherAnimation': '0', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '3', 'appGridFolderRows': '3', 'appGridSpacing': '12', 'appGridFolderIconGrid': '2', 'appGridContent': '2', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appGridNamesMode': '0', 'appGridActivePreview': 'false', 'appGridFolderCenter': 'false', 'searchWindowsEnable': 'true', 'searchRecentFilesEnable': 'true', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '0', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'favoritesNotify': '1', 'notificationPosition': '1', 'hotCornerAction': '1', 'hotCornerPosition': '6', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'false', 'alwaysActivateSelectedWindow': 'false', 'workspaceThumbnailsModule': 'true', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'winAttentionHandlerModule': 'true', 'swipeTrackerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true'}</default> <default>{'workspaceThumbnailsPosition': '5', 'wsMaxSpacing': '80', 'wsPreviewScale': '100', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '2', 'dashPositionAdjust': '0', 'wsTmbPositionAdjust': '0', 'showWsTmbLabels': '0', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '0', 'dashMaxIconSize': '64', 'dashShowWindowsIcon': '2', 'dashShowRecentFilesIcon': '2', 'dashShowExtensionsIcon': '2', 'centerDashToWs': 'false', 'showAppsIconPosition': '1', 'wsThumbnailScale': '5', 'wsThumbnailScaleAppGrid': '15', 'secWsThumbnailScale': '5', 'showSearchEntry': 'true', 'centerSearch': 'true', 'centerAppGrid': 'true', 'dashBgOpacity': '20', 'dashBgColor': '1', 'dashBgRadius': '0', 'dashBgGS3Style': 'false', 'runningDotStyle': '1', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'false', 'showWsPreviewBg': 'true', 'wsPreviewBgRadius': '30', 'showBgInOverview': 'true', 'overviewBgBrightness': '50', 'searchBgBrightness': '30', 'overviewBgBlurSigma': '50', 'appGridBgBlurSigma': '40', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'winPreviewIconSize': '1', 'winTitlePosition': '0', 'startupState': '0', 'overviewMode': '0', 'workspaceSwitcherAnimation': '0', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '0', 'appGridFolderRows': '0', 'appGridFolderIconGrid': '2', 'appGridContent': '2', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appFolderOrder': '0', 'appGridNamesMode': '1', 'appGridActivePreview': 'false', 'appGridFolderCenter': 'true', 'appGridPageWidthScale': '90', 'appGridSpacing': '12', 'searchWindowsOrder': '1', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'dashIconScroll': '1', 'dashIsolateWorkspaces': 'false', 'searchWindowsIconScroll': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '0', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'wsSwitcherWraparound': 'false', 'wsSwitcherIgnoreLast': 'false', 'favoritesNotify': '1', 'notificationPosition': '1', 'osdPosition': '6', 'hotCornerAction': '1', 'hotCornerPosition': '6', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'false', 'alwaysActivateSelectedWindow': 'false', 'winPreviewSecBtnAction': '2', 'winPreviewMidBtnAction': '1', 'winPreviewShowCloseButton': 'true', 'windowIconClickAction': '1', 'overlayKeyPrimary': '1', 'overlayKeySecondary': '1', 'overviewEscBehavior': '0', 'newWindowFocusFix': 'false', 'appGridPerformance': 'true', 'windowThumbnailScale': '20', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'windowAttentionHandlerModule': 'true', 'windowThumbnailModule': 'true', 'swipeTrackerModule': 'true', 'searchControllerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'overlayKeyModule': 'true', 'osdWindowModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true', 'windowSearchProviderModule': 'true', 'extensionsSearchProviderModule': 'true'}</default>
</key> </key>
<key type="s" name="profile-name-3"> <key type="s" name="profile-name-3">
<default>""</default> <default>""</default>
</key> </key>
<key type="a{ss}" name="profile-data-3"> <key type="a{ss}" name="profile-data-3">
<default>{'workspaceThumbnailsPosition': '0', 'wsMaxSpacing': '350', 'wsPreviewScale': '95', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '0', 'dashPositionAdjust': '-100', 'wsTmbPositionAdjust': '-100', 'showWsTmbLabels': '3', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '0', 'dashMaxIconSize': '48', 'dashShowWindowsIcon': '1', 'dashShowRecentFilesIcon': '1', 'centerDashToWs': 'false', 'showAppsIconPosition': '0', 'wsThumbnailScale': '13', 'wsThumbnailScaleAppGrid': '0', 'secWsThumbnailScale': '13', 'showSearchEntry': 'false', 'centerSearch': 'true', 'centerAppGrid': 'false', 'appGridPageWidthScale': '90', 'dashBgOpacity': '85', 'dashBgRadius': '17', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'true', 'showWsPreviewBg': 'false', 'showBgInOverview': 'true', 'overviewBgBrightness': '95', 'overviewBgBlurSigma': '0', 'appGridBgBlurSigma': '80', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'fixUbuntuDock': 'true', 'winPreviewIconSize': '1', 'alwaysShowWinTitles': 'true', 'startupState': '2', 'overviewMode': '1', 'workspaceSwitcherAnimation': '1', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '0', 'appGridFolderRows': '0', 'appGridSpacing': '12', 'appGridFolderIconGrid': '3', 'appGridContent': '0', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appGridNamesMode': '0', 'appGridActivePreview': 'true', 'appGridFolderCenter': 'false', 'searchWindowsEnable': 'true', 'searchRecentFilesEnable': 'true', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '2', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'favoritesNotify': '0', 'notificationPosition': '2', 'hotCornerAction': '1', 'hotCornerPosition': '1', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'true', 'alwaysActivateSelectedWindow': 'false', 'workspaceThumbnailsModule': 'true', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'winAttentionHandlerModule': 'true', 'swipeTrackerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true'}</default> <default>{'workspaceThumbnailsPosition': '0', 'wsMaxSpacing': '350', 'wsPreviewScale': '95', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '0', 'dashPositionAdjust': '-100', 'wsTmbPositionAdjust': '-100', 'showWsTmbLabels': '3', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '0', 'dashMaxIconSize': '48', 'dashShowWindowsIcon': '1', 'dashShowRecentFilesIcon': '1', 'dashShowExtensionsIcon': '1', 'centerDashToWs': 'false', 'showAppsIconPosition': '0', 'wsThumbnailScale': '13', 'wsThumbnailScaleAppGrid': '13', 'secWsThumbnailScale': '13', 'showSearchEntry': 'false', 'centerSearch': 'true', 'centerAppGrid': 'false', 'dashBgOpacity': '20', 'dashBgColor': '1', 'dashBgRadius': '0', 'dashBgGS3Style': 'false', 'runningDotStyle': '1', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'false', 'showWsPreviewBg': 'true', 'wsPreviewBgRadius': '30', 'showBgInOverview': 'true', 'overviewBgBrightness': '60', 'searchBgBrightness': '30', 'overviewBgBlurSigma': '30', 'appGridBgBlurSigma': '80', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'winPreviewIconSize': '1', 'winTitlePosition': '0', 'startupState': '2', 'overviewMode': '1', 'workspaceSwitcherAnimation': '1', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '0', 'appGridFolderRows': '0', 'appGridFolderIconGrid': '3', 'appGridContent': '0', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appFolderOrder': '0', 'appGridNamesMode': '1', 'appGridActivePreview': 'true', 'appGridFolderCenter': 'false', 'appGridPageWidthScale': '90', 'appGridSpacing': '12', 'searchWindowsOrder': '1', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'dashIconScroll': '1', 'dashIsolateWorkspaces': 'false', 'searchWindowsIconScroll': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '0', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'wsSwitcherWraparound': 'false', 'wsSwitcherIgnoreLast': 'false', 'favoritesNotify': '0', 'notificationPosition': '2', 'osdPosition': '6', 'hotCornerAction': '1', 'hotCornerPosition': '1', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'true', 'alwaysActivateSelectedWindow': 'false', 'winPreviewSecBtnAction': '2', 'winPreviewMidBtnAction': '1', 'winPreviewShowCloseButton': 'true', 'windowIconClickAction': '1', 'overlayKeyPrimary': '1', 'overlayKeySecondary': '1', 'overviewEscBehavior': '0', 'newWindowFocusFix': 'false', 'appGridPerformance': 'true', 'windowThumbnailScale': '20', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'windowAttentionHandlerModule': 'true', 'windowThumbnailModule': 'true', 'swipeTrackerModule': 'true', 'searchControllerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'overlayKeyModule': 'true', 'osdWindowModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true', 'windowSearchProviderModule': 'true', 'extensionsSearchProviderModule': 'true'}</default>
</key> </key>
<key type="s" name="profile-name-4"> <key type="s" name="profile-name-4">
<default>""</default> <default>""</default>
</key> </key>
<key type="a{ss}" name="profile-data-4"> <key type="a{ss}" name="profile-data-4">
<default>{'workspaceThumbnailsPosition': '6', 'wsMaxSpacing': '65', 'wsPreviewScale': '95', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '2', 'dashPositionAdjust': '0', 'wsTmbPositionAdjust': '0', 'showWsTmbLabels': '3', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '0', 'dashMaxIconSize': '48', 'dashShowWindowsIcon': '1', 'dashShowRecentFilesIcon': '1', 'centerDashToWs': 'false', 'showAppsIconPosition': '1', 'wsThumbnailScale': '10', 'wsThumbnailScaleAppGrid': '0', 'secWsThumbnailScale': '10', 'showSearchEntry': 'false', 'centerSearch': 'true', 'centerAppGrid': 'false', 'appGridPageWidthScale': '90', 'dashBgOpacity': '85', 'dashBgRadius': '17', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'true', 'showWsPreviewBg': 'true', 'showBgInOverview': 'true', 'overviewBgBrightness': '100', 'overviewBgBlurSigma': '80', 'appGridBgBlurSigma': '80', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'fixUbuntuDock': 'true', 'winPreviewIconSize': '2', 'alwaysShowWinTitles': 'true', 'startupState': '2', 'overviewMode': '2', 'workspaceSwitcherAnimation': '1', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '0', 'appGridFolderRows': '0', 'appGridSpacing': '12', 'appGridFolderIconGrid': '3', 'appGridContent': '0', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appGridNamesMode': '0', 'appGridActivePreview': 'true', 'appGridFolderCenter': 'false', 'searchWindowsEnable': 'true', 'searchRecentFilesEnable': 'true', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '2', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'favoritesNotify': '0', 'notificationPosition': '1', 'hotCornerAction': '1', 'hotCornerPosition': '6', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'false', 'alwaysActivateSelectedWindow': 'false', 'workspaceThumbnailsModule': 'true', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'winAttentionHandlerModule': 'true', 'swipeTrackerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true'}</default> <default>{'workspaceThumbnailsPosition': '6', 'wsMaxSpacing': '65', 'wsPreviewScale': '95', 'secWsPreviewScale': '100', 'secWsPreviewShift': 'false', 'wsThumbnailsFull': 'false', 'secWsThumbnailsPosition': '2', 'dashPosition': '2', 'dashPositionAdjust': '0', 'wsTmbPositionAdjust': '0', 'showWsTmbLabels': '3', 'showWsTmbLabelsOnHover': 'false', 'closeWsButtonMode': '2', 'secWsTmbPositionAdjust': '0', 'dashMaxIconSize': '48', 'dashShowWindowsIcon': '1', 'dashShowRecentFilesIcon': '1', 'dashShowExtensionsIcon': '1', 'centerDashToWs': 'false', 'showAppsIconPosition': '1', 'wsThumbnailScale': '10', 'wsThumbnailScaleAppGrid': '10', 'secWsThumbnailScale': '10', 'showSearchEntry': 'false', 'centerSearch': 'true', 'centerAppGrid': 'false', 'dashBgOpacity': '100', 'dashBgColor': '0', 'dashBgRadius': '0', 'dashBgGS3Style': 'false', 'runningDotStyle': '1', 'enablePageShortcuts': 'true', 'showWsSwitcherBg': 'true', 'showWsPreviewBg': 'true', 'wsPreviewBgRadius': '30', 'showBgInOverview': 'true', 'overviewBgBrightness': '60', 'searchBgBrightness': '30', 'overviewBgBlurSigma': '80', 'appGridBgBlurSigma': '80', 'smoothBlurTransitions': 'false', 'appGridAnimation': '4', 'searchViewAnimation': '4', 'workspaceAnimation': '1', 'animationSpeedFactor': '100', 'winPreviewIconSize': '1', 'winTitlePosition': '0', 'startupState': '2', 'overviewMode': '2', 'workspaceSwitcherAnimation': '1', 'searchIconSize': '96', 'searchViewScale': '104', 'appGridIconSize': '-1', 'appGridColumns': '0', 'appGridRows': '0', 'appGridFolderIconSize': '-1', 'appGridFolderColumns': '0', 'appGridFolderRows': '0', 'appGridFolderIconGrid': '3', 'appGridContent': '0', 'appGridIncompletePages': 'false', 'appGridOrder': '0', 'appFolderOrder': '0', 'appGridNamesMode': '1', 'appGridActivePreview': 'true', 'appGridFolderCenter': 'false', 'appGridPageWidthScale': '90', 'appGridSpacing': '5', 'searchWindowsOrder': '1', 'searchFuzzy': 'false', 'searchMaxResultsRows': '5', 'dashShowWindowsBeforeActivation': '1', 'dashIconScroll': '1', 'dashIsolateWorkspaces': 'false', 'searchWindowsIconScroll': '1', 'panelVisibility': '0', 'panelPosition': '0', 'windowAttentionMode': '0', 'wsSwPopupHPosition': '50', 'wsSwPopupVPosition': '95', 'wsSwPopupMode': '1', 'wsSwitcherWraparound': 'false', 'wsSwitcherIgnoreLast': 'false', 'favoritesNotify': '0', 'notificationPosition': '1', 'osdPosition': '6', 'hotCornerAction': '1', 'hotCornerPosition': '6', 'hotCornerFullscreen': 'true', 'hotCornerRipples': 'false', 'alwaysActivateSelectedWindow': 'false', 'winPreviewSecBtnAction': '2', 'winPreviewMidBtnAction': '1', 'winPreviewShowCloseButton': 'true', 'windowIconClickAction': '1', 'overlayKeyPrimary': '1', 'overlayKeySecondary': '1', 'overviewEscBehavior': '0', 'newWindowFocusFix': 'false', 'appGridPerformance': 'true', 'windowThumbnailScale': '20', 'workspaceSwitcherPopupModule': 'true', 'workspaceAnimationModule': 'true', 'workspaceModule': 'true', 'windowManagerModule': 'true', 'windowPreviewModule': 'true', 'windowAttentionHandlerModule': 'true', 'windowThumbnailModule': 'true', 'swipeTrackerModule': 'true', 'searchControllerModule': 'true', 'searchModule': 'true', 'panelModule': 'true', 'overlayKeyModule': 'true', 'osdWindowModule': 'true', 'messageTrayModule': 'true', 'layoutModule': 'true', 'dashModule': 'true', 'appFavoritesModule': 'true', 'appDisplayModule': 'true', 'windowSearchProviderModule': 'true', 'extensionsSearchProviderModule': 'true'}</default>
</key> </key>
</schema> </schema>

View file

@ -5,15 +5,18 @@
/* General dash */ /* General dash */
#dash.vertical { #dash.vertical {
margin-right: 0px; margin: 0px;
margin-left: 0px; padding: 0px;
padding: 0px 0;
} }
#dash.vertical .app-well-app, #dash.vertical .app-well-app,
#dash.vertical .show-apps { #dash.vertical .show-apps {
padding-right: 8px; /* left/right padding exceeds dash bg by 6px to
padding-left: 8px; cover spacing between dash and the edge of the screen
so the icons will be selectable even at the edge
this spacing must be accounted for in overview allocate() */
padding-right: 16px;
padding-left: 16px;
/*spacing between icons*/ /*spacing between icons*/
padding-top: 1px; padding-top: 1px;
padding-bottom: 1px; padding-bottom: 1px;
@ -35,48 +38,81 @@
#dash.vertical .app-well-app-running-dot { #dash.vertical .app-well-app-running-dot {
margin: 4px 0px; margin: 4px 0px;
}
#dash.vertical .app-well-app-running-dot-custom {
margin: 4px 0px;
width: 2px; width: 2px;
height: 16px; height: 16px;
} }
#dash.vertical .dash-background { #dash.vertical .dash-background {
margin: 0; margin: 0px;
} }
#dash.vertical-left .dash-background { #dash.vertical-gs3-left .dash-background {
border-radius: 0 18px 18px 0; border-radius: 0 18px 18px 0;
border-left: 0px; border-left: 0px;
padding: 8px 12px 8px 4px; padding: 8px 12px 8px 4px;
margin-left: 0;
} }
#dash.vertical-right .dash-background { #dash.vertical-gs3-right .dash-background {
border-radius: 18px 0 0 18px; border-radius: 18px 0 0 18px;
border-right: 0px; border-right: 0px;
padding: 8px 4px 8px 12px; padding: 8px 4px 8px 12px;
margin-right: 0;
} }
/* default horizontal dash */ #dash.vertical-gs3-left {
.v-shell-dash-background { margin-right: 6px;
padding: 6px; margin-left: 0px;
padding: 0px;
} }
.app-well-app { #dash.vertical-gs3-right {
margin-left: 1px; margin-right: 0px;
margin-right: 1px; margin-left: 6px;
padding: 0px;
}
#dash.vertical-gs3-left .app-well-app,
#dash.vertical-gs3-left .show-apps,
#dash.vertical-gs3-right .app-well-app,
#dash.vertical-gs3-right .show-apps {
/* left/right padding exceeds dash bg by 6px to
cover spacing between dash and the edge of the screen
so the icons will be selectable even at the edge
this spacing must be accounted for in overview allocate() */
padding-right: 9px;
padding-left: 9px;
}
.dash-background-light {
background-color: rgb(200, 200, 200);
border-color: rgba(150, 150, 150, 0.4);
}
.dash-background-reduced {
padding: 10px;
} }
.app-well-app-running-dot { .app-well-app-running-dot {
margin-bottom: 6px; margin-bottom: 12px;
}
.app-well-app-running-dot-custom {
margin-bottom: 12px;
width: 16px; width: 16px;
height: 2px; height: 2px;
} }
/* add shadow to the app grid app label to be readable if it overlaps light icon below */ /* add shadow to the app grid app label to be readable if it overlaps light icon below */
.overview-icon-with-label { .overview-icon-with-label, .folder-name-label {
text-shadow: 1px 1px 3px rgba(33, 33, 33, 1); text-shadow: 1px 1px 3px rgba(33, 33, 33, 0.5);
} }
/*adjustment for the vertical ws switcher indicator popup*/ /* adjustment for the vertical ws switcher indicator popup*/
.ws-switcher-indicator { .ws-switcher-indicator {
padding: 3px; padding: 3px;
margin: 5px; margin: 5px;
@ -87,11 +123,11 @@
margin: 3px; margin: 3px;
} }
/*ws thumbnails captions*/ /* ws thumbnails captions */
.ws-tmb-label { .ws-tmb-label {
padding: 2px; padding: 2px;
color: rgb(255, 255, 255); color: rgb(255, 255, 255);
background-color: rgba(10,10,10,0.8); background-color: rgba(40,40,40,0.8);
text-align: center; text-align: center;
} }
@ -103,7 +139,12 @@
border: 0px; border: 0px;
} }
/*app grid page indicatos*/ .ws-tmb-transparent {
border: 0px;
background-color: rgba(200, 200, 200, 0.2);
}
/* app grid page indicatos */
.page-indicator-icon { .page-indicator-icon {
margin: 10px 10px 10px 10px; margin: 10px 10px 10px 10px;
} }
@ -128,32 +169,47 @@
border-radius: 0px 0px 100px 100px; border-radius: 0px 0px 100px 100px;
} }
/*
.search-entry, .search-entry-om2 { .search-entry{
padding: 5px; background-color: rgba(200, 200, 200, 0.1);
color: white;
border-color: rgba(160, 160, 160, 0.4);
} }
.search-entry:hover,
.search-entry:focus {
background-color: rgba(200, 200, 200, 0.2);
}*/
.search-entry-om2 { .search-entry-om2 {
border: 5px; color: white;
background-color: rgba(40, 40, 40, 1);
} }
.search-section-content { .search-entry-om2:hover,
background-color: rgba(20, 20, 20, 0.8); .search-entry-om2:focus {
color: white; background-color: rgba(50, 50, 50, 1);
} }
/* for static ws mode */ /* for static ws mode */
.search-section-content-om2 { /*.search-section-content-bg,*/
background-color: rgba(20, 20, 20, 0.95); .search-section-content-bg-om2 {
color: white; border-radius: 26px;
border-radius: 20px; border: 1px, rgb(60, 60, 60);
border: 1px, rgb(40, 40, 40); padding-top: 15px;
padding-top: 12px; }
.search-section-content-bg-om2 {
background-color: rgb(40, 40, 40);
}
.search-section-content {
background-color: rgba(200, 200, 200, 0.1);
} }
/* "no results" / "searching..." text*/ /* "no results" / "searching..." text*/
.search-statustext { .search-statustext, .search-statustext-om2 {
background-color: rgba(23,23,23, 0.95); background-color: rgba(200, 200, 200, 0.1);
color: white; color: white;
margin-top: 50px; margin-top: 50px;
padding: 30px; padding: 30px;
@ -161,17 +217,18 @@
text-shadow: 0px 0px 5px rgb(23, 23, 23); text-shadow: 0px 0px 5px rgb(23, 23, 23);
} }
.transparent-panel { .search-statustext-om2 {
background-color: rgb(40, 40, 40);
border: 1px rgba(200, 200, 200, 0.1);
}
#panel:overview, .transparent-panel {
background-color: transparent; background-color: transparent;
} }
/*reduce spacing between app icons in search results*/ /* reduce spacing between app icons in search results */
.grid-search-results { .grid-search-results {
spacing: 2px; spacing: 4px;
}
.panel {
text-shadow: 1px 1px 3px rgba(33, 33, 33, 1);
} }
/* hide vertical scroll bar, it's distracting in the search results */ /* hide vertical scroll bar, it's distracting in the search results */
@ -222,3 +279,29 @@ StButton#vhandle {
.osd-window { .osd-window {
margin: 4em; margin: 4em;
} }
.app-folder .overview-icon,
.edit-folder-button,
.folder-name-entry {
background-color: rgba(200, 200, 200, 0.08);
}
.app-folder-dialog-vshell {
background-color: rgba(200, 200, 200, 0.08);
}
.app-folder-dialog {
border-color: rgba(160, 160, 160, 0.3);
}
.edit-folder-button:hover,
.app-folder:hover .overview-icon,
.app-folder:focus .overview-icon {
background-color: rgba(200, 200, 200, 0.15);
}
/* reduce quick menu buttons height in GS44 */
/*.quick-toggle,
.quick-menu-toggle {
min-height: 42px;
}*/