Updating 44/vertical-workspaces to version 37+20231208 [0d82192].
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
975b88c6bb
commit
07381ac119
37 changed files with 9559 additions and 4338 deletions
File diff suppressed because it is too large
Load diff
|
@ -10,45 +10,63 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { Shell } = imports.gi;
|
||||
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 _overrides;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('appFavoritesModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var AppFavoritesModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
|
||||
_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;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
_overrides = new _Util.Overrides();
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
}
|
||||
|
||||
// AppFavorites.AppFavorites is const, first access returns undefined
|
||||
const dummy = AppFavorites.AppFavorites;
|
||||
_overrides.addOverride('AppFavorites', AppFavorites.AppFavorites.prototype, AppFavoritesCommon);
|
||||
}
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('appFavoritesModule');
|
||||
|
||||
// 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 = {
|
||||
addFavoriteAtPos(appId, pos) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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();
|
||||
}
|
||||
});
|
|
@ -9,11 +9,13 @@
|
|||
*/
|
||||
|
||||
'use strict';
|
||||
const { GLib, St, Meta } = imports.gi;
|
||||
|
||||
const St = imports.gi.St;
|
||||
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const _Util = Me.imports.lib.util;
|
||||
const shellVersion = _Util.shellVersion;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
|
||||
// added sizes for better scaling
|
||||
const IconSize = {
|
||||
|
@ -29,47 +31,58 @@ const IconSize = {
|
|||
LARGE: 96,
|
||||
80: 80,
|
||||
64: 64,
|
||||
48: 48,
|
||||
TINY: 32,
|
||||
TINY: 48,
|
||||
};
|
||||
|
||||
const PAGE_WIDTH_CORRECTION = 100;
|
||||
|
||||
let opt;
|
||||
let _overrides;
|
||||
let _firstRun = true;
|
||||
var IconGridModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('appDisplayModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
cleanGlobals() {
|
||||
Me = 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) {
|
||||
IconGridCommon['findBestModeForSize'] = IconGridCommon._findBestModeForSize;
|
||||
IconGridCommon['_findBestModeForSize'] = undefined;
|
||||
// don't touch original code if module disabled
|
||||
if (reset && !this._firstActivation) {
|
||||
this._disableModule();
|
||||
} else if (!reset) {
|
||||
this._firstActivation = false;
|
||||
this._activateModule();
|
||||
}
|
||||
}
|
||||
_overrides.addOverride('IconGrid', IconGrid.IconGrid.prototype, IconGridCommon);
|
||||
_overrides.addOverride('IconGridLayout', IconGrid.IconGridLayout.prototype, IconGridLayoutCommon);
|
||||
}
|
||||
// workaround - silence page -2 error on gnome 43 while cleaning app grid
|
||||
|
||||
_activateModule() {
|
||||
if (!this._overrides)
|
||||
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 = {
|
||||
getItemsAtPage(page) {
|
||||
|
@ -87,7 +100,7 @@ const IconGridCommon = {
|
|||
return;
|
||||
const { pagePadding } = this.layout_manager;
|
||||
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
|
||||
const pageIndicatorCompensation = opt.ORIENTATION ? 0 : PAGE_WIDTH_CORRECTION;
|
||||
|
||||
|
@ -99,8 +112,13 @@ const IconGridCommon = {
|
|||
this.layoutManager._gridWidth = width;
|
||||
this.layoutManager._gridHeight = height;
|
||||
|
||||
width -= 80; // compensation for default padding
|
||||
height -= 80;
|
||||
|
||||
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 (iconSize > 0 && this._gridModes.length > 1) {
|
||||
let columns = opt.APP_GRID_COLUMNS;
|
||||
|
@ -109,17 +127,20 @@ const IconGridCommon = {
|
|||
let unusedSpaceH = -1;
|
||||
let unusedSpaceV = -1;
|
||||
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) {
|
||||
columns -= 1;
|
||||
unusedSpaceH = width - columns * (iconSize + iconPadding) - (columns - 1) * spacing;
|
||||
unusedSpaceH = width - columns * itemSize - (columns - 1) * spacing;
|
||||
}
|
||||
}
|
||||
if (!rows) {
|
||||
rows = Math.floor(height / (iconSize + iconPadding)) + 1;
|
||||
rows = Math.floor(height / itemSize) + 1;
|
||||
while (unusedSpaceV < 0) {
|
||||
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 nColumns = this.columnsPerPage;
|
||||
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 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 paddingV = this._isFolder ? this.pagePadding.top + this.pagePadding.bottom : 0;
|
||||
|
@ -156,10 +184,14 @@ const IconGridLayoutCommon = {
|
|||
return opt.APP_GRID_ICON_SIZE_DEFAULT;*/
|
||||
|
||||
let iconSizes = Object.values(IconSize).sort((a, b) => b - a);
|
||||
|
||||
// limit max icon size for folders, the whole range is for the main grid with active folders
|
||||
if (this._isFolder)
|
||||
// limit max icon size for folders and fully adaptive folder grids, 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)
|
||||
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);
|
||||
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;
|
||||
for (const size of iconSizes) {
|
||||
|
@ -167,10 +199,9 @@ const IconGridLayoutCommon = {
|
|||
|
||||
if (firstItem) {
|
||||
firstItem.icon.setIconSize(size);
|
||||
const [firstItemWidth, firstItemHeight] =
|
||||
firstItem.get_preferred_size();
|
||||
const [firstItemWidth] = firstItem.get_preferred_size();
|
||||
|
||||
const itemSize = Math.max(firstItemWidth, firstItemHeight);
|
||||
const itemSize = firstItemWidth;
|
||||
if (itemSize < size)
|
||||
sizeInvalid = true;
|
||||
|
||||
|
@ -199,7 +230,7 @@ const IconGridLayoutCommon = {
|
|||
|
||||
removeItem(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;
|
||||
// throw new Error(`Item ${item} is not part of the IconGridLayout`);
|
||||
}
|
||||
|
@ -215,13 +246,13 @@ const IconGridLayoutCommon = {
|
|||
|
||||
addItem(item, page = -1, index = -1) {
|
||||
if (this._items.has(item)) {
|
||||
log(`iconGrid: Item ${item} already added to IconGridLayout`);
|
||||
console.error(`iconGrid: Item ${item} already added to IconGridLayout`);
|
||||
return;
|
||||
// throw new Error(`Item ${item} already added to IconGridLayout`);
|
||||
}
|
||||
|
||||
if (page > this._pages.length) {
|
||||
log(`iconGrid: Cannot add ${item} to page ${page}`);
|
||||
console.error(`iconGrid: Cannot add ${item} to page ${page}`);
|
||||
page = -1;
|
||||
index = -1;
|
||||
// throw new Error(`Cannot add ${item} to page ${page}`);
|
||||
|
@ -240,7 +271,7 @@ const IconGridLayoutCommon = {
|
|||
|
||||
moveItem(item, newPage, newPosition) {
|
||||
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;
|
||||
// throw new Error(`Item ${item} is not part of the IconGridLayout`);
|
||||
}
|
||||
|
|
|
@ -10,67 +10,107 @@
|
|||
|
||||
'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 Ripples = imports.ui.ripples;
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const _Util = Me.imports.lib.util;
|
||||
|
||||
let _overrides;
|
||||
let _timeouts;
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
let _originalUpdateHotCorners;
|
||||
|
||||
function update(reset = false) {
|
||||
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;
|
||||
let _timeouts;
|
||||
|
||||
// don't even touch this module if disabled or in conflict
|
||||
if (_firstRun && (reset || conflict))
|
||||
return;
|
||||
var LayoutModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
_timeouts = {};
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (!_originalUpdateHotCorners)
|
||||
_originalUpdateHotCorners = Layout.LayoutManager.prototype._updateHotCorners;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
if (_timeouts) {
|
||||
Object.values(_timeouts).forEach(t => {
|
||||
if (t)
|
||||
GLib.source_remove(t);
|
||||
});
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
this._originalUpdateHotCorners = null;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
_timeouts = null;
|
||||
Main.layoutManager._updateHotCorners = _originalUpdateHotCorners;
|
||||
Main.layoutManager._updateHotCorners();
|
||||
return;
|
||||
}
|
||||
|
||||
_timeouts = {};
|
||||
update(reset) {
|
||||
this._removeTimeouts();
|
||||
|
||||
_overrides = new _Util.Overrides();
|
||||
_overrides.addOverride('LayoutManager', Layout.LayoutManager.prototype, LayoutManagerCommon);
|
||||
this.moduleEnabled = opt.get('layoutModule');
|
||||
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();
|
||||
Main.layoutManager._updateHotCorners();
|
||||
}
|
||||
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(' 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 = {
|
||||
_updatePanelBarrier() {
|
||||
|
@ -84,7 +124,7 @@ const LayoutManagerCommon = {
|
|||
this._leftPanelBarrier = null;
|
||||
}
|
||||
|
||||
if (!this.primaryMonitor || !opt)
|
||||
if (!this.primaryMonitor || !opt || Me.Util.getEnabledExtensions('hidetopbar'))
|
||||
return;
|
||||
|
||||
if (this.panelBox.height) {
|
||||
|
@ -113,6 +153,7 @@ const LayoutManagerCommon = {
|
|||
// avoid errors if called from foreign override
|
||||
if (!opt)
|
||||
return;
|
||||
|
||||
// destroy old hot corners
|
||||
this.hotCorners.forEach(corner => corner?.destroy());
|
||||
this.hotCorners = [];
|
||||
|
@ -122,7 +163,7 @@ const LayoutManagerCommon = {
|
|||
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
|
||||
const position = opt.HOT_CORNER_POSITION;
|
||||
|
@ -181,8 +222,8 @@ const LayoutManagerCommon = {
|
|||
}
|
||||
|
||||
if (haveCorner) {
|
||||
let corner = new HotCorner(this, monitor, cornerX, cornerY);
|
||||
corner.setBarrierSize(size);
|
||||
let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY);
|
||||
corner.setBarrierSize(size, false);
|
||||
this.hotCorners.push(corner);
|
||||
} else {
|
||||
this.hotCorners.push(null);
|
||||
|
@ -193,11 +234,8 @@ const LayoutManagerCommon = {
|
|||
},
|
||||
};
|
||||
|
||||
var HotCorner = GObject.registerClass(
|
||||
class HotCorner extends Layout.HotCorner {
|
||||
_init(layoutManager, monitor, x, y) {
|
||||
super._init(layoutManager, monitor, x, y);
|
||||
|
||||
const HotCornerCommon = {
|
||||
after__init() {
|
||||
let angle = 0;
|
||||
switch (opt.HOT_CORNER_POSITION) {
|
||||
case 2:
|
||||
|
@ -214,9 +252,14 @@ class HotCorner extends Layout.HotCorner {
|
|||
this._ripples._ripple1.rotation_angle_z = angle;
|
||||
this._ripples._ripple2.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) {
|
||||
this._pressureBarrier.removeBarrier(this._verticalBarrier);
|
||||
this._verticalBarrier.destroy();
|
||||
|
@ -232,8 +275,8 @@ class HotCorner extends Layout.HotCorner {
|
|||
if (size > 0) {
|
||||
const primaryMonitor = global.display.get_primary_monitor();
|
||||
const monitor = this._monitor;
|
||||
const extendV = opt && opt.HOT_CORNER_EDGE && opt.DASH_VERTICAL && monitor.index === primaryMonitor;
|
||||
const extendH = 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_ACTION && opt.HOT_CORNER_EDGE && !opt.DASH_VERTICAL && monitor.index === primaryMonitor;
|
||||
|
||||
if (opt.HOT_CORNER_POSITION <= 1) {
|
||||
this._verticalBarrier = new Meta.Barrier({
|
||||
|
@ -284,25 +327,52 @@ class HotCorner extends Layout.HotCorner {
|
|||
this._pressureBarrier.addBarrier(this._verticalBarrier);
|
||||
this._pressureBarrier.addBarrier(this._horizontalBarrier);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_toggleOverview() {
|
||||
if (!opt.HOT_CORNER_ACTION || (!opt.HOT_CORNER_FULLSCREEN && this._monitor.inFullscreen && !Main.overview.visible))
|
||||
return;
|
||||
|
||||
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);
|
||||
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);
|
||||
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();
|
||||
}
|
||||
if (opt.HOT_CORNER_RIPPLES && Main.overview.animationInProgress)
|
||||
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)) {
|
||||
Main.overview.hide();
|
||||
} else if (Main.overview.dash.showAppsButton.checked) {
|
||||
|
@ -320,17 +390,17 @@ class HotCorner extends Layout.HotCorner {
|
|||
// delay cannot be too short
|
||||
200,
|
||||
() => {
|
||||
Main.overview.show();
|
||||
Main.overview.show(1, customOverviewMode);
|
||||
|
||||
_timeouts.releaseKeyboardTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
Main.overview.show();
|
||||
Main.overview.show(1, customOverviewMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_toggleApplications(leaveOverview = false) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_toggleWindowSearchProvider() {
|
||||
if (!Main.overview._overview._controls._searchController._searchActive) {
|
||||
this._toggleWindowPicker();
|
||||
const prefix = 'wq// ';
|
||||
opt.OVERVIEW_MODE = 2;
|
||||
opt.OVERVIEW_MODE2 = true;
|
||||
opt.WORKSPACE_MODE = 0;
|
||||
this._toggleWindowPicker(false, true);
|
||||
const prefix = Me.WSP_PREFIX;
|
||||
const position = prefix.length;
|
||||
const searchEntry = Main.overview.searchEntry;
|
||||
searchEntry.set_text(prefix);
|
||||
|
@ -376,5 +449,5 @@ class HotCorner extends Layout.HotCorner {
|
|||
// Main.overview.searchEntry.text = '';
|
||||
Main.overview.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -10,58 +10,82 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { Clutter } = imports.gi;
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const Clutter = imports.gi.Clutter;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('messageTrayModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var MessageTrayModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
}
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (reset) {
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
setNotificationPosition(1);
|
||||
return;
|
||||
}
|
||||
|
||||
setNotificationPosition(opt.NOTIFICATION_POSITION);
|
||||
}
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('messageTrayModule');
|
||||
const conflict = false;
|
||||
|
||||
function 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;
|
||||
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(' MessageTrayModule - Keeping untouched');
|
||||
}
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,41 +9,35 @@
|
|||
|
||||
'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;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
const Settings = Me.imports.lib.settings;
|
||||
|
||||
const shellVersion = Settings.shellVersion;
|
||||
let Me;
|
||||
|
||||
// gettext
|
||||
const _ = Settings._;
|
||||
let _; // = Settings._;
|
||||
|
||||
const ProfileNames = [
|
||||
_('GNOME 3'),
|
||||
_('GNOME 40+ - Bottom Hot Edge'),
|
||||
_('Hot Corner Centric - Top Left Hot Corner'),
|
||||
_('Dock Overview - Bottom Hot Edge'),
|
||||
];
|
||||
function init(me) {
|
||||
Me = me;
|
||||
_ = Me.gettext;
|
||||
}
|
||||
|
||||
// libadwaita is available starting with GNOME Shell 42.
|
||||
let Adw = null;
|
||||
try {
|
||||
Adw = imports.gi.Adw;
|
||||
} catch (e) {}
|
||||
function cleanGlobals() {
|
||||
Me = null;
|
||||
_ = null;
|
||||
}
|
||||
|
||||
function _newImageFromIconName(name) {
|
||||
return Gtk.Image.new_from_icon_name(name);
|
||||
}
|
||||
|
||||
var ItemFactory = class ItemFactory {
|
||||
constructor(gOptions) {
|
||||
this._gOptions = gOptions;
|
||||
this._settings = this._gOptions._gsettings;
|
||||
constructor() {
|
||||
this._settings = Me.Opt._gsettings;
|
||||
}
|
||||
|
||||
getRowWidget(text, caption, widget, variable, options = []) {
|
||||
getRowWidget(text, caption, widget, variable, options = [], dependsOn) {
|
||||
let item = [];
|
||||
let label;
|
||||
if (widget) {
|
||||
|
@ -81,8 +75,8 @@ var ItemFactory = class ItemFactory {
|
|||
|
||||
let key;
|
||||
|
||||
if (variable && this._gOptions.options[variable]) {
|
||||
const opt = this._gOptions.options[variable];
|
||||
if (variable && Me.Opt.options[variable]) {
|
||||
const opt = Me.Opt.options[variable];
|
||||
key = opt[1];
|
||||
}
|
||||
|
||||
|
@ -95,6 +89,11 @@ var ItemFactory = class ItemFactory {
|
|||
this._connectComboBox(widget, key, variable, options);
|
||||
else if (widget._isDropDown)
|
||||
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;
|
||||
|
@ -111,7 +110,7 @@ var ItemFactory = class ItemFactory {
|
|||
_connectComboBox(widget, key, variable, options) {
|
||||
let model = widget.get_model();
|
||||
widget._comboMap = {};
|
||||
const currentValue = this._gOptions.get(variable);
|
||||
const currentValue = Me.Opt.get(variable);
|
||||
for (const [label, value] of options) {
|
||||
let iter;
|
||||
model.set(iter = model.append(), [0, 1], [label, value]);
|
||||
|
@ -120,8 +119,8 @@ var ItemFactory = class ItemFactory {
|
|||
|
||||
widget._comboMap[value] = iter;
|
||||
}
|
||||
this._gOptions.connect(`changed::${key}`, () => {
|
||||
widget.set_active_iter(widget._comboMap[this._gOptions.get(variable, true)]);
|
||||
Me.Opt.connect(`changed::${key}`, () => {
|
||||
widget.set_active_iter(widget._comboMap[Me.Opt.get(variable, true)]);
|
||||
});
|
||||
widget.connect('changed', () => {
|
||||
const [success, iter] = widget.get_active_iter();
|
||||
|
@ -129,17 +128,17 @@ var ItemFactory = class ItemFactory {
|
|||
if (!success)
|
||||
return;
|
||||
|
||||
this._gOptions.set(variable, model.get_value(iter, 1));
|
||||
Me.Opt.set(variable, model.get_value(iter, 1));
|
||||
});
|
||||
}
|
||||
|
||||
_connectDropDown(widget, key, variable, options) {
|
||||
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++) {
|
||||
const text = options[i][0];
|
||||
const id = options[i][1];
|
||||
model.append(new DropDownItem({ text, id }));
|
||||
model.append(new DropDownItemVW({ text, id }));
|
||||
if (id === currentValue)
|
||||
widget.set_selected(i);
|
||||
}
|
||||
|
@ -157,11 +156,11 @@ var ItemFactory = class ItemFactory {
|
|||
|
||||
widget.connect('notify::selected-item', dropDown => {
|
||||
const item = dropDown.get_selected_item();
|
||||
this._gOptions.set(variable, item.id);
|
||||
Me.Opt.set(variable, item.id);
|
||||
});
|
||||
|
||||
this._gOptions.connect(`changed::${key}`, () => {
|
||||
const newId = this._gOptions.get(variable, true);
|
||||
Me.Opt.connect(`changed::${key}`, () => {
|
||||
const newId = Me.Opt.get(variable, true);
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const id = options[i][1];
|
||||
if (id === newId)
|
||||
|
@ -214,7 +213,7 @@ var ItemFactory = class ItemFactory {
|
|||
newDropDown() {
|
||||
const dropDown = new Gtk.DropDown({
|
||||
model: new Gio.ListStore({
|
||||
item_type: DropDownItem,
|
||||
item_type: DropDownItemVW,
|
||||
}),
|
||||
halign: Gtk.Align.END,
|
||||
valign: Gtk.Align.CENTER,
|
||||
|
@ -255,11 +254,11 @@ var ItemFactory = class ItemFactory {
|
|||
|
||||
newLinkButton(uri) {
|
||||
const linkBtn = new Gtk.LinkButton({
|
||||
label: shellVersion < 42 ? 'Click Me!' : '',
|
||||
uri,
|
||||
halign: Gtk.Align.END,
|
||||
valign: Gtk.Align.CENTER,
|
||||
hexpand: true,
|
||||
icon_name: 'emblem-symbolic-link',
|
||||
});
|
||||
return linkBtn;
|
||||
}
|
||||
|
@ -298,18 +297,23 @@ var ItemFactory = class ItemFactory {
|
|||
entry.set_text(opt.get(`profileName${profileIndex}`));
|
||||
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'edit-clear-symbolic');
|
||||
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();
|
||||
resetProfile.set({
|
||||
tooltip_text: _('Reset profile to defaults'),
|
||||
icon_name: 'edit-delete-symbolic',
|
||||
icon_name: 'document-revert-symbolic',
|
||||
hexpand: false,
|
||||
css_classes: ['destructive-action'],
|
||||
});
|
||||
|
||||
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);
|
||||
if (!name)
|
||||
name = ProfileNames[profileIndex - 1];
|
||||
|
@ -317,6 +321,10 @@ var ItemFactory = class ItemFactory {
|
|||
}
|
||||
|
||||
setName();
|
||||
|
||||
entry.connect('icon-press', e => e.set_text(''));
|
||||
entry.connect('changed', e => opt.set(`profileName${profileIndex}`, e.get_text()));
|
||||
|
||||
resetProfile.connect('clicked', () => {
|
||||
reset(profileIndex);
|
||||
setName();
|
||||
|
@ -366,7 +374,7 @@ var ItemFactory = class ItemFactory {
|
|||
valign: Gtk.Align.CENTER,
|
||||
hexpand: true,
|
||||
css_classes: ['destructive-action'],
|
||||
icon_name: 'edit-delete-symbolic',
|
||||
icon_name: 'document-revert-symbolic',
|
||||
});
|
||||
|
||||
btn.connect('clicked', () => {
|
||||
|
@ -382,7 +390,7 @@ var ItemFactory = class ItemFactory {
|
|||
|
||||
var AdwPrefs = class {
|
||||
constructor(gOptions) {
|
||||
this._gOptions = gOptions;
|
||||
Me.Opt = gOptions;
|
||||
}
|
||||
|
||||
getFilledWindow(window, pages) {
|
||||
|
@ -457,158 +465,9 @@ var AdwPrefs = class {
|
|||
}
|
||||
};
|
||||
|
||||
var LegacyPrefs = class {
|
||||
constructor(gOptions) {
|
||||
this._gOptions = gOptions;
|
||||
}
|
||||
|
||||
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',
|
||||
const { GObject } = imports.gi;
|
||||
const DropDownItemVW = GObject.registerClass({
|
||||
GTypeName: 'DropDownItemVW',
|
||||
Properties: {
|
||||
'text': GObject.ParamSpec.string(
|
||||
'text',
|
||||
|
@ -622,10 +481,11 @@ const DropDownItem = GObject.registerClass({
|
|||
'Id',
|
||||
'Item id stored in settings',
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0, 100, 0
|
||||
// min, max, default
|
||||
-2147483648, 2147483647, 0
|
||||
),
|
||||
},
|
||||
}, class DropDownItem extends GObject.Object {
|
||||
}, class DropDownItemVW extends GObject.Object {
|
||||
get text() {
|
||||
return this._text;
|
||||
}
|
||||
|
@ -641,5 +501,4 @@ const DropDownItem = GObject.registerClass({
|
|||
set id(id) {
|
||||
this._id = id;
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -10,79 +10,104 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { Clutter } = imports.gi;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const OsdWindow = imports.ui.osdWindow;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
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 Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('osdWindowModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
let OsdPositions;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
var OsdWindowModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
_firstRun = false;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
if (reset || !moduleEnabled) {
|
||||
updateExistingOsdWindows(6);
|
||||
_overrides = null;
|
||||
opt = null;
|
||||
return;
|
||||
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,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
_overrides = new _Util.Overrides();
|
||||
_overrides.addOverride('osdWindow', OsdWindow.OsdWindow.prototype, OsdWindowCommon);
|
||||
}
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
OsdPositions = null;
|
||||
}
|
||||
|
||||
function updateExistingOsdWindows(position) {
|
||||
position = position ? position : opt.OSD_POSITION;
|
||||
Main.osdWindowManager._osdWindows.forEach(osd => {
|
||||
osd.set(OsdPositions[position]);
|
||||
});
|
||||
}
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('osdWindowModule');
|
||||
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(' 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 = {
|
||||
after_show() {
|
||||
|
|
|
@ -9,81 +9,94 @@
|
|||
*/
|
||||
|
||||
'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 Overview = imports.ui.overview;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
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 Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
let _originalOverlayKeyHandlerId;
|
||||
let _overlayKeyHandlerId;
|
||||
var OverlayKeyModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('overlayKeyModule', true);
|
||||
reset = reset || (!_firstRun && !moduleEnabled);
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._originalOverlayKeyHandlerId = 0;
|
||||
this._overlayKeyHandlerId = 0;
|
||||
}
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && !moduleEnabled)
|
||||
return;
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (reset) {
|
||||
_updateOverlayKey(reset);
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
return;
|
||||
}
|
||||
|
||||
_updateOverlayKey();
|
||||
}
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('overlayKeyModule');
|
||||
const conflict = false;
|
||||
|
||||
function _updateOverlayKey(reset = false) {
|
||||
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)();
|
||||
}
|
||||
}
|
||||
reset = reset || !this.moduleEnabled || conflict;
|
||||
|
||||
function _restoreOverlayKeyHandler() {
|
||||
// Disconnect modified overlay key handler
|
||||
if (_overlayKeyHandlerId !== null) {
|
||||
global.display.disconnect(_overlayKeyHandlerId);
|
||||
_overlayKeyHandlerId = null;
|
||||
if (reset && !this._firstActivation) {
|
||||
this._disableModule();
|
||||
} else if (!reset) {
|
||||
this._firstActivation = false;
|
||||
this._activateModule();
|
||||
}
|
||||
if (reset && this._firstActivation)
|
||||
console.debug(' OverlayKeyModule - Keeping untouched');
|
||||
}
|
||||
|
||||
// Unblock original overlay key handler
|
||||
if (_originalOverlayKeyHandlerId !== null) {
|
||||
global.display.unblock_signal_handler(_originalOverlayKeyHandlerId);
|
||||
_originalOverlayKeyHandlerId = null;
|
||||
_activateModule() {
|
||||
if (!this._originalOverlayKeyHandlerId) {
|
||||
this._originalOverlayKeyHandlerId = GObject.signal_handler_find(global.display, { signalId: 'overlay-key' });
|
||||
if (this._originalOverlayKeyHandlerId !== null) {
|
||||
global.display.block_signal_handler(this._originalOverlayKeyHandlerId);
|
||||
this._connectOverlayKey();
|
||||
}
|
||||
}
|
||||
console.debug(' OverlayKeyModule - Activated');
|
||||
}
|
||||
}
|
||||
|
||||
function _connectOverlayKey() {
|
||||
this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
|
||||
_disableModule() {
|
||||
this._restoreOverlayKeyHandler();
|
||||
|
||||
this._lastOverlayKeyTime = 0;
|
||||
_overlayKeyHandlerId = global.display.connect('overlay-key', () => {
|
||||
console.debug(' OverlayKeyModule - Disabled');
|
||||
}
|
||||
|
||||
_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'))
|
||||
return;
|
||||
|
||||
const { initialState, finalState, transitioning } =
|
||||
this._stateAdjustment.getStateTransitionParams();
|
||||
this._stateAdjustment.getStateTransitionParams();
|
||||
|
||||
const time = GLib.get_monotonic_time() / 1000;
|
||||
const timeDiff = time - this._lastOverlayKeyTime;
|
||||
|
@ -95,14 +108,61 @@ function _connectOverlayKey() {
|
|||
|
||||
const mode = opt.OVERLAY_KEY_SECONDARY;
|
||||
if (shouldShift) {
|
||||
if (mode === 1)
|
||||
Me.Util.activateSearchProvider('');
|
||||
if (mode === 1) {
|
||||
this._shiftState(Meta.MotionDirection.UP);
|
||||
else if (mode === 2)
|
||||
_Util.activateSearchProvider(WIN_SEARCH_PREFIX);
|
||||
else if (mode === 3)
|
||||
_Util.activateSearchProvider(RECENT_FILES_PREFIX);
|
||||
} else if (mode === 2) {
|
||||
Me.Util.activateSearchProvider(Me.WSP_PREFIX);
|
||||
} else if (mode === 3) {
|
||||
// Changing the overview mode automatically changes the overview transition
|
||||
opt.OVERVIEW_MODE = 0;
|
||||
opt.OVERVIEW_MODE2 = false;
|
||||
opt.WORKSPACE_MODE = 1;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,43 +10,113 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const OverviewControls = imports.ui.overviewControls;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const _Util = Me.imports.lib.util;
|
||||
|
||||
let _overrides;
|
||||
let Me;
|
||||
let opt;
|
||||
|
||||
function update(reset = false) {
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
var OverviewModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
opt = null;
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
_overrides = new _Util.Overrides();
|
||||
cleanGlobals() {
|
||||
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 = {
|
||||
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() {
|
||||
this._animationInProgress = false;
|
||||
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
|
||||
if (!this._shown)
|
||||
this._animateNotVisible();
|
||||
|
||||
this._syncGrab();
|
||||
|
||||
// if user activates overview during startup animation, transition needs to be shifted to the state 2 here
|
||||
const controls = this._overview._controls;
|
||||
if (controls._searchController._searchActive && controls._stateAdjustment.value === 1) {
|
||||
|
@ -55,5 +125,41 @@ const OverviewCommon = {
|
|||
else if (!opt.OVERVIEW_MODE2)
|
||||
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
|
@ -10,188 +10,247 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { GLib } = imports.gi;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const _Util = Me.imports.lib.util;
|
||||
|
||||
const ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
|
||||
const Overview = imports.ui.overview;
|
||||
const Panel = imports.ui.panel;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
let _showingOverviewConId;
|
||||
let _hidingOverviewConId;
|
||||
let _styleChangedConId;
|
||||
const ANIMATION_TIME = Overview.ANIMATION_TIME;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('panelModule', true);
|
||||
// Avoid conflict with other extensions
|
||||
const conflict = _Util.getEnabledExtensions('dash-to-panel').length ||
|
||||
_Util.getEnabledExtensions('hidetopbar').length;
|
||||
reset = reset || (!_firstRun && !moduleEnabled);
|
||||
var PanelModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled or in potential conflict
|
||||
if (_firstRun && (reset || conflict))
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
const panelBox = Main.layoutManager.panelBox;
|
||||
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;
|
||||
this._showingOverviewConId = 0;
|
||||
this._hidingOverviewConId = 0;
|
||||
this._styleChangedConId = 0;
|
||||
}
|
||||
|
||||
_setPanelPosition();
|
||||
_updateStyleChangedConnection();
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
}
|
||||
|
||||
if (opt.PANEL_MODE === 0) {
|
||||
_updateOverviewConnection(true);
|
||||
_reparentPanel(false);
|
||||
panelBox.translation_y = 0;
|
||||
Main.panel.opacity = 255;
|
||||
_setPanelStructs(true);
|
||||
} else if (opt.PANEL_MODE === 1) {
|
||||
if (opt.SHOW_WS_PREVIEW_BG) {
|
||||
_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);
|
||||
_updateOverviewConnection();
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('panelModule');
|
||||
const conflict = Me.Util.getEnabledExtensions('dash-to-panel').length ||
|
||||
Me.Util.getEnabledExtensions('hidetopbar').length;
|
||||
|
||||
if (conflict && !reset)
|
||||
console.warn(`[${Me.metadata.name}] Warning: "Panel" module disabled due to potential conflict with another extension`);
|
||||
|
||||
reset = reset || !this.moduleEnabled || conflict || Main.sessionMode.isLocked;
|
||||
|
||||
// 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(' 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 {
|
||||
// otherwise move the panel below overviewGroup so it can get below workspacesDisplay
|
||||
Main.layoutManager.overviewGroup.set_child_below_sibling(panelBox, Main.overview._overview);
|
||||
_updateOverviewConnection(true);
|
||||
// if ws preview bg is disabled, panel can stay in uiGroup
|
||||
this._reparentPanel(false);
|
||||
this._showPanel(false);
|
||||
this._updateOverviewConnection();
|
||||
}
|
||||
_showPanel(true);
|
||||
} else {
|
||||
// if ws preview bg is disabled, panel can stay in uiGroup
|
||||
_reparentPanel(false);
|
||||
_showPanel(false);
|
||||
_updateOverviewConnection();
|
||||
// _connectPanel();
|
||||
} else if (opt.PANEL_MODE === 2) {
|
||||
this._updateOverviewConnection(true);
|
||||
this._reparentPanel(false);
|
||||
this._showPanel(false);
|
||||
// _connectPanel();
|
||||
}
|
||||
// _connectPanel();
|
||||
} else if (opt.PANEL_MODE === 2) {
|
||||
_updateOverviewConnection(true);
|
||||
_reparentPanel(false);
|
||||
_showPanel(false);
|
||||
// _connectPanel();
|
||||
this._setPanelStructs(opt.PANEL_MODE === 0);
|
||||
Main.layoutManager._updateHotCorners();
|
||||
|
||||
this._overrides.addOverride('ActivitiesButton', Panel.ActivitiesButton.prototype, ActivitiesButton);
|
||||
|
||||
console.debug(' PanelModule - Activated');
|
||||
}
|
||||
_setPanelStructs(opt.PANEL_MODE === 0);
|
||||
Main.layoutManager._updateHotCorners();
|
||||
}
|
||||
|
||||
function _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
|
||||
_disableModule() {
|
||||
const reset = true;
|
||||
this._setPanelPosition(reset);
|
||||
this._updateOverviewConnection(reset);
|
||||
this._reparentPanel(false);
|
||||
|
||||
if (opt.PANEL_POSITION_TOP || reset)
|
||||
panelBox.set_position(geometry.x, geometry.y);
|
||||
else
|
||||
panelBox.set_position(geometry.x, geometry.y + geometry.height - panelHeight);
|
||||
}
|
||||
this._updateStyleChangedConnection(reset);
|
||||
|
||||
function _updateStyleChangedConnection(reset = false) {
|
||||
if (reset) {
|
||||
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) {
|
||||
const panelBox = Main.layoutManager.panelBox;
|
||||
panelBox.translation_y = 0;
|
||||
Main.panel.opacity = 255;
|
||||
Main.layoutManager.panelBox.ease({
|
||||
duration: ANIMATION_TIME,
|
||||
translation_y: 0,
|
||||
onComplete: () => {
|
||||
_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;
|
||||
_setPanelStructs(opt.PANEL_MODE === 0);
|
||||
},
|
||||
});
|
||||
this._setPanelStructs(true);
|
||||
if (this._overrides)
|
||||
this._overrides.removeAll();
|
||||
this._overrides = null;
|
||||
|
||||
console.debug(' PanelModule - Disabled');
|
||||
}
|
||||
}
|
||||
|
||||
_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;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Vertical Workspaces
|
||||
* V-Shell (Vertical Workspaces)
|
||||
* recentFilesSearchProvider.js
|
||||
*
|
||||
* @author GdH <G-dH@github.com>
|
||||
|
@ -9,116 +9,146 @@
|
|||
|
||||
'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 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
|
||||
const _ = Settings._;
|
||||
|
||||
const shellVersion = Settings.shellVersion;
|
||||
|
||||
const ModifierType = imports.gi.Clutter.ModifierType;
|
||||
|
||||
let recentFilesSearchProvider;
|
||||
let _enableTimeoutId = 0;
|
||||
let _;
|
||||
|
||||
// prefix helps to eliminate results from other search providers
|
||||
// so it needs to be something less common
|
||||
// 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() {
|
||||
return Main.overview._overview.controls._searchController._searchResults;
|
||||
}
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._recentFilesSearchProvider = null;
|
||||
this._enableTimeoutId = 0;
|
||||
}
|
||||
|
||||
|
||||
function update(reset = false) {
|
||||
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();
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
function enable() {
|
||||
// delay because Fedora had problem to register a new provider soon after Shell restarts
|
||||
_enableTimeoutId = GLib.timeout_add(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
2000,
|
||||
() => {
|
||||
if (!recentFilesSearchProvider) {
|
||||
recentFilesSearchProvider = new RecentFilesSearchProvider(opt);
|
||||
getOverviewSearchResult()._registerProvider(recentFilesSearchProvider);
|
||||
}
|
||||
_enableTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('recentFilesSearchProviderModule');
|
||||
|
||||
reset = reset || !this.moduleEnabled;
|
||||
|
||||
if (reset && !this._firstActivation) {
|
||||
this._disableModule();
|
||||
} else if (!reset) {
|
||||
this._firstActivation = false;
|
||||
this._activateModule();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function disable() {
|
||||
if (recentFilesSearchProvider) {
|
||||
getOverviewSearchResult()._unregisterProvider(recentFilesSearchProvider);
|
||||
recentFilesSearchProvider = null;
|
||||
if (reset && this._firstActivation)
|
||||
console.debug(' RecentFilesSearchProviderModule - Keeping untouched');
|
||||
}
|
||||
if (_enableTimeoutId) {
|
||||
GLib.source_remove(_enableTimeoutId);
|
||||
_enableTimeoutId = 0;
|
||||
|
||||
_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._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) {
|
||||
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();
|
||||
_disableModule() {
|
||||
if (this._recentFilesSearchProvider) {
|
||||
this._getOverviewSearchResult()._unregisterProvider(this._recentFilesSearchProvider);
|
||||
this._recentFilesSearchProvider = null;
|
||||
}
|
||||
if (this._enableTimeoutId) {
|
||||
GLib.source_remove(this._enableTimeoutId);
|
||||
this._enableTimeoutId = 0;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
console.debug(' RecentFilesSearchProviderModule - Disabled');
|
||||
}
|
||||
|
||||
const closeSelectedRegex = /^\/x!$/;
|
||||
const closeAllResultsRegex = /^\/xa!$/;
|
||||
const moveToWsRegex = /^\/m[0-9]+$/;
|
||||
const moveAllToWsRegex = /^\/ma[0-9]+$/;
|
||||
_getOverviewSearchResult() {
|
||||
return Main.overview._overview.controls._searchController._searchResults;
|
||||
}
|
||||
};
|
||||
|
||||
const RecentFilesSearchProvider = class RecentFilesSearchProvider {
|
||||
class RecentFilesSearchProvider {
|
||||
constructor() {
|
||||
this.id = 'org.gnome.Nautilus.desktop';
|
||||
this.appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -ws recent:///', 'Recent Files', null);
|
||||
// this.appInfo = Shell.AppSystem.get_default().lookup_app('org.gnome.Nautilus.desktop').appInfo;
|
||||
this.appInfo.get_description = () => _('Search recent files');
|
||||
this.appInfo.get_name = () => _('Recent Files');
|
||||
this.appInfo.get_id = () => this.id;
|
||||
this.appInfo.get_icon = () => Gio.icon_new_for_string('document-open-recent-symbolic');
|
||||
this.appInfo.should_show = () => true;
|
||||
this.id = 'recent-files';
|
||||
const appSystem = Shell.AppSystem.get_default();
|
||||
let appInfo = appSystem.lookup_app('org.gnome.Nautilus.desktop')?.get_app_info();
|
||||
if (!appInfo)
|
||||
appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -w', _('Recent Files'), null);
|
||||
appInfo.get_description = () => _('Search recent files');
|
||||
appInfo.get_name = () => _('Recent Files');
|
||||
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.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) {
|
||||
if (!terms[0].startsWith(prefix))
|
||||
if (!terms[0].startsWith(PREFIX))
|
||||
return [];
|
||||
// do not modify original terms
|
||||
let termsCopy = [...terms];
|
||||
// search for terms without prefix
|
||||
termsCopy[0] = termsCopy[0].replace(prefix, '');
|
||||
termsCopy[0] = termsCopy[0].replace(PREFIX, '');
|
||||
|
||||
const candidates = this.files;
|
||||
const _terms = [].concat(termsCopy);
|
||||
|
@ -135,15 +165,18 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
|
|||
const file = this.files[id];
|
||||
const name = `${file.get_age()}d: ${file.get_display_name()} ${file.get_uri_display().replace(`/${file.get_display_name()}`, '')}`;
|
||||
if (opt.SEARCH_FUZZY)
|
||||
m = _Util.fuzzyMatch(term, name);
|
||||
m = Me.Util.fuzzyMatch(term, name);
|
||||
else
|
||||
m = _Util.strictMatch(term, name);
|
||||
m = Me.Util.strictMatch(term, name);
|
||||
|
||||
if (m !== -1)
|
||||
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);
|
||||
return this.resultIds;
|
||||
|
@ -151,7 +184,7 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
|
|||
|
||||
getResultMetas(resultIds, callback = null) {
|
||||
const metas = resultIds.map(id => this.getResultMeta(id));
|
||||
if (shellVersion >= 43)
|
||||
if (Me.shellVersion >= 43)
|
||||
return new Promise(resolve => resolve(metas));
|
||||
else if (callback)
|
||||
callback(metas);
|
||||
|
@ -172,89 +205,54 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
if (path) {
|
||||
gicon = Gio.FileIcon.new(Gio.File.new_for_path(path));
|
||||
} else {
|
||||
const appInfo = Gio.AppInfo.get_default_for_type(result.get_mime_type(), false);
|
||||
if (appInfo)
|
||||
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)
|
||||
icon = new St.Icon({ gicon, icon_size: size });
|
||||
else
|
||||
icon = new St.Icon({ icon_name: 'icon-missing', icon_size: size });
|
||||
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
launchSearch(/* terms, timeStamp */) {
|
||||
this._openNautilus('recent:///');
|
||||
launchSearch(terms, timeStamp) {
|
||||
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) {
|
||||
try {
|
||||
GLib.spawn_command_line_async(`nautilus -ws ${uri}`);
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
||||
|
||||
activateResult(resultId /* , terms, timeStamp */) {
|
||||
const file = this.files[resultId];
|
||||
|
||||
if (_Util.isShiftPressed()) {
|
||||
activateResult(resultId, terms, timeStamp) {
|
||||
const uri = resultId;
|
||||
const context = global.create_app_launch_context(timeStamp, -1);
|
||||
if (Me.Util.isShiftPressed()) {
|
||||
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 {
|
||||
const appInfo = Gio.AppInfo.get_default_for_type(file.get_mime_type(), false);
|
||||
if (!(appInfo && appInfo.launch_uris([file.get_uri()], null)))
|
||||
this._openNautilus(file.get_uri());
|
||||
this.appInfo.launch_uris([uri], context);
|
||||
}
|
||||
}
|
||||
|
||||
getInitialResultSet(terms, callback /* , cancellable = null*/) {
|
||||
// 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);
|
||||
filterResults(results /* , maxResults*/) {
|
||||
// return results.slice(0, maxResults);
|
||||
return results.slice(0, 20);
|
||||
}
|
||||
|
||||
getSubsearchResultSet(previousResults, terms, callback /* , cancellable*/) {
|
||||
// if we return previous results, quick typers get non-actual 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));
|
||||
}
|
||||
|
||||
/* createResultObject(resultMeta) {
|
||||
return this.files[resultMeta.id];
|
||||
}*/
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,92 +9,137 @@
|
|||
*/
|
||||
|
||||
'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 IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const _Util = Me.imports.lib.util;
|
||||
|
||||
const _ = Me.imports.lib.settings._;
|
||||
const shellVersion = _Util.shellVersion;
|
||||
|
||||
let Me;
|
||||
// gettext
|
||||
let _;
|
||||
let opt;
|
||||
let _overrides;
|
||||
let _firstRun = true;
|
||||
|
||||
|
||||
let SEARCH_MAX_WIDTH;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('searchModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var SearchModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
_ = Me.gettext;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
_updateSearchViewWidth(reset);
|
||||
|
||||
if (reset) {
|
||||
Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
_overrides = null;
|
||||
return;
|
||||
_ = null;
|
||||
}
|
||||
|
||||
_overrides = new _Util.Overrides();
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('searchModule');
|
||||
const conflict = false;
|
||||
|
||||
_overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider);
|
||||
_overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
|
||||
_overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
|
||||
reset = reset || !this.moduleEnabled || conflict;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
function _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;
|
||||
// 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(' SearchModule - Keeping untouched');
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
searchContent.set_style('');
|
||||
} else {
|
||||
let width = Math.round(SEARCH_MAX_WIDTH * opt.SEARCH_VIEW_SCALE);
|
||||
searchContent.set_style(`max-width: ${width}px;`);
|
||||
_activateModule() {
|
||||
this._updateSearchViewWidth();
|
||||
|
||||
if (!this._overrides)
|
||||
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
|
||||
const AppSearchProvider = {
|
||||
getInitialResultSet(terms, callback, _cancellable) {
|
||||
getInitialResultSet(terms, callback, cancellable) {
|
||||
// Defer until the parental controls manager is initialized, so the
|
||||
// results can be filtered correctly.
|
||||
if (!this._parentalControlsManager.initialized) {
|
||||
let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
|
||||
if (this._parentalControlsManager.initialized) {
|
||||
this._parentalControlsManager.disconnect(initializedId);
|
||||
this.getInitialResultSet(terms, callback, _cancellable);
|
||||
}
|
||||
});
|
||||
return;
|
||||
if (Me.shellVersion < 43) {
|
||||
let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
|
||||
if (this._parentalControlsManager.initialized) {
|
||||
this._parentalControlsManager.disconnect(initializedId);
|
||||
this.getInitialResultSet(terms, callback, cancellable);
|
||||
}
|
||||
});
|
||||
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(' ');
|
||||
|
||||
let appInfoList = Shell.AppSystem.get_default().get_installed();
|
||||
|
||||
let weightList = {};
|
||||
|
@ -113,22 +158,25 @@ const AppSearchProvider = {
|
|||
shouldShow = appInfo.should_show() && this._parentalControlsManager.shouldShowApp(appInfo);
|
||||
|
||||
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 gName = appInfo.get_generic_name() || '';
|
||||
let description = appInfo.get_description() || '';
|
||||
let categories = appInfo.get_string('Categories') || '';
|
||||
let keywords = appInfo.get_string('Keywords') || '';
|
||||
name = dispName;
|
||||
string = `${dispName} ${gName} ${description} ${categories} ${keywords}`;
|
||||
name = `${dispName} ${id}`;
|
||||
string = `${dispName} ${gName} ${baseName} ${description} ${categories} ${keywords} ${id}`;
|
||||
}
|
||||
}
|
||||
|
||||
let m = -1;
|
||||
if (shouldShow && opt.SEARCH_FUZZY) {
|
||||
m = _Util.fuzzyMatch(pattern, name);
|
||||
m = (m + _Util.strictMatch(pattern, string)) / 2;
|
||||
m = Me.Util.fuzzyMatch(pattern, name);
|
||||
m = (m + Me.Util.strictMatch(pattern, string)) / 2;
|
||||
} else if (shouldShow) {
|
||||
m = _Util.strictMatch(pattern, string);
|
||||
m = Me.Util.strictMatch(pattern, string);
|
||||
}
|
||||
|
||||
if (m !== -1)
|
||||
|
@ -143,16 +191,18 @@ const AppSearchProvider = {
|
|||
// sort apps by usage list
|
||||
appInfoList.sort((a, b) => usage.compare(a.get_id(), b.get_id()));
|
||||
// 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());
|
||||
|
||||
results = results.concat(this._systemActions.getMatchingActions(terms));
|
||||
|
||||
if (shellVersion < 43)
|
||||
if (Me.shellVersion < 43) {
|
||||
callback(results);
|
||||
else
|
||||
return null;
|
||||
} else {
|
||||
return new Promise(resolve => resolve(results));
|
||||
}
|
||||
},
|
||||
|
||||
// App search result size
|
||||
|
@ -181,12 +231,69 @@ const SearchResult = {
|
|||
St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
|
||||
}
|
||||
// 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();
|
||||
},
|
||||
};
|
||||
|
||||
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() {
|
||||
let haveResults = this._providers.some(provider => {
|
||||
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);
|
||||
},
|
||||
};
|
||||
|
|
94
extensions/44/vertical-workspaces/lib/searchController.js
Normal file
94
extensions/44/vertical-workspaces/lib/searchController.js
Normal 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;
|
||||
},
|
||||
};
|
|
@ -9,25 +9,15 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { GLib } = imports.gi;
|
||||
const GLib = imports.gi.GLib;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
|
||||
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;
|
||||
let Me;
|
||||
|
||||
var Options = class Options {
|
||||
constructor() {
|
||||
this._gsettings = ExtensionUtils.getSettings(_schema);
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
|
||||
this._gsettings = Me.gSettings;
|
||||
this._connectionIds = [];
|
||||
this._writeTimeoutId = 0;
|
||||
this._gsettings.delay();
|
||||
|
@ -51,8 +41,8 @@ var Options = class Options {
|
|||
wsMaxSpacing: ['int', 'ws-max-spacing'],
|
||||
wsPreviewScale: ['int', 'ws-preview-scale'],
|
||||
secWsPreviewScale: ['int', 'secondary-ws-preview-scale'],
|
||||
secWsPreviewShift: ['bool', 'secondary-ws-preview-shift'],
|
||||
wsThumbnailsFull: ['bool', 'ws-thumbnails-full'],
|
||||
secWsPreviewShift: ['boolean', 'secondary-ws-preview-shift'],
|
||||
wsThumbnailsFull: ['boolean', 'ws-thumbnails-full'],
|
||||
secWsThumbnailsPosition: ['int', 'secondary-ws-thumbnails-position'],
|
||||
dashPosition: ['int', 'dash-position'],
|
||||
dashPositionAdjust: ['int', 'dash-position-adjust'],
|
||||
|
@ -64,6 +54,7 @@ var Options = class Options {
|
|||
dashMaxIconSize: ['int', 'dash-max-icon-size'],
|
||||
dashShowWindowsIcon: ['int', 'dash-show-windows-icon'],
|
||||
dashShowRecentFilesIcon: ['int', 'dash-show-recent-files-icon'],
|
||||
dashShowExtensionsIcon: ['int', 'dash-show-extensions-icon'],
|
||||
centerDashToWs: ['boolean', 'center-dash-to-ws'],
|
||||
showAppsIconPosition: ['int', 'show-app-icon-position'],
|
||||
wsThumbnailScale: ['int', 'ws-thumbnail-scale'],
|
||||
|
@ -73,13 +64,17 @@ var Options = class Options {
|
|||
centerSearch: ['boolean', 'center-search'],
|
||||
centerAppGrid: ['boolean', 'center-app-grid'],
|
||||
dashBgOpacity: ['int', 'dash-bg-opacity'],
|
||||
dashBgColor: ['int', 'dash-bg-color'],
|
||||
dashBgRadius: ['int', 'dash-bg-radius'],
|
||||
dashBgGS3Style: ['boolean', 'dash-bg-gs3-style'],
|
||||
runningDotStyle: ['int', 'running-dot-style'],
|
||||
enablePageShortcuts: ['boolean', 'enable-page-shortcuts'],
|
||||
showWsSwitcherBg: ['boolean', 'show-ws-switcher-bg'],
|
||||
showWsPreviewBg: ['boolean', 'show-ws-preview-bg'],
|
||||
wsPreviewBgRadius: ['int', 'ws-preview-bg-radius'],
|
||||
showBgInOverview: ['boolean', 'show-bg-in-overview'],
|
||||
overviewBgBrightness: ['int', 'overview-bg-brightness'],
|
||||
searchBgBrightness: ['int', 'search-bg-brightness'],
|
||||
overviewBgBlurSigma: ['int', 'overview-bg-blur-sigma'],
|
||||
appGridBgBlurSigma: ['int', 'app-grid-bg-blur-sigma'],
|
||||
smoothBlurTransitions: ['boolean', 'smooth-blur-transitions'],
|
||||
|
@ -87,9 +82,8 @@ var Options = class Options {
|
|||
searchViewAnimation: ['int', 'search-view-animation'],
|
||||
workspaceAnimation: ['int', 'workspace-animation'],
|
||||
animationSpeedFactor: ['int', 'animation-speed-factor'],
|
||||
fixUbuntuDock: ['boolean', 'fix-ubuntu-dock'],
|
||||
winPreviewIconSize: ['int', 'win-preview-icon-size'],
|
||||
alwaysShowWinTitles: ['boolean', 'always-show-win-titles'],
|
||||
winTitlePosition: ['int', 'win-title-position'],
|
||||
startupState: ['int', 'startup-state'],
|
||||
overviewMode: ['int', 'overview-mode'],
|
||||
workspaceSwitcherAnimation: ['int', 'workspace-switcher-animation'],
|
||||
|
@ -105,17 +99,18 @@ var Options = class Options {
|
|||
appGridContent: ['int', 'app-grid-content'],
|
||||
appGridIncompletePages: ['boolean', 'app-grid-incomplete-pages'],
|
||||
appGridOrder: ['int', 'app-grid-order'],
|
||||
appFolderOrder: ['int', 'app-folder-order'],
|
||||
appGridNamesMode: ['int', 'app-grid-names'],
|
||||
appGridActivePreview: ['boolean', 'app-grid-active-preview'],
|
||||
appGridFolderCenter: ['boolean', 'app-grid-folder-center'],
|
||||
appGridPageWidthScale: ['int', 'app-grid-page-width-scale'],
|
||||
appGridSpacing: ['int', 'app-grid-spacing'],
|
||||
searchWindowsEnable: ['boolean', 'search-windows-enable'],
|
||||
searchRecentFilesEnable: ['boolean', 'search-recent-files-enable'],
|
||||
searchWindowsOrder: ['int', 'search-windows-order'],
|
||||
searchFuzzy: ['boolean', 'search-fuzzy'],
|
||||
searchMaxResultsRows: ['int', 'search-max-results-rows'],
|
||||
dashShowWindowsBeforeActivation: ['int', 'dash-show-windows-before-activation'],
|
||||
dashIconScroll: ['int', 'dash-icon-scroll'],
|
||||
dashIsolateWorkspaces: ['boolean', 'dash-isolate-workspaces'],
|
||||
searchWindowsIconScroll: ['int', 'search-windows-icon-scroll'],
|
||||
panelVisibility: ['int', 'panel-visibility'],
|
||||
panelPosition: ['int', 'panel-position'],
|
||||
|
@ -123,6 +118,8 @@ var Options = class Options {
|
|||
wsSwPopupHPosition: ['int', 'ws-sw-popup-h-position'],
|
||||
wsSwPopupVPosition: ['int', 'ws-sw-popup-v-position'],
|
||||
wsSwPopupMode: ['int', 'ws-sw-popup-mode'],
|
||||
wsSwitcherWraparound: ['boolean', 'ws-switcher-wraparound'],
|
||||
wsSwitcherIgnoreLast: ['boolean', 'ws-switcher-ignore-last'],
|
||||
favoritesNotify: ['int', 'favorites-notify'],
|
||||
notificationPosition: ['int', 'notification-position'],
|
||||
osdPosition: ['int', 'osd-position'],
|
||||
|
@ -131,17 +128,26 @@ var Options = class Options {
|
|||
hotCornerFullscreen: ['boolean', 'hot-corner-fullscreen'],
|
||||
hotCornerRipples: ['boolean', 'hot-corner-ripples'],
|
||||
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'],
|
||||
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'],
|
||||
workspaceAnimationModule: ['boolean', 'workspace-animation-module'],
|
||||
workspaceModule: ['boolean', 'workspace-module'],
|
||||
windowManagerModule: ['boolean', 'window-manager-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'],
|
||||
searchControllerModule: ['boolean', 'search-controller-module'],
|
||||
searchModule: ['boolean', 'search-module'],
|
||||
panelModule: ['boolean', 'panel-module'],
|
||||
overlayKeyModule: ['boolean', 'overlay-key-module'],
|
||||
|
@ -151,6 +157,9 @@ var Options = class Options {
|
|||
dashModule: ['boolean', 'dash-module'],
|
||||
appFavoritesModule: ['boolean', 'app-favorites-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'],
|
||||
profileName2: ['string', 'profile-name-2'],
|
||||
|
@ -158,9 +167,10 @@ var Options = class Options {
|
|||
profileName4: ['string', 'profile-name-4'],
|
||||
};
|
||||
this.cachedOptions = {};
|
||||
}
|
||||
|
||||
this.shellVersion = shellVersion;
|
||||
// this.storeProfile(0);
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
}
|
||||
|
||||
connect(name, callback) {
|
||||
|
@ -183,7 +193,7 @@ var Options = class Options {
|
|||
|
||||
get(option, updateCache = false) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -195,7 +205,6 @@ var Options = class Options {
|
|||
else
|
||||
gSettings = this._gsettings;
|
||||
|
||||
|
||||
this.cachedOptions[option] = gSettings.get_value(key).deep_unpack();
|
||||
}
|
||||
|
||||
|
@ -242,7 +251,8 @@ var Options = class Options {
|
|||
storeProfile(index) {
|
||||
const profile = {};
|
||||
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));
|
||||
|
@ -250,8 +260,14 @@ var Options = class Options {
|
|||
|
||||
loadProfile(index) {
|
||||
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'));
|
||||
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];
|
||||
let value = options[o];
|
||||
switch (type) {
|
||||
|
@ -275,7 +291,14 @@ var Options = class Options {
|
|||
}
|
||||
|
||||
_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_RIGHT = this.DASH_POSITION === 1;
|
||||
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_FOLLOW_RECENT_WIN = false;
|
||||
|
||||
this.DASH_CLICK_ACTION = this.get('dashShowWindowsBeforeActivation', true);
|
||||
this.DASH_ICON_SCROLL = this.get('dashIconScroll', true);
|
||||
this.DASH_ISOLATE_WS = this.get('dashIsolateWorkspaces');
|
||||
|
||||
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.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.CENTER_DASH_WS = this.get('centerDashToWs', true);
|
||||
this.CENTER_DASH_WS = this.get('centerDashToWs');
|
||||
|
||||
this.MAX_ICON_SIZE = 64; // updates from main module
|
||||
this.SHOW_WINDOWS_ICON = this.get('dashShowWindowsIcon', true);
|
||||
this.SHOW_RECENT_FILES_ICON = this.get('dashShowRecentFilesIcon', true);
|
||||
this.MAX_ICON_SIZE = this.get('dashMaxIconSize');
|
||||
this.SHOW_WINDOWS_ICON = this.get('dashShowWindowsIcon');
|
||||
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.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing', true);
|
||||
this.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing');
|
||||
// ORIENTATION || DASH_LEFT || DASH_RIGHT ? 350 : 80;
|
||||
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
|
||||
// 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];
|
||||
|
@ -311,81 +343,104 @@ var Options = class Options {
|
|||
this.WS_TMB_RIGHT = this.WS_TMB_POSITION === 1;
|
||||
this.WS_TMB_BOTTOM = this.WS_TMB_POSITION === 2;
|
||||
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.SEC_WS_TMB_POSITION = this.get('secWsThumbnailsPosition', true);
|
||||
this.WS_TMB_POSITION_ADJUSTMENT = this.get('wsTmbPositionAdjust') * -1 / 100; // range 1 to -1
|
||||
this.SEC_WS_TMB_POSITION = this.get('secWsThumbnailsPosition');
|
||||
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_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_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_PREVIEW_SHIFT = this.get('secWsPreviewShift', true);
|
||||
this.SHOW_WST_LABELS = this.get('showWsTmbLabels', true);
|
||||
this.SHOW_WST_LABELS_ON_HOVER = this.get('showWsTmbLabelsOnHover', true);
|
||||
this.CLOSE_WS_BUTTON_MODE = this.get('closeWsButtonMode', true);
|
||||
this.SEC_WS_TMB_POSITION_ADJUSTMENT = this.get('secWsTmbPositionAdjust') * -1 / 100; // range 1 to -1
|
||||
this.SEC_WS_PREVIEW_SHIFT = this.get('secWsPreviewShift');
|
||||
this.SHOW_WST_LABELS = this.get('showWsTmbLabels');
|
||||
this.SHOW_WST_LABELS_ON_HOVER = this.get('showWsTmbLabelsOnHover');
|
||||
this.CLOSE_WS_BUTTON_MODE = this.get('closeWsButtonMode');
|
||||
|
||||
this.MAX_THUMBNAIL_SCALE = this.get('wsThumbnailScale', true) / 100;
|
||||
this.MAX_THUMBNAIL_SCALE_APPGRID = this.get('wsThumbnailScaleAppGrid', true) / 100;
|
||||
if (this.MAX_THUMBNAIL_SCALE_APPGRID === 0)
|
||||
this.MAX_THUMBNAIL_SCALE_APPGRID = this.MAX_THUMBNAIL_SCALE;
|
||||
this.MAX_THUMBNAIL_SCALE = this.get('wsThumbnailScale') / 100;
|
||||
if (this.MAX_THUMBNAIL_SCALE === 0) {
|
||||
this.MAX_THUMBNAIL_SCALE = 0.01;
|
||||
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.SEC_MAX_THUMBNAIL_SCALE = this.get('secWsThumbnailScale', true) / 100;
|
||||
|
||||
this.WS_PREVIEW_SCALE = this.get('wsPreviewScale', true) / 100;
|
||||
this.SEC_WS_PREVIEW_SCALE = this.get('secWsPreviewScale', true) / 100;
|
||||
this.SEC_MAX_THUMBNAIL_SCALE = this.get('secWsThumbnailScale') / 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
|
||||
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.WS_PREVIEW_BG_RADIUS = this.get('wsPreviewBgRadius', true);
|
||||
this.SHOW_WS_PREVIEW_BG = this.get('showWsPreviewBg', true);
|
||||
this.SHOW_WS_TMB_BG = this.get('showWsSwitcherBg') && this.SHOW_WS_TMB;
|
||||
this.WS_PREVIEW_BG_RADIUS = this.get('wsPreviewBgRadius');
|
||||
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.CENTER_SEARCH_VIEW = this.get('centerSearch', true);
|
||||
this.APP_GRID_ANIMATION = this.get('appGridAnimation', true);
|
||||
this.SHOW_SEARCH_ENTRY = this.get('showSearchEntry');
|
||||
this.CENTER_SEARCH_VIEW = this.get('centerSearch');
|
||||
this.APP_GRID_ANIMATION = this.get('appGridAnimation');
|
||||
if (this.APP_GRID_ANIMATION === 4)
|
||||
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)
|
||||
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.ALWAYS_SHOW_WIN_TITLES = this.get('alwaysShowWinTitles', true);
|
||||
this.WIN_PREVIEW_ICON_SIZE = [64, 48, 32, 22, 8][this.get('winPreviewIconSize')];
|
||||
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.SHOW_BG_IN_OVERVIEW = this.get('showBgInOverview', true);
|
||||
this.OVERVIEW_BG_BRIGHTNESS = this.get('overviewBgBrightness', true) / 100;
|
||||
this.OVERVIEW_BG_BLUR_SIGMA = this.get('overviewBgBlurSigma', true);
|
||||
this.APP_GRID_BG_BLUR_SIGMA = this.get('appGridBgBlurSigma', true);
|
||||
this.SMOOTH_BLUR_TRANSITIONS = this.get('smoothBlurTransitions', true);
|
||||
this.STARTUP_STATE = this.get('startupState');
|
||||
this.SHOW_BG_IN_OVERVIEW = this.get('showBgInOverview');
|
||||
this.OVERVIEW_BG_BRIGHTNESS = this.get('overviewBgBrightness') / 100;
|
||||
this.SEARCH_BG_BRIGHTNESS = this.get('searchBgBrightness') / 100;
|
||||
this.OVERVIEW_BG_BLUR_SIGMA = this.get('overviewBgBlurSigma');
|
||||
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.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_VIEW_SCALE = this.get('searchViewScale', true) / 100;
|
||||
this.SEARCH_MAX_ROWS = this.get('searchMaxResultsRows', true);
|
||||
this.SEARCH_FUZZY = this.get('searchFuzzy', true);
|
||||
this.SEARCH_ICON_SIZE = this.get('searchIconSize');
|
||||
this.SEARCH_VIEW_SCALE = this.get('searchViewScale') / 100;
|
||||
this.SEARCH_MAX_ROWS = this.get('searchMaxResultsRows');
|
||||
this.SEARCH_FUZZY = this.get('searchFuzzy');
|
||||
|
||||
this.APP_GRID_ALLOW_INCOMPLETE_PAGES = this.get('appGridIncompletePages', true);
|
||||
this.APP_GRID_ICON_SIZE = this.get('appGridIconSize', true);
|
||||
this.APP_GRID_COLUMNS = this.get('appGridColumns', true);
|
||||
this.APP_GRID_ROWS = this.get('appGridRows', true);
|
||||
this.APP_GRID_ALLOW_INCOMPLETE_PAGES = this.get('appGridIncompletePages');
|
||||
this.APP_GRID_ICON_SIZE = this.get('appGridIconSize');
|
||||
this.APP_GRID_COLUMNS = this.get('appGridColumns');
|
||||
this.APP_GRID_ROWS = this.get('appGridRows');
|
||||
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
|
||||
0 - Include All
|
||||
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_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_GRID = this.get('appGridFolderIconGrid', true);
|
||||
this.APP_GRID_FOLDER_COLUMNS = this.get('appGridFolderColumns', true);
|
||||
this.APP_GRID_FOLDER_ROWS = this.get('appGridFolderRows', true);
|
||||
this.APP_GRID_SPACING = this.get('appGridSpacing', true);
|
||||
this.APP_GRID_FOLDER_ICON_SIZE = this.get('appGridFolderIconSize');
|
||||
this.APP_GRID_FOLDER_ICON_GRID = this.get('appGridFolderIconGrid');
|
||||
this.APP_GRID_FOLDER_COLUMNS = this.get('appGridFolderColumns');
|
||||
this.APP_GRID_FOLDER_ROWS = this.get('appGridFolderRows');
|
||||
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_ACTIVE_PREVIEW = this.get('appGridActivePreview', true);
|
||||
this.APP_GRID_FOLDER_CENTER = this.get('appGridFolderCenter', true);
|
||||
this.APP_GRID_PAGE_WIDTH_SCALE = this.get('appGridPageWidthScale', true) / 100;
|
||||
this.APP_GRID_FOLDER_ADAPTIVE = !this.APP_GRID_FOLDER_COLUMNS && !this.APP_GRID_FOLDER_ROWS;
|
||||
this.APP_GRID_ACTIVE_PREVIEW = this.get('appGridActivePreview');
|
||||
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.WINDOW_SEARCH_PROVIDER_ENABLED = this.get('searchWindowsEnable', true);
|
||||
this.RECENT_FILES_SEARCH_PROVIDER_ENABLED = this.get('searchRecentFilesEnable', true);
|
||||
this.APP_GRID_PERFORMANCE = this.get('appGridPerformance');
|
||||
|
||||
this.PANEL_POSITION_TOP = this.get('panelPosition', true) === 0;
|
||||
this.PANEL_MODE = this.get('panelVisibility', true);
|
||||
this.WINDOW_SEARCH_ORDER = this.get('searchWindowsOrder');
|
||||
|
||||
this.PANEL_POSITION_TOP = this.get('panelPosition') === 0;
|
||||
this.PANEL_MODE = this.get('panelVisibility');
|
||||
this.PANEL_DISABLED = this.PANEL_MODE === 2;
|
||||
this.PANEL_OVERVIEW_ONLY = this.PANEL_MODE === 1;
|
||||
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_FOCUS_IMMEDIATELY = this.WINDOW_ATTENTION_MODE === 2;
|
||||
|
||||
this.WS_SW_POPUP_H_POSITION = this.get('wsSwPopupHPosition', true) / 100;
|
||||
this.WS_SW_POPUP_V_POSITION = this.get('wsSwPopupVPosition', true) / 100;
|
||||
this.WS_SW_POPUP_MODE = this.get('wsSwPopupMode', true);
|
||||
this.WS_SW_POPUP_H_POSITION = this.get('wsSwPopupHPosition') / 100;
|
||||
this.WS_SW_POPUP_V_POSITION = this.get('wsSwPopupVPosition') / 100;
|
||||
this.WS_SW_POPUP_MODE = this.get('wsSwPopupMode');
|
||||
|
||||
this.SHOW_FAV_NOTIFICATION = this.get('favoritesNotify', true);
|
||||
this.NOTIFICATION_POSITION = this.get('notificationPosition', true);
|
||||
this.WS_WRAPAROUND = this.get('wsSwitcherWraparound');
|
||||
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.HOT_CORNER_POSITION = this.get('hotCornerPosition', true);
|
||||
this.OSD_POSITION = this.get('osdPosition');
|
||||
|
||||
this.HOT_CORNER_ACTION = this.get('hotCornerAction');
|
||||
this.HOT_CORNER_POSITION = this.get('hotCornerPosition');
|
||||
if (this.HOT_CORNER_POSITION === 6 && this.DASH_VISIBLE)
|
||||
this.HOT_CORNER_EDGE = true;
|
||||
else
|
||||
|
@ -451,13 +510,24 @@ var Options = class Options {
|
|||
else
|
||||
this.HOT_CORNER_POSITION = 0;
|
||||
}
|
||||
this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen', true);
|
||||
this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples', true);
|
||||
this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen');
|
||||
this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples');
|
||||
|
||||
this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow', true);
|
||||
this.WINDOW_ICON_CLICK_SEARCH = this.get('windowIconClickSearch', true);
|
||||
this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow');
|
||||
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() {
|
||||
|
|
|
@ -10,61 +10,90 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { Clutter, GObject } = imports.gi;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const SwipeTracker = imports.ui.swipeTracker;
|
||||
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
let _vwGestureUpdateId;
|
||||
let _originalGestureUpdateId;
|
||||
var SwipeTrackerModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
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;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
}
|
||||
|
||||
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
|
||||
Main.overview._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
|
||||
Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
|
||||
// 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
|
||||
if (!_originalGestureUpdateId) {
|
||||
_originalGestureUpdateId = GObject.signal_handler_find(Main.overview._swipeTracker._touchpadGesture, { signalId: 'update' });
|
||||
Main.overview._swipeTracker._touchpadGesture.block_signal_handler(_originalGestureUpdateId);
|
||||
if (!this._originalGestureUpdateId) {
|
||||
this._originalGestureUpdateId = GObject.signal_handler_find(Main.overview._swipeTracker._touchpadGesture, { signalId: 'update' });
|
||||
Main.overview._swipeTracker._touchpadGesture.block_signal_handler(this._originalGestureUpdateId);
|
||||
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 = {
|
||||
_updateGesture(gesture, time, delta, distance) {
|
||||
|
|
|
@ -10,16 +10,27 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Meta = imports.gi.Meta;
|
||||
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;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
let Me;
|
||||
|
||||
var shellVersion = parseFloat(Config.PACKAGE_VERSION);
|
||||
let _installedExtensions;
|
||||
|
||||
function init(me) {
|
||||
Me = me;
|
||||
}
|
||||
|
||||
function cleanGlobals() {
|
||||
Me = null;
|
||||
_installedExtensions = null;
|
||||
}
|
||||
|
||||
var Overrides = class {
|
||||
constructor() {
|
||||
|
@ -27,8 +38,13 @@ var Overrides = class {
|
|||
}
|
||||
|
||||
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] = {
|
||||
originals: this.overrideProto(prototype, overrideList),
|
||||
originals,
|
||||
prototype,
|
||||
};
|
||||
}
|
||||
|
@ -38,15 +54,15 @@ var Overrides = class {
|
|||
if (!override)
|
||||
return false;
|
||||
|
||||
this.overrideProto(override.prototype, override.originals);
|
||||
this._overrides[name] = undefined;
|
||||
this.overrideProto(override.prototype, override.originals, name);
|
||||
delete this._overrides[name];
|
||||
return true;
|
||||
}
|
||||
|
||||
removeAll() {
|
||||
for (let name in this._overrides) {
|
||||
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);
|
||||
}
|
||||
|
||||
overrideProto(proto, overrides) {
|
||||
overrideProto(proto, overrides, name) {
|
||||
const backup = {};
|
||||
|
||||
const originals = this._overrides[name]?.originals;
|
||||
for (let symbol in overrides) {
|
||||
if (symbol.startsWith('after_')) {
|
||||
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];
|
||||
proto[actualSymbol] = function (...args) {
|
||||
args = Array.prototype.slice.call(args);
|
||||
|
@ -72,11 +92,11 @@ var Overrides = class {
|
|||
} else {
|
||||
backup[symbol] = proto[symbol];
|
||||
if (symbol.startsWith('vfunc')) {
|
||||
if (shellVersion < 42)
|
||||
if (Me.shellVersion < 42)
|
||||
this.hookVfunc(proto, symbol.slice(6), overrides[symbol]);
|
||||
else
|
||||
this.hookVfunc(proto[Gi.gobject_prototype_symbol], symbol.slice(6), overrides[symbol]);
|
||||
} else {
|
||||
} else if (overrides[symbol] !== null) {
|
||||
proto[symbol] = overrides[symbol];
|
||||
}
|
||||
}
|
||||
|
@ -85,87 +105,21 @@ var Overrides = class {
|
|||
}
|
||||
};
|
||||
|
||||
function getOverviewTranslations(opt, dash, tmbBox, searchEntryBin) {
|
||||
// const tmbBox = Main.overview._overview._controls._thumbnailsBox;
|
||||
let searchTranslationY = 0;
|
||||
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() {
|
||||
function openPreferences(metadata) {
|
||||
if (!metadata)
|
||||
metadata = Me.metadata;
|
||||
const windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null);
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
let metaWin, isVW = null;
|
||||
|
||||
for (let win of windows) {
|
||||
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
|
||||
metaWin = win;
|
||||
isVW = true;
|
||||
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
|
||||
metaWin = win;
|
||||
isVW = false;
|
||||
|
@ -182,17 +136,20 @@ function openPreferences() {
|
|||
}
|
||||
|
||||
if (!metaWin || (metaWin && !isVW)) {
|
||||
try {
|
||||
Main.extensionManager.openExtensionPrefs(Me.metadata.uuid, '', {});
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
GLib.idle_add(GLib.PRIORITY_LOW, () => {
|
||||
try {
|
||||
Main.extensionManager.openExtensionPrefs(metadata.uuid, '', {});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function activateSearchProvider(prefix = '') {
|
||||
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} `;
|
||||
const position = prefix.length;
|
||||
searchEntry.set_text(prefix);
|
||||
|
@ -220,9 +177,16 @@ function reorderWorkspace(direction = 0) {
|
|||
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) {
|
||||
// expose windows for static overview modes
|
||||
if (!adjustment.value && !Main.overview._animationInProgress) {
|
||||
if (!adjustment.value/* && !Main.overview._animationInProgress*/) {
|
||||
if (adjustment.value === 0) {
|
||||
adjustment.value = 0;
|
||||
adjustment.ease(1, {
|
||||
|
@ -330,13 +294,48 @@ function isMoreRelevant(stringA, stringB, pattern) {
|
|||
return !aAny && bAny;
|
||||
}
|
||||
|
||||
function getEnabledExtensions(uuid = '') {
|
||||
let extensions = [];
|
||||
Main.extensionManager._extensions.forEach(e => {
|
||||
if (e.state === 1 && e.uuid.includes(uuid))
|
||||
extensions.push(e);
|
||||
});
|
||||
return extensions;
|
||||
function getEnabledExtensions(pattern = '') {
|
||||
let result = [];
|
||||
// extensionManager is unreliable at startup (if not all extensions were loaded)
|
||||
// but gsettings key can contain removed extensions...
|
||||
// therefore we have to look into filesystem, what's really installed
|
||||
if (!_installedExtensions) {
|
||||
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) {
|
||||
|
|
525
extensions/44/vertical-workspaces/lib/winTmb.js
Normal file
525
extensions/44/vertical-workspaces/lib/winTmb.js
Normal 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;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
|
@ -11,47 +11,69 @@
|
|||
'use strict';
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
const _Util = Me.imports.lib.util;
|
||||
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = false;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('winAttentionHandlerModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var WindowAttentionHandlerModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
|
||||
_firstRun = false;
|
||||
if (reset) {
|
||||
reset = true;
|
||||
_updateConnections(reset);
|
||||
opt = null;
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
_updateConnections();
|
||||
}
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
}
|
||||
|
||||
function _updateConnections(reset) {
|
||||
global.display.disconnectObject(Main.windowAttentionHandler);
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('windowAttentionHandlerModule');
|
||||
const conflict = false;
|
||||
|
||||
const handlerFnc = reset
|
||||
? Main.windowAttentionHandler._onWindowDemandsAttention
|
||||
: WindowAttentionHandlerCommon._onWindowDemandsAttention;
|
||||
reset = reset || !this.moduleEnabled || conflict;
|
||||
|
||||
global.display.connectObject(
|
||||
'window-demands-attention', handlerFnc.bind(Main.windowAttentionHandler),
|
||||
'window-marked-urgent', handlerFnc.bind(Main.windowAttentionHandler),
|
||||
Main.windowAttentionHandler);
|
||||
}
|
||||
// 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(' 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 = {
|
||||
_onWindowDemandsAttention(display, window) {
|
||||
|
|
|
@ -10,81 +10,101 @@
|
|||
|
||||
'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 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 _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('windowManagerModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var WindowManagerModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
|
||||
_firstRun = false;
|
||||
this._originalMinimizeSigId = 0;
|
||||
this._minimizeSigId = 0;
|
||||
this._originalUnminimizeSigId = 0;
|
||||
this._unminimizeSigId = 0;
|
||||
}
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
|
||||
_replaceMinimizeFunction(reset);
|
||||
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
cleanGlobals() {
|
||||
Me = 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 --------------------------------------
|
||||
|
||||
let _originalMinimizeSigId;
|
||||
let _minimizeSigId;
|
||||
let _originalUnminimizeSigId;
|
||||
let _unminimizeSigId;
|
||||
|
||||
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));
|
||||
// don't even 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(' 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
|
||||
// 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()) {
|
||||
actor.get_first_child().ease({
|
||||
opacity: 0,
|
||||
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
onStopped: () => this._minimizeWindowDone(shellwm, actor),
|
||||
});
|
||||
} else { */
|
||||
|
@ -140,8 +160,8 @@ const WindowManagerCommon = {
|
|||
scale_y: yScale,
|
||||
x: xDest,
|
||||
y: yDest,
|
||||
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
onStopped: () => this._minimizeWindowDone(shellwm, actor),
|
||||
});
|
||||
// }
|
||||
|
@ -176,8 +196,8 @@ const WindowManagerCommon = {
|
|||
actor.set_scale(1.0, 1.0);
|
||||
actor.ease({
|
||||
opacity: 255,
|
||||
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
onStopped: () => this._unminimizeWindowDone(shellwm, actor),
|
||||
});
|
||||
} else { */
|
||||
|
@ -208,8 +228,8 @@ const WindowManagerCommon = {
|
|||
scale_y: 1,
|
||||
x: xDest,
|
||||
y: yDest,
|
||||
duration: MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
|
||||
onStopped: () => this._unminimizeWindowDone(shellwm, actor),
|
||||
});
|
||||
// }
|
||||
|
|
|
@ -10,103 +10,372 @@
|
|||
|
||||
'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 OverviewControls = imports.ui.overviewControls;
|
||||
const WindowPreview = imports.ui.windowPreview;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
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 Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('windowPreviewModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
const WINDOW_SCALE_TIME = 200;
|
||||
const WINDOW_ACTIVE_SIZE_INC = 5;
|
||||
const WINDOW_OVERLAY_FADE_TIME = 200;
|
||||
const WINDOW_DND_SIZE = 256;
|
||||
const DRAGGING_WINDOW_OPACITY = 100;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
const ControlsState = OverviewControls.ControlsState;
|
||||
|
||||
_firstRun = false;
|
||||
var WindowPreviewModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
opt = null;
|
||||
WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
_overrides = new _Util.Overrides();
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
}
|
||||
|
||||
_overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon);
|
||||
// A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer
|
||||
if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
|
||||
WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
|
||||
}
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('windowPreviewModule');
|
||||
const conflict = false;
|
||||
|
||||
const WindowPreviewCommon = {
|
||||
// injection to _init()
|
||||
after__init() {
|
||||
const ICON_OVERLAP = 0.7;
|
||||
reset = reset || !this.moduleEnabled || conflict;
|
||||
|
||||
if (opt.WIN_PREVIEW_ICON_SIZE < 64) {
|
||||
this.remove_child(this._icon);
|
||||
this._icon.destroy();
|
||||
const tracker = Shell.WindowTracker.get_default();
|
||||
const app = tracker.get_window_app(this.metaWindow);
|
||||
this._icon = app.create_icon_texture(opt.WIN_PREVIEW_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: this.windowContainer,
|
||||
coordinate: Clutter.BindCoordinate.POSITION,
|
||||
}));
|
||||
this._icon.add_constraint(new Clutter.AlignConstraint({
|
||||
source: this.windowContainer,
|
||||
align_axis: Clutter.AlignAxis.X_AXIS,
|
||||
factor: 0.5,
|
||||
}));
|
||||
this._icon.add_constraint(new Clutter.AlignConstraint({
|
||||
source: this.windowContainer,
|
||||
align_axis: Clutter.AlignAxis.Y_AXIS,
|
||||
pivot_point: new Graphene.Point({ x: -1, y: ICON_OVERLAP }),
|
||||
factor: 1,
|
||||
}));
|
||||
this.add_child(this._icon);
|
||||
if (opt.WIN_PREVIEW_ICON_SIZE < 22) {
|
||||
// disable app icon
|
||||
this._icon.hide();
|
||||
}
|
||||
this._iconSize = opt.WIN_PREVIEW_ICON_SIZE;
|
||||
// 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(' WindowPreviewModule - Keeping untouched');
|
||||
}
|
||||
|
||||
_activateModule() {
|
||||
if (!this._overrides)
|
||||
this._overrides = new Me.Util.Overrides();
|
||||
|
||||
this._overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon);
|
||||
// A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer
|
||||
if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
|
||||
WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
|
||||
console.debug(' WindowPreviewModule - Activated');
|
||||
}
|
||||
|
||||
_disableModule() {
|
||||
// If WindowPreview._init was injected by another extension (like Burn My Windows)
|
||||
// which enables/disables before V-Shell
|
||||
// don't restore the original if it's not injected,
|
||||
// because it would restore injected _init and recursion would freeze GS when extensions are enabled again.
|
||||
// This can happen when all extension re-enabled, not only when screen is locked/unlocked
|
||||
// If _init doesn't include "fn.apply(this, args)" when reset === true, some extension already restored the original
|
||||
const skipReset = WindowPreview.WindowPreview.prototype._init.toString().includes('fn.apply(this, args)');
|
||||
if (this._overrides && skipReset) {
|
||||
// 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 iconOverlap = opt.WIN_PREVIEW_ICON_SIZE * ICON_OVERLAP;
|
||||
// we cannot get proper title height before it gets to the stage, so 35 is estimated height + spacing
|
||||
this._title.get_constraints()[1].offset = scaleFactor * (-iconOverlap - 35);
|
||||
this.set_child_above_sibling(this._title, null);
|
||||
this._title = new St.Label({
|
||||
visible: false,
|
||||
style_class: 'window-caption',
|
||||
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 (Main.overview._overview._controls._stateAdjustment.value < 1) {
|
||||
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)
|
||||
return;
|
||||
|
||||
const adjustment = this._workspace._background._stateAdjustment;
|
||||
opt.WORKSPACE_MODE = 1;
|
||||
_Util.exposeWindows(adjustment, false);
|
||||
const view = this._workspace.get_parent();
|
||||
view.exposeWindows(this._workspace.metaWorkspace.index());
|
||||
this.disconnect(this._wsStateConId);
|
||||
});
|
||||
}
|
||||
|
@ -136,53 +405,39 @@ const WindowPreviewCommon = {
|
|||
this._stateAdjustmentSigId = this._workspace.stateAdjustment.connect('notify::value', this._updateIconScale.bind(this));
|
||||
}
|
||||
|
||||
// replace click action with custom one
|
||||
const action = this.get_actions()[0];
|
||||
|
||||
const handlerId = GObject.signal_handler_find(action, { signalId: 'clicked' });
|
||||
if (handlerId)
|
||||
action.disconnect(handlerId);
|
||||
|
||||
action.connect('clicked', act => {
|
||||
const button = act.get_button();
|
||||
if (button === Clutter.BUTTON_PRIMARY) {
|
||||
this._activate();
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (button === Clutter.BUTTON_SECONDARY) {
|
||||
// this action cancels long-press event and the 'long-press-cancel' event is used by the Shell to actually initiate DnD
|
||||
// so the dnd initiation needs to be removed
|
||||
if (this._longPressLater) {
|
||||
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);
|
||||
const metaWin = this.metaWindow;
|
||||
if (opt.DASH_ISOLATE_WS && !metaWin._wsChangedConId) {
|
||||
metaWin._wsChangedConId = metaWin.connect('workspace-changed',
|
||||
() => Main.overview.dash._queueRedisplay());
|
||||
} else if (!opt.DASH_ISOLATE_WS && metaWin._wsChangedConId) {
|
||||
metaWin.disconnect(metaWin._wsChangedConId);
|
||||
}
|
||||
},
|
||||
|
||||
_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() {
|
||||
let { currentState, initialState, finalState } =
|
||||
this._overviewAdjustment.getStateTransitionParams();
|
||||
|
@ -192,7 +447,7 @@ const WindowPreviewCommon = {
|
|||
|
||||
const visible =
|
||||
(initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN) &&
|
||||
!(finalState === ControlsState.APP_GRID && primaryMonitor);
|
||||
!(finalState === ControlsState.APP_GRID && opt.WS_ANIMATION && primaryMonitor);
|
||||
|
||||
let scale = 0;
|
||||
if (visible)
|
||||
|
@ -210,7 +465,6 @@ const WindowPreviewCommon = {
|
|||
else if (primaryMonitor && currentState > ControlsState.WINDOW_PICKER)
|
||||
scale = 0;
|
||||
|
||||
|
||||
// in static workspace mode show icon and title on windows expose
|
||||
if (opt.OVERVIEW_MODE) {
|
||||
if (currentState === 1)
|
||||
|
@ -219,29 +473,32 @@ const WindowPreviewCommon = {
|
|||
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) {
|
||||
this._icon.ease({
|
||||
duration: 50,
|
||||
scale_x: scale,
|
||||
scale_y: scale,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
this._icon.set({
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
});
|
||||
this._title.ease({
|
||||
duration: 100,
|
||||
opacity: 255,
|
||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||
});
|
||||
} else if (this._icon.scale_x !== 0) {
|
||||
this._icon.set({
|
||||
scale_x: 0,
|
||||
scale_y: 0,
|
||||
});
|
||||
} else {
|
||||
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) {
|
||||
|
@ -252,7 +509,7 @@ const WindowPreviewCommon = {
|
|||
return;
|
||||
|
||||
this._overlayShown = true;
|
||||
if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
|
||||
if (opt.WIN_TITLES_POSITION === 2)
|
||||
this._restack();
|
||||
|
||||
// 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)
|
||||
return;
|
||||
|
||||
const toShow = this._windowCanClose()
|
||||
const toShow = this._windowCanClose() && opt.SHOW_CLOSE_BUTTON
|
||||
? [this._closeButton]
|
||||
: [];
|
||||
|
||||
|
@ -301,12 +558,12 @@ const WindowPreviewCommon = {
|
|||
if (!this._overlayShown)
|
||||
return;
|
||||
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();
|
||||
|
||||
// If we're supposed to animate and an animation in our direction
|
||||
|
@ -353,14 +610,11 @@ const WindowPreviewCommon = {
|
|||
this._delegate = null;
|
||||
|
||||
if (this._longPressLater) {
|
||||
if (shellVersion >= 44) {
|
||||
const laters = global.compositor.get_laters();
|
||||
laters.remove(this._longPressLater);
|
||||
delete this._longPressLater;
|
||||
} else {
|
||||
Meta.later_remove(this._longPressLater);
|
||||
delete this._longPressLater;
|
||||
}
|
||||
if (Meta.later_add)
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, this._longPressLater);
|
||||
else
|
||||
global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, this._longPressLater);
|
||||
delete this._longPressLater;
|
||||
}
|
||||
|
||||
if (this._idleHideOverlayId > 0) {
|
||||
|
|
|
@ -9,30 +9,23 @@
|
|||
|
||||
'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 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
|
||||
const _ = Settings._;
|
||||
|
||||
const shellVersion = Settings.shellVersion;
|
||||
|
||||
const ModifierType = imports.gi.Clutter.ModifierType;
|
||||
|
||||
let windowSearchProvider;
|
||||
let _enableTimeoutId = 0;
|
||||
let _;
|
||||
|
||||
// prefix helps to eliminate results from other search providers
|
||||
// so it needs to be something less common
|
||||
// needs to be accessible from vw module
|
||||
var prefix = 'wq//';
|
||||
|
||||
let opt;
|
||||
const PREFIX = 'wq//';
|
||||
|
||||
const Action = {
|
||||
NONE: 0,
|
||||
|
@ -42,66 +35,77 @@ const Action = {
|
|||
MOVE_ALL_TO_WS: 4,
|
||||
};
|
||||
|
||||
function getOverviewSearchResult() {
|
||||
return Main.overview._overview.controls._searchController._searchResults;
|
||||
}
|
||||
var WindowSearchProviderModule = class {
|
||||
// export for other modules
|
||||
static _PREFIX = PREFIX;
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
_ = Me.gettext;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
if (!reset && opt.WINDOW_SEARCH_PROVIDER_ENABLED && !windowSearchProvider) {
|
||||
enable();
|
||||
} else if (reset || !opt.WINDOW_SEARCH_PROVIDER_ENABLED) {
|
||||
disable();
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
// export for other modules
|
||||
|
||||
this._windowSearchProvider = null;
|
||||
this._enableTimeoutId = 0;
|
||||
}
|
||||
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
function enable() {
|
||||
// delay because Fedora had problem to register a new provider soon after Shell restarts
|
||||
_enableTimeoutId = GLib.timeout_add(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
2000,
|
||||
() => {
|
||||
if (!windowSearchProvider) {
|
||||
windowSearchProvider = new WindowSearchProvider(opt);
|
||||
getOverviewSearchResult()._registerProvider(
|
||||
windowSearchProvider
|
||||
);
|
||||
}
|
||||
_enableTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('windowSearchProviderModule');
|
||||
|
||||
reset = reset || !this.moduleEnabled;
|
||||
|
||||
if (reset && !this._firstActivation) {
|
||||
this._disableModule();
|
||||
} else if (!reset) {
|
||||
this._firstActivation = false;
|
||||
this._activateModule();
|
||||
}
|
||||
);
|
||||
}
|
||||
if (reset && this._firstActivation)
|
||||
console.debug(' WindowSearchProviderModule - Keeping untouched');
|
||||
}
|
||||
|
||||
function disable() {
|
||||
if (windowSearchProvider) {
|
||||
getOverviewSearchResult()._unregisterProvider(
|
||||
windowSearchProvider
|
||||
_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._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);
|
||||
_enableTimeoutId = 0;
|
||||
|
||||
_disableModule() {
|
||||
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) {
|
||||
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,
|
||||
};
|
||||
}
|
||||
_getOverviewSearchResult() {
|
||||
return Main.overview._overview.controls._searchController._searchResults;
|
||||
}
|
||||
};
|
||||
|
||||
const closeSelectedRegex = /^\/x!$/;
|
||||
const closeAllResultsRegex = /^\/xa!$/;
|
||||
|
@ -110,15 +114,22 @@ const moveAllToWsRegex = /^\/ma[0-9]+$/;
|
|||
|
||||
const WindowSearchProvider = class WindowSearchProvider {
|
||||
constructor() {
|
||||
this.id = `open-windows@${Me.metadata.uuid}`;
|
||||
this.appInfo = Gio.AppInfo.create_from_commandline('true', _('Open Windows'), null);
|
||||
this.appInfo.get_description = () => _('List of open windows');
|
||||
this.appInfo.get_name = () => _('Open Windows');
|
||||
this.appInfo.get_id = () => this.id;
|
||||
this.appInfo.get_icon = () => Gio.icon_new_for_string('focus-windows-symbolic');
|
||||
this.appInfo.should_show = () => true;
|
||||
this.id = 'open-windows';
|
||||
const appSystem = Shell.AppSystem.get_default();
|
||||
// use arbitrary app to get complete appInfo object
|
||||
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('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.action = 0;
|
||||
|
@ -128,7 +139,7 @@ const WindowSearchProvider = class WindowSearchProvider {
|
|||
// do not modify original terms
|
||||
let termsCopy = [...terms];
|
||||
// search for terms without prefix
|
||||
termsCopy[0] = termsCopy[0].replace(prefix, '');
|
||||
termsCopy[0] = termsCopy[0].replace(PREFIX, '');
|
||||
|
||||
/* if (gOptions.get('searchWindowsCommands')) {
|
||||
this.action = 0;
|
||||
|
@ -167,9 +178,9 @@ const WindowSearchProvider = class WindowSearchProvider {
|
|||
let m;
|
||||
for (let key in candidates) {
|
||||
if (opt.SEARCH_FUZZY)
|
||||
m = _Util.fuzzyMatch(term, candidates[key].name);
|
||||
m = Me.Util.fuzzyMatch(term, candidates[key].name);
|
||||
else
|
||||
m = _Util.strictMatch(term, candidates[key].name);
|
||||
m = Me.Util.strictMatch(term, candidates[key].name);
|
||||
|
||||
if (m !== -1)
|
||||
results.push({ weight: m, id: key });
|
||||
|
@ -178,7 +189,19 @@ const WindowSearchProvider = class WindowSearchProvider {
|
|||
results.sort((a, b) => a.weight > b.weight);
|
||||
const currentWs = global.workspace_manager.get_active_workspace_index();
|
||||
// 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));
|
||||
|
||||
this.resultIds = results.map(item => item.id);
|
||||
|
@ -187,7 +210,7 @@ const WindowSearchProvider = class WindowSearchProvider {
|
|||
|
||||
getResultMetas(resultIds, callback = null) {
|
||||
const metas = resultIds.map(id => this.getResultMeta(id));
|
||||
if (shellVersion >= 43)
|
||||
if (Me.shellVersion >= 43)
|
||||
return new Promise(resolve => resolve(metas));
|
||||
else
|
||||
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*/) {
|
||||
|
||||
}
|
||||
|
||||
activateResult(resultId/* , terms, timeStamp*/) {
|
||||
const isCtrlPressed = _Util.isCtrlPressed();
|
||||
const isShiftPressed = _Util.isShiftPressed();
|
||||
const isCtrlPressed = Me.Util.isCtrlPressed();
|
||||
const isShiftPressed = Me.Util.isShiftPressed();
|
||||
|
||||
this.action = 0;
|
||||
this.targetWs = 0;
|
||||
|
@ -276,15 +316,16 @@ const WindowSearchProvider = class WindowSearchProvider {
|
|||
this.windows = windows = {};
|
||||
global.display.get_tab_list(Meta.TabList.NORMAL, null).filter(w => w.get_workspace() !== null).map(
|
||||
(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()}`];
|
||||
}
|
||||
);
|
||||
|
||||
if (shellVersion >= 43)
|
||||
if (Me.shellVersion >= 43)
|
||||
return new Promise(resolve => resolve(this._getResultSet(terms)));
|
||||
else
|
||||
callback(this._getResultSet(terms));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -293,13 +334,15 @@ const WindowSearchProvider = class WindowSearchProvider {
|
|||
return results;
|
||||
}
|
||||
|
||||
getSubsearchResultSet(previousResults, terms, callback/* , cancellable*/) {
|
||||
// if we return previous results, quick typers get non-actual results
|
||||
callback(this._getResultSet(terms));
|
||||
getSubsearchResultSet(previousResults, terms, callback) {
|
||||
if (Me.shellVersion < 43) {
|
||||
this.getSubsearchResultSet42(terms, callback);
|
||||
return null;
|
||||
}
|
||||
return this.getInitialResultSet(terms);
|
||||
}
|
||||
|
||||
/* createResultObject(resultMeta) {
|
||||
const app = Shell.WindowTracker.get_default().get_window_app(resultMeta.id);
|
||||
return new AppIcon(app);
|
||||
}*/
|
||||
getSubsearchResultSet42(terms, callback) {
|
||||
callback(this._getResultSet(terms));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,51 +10,68 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { St, Graphene } = imports.gi;
|
||||
const Graphene = imports.gi.Graphene;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Util = imports.misc.util;
|
||||
const Workspace = imports.ui.workspace;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
const _Util = Me.imports.lib.util;
|
||||
|
||||
let _overrides;
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('workspaceModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var WorkspaceModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
|
||||
if (reset) {
|
||||
Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
|
||||
_overrides = null;
|
||||
opt = null;
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
_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
|
||||
_overrides.addOverride('WorkspaceLayout', Workspace.WorkspaceLayout.prototype, WorkspaceLayout);
|
||||
}
|
||||
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(' 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)
|
||||
// smaller window cannot be scaled below 0.95 (WINDOW_PREVIEW_MAXIMUM_SCALE)
|
||||
|
|
|
@ -9,81 +9,147 @@
|
|||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
||||
const WorkspaceAnimation = imports.ui.workspaceAnimation;
|
||||
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const _Util = Me.imports.lib.util;
|
||||
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
||||
|
||||
// first reference to constant defined using const in other module returns undefined, the MonitorGroup const will remain empty and unused
|
||||
let MonitorGroupDummy = WorkspaceAnimation.MonitorGroup;
|
||||
MonitorGroupDummy = null;
|
||||
|
||||
let _origBaseDistance;
|
||||
let _wsAnimationSwipeBeginId;
|
||||
let _wsAnimationSwipeUpdateId;
|
||||
let _wsAnimationSwipeEndId;
|
||||
|
||||
let _overrides;
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('workspaceAnimationModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var WorkspaceAnimationModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
// first reference to constant defined using const in other module returns undefined, the MonitorGroup const will remain empty and unused
|
||||
this.dummy = WorkspaceAnimation.MonitorGroup;
|
||||
|
||||
_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)
|
||||
_overrides.removeAll();
|
||||
|
||||
if (reset || !moduleEnabled) {
|
||||
_connectWsAnimationSwipeTracker(true);
|
||||
_overrideMonitorGroupProperty(true);
|
||||
_overrides = null;
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt.STATIC_WS_SWITCHER_BG) {
|
||||
_overrides = new _Util.Overrides();
|
||||
_overrideMonitorGroupProperty();
|
||||
_overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
|
||||
update(reset) {
|
||||
this.moduleEnabled = opt.get('workspaceAnimationModule');
|
||||
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(' 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
|
||||
function _overrideMonitorGroupProperty(reset = false) {
|
||||
if (!_origBaseDistance)
|
||||
_origBaseDistance = Object.getOwnPropertyDescriptor(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance').get;
|
||||
if (opt.STATIC_WS_SWITCHER_BG) {
|
||||
this._overrideMonitorGroupProperty();
|
||||
this._overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
|
||||
}
|
||||
|
||||
let getter;
|
||||
if (reset) {
|
||||
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;
|
||||
},
|
||||
};
|
||||
this._connectWsAnimationSwipeTracker();
|
||||
console.debug(' WorkspaceAnimationModule - Activated');
|
||||
}
|
||||
|
||||
if (getter)
|
||||
Object.defineProperty(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance', getter);
|
||||
}
|
||||
_disableModule() {
|
||||
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 = {
|
||||
// injection to _init()
|
||||
|
@ -119,7 +185,9 @@ const MonitorGroup = {
|
|||
// hide (scale to 0) all non-sticky windows, their clones will be animated
|
||||
global.get_window_actors().forEach(actor => {
|
||||
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.
|
||||
// scaling them to 0 works well
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -13,52 +13,71 @@
|
|||
const Main = imports.ui.main;
|
||||
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
const _Util = Me.imports.lib.util;
|
||||
let _overrides;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
let _firstRun = true;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
const moduleEnabled = opt.get('workspaceSwitcherPopupModule', true);
|
||||
reset = reset || !moduleEnabled;
|
||||
var WorkspaceSwitcherPopupModule = class {
|
||||
constructor(me) {
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
// don't even touch this module if disabled
|
||||
if (_firstRun && reset)
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
_firstRun = false;
|
||||
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
cleanGlobals() {
|
||||
Me = 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');
|
||||
const allowWsPopupInjection = !(enabled.includes('workspace-switcher-manager@G-dH.github.com') || enabled.includes('WsSwitcherPopupManager@G-dH.github.com-dev'));
|
||||
if (allowWsPopupInjection) { // 1-VERTICAL, 0-HORIZONTAL
|
||||
_overrides.addOverride('WorkspaceSwitcherPopup', WorkspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype, WorkspaceSwitcherPopupOverride);
|
||||
if (conflict && !reset)
|
||||
console.warn(`[${Me.metadata.name}] Warning: "WorkspaceSwitcherPopup" module disabled due to potential conflict with another extension`);
|
||||
|
||||
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()
|
||||
after__init() {
|
||||
if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
|
||||
this._list.vertical = true;
|
||||
}
|
||||
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()
|
||||
|
|
|
@ -10,56 +10,90 @@
|
|||
|
||||
'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 Main = imports.ui.main;
|
||||
const Background = imports.ui.background;
|
||||
const OverviewControls = imports.ui.overviewControls;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
|
||||
const ThumbnailState = WorkspaceThumbnail.ThumbnailState;
|
||||
|
||||
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 ControlsState = OverviewControls.ControlsState;
|
||||
|
||||
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) {
|
||||
if (_overrides)
|
||||
_overrides.removeAll();
|
||||
|
||||
|
||||
if (reset) {
|
||||
if (_originalMaxThumbnailScale)
|
||||
WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = _originalMaxThumbnailScale;
|
||||
_overrides = null;
|
||||
opt = null;
|
||||
return;
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
_overrides = new _Util.Overrides();
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
}
|
||||
|
||||
// don't limit max thumbnail scale for other clients than overview, for example AATWS.
|
||||
WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = 1;
|
||||
update(reset) {
|
||||
this.moduleEnabled = true;
|
||||
const conflict = false;
|
||||
|
||||
_overrides.addOverride('WorkspaceThumbnail', WorkspaceThumbnail.WorkspaceThumbnail.prototype, WorkspaceThumbnailCommon);
|
||||
_overrides.addOverride('ThumbnailsBoxCommon', WorkspaceThumbnail.ThumbnailsBox.prototype, ThumbnailsBoxCommon);
|
||||
reset = reset || !this.moduleEnabled || conflict;
|
||||
|
||||
// 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;
|
||||
}
|
||||
// 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(' 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 = {
|
||||
// injection to _init()
|
||||
|
@ -70,6 +104,8 @@ const WorkspaceThumbnailCommon = {
|
|||
// unless border is removed
|
||||
if (opt.SHOW_WS_TMB_BG)
|
||||
this.add_style_class_name('ws-tmb-labeled');
|
||||
else
|
||||
this.add_style_class_name('ws-tmb-transparent');
|
||||
|
||||
// add workspace thumbnails labels if enabled
|
||||
if (opt.SHOW_WST_LABELS) { // 0 - disable
|
||||
|
@ -77,7 +113,7 @@ const WorkspaceThumbnailCommon = {
|
|||
const wsIndex = this.metaWorkspace.index();
|
||||
let label = `${wsIndex + 1}`;
|
||||
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');
|
||||
if (wsLabels.length > wsIndex && wsLabels[wsIndex])
|
||||
label += `: ${wsLabels[wsIndex]}`;
|
||||
|
@ -129,7 +165,9 @@ const WorkspaceThumbnailCommon = {
|
|||
}
|
||||
});
|
||||
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, () => {
|
||||
const newLabel = getLabel();
|
||||
this._wsLabel.text = newLabel;
|
||||
|
@ -168,7 +206,7 @@ const WorkspaceThumbnailCommon = {
|
|||
closeButton.opacity = 255;
|
||||
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
|
||||
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');
|
||||
}
|
||||
});
|
||||
|
@ -220,12 +258,6 @@ const WorkspaceThumbnailCommon = {
|
|||
|
||||
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
|
||||
// there is a grey bg under the wallpaper
|
||||
this._bgManager.backgroundActor.opacity = 220;
|
||||
|
@ -256,7 +288,7 @@ const WorkspaceThumbnailCommon = {
|
|||
this._lastCloseClickTime = Date.now();
|
||||
return;
|
||||
}
|
||||
} else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !_Util.isCtrlPressed()) {
|
||||
} else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !Me.Util.isCtrlPressed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -335,7 +367,7 @@ const WorkspaceThumbnailCommon = {
|
|||
if (!source.app && source.shellWorkspaceLaunch)
|
||||
return DND.DragMotionResult.COPY_DROP;
|
||||
|
||||
if (source instanceof imports.ui.appDisplay.FolderIcon)
|
||||
if (source instanceof AppDisplay.FolderIcon)
|
||||
return DND.DragMotionResult.COPY_DROP;
|
||||
|
||||
|
||||
|
@ -369,8 +401,8 @@ const WorkspaceThumbnailCommon = {
|
|||
timestamp: time,
|
||||
});
|
||||
return true;
|
||||
} else if (source instanceof imports.ui.appDisplay.FolderIcon) {
|
||||
if (shellVersion >= 44) {
|
||||
} else if (source instanceof AppDisplay.FolderIcon) {
|
||||
if (Me.shellVersion >= 44) {
|
||||
for (let app of source.view._apps) {
|
||||
// const app = Shell.AppSystem.get_default().lookup_app(id);
|
||||
app.open_new_window(this.metaWorkspace.index());
|
||||
|
@ -419,7 +451,7 @@ const ThumbnailsBoxCommon = {
|
|||
if (!source.metaWindow &&
|
||||
(!source.app || !source.app.can_open_new_window()) &&
|
||||
(source.app || !source.shellWorkspaceLaunch) &&
|
||||
!(source instanceof imports.ui.appDisplay.FolderIcon))
|
||||
!(source instanceof AppDisplay.FolderIcon))
|
||||
return false;
|
||||
|
||||
|
||||
|
@ -448,8 +480,8 @@ const ThumbnailsBoxCommon = {
|
|||
workspace: newWorkspaceIndex,
|
||||
timestamp: time,
|
||||
});
|
||||
} else if (source instanceof imports.ui.appDisplay.FolderIcon) {
|
||||
if (shellVersion >= 44) {
|
||||
} else if (source instanceof AppDisplay.FolderIcon) {
|
||||
if (Me.shellVersion >= 44) {
|
||||
for (let app of source.view._apps) {
|
||||
// const app = Shell.AppSystem.get_default().lookup_app(id);
|
||||
app.open_new_window(newWorkspaceIndex);
|
||||
|
@ -495,7 +527,7 @@ const ThumbnailsBoxCommon = {
|
|||
if (!source.metaWindow &&
|
||||
(!source.app || !source.app.can_open_new_window()) &&
|
||||
(source.app || !source.shellWorkspaceLaunch) &&
|
||||
source !== Main.xdndHandler && !(source instanceof imports.ui.appDisplay.FolderIcon))
|
||||
source !== Main.xdndHandler && !(source instanceof AppDisplay.FolderIcon))
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
|
||||
const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
|
||||
|
@ -551,18 +583,18 @@ const ThumbnailsBoxCommon = {
|
|||
return ThumbnailsBoxHorizontal._withinWorkspace.bind(this)(...args);
|
||||
},
|
||||
|
||||
get_preferred_custom_width(...args) {
|
||||
vfunc_get_preferred_width(...args) {
|
||||
if (this._boxOrientation)
|
||||
return ThumbnailsBoxVertical.get_preferred_custom_width.bind(this)(...args);
|
||||
return ThumbnailsBoxVertical.vfunc_get_preferred_width.bind(this)(...args);
|
||||
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)
|
||||
return ThumbnailsBoxVertical.get_preferred_custom_height.bind(this)(...args);
|
||||
return ThumbnailsBoxVertical.vfunc_get_preferred_height.bind(this)(...args);
|
||||
else
|
||||
return ThumbnailsBoxHorizontal.get_preferred_custom_height.bind(this)(...args);
|
||||
return ThumbnailsBoxHorizontal.vfunc_get_preferred_height.bind(this)(...args);
|
||||
},
|
||||
|
||||
vfunc_allocate(...args) {
|
||||
|
@ -632,14 +664,9 @@ const ThumbnailsBoxVertical = {
|
|||
return y > workspaceY1 && y <= workspaceY2;
|
||||
},
|
||||
|
||||
// vfunc_get_preferred_width: function(forHeight) {
|
||||
// override of this vfunc doesn't work for some reason (tested on Ubuntu and Fedora), it's not reachable
|
||||
get_preferred_custom_width(forHeight) {
|
||||
if (!this.visible)
|
||||
return [0, 0];
|
||||
|
||||
if (forHeight === -1)
|
||||
return this.get_preferred_custom_height(forHeight);
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
if (forHeight < 10)
|
||||
return [this._porthole.width, this._porthole.width];
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
|
@ -652,19 +679,14 @@ const ThumbnailsBoxVertical = {
|
|||
const avail = forHeight - totalSpacing;
|
||||
|
||||
let scale = (avail / nWorkspaces) / this._porthole.height;
|
||||
// scale = Math.min(scale, opt.MAX_THUMBNAIL_SCALE);
|
||||
|
||||
const width = Math.round(this._porthole.width * scale);
|
||||
return themeNode.adjust_preferred_height(width, width);
|
||||
},
|
||||
|
||||
get_preferred_custom_height(_forWidth) {
|
||||
if (!this.visible)
|
||||
return [0, 0];
|
||||
|
||||
// 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.
|
||||
vfunc_get_preferred_height(forWidth) {
|
||||
if (forWidth < 10)
|
||||
return [0, this._porthole.height];
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
let spacing = themeNode.get_length('spacing');
|
||||
|
@ -674,15 +696,14 @@ const ThumbnailsBoxVertical = {
|
|||
let totalSpacing = (nWorkspaces - 3) * spacing;
|
||||
|
||||
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 progress = 1 - thumbnail.collapse_fraction;
|
||||
const height = tmbHeight * progress;
|
||||
return accumulator + height;
|
||||
}, 0);
|
||||
|
||||
return themeNode.adjust_preferred_width(totalSpacing, naturalheight);
|
||||
return themeNode.adjust_preferred_width(totalSpacing, Math.round(naturalheight));
|
||||
},
|
||||
|
||||
// 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.get_position());
|
||||
|
||||
if (shellVersion >= 44) {
|
||||
const laters = global.compositor.get_laters();
|
||||
laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.hide();
|
||||
});
|
||||
} else {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.hide();
|
||||
});
|
||||
}
|
||||
const laterFunc = () => this._dropPlaceholder.hide();
|
||||
if (Meta.later_add)
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
else
|
||||
global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
}
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
@ -796,16 +812,11 @@ const ThumbnailsBoxVertical = {
|
|||
|
||||
this._dropPlaceholder.allocate(childBox);
|
||||
|
||||
if (shellVersion >= 44) {
|
||||
const laters = global.compositor.get_laters();
|
||||
laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.show();
|
||||
});
|
||||
} else {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.show();
|
||||
});
|
||||
}
|
||||
const laterFunc = () => this._dropPlaceholder.show();
|
||||
if (Meta.later_add)
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
else
|
||||
global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
y += placeholderHeight + spacing;
|
||||
}
|
||||
|
||||
|
@ -925,7 +936,10 @@ const ThumbnailsBoxHorizontal = {
|
|||
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();
|
||||
|
||||
forWidth = themeNode.adjust_for_width(forWidth);
|
||||
|
@ -937,18 +951,15 @@ const ThumbnailsBoxHorizontal = {
|
|||
const avail = forWidth - totalSpacing;
|
||||
|
||||
let scale = (avail / nWorkspaces) / this._porthole.width;
|
||||
// scale = Math.min(scale, opt.MAX_THUMBNAIL_SCALE);
|
||||
|
||||
const height = Math.round(this._porthole.height * scale);
|
||||
|
||||
return themeNode.adjust_preferred_height(height, height);
|
||||
},
|
||||
|
||||
get_preferred_custom_width(_forHeight) {
|
||||
// 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.
|
||||
if (!this.visible)
|
||||
return [0, 0];
|
||||
vfunc_get_preferred_width(forHeight) {
|
||||
if (forHeight < 10)
|
||||
return [0, this._porthole.width];
|
||||
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
|
@ -959,13 +970,14 @@ const ThumbnailsBoxHorizontal = {
|
|||
|
||||
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 progress = 1 - thumbnail.collapse_fraction;
|
||||
const width = tmbWidth * progress;
|
||||
return accumulator + width;
|
||||
}, 0);
|
||||
|
||||
return themeNode.adjust_preferred_width(totalSpacing, naturalWidth);
|
||||
},
|
||||
|
||||
|
@ -1041,16 +1053,11 @@ const ThumbnailsBoxHorizontal = {
|
|||
this._dropPlaceholder.allocate_preferred_size(
|
||||
...this._dropPlaceholder.get_position());
|
||||
|
||||
if (shellVersion >= 44) {
|
||||
const laters = global.compositor.get_laters();
|
||||
laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.hide();
|
||||
});
|
||||
} else {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.hide();
|
||||
});
|
||||
}
|
||||
const laterFunc = () => this._dropPlaceholder.hide();
|
||||
if (Meta.later_add)
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
else
|
||||
global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
}
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
@ -1078,16 +1085,11 @@ const ThumbnailsBoxHorizontal = {
|
|||
|
||||
this._dropPlaceholder.allocate(childBox);
|
||||
|
||||
if (shellVersion >= 44) {
|
||||
const laters = global.compositor.get_laters();
|
||||
laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.show();
|
||||
});
|
||||
} else {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
||||
this._dropPlaceholder.show();
|
||||
});
|
||||
}
|
||||
const laterFunc = () => this._dropPlaceholder.show();
|
||||
if (Meta.later_add)
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
else
|
||||
global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
|
||||
x += placeholderWidth + spacing;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,62 +10,92 @@
|
|||
|
||||
'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 Util = imports.misc.util;
|
||||
const OverviewControls = imports.ui.overviewControls;
|
||||
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 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;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
let Me;
|
||||
let opt;
|
||||
|
||||
const ControlsState = OverviewControls.ControlsState;
|
||||
const FitMode = WorkspacesView.FitMode;
|
||||
|
||||
function update(reset = false) {
|
||||
opt = Me.imports.lib.settings.opt;
|
||||
opt.DESKTOP_CUBE_ENABLED = Main.extensionManager._enabledExtensions.includes('desktop-cube@schneegans.github.com');
|
||||
const cubeSupported = opt.DESKTOP_CUBE_ENABLED && !opt.ORIENTATION && !opt.OVERVIEW_MODE;
|
||||
var WorkspacesViewModule = class {
|
||||
constructor(me) {
|
||||
// first reference to constant defined using const in other module returns undefined, the SecondaryMonitorDisplay const will remain empty and unused
|
||||
this.dummy = WorkspacesView.SecondaryMonitorDisplay;
|
||||
|
||||
// if desktop cube extension is enabled while V-Shell is loaded, removeAll() would override its code
|
||||
if (_overrides && !cubeSupported) {
|
||||
_overrides.removeAll();
|
||||
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1);
|
||||
Me = me;
|
||||
opt = Me.opt;
|
||||
|
||||
this._firstActivation = true;
|
||||
this.moduleEnabled = false;
|
||||
this._overrides = null;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
_overrides = null;
|
||||
cleanGlobals() {
|
||||
Me = null;
|
||||
opt = null;
|
||||
return;
|
||||
}
|
||||
|
||||
update(reset) {
|
||||
this.moduleEnabled = true;
|
||||
const conflict = false;
|
||||
|
||||
_overrides = new _Util.Overrides();
|
||||
reset = reset || !this.moduleEnabled || conflict;
|
||||
|
||||
if (!cubeSupported)
|
||||
_overrides.addOverride('WorkspacesView', WorkspacesView.WorkspacesView.prototype, WorkspacesViewCommon);
|
||||
|
||||
_overrides.addOverride('WorkspacesDisplay', WorkspacesView.WorkspacesDisplay.prototype, WorkspacesDisplay);
|
||||
_overrides.addOverride('ExtraWorkspaceView', WorkspacesView.ExtraWorkspaceView.prototype, ExtraWorkspaceView);
|
||||
|
||||
if (opt.ORIENTATION) {
|
||||
// switch internal workspace orientation in GS
|
||||
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, -1, 1);
|
||||
_overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayVertical);
|
||||
} else {
|
||||
_overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayHorizontal);
|
||||
// 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(' WorkspacesViewModule - Keeping untouched');
|
||||
}
|
||||
}
|
||||
|
||||
_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 = {
|
||||
_getFirstFitSingleWorkspaceBox(box, spacing, vertical) {
|
||||
|
@ -91,7 +121,6 @@ const WorkspacesViewCommon = {
|
|||
}
|
||||
|
||||
const fitSingleBox = new Clutter.ActorBox({ x1, y1 });
|
||||
|
||||
fitSingleBox.set_size(workspaceWidth, workspaceHeight);
|
||||
|
||||
return fitSingleBox;
|
||||
|
@ -143,21 +172,7 @@ const WorkspacesViewCommon = {
|
|||
},
|
||||
|
||||
_updateVisibility() {
|
||||
// replaced in _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;
|
||||
}*/
|
||||
// visibility handles _updateWorkspacesState()
|
||||
},
|
||||
|
||||
// disable scaling and hide inactive workspaces
|
||||
|
@ -175,27 +190,21 @@ const WorkspacesViewCommon = {
|
|||
|
||||
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 secondaryMonitor = this._monitorIndex !== global.display.get_primary_monitor();
|
||||
const blockSecondaryAppGrid = opt.OVERVIEW_MODE && currentState > 1;
|
||||
|
||||
// Hide inactive workspaces
|
||||
this._workspaces.forEach((w, index) => {
|
||||
if (!(blockSecondaryAppGrid && secondaryMonitor))
|
||||
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 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
|
||||
// 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,
|
||||
// adjacent workspaces are hidden and we need them to show up
|
||||
// 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) {
|
||||
w.scale_x = scaleX;
|
||||
w.scale_y = scaleY;
|
||||
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({
|
||||
duration: 100,
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
duration: 300,
|
||||
translation_x: 0,
|
||||
translation_y: 0,
|
||||
opacity: 255,
|
||||
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
|
||||
|
@ -238,9 +253,40 @@ const WorkspacesViewCommon = {
|
|||
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 = {
|
||||
_getThumbnailParamsForState(state) {
|
||||
|
||||
|
@ -270,24 +316,6 @@ const SecondaryMonitorDisplayVertical = {
|
|||
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) {
|
||||
// const { ControlsState } = OverviewControls;
|
||||
const workspaceBox = box.copy();
|
||||
|
@ -303,7 +331,7 @@ const SecondaryMonitorDisplayVertical = {
|
|||
break;
|
||||
|
||||
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)
|
||||
yShift = Main.panel.height;
|
||||
else
|
||||
|
@ -341,26 +369,40 @@ const SecondaryMonitorDisplayVertical = {
|
|||
const spacing = themeNode.get_length('spacing') * expandFraction;
|
||||
const padding = Math.round(0.1 * height);
|
||||
|
||||
let thumbnailsWidth = this._getThumbnailsWidth(contentBox, spacing);
|
||||
let [, thumbnailsHeight] = this._thumbnails.get_preferred_custom_height(thumbnailsWidth);
|
||||
thumbnailsHeight = Math.min(thumbnailsHeight, height - 2 * spacing);
|
||||
|
||||
let thumbnailsWidth = 0;
|
||||
let thumbnailsHeight = 0;
|
||||
this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
|
||||
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;
|
||||
if (opt.SEC_WS_TMB_LEFT) { // left
|
||||
wsTmbX = Math.round(spacing / 4);
|
||||
wsTmbX = spacing / 2;
|
||||
this._thumbnails._positionLeft = true;
|
||||
} else {
|
||||
wsTmbX = Math.round(width - spacing / 4 - thumbnailsWidth);
|
||||
wsTmbX = width - spacing / 2 - thumbnailsWidth;
|
||||
this._thumbnails._positionLeft = false;
|
||||
}
|
||||
|
||||
const childBox = new Clutter.ActorBox();
|
||||
const availSpace = height - thumbnailsHeight - 2 * spacing;
|
||||
const availSpace = height - thumbnailsHeight;
|
||||
|
||||
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_size(thumbnailsWidth, thumbnailsHeight);
|
||||
|
@ -390,22 +432,14 @@ const SecondaryMonitorDisplayVertical = {
|
|||
if (opt.OVERVIEW_MODE2)
|
||||
this.set_child_above_sibling(this._thumbnails, null);
|
||||
|
||||
|
||||
const visible = !opt.SEC_WS_TMB_HIDDEN;
|
||||
|
||||
if (this._thumbnails.visible === visible)
|
||||
return;
|
||||
|
||||
this._thumbnails.show();
|
||||
this._thumbnails.visible = visible;
|
||||
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() {
|
||||
|
@ -417,7 +451,6 @@ const SecondaryMonitorDisplayVertical = {
|
|||
if (!this._thumbnails._thumbnails.length)
|
||||
this._thumbnails._createThumbnails();
|
||||
|
||||
|
||||
const { initialState, finalState, progress } =
|
||||
this._overviewAdjustment.getStateTransitionParams();
|
||||
|
||||
|
@ -474,7 +507,6 @@ const SecondaryMonitorDisplayVertical = {
|
|||
},
|
||||
};
|
||||
|
||||
// SecondaryMonitorDisplay Horizontal
|
||||
const SecondaryMonitorDisplayHorizontal = {
|
||||
_getThumbnailParamsForState(state) {
|
||||
// const { ControlsState } = OverviewControls;
|
||||
|
@ -520,7 +552,7 @@ const SecondaryMonitorDisplayHorizontal = {
|
|||
break;
|
||||
|
||||
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)
|
||||
yShift = Main.panel.height;
|
||||
else
|
||||
|
@ -571,24 +603,36 @@ const SecondaryMonitorDisplayHorizontal = {
|
|||
const spacing = themeNode.get_length('spacing') * expandFraction;
|
||||
const padding = Math.round(0.1 * height);
|
||||
|
||||
let thumbnailsHeight = this._getThumbnailsHeight(contentBox);
|
||||
let [, thumbnailsWidth] = this._thumbnails.get_preferred_custom_width(thumbnailsHeight);
|
||||
thumbnailsWidth = Math.min(thumbnailsWidth, width - 2 * spacing);
|
||||
|
||||
let thumbnailsWidth = 0;
|
||||
let thumbnailsHeight = 0;
|
||||
this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
|
||||
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;
|
||||
if (opt.SEC_WS_TMB_TOP)
|
||||
wsTmbY = Math.round(spacing / 4);
|
||||
wsTmbY = spacing / 2 + reservedHeight;
|
||||
else
|
||||
wsTmbY = Math.round(height - spacing / 4 - thumbnailsHeight);
|
||||
|
||||
wsTmbY = height - spacing / 2 - thumbnailsHeight;
|
||||
|
||||
const childBox = new Clutter.ActorBox();
|
||||
const availSpace = width - thumbnailsWidth - 2 * spacing;
|
||||
const availSpace = width - thumbnailsWidth;
|
||||
|
||||
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_size(thumbnailsWidth, thumbnailsHeight);
|
||||
|
@ -625,7 +669,6 @@ const SecondaryMonitorDisplayHorizontal = {
|
|||
if (!this._thumbnails._thumbnails.length)
|
||||
this._thumbnails._createThumbnails();
|
||||
|
||||
|
||||
const { initialState, finalState, progress } =
|
||||
this._overviewAdjustment.getStateTransitionParams();
|
||||
|
||||
|
@ -682,7 +725,7 @@ const SecondaryMonitorDisplayHorizontal = {
|
|||
},
|
||||
};
|
||||
|
||||
const ExtraWorkspaceView = {
|
||||
const ExtraWorkspaceViewCommon = {
|
||||
_updateWorkspaceMode() {
|
||||
const overviewState = this._overviewAdjustment.value;
|
||||
|
||||
|
@ -701,9 +744,23 @@ const ExtraWorkspaceView = {
|
|||
if (!opt.SHOW_WS_PREVIEW_BG && this._workspace._background.opacity)
|
||||
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() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].destroy();
|
||||
|
@ -761,8 +818,8 @@ const WorkspacesDisplay = {
|
|||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
if (_Util.isShiftPressed()) {
|
||||
let direction = _Util.getScrollDirection(event);
|
||||
if (Me.Util.isShiftPressed()) {
|
||||
let direction = Me.Util.getScrollDirection(event);
|
||||
if (direction === null || (Date.now() - this._lastScrollTime) < 150)
|
||||
return Clutter.EVENT_STOP;
|
||||
this._lastScrollTime = Date.now();
|
||||
|
@ -775,11 +832,11 @@ const WorkspacesDisplay = {
|
|||
else
|
||||
direction = 0;
|
||||
|
||||
|
||||
if (direction) {
|
||||
_Util.reorderWorkspace(direction);
|
||||
Me.Util.reorderWorkspace(direction);
|
||||
// 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;
|
||||
});
|
||||
return Clutter.EVENT_STOP;
|
||||
|
@ -806,7 +863,7 @@ const WorkspacesDisplay = {
|
|||
switch (symbol) {
|
||||
case Clutter.KEY_Return:
|
||||
case Clutter.KEY_KP_Enter:
|
||||
if (_Util.isCtrlPressed()) {
|
||||
if (Me.Util.isCtrlPressed()) {
|
||||
Main.ctrlAltTabManager._items.forEach(i => {
|
||||
if (i.sortGroup === 1 && i.name === 'Dash')
|
||||
Main.ctrlAltTabManager.focusGroup(i);
|
||||
|
@ -836,17 +893,17 @@ const WorkspacesDisplay = {
|
|||
which = workspaceManager.n_workspaces - 1;
|
||||
break;
|
||||
case Clutter.KEY_space:
|
||||
if (_Util.isCtrlPressed() && _Util.isShiftPressed()) {
|
||||
_Util.openPreferences();
|
||||
} else if (_Util.isAltPressed()) {
|
||||
if (Me.Util.isCtrlPressed() && Me.Util.isShiftPressed()) {
|
||||
Me.Util.activateSearchProvider(Me.ESP_PREFIX);
|
||||
} else if (Me.Util.isAltPressed()) {
|
||||
Main.ctrlAltTabManager._items.forEach(i => {
|
||||
if (i.sortGroup === 1 && i.name === 'Dash')
|
||||
Main.ctrlAltTabManager.focusGroup(i);
|
||||
});
|
||||
} else if (opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED && _Util.isCtrlPressed()) {
|
||||
_Util.activateSearchProvider(SEARCH_RECENT_FILES_PREFIX);
|
||||
} else if (opt.WINDOW_SEARCH_PROVIDER_ENABLED) {
|
||||
_Util.activateSearchProvider(SEARCH_WINDOWS_PREFIX);
|
||||
} else if (opt.get('recentFilesSearchProviderModule') && Me.Util.isCtrlPressed()) {
|
||||
Me.Util.activateSearchProvider(Me.RFSP_PREFIX);
|
||||
} else if (opt.get('windowSearchProviderModule')) {
|
||||
Me.Util.activateSearchProvider(Me.WSP_PREFIX);
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
|
@ -867,16 +924,18 @@ const WorkspacesDisplay = {
|
|||
});
|
||||
} else if (opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE && state === 1) {
|
||||
// expose windows for OVERVIEW_MODE 1
|
||||
const adjustment = this._workspacesViews[0]._workspaces[global.workspace_manager.get_active_workspace().index()]._background._stateAdjustment;
|
||||
opt.WORKSPACE_MODE = 1;
|
||||
_Util.exposeWindows(adjustment, true);
|
||||
const wsIndex = global.workspace_manager.get_active_workspace().index();
|
||||
// after expose animation activate keyboard for window selection
|
||||
const callback = Me.Util.activateKeyboardForWorkspaceView;
|
||||
this._workspacesViews.forEach(
|
||||
view => {
|
||||
view.exposeWindows(wsIndex, callback);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (state === 2)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
Main.ctrlAltTabManager._items.forEach(i => {
|
||||
if (i.sortGroup === 1 && i.name === 'Windows')
|
||||
Main.ctrlAltTabManager.focusGroup(i);
|
||||
});
|
||||
Me.Util.activateKeyboardForWorkspaceView();
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
|
@ -895,14 +954,14 @@ const WorkspacesDisplay = {
|
|||
// Otherwise it is a workspace index
|
||||
ws = workspaceManager.get_workspace_by_index(which);
|
||||
|
||||
if (_Util.isShiftPressed()) {
|
||||
if (Me.Util.isShiftPressed()) {
|
||||
let direction;
|
||||
if (which === Meta.MotionDirection.UP || which === Meta.MotionDirection.LEFT)
|
||||
direction = -1;
|
||||
else if (which === Meta.MotionDirection.DOWN || which === Meta.MotionDirection.RIGHT)
|
||||
direction = 1;
|
||||
if (direction)
|
||||
_Util.reorderWorkspace(direction);
|
||||
Me.Util.reorderWorkspace(direction);
|
||||
// make all workspaces on primary monitor visible for case the new position is hidden
|
||||
Main.overview._overview._controls._workspacesDisplay._workspacesViews[0]._workspaces.forEach(w => {
|
||||
w.visible = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue