[gnome] Bump extension versions ... I should probably get these out of here
This commit is contained in:
@ -54,7 +54,7 @@ export function TalkativeLog(msg) {
|
||||
* @returns {string} the version
|
||||
*/
|
||||
export function getFullVersion() {
|
||||
return '1.11.0'; // FULL_VERSION
|
||||
return '1.11.1'; // FULL_VERSION
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -65,7 +65,8 @@ const EasyScreenCastIndicator = GObject.registerClass({
|
||||
);
|
||||
|
||||
this.CtrlAudio = new UtilAudio.MixerAudio();
|
||||
this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam'));
|
||||
// CtrlWebcam is initialized lazy to avoid problems like #368
|
||||
this.CtrlWebcam = null;
|
||||
|
||||
this.CtrlNotify = new UtilNotify.NotifyManager();
|
||||
this.CtrlExe = new UtilExeCmd.ExecuteStuff(this);
|
||||
@ -587,7 +588,8 @@ const EasyScreenCastIndicator = GObject.registerClass({
|
||||
);
|
||||
|
||||
// start monitoring inputvideo
|
||||
this.CtrlWebcam.startMonitor();
|
||||
if (this.CtrlWebcam !== null)
|
||||
this.CtrlWebcam.startMonitor();
|
||||
|
||||
// add indicator
|
||||
this.add_child(this.indicatorBox);
|
||||
@ -600,7 +602,8 @@ const EasyScreenCastIndicator = GObject.registerClass({
|
||||
// remove key binding
|
||||
this._removeKeybindings();
|
||||
// stop monitoring inputvideo
|
||||
this.CtrlWebcam.stopMonitor();
|
||||
if (this.CtrlWebcam !== null)
|
||||
this.CtrlWebcam.stopMonitor();
|
||||
// unregister mixer control
|
||||
this.CtrlAudio.destroy();
|
||||
|
||||
|
||||
@ -11,5 +11,5 @@
|
||||
],
|
||||
"url": "https://github.com/EasyScreenCast/EasyScreenCast",
|
||||
"uuid": "EasyScreenCast@iacopodeenosee.gmail.com",
|
||||
"version": 52
|
||||
"version": 53
|
||||
}
|
||||
@ -30,7 +30,12 @@ export const HelperWebcam = GObject.registerClass({
|
||||
this._unspecified_webcam_text = unspecifiedWebcamText;
|
||||
Lib.TalkativeLog('-@-init webcam');
|
||||
|
||||
Gst.init(null);
|
||||
var [result, _] = Gst.init_check(null);
|
||||
Lib.TalkativeLog(`-@-gstreamer init result: ${result}`);
|
||||
if (!result) {
|
||||
Lib.TalkativeLog('-@-gstreamer init failed');
|
||||
throw new Error('GStreamer init failed');
|
||||
}
|
||||
|
||||
// get gstreamer lib version
|
||||
var [M, m, micro, nano] = Gst.version();
|
||||
|
||||
@ -194,7 +194,7 @@ class AppIndicatorProxy extends DBusProxy {
|
||||
});
|
||||
} catch (e) {
|
||||
if (!AppIndicatorProxy.OPTIONAL_PROPERTIES.includes(p) ||
|
||||
!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_PROPERTY))
|
||||
!(e instanceof Gio.DBusError))
|
||||
logError(e);
|
||||
}
|
||||
}));
|
||||
@ -315,7 +315,8 @@ class AppIndicatorProxy extends DBusProxy {
|
||||
Util.Logger.debug(`Error when calling 'Get(${propertyName})' ` +
|
||||
`in ${this.gName}, ${this.gObjectPath}, ` +
|
||||
`org.freedesktop.DBus.Properties, ${this.gInterfaceName} ` +
|
||||
`while refreshing property ${propertyName}: ${e}`);
|
||||
`while refreshing property ${propertyName}: ${e}\n` +
|
||||
`${e.stack}`);
|
||||
this.set_cached_property(propertyName, null);
|
||||
this._cancellables.delete(propertyName);
|
||||
delete this._changedProperties[propertyName];
|
||||
@ -1324,8 +1325,13 @@ class AppIndicatorsIconActor extends St.Icon {
|
||||
preferredHeight: height,
|
||||
});
|
||||
|
||||
imageContent.set_bytes(pixmapVariant.get_data_as_bytes(), PIXMAPS_FORMAT,
|
||||
width, height, rowStride);
|
||||
// Remove this dynamic check when we depend on GNOME 48.
|
||||
const coglContext = [];
|
||||
const mutterBackend = global.stage?.context?.get_backend?.();
|
||||
if (imageContent.set_bytes.length === 6 && mutterBackend?.get_cogl_context)
|
||||
coglContext.push(mutterBackend.get_cogl_context());
|
||||
imageContent.set_bytes(...coglContext, pixmapVariant.get_data_as_bytes(),
|
||||
PIXMAPS_FORMAT, width, height, rowStride);
|
||||
|
||||
if (iconType !== SNIconType.OVERLAY && !this._indicator.hasOverlayIcon) {
|
||||
const scaledSize = iconSize * scaleFactor;
|
||||
|
||||
@ -12,5 +12,5 @@
|
||||
],
|
||||
"url": "https://github.com/ubuntu/gnome-shell-extension-appindicator",
|
||||
"uuid": "appindicatorsupport@rgcjonas.gmail.com",
|
||||
"version": 59
|
||||
}
|
||||
"version": 60
|
||||
}
|
||||
@ -2,325 +2,43 @@
|
||||
|
||||
/* exported init, buildPrefsWidget */
|
||||
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Gio from 'gi://Gio';
|
||||
import Gtk from 'gi://Gtk';
|
||||
import Gtk from 'gi://Gtk'; // will be removed
|
||||
import Gdk from 'gi://Gdk';
|
||||
import * as GeneralPreferences from './preferences/generalPage.js';
|
||||
import * as CustomIconPreferences from './preferences/customIconPage.js';
|
||||
|
||||
import {
|
||||
ExtensionPreferences,
|
||||
gettext as _
|
||||
} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
||||
|
||||
const AppIndicatorPreferences = GObject.registerClass(
|
||||
class AppIndicatorPreferences extends Gtk.Box {
|
||||
_init(extension) {
|
||||
super._init({orientation: Gtk.Orientation.VERTICAL, spacing: 30});
|
||||
this._settings = extension.getSettings();
|
||||
|
||||
let label = null;
|
||||
let widget = null;
|
||||
|
||||
this.preferences_vbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 8,
|
||||
margin_start: 30,
|
||||
margin_end: 30,
|
||||
margin_top: 30,
|
||||
margin_bottom: 30,
|
||||
});
|
||||
this.custom_icons_vbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
|
||||
label = new Gtk.Label({
|
||||
label: _('Enable Legacy Tray Icons support'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
widget = new Gtk.Switch({halign: Gtk.Align.END});
|
||||
|
||||
this._settings.bind('legacy-tray-enabled', widget, 'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
this.legacy_tray_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
|
||||
this.legacy_tray_hbox.append(label);
|
||||
this.legacy_tray_hbox.append(widget);
|
||||
|
||||
// Icon opacity
|
||||
this.opacity_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
label = new Gtk.Label({
|
||||
label: _('Opacity (min: 0, max: 255)'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
|
||||
widget = new Gtk.SpinButton({halign: Gtk.Align.END});
|
||||
widget.set_sensitive(true);
|
||||
widget.set_range(0, 255);
|
||||
widget.set_value(this._settings.get_int('icon-opacity'));
|
||||
widget.set_increments(1, 2);
|
||||
widget.connect('value-changed', w => {
|
||||
this._settings.set_int('icon-opacity', w.get_value_as_int());
|
||||
});
|
||||
this.opacity_hbox.append(label);
|
||||
this.opacity_hbox.append(widget);
|
||||
|
||||
// Icon saturation
|
||||
this.saturation_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
label = new Gtk.Label({
|
||||
label: _('Desaturation (min: 0.0, max: 1.0)'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1});
|
||||
widget.set_sensitive(true);
|
||||
widget.set_range(0.0, 1.0);
|
||||
widget.set_value(this._settings.get_double('icon-saturation'));
|
||||
widget.set_increments(0.1, 0.2);
|
||||
widget.connect('value-changed', w => {
|
||||
this._settings.set_double('icon-saturation', w.get_value());
|
||||
});
|
||||
this.saturation_hbox.append(label);
|
||||
this.saturation_hbox.append(widget);
|
||||
|
||||
// Icon brightness
|
||||
this.brightness_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
label = new Gtk.Label({
|
||||
label: _('Brightness (min: -1.0, max: 1.0)'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1});
|
||||
widget.set_sensitive(true);
|
||||
widget.set_range(-1.0, 1.0);
|
||||
widget.set_value(this._settings.get_double('icon-brightness'));
|
||||
widget.set_increments(0.1, 0.2);
|
||||
widget.connect('value-changed', w => {
|
||||
this._settings.set_double('icon-brightness', w.get_value());
|
||||
});
|
||||
this.brightness_hbox.append(label);
|
||||
this.brightness_hbox.append(widget);
|
||||
|
||||
// Icon contrast
|
||||
this.contrast_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
label = new Gtk.Label({
|
||||
label: _('Contrast (min: -1.0, max: 1.0)'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1});
|
||||
widget.set_sensitive(true);
|
||||
widget.set_range(-1.0, 1.0);
|
||||
widget.set_value(this._settings.get_double('icon-contrast'));
|
||||
widget.set_increments(0.1, 0.2);
|
||||
widget.connect('value-changed', w => {
|
||||
this._settings.set_double('icon-contrast', w.get_value());
|
||||
});
|
||||
this.contrast_hbox.append(label);
|
||||
this.contrast_hbox.append(widget);
|
||||
|
||||
// Icon size
|
||||
this.icon_size_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
label = new Gtk.Label({
|
||||
label: _('Icon size (min: 0, max: 96)'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
widget = new Gtk.SpinButton({halign: Gtk.Align.END});
|
||||
widget.set_sensitive(true);
|
||||
widget.set_range(0, 96);
|
||||
widget.set_value(this._settings.get_int('icon-size'));
|
||||
widget.set_increments(1, 2);
|
||||
widget.connect('value-changed', w => {
|
||||
this._settings.set_int('icon-size', w.get_value_as_int());
|
||||
});
|
||||
this.icon_size_hbox.append(label);
|
||||
this.icon_size_hbox.append(widget);
|
||||
|
||||
// Tray position in panel
|
||||
this.tray_position_hbox = new Gtk.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 10,
|
||||
margin_start: 10,
|
||||
margin_end: 10,
|
||||
margin_top: 10,
|
||||
margin_bottom: 10,
|
||||
});
|
||||
label = new Gtk.Label({
|
||||
label: _('Tray horizontal alignment'),
|
||||
hexpand: true,
|
||||
halign: Gtk.Align.START,
|
||||
});
|
||||
widget = new Gtk.ComboBoxText();
|
||||
widget.append('center', _('Center'));
|
||||
widget.append('left', _('Left'));
|
||||
widget.append('right', _('Right'));
|
||||
this._settings.bind('tray-pos', widget, 'active-id',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this.tray_position_hbox.append(label);
|
||||
this.tray_position_hbox.append(widget);
|
||||
|
||||
this.preferences_vbox.append(this.legacy_tray_hbox);
|
||||
this.preferences_vbox.append(this.opacity_hbox);
|
||||
this.preferences_vbox.append(this.saturation_hbox);
|
||||
this.preferences_vbox.append(this.brightness_hbox);
|
||||
this.preferences_vbox.append(this.contrast_hbox);
|
||||
this.preferences_vbox.append(this.icon_size_hbox);
|
||||
this.preferences_vbox.append(this.tray_position_hbox);
|
||||
|
||||
// Custom icons section
|
||||
|
||||
const customListStore = new Gtk.ListStore();
|
||||
customListStore.set_column_types([
|
||||
GObject.TYPE_STRING,
|
||||
GObject.TYPE_STRING,
|
||||
GObject.TYPE_STRING,
|
||||
]);
|
||||
const customInitArray = this._settings.get_value('custom-icons').deep_unpack();
|
||||
customInitArray.forEach(pair => {
|
||||
customListStore.set(customListStore.append(), [0, 1, 2], pair);
|
||||
});
|
||||
customListStore.append();
|
||||
|
||||
const customTreeView = new Gtk.TreeView({
|
||||
model: customListStore,
|
||||
hexpand: true,
|
||||
vexpand: true,
|
||||
});
|
||||
const customTitles = [
|
||||
_('Indicator ID'),
|
||||
_('Icon Name'),
|
||||
_('Attention Icon Name'),
|
||||
];
|
||||
const indicatorIdColumn = new Gtk.TreeViewColumn({
|
||||
title: customTitles[0],
|
||||
sizing: Gtk.TreeViewColumnSizing.AUTOSIZE,
|
||||
});
|
||||
const customIconColumn = new Gtk.TreeViewColumn({
|
||||
title: customTitles[1],
|
||||
sizing: Gtk.TreeViewColumnSizing.AUTOSIZE,
|
||||
});
|
||||
const customAttentionIconColumn = new Gtk.TreeViewColumn({
|
||||
title: customTitles[2],
|
||||
sizing: Gtk.TreeViewColumnSizing.AUTOSIZE,
|
||||
});
|
||||
|
||||
const cellrenderer = new Gtk.CellRendererText({editable: true});
|
||||
|
||||
indicatorIdColumn.pack_start(cellrenderer, true);
|
||||
customIconColumn.pack_start(cellrenderer, true);
|
||||
customAttentionIconColumn.pack_start(cellrenderer, true);
|
||||
indicatorIdColumn.add_attribute(cellrenderer, 'text', 0);
|
||||
customIconColumn.add_attribute(cellrenderer, 'text', 1);
|
||||
customAttentionIconColumn.add_attribute(cellrenderer, 'text', 2);
|
||||
customTreeView.insert_column(indicatorIdColumn, 0);
|
||||
customTreeView.insert_column(customIconColumn, 1);
|
||||
customTreeView.insert_column(customAttentionIconColumn, 2);
|
||||
customTreeView.set_grid_lines(Gtk.TreeViewGridLines.BOTH);
|
||||
|
||||
this.custom_icons_vbox.append(customTreeView);
|
||||
|
||||
cellrenderer.connect('edited', (w, path, text) => {
|
||||
this.selection = customTreeView.get_selection();
|
||||
const title = customTreeView.get_cursor()[1].get_title();
|
||||
const columnIndex = customTitles.indexOf(title);
|
||||
const selection = this.selection.get_selected();
|
||||
const iter = selection.at(2);
|
||||
const text2 = customListStore.get_value(iter, columnIndex ? 0 : 1);
|
||||
customListStore.set(iter, [columnIndex], [text]);
|
||||
const storeLength = customListStore.iter_n_children(null);
|
||||
const customIconArray = [];
|
||||
|
||||
for (let i = 0; i < storeLength; i++) {
|
||||
const returnIter = customListStore.iter_nth_child(null, i);
|
||||
const [success, iterList] = returnIter;
|
||||
if (!success)
|
||||
break;
|
||||
|
||||
if (iterList) {
|
||||
const id = customListStore.get_value(iterList, 0);
|
||||
const customIcon = customListStore.get_value(iterList, 1);
|
||||
const customAttentionIcon = customListStore.get_value(iterList, 2);
|
||||
if (id && customIcon)
|
||||
customIconArray.push([id, customIcon, customAttentionIcon || '']);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._settings.set_value('custom-icons', new GLib.Variant(
|
||||
'a(sss)', customIconArray));
|
||||
if (storeLength === 1 && (text || text2))
|
||||
customListStore.append();
|
||||
|
||||
if (storeLength > 1) {
|
||||
if ((!text && !text2) && (storeLength - 1 > path))
|
||||
customListStore.remove(iter);
|
||||
if ((text || text2) && storeLength - 1 <= path)
|
||||
customListStore.append();
|
||||
}
|
||||
});
|
||||
|
||||
this.notebook = new Gtk.Notebook();
|
||||
this.notebook.append_page(this.preferences_vbox,
|
||||
new Gtk.Label({label: _('Preferences')}));
|
||||
this.notebook.append_page(this.custom_icons_vbox,
|
||||
new Gtk.Label({label: _('Custom Icons')}));
|
||||
|
||||
this.append(this.notebook);
|
||||
}
|
||||
});
|
||||
const SettingsKey = {
|
||||
LEGACY_TRAY_ENABLED: 'legacy-tray-enabled',
|
||||
ICON_SIZE: 'icon-size',
|
||||
ICON_OPACITY: 'icon-opacity',
|
||||
ICON_SATURATION: 'icon-saturation',
|
||||
ICON_BRIGHTNESS: 'icon-brightness',
|
||||
ICON_CONTRAST: 'icon-contrast',
|
||||
TRAY_POS: 'tray-pos',
|
||||
CUSTOM_ICONS: 'custom-icons',
|
||||
};
|
||||
|
||||
export default class DockPreferences extends ExtensionPreferences {
|
||||
getPreferencesWidget() {
|
||||
return new AppIndicatorPreferences(this);
|
||||
fillPreferencesWindow(window) {
|
||||
const iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default());
|
||||
if (!iconTheme.get_search_path().includes(`${this.path}/icons`))
|
||||
iconTheme.add_search_path(`${this.path}/icons`);
|
||||
|
||||
|
||||
const settings = this.getSettings();
|
||||
const generalPage = new GeneralPreferences.GeneralPage(settings, SettingsKey);
|
||||
const customIconPage = new CustomIconPreferences.CustomIconPage(settings, SettingsKey);
|
||||
|
||||
window.add(generalPage);
|
||||
window.add(customIconPage);
|
||||
|
||||
window.connect('close-request', () => {
|
||||
window.destroy();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,18 @@
|
||||
"wmClass": "org.mozilla.Thunderbird.desktop",
|
||||
"wmTitle": "!Mozilla Thunderbird",
|
||||
"mode": "float"
|
||||
},
|
||||
{
|
||||
"wmClass": "evolution-alarm-notify",
|
||||
"mode": "float"
|
||||
},
|
||||
{
|
||||
"wmClass": "variety",
|
||||
"mode": "float"
|
||||
},
|
||||
{
|
||||
"wmClass": "update-manager",
|
||||
"mode": "float"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -74,7 +74,27 @@ export class WindowManager extends GObject.Object {
|
||||
this.eventQueue = new Queue();
|
||||
this.theme = this.ext.theme;
|
||||
this.lastFocusedWindow = null;
|
||||
this.shouldFocusOnHover = this.ext.settings.get_boolean("focus-on-hover-enabled");
|
||||
|
||||
Logger.info("forge initialized");
|
||||
|
||||
if (this.shouldFocusOnHover) {
|
||||
// Start the pointer loop to observe the pointer position
|
||||
// and change the focus window accordingly
|
||||
this.pointerLoopInit();
|
||||
}
|
||||
}
|
||||
|
||||
pointerLoopInit() {
|
||||
if (this._pointerFocusTimeoutId) {
|
||||
GLib.Source.remove(this._pointerFocusTimeoutId);
|
||||
}
|
||||
|
||||
this._pointerFocusTimeoutId = GLib.timeout_add(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
16,
|
||||
this._focusWindowUnderPointer.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
addFloatOverride(metaWindow, withWmId) {
|
||||
@ -267,6 +287,14 @@ export class WindowManager extends GObject.Object {
|
||||
switch (settingName) {
|
||||
case "focus-border-toggle":
|
||||
this.renderTree(settingName);
|
||||
break;
|
||||
case "focus-on-hover-enabled":
|
||||
this.shouldFocusOnHover = settings.get_boolean(settingName);
|
||||
|
||||
if (this.shouldFocusOnHover) {
|
||||
this.pointerLoopInit();
|
||||
}
|
||||
|
||||
break;
|
||||
case "tiling-mode-enabled":
|
||||
this.renderTree(settingName);
|
||||
@ -891,16 +919,20 @@ export class WindowManager extends GObject.Object {
|
||||
});
|
||||
}
|
||||
|
||||
hideActorBorder(actor) {
|
||||
if (actor.border) {
|
||||
actor.border.hide();
|
||||
}
|
||||
if (actor.splitBorder) {
|
||||
actor.splitBorder.hide();
|
||||
}
|
||||
}
|
||||
|
||||
hideWindowBorders() {
|
||||
this.tree.nodeWindows.forEach((nodeWindow) => {
|
||||
let actor = nodeWindow.windowActor;
|
||||
if (actor) {
|
||||
if (actor.border) {
|
||||
actor.border.hide();
|
||||
}
|
||||
if (actor.splitBorder) {
|
||||
actor.splitBorder.hide();
|
||||
}
|
||||
this.hideActorBorder(actor);
|
||||
}
|
||||
if (nodeWindow.parentNode.isTabbed()) {
|
||||
if (nodeWindow.tab) {
|
||||
@ -1090,6 +1122,11 @@ export class WindowManager extends GObject.Object {
|
||||
this._queueSourceId = 0;
|
||||
}
|
||||
|
||||
if (this._pointerFocusTimeoutId) {
|
||||
GLib.Source.remove(this._pointerFocusTimeoutId);
|
||||
this._pointerFocusTimeoutId = 0;
|
||||
}
|
||||
|
||||
if (this._prefsOpenSrcId) {
|
||||
GLib.Source.remove(this._prefsOpenSrcId);
|
||||
this._prefsOpenSrcId = 0;
|
||||
@ -1410,6 +1447,9 @@ export class WindowManager extends GObject.Object {
|
||||
let from = "size-changed";
|
||||
this.updateMetaPositionSize(_metaWindow, from);
|
||||
}),
|
||||
metaWindow.connect("unmanaged", (_metaWindow) => {
|
||||
this.hideActorBorder(windowActor);
|
||||
}),
|
||||
metaWindow.connect("focus", (_metaWindowFocus) => {
|
||||
this.queueEvent({
|
||||
name: "focus-update",
|
||||
@ -2243,6 +2283,62 @@ export class WindowManager extends GObject.Object {
|
||||
return nodeWinAtPointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the window under the pointer and raise it.
|
||||
*
|
||||
* @returns {boolean} true if we should continue polling, false otherwise
|
||||
*/
|
||||
_focusWindowUnderPointer() {
|
||||
// Break the loop if the user has disabled the feature
|
||||
// or if the window manager is disabled
|
||||
if (!this.shouldFocusOnHover || this.disabled) return false;
|
||||
|
||||
// We don't want to focus windows when the overview is visible
|
||||
if (Main.overview.visible) return true;
|
||||
|
||||
// Get the global mouse position
|
||||
let pointer = global.get_pointer();
|
||||
|
||||
const metaWindow = this._getMetaWindowAtPointer(pointer);
|
||||
|
||||
if (metaWindow) {
|
||||
// If window is not null, focus it
|
||||
metaWindow.focus(global.get_current_time());
|
||||
// Raise it to the top
|
||||
metaWindow.raise();
|
||||
}
|
||||
|
||||
// Continue polling
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Meta.Window at the pointer coordinates
|
||||
*
|
||||
* @param {[number, number]} pointer x and y coordinates
|
||||
* @returns null if no window is found, otherwise the Meta.Window
|
||||
*/
|
||||
_getMetaWindowAtPointer(pointer) {
|
||||
const windows = global.get_window_actors();
|
||||
const [x, y] = pointer;
|
||||
|
||||
// Iterate through the windows in reverse order to get the top-most window
|
||||
for (let i = windows.length - 1; i >= 0; i--) {
|
||||
let window = windows[i];
|
||||
let metaWindow = window.meta_window;
|
||||
|
||||
let { x: wx, y: wy, width, height } = metaWindow.get_frame_rect();
|
||||
|
||||
// Check if the position is within the window bounds
|
||||
if (x >= wx && x <= wx + width && y >= wy && y <= wy + height) {
|
||||
return metaWindow;
|
||||
}
|
||||
}
|
||||
|
||||
// No window found at the pointer
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the NodeWindow under the Meta.Window and the
|
||||
* current pointer coordinates;
|
||||
|
||||
@ -25,16 +25,17 @@ export class AppearancePage extends PreferencesPage {
|
||||
*/
|
||||
static getCssSelectorAsMessage(selector) {
|
||||
switch (selector) {
|
||||
// TODO: make separate color selection for preview hint
|
||||
case ".window-tiled-border":
|
||||
return _("Tiled Focus Hint and Preview");
|
||||
case ".window-floated-border":
|
||||
return _("Floated Focus Hint");
|
||||
case ".window-split-border":
|
||||
return _("Split Direction Hint");
|
||||
case ".window-stacked-border":
|
||||
return _("Stacked Focus Hint and Preview");
|
||||
return _("Tiled window");
|
||||
case ".window-tabbed-border":
|
||||
return _("Tabbed Focus Hint and Preview");
|
||||
return _("Tabbed window");
|
||||
case ".window-stacked-border":
|
||||
return _("Stacked window");
|
||||
case ".window-floated-border":
|
||||
return _("Floating window");
|
||||
case ".window-split-border":
|
||||
return _("Split direction hint");
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,32 +46,63 @@ export class AppearancePage extends PreferencesPage {
|
||||
this.themeMgr = new PrefsThemeManager(this);
|
||||
this.add_group({
|
||||
title: _("Gaps"),
|
||||
description: _("Change the gap size between windows"),
|
||||
children: [
|
||||
// Gaps size
|
||||
new SpinButtonRow({
|
||||
title: _("Gaps Size"),
|
||||
title: _("Gap size"),
|
||||
range: [0, 32, 1],
|
||||
settings,
|
||||
bind: "window-gap-size",
|
||||
}),
|
||||
// Gaps size multiplier
|
||||
new SpinButtonRow({
|
||||
title: _("Gaps Size Multiplier"),
|
||||
range: [0, 8, 1],
|
||||
title: _("Gap size multiplier"),
|
||||
range: [0, 32, 1],
|
||||
settings,
|
||||
bind: "window-gap-size-increment",
|
||||
}),
|
||||
// Gap Hidden when Single Window
|
||||
new SwitchRow({
|
||||
title: _("Gaps Hidden when Single"),
|
||||
title: _("Disable gaps for single window"),
|
||||
subtitle: _("Disables window gaps when only a single window is present"),
|
||||
settings,
|
||||
bind: "window-gap-hidden-on-single",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
this.add_group({
|
||||
title: _("Style"),
|
||||
description: _("Change how the shell looks"),
|
||||
children: [
|
||||
new SwitchRow({
|
||||
title: _("Preview hint"),
|
||||
subtitle: _("Shows where the window will be tiled when you let go of it"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "preview-hint-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Border around focused window"),
|
||||
subtitle: _("Display a colored border around the focused window"),
|
||||
settings,
|
||||
bind: "focus-border-toggle",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Window split hint border"),
|
||||
subtitle: _("Show split direction border on focused window"),
|
||||
settings,
|
||||
bind: "split-border-toggle",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Forge in quick settings"),
|
||||
subtitle: _("Toggles the Forge tile in quick settings"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "quick-settings-enabled",
|
||||
}),
|
||||
],
|
||||
});
|
||||
this.add_group({
|
||||
title: _("Color"),
|
||||
description: _("Changes the focused window's border and preview hint colors"),
|
||||
children: [
|
||||
"window-tiled-border",
|
||||
"window-tabbed-border",
|
||||
@ -92,7 +124,7 @@ export class AppearancePage extends PreferencesPage {
|
||||
const row = new Adw.ExpanderRow({ title });
|
||||
|
||||
const borderSizeRow = new SpinButtonRow({
|
||||
title: _("Border Size"),
|
||||
title: _("Border size"),
|
||||
range: [1, 6, 1],
|
||||
// subtitle: 'Properties of the focus hint',
|
||||
max_width_chars: 1,
|
||||
@ -164,7 +196,7 @@ export class AppearancePage extends PreferencesPage {
|
||||
};
|
||||
|
||||
const borderColorRow = new ColorRow({
|
||||
title: _("Border Color"),
|
||||
title: _("Border color"),
|
||||
init: theme.getCssProperty(selector, "border-color").value,
|
||||
onChange: updateCssColors,
|
||||
});
|
||||
|
||||
@ -18,34 +18,14 @@ export class KeyboardPage extends PreferencesPage {
|
||||
constructor({ kbdSettings }) {
|
||||
super({ title: _("Keyboard"), icon_name: "input-keyboard-symbolic" });
|
||||
|
||||
const description = `${_("Syntax")}: <Super>h, <Shift>g, <Shift><Super>h
|
||||
${_("Legend")}: <Super> - ${_("Windows key")}, <Primary> - ${_("Control key")}
|
||||
${_("Delete text to unset. Press Return key to accept. Focus out to ignore.")} <i>${_(
|
||||
"Resets"
|
||||
)}</i> ${_("to previous value when invalid")}`;
|
||||
|
||||
this.add_group({
|
||||
title: _("Update Shortcuts"),
|
||||
description,
|
||||
children: Object.entries({
|
||||
window: "Window Shortcuts",
|
||||
workspace: "Workspace Shortcuts",
|
||||
con: "Container Shortcuts",
|
||||
focus: "Focus Shortcuts",
|
||||
prefs: "Other Shortcuts",
|
||||
}).map(([prefix, gettextKey]) =>
|
||||
KeyboardPage.makeKeygroupExpander(prefix, gettextKey, kbdSettings)
|
||||
title: _("Drag-and-drop modifier key"),
|
||||
description: _(
|
||||
"Change the modifier key for tiling windows via drag-and-drop. Select 'None' to always tile"
|
||||
),
|
||||
});
|
||||
|
||||
this.add_group({
|
||||
title: _("Drag-Drop Tiling Modifier Key Options"),
|
||||
description: `<i>${_(
|
||||
"Change the modifier for <b>tiling</b> windows via mouse/drag-drop"
|
||||
)}</i> ${_("Select <i>None</i> to <u>always tile immediately</u> by default")}`,
|
||||
children: [
|
||||
new RadioRow({
|
||||
title: _("Tile Modifier"),
|
||||
title: _("Modifier key"),
|
||||
settings: kbdSettings,
|
||||
bind: "mod-mask-mouse-tile",
|
||||
options: {
|
||||
@ -57,6 +37,21 @@ export class KeyboardPage extends PreferencesPage {
|
||||
}),
|
||||
],
|
||||
});
|
||||
this.add_group({
|
||||
title: _("Shortcuts"),
|
||||
description: _(
|
||||
'Change the tiling shortcuts. To clear a shortcut clear the input field. To apply a shortcut press enter. <a href="https://github.com/forge-ext/forge/wiki/Keyboard-Shortcuts">Syntax examples</a>'
|
||||
),
|
||||
children: Object.entries({
|
||||
window: "Tiling shortcuts",
|
||||
con: "Container shortcuts",
|
||||
workspace: "Workspace shortcuts",
|
||||
focus: "Appearance shortcuts",
|
||||
prefs: "Other shortcuts",
|
||||
}).map(([prefix, gettextKey]) =>
|
||||
KeyboardPage.makeKeygroupExpander(prefix, gettextKey, kbdSettings)
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
static makeKeygroupExpander(prefix, gettextKey, settings) {
|
||||
|
||||
@ -8,7 +8,7 @@ import { Logger } from "../shared/logger.js";
|
||||
import { production } from "../shared/settings.js";
|
||||
|
||||
// Prefs UI
|
||||
import { DropDownRow, SwitchRow, PreferencesPage } from "./widgets.js";
|
||||
import { DropDownRow, SwitchRow, PreferencesPage, EntryRow } from "./widgets.js";
|
||||
|
||||
// Extension imports
|
||||
import { gettext as _ } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js";
|
||||
@ -51,65 +51,57 @@ export class SettingsPage extends PreferencesPage {
|
||||
}
|
||||
|
||||
constructor({ settings, window, metadata }) {
|
||||
super({ title: _("Settings"), icon_name: "settings-symbolic" });
|
||||
super({ title: _("Tiling"), icon_name: "view-grid-symbolic" });
|
||||
this.add_group({
|
||||
title: _("Settings"),
|
||||
description: _("Toggle Forge's high-level features"),
|
||||
title: _("Behavior"),
|
||||
description: _("Change how the tiling behaves"),
|
||||
header_suffix: makeAboutButton(window, metadata),
|
||||
children: [
|
||||
new SwitchRow({
|
||||
title: _("Stacked Tiling Mode"),
|
||||
subtitle: _("Stack windows on top of each other while still being tiled"),
|
||||
title: _("Focus on Hover"),
|
||||
subtitle: _("Window focus follows the pointer"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "focus-on-hover-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Move pointer with focused window"),
|
||||
subtitle: _("Moves the pointer when focusing or swapping via keyboard"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "move-pointer-focus-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Quarter tiling"),
|
||||
subtitle: _("Places new windows in a clock-wise fashion"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "auto-split-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Stacked tiling"),
|
||||
subtitle: _("Stacks windows on top of each other while still tiling them"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "stacked-tiling-mode-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Tabbed Tiling Mode"),
|
||||
subtitle: _("Group tiles windows as tabs"),
|
||||
title: _("Tabbed tiling"),
|
||||
subtitle: _("Groups windows as tabs"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "tabbed-tiling-mode-enabled",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
this.add_group({
|
||||
title: _("Behavior"),
|
||||
children: [
|
||||
new SwitchRow({
|
||||
title: _("Move Pointer with the Focus"),
|
||||
subtitle: _("Move the pointer when focusing or swapping via keyboard"),
|
||||
experimental: true,
|
||||
title: _("Auto exit tabbed tiling"),
|
||||
subtitle: _("Exit tabbed tiling mode when only a single tab remains"),
|
||||
settings,
|
||||
bind: "auto-exit-tabbed",
|
||||
bind: "move-pointer-focus-enabled",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
this.add_group({
|
||||
title: _("Tiling"),
|
||||
children: [
|
||||
new SwitchRow({
|
||||
title: _("Preview Hint Toggle"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "preview-hint-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Show Focus Hint Border"),
|
||||
subtitle: _("Display a colored border around the focused window"),
|
||||
settings,
|
||||
bind: "focus-border-toggle",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Show Window Split Hint Border"),
|
||||
subtitle: _("Show split direction border on focused window"),
|
||||
settings,
|
||||
bind: "split-border-toggle",
|
||||
}),
|
||||
new DropDownRow({
|
||||
title: _("Default Drag-and-Drop Center Layout"),
|
||||
title: _("Drag-and-drop behavior"),
|
||||
subtitle: _("What to do when dragging one window on top of another"),
|
||||
settings,
|
||||
type: "s",
|
||||
bind: "dnd-center-layout",
|
||||
@ -120,35 +112,25 @@ export class SettingsPage extends PreferencesPage {
|
||||
],
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Auto Exit Tabbed Tiling Mode"),
|
||||
subtitle: _("Exit tabbed tiling mode when only a single tab remains"),
|
||||
settings,
|
||||
bind: "auto-exit-tabbed",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Auto Split"),
|
||||
subtitle: _("Quarter Tiling"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "auto-split-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Float Mode Always On Top"),
|
||||
subtitle: _("Floating windows always above tiling windows"),
|
||||
title: _("Always on Top mode for floating windows"),
|
||||
subtitle: _("Makes floating windows appear above tiled windows"),
|
||||
experimental: true,
|
||||
settings,
|
||||
bind: "float-always-on-top-enabled",
|
||||
}),
|
||||
new SwitchRow({
|
||||
title: _("Show Tiling Quick Settings"),
|
||||
subtitle: _("Toggle showing Forge on quick settings"),
|
||||
experimental: true,
|
||||
],
|
||||
});
|
||||
this.add_group({
|
||||
title: _("Non-tiling workspaces"),
|
||||
description: _("Disables tiling on specified workspaces. Starts from 0, separated by commas"),
|
||||
children: [
|
||||
new EntryRow({
|
||||
title: _("Example: 0,1,2"),
|
||||
settings,
|
||||
bind: "quick-settings-enabled",
|
||||
bind: "workspace-skip-tile",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
if (!production) {
|
||||
this.add_group({
|
||||
title: _("Logger"),
|
||||
|
||||
@ -218,7 +218,7 @@ export class ResetButton extends Gtk.Button {
|
||||
|
||||
constructor({ settings = undefined, bind = undefined, onReset }) {
|
||||
super({
|
||||
icon_name: "edit-clear-symbolic",
|
||||
icon_name: "edit-undo-symbolic",
|
||||
tooltip_text: _("Reset"),
|
||||
valign: Gtk.Align.CENTER,
|
||||
});
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
// Gnome imports
|
||||
import GObject from "gi://GObject";
|
||||
|
||||
import { gettext as _ } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js";
|
||||
|
||||
import { EntryRow, PreferencesPage } from "./widgets.js";
|
||||
|
||||
export class WorkspacePage extends PreferencesPage {
|
||||
static {
|
||||
GObject.registerClass(this);
|
||||
}
|
||||
|
||||
constructor({ settings }) {
|
||||
super({ title: _("Workspace"), icon_name: "shell-overview-symbolic" });
|
||||
this.add_group({
|
||||
title: _("Update Workspace Settings"),
|
||||
description: _(
|
||||
"Provide workspace indices to skip. E.g. 0,1. Empty text to disable. Enter to accept"
|
||||
),
|
||||
children: [
|
||||
new EntryRow({
|
||||
title: _("Skip Workspace Tiling"),
|
||||
settings,
|
||||
bind: "workspace-skip-tile",
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -16,5 +16,5 @@
|
||||
],
|
||||
"url": "https://github.com/forge-ext/forge",
|
||||
"uuid": "forge@jmmaranan.com",
|
||||
"version": 84
|
||||
}
|
||||
"version": 88
|
||||
}
|
||||
@ -24,7 +24,6 @@ import { ExtensionPreferences } from "resource:///org/gnome/Shell/Extensions/js/
|
||||
|
||||
import { KeyboardPage } from "./lib/prefs/keyboard.js";
|
||||
import { AppearancePage } from "./lib/prefs/appearance.js";
|
||||
import { WorkspacePage } from "./lib/prefs/workspace.js";
|
||||
import { SettingsPage } from "./lib/prefs/settings.js";
|
||||
|
||||
export default class ForgeExtensionPreferences extends ExtensionPreferences {
|
||||
@ -45,7 +44,6 @@ export default class ForgeExtensionPreferences extends ExtensionPreferences {
|
||||
window._kbdSettings = this.kbdSettings;
|
||||
window.add(new SettingsPage(this));
|
||||
window.add(new AppearancePage(this));
|
||||
window.add(new WorkspacePage(this));
|
||||
window.add(new KeyboardPage(this));
|
||||
window.search_enabled = true;
|
||||
window.can_navigate_back = true;
|
||||
|
||||
Binary file not shown.
@ -123,6 +123,10 @@
|
||||
<default>false</default>
|
||||
<summary>Move the pointer when focusing or swapping via kbd</summary>
|
||||
</key>
|
||||
<key type="b" name="focus-on-hover-enabled">
|
||||
<default>false</default>
|
||||
<summary>Focus switches to the window under the pointer.</summary>
|
||||
</key>
|
||||
<key type="b" name="float-always-on-top-enabled">
|
||||
<default>true</default>
|
||||
<summary>Floating windows toggle always-on-top</summary>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* extension.js
|
||||
* Copyright (C) 2024 kosmospredanie, shyzus, Shinigaminai
|
||||
* Copyright (C) 2025 kosmospredanie, shyzus, Shinigaminai
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -77,6 +77,9 @@ export default class ScreenAutoRotateExtension extends Extension {
|
||||
*/
|
||||
this._timeoutId = setTimeout(() => {
|
||||
this._set_hide_lock_rotate(this._settings.get_boolean('hide-lock-rotate'));
|
||||
|
||||
// Rotate once on start up to the orientation detected by the claimed accelerometer
|
||||
this.rotate_to(this._sensor_proxy.get_accelerometer_orientation());
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
{
|
||||
"_generated": "Generated by SweetTooth, do not edit",
|
||||
"description": "Enable screen rotation regardless of touch mode. Fork of Screen Autorotate by Kosmospredanie.",
|
||||
"donations": {
|
||||
"github": "shyzus"
|
||||
},
|
||||
"gettext-domain": "gnome-shell-extension-screen-rotate",
|
||||
"name": "Screen Rotate",
|
||||
"session-modes": [
|
||||
@ -16,5 +19,5 @@
|
||||
],
|
||||
"url": "https://github.com/shyzus/gnome-shell-extension-screen-autorotate",
|
||||
"uuid": "screen-rotate@shyzus.github.io",
|
||||
"version": 24
|
||||
}
|
||||
"version": 25
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/* sensorProxy.js
|
||||
* Copyright (C) 2024 kosmospredanie, shyzus
|
||||
* Copyright (C) 2025 kosmospredanie, shyzus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -64,6 +64,17 @@ export class SensorProxy {
|
||||
this._proxy = null;
|
||||
}
|
||||
|
||||
get_accelerometer_orientation() {
|
||||
if (this._enabled) {
|
||||
let variant = this._proxy.get_cached_property('AccelerometerOrientation');
|
||||
let orientation = variant.unpack();
|
||||
variant.unref();
|
||||
return orientation;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
properties_changed(proxy, changed, _invalidated) {
|
||||
if (!this._enabled) return;
|
||||
let properties = changed.deep_unpack();
|
||||
|
||||
Reference in New Issue
Block a user