Fix issues with Gnome 45

This commit is contained in:
2024-04-03 11:31:53 +02:00
parent 747d4a2423
commit 43d9b68be6
8 changed files with 2274 additions and 1804 deletions

View File

@@ -25,12 +25,11 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const Gettext = imports.gettext;
const Gio = imports.gi.Gio;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
import { gettext as Gettext } from "resource:///org/gnome/shell/extensions/extension.js";
import Gio from "gi://Gio";
import * as Config from "resource:///org/gnome/shell/misc/config.js";
import * as extension from "./extension.js";
/**
* initTranslations:
* @domain: (optional): the gettext domain to use
@@ -38,20 +37,17 @@ const ExtensionUtils = imports.misc.extensionUtils;
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
function initTranslations(domain) {
let extension = ExtensionUtils.getCurrentExtension();
domain = domain || extension.metadata['gettext-domain'];
export function initTranslations(domain) {
domain = domain || extension.metadata["gettext-domain"];
// check if this extension was built with "make zip-file", and thus
// has the locale files in a subfolder
// otherwise assume that extension has been installed in the
// same prefix as gnome-shell
let localeDir = extension.dir.get_child('locale');
let localeDir = extension.dir.get_child("locale");
if (localeDir.query_exists(null))
Gettext.bindtextdomain(domain, localeDir.get_path());
else
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
else Gettext.bindtextdomain(domain, Config.LOCALEDIR);
}
/**
@@ -62,10 +58,8 @@ function initTranslations(domain) {
* in extensionsdir/schemas. If @schema is not provided, it is taken from
* metadata['settings-schema'].
*/
function getSettings(schema) {
let extension = ExtensionUtils.getCurrentExtension();
schema = schema || extension.metadata['settings-schema'];
export function getSettings(schema) {
schema = schema || extension.metadata["settings-schema"];
const GioSSS = Gio.SettingsSchemaSource;
@@ -74,20 +68,25 @@ function getSettings(schema) {
// otherwise assume that extension has been installed in the
// same prefix as gnome-shell (and therefore schemas are available
// in the standard folders)
let schemaDir = extension.dir.get_child('schemas');
let schemaDir = extension.dir.get_child("schemas");
let schemaSource;
if (schemaDir.query_exists(null))
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(),
false);
else
schemaSource = GioSSS.get_default();
schemaSource = GioSSS.new_from_directory(
schemaDir.get_path(),
GioSSS.get_default(),
false,
);
else schemaSource = GioSSS.get_default();
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj)
throw new Error('Schema ' + schema + ' could not be found for extension '
+ extension.metadata.uuid + '. Please check your installation.');
throw new Error(
"Schema " +
schema +
" could not be found for extension " +
extension.metadata.uuid +
". Please check your installation.",
);
return new Gio.Settings({ settings_schema: schemaObj });
}

View File

@@ -15,98 +15,97 @@ You should have received a copy of the GNU General Public License
along with this program; if not, visit https://www.gnu.org/licenses/.
*/
const { Clutter, Gio } = imports.gi;
import Clutter from "gi://Clutter";
import Gio from "gi://Gio";
const Main = imports.ui.main;
var { ANIMATION_TIME } = imports.ui.overview;
import * as Main from "resource:///org/gnome/shell/ui/main.js";
import { ANIMATION_TIME } from "resource:///org/gnome/shell/ui/overview.js";
import { Extension } from "resource:///org/gnome/shell/extensions/extension.js";
const Config = imports.misc.config;
const GNOME_SHELL_VERSION = Config.PACKAGE_VERSION.split('.');
import * as Config from "resource:///org/gnome/shell/misc/config.js";
const GNOME_SHELL_VERSION = Config.PACKAGE_VERSION.split(".");
const ExtensionUtils = imports.misc.extensionUtils;
const MultiMonitors = ExtensionUtils.getCurrentExtension();
const Convenience = MultiMonitors.imports.convenience;
import * as Convenience from "./convenience.js";
const MMLayout = MultiMonitors.imports.mmlayout;
const MMOverview = MultiMonitors.imports.mmoverview;
const MMIndicator = MultiMonitors.imports.indicator;
import * as MMLayout from "./mmlayout.js";
import * as MMOverview from "./mmoverview.js";
import * as MMIndicator from "./indicator.js";
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
const MUTTER_SCHEMA = 'org.gnome.mutter';
const WORKSPACES_ONLY_ON_PRIMARY_ID = 'workspaces-only-on-primary';
const OVERRIDE_SCHEMA = "org.gnome.shell.overrides";
const MUTTER_SCHEMA = "org.gnome.mutter";
const WORKSPACES_ONLY_ON_PRIMARY_ID = "workspaces-only-on-primary";
const SHOW_INDICATOR_ID = 'show-indicator';
const THUMBNAILS_SLIDER_POSITION_ID = 'thumbnails-slider-position';
const SHOW_INDICATOR_ID = "show-indicator";
const THUMBNAILS_SLIDER_POSITION_ID = "thumbnails-slider-position";
function copyClass (s, d) {
// global.log(s.name +" > "+ d.name);
if (!s) throw Error(`copyClass s undefined for d ${d.name}`)
let propertyNames = Reflect.ownKeys(s.prototype);
for (let pName of propertyNames.values()) {
// global.log(" ) "+pName.toString());
if (typeof pName === "symbol") continue;
if (d.prototype.hasOwnProperty(pName)) continue;
if (pName === "prototype") continue;
if (pName === "constructor") continue;
// global.log(pName);
let pDesc = Reflect.getOwnPropertyDescriptor(s.prototype, pName);
// global.log(typeof pDesc);
if (typeof pDesc !== 'object') continue;
Reflect.defineProperty(d.prototype, pName, pDesc);
}
};
function gnomeShellVersion() {
return GNOME_SHELL_VERSION;
export function copyClass(s, d) {
// global.log(s.name +" > "+ d.name);
if (!s) throw Error(`copyClass s undefined for d ${d.name}`);
let propertyNames = Reflect.ownKeys(s.prototype);
for (let pName of propertyNames.values()) {
// global.log(" ) "+pName.toString());
if (typeof pName === "symbol") continue;
if (d.prototype.hasOwnProperty(pName)) continue;
if (pName === "prototype") continue;
if (pName === "constructor") continue;
// global.log(pName);
let pDesc = Reflect.getOwnPropertyDescriptor(s.prototype, pName);
// global.log(typeof pDesc);
if (typeof pDesc !== "object") continue;
Reflect.defineProperty(d.prototype, pName, pDesc);
}
}
class MultiMonitorsAddOn {
export function gnomeShellVersion() {
return GNOME_SHELL_VERSION;
}
constructor() {
this._settings = Convenience.getSettings();
// this._ov_settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._mu_settings = new Gio.Settings({ schema: MUTTER_SCHEMA });
export class MultiMonitorsAddOn extends Extension {
constructor() {
this._settings = Convenience.getSettings();
// this._ov_settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._mu_settings = new Gio.Settings({ schema: MUTTER_SCHEMA });
this.mmIndicator = null;
Main.mmOverview = null;
Main.mmLayoutManager = null;
this.mmIndicator = null;
Main.mmOverview = null;
Main.mmLayoutManager = null;
this._mmMonitors = 0;
this.syncWorkspacesActualGeometry = null;
}
this._mmMonitors = 0;
this.syncWorkspacesActualGeometry = null;
}
_showIndicator() {
if(this._settings.get_boolean(SHOW_INDICATOR_ID)) {
if(!this.mmIndicator) {
this.mmIndicator = Main.panel.addToStatusArea('MultiMonitorsAddOn', new MMIndicator.MultiMonitorsIndicator());
_showIndicator() {
if (this._settings.get_boolean(SHOW_INDICATOR_ID)) {
if (!this.mmIndicator) {
this.mmIndicator = Main.panel.addToStatusArea(
"MultiMonitorsAddOn",
new MMIndicator.MultiMonitorsIndicator(),
);
}
}
else {
} else {
this._hideIndicator();
}
}
}
_hideIndicator() {
if(this.mmIndicator) {
_hideIndicator() {
if (this.mmIndicator) {
this.mmIndicator.destroy();
this.mmIndicator = null;
}
}
}
_showThumbnailsSlider() {
if (this._settings.get_string(THUMBNAILS_SLIDER_POSITION_ID) === 'none') {
_showThumbnailsSlider() {
if (this._settings.get_string(THUMBNAILS_SLIDER_POSITION_ID) === "none") {
this._hideThumbnailsSlider();
return;
}
// if(this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
// this._ov_settings.set_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID, false);
if(this._mu_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
// if(this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
// this._ov_settings.set_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID, false);
if (this._mu_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
this._mu_settings.set_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID, false);
if (Main.mmOverview)
return;
if (Main.mmOverview) return;
Main.mmOverview = [];
for (let idx = 0; idx < Main.layoutManager.monitors.length; idx++) {
@@ -115,178 +114,194 @@ class MultiMonitorsAddOn {
}
}
this.syncWorkspacesActualGeometry = Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry;
Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry = function() {
if (this._inWindowFade)
return;
this.syncWorkspacesActualGeometry =
Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry;
Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry =
function () {
if (this._inWindowFade) return;
const primaryView = this._getPrimaryView();
if (primaryView) {
primaryView.ease({
...this._actualGeometry,
duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
}
const primaryView = this._getPrimaryView();
if (primaryView) {
primaryView.ease({
...this._actualGeometry,
duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
}
for (let idx = 0; idx < Main.mmOverview.length; idx++) {
if (!Main.mmOverview[idx])
continue;
if (!Main.mmOverview[idx]._overview)
continue;
const mmView = Main.mmOverview[idx]._overview._controls._workspacesViews;
if (!mmView)
continue;
for (let idx = 0; idx < Main.mmOverview.length; idx++) {
if (!Main.mmOverview[idx]) continue;
if (!Main.mmOverview[idx]._overview) continue;
const mmView =
Main.mmOverview[idx]._overview._controls._workspacesViews;
if (!mmView) continue;
const mmGeometry = Main.mmOverview[idx].getWorkspacesActualGeometry();
mmView.ease({
...mmGeometry,
duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
}
}
}
const mmGeometry = Main.mmOverview[idx].getWorkspacesActualGeometry();
mmView.ease({
...mmGeometry,
duration: Main.overview.animationInProgress ? ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
}
};
}
_hideThumbnailsSlider() {
if (!Main.mmOverview)
return;
if (!Main.mmOverview) return;
for (let idx = 0; idx < Main.mmOverview.length; idx++) {
if (Main.mmOverview[idx])
Main.mmOverview[idx].destroy();
}
Main.mmOverview = null;
Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry = this.syncWorkspacesActualGeometry;
}
for (let idx = 0; idx < Main.mmOverview.length; idx++) {
if (Main.mmOverview[idx]) Main.mmOverview[idx].destroy();
}
Main.mmOverview = null;
Main.overview.searchController._workspacesDisplay._syncWorkspacesActualGeometry =
this.syncWorkspacesActualGeometry;
}
_relayout() {
if(this._mmMonitors!=Main.layoutManager.monitors.length){
_relayout() {
if (this._mmMonitors != Main.layoutManager.monitors.length) {
this._mmMonitors = Main.layoutManager.monitors.length;
global.log("pi:"+Main.layoutManager.primaryIndex);
global.log("pi:" + Main.layoutManager.primaryIndex);
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
let monitor = Main.layoutManager.monitors[i];
global.log("i:"+i+" x:"+monitor.x+" y:"+monitor.y+" w:"+monitor.width+" h:"+monitor.height);
global.log(
"i:" +
i +
" x:" +
monitor.x +
" y:" +
monitor.y +
" w:" +
monitor.width +
" h:" +
monitor.height,
);
}
this._hideThumbnailsSlider();
this._showThumbnailsSlider();
}
}
}
_switchOffThumbnails() {
_switchOffThumbnails() {
if (
// this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID) ||
this._mu_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID))
{
this._settings.set_string(THUMBNAILS_SLIDER_POSITION_ID, 'none');
// this._ov_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID) ||
this._mu_settings.get_boolean(WORKSPACES_ONLY_ON_PRIMARY_ID)
) {
this._settings.set_string(THUMBNAILS_SLIDER_POSITION_ID, "none");
}
}
}
enable(version) {
global.log("Enable Multi Monitors Add-On (" + version + ")...");
if (Main.panel.statusArea.MultiMonitorsAddOn) disable();
enable(version) {
global.log("Enable Multi Monitors Add-On ("+version+")...")
if(Main.panel.statusArea.MultiMonitorsAddOn)
disable();
this._mmMonitors = 0;
// this._switchOffThumbnailsOvId = this._ov_settings.connect('changed::'+WORKSPACES_ONLY_ON_PRIMARY_ID,
// this._switchOffThumbnails.bind(this));
this._switchOffThumbnailsMuId = this._mu_settings.connect('changed::'+WORKSPACES_ONLY_ON_PRIMARY_ID,
this._switchOffThumbnails.bind(this));
// this._switchOffThumbnailsOvId = this._ov_settings.connect('changed::'+WORKSPACES_ONLY_ON_PRIMARY_ID,
// this._switchOffThumbnails.bind(this));
this._switchOffThumbnailsMuId = this._mu_settings.connect(
"changed::" + WORKSPACES_ONLY_ON_PRIMARY_ID,
this._switchOffThumbnails.bind(this),
);
this._showIndicatorId = this._settings.connect('changed::'+SHOW_INDICATOR_ID, this._showIndicator.bind(this));
this._showIndicatorId = this._settings.connect(
"changed::" + SHOW_INDICATOR_ID,
this._showIndicator.bind(this),
);
this._showIndicator();
Main.mmLayoutManager = new MMLayout.MultiMonitorsLayoutManager();
this._showPanelId = this._settings.connect('changed::'+MMLayout.SHOW_PANEL_ID, Main.mmLayoutManager.showPanel.bind(Main.mmLayoutManager));
Main.mmLayoutManager.showPanel();
this._thumbnailsSliderPositionId = this._settings.connect('changed::'+THUMBNAILS_SLIDER_POSITION_ID, this._showThumbnailsSlider.bind(this));
this._relayoutId = Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
this._relayout();
}
disable() {
Main.mmLayoutManager = new MMLayout.MultiMonitorsLayoutManager();
this._showPanelId = this._settings.connect(
"changed::" + MMLayout.SHOW_PANEL_ID,
Main.mmLayoutManager.showPanel.bind(Main.mmLayoutManager),
);
Main.mmLayoutManager.showPanel();
this._thumbnailsSliderPositionId = this._settings.connect(
"changed::" + THUMBNAILS_SLIDER_POSITION_ID,
this._showThumbnailsSlider.bind(this),
);
this._relayoutId = Main.layoutManager.connect(
"monitors-changed",
this._relayout.bind(this),
);
this._relayout();
}
disable() {
Main.layoutManager.disconnect(this._relayoutId);
// this._ov_settings.disconnect(this._switchOffThumbnailsOvId);
// this._ov_settings.disconnect(this._switchOffThumbnailsOvId);
this._mu_settings.disconnect(this._switchOffThumbnailsMuId);
this._settings.disconnect(this._showPanelId);
this._settings.disconnect(this._thumbnailsSliderPositionId);
this._settings.disconnect(this._showIndicatorId);
this._hideIndicator();
Main.mmLayoutManager.hidePanel();
Main.mmLayoutManager = null;
this._hideThumbnailsSlider();
this._mmMonitors = 0;
global.log("Disable Multi Monitors Add-On ...")
}
global.log("Disable Multi Monitors Add-On ...");
}
}
var multiMonitorsAddOn = null;
var version = null;
function init() {
Convenience.initTranslations();
export function init() {
Convenience.initTranslations();
// fix bug in panel: Destroy function many time added to this same indicator.
Main.panel._ensureIndicator = function(role) {
let indicator = this.statusArea[role];
if (indicator) {
indicator.container.show();
return null;
}
else {
let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
return null;
}
indicator = new constructor(this);
this.statusArea[role] = indicator;
}
return indicator;
};
// fix bug in panel: Destroy function many time added to this same indicator.
Main.panel._ensureIndicator = function (role) {
let indicator = this.statusArea[role];
if (indicator) {
indicator.container.show();
return null;
} else {
let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
return null;
}
indicator = new constructor(this);
this.statusArea[role] = indicator;
}
return indicator;
};
const metaVersion = MultiMonitors.metadata['version'];
if (Number.isFinite(metaVersion)) {
version = 'v'+Math.trunc(metaVersion);
switch(Math.round((metaVersion%1)*10)) {
case 0:
break;
case 1:
version += '+bugfix';
break;
case 2:
version += '+develop';
break;
default:
version += '+modified';
break;
}
}
else
version = metaVersion;
const metaVersion = MultiMonitors.metadata["version"];
if (Number.isFinite(metaVersion)) {
version = "v" + Math.trunc(metaVersion);
switch (Math.round((metaVersion % 1) * 10)) {
case 0:
break;
case 1:
version += "+bugfix";
break;
case 2:
version += "+develop";
break;
default:
version += "+modified";
break;
}
} else version = metaVersion;
}
function enable() {
if (multiMonitorsAddOn !== null)
return;
export function enable() {
if (multiMonitorsAddOn !== null) return;
multiMonitorsAddOn = new MultiMonitorsAddOn();
multiMonitorsAddOn.enable(version);
multiMonitorsAddOn = new MultiMonitorsAddOn();
multiMonitorsAddOn.enable(version);
}
function disable() {
if (multiMonitorsAddOn == null)
return;
export function disable() {
if (multiMonitorsAddOn == null) return;
multiMonitorsAddOn.disable();
multiMonitorsAddOn = null;
multiMonitorsAddOn.disable();
multiMonitorsAddOn = null;
}

View File

@@ -15,20 +15,25 @@ You should have received a copy of the GNU General Public License
along with this program; if not, visit https://www.gnu.org/licenses/.
*/
const { St, Gio, GLib, GObject } = imports.gi;
import St from "gi://St";
import Gio from "gi://Gio";
import GLib from "gi://GLib";
import GObject from "gi://GObject";
const Util = imports.misc.util;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
import * as Util from "resource:///org/gnome/shell/misc/util.js";
imports.misc.util;
import * as Main from "resource:///org/gnome/shell/ui/main.js";
import * as PanelMenu from "resource:///org/gnome/shell/ui/panelMenu.js";
const Gettext = imports.gettext.domain('multi-monitors-add-on');
const _ = Gettext.gettext;
const CE = imports.misc.extensionUtils.getCurrentExtension();
const MultiMonitors = CE.imports.extension;
const Convenience = CE.imports.convenience;
const extensionPath = CE.path;
import {
Extension,
gettext as _,
} from "resource:///org/gnome/shell/extensions/extension.js";
import * as MultiMonitors from "./extension.js";
import * as Convenience from "./convenience.js";
const extensionPath = Extension.path;
var MultiMonitorsIndicator = (() => {
export const MultiMonitorsIndicator = (() => {
let MultiMonitorsIndicator = class MultiMonitorsIndicator extends PanelMenu.Button {
_init() {
super._init(0.0, "MultiMonitorsAddOn", false);
@@ -36,53 +41,65 @@ var MultiMonitorsIndicator = (() => {
Convenience.initTranslations();
this.text = null;
this._mmStatusIcon = new St.BoxLayout({ style_class: 'multimonitor-status-indicators-box' });
this._mmStatusIcon = new St.BoxLayout({
style_class: "multimonitor-status-indicators-box",
});
this._mmStatusIcon.hide();
this.add_child(this._mmStatusIcon);
this._leftRightIcon = true;
this.menu.addAction(_("Preferences"), this._onPreferences.bind(this));
this._viewMonitorsId = Main.layoutManager.connect('monitors-changed', this._viewMonitors.bind(this));
this._viewMonitorsId = Main.layoutManager.connect(
"monitors-changed",
this._viewMonitors.bind(this),
);
this._viewMonitors();
}
_onDestroy() {
Main.layoutManager.disconnect(this._viewMonitorsId);
super._onDestroy();
}
_syncIndicatorsVisible() {
this._mmStatusIcon.visible = this._mmStatusIcon.get_children().some(a => a.visible);
}
_syncIndicatorsVisible() {
this._mmStatusIcon.visible = this._mmStatusIcon
.get_children()
.some((a) => a.visible);
}
_icon_name (icon, iconName) {
icon.set_gicon(Gio.icon_new_for_string(extensionPath+"/icons/"+iconName+".svg"));
}
_icon_name(icon, iconName) {
icon.set_gicon(
Gio.icon_new_for_string(extensionPath + "/icons/" + iconName + ".svg"),
);
}
_viewMonitors() {
let monitors = this._mmStatusIcon.get_children();
let monitorChange = Main.layoutManager.monitors.length - monitors.length;
if(monitorChange>0){
if (monitorChange > 0) {
global.log("Add Monitors ...");
for(let idx = 0; idx<monitorChange; idx++){
for (let idx = 0; idx < monitorChange; idx++) {
let icon;
icon = new St.Icon({style_class: 'system-status-icon multimonitor-status-icon'});
icon = new St.Icon({
style_class: "system-status-icon multimonitor-status-icon",
});
this._mmStatusIcon.add_child(icon);
icon.connect('notify::visible', this._syncIndicatorsVisible.bind(this));
icon.connect(
"notify::visible",
this._syncIndicatorsVisible.bind(this),
);
if (this._leftRightIcon)
this._icon_name(icon, 'multi-monitors-l-symbolic');
else
this._icon_name(icon, 'multi-monitors-r-symbolic');
this._icon_name(icon, "multi-monitors-l-symbolic");
else this._icon_name(icon, "multi-monitors-r-symbolic");
this._leftRightIcon = !this._leftRightIcon;
}
this._syncIndicatorsVisible();
}
else if(monitorChange<0){
} else if (monitorChange < 0) {
global.log("Remove Monitors ...");
monitorChange = -monitorChange;
for(let idx = 0; idx<monitorChange; idx++){
for (let idx = 0; idx < monitorChange; idx++) {
let icon = this._mmStatusIcon.get_last_child();
this._mmStatusIcon.remove_child(icon);
icon.destroy();
@@ -92,17 +109,18 @@ var MultiMonitorsIndicator = (() => {
}
_onPreferences() {
const uuid = "multi-monitors-add-on@breizhhardware";
const uuid = "multi-monitors-add-on@spin83";
Gio.DBus.session.call(
'org.gnome.Shell.Extensions',
'/org/gnome/Shell/Extensions',
'org.gnome.Shell.Extensions',
'OpenExtensionPrefs',
new GLib.Variant('(ssa{sv})', [uuid, '', {}]),
"org.gnome.Shell.Extensions",
"/org/gnome/Shell/Extensions",
"org.gnome.Shell.Extensions",
"OpenExtensionPrefs",
new GLib.Variant("(ssa{sv})", [uuid, "", {}]),
null,
Gio.DBusCallFlags.NONE,
-1,
null);
null,
);
}
};
return GObject.registerClass(MultiMonitorsIndicator);

View File

@@ -15,398 +15,489 @@ You should have received a copy of the GNU General Public License
along with this program; if not, visit https://www.gnu.org/licenses/.
*/
const Signals = imports.signals;
import * as Signals from "resource:///org/gnome/shell/signals.js";
const { St, Gio, Shell, Clutter, GnomeDesktop, Pango, GObject, GLib } = imports.gi;
import St from "gi://St";
import Gio from "gi://Gio";
import GLib from "gi://GLib";
import GObject from "gi://GObject";
import Shell from "gi://Shell";
import Clutter from "gi://Clutter";
import GnomeDesktop from "gi://GnomeDesktop";
import Pango from "gi://Pango";
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const MessageList = imports.ui.messageList;
const DateMenu = imports.ui.dateMenu;
const Calendar = imports.ui.calendar;
const PopupMenu = imports.ui.popupMenu;
import * as Main from "resource:///org/gnome/shell/ui/main.js";
import * as PanelMenu from "resource:///org/gnome/shell/ui/panelMenu.js";
import * as MessageList from "resource:///org/gnome/shell/ui/messageList.js";
import * as DateMenu from "resource:///org/gnome/shell/ui/dateMenu.js";
import * as Calendar from "resource:///org/gnome/shell/ui/calendar.js";
import * as PopupMenu from "resource:///org/gnome/shell/ui/popupMenu.js";
const ExtensionUtils = imports.misc.extensionUtils;
const CE = ExtensionUtils.getCurrentExtension();
const MultiMonitors = CE.imports.extension;
const Convenience = CE.imports.convenience;
import * as MultiMonitors from "./extension.js";
import * as Convenience from "./convenience.js";
// Calendar.DoNotDisturbSwitch is const, so not exported. Either
// <https://gjs.guide/guides/gobject/subclassing.html#gtypename> is untrue, or
// GObject.type_from_name() is broken, so we can't get its constructor via GI
// either. Luckily it's a short class, so we can copy & paste.
const MultiMonitorsDoNotDisturbSwitch = GObject.registerClass(
class MultiMonitorsDoNotDisturbSwitch extends PopupMenu.Switch {
_init() {
this._settings = new Gio.Settings({
schema_id: 'org.gnome.desktop.notifications',
});
export const MultiMonitorsDoNotDisturbSwitch = GObject.registerClass(
class MultiMonitorsDoNotDisturbSwitch extends PopupMenu.Switch {
_init() {
this._settings = new Gio.Settings({
schema_id: "org.gnome.desktop.notifications",
});
super._init(this._settings.get_boolean('show-banners'));
super._init(this._settings.get_boolean("show-banners"));
this._settings.bind('show-banners',
this, 'state',
Gio.SettingsBindFlags.INVERT_BOOLEAN);
this._settings.bind(
"show-banners",
this,
"state",
Gio.SettingsBindFlags.INVERT_BOOLEAN,
);
this.connect('destroy', () => {
this._settings.run_dispose();
this._settings = null;
});
}
});
this.connect("destroy", () => {
this._settings.run_dispose();
this._settings = null;
});
}
},
);
var MultiMonitorsCalendar = (() => {
let MultiMonitorsCalendar = class MultiMonitorsCalendar extends St.Widget {
_init () {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
this._showWeekdateKeyId = this._settings.connect('changed::%s'.format(Calendar.SHOW_WEEKDATE_KEY), this._onSettingsChange.bind(this));
this._useWeekdate = this._settings.get_boolean(Calendar.SHOW_WEEKDATE_KEY);
this._headerFormatWithoutYear = _('%OB');
this._headerFormat = _('%OB %Y');
// Start off with the current date
this._selectedDate = new Date();
this._shouldDateGrabFocus = false;
super._init({
style_class: 'calendar',
layout_manager: new Clutter.GridLayout(),
reactive: true,
});
this._buildHeader();
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
this._settings.disconnect(this._showWeekdateKeyId);
}
};
MultiMonitors.copyClass(Calendar.Calendar, MultiMonitorsCalendar);
return GObject.registerClass({
Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } },
}, MultiMonitorsCalendar);
export const MultiMonitorsCalendar = (() => {
let MultiMonitorsCalendar = class MultiMonitorsCalendar extends St.Widget {
_init() {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({
schema_id: "org.gnome.desktop.calendar",
});
this._showWeekdateKeyId = this._settings.connect(
"changed::%s".format(Calendar.SHOW_WEEKDATE_KEY),
this._onSettingsChange.bind(this),
);
this._useWeekdate = this._settings.get_boolean(
Calendar.SHOW_WEEKDATE_KEY,
);
this._headerFormatWithoutYear = _("%OB");
this._headerFormat = _("%OB %Y");
// Start off with the current date
this._selectedDate = new Date();
this._shouldDateGrabFocus = false;
super._init({
style_class: "calendar",
layout_manager: new Clutter.GridLayout(),
reactive: true,
});
this._buildHeader();
this.connect("destroy", this._onDestroy.bind(this));
}
_onDestroy() {
this._settings.disconnect(this._showWeekdateKeyId);
}
};
MultiMonitors.copyClass(Calendar.Calendar, MultiMonitorsCalendar);
return GObject.registerClass(
{
Signals: {
"selected-date-changed": { param_types: [GLib.DateTime.$gtype] },
},
},
MultiMonitorsCalendar,
);
})();
var MultiMonitorsEventsSection = (() => {
export var MultiMonitorsEventsSection = (() => {
let MultiMonitorsEventsSection = class MultiMonitorsEventsSection extends St.Button {
_init() {
super._init({
style_class: 'events-button',
can_focus: true,
x_expand: true,
child: new St.BoxLayout({
style_class: 'events-box',
_init() {
super._init({
style_class: "events-button",
can_focus: true,
x_expand: true,
child: new St.BoxLayout({
style_class: "events-box",
vertical: true,
x_expand: true,
}),
});
this._startDate = null;
this._endDate = null;
this._eventSource = null;
this._calendarApp = null;
this._title = new St.Label({
style_class: "events-title",
});
this.child.add_child(this._title);
this._eventsList = new St.BoxLayout({
style_class: "events-list",
vertical: true,
x_expand: true,
}),
});
});
this.child.add_child(this._eventsList);
this._startDate = null;
this._endDate = null;
this._appSys = Shell.AppSystem.get_default();
this._appInstalledChangedId = this._appSys.connect(
"installed-changed",
this._appInstalledChanged.bind(this),
);
this._appInstalledChanged();
this._eventSource = null;
this._calendarApp = null;
this.connect("destroy", this._onDestroy.bind(this));
this._appInstalledChanged();
}
this._title = new St.Label({
style_class: 'events-title',
});
this.child.add_child(this._title);
this._eventsList = new St.BoxLayout({
style_class: 'events-list',
vertical: true,
x_expand: true,
});
this.child.add_child(this._eventsList);
this._appSys = Shell.AppSystem.get_default();
this._appInstalledChangedId = this._appSys.connect('installed-changed',
this._appInstalledChanged.bind(this));
this._appInstalledChanged();
this.connect('destroy', this._onDestroy.bind(this));
this._appInstalledChanged();
}
_onDestroy() {
this._appSys.disconnect(this._appInstalledChangedId);
}};
_onDestroy() {
this._appSys.disconnect(this._appInstalledChangedId);
}
};
MultiMonitors.copyClass(DateMenu.EventsSection, MultiMonitorsEventsSection);
return GObject.registerClass(MultiMonitorsEventsSection);
return GObject.registerClass(MultiMonitorsEventsSection);
})();
var MultiMonitorsNotificationSection = (() => {
export var MultiMonitorsNotificationSection = (() => {
let MultiMonitorsNotificationSection = class MultiMonitorsNotificationSection extends MessageList.MessageListSection {
_init() {
super._init();
_init() {
super._init();
this._sources = new Map();
this._nUrgent = 0;
this._sources = new Map();
this._nUrgent = 0;
this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
Main.messageTray.getSources().forEach(source => {
this._sourceAdded(Main.messageTray, source);
});
this._sourceAddedId = Main.messageTray.connect(
"source-added",
this._sourceAdded.bind(this),
);
Main.messageTray.getSources().forEach((source) => {
this._sourceAdded(Main.messageTray, source);
});
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
Main.messageTray.disconnect(this._sourceAddedId);
let source, obj;
for ([source, obj] of this._sources.entries()) {
this._onSourceDestroy(source, obj);
this.connect("destroy", this._onDestroy.bind(this));
}
}};
MultiMonitors.copyClass(Calendar.NotificationSection, MultiMonitorsNotificationSection);
_onDestroy() {
Main.messageTray.disconnect(this._sourceAddedId);
let source, obj;
for ([source, obj] of this._sources.entries()) {
this._onSourceDestroy(source, obj);
}
}
};
MultiMonitors.copyClass(
Calendar.NotificationSection,
MultiMonitorsNotificationSection,
);
return GObject.registerClass(MultiMonitorsNotificationSection);
})();
var MultiMonitorsCalendarMessageList = (() => {
let MultiMonitorsCalendarMessageList = class MultiMonitorsCalendarMessageList extends St.Widget {
_init() {
super._init({
style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
export var MultiMonitorsCalendarMessageList = (() => {
let MultiMonitorsCalendarMessageList = class MultiMonitorsCalendarMessageList extends St.Widget {
_init() {
super._init({
style_class: "message-list",
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this._sessionModeUpdatedId = 0;
this._sessionModeUpdatedId = 0;
this._placeholder = new Calendar.Placeholder();
this.add_actor(this._placeholder);
this._placeholder = new Calendar.Placeholder();
this.add_actor(this._placeholder);
let box = new St.BoxLayout({ vertical: true,
x_expand: true, y_expand: true });
this.add_actor(box);
let box = new St.BoxLayout({
vertical: true,
x_expand: true,
y_expand: true,
});
this.add_actor(box);
this._scrollView = new St.ScrollView({
style_class: 'vfade',
overlay_scrollbars: true,
x_expand: true, y_expand: true,
});
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
box.add_actor(this._scrollView);
this._scrollView = new St.ScrollView({
style_class: "vfade",
overlay_scrollbars: true,
x_expand: true,
y_expand: true,
});
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
box.add_actor(this._scrollView);
let hbox = new St.BoxLayout({ style_class: 'message-list-controls' });
box.add_child(hbox);
let hbox = new St.BoxLayout({ style_class: "message-list-controls" });
box.add_child(hbox);
const dndLabel = new St.Label({
text: _('Do Not Disturb'),
y_align: Clutter.ActorAlign.CENTER,
});
hbox.add_child(dndLabel);
const dndLabel = new St.Label({
text: _("Do Not Disturb"),
y_align: Clutter.ActorAlign.CENTER,
});
hbox.add_child(dndLabel);
this._dndSwitch = new MultiMonitorsDoNotDisturbSwitch();
this._dndButton = new St.Button({
can_focus: true,
toggle_mode: true,
child: this._dndSwitch,
label_actor: dndLabel,
});
this._dndSwitch = new MultiMonitorsDoNotDisturbSwitch();
this._dndButton = new St.Button({
can_focus: true,
toggle_mode: true,
child: this._dndSwitch,
label_actor: dndLabel,
});
this._dndSwitch.bind_property('state',
this._dndButton, 'checked',
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
this._dndSwitch.bind_property(
"state",
this._dndButton,
"checked",
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE,
);
hbox.add_child(this._dndButton);
hbox.add_child(this._dndButton);
this._clearButton = new St.Button({
style_class: 'message-list-clear-button button',
label: _('Clear'),
can_focus: true,
x_expand: true,
x_align: Clutter.ActorAlign.END,
});
this._clearButton.connect('clicked', () => {
this._sectionList.get_children().forEach(s => s.clear());
});
hbox.add_actor(this._clearButton);
this._clearButton = new St.Button({
style_class: "message-list-clear-button button",
label: _("Clear"),
can_focus: true,
x_expand: true,
x_align: Clutter.ActorAlign.END,
});
this._clearButton.connect("clicked", () => {
this._sectionList.get_children().forEach((s) => s.clear());
});
hbox.add_actor(this._clearButton);
this._placeholder.bind_property('visible',
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
this._placeholder.bind_property(
"visible",
this._clearButton,
"visible",
GObject.BindingFlags.INVERT_BOOLEAN,
);
this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
vertical: true,
x_expand: true,
y_expand: true,
y_align: Clutter.ActorAlign.START });
this._sectionList.connect('actor-added', this._sync.bind(this));
this._sectionList.connect('actor-removed', this._sync.bind(this));
this._scrollView.add_actor(this._sectionList);
this._sectionList = new St.BoxLayout({
style_class: "message-list-sections",
vertical: true,
x_expand: true,
y_expand: true,
y_align: Clutter.ActorAlign.START,
});
this._sectionList.connect("actor-added", this._sync.bind(this));
this._sectionList.connect("actor-removed", this._sync.bind(this));
this._scrollView.add_actor(this._sectionList);
this._notificationSection = new MultiMonitorsNotificationSection();
this._addSection(this._notificationSection);
this._notificationSection = new MultiMonitorsNotificationSection();
this._addSection(this._notificationSection);
this._sessionModeUpdatedId = Main.sessionMode.connect('updated', this._sync.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
this._sessionModeUpdatedId = Main.sessionMode.connect(
"updated",
this._sync.bind(this),
);
this.connect("destroy", this._onDestroy.bind(this));
}
_onDestroy() {
Main.sessionMode.disconnect(this._sessionModeUpdatedId);
this._sessionModeUpdatedId = 0;
}
_onDestroy() {
Main.sessionMode.disconnect(this._sessionModeUpdatedId);
this._sessionModeUpdatedId = 0;
}
_sync() {
if (this._sessionModeUpdatedId === 0) return;
Calendar.CalendarMessageList.prototype._sync.call(this);
}};
_sync() {
if (this._sessionModeUpdatedId === 0) return;
Calendar.CalendarMessageList.prototype._sync.call(this);
}
};
MultiMonitors.copyClass(Calendar.CalendarMessageList, MultiMonitorsCalendarMessageList);
MultiMonitors.copyClass(
Calendar.CalendarMessageList,
MultiMonitorsCalendarMessageList,
);
return GObject.registerClass(MultiMonitorsCalendarMessageList);
})();
var MultiMonitorsMessagesIndicator = (() => {
export var MultiMonitorsMessagesIndicator = (() => {
let MultiMonitorsMessagesIndicator = class MultiMonitorsMessagesIndicator extends St.Icon {
_init() {
super._init({
icon_size: 16,
visible: false,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
_init() {
super._init({
icon_size: 16,
visible: false,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
this._sources = [];
this._count = 0;
this._sources = [];
this._count = 0;
this._settings = new Gio.Settings({
schema_id: 'org.gnome.desktop.notifications',
});
this._settings.connect('changed::show-banners', this._sync.bind(this));
this._settings = new Gio.Settings({
schema_id: "org.gnome.desktop.notifications",
});
this._settings.connect("changed::show-banners", this._sync.bind(this));
this._sourceAddedId = Main.messageTray.connect('source-added', this._onSourceAdded.bind(this));
this._sourceRemovedId = Main.messageTray.connect('source-removed', this._onSourceRemoved.bind(this));
this._queueChangedId = Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
this._sourceAddedId = Main.messageTray.connect(
"source-added",
this._onSourceAdded.bind(this),
);
this._sourceRemovedId = Main.messageTray.connect(
"source-removed",
this._onSourceRemoved.bind(this),
);
this._queueChangedId = Main.messageTray.connect(
"queue-changed",
this._updateCount.bind(this),
);
let sources = Main.messageTray.getSources();
sources.forEach(source => this._onSourceAdded(null, source));
let sources = Main.messageTray.getSources();
sources.forEach((source) => this._onSourceAdded(null, source));
this._sync();
this._sync();
this.connect('destroy', () => {
this._settings.run_dispose();
this._settings = null;
Main.messageTray.disconnect(this._sourceAddedId);
Main.messageTray.disconnect(this._sourceRemovedId);
Main.messageTray.disconnect(this._queueChangedId);
});
}};
this.connect("destroy", () => {
this._settings.run_dispose();
this._settings = null;
Main.messageTray.disconnect(this._sourceAddedId);
Main.messageTray.disconnect(this._sourceRemovedId);
Main.messageTray.disconnect(this._queueChangedId);
});
}
};
MultiMonitors.copyClass(DateMenu.MessagesIndicator, MultiMonitorsMessagesIndicator);
MultiMonitors.copyClass(
DateMenu.MessagesIndicator,
MultiMonitorsMessagesIndicator,
);
return GObject.registerClass(MultiMonitorsMessagesIndicator);
})();
var MultiMonitorsDateMenuButton = (() => {
export var MultiMonitorsDateMenuButton = (() => {
let MultiMonitorsDateMenuButton = class MultiMonitorsDateMenuButton extends PanelMenu.Button {
_init() {
let hbox;
let vbox;
_init() {
let hbox;
let vbox;
super._init(0.5);
super._init(0.5);
this._clockDisplay = new St.Label({ style_class: 'clock' });
this._clockDisplay.clutter_text.y_align = Clutter.ActorAlign.CENTER;
this._clockDisplay.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._clockDisplay = new St.Label({ style_class: "clock" });
this._clockDisplay.clutter_text.y_align = Clutter.ActorAlign.CENTER;
this._clockDisplay.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._indicator = new MultiMonitorsMessagesIndicator();
this._indicator = new MultiMonitorsMessagesIndicator();
const indicatorPad = new St.Widget();
this._indicator.bind_property('visible',
indicatorPad, 'visible',
GObject.BindingFlags.SYNC_CREATE);
indicatorPad.add_constraint(new Clutter.BindConstraint({
source: this._indicator,
coordinate: Clutter.BindCoordinate.SIZE,
}));
const indicatorPad = new St.Widget();
this._indicator.bind_property(
"visible",
indicatorPad,
"visible",
GObject.BindingFlags.SYNC_CREATE,
);
indicatorPad.add_constraint(
new Clutter.BindConstraint({
source: this._indicator,
coordinate: Clutter.BindCoordinate.SIZE,
}),
);
let box = new St.BoxLayout({ style_class: 'clock-display-box' });
box.add_actor(indicatorPad);
box.add_actor(this._clockDisplay);
box.add_actor(this._indicator);
let box = new St.BoxLayout({ style_class: "clock-display-box" });
box.add_actor(indicatorPad);
box.add_actor(this._clockDisplay);
box.add_actor(this._indicator);
this.label_actor = this._clockDisplay;
this.add_actor(box);
this.add_style_class_name('clock-display');
this.label_actor = this._clockDisplay;
this.add_actor(box);
this.add_style_class_name("clock-display");
let layout = new DateMenu.FreezableBinLayout();
let bin = new St.Widget({ layout_manager: layout });
// For some minimal compatibility with PopupMenuItem
bin._delegate = this;
this.menu.box.add_child(bin);
let layout = new DateMenu.FreezableBinLayout();
let bin = new St.Widget({ layout_manager: layout });
// For some minimal compatibility with PopupMenuItem
bin._delegate = this;
this.menu.box.add_child(bin);
hbox = new St.BoxLayout({ name: 'calendarArea' });
bin.add_actor(hbox);
hbox = new St.BoxLayout({ name: "calendarArea" });
bin.add_actor(hbox);
this._calendar = new MultiMonitorsCalendar();
this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
let date = DateMenu._gDateTimeToDate(datetime);
layout.frozen = !DateMenu._isToday(date);
this._eventsItem.setDate(date);
});
this._date = new DateMenu.TodayButton(this._calendar);
this._calendar = new MultiMonitorsCalendar();
this._calendar.connect("selected-date-changed", (_calendar, datetime) => {
let date = DateMenu._gDateTimeToDate(datetime);
layout.frozen = !DateMenu._isToday(date);
this._eventsItem.setDate(date);
});
this._date = new DateMenu.TodayButton(this._calendar);
this.menu.connect('open-state-changed', (menu, isOpen) => {
// Whenever the menu is opened, select today
if (isOpen) {
let now = new Date();
this._calendar.setDate(now);
this._date.setDate(now);
this._eventsItem.setDate(now);
}
});
this.menu.connect("open-state-changed", (menu, isOpen) => {
// Whenever the menu is opened, select today
if (isOpen) {
let now = new Date();
this._calendar.setDate(now);
this._date.setDate(now);
this._eventsItem.setDate(now);
}
});
// Fill up the first column
this._messageList = new MultiMonitorsCalendarMessageList();
hbox.add_child(this._messageList);
// Fill up the first column
this._messageList = new MultiMonitorsCalendarMessageList();
hbox.add_child(this._messageList);
// Fill up the second column
const boxLayout = new DateMenu.CalendarColumnLayout([this._calendar, this._date]);
vbox = new St.Widget({ style_class: 'datemenu-calendar-column',
layout_manager: boxLayout });
boxLayout.hookup_style(vbox);
hbox.add(vbox);
// Fill up the second column
const boxLayout = new DateMenu.CalendarColumnLayout([
this._calendar,
this._date,
]);
vbox = new St.Widget({
style_class: "datemenu-calendar-column",
layout_manager: boxLayout,
});
boxLayout.hookup_style(vbox);
hbox.add(vbox);
vbox.add_actor(this._date);
vbox.add_actor(this._calendar);
vbox.add_actor(this._date);
vbox.add_actor(this._calendar);
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
x_expand: true,
overlay_scrollbars: true });
this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
vbox.add_actor(this._displaysSection);
this._displaysSection = new St.ScrollView({
style_class: "datemenu-displays-section vfade",
x_expand: true,
overlay_scrollbars: true,
});
this._displaysSection.set_policy(
St.PolicyType.NEVER,
St.PolicyType.EXTERNAL,
);
vbox.add_actor(this._displaysSection);
let displaysBox = new St.BoxLayout({ vertical: true,
x_expand: true,
style_class: 'datemenu-displays-box' });
this._displaysSection.add_actor(displaysBox);
let displaysBox = new St.BoxLayout({
vertical: true,
x_expand: true,
style_class: "datemenu-displays-box",
});
this._displaysSection.add_actor(displaysBox);
this._eventsItem = new MultiMonitorsEventsSection();
displaysBox.add_child(this._eventsItem);
this._eventsItem = new MultiMonitorsEventsSection();
displaysBox.add_child(this._eventsItem);
this._clock = new GnomeDesktop.WallClock();
this._clock.bind_property('clock', this._clockDisplay, 'text', GObject.BindingFlags.SYNC_CREATE);
this._clockNotifyTimezoneId = this._clock.connect('notify::timezone', this._updateTimeZone.bind(this));
this._clock = new GnomeDesktop.WallClock();
this._clock.bind_property(
"clock",
this._clockDisplay,
"text",
GObject.BindingFlags.SYNC_CREATE,
);
this._clockNotifyTimezoneId = this._clock.connect(
"notify::timezone",
this._updateTimeZone.bind(this),
);
this._sessionModeUpdatedId = Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
}
this._sessionModeUpdatedId = Main.sessionMode.connect(
"updated",
this._sessionUpdated.bind(this),
);
this._sessionUpdated();
}
_onDestroy() {
Main.sessionMode.disconnect(this._sessionModeUpdatedId);
this._clock.disconnect(this._clockNotifyTimezoneId);
super._onDestroy();
}};
_onDestroy() {
Main.sessionMode.disconnect(this._sessionModeUpdatedId);
this._clock.disconnect(this._clockNotifyTimezoneId);
super._onDestroy();
}
};
MultiMonitors.copyClass(DateMenu.DateMenuButton, MultiMonitorsDateMenuButton);
return GObject.registerClass(MultiMonitorsDateMenuButton);
})();

View File

@@ -2,142 +2,166 @@
* New node file
*/
const { St, Meta } = imports.gi;
import St from "gi://St";
import Meta from "gi://Meta";
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Layout = imports.ui.layout;
import * as Main from "resource:///org/gnome/shell/ui/main.js";
import * as Panel from "resource:///org/gnome/shell/ui/panel.js";
import * as Layout from "resource:///org/gnome/shell/ui/layout.js";
const Config = imports.misc.config;
import * as Config from "resource:///org/gnome/shell/misc/config.js";
const ExtensionUtils = imports.misc.extensionUtils;
const CE = ExtensionUtils.getCurrentExtension();
const Convenience = CE.imports.convenience;
const MultiMonitors = CE.imports.extension;
const MMPanel = CE.imports.mmpanel;
import {
Extension,
gettext as _,
} from "resource:///org/gnome/shell/extensions/extension.js";
import * as Convenience from "./convenience.js";
import * as MultiMonitors from "./extension.js";
import * as MMPanel from "./mmpanel.js";
var SHOW_PANEL_ID = 'show-panel';
var ENABLE_HOT_CORNERS = 'enable-hot-corners';
var SHOW_PANEL_ID = "show-panel";
var ENABLE_HOT_CORNERS = "enable-hot-corners";
const MultiMonitorsPanelBox = class MultiMonitorsPanelBox {
constructor(monitor) {
this.panelBox = new St.BoxLayout({ name: 'panelBox', vertical: true, clip_to_allocation: true });
Main.layoutManager.addChrome(this.panelBox, { affectsStruts: true, trackFullscreen: true });
this.panelBox.set_position(monitor.x, monitor.y);
this.panelBox.set_size(monitor.width, -1);
Main.uiGroup.set_child_below_sibling(this.panelBox, Main.layoutManager.panelBox);
}
export const MultiMonitorsPanelBox = class MultiMonitorsPanelBox {
constructor(monitor) {
this.panelBox = new St.BoxLayout({
name: "panelBox",
vertical: true,
clip_to_allocation: true,
});
Main.layoutManager.addChrome(this.panelBox, {
affectsStruts: true,
trackFullscreen: true,
});
this.panelBox.set_position(monitor.x, monitor.y);
this.panelBox.set_size(monitor.width, -1);
Main.uiGroup.set_child_below_sibling(
this.panelBox,
Main.layoutManager.panelBox,
);
}
destroy() {
this.panelBox.destroy();
}
destroy() {
this.panelBox.destroy();
}
updatePanel(monitor) {
this.panelBox.set_position(monitor.x, monitor.y);
this.panelBox.set_size(monitor.width, -1);
}
updatePanel(monitor) {
this.panelBox.set_position(monitor.x, monitor.y);
this.panelBox.set_size(monitor.width, -1);
}
};
var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
export const class MultiMonitorsLayoutManager {
constructor() {
this._settings = Convenience.getSettings();
this._desktopSettings = Convenience.getSettings("org.gnome.desktop.interface");
this._desktopSettings = Convenience.getSettings(
"org.gnome.desktop.interface",
);
Main.mmPanel = [];
this._monitorIds = [];
this.mmPanelBox = [];
this.mmappMenu = false;
this._showAppMenuId = null;
this._monitorsChangedId = null;
this.statusIndicatorsController = null;
this._layoutManager_updateHotCorners = null;
this._changedEnableHotCornersId = null;
}
showPanel() {
if (this._settings.get_boolean(SHOW_PANEL_ID)) {
if (!this._monitorsChangedId) {
this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', this._monitorsChanged.bind(this));
this._monitorsChanged();
}
if (!this._showAppMenuId) {
this._showAppMenuId = this._settings.connect('changed::'+MMPanel.SHOW_APP_MENU_ID, this._showAppMenu.bind(this));
}
showPanel() {
if (this._settings.get_boolean(SHOW_PANEL_ID)) {
if (!this._monitorsChangedId) {
this._monitorsChangedId = Main.layoutManager.connect(
"monitors-changed",
this._monitorsChanged.bind(this),
);
this._monitorsChanged();
}
if (!this._showAppMenuId) {
this._showAppMenuId = this._settings.connect(
"changed::" + MMPanel.SHOW_APP_MENU_ID,
this._showAppMenu.bind(this),
);
}
if (!this.statusIndicatorsController) {
this.statusIndicatorsController = new MMPanel.StatusIndicatorsController();
}
if (!this.statusIndicatorsController) {
this.statusIndicatorsController =
new MMPanel.StatusIndicatorsController();
}
if (!this._layoutManager_updateHotCorners) {
this._layoutManager_updateHotCorners = Main.layoutManager._updateHotCorners;
if (!this._layoutManager_updateHotCorners) {
this._layoutManager_updateHotCorners =
Main.layoutManager._updateHotCorners;
const _this = this;
Main.layoutManager._updateHotCorners = function() {
this.hotCorners.forEach((corner) => {
if (corner)
corner.destroy();
});
this.hotCorners = [];
const _this = this;
Main.layoutManager._updateHotCorners = function () {
this.hotCorners.forEach((corner) => {
if (corner) corner.destroy();
});
this.hotCorners = [];
if (!_this._desktopSettings.get_boolean(ENABLE_HOT_CORNERS)) {
this.emit('hot-corners-changed');
return;
}
if (!_this._desktopSettings.get_boolean(ENABLE_HOT_CORNERS)) {
this.emit("hot-corners-changed");
return;
}
let size = this.panelBox.height;
let size = this.panelBox.height;
for (let i = 0; i < this.monitors.length; i++) {
let monitor = this.monitors[i];
let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
let cornerY = monitor.y;
for (let i = 0; i < this.monitors.length; i++) {
let monitor = this.monitors[i];
let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
let cornerY = monitor.y;
let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY);
corner.setBarrierSize(size);
this.hotCorners.push(corner);
}
let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY);
corner.setBarrierSize(size);
this.hotCorners.push(corner);
}
this.emit('hot-corners-changed');
};
this.emit("hot-corners-changed");
};
if (!this._changedEnableHotCornersId) {
this._changedEnableHotCornersId = this._desktopSettings.connect('changed::'+ENABLE_HOT_CORNERS,
Main.layoutManager._updateHotCorners.bind(Main.layoutManager));
}
if (!this._changedEnableHotCornersId) {
this._changedEnableHotCornersId = this._desktopSettings.connect(
"changed::" + ENABLE_HOT_CORNERS,
Main.layoutManager._updateHotCorners.bind(Main.layoutManager),
);
}
Main.layoutManager._updateHotCorners();
}
}
else {
this.hidePanel();
}
}
Main.layoutManager._updateHotCorners();
}
} else {
this.hidePanel();
}
}
hidePanel() {
if (this._changedEnableHotCornersId) {
global.settings.disconnect(this._changedEnableHotCornersId);
this._changedEnableHotCornersId = null;
}
if (this._layoutManager_updateHotCorners) {
Main.layoutManager['_updateHotCorners'] = this._layoutManager_updateHotCorners;
Main.layoutManager["_updateHotCorners"] =
this._layoutManager_updateHotCorners;
this._layoutManager_updateHotCorners = null;
Main.layoutManager._updateHotCorners();
}
if (this.statusIndicatorsController) {
this.statusIndicatorsController.destroy();
this.statusIndicatorsController = null;
}
if (this._showAppMenuId) {
this._settings.disconnect(this._showAppMenuId);
this._showAppMenuId = null;
}
this._hideAppMenu();
if (this._monitorsChangedId) {
Main.layoutManager.disconnect(this._monitorsChangedId);
this._monitorsChangedId = null;
@@ -147,37 +171,50 @@ var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
for (let i = 0; i < panels2remove; i++) {
let monitorId = this._monitorIds.pop();
this._popPanel();
global.log("remove: "+monitorId);
global.log("remove: " + monitorId);
}
}
_monitorsChanged () {
let monitorChange = Main.layoutManager.monitors.length - this._monitorIds.length -1;
if (monitorChange<0) {
for (let idx = 0; idx<-monitorChange; idx++) {
_monitorsChanged() {
let monitorChange =
Main.layoutManager.monitors.length - this._monitorIds.length - 1;
if (monitorChange < 0) {
for (let idx = 0; idx < -monitorChange; idx++) {
let monitorId = this._monitorIds.pop();
this._popPanel();
global.log("remove: "+monitorId);
global.log("remove: " + monitorId);
}
}
let j = 0;
let tIndicators = false;
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
if (i!=Main.layoutManager.primaryIndex) {
if (i != Main.layoutManager.primaryIndex) {
let monitor = Main.layoutManager.monitors[i];
let monitorId = "i"+i+"x"+monitor.x+"y"+monitor.y+"w"+monitor.width+"h"+monitor.height;
if (monitorChange>0 && j==this._monitorIds.length) {
let monitorId =
"i" +
i +
"x" +
monitor.x +
"y" +
monitor.y +
"w" +
monitor.width +
"h" +
monitor.height;
if (monitorChange > 0 && j == this._monitorIds.length) {
this._monitorIds.push(monitorId);
this._pushPanel(i, monitor);
global.log("new: "+monitorId);
global.log("new: " + monitorId);
tIndicators = true;
}
else if (this._monitorIds[j]>monitorId || this._monitorIds[j]<monitorId) {
} else if (
this._monitorIds[j] > monitorId ||
this._monitorIds[j] < monitorId
) {
let oldMonitorId = this._monitorIds[j];
this._monitorIds[j]=monitorId;
this._monitorIds[j] = monitorId;
this.mmPanelBox[j].updatePanel(monitor);
global.log("update: "+oldMonitorId+">"+monitorId);
global.log("update: " + oldMonitorId + ">" + monitorId);
}
j++;
}
@@ -191,7 +228,7 @@ var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
_pushPanel(i, monitor) {
let mmPanelBox = new MultiMonitorsPanelBox(monitor);
let panel = new MMPanel.MultiMonitorsPanel(i, mmPanelBox);
Main.mmPanel.push(panel);
this.mmPanelBox.push(mmPanelBox);
}
@@ -203,7 +240,7 @@ var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
}
let mmPanelBox = this.mmPanelBox.pop();
mmPanelBox.destroy();
}
}
_changeMainPanelAppMenuButton(appMenuButton) {
let role = "appMenu";
@@ -214,29 +251,31 @@ var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
if (indicator._actionGroupNotifyId) {
indicator._targetApp.disconnect(indicator._actionGroupNotifyId);
indicator._actionGroupNotifyId = 0;
}
if (indicator._busyNotifyId) {
indicator._targetApp.disconnect(indicator._busyNotifyId);
indicator._busyNotifyId = 0;
}
if (indicator.menu._windowsChangedId) {
indicator.menu._app.disconnect(indicator.menu._windowsChangedId);
indicator.menu._windowsChangedId = 0;
}
}
if (indicator._busyNotifyId) {
indicator._targetApp.disconnect(indicator._busyNotifyId);
indicator._busyNotifyId = 0;
}
if (indicator.menu._windowsChangedId) {
indicator.menu._app.disconnect(indicator.menu._windowsChangedId);
indicator.menu._windowsChangedId = 0;
}
indicator = new appMenuButton(panel);
panel.statusArea[role] = indicator;
let box = panel._leftBox;
panel._addToPanelBox(role, indicator, box.get_n_children()+1, box);
panel._addToPanelBox(role, indicator, box.get_n_children() + 1, box);
}
_showAppMenu() {
if (this._settings.get_boolean(MMPanel.SHOW_APP_MENU_ID) && Main.mmPanel.length>0) {
if (
this._settings.get_boolean(MMPanel.SHOW_APP_MENU_ID) &&
Main.mmPanel.length > 0
) {
if (!this.mmappMenu) {
this._changeMainPanelAppMenuButton(MMPanel.MultiMonitorsAppMenuButton);
this.mmappMenu = true;
}
}
else {
} else {
this._hideAppMenu();
}
}
@@ -245,7 +284,7 @@ var MultiMonitorsLayoutManager = class MultiMonitorsLayoutManager {
if (this.mmappMenu) {
this._changeMainPanelAppMenuButton(Panel.AppMenuButton);
this.mmappMenu = false;
Main.panel._updatePanel()
}
Main.panel._updatePanel();
}
}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,83 +15,98 @@ You should have received a copy of the GNU General Public License
along with this program; if not, visit https://www.gnu.org/licenses/.
*/
const { St, Shell, Meta, Atk, Clutter, GObject } = imports.gi;
import St from "gi://St";
import Shell from "gi://Shell";
import Meta from "gi://Meta";
import Atk from "gi://Atk";
import Clutter from "gi://Clutter";
import GObject from "gi://GObject";
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const CtrlAltTab = imports.ui.ctrlAltTab;
const ExtensionSystem = imports.ui.extensionSystem;
import * as Main from "resource:///org/gnome/shell/ui/main.js";
import * as Panel from "resource:///org/gnome/shell/ui/panel.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 CtrlAltTab from "resource:///org/gnome/shell/ui/ctrlAltTab.js";
import * as ExtensionSystem from "resource:///org/gnome/shell/ui/extensionSystem.js";
const ExtensionUtils = imports.misc.extensionUtils;
const CE = ExtensionUtils.getCurrentExtension();
const MultiMonitors = CE.imports.extension;
const Convenience = CE.imports.convenience;
const MMCalendar = CE.imports.mmcalendar;
import * as MultiMonitors from "./extension.js";
import * as Convenience from "./convenience.js";
import * as MMCalendar from "./mmcalendar.js";
const SHOW_ACTIVITIES_ID = 'show-activities';
var SHOW_APP_MENU_ID = 'show-app-menu';
const SHOW_DATE_TIME_ID = 'show-date-time';
const AVAILABLE_INDICATORS_ID = 'available-indicators';
const TRANSFER_INDICATORS_ID = 'transfer-indicators';
const SHOW_ACTIVITIES_ID = "show-activities";
var SHOW_APP_MENU_ID = "show-app-menu";
const SHOW_DATE_TIME_ID = "show-date-time";
const AVAILABLE_INDICATORS_ID = "available-indicators";
const TRANSFER_INDICATORS_ID = "transfer-indicators";
var StatusIndicatorsController = class StatusIndicatorsController {
constructor() {
this._transfered_indicators = [];
this._settings = Convenience.getSettings();
export var StatusIndicatorsController = class StatusIndicatorsController {
constructor() {
this._transfered_indicators = [];
this._settings = Convenience.getSettings();
this._updatedSessionId = Main.sessionMode.connect('updated', this._updateSessionIndicators.bind(this));
this._updateSessionIndicators();
this._extensionStateChangedId = Main.extensionManager.connect('extension-state-changed',
this._extensionStateChanged.bind(this));
this._updatedSessionId = Main.sessionMode.connect(
"updated",
this._updateSessionIndicators.bind(this),
);
this._updateSessionIndicators();
this._extensionStateChangedId = Main.extensionManager.connect(
"extension-state-changed",
this._extensionStateChanged.bind(this),
);
this._transferIndicatorsId = this._settings.connect('changed::'+TRANSFER_INDICATORS_ID,
this.transferIndicators.bind(this));
}
this._transferIndicatorsId = this._settings.connect(
"changed::" + TRANSFER_INDICATORS_ID,
this.transferIndicators.bind(this),
);
}
destroy() {
this._settings.disconnect(this._transferIndicatorsId);
Main.extensionManager.disconnect(this._extensionStateChangedId);
Main.sessionMode.disconnect(this._updatedSessionId);
this._settings.set_strv(AVAILABLE_INDICATORS_ID, []);
this._transferBack(this._transfered_indicators);
}
destroy() {
this._settings.disconnect(this._transferIndicatorsId);
Main.extensionManager.disconnect(this._extensionStateChangedId);
Main.sessionMode.disconnect(this._updatedSessionId);
this._settings.set_strv(AVAILABLE_INDICATORS_ID, []);
this._transferBack(this._transfered_indicators);
}
transferBack(panel) {
let transfer_back = this._transfered_indicators.filter((element) => {
return element.monitor==panel.monitorIndex;
return element.monitor == panel.monitorIndex;
});
this._transferBack(transfer_back, panel);
}
transferIndicators() {
let boxs = ['_leftBox', '_centerBox', '_rightBox'];
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
let show_app_menu = this._settings.get_value(SHOW_APP_MENU_ID);
let transfer_back = this._transfered_indicators.filter((element) => {
return !transfers.hasOwnProperty(element.iname);
let boxs = ["_leftBox", "_centerBox", "_rightBox"];
let transfers = this._settings
.get_value(TRANSFER_INDICATORS_ID)
.deep_unpack();
let show_app_menu = this._settings.get_value(SHOW_APP_MENU_ID);
let transfer_back = this._transfered_indicators.filter((element) => {
return !transfers.hasOwnProperty(element.iname);
});
this._transferBack(transfer_back);
for(let iname in transfers) {
if(transfers.hasOwnProperty(iname) && Main.panel.statusArea[iname]) {
this._transferBack(transfer_back);
for (let iname in transfers) {
if (transfers.hasOwnProperty(iname) && Main.panel.statusArea[iname]) {
let monitor = transfers[iname];
let indicator = Main.panel.statusArea[iname];
let panel = this._findPanel(monitor);
boxs.forEach((box) => {
if(Main.panel[box].contains(indicator.container) && panel) {
global.log('a '+box+ " > " + iname + " : "+ monitor);
this._transfered_indicators.push({iname:iname, box:box, monitor:monitor});
if (Main.panel[box].contains(indicator.container) && panel) {
global.log("a " + box + " > " + iname + " : " + monitor);
this._transfered_indicators.push({
iname: iname,
box: box,
monitor: monitor,
});
Main.panel[box].remove_child(indicator.container);
if (show_app_menu && box === '_leftBox')
if (show_app_menu && box === "_leftBox")
panel[box].insert_child_at_index(indicator.container, 1);
else
panel[box].insert_child_at_index(indicator.container, 0);
else panel[box].insert_child_at_index(indicator.container, 0);
}
});
}
@@ -108,20 +123,35 @@ var StatusIndicatorsController = class StatusIndicatorsController {
}
_transferBack(transfer_back, panel) {
transfer_back.forEach((element) => {
this._transfered_indicators.splice(this._transfered_indicators.indexOf(element));
if(Main.panel.statusArea[element.iname]) {
transfer_back.forEach((element) => {
this._transfered_indicators.splice(
this._transfered_indicators.indexOf(element),
);
if (Main.panel.statusArea[element.iname]) {
let indicator = Main.panel.statusArea[element.iname];
if(!panel) {
if (!panel) {
panel = this._findPanel(element.monitor);
}
if(panel[element.box].contains(indicator.container)) {
global.log("r "+element.box+ " > " + element.iname + " : "+ element.monitor);
panel[element.box].remove_child(indicator.container);
if (element.box === '_leftBox')
Main.panel[element.box].insert_child_at_index(indicator.container, 1);
else
Main.panel[element.box].insert_child_at_index(indicator.container, 0);
if (panel[element.box].contains(indicator.container)) {
global.log(
"r " +
element.box +
" > " +
element.iname +
" : " +
element.monitor,
);
panel[element.box].remove_child(indicator.container);
if (element.box === "_leftBox")
Main.panel[element.box].insert_child_at_index(
indicator.container,
1,
);
else
Main.panel[element.box].insert_child_at_index(
indicator.container,
0,
);
}
}
});
@@ -129,392 +159,423 @@ var StatusIndicatorsController = class StatusIndicatorsController {
_extensionStateChanged() {
this._findAvailableIndicators();
this.transferIndicators();
this.transferIndicators();
}
_updateSessionIndicators() {
let session_indicators = [];
session_indicators.push('MultiMonitorsAddOn');
let sessionPanel = Main.sessionMode.panel;
for (let sessionBox in sessionPanel){
sessionPanel[sessionBox].forEach((sesionIndicator) => {
session_indicators.push(sesionIndicator);
});
}
this._session_indicators = session_indicators;
let session_indicators = [];
session_indicators.push("MultiMonitorsAddOn");
let sessionPanel = Main.sessionMode.panel;
for (let sessionBox in sessionPanel) {
sessionPanel[sessionBox].forEach((sesionIndicator) => {
session_indicators.push(sesionIndicator);
});
}
this._session_indicators = session_indicators;
this._available_indicators = [];
this._findAvailableIndicators();
this.transferIndicators();
this._findAvailableIndicators();
this.transferIndicators();
}
_findAvailableIndicators() {
_findAvailableIndicators() {
let available_indicators = [];
let statusArea = Main.panel.statusArea;
for(let indicator in statusArea) {
if(statusArea.hasOwnProperty(indicator) && this._session_indicators.indexOf(indicator)<0){
for (let indicator in statusArea) {
if (
statusArea.hasOwnProperty(indicator) &&
this._session_indicators.indexOf(indicator) < 0
) {
available_indicators.push(indicator);
}
}
if(available_indicators.length!=this._available_indicators.length) {
if (available_indicators.length != this._available_indicators.length) {
this._available_indicators = available_indicators;
// global.log(this._available_indicators);
this._settings.set_strv(AVAILABLE_INDICATORS_ID, this._available_indicators);
// global.log(this._available_indicators);
this._settings.set_strv(
AVAILABLE_INDICATORS_ID,
this._available_indicators,
);
}
}
};
var MultiMonitorsAppMenuButton = (() => {
export var MultiMonitorsAppMenuButton = (() => {
let MultiMonitorsAppMenuButton = class MultiMonitorsAppMenuButton extends PanelMenu.Button {
_init(panel) {
if (panel.monitorIndex==undefined)
this._monitorIndex = Main.layoutManager.primaryIndex;
else
this._monitorIndex = panel.monitorIndex;
this._actionOnWorkspaceGroupNotifyId = 0;
this._targetAppGroup = null;
this._lastFocusedWindow = null;
Panel.AppMenuButton.prototype._init.call(this, panel);
_init(panel) {
if (panel.monitorIndex == undefined)
this._monitorIndex = Main.layoutManager.primaryIndex;
else this._monitorIndex = panel.monitorIndex;
this._actionOnWorkspaceGroupNotifyId = 0;
this._targetAppGroup = null;
this._lastFocusedWindow = null;
Panel.AppMenuButton.prototype._init.call(this, panel);
this._windowEnteredMonitorId = global.display.connect('window-entered-monitor',
this._windowEnteredMonitor.bind(this));
this._windowLeftMonitorId = global.display.connect('window-left-monitor',
this._windowLeftMonitor.bind(this));
}
_windowEnteredMonitor (metaScreen, monitorIndex, metaWin) {
if (monitorIndex == this._monitorIndex) {
switch(metaWin.get_window_type()){
case Meta.WindowType.NORMAL:
case Meta.WindowType.DIALOG:
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.SPLASHSCREEN:
this._sync();
break;
}
}
}
_windowLeftMonitor (metaScreen, monitorIndex, metaWin) {
if (monitorIndex == this._monitorIndex) {
switch(metaWin.get_window_type()){
case Meta.WindowType.NORMAL:
case Meta.WindowType.DIALOG:
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.SPLASHSCREEN:
this._sync();
break;
}
}
}
_findTargetApp() {
if (this._actionOnWorkspaceGroupNotifyId) {
this._targetAppGroup.disconnect(this._actionOnWorkspaceGroupNotifyId);
this._actionOnWorkspaceGroupNotifyId = 0;
this._targetAppGroup = null;
}
let groupWindow = false;
let groupFocus = false;
let workspaceManager = global.workspace_manager;
let workspace = workspaceManager.get_active_workspace();
let tracker = Shell.WindowTracker.get_default();
let focusedApp = tracker.focus_app;
if (focusedApp && focusedApp.is_on_workspace(workspace)){
let windows = focusedApp.get_windows();
for (let i = 0; i < windows.length; i++) {
let win = windows[i];
if (win.located_on_workspace(workspace)){
if (win.get_monitor() == this._monitorIndex){
if (win.has_focus()){
this._lastFocusedWindow = win;
// global.log(this._monitorIndex+": focus :"+win.get_title()+" : "+win.has_focus());
return focusedApp;
}
else
groupWindow = true;
}
else {
if(win.has_focus())
groupFocus = true;
}
if (groupFocus && groupWindow) {
if(focusedApp != this._targetApp){
this._targetAppGroup = focusedApp;
this._actionOnWorkspaceGroupNotifyId = this._targetAppGroup.connect('notify::action-group',
this._sync.bind(this));
// global.log(this._monitorIndex+": gConnect :"+win.get_title()+" : "+win.has_focus());
this._windowEnteredMonitorId = global.display.connect(
"window-entered-monitor",
this._windowEnteredMonitor.bind(this),
);
this._windowLeftMonitorId = global.display.connect(
"window-left-monitor",
this._windowLeftMonitor.bind(this),
);
}
_windowEnteredMonitor(metaScreen, monitorIndex, metaWin) {
if (monitorIndex == this._monitorIndex) {
switch (metaWin.get_window_type()) {
case Meta.WindowType.NORMAL:
case Meta.WindowType.DIALOG:
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.SPLASHSCREEN:
this._sync();
break;
}
}
}
_windowLeftMonitor(metaScreen, monitorIndex, metaWin) {
if (monitorIndex == this._monitorIndex) {
switch (metaWin.get_window_type()) {
case Meta.WindowType.NORMAL:
case Meta.WindowType.DIALOG:
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.SPLASHSCREEN:
this._sync();
break;
}
}
}
_findTargetApp() {
if (this._actionOnWorkspaceGroupNotifyId) {
this._targetAppGroup.disconnect(this._actionOnWorkspaceGroupNotifyId);
this._actionOnWorkspaceGroupNotifyId = 0;
this._targetAppGroup = null;
}
let groupWindow = false;
let groupFocus = false;
let workspaceManager = global.workspace_manager;
let workspace = workspaceManager.get_active_workspace();
let tracker = Shell.WindowTracker.get_default();
let focusedApp = tracker.focus_app;
if (focusedApp && focusedApp.is_on_workspace(workspace)) {
let windows = focusedApp.get_windows();
for (let i = 0; i < windows.length; i++) {
let win = windows[i];
if (win.located_on_workspace(workspace)) {
if (win.get_monitor() == this._monitorIndex) {
if (win.has_focus()) {
this._lastFocusedWindow = win;
// global.log(this._monitorIndex+": focus :"+win.get_title()+" : "+win.has_focus());
return focusedApp;
} else groupWindow = true;
} else {
if (win.has_focus()) groupFocus = true;
}
if (groupFocus && groupWindow) {
if (focusedApp != this._targetApp) {
this._targetAppGroup = focusedApp;
this._actionOnWorkspaceGroupNotifyId =
this._targetAppGroup.connect(
"notify::action-group",
this._sync.bind(this),
);
// global.log(this._monitorIndex+": gConnect :"+win.get_title()+" : "+win.has_focus());
}
break;
}
}
}
}
for (let i = 0; i < this._startingApps.length; i++)
if (this._startingApps[i].is_on_workspace(workspace)){
// global.log(this._monitorIndex+": newAppFocus");
return this._startingApps[i];
}
if (this._lastFocusedWindow && this._lastFocusedWindow.located_on_workspace(workspace) &&
this._lastFocusedWindow.get_monitor() == this._monitorIndex){
// global.log(this._monitorIndex+": lastFocus :"+this._lastFocusedWindow.get_title());
return tracker.get_window_app(this._lastFocusedWindow);
}
let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, workspace);
for (let i = 0; i < windows.length; i++) {
if(windows[i].get_monitor() == this._monitorIndex){
this._lastFocusedWindow = windows[i];
// global.log(this._monitorIndex+": appFind :"+windows[i].get_title());
return tracker.get_window_app(windows[i]);
}
}
return null;
}
_sync() {
if (!this._switchWorkspaceNotifyId)
return;
Panel.AppMenuButton.prototype._sync.call(this);
}
_onDestroy() {
if (this._actionGroupNotifyId) {
this._targetApp.disconnect(this._actionGroupNotifyId);
this._actionGroupNotifyId = 0;
}
break;
}
}
}
}
global.display.disconnect(this._windowEnteredMonitorId);
global.display.disconnect(this._windowLeftMonitorId);
if (this._busyNotifyId) {
this._targetApp.disconnect(this._busyNotifyId);
this._busyNotifyId = 0;
}
if (this.menu._windowsChangedId) {
this.menu._app.disconnect(this.menu._windowsChangedId);
this.menu._windowsChangedId = 0;
}
Panel.AppMenuButton.prototype._onDestroy.call(this);
for (let i = 0; i < this._startingApps.length; i++)
if (this._startingApps[i].is_on_workspace(workspace)) {
// global.log(this._monitorIndex+": newAppFocus");
return this._startingApps[i];
}
if (
this._lastFocusedWindow &&
this._lastFocusedWindow.located_on_workspace(workspace) &&
this._lastFocusedWindow.get_monitor() == this._monitorIndex
) {
// global.log(this._monitorIndex+": lastFocus :"+this._lastFocusedWindow.get_title());
return tracker.get_window_app(this._lastFocusedWindow);
}
let windows = global.display.get_tab_list(
Meta.TabList.NORMAL_ALL,
workspace,
);
for (let i = 0; i < windows.length; i++) {
if (windows[i].get_monitor() == this._monitorIndex) {
this._lastFocusedWindow = windows[i];
// global.log(this._monitorIndex+": appFind :"+windows[i].get_title());
return tracker.get_window_app(windows[i]);
}
}
return null;
}
_sync() {
if (!this._switchWorkspaceNotifyId) return;
Panel.AppMenuButton.prototype._sync.call(this);
}
_onDestroy() {
if (this._actionGroupNotifyId) {
this._targetApp.disconnect(this._actionGroupNotifyId);
this._actionGroupNotifyId = 0;
}
global.display.disconnect(this._windowEnteredMonitorId);
global.display.disconnect(this._windowLeftMonitorId);
if (this._busyNotifyId) {
this._targetApp.disconnect(this._busyNotifyId);
this._busyNotifyId = 0;
}
if (this.menu._windowsChangedId) {
this.menu._app.disconnect(this.menu._windowsChangedId);
this.menu._windowsChangedId = 0;
}
Panel.AppMenuButton.prototype._onDestroy.call(this);
}
};
MultiMonitors.copyClass(Panel.AppMenuButton, MultiMonitorsAppMenuButton);
return GObject.registerClass({Signals: {'changed': {}},}, MultiMonitorsAppMenuButton);
return GObject.registerClass(
{ Signals: { changed: {} } },
MultiMonitorsAppMenuButton,
);
})();
var MultiMonitorsActivitiesButton = (() => {
let MultiMonitorsActivitiesButton = class MultiMonitorsActivitiesButton extends PanelMenu.Button {
_init() {
super._init(0.0, null, true);
this.accessible_role = Atk.Role.TOGGLE_BUTTON;
let MultiMonitorsActivitiesButton = class MultiMonitorsActivitiesButton extends PanelMenu.Button {
_init() {
super._init(0.0, null, true);
this.accessible_role = Atk.Role.TOGGLE_BUTTON;
this.name = 'mmPanelActivities';
this.name = "mmPanelActivities";
/* Translators: If there is no suitable word for "Activities"
in your language, you can use the word for "Overview". */
this._label = new St.Label({ text: _("Activities"),
y_align: Clutter.ActorAlign.CENTER });
this.add_actor(this._label);
/* Translators: If there is no suitable word for "Activities"
in your language, you can use the word for "Overview". */
this._label = new St.Label({
text: _("Activities"),
y_align: Clutter.ActorAlign.CENTER,
});
this.add_actor(this._label);
this.label_actor = this._label;
this.label_actor = this._label;
this._showingId = Main.overview.connect('showing', () => {
this.add_style_pseudo_class('overview');
this.add_accessible_state (Atk.StateType.CHECKED);
});
this._hidingId = Main.overview.connect('hiding', () => {
this.remove_style_pseudo_class('overview');
this.remove_accessible_state (Atk.StateType.CHECKED);
});
this._xdndTimeOut = 0;
}
this._showingId = Main.overview.connect("showing", () => {
this.add_style_pseudo_class("overview");
this.add_accessible_state(Atk.StateType.CHECKED);
});
this._hidingId = Main.overview.connect("hiding", () => {
this.remove_style_pseudo_class("overview");
this.remove_accessible_state(Atk.StateType.CHECKED);
});
_onDestroy() {
Main.overview.disconnect(this._showingId);
Main.overview.disconnect(this._hidingId);
super._onDestroy();
}
}
MultiMonitors.copyClass(Panel.ActivitiesButton, MultiMonitorsActivitiesButton);
return GObject.registerClass(MultiMonitorsActivitiesButton);
this._xdndTimeOut = 0;
}
_onDestroy() {
Main.overview.disconnect(this._showingId);
Main.overview.disconnect(this._hidingId);
super._onDestroy();
}
};
MultiMonitors.copyClass(
Panel.ActivitiesButton,
MultiMonitorsActivitiesButton,
);
return GObject.registerClass(MultiMonitorsActivitiesButton);
})();
const MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS = {
'activities': MultiMonitorsActivitiesButton,
'appMenu': MultiMonitorsAppMenuButton,
'dateMenu': MMCalendar.MultiMonitorsDateMenuButton,
activities: MultiMonitorsActivitiesButton,
appMenu: MultiMonitorsAppMenuButton,
dateMenu: MMCalendar.MultiMonitorsDateMenuButton,
};
var MultiMonitorsPanel = (() => {
let MultiMonitorsPanel = class MultiMonitorsPanel extends St.Widget {
_init(monitorIndex, mmPanelBox) {
super._init({ name: 'panel',
reactive: true });
export const MultiMonitorsPanel = (() => {
let MultiMonitorsPanel = class MultiMonitorsPanel extends St.Widget {
_init(monitorIndex, mmPanelBox) {
super._init({ name: "panel", reactive: true });
this.monitorIndex = monitorIndex;
this.monitorIndex = monitorIndex;
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._sessionStyle = null;
this._sessionStyle = null;
this.statusArea = {};
this.statusArea = {};
this.menuManager = new PopupMenu.PopupMenuManager(this);
this.menuManager = new PopupMenu.PopupMenuManager(this);
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this.add_child(this._leftBox);
this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this.add_child(this._centerBox);
this._rightBox = new St.BoxLayout({ name: 'panelRight' });
this.add_child(this._rightBox);
this._leftBox = new St.BoxLayout({ name: "panelLeft" });
this.add_child(this._leftBox);
this._centerBox = new St.BoxLayout({ name: "panelCenter" });
this.add_child(this._centerBox);
this._rightBox = new St.BoxLayout({ name: "panelRight" });
this.add_child(this._rightBox);
this._showingId = Main.overview.connect('showing', () => {
this.add_style_pseudo_class('overview');
});
this._hidingId = Main.overview.connect('hiding', () => {
this.remove_style_pseudo_class('overview');
});
this._showingId = Main.overview.connect("showing", () => {
this.add_style_pseudo_class("overview");
});
this._hidingId = Main.overview.connect("hiding", () => {
this.remove_style_pseudo_class("overview");
});
mmPanelBox.panelBox.add(this);
Main.ctrlAltTabManager.addGroup(this, _("Top Bar"), 'focus-top-bar-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP });
mmPanelBox.panelBox.add(this);
Main.ctrlAltTabManager.addGroup(
this,
_("Top Bar"),
"focus-top-bar-symbolic",
{ sortGroup: CtrlAltTab.SortGroup.TOP },
);
this._updatedId = Main.sessionMode.connect('updated', this._updatePanel.bind(this));
this._updatedId = Main.sessionMode.connect(
"updated",
this._updatePanel.bind(this),
);
this._workareasChangedId = global.display.connect('workareas-changed', () => this.queue_relayout());
this._updatePanel();
this._workareasChangedId = global.display.connect(
"workareas-changed",
() => this.queue_relayout(),
);
this._updatePanel();
this._settings = Convenience.getSettings();
this._showActivitiesId = this._settings.connect('changed::'+SHOW_ACTIVITIES_ID,
this._showActivities.bind(this));
this._showActivities();
this._settings = Convenience.getSettings();
this._showActivitiesId = this._settings.connect(
"changed::" + SHOW_ACTIVITIES_ID,
this._showActivities.bind(this),
);
this._showActivities();
this._showAppMenuId = this._settings.connect('changed::'+SHOW_APP_MENU_ID,
this._showAppMenu.bind(this));
this._showAppMenu();
this._showAppMenuId = this._settings.connect(
"changed::" + SHOW_APP_MENU_ID,
this._showAppMenu.bind(this),
);
this._showAppMenu();
this._showDateTimeId = this._settings.connect('changed::'+SHOW_DATE_TIME_ID,
this._showDateTime.bind(this));
this._showDateTime();
this._showDateTimeId = this._settings.connect(
"changed::" + SHOW_DATE_TIME_ID,
this._showDateTime.bind(this),
);
this._showDateTime();
this.connect('destroy', this._onDestroy.bind(this));
}
this.connect("destroy", this._onDestroy.bind(this));
}
_onDestroy() {
global.display.disconnect(this._workareasChangedId);
Main.overview.disconnect(this._showingId);
Main.overview.disconnect(this._hidingId);
_onDestroy() {
global.display.disconnect(this._workareasChangedId);
Main.overview.disconnect(this._showingId);
Main.overview.disconnect(this._hidingId);
this._settings.disconnect(this._showActivitiesId);
this._settings.disconnect(this._showAppMenuId);
this._settings.disconnect(this._showDateTimeId);
this._settings.disconnect(this._showActivitiesId);
this._settings.disconnect(this._showAppMenuId);
this._settings.disconnect(this._showDateTimeId);
Main.ctrlAltTabManager.removeGroup(this);
Main.sessionMode.disconnect(this._updatedId);
}
Main.ctrlAltTabManager.removeGroup(this);
Main.sessionMode.disconnect(this._updatedId);
}
_showActivities() {
let name = 'activities';
if (this._settings.get_boolean(SHOW_ACTIVITIES_ID)) {
if (this.statusArea[name])
this.statusArea[name].visible = true;
}
else {
if (this.statusArea[name])
this.statusArea[name].visible = false;
}
}
_showActivities() {
let name = "activities";
if (this._settings.get_boolean(SHOW_ACTIVITIES_ID)) {
if (this.statusArea[name]) this.statusArea[name].visible = true;
} else {
if (this.statusArea[name]) this.statusArea[name].visible = false;
}
}
_showDateTime() {
let name = 'dateMenu';
if (this._settings.get_boolean(SHOW_DATE_TIME_ID)) {
if (this.statusArea[name])
this.statusArea[name].visible = true;
}
else {
if (this.statusArea[name])
this.statusArea[name].visible = false;
}
}
_showDateTime() {
let name = "dateMenu";
if (this._settings.get_boolean(SHOW_DATE_TIME_ID)) {
if (this.statusArea[name]) this.statusArea[name].visible = true;
} else {
if (this.statusArea[name]) this.statusArea[name].visible = false;
}
}
_showAppMenu() {
let name = 'appMenu';
if (this._settings.get_boolean(SHOW_APP_MENU_ID)) {
if (!this.statusArea[name]) {
let indicator = new MultiMonitorsAppMenuButton(this);
this.statusArea[name] = indicator;
let box = this._leftBox;
this._addToPanelBox(name, indicator, box.get_n_children()+1, box);
}
}
else {
if (this.statusArea[name]) {
let indicator = this.statusArea[name];
this.menuManager.removeMenu(indicator.menu);
indicator.destroy();
delete this.statusArea[name];
}
}
}
_showAppMenu() {
let name = "appMenu";
if (this._settings.get_boolean(SHOW_APP_MENU_ID)) {
if (!this.statusArea[name]) {
let indicator = new MultiMonitorsAppMenuButton(this);
this.statusArea[name] = indicator;
let box = this._leftBox;
this._addToPanelBox(name, indicator, box.get_n_children() + 1, box);
}
} else {
if (this.statusArea[name]) {
let indicator = this.statusArea[name];
this.menuManager.removeMenu(indicator.menu);
indicator.destroy();
delete this.statusArea[name];
}
}
}
vfunc_get_preferred_width(forHeight) {
if (Main.layoutManager.monitors.length>this.monitorIndex)
return [0, Main.layoutManager.monitors[this.monitorIndex].width];
return [0, 0];
}
vfunc_get_preferred_width(forHeight) {
if (Main.layoutManager.monitors.length > this.monitorIndex)
return [0, Main.layoutManager.monitors[this.monitorIndex].width];
_hideIndicators() {
for (let role in MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS) {
let indicator = this.statusArea[role];
if (!indicator)
continue;
indicator.container.hide();
}
}
return [0, 0];
}
_ensureIndicator(role) {
let indicator = this.statusArea[role];
if (indicator) {
indicator.container.show();
return null;
}
else {
let constructor = MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
return null;
}
indicator = new constructor(this);
this.statusArea[role] = indicator;
}
return indicator;
}
_hideIndicators() {
for (let role in MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS) {
let indicator = this.statusArea[role];
if (!indicator) continue;
indicator.container.hide();
}
}
_getDraggableWindowForPosition(stageX) {
let workspaceManager = global.workspace_manager;
const windows = workspaceManager.get_active_workspace().list_windows();
const allWindowsByStacking =
global.display.sort_windows_by_stacking(windows).reverse();
_ensureIndicator(role) {
let indicator = this.statusArea[role];
if (indicator) {
indicator.container.show();
return null;
} else {
let constructor = MULTI_MONITOR_PANEL_ITEM_IMPLEMENTATIONS[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
return null;
}
indicator = new constructor(this);
this.statusArea[role] = indicator;
}
return indicator;
}
return allWindowsByStacking.find(metaWindow => {
let rect = metaWindow.get_frame_rect();
return metaWindow.get_monitor() == this.monitorIndex &&
metaWindow.showing_on_its_workspace() &&
metaWindow.get_window_type() != Meta.WindowType.DESKTOP &&
metaWindow.maximized_vertically &&
stageX > rect.x && stageX < rect.x + rect.width;
});
}};
_getDraggableWindowForPosition(stageX) {
let workspaceManager = global.workspace_manager;
const windows = workspaceManager.get_active_workspace().list_windows();
const allWindowsByStacking = global.display
.sort_windows_by_stacking(windows)
.reverse();
MultiMonitors.copyClass(Panel.Panel, MultiMonitorsPanel);
return GObject.registerClass(MultiMonitorsPanel);
return allWindowsByStacking.find((metaWindow) => {
let rect = metaWindow.get_frame_rect();
return (
metaWindow.get_monitor() == this.monitorIndex &&
metaWindow.showing_on_its_workspace() &&
metaWindow.get_window_type() != Meta.WindowType.DESKTOP &&
metaWindow.maximized_vertically &&
stageX > rect.x &&
stageX < rect.x + rect.width
);
});
}
};
MultiMonitors.copyClass(Panel.Panel, MultiMonitorsPanel);
return GObject.registerClass(MultiMonitorsPanel);
})();

View File

@@ -15,277 +15,398 @@ You should have received a copy of the GNU General Public License
along with this program; if not, visit https://www.gnu.org/licenses/.
*/
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
import * as Lang from "resource:///org/gnome/shell/Extensions/js/lang.js";
const Lang = imports.lang;
import GObject from "gi://GObject";
import Gdk from "gi://Gdk";
import Gtk from "gi://Gtk";
import Gio from "gi://Gio";
import GLib from "gi://GLib";
const GObject = imports.gi.GObject;
const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
import { gettext as _ } from "resource:///org/gnome/shell/extensions/extension.js";
const Gettext = imports.gettext.domain('multi-monitors-add-on');
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const MultiMonitors = ExtensionUtils.getCurrentExtension();
import * as MultiMonitors from "./extension.js";
const Convenience = MultiMonitors.imports.convenience;
const SHOW_INDICATOR_ID = 'show-indicator';
const SHOW_PANEL_ID = 'show-panel';
const SHOW_ACTIVITIES_ID = 'show-activities';
const SHOW_APP_MENU_ID = 'show-app-menu';
const SHOW_DATE_TIME_ID = 'show-date-time';
const THUMBNAILS_SLIDER_POSITION_ID = 'thumbnails-slider-position';
const AVAILABLE_INDICATORS_ID = 'available-indicators';
const TRANSFER_INDICATORS_ID = 'transfer-indicators';
const ENABLE_HOT_CORNERS = 'enable-hot-corners';
const SHOW_INDICATOR_ID = "show-indicator";
const SHOW_PANEL_ID = "show-panel";
const SHOW_ACTIVITIES_ID = "show-activities";
const SHOW_APP_MENU_ID = "show-app-menu";
const SHOW_DATE_TIME_ID = "show-date-time";
const THUMBNAILS_SLIDER_POSITION_ID = "thumbnails-slider-position";
const AVAILABLE_INDICATORS_ID = "available-indicators";
const TRANSFER_INDICATORS_ID = "transfer-indicators";
const ENABLE_HOT_CORNERS = "enable-hot-corners";
const Columns = {
INDICATOR_NAME: 0,
MONITOR_NUMBER: 1
MONITOR_NUMBER: 1,
};
var MultiMonitorsPrefsWidget = GObject.registerClass(
class MultiMonitorsPrefsWidget extends Gtk.Grid {
_init() {
super._init({
margin_top: 6, margin_end: 6, margin_bottom: 6, margin_start: 6
});
class MultiMonitorsPrefsWidget extends Gtk.Grid {
_init() {
super._init({
margin_top: 6,
margin_end: 6,
margin_bottom: 6,
margin_start: 6,
});
this._numRows = 0;
this._numRows = 0;
this.set_orientation(Gtk.Orientation.VERTICAL);
this.set_orientation(Gtk.Orientation.VERTICAL);
this._settings = Convenience.getSettings();
this._desktopSettings = Convenience.getSettings("org.gnome.desktop.interface");
this._settings = Convenience.getSettings();
this._desktopSettings = Convenience.getSettings(
"org.gnome.desktop.interface",
);
this._display = Gdk.Display.get_default();
this._monitors = this._display.get_monitors()
this._display = Gdk.Display.get_default();
this._monitors = this._display.get_monitors();
this._addBooleanSwitch(_('Show Multi Monitors indicator on Top Panel.'), SHOW_INDICATOR_ID);
this._addBooleanSwitch(_('Show Panel on additional monitors.'), SHOW_PANEL_ID);
this._addBooleanSwitch(_('Show Activities-Button on additional monitors.'), SHOW_ACTIVITIES_ID);
this._addBooleanSwitch(_('Show AppMenu-Button on additional monitors.'), SHOW_APP_MENU_ID);
this._addBooleanSwitch(_('Show DateTime-Button on additional monitors.'), SHOW_DATE_TIME_ID);
this._addComboBoxSwitch(_('Show Thumbnails-Slider on additional monitors.'), THUMBNAILS_SLIDER_POSITION_ID, {
none: _('No'),
right: _('On the right'),
left: _('On the left'),
auto: _('Auto')
});
this._addSettingsBooleanSwitch(_('Enable hot corners.'), this._desktopSettings, ENABLE_HOT_CORNERS);
this._addBooleanSwitch(
_("Show Multi Monitors indicator on Top Panel."),
SHOW_INDICATOR_ID,
);
this._addBooleanSwitch(
_("Show Panel on additional monitors."),
SHOW_PANEL_ID,
);
this._addBooleanSwitch(
_("Show Activities-Button on additional monitors."),
SHOW_ACTIVITIES_ID,
);
this._addBooleanSwitch(
_("Show AppMenu-Button on additional monitors."),
SHOW_APP_MENU_ID,
);
this._addBooleanSwitch(
_("Show DateTime-Button on additional monitors."),
SHOW_DATE_TIME_ID,
);
this._addComboBoxSwitch(
_("Show Thumbnails-Slider on additional monitors."),
THUMBNAILS_SLIDER_POSITION_ID,
{
none: _("No"),
right: _("On the right"),
left: _("On the left"),
auto: _("Auto"),
},
);
this._addSettingsBooleanSwitch(
_("Enable hot corners."),
this._desktopSettings,
ENABLE_HOT_CORNERS,
);
this._store = new Gtk.ListStore();
this._store.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT]);
this._store = new Gtk.ListStore();
this._store.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT]);
this._treeView = new Gtk.TreeView({ model: this._store, hexpand: true, vexpand: true });
this._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
this._treeView = new Gtk.TreeView({
model: this._store,
hexpand: true,
vexpand: true,
});
this._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
let appColumn = new Gtk.TreeViewColumn({ expand: true, sort_column_id: Columns.INDICATOR_NAME,
title: _("A list of indicators for transfer to additional monitors.") });
let appColumn = new Gtk.TreeViewColumn({
expand: true,
sort_column_id: Columns.INDICATOR_NAME,
title: _("A list of indicators for transfer to additional monitors."),
});
let nameRenderer = new Gtk.CellRendererText;
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.INDICATOR_NAME);
let nameRenderer = new Gtk.CellRendererText();
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.INDICATOR_NAME);
nameRenderer = new Gtk.CellRendererText;
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.MONITOR_NUMBER);
this._treeView.append_column(appColumn);
this.add(this._treeView);
nameRenderer = new Gtk.CellRendererText();
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.MONITOR_NUMBER);
let toolbar = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL});
toolbar.get_style_context().add_class("inline-toolbar");
this._treeView.append_column(appColumn);
this.add(this._treeView);
this._settings.connect('changed::'+TRANSFER_INDICATORS_ID, Lang.bind(this, this._updateIndicators));
this._updateIndicators();
let toolbar = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
toolbar.get_style_context().add_class("inline-toolbar");
let addTButton = new Gtk.Button({ icon_name: "list-add" });
addTButton.connect('clicked', Lang.bind(this, this._addIndicator));
toolbar.append(addTButton);
this._settings.connect(
"changed::" + TRANSFER_INDICATORS_ID,
Lang.bind(this, this._updateIndicators),
);
this._updateIndicators();
let removeTButton = new Gtk.Button({ icon_name: "list-remove" });
removeTButton.connect('clicked', Lang.bind(this, this._removeIndicator));
toolbar.append(removeTButton);
this.add(toolbar);
}
let addTButton = new Gtk.Button({ icon_name: "list-add" });
addTButton.connect("clicked", Lang.bind(this, this._addIndicator));
toolbar.append(addTButton);
add(child) {
this.attach(child, 0, this._numRows++, 1, 1);
}
let removeTButton = new Gtk.Button({ icon_name: "list-remove" });
removeTButton.connect("clicked", Lang.bind(this, this._removeIndicator));
toolbar.append(removeTButton);
_updateIndicators() {
this._store.clear();
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
for(let indicator in transfers) {
if(transfers.hasOwnProperty(indicator)){
let monitor = transfers[indicator];
let iter = this._store.append();
this._store.set(iter, [Columns.INDICATOR_NAME, Columns.MONITOR_NUMBER], [indicator, monitor]);
}
}
}
_addIndicator() {
let dialog = new Gtk.Dialog({ title: _("Select indicator"),
transient_for: this.get_toplevel(), modal: true });
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
dialog.add_button(_("Add"), Gtk.ResponseType.OK);
dialog.set_default_response(Gtk.ResponseType.OK);
let grid = new Gtk.Grid({ column_spacing: 10, row_spacing: 15,
margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10 });
grid.set_orientation(Gtk.Orientation.VERTICAL);
dialog._store = new Gtk.ListStore();
dialog._store.set_column_types([GObject.TYPE_STRING]);
dialog._treeView = new Gtk.TreeView({ model: dialog._store, hexpand: true, vexpand: true });
dialog._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
let appColumn = new Gtk.TreeViewColumn({ expand: true, sort_column_id: Columns.INDICATOR_NAME,
title: _("Indicators on Top Panel") });
let nameRenderer = new Gtk.CellRendererText;
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.INDICATOR_NAME);
dialog._treeView.append_column(appColumn);
let availableIndicators = () => {
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).unpack();
dialog._store.clear();
this._settings.get_strv(AVAILABLE_INDICATORS_ID).forEach((indicator) => {
if(!transfers.hasOwnProperty(indicator)){
let iter = dialog._store.append();
dialog._store.set(iter, [Columns.INDICATOR_NAME], [indicator]);
}
});
};
let availableIndicatorsId = this._settings.connect('changed::'+AVAILABLE_INDICATORS_ID,
availableIndicators);
let transferIndicatorsId = this._settings.connect('changed::'+TRANSFER_INDICATORS_ID,
availableIndicators);
availableIndicators.apply(this);
grid.attach(dialog._treeView, 0, 0, 2, 1);
let gHBox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10,
spacing: 20, hexpand: true});
let gLabel = new Gtk.Label({label: _('Monitor index:'), halign: Gtk.Align.START});
gHBox.append(gLabel);
dialog._adjustment = new Gtk.Adjustment({lower: 0.0, upper: 0.0, step_increment:1.0});
let spinButton = new Gtk.SpinButton({halign: Gtk.Align.END, adjustment: dialog._adjustment, numeric: 1});
gHBox.append(spinButton);
let monitorsChanged = () => {
let n_monitors = this._monitors.get_n_items() -1;
dialog._adjustment.set_upper(n_monitors)
dialog._adjustment.set_value(n_monitors);
};
let monitorsChangedId = this._monitors.connect('items-changed', monitorsChanged);
monitorsChanged.apply(this);
grid.append(gHBox);
dialog.get_content_area().append(grid);
dialog.connect('response', (dialog, id) => {
this._monitors.disconnect(monitorsChangedId);
this._settings.disconnect(availableIndicatorsId);
this._settings.disconnect(transferIndicatorsId);
if (id != Gtk.ResponseType.OK) {
dialog.destroy();
return;
}
let [any, model, iter] = dialog._treeView.get_selection().get_selected();
if (any) {
let indicator = model.get_value(iter, Columns.INDICATOR_NAME);
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
if(!transfers.hasOwnProperty(indicator)){
transfers[indicator] = dialog._adjustment.get_value();
this._settings.set_value(TRANSFER_INDICATORS_ID, new GLib.Variant('a{si}', transfers));
}
}
dialog.destroy();
});
}
_removeIndicator() {
let [any, model, iter] = this._treeView.get_selection().get_selected();
if (any) {
let indicator = model.get_value(iter, Columns.INDICATOR_NAME);
let transfers = this._settings.get_value(TRANSFER_INDICATORS_ID).deep_unpack();
if(transfers.hasOwnProperty(indicator)){
delete transfers[indicator];
this._settings.set_value(TRANSFER_INDICATORS_ID, new GLib.Variant('a{si}', transfers));
}
this.add(toolbar);
}
}
_addComboBoxSwitch(label, schema_id, options) {
this._addSettingsComboBoxSwitch(label, this._settings, schema_id, options)
}
add(child) {
this.attach(child, 0, this._numRows++, 1, 1);
}
_addSettingsComboBoxSwitch(label, settings, schema_id, options) {
let gHBox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10,
spacing: 20, hexpand: true});
let gLabel = new Gtk.Label({label: _(label), halign: Gtk.Align.START});
gHBox.append(gLabel);
_updateIndicators() {
this._store.clear();
let gCBox = new Gtk.ComboBoxText({halign: Gtk.Align.END});
Object.entries(options).forEach(function(entry) {
const [key, val] = entry;
gCBox.append(key, val);
});
gHBox.append(gCBox);
let transfers = this._settings
.get_value(TRANSFER_INDICATORS_ID)
.deep_unpack();
this.add(gHBox);
for (let indicator in transfers) {
if (transfers.hasOwnProperty(indicator)) {
let monitor = transfers[indicator];
let iter = this._store.append();
this._store.set(
iter,
[Columns.INDICATOR_NAME, Columns.MONITOR_NUMBER],
[indicator, monitor],
);
}
}
}
settings.bind(schema_id, gCBox, 'active-id', Gio.SettingsBindFlags.DEFAULT);
}
_addIndicator() {
let dialog = new Gtk.Dialog({
title: _("Select indicator"),
transient_for: this.get_toplevel(),
modal: true,
});
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
dialog.add_button(_("Add"), Gtk.ResponseType.OK);
dialog.set_default_response(Gtk.ResponseType.OK);
_addBooleanSwitch(label, schema_id) {
this._addSettingsBooleanSwitch(label, this._settings, schema_id);
}
let grid = new Gtk.Grid({
column_spacing: 10,
row_spacing: 15,
margin_top: 10,
margin_end: 10,
margin_bottom: 10,
margin_start: 10,
});
_addSettingsBooleanSwitch(label, settings, schema_id) {
let gHBox = new Gtk.Box({orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 10, margin_end: 10, margin_bottom: 10, margin_start: 10,
spacing: 20, hexpand: true});
let gLabel = new Gtk.Label({label: _(label), halign: Gtk.Align.START});
gHBox.append(gLabel);
let gSwitch = new Gtk.Switch({halign: Gtk.Align.END});
gHBox.append(gSwitch);
this.add(gHBox);
grid.set_orientation(Gtk.Orientation.VERTICAL);
settings.bind(schema_id, gSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
}
});
dialog._store = new Gtk.ListStore();
dialog._store.set_column_types([GObject.TYPE_STRING]);
function init() {
dialog._treeView = new Gtk.TreeView({
model: dialog._store,
hexpand: true,
vexpand: true,
});
dialog._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
let appColumn = new Gtk.TreeViewColumn({
expand: true,
sort_column_id: Columns.INDICATOR_NAME,
title: _("Indicators on Top Panel"),
});
let nameRenderer = new Gtk.CellRendererText();
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.INDICATOR_NAME);
dialog._treeView.append_column(appColumn);
let availableIndicators = () => {
let transfers = this._settings
.get_value(TRANSFER_INDICATORS_ID)
.unpack();
dialog._store.clear();
this._settings
.get_strv(AVAILABLE_INDICATORS_ID)
.forEach((indicator) => {
if (!transfers.hasOwnProperty(indicator)) {
let iter = dialog._store.append();
dialog._store.set(iter, [Columns.INDICATOR_NAME], [indicator]);
}
});
};
let availableIndicatorsId = this._settings.connect(
"changed::" + AVAILABLE_INDICATORS_ID,
availableIndicators,
);
let transferIndicatorsId = this._settings.connect(
"changed::" + TRANSFER_INDICATORS_ID,
availableIndicators,
);
availableIndicators.apply(this);
grid.attach(dialog._treeView, 0, 0, 2, 1);
let gHBox = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 10,
margin_end: 10,
margin_bottom: 10,
margin_start: 10,
spacing: 20,
hexpand: true,
});
let gLabel = new Gtk.Label({
label: _("Monitor index:"),
halign: Gtk.Align.START,
});
gHBox.append(gLabel);
dialog._adjustment = new Gtk.Adjustment({
lower: 0.0,
upper: 0.0,
step_increment: 1.0,
});
let spinButton = new Gtk.SpinButton({
halign: Gtk.Align.END,
adjustment: dialog._adjustment,
numeric: 1,
});
gHBox.append(spinButton);
let monitorsChanged = () => {
let n_monitors = this._monitors.get_n_items() - 1;
dialog._adjustment.set_upper(n_monitors);
dialog._adjustment.set_value(n_monitors);
};
let monitorsChangedId = this._monitors.connect(
"items-changed",
monitorsChanged,
);
monitorsChanged.apply(this);
grid.append(gHBox);
dialog.get_content_area().append(grid);
dialog.connect("response", (dialog, id) => {
this._monitors.disconnect(monitorsChangedId);
this._settings.disconnect(availableIndicatorsId);
this._settings.disconnect(transferIndicatorsId);
if (id != Gtk.ResponseType.OK) {
dialog.destroy();
return;
}
let [any, model, iter] = dialog._treeView
.get_selection()
.get_selected();
if (any) {
let indicator = model.get_value(iter, Columns.INDICATOR_NAME);
let transfers = this._settings
.get_value(TRANSFER_INDICATORS_ID)
.deep_unpack();
if (!transfers.hasOwnProperty(indicator)) {
transfers[indicator] = dialog._adjustment.get_value();
this._settings.set_value(
TRANSFER_INDICATORS_ID,
new GLib.Variant("a{si}", transfers),
);
}
}
dialog.destroy();
});
}
_removeIndicator() {
let [any, model, iter] = this._treeView.get_selection().get_selected();
if (any) {
let indicator = model.get_value(iter, Columns.INDICATOR_NAME);
let transfers = this._settings
.get_value(TRANSFER_INDICATORS_ID)
.deep_unpack();
if (transfers.hasOwnProperty(indicator)) {
delete transfers[indicator];
this._settings.set_value(
TRANSFER_INDICATORS_ID,
new GLib.Variant("a{si}", transfers),
);
}
}
}
_addComboBoxSwitch(label, schema_id, options) {
this._addSettingsComboBoxSwitch(
label,
this._settings,
schema_id,
options,
);
}
_addSettingsComboBoxSwitch(label, settings, schema_id, options) {
let gHBox = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 10,
margin_end: 10,
margin_bottom: 10,
margin_start: 10,
spacing: 20,
hexpand: true,
});
let gLabel = new Gtk.Label({ label: _(label), halign: Gtk.Align.START });
gHBox.append(gLabel);
let gCBox = new Gtk.ComboBoxText({ halign: Gtk.Align.END });
Object.entries(options).forEach(function (entry) {
const [key, val] = entry;
gCBox.append(key, val);
});
gHBox.append(gCBox);
this.add(gHBox);
settings.bind(
schema_id,
gCBox,
"active-id",
Gio.SettingsBindFlags.DEFAULT,
);
}
_addBooleanSwitch(label, schema_id) {
this._addSettingsBooleanSwitch(label, this._settings, schema_id);
}
_addSettingsBooleanSwitch(label, settings, schema_id) {
let gHBox = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
margin_top: 10,
margin_end: 10,
margin_bottom: 10,
margin_start: 10,
spacing: 20,
hexpand: true,
});
let gLabel = new Gtk.Label({ label: _(label), halign: Gtk.Align.START });
gHBox.append(gLabel);
let gSwitch = new Gtk.Switch({ halign: Gtk.Align.END });
gHBox.append(gSwitch);
this.add(gHBox);
settings.bind(
schema_id,
gSwitch,
"active",
Gio.SettingsBindFlags.DEFAULT,
);
}
},
);
export function init() {
Convenience.initTranslations();
}
function buildPrefsWidget() {
export function buildPrefsWidget() {
let widget = new MultiMonitorsPrefsWidget();
return widget;