284 lines
10 KiB
JavaScript
Executable File
284 lines
10 KiB
JavaScript
Executable File
import Gio from 'gi://Gio';
|
|
import GLib from 'gi://GLib';
|
|
import GObject from 'gi://GObject';
|
|
import Shell from 'gi://Shell';
|
|
import St from 'gi://St';
|
|
|
|
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
|
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
|
|
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
|
|
import * as Util from 'resource:///org/gnome/shell/misc/util.js';
|
|
|
|
import * as Constants from './constants.js';
|
|
import * as Selection from './selection.js';
|
|
|
|
import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
|
|
|
|
const MenuItem = GObject.registerClass(
|
|
class LogoMenuMenuItem extends PopupMenu.PopupMenuItem {
|
|
_init(name, activateFunction) {
|
|
super._init(name);
|
|
this.connect('activate', () => activateFunction());
|
|
}
|
|
});
|
|
|
|
const MenuButton = GObject.registerClass(
|
|
class LogoMenuMenuButton extends PanelMenu.Button {
|
|
_init(extension) {
|
|
super._init(0.5, 'LogoMenu');
|
|
this._extension = extension;
|
|
this._settings = extension.getSettings();
|
|
|
|
// Icon
|
|
this.icon = new St.Icon({
|
|
style_class: 'menu-button',
|
|
});
|
|
|
|
this._settings.connectObject('changed::hide-icon-shadow', () => this.hideIconShadow(), this);
|
|
this._settings.connectObject('changed::menu-button-icon-image', () => this.setIconImage(), this);
|
|
this._settings.connectObject('changed::symbolic-icon', () => this.setIconImage(), this);
|
|
this._settings.connectObject('changed::use-custom-icon', () => this.setIconImage(), this);
|
|
this._settings.connectObject('changed::custom-icon-path', () => this.setIconImage(), this);
|
|
this._settings.connectObject('changed::menu-button-icon-size', () => this.setIconSize(), this);
|
|
|
|
this.hideIconShadow();
|
|
this.setIconImage();
|
|
this.setIconSize();
|
|
this.add_child(this.icon);
|
|
|
|
// Menu
|
|
this._settings.connectObject('changed::hide-softwarecentre', () => this._displayMenuItems(), this);
|
|
this._settings.connectObject('changed::show-power-options', () => this._displayMenuItems(), this);
|
|
this._settings.connectObject('changed::hide-forcequit', () => this._displayMenuItems(), this);
|
|
this._settings.connectObject('changed::show-lockscreen', () => this._displayMenuItems(), this);
|
|
this._settings.connectObject('changed::show-activities-button', () => this._displayMenuItems(), this);
|
|
this._displayMenuItems();
|
|
|
|
// bind middle click option to toggle overview
|
|
this.connect('button-press-event', this._buttonPressEvent.bind(this));
|
|
}
|
|
|
|
_addItem(item) {
|
|
this.menu.addMenuItem(item);
|
|
}
|
|
|
|
_displayMenuItems() {
|
|
const showPowerOptions = this._settings.get_boolean('show-power-options');
|
|
const showForceQuit = !this._settings.get_boolean('hide-forcequit');
|
|
const showLockScreen = this._settings.get_boolean('show-lockscreen');
|
|
const showSoftwareCenter = !this._settings.get_boolean('hide-softwarecentre');
|
|
const showActivitiesButton = this._settings.get_boolean('show-activities-button');
|
|
|
|
this.menu.removeAll();
|
|
|
|
this._addItem(new MenuItem(_('About My System'), () => this._aboutThisDistro()));
|
|
// this._addItem(new MenuItem(_('System Settings...'), () => this._systemPreferences()));
|
|
this._addItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
|
|
if (!showActivitiesButton)
|
|
this._addItem(new MenuItem(_('Activities'), () => this._overviewToggle()));
|
|
|
|
this._addItem(new MenuItem(_('App Grid'), () => this._showAppGrid()));
|
|
this._addItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
|
|
if (showSoftwareCenter)
|
|
this._addItem(new MenuItem(_('Software Center...'), () => this._openSoftwareCenter()));
|
|
|
|
this._addItem(new MenuItem(_('System Monitor'), () => this._openSystemMonitor()));
|
|
this._addItem(new MenuItem(_('Terminal'), () => this._openTerminal()));
|
|
this._addItem(new MenuItem(_('Extensions'), () => this._openExtensionsApp()));
|
|
|
|
if (showForceQuit) {
|
|
this._addItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this._addItem(new MenuItem(_('Force Quit App'), () => this._forceQuit()));
|
|
}
|
|
|
|
if (showPowerOptions) {
|
|
this._addItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this._addItem(new MenuItem(_('Sleep'), () => this._sleep()));
|
|
this._addItem(new MenuItem(_('Restart...'), () => this._restart()));
|
|
this._addItem(new MenuItem(_('Shut Down...'), () => this._shutdown()));
|
|
this._addItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
|
|
if (showLockScreen)
|
|
this._addItem(new MenuItem(_('Lock Screen'), () => this._lockScreen()));
|
|
|
|
this._addItem(new MenuItem(_('Log Out...'), () => this._logOut()));
|
|
} else if (!showPowerOptions && showLockScreen) {
|
|
this._addItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
this._addItem(new MenuItem(_('Lock Screen'), () => this._lockScreen()));
|
|
}
|
|
}
|
|
|
|
_buttonPressEvent(actor, event) {
|
|
// left click === 1, middle click === 2, right click === 3
|
|
const clickType = this._settings.get_int('menu-button-icon-click-type');
|
|
if (event.get_button() === clickType) {
|
|
this.menu.close();
|
|
Main.overview.toggle();
|
|
}
|
|
}
|
|
|
|
_aboutThisDistro() {
|
|
Util.spawn(['gnome-control-center', 'info-overview']);
|
|
}
|
|
|
|
_systemPreferences() {
|
|
Util.spawn(['gnome-control-center']);
|
|
}
|
|
|
|
_overviewToggle() {
|
|
Main.overview.toggle();
|
|
}
|
|
|
|
_sleep() {
|
|
Util.spawn(['systemctl', 'suspend']);
|
|
}
|
|
|
|
_restart() {
|
|
Util.spawn(['gnome-session-quit', '--reboot']);
|
|
}
|
|
|
|
_shutdown() {
|
|
Util.spawn(['gnome-session-quit', '--power-off']);
|
|
}
|
|
|
|
_lockScreen() {
|
|
Util.spawn(['loginctl', 'lock-session']);
|
|
}
|
|
|
|
_logOut() {
|
|
Util.spawn(['gnome-session-quit', '--logout']);
|
|
}
|
|
|
|
_showAppGrid() {
|
|
// Code snippet from - https://github.com/G-dH/custom-hot-corners-extended/blob/gdh/actions.js
|
|
// Pressing the apps btn before overview activation avoids icons animation in GS 3.36/3.38
|
|
Main.overview.dash.showAppsButton.checked = true;
|
|
// in 3.36 pressing the button is usualy enough to activate overview, but not always
|
|
Main.overview.show();
|
|
// pressing apps btn before overview has no effect in GS 40, so once again
|
|
Main.overview.dash.showAppsButton.checked = true;
|
|
}
|
|
|
|
_forceQuit() {
|
|
new Selection.SelectionWindow();
|
|
}
|
|
|
|
_openTerminal() {
|
|
Util.trySpawnCommandLine(this._settings.get_string('menu-button-terminal'));
|
|
}
|
|
|
|
_openSoftwareCenter() {
|
|
Util.trySpawnCommandLine(this._settings.get_string('menu-button-software-center'));
|
|
}
|
|
|
|
_openSystemMonitor() {
|
|
Util.trySpawnCommandLine(this._settings.get_string('menu-button-system-monitor'));
|
|
}
|
|
|
|
_openExtensionsApp() {
|
|
const appSys = Shell.AppSystem.get_default();
|
|
const extensionManagerChoice = this._settings.get_string('menu-button-extensions-app');
|
|
const extensionApp = appSys.lookup_app(extensionManagerChoice);
|
|
if (extensionApp) {
|
|
try {
|
|
extensionApp.launch(
|
|
0,
|
|
-1,
|
|
Shell.AppLaunchGpu.APP_PREF
|
|
);
|
|
} catch (e) {
|
|
log(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
setIconImage() {
|
|
const iconIndex = this._settings.get_int('menu-button-icon-image');
|
|
const isSymbolic = this._settings.get_boolean('symbolic-icon');
|
|
const useCustomIcon = this._settings.get_boolean('use-custom-icon');
|
|
const customIconPath = this._settings.get_string('custom-icon-path');
|
|
let isStartHereSymbolic = false;
|
|
let iconPath;
|
|
let notFound = false;
|
|
|
|
if (useCustomIcon && customIconPath !== '') {
|
|
iconPath = customIconPath;
|
|
} else if (isSymbolic) {
|
|
if (Constants.SymbolicDistroIcons[iconIndex] !== undefined) {
|
|
isStartHereSymbolic = Constants.SymbolicDistroIcons[iconIndex].PATH === 'start-here-symbolic';
|
|
iconPath = this._extension.path + Constants.SymbolicDistroIcons[iconIndex].PATH;
|
|
} else {
|
|
notFound = true;
|
|
}
|
|
} else {
|
|
if (Constants.ColouredDistroIcons[iconIndex] !== undefined) {
|
|
iconPath = this._extension.path + Constants.ColouredDistroIcons[iconIndex].PATH;
|
|
} else {
|
|
notFound = true;
|
|
}
|
|
}
|
|
|
|
if (notFound) {
|
|
iconPath = 'start-here-symbolic';
|
|
this._settings.set_boolean('symbolic-icon', true);
|
|
this._settings.set_int('menu-button-icon-image', 0);
|
|
}
|
|
|
|
const fileExists = GLib.file_test(iconPath, GLib.FileTest.IS_REGULAR);
|
|
|
|
const icon = isStartHereSymbolic || !fileExists ? 'start-here-symbolic' : iconPath;
|
|
|
|
this.icon.gicon = Gio.icon_new_for_string(icon);
|
|
}
|
|
setIconSize() {
|
|
const iconSize = this._settings.get_int('menu-button-icon-size');
|
|
this.icon.icon_size = iconSize;
|
|
}
|
|
|
|
hideIconShadow() {
|
|
const iconShadow = this._settings.get_boolean('hide-icon-shadow');
|
|
|
|
if(!iconShadow){
|
|
this.icon.add_style_class_name('system-status-icon');
|
|
} else {
|
|
this.icon.remove_style_class_name('system-status-icon');
|
|
}
|
|
}
|
|
});
|
|
|
|
export default class LogoMenu extends Extension {
|
|
enable() {
|
|
this.settings = this.getSettings();
|
|
|
|
this.settings.connectObject('changed::show-activities-button',
|
|
() => this._setActivitiesVisibility(), this);
|
|
|
|
this._setActivitiesVisibility();
|
|
|
|
const indicator = new MenuButton(this);
|
|
Main.panel.addToStatusArea('LogoMenu', indicator, 0, 'left');
|
|
}
|
|
|
|
disable() {
|
|
if (!Main.sessionMode.isLocked)
|
|
Main.panel.statusArea.activities?.container.show();
|
|
|
|
Main.panel.statusArea['LogoMenu'].destroy();
|
|
}
|
|
|
|
_setActivitiesVisibility() {
|
|
const showActivitiesButton = this.settings.get_boolean('show-activities-button');
|
|
const activitiesButton = Main.panel.statusArea['activities'];
|
|
|
|
if (!activitiesButton)
|
|
return;
|
|
|
|
if (showActivitiesButton)
|
|
activitiesButton.container.show();
|
|
else
|
|
activitiesButton.container.hide();
|
|
}
|
|
}
|