From ec3f9f0bd7c6e9fbd7bf9331dcdc0fb66b39f51b Mon Sep 17 00:00:00 2001 From: Chris Ondrovic Date: Fri, 10 Apr 2026 18:26:26 -0400 Subject: [PATCH 1/2] feat: GNOME Shell 50 compatibility, overview signals, and QA tooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align Search Light with GNOME Shell 48–50 by connecting to Main.overview's real showing/hidden signals instead of overview-showing/overview-hidden, so _inOverview tracks the overview correctly. Replace the brittlesearch-results grid walk in _isDraggingIcon with a recursive lookup for grid-search-results and defensive drag checks. Drop unused Graphene wiring and fix metadata to use settings-schema for current Extension APIs. Refresh the README for install, session restart, shortcuts, and blurdependencies. Add make test (strict schemas + ESLint via npx), relax ESLint for this codebase's style, and fall back to Python when zip is missing for publish. Bump extension version to 102. Also apply small lint-driven fixes across prefs, keybinding, effects, shortcuts, style, timer, and easing (including a runAnimation array check). --- .eslintrc.yml | 32 ++++++++ Makefile | 16 ++-- README.md | 75 ++++++++++------- effects/blur_effect.js | 2 +- effects/color_effect.js | 2 +- effects/easing.js | 2 +- effects/monochrome_effect.js | 2 +- effects/tint_effect.js | 2 +- extension.js | 155 ++++++++++++++++++----------------- keybinding.js | 18 ++-- metadata.json | 4 +- preferences/prefKeys.js | 18 ++-- prefs.js | 6 +- shortcuts.js | 2 +- style.js | 6 +- timer.js | 6 +- 16 files changed, 199 insertions(+), 149 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 5e3347d..1c74708 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,3 +1,35 @@ extends: - ./lint/eslintrc-gjs.yml - ./lint/eslintrc-shell.yml + +# ESM (GNOME Shell 45+); legacy gjs harnesses and unused helpers excluded +parserOptions: + ecmaVersion: 2022 + sourceType: module + +ignorePatterns: + - tests/ + - drawing.js + - utils.js + - imports_extension.js + - imports_prefs.js + +# Project uses 2-space indent and relaxed brace style; keep error detection without mass reformat +overrides: + - files: + - '*.js' + - 'effects/**/*.js' + - 'preferences/**/*.js' + rules: + indent: 'off' + curly: 'off' + comma-dangle: 'off' + nonblock-statement-body-position: 'off' + arrow-parens: 'off' + camelcase: 'off' + object-curly-spacing: 'off' + lines-between-class-members: 'off' + spaced-comment: 'off' + eqeqeq: 'off' + no-shadow: 'off' + no-extra-parens: 'off' diff --git a/Makefile b/Makefile index 9e93e98..1960fd9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -all: build install lint +all: test install -.PHONY: build install +.PHONY: build install lint test build: glib-compile-schemas --strict --targetdir=schemas/ schemas @@ -29,8 +29,11 @@ publish: rm -rf ./build/chamfer.js rm -rf ./build/imports_* rm -rf ./*.zip - cd build ; \ - zip -qr ../search-light@icedman.github.com.zip . + @if command -v zip >/dev/null 2>&1; then \ + cd build && zip -qr ../search-light@icedman.github.com.zip .; \ + else \ + python3 -c "import os, shutil; os.chdir('build'); shutil.make_archive('../search-light@icedman.github.com', 'zip', '.');"; \ + fi install-zip: publish echo "installing zip..." @@ -82,7 +85,10 @@ test-shell: install rm /run/user/1000/gnome-shell-disable-extensions lint: - eslint ./ + ESLINT_USE_FLAT_CONFIG=false npx --yes eslint@8.57.0 -c .eslintrc.yml ./ + +test: build lint + @echo "OK: schema compile and lint passed." xml-lint: cd ui ; \ diff --git a/README.md b/README.md index 00b5ce5..bc4ea0f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

Search Light

- A GNOME Shell 42+ Extension + A GNOME Shell extension (GNOME Shell 48–50)

@@ -11,54 +11,69 @@ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/icedman) -![Contributors](https://img.shields.io/github/contributors/icedman/search-light?color=dark-green) ![Forks](https://img.shields.io/github/forks/icedman/search-light?style=social) ![Stargazers](https://img.shields.io/github/stars/icedman/search-light?style=social) ![Issues](https://img.shields.io/github/issues/icedman/search-light) ![License](https://img.shields.io/github/license/icedman/search-light) +![Contributors](https://img.shields.io/github/contributors/icedman/search-light?color=dark-green) ![Forks](https://img.shields.io/github/forks/icedman/search-light?style=social) ![Stargazers](https://img.shields.io/github/stars/icedman/search-light?style=social) ![Issues](https://img.shields.io/github/issues/icedman/search-light) ![License](https://img.shields.io/github/license/icedman/search-light) ![First Release](https://raw.githubusercontent.com/icedman/search-light/main/screenshots/Screenshot%20from%202022-11-03%2011-53-28.png) +This is a GNOME Shell extension that takes the applications search widget out of Overview, similar to macOS Spotlight or Alfred. -This is a Gnome Shell extension that takes the apps search widget out of Overview. Like the macOS spotlight, or Alfred. +### Compatibility -### Notice - -* Gnome 48 ready for testing -* Gnome 47 and prior will now be numer gnome-47 branch -* Gnome 46 port is ready for testing -* Gnome 45 port is ready for testing -* Gnome 44 and prior will be under g44 branch +- **GNOME Shell 48, 49, and 50** are supported on this branch (see `shell-version` in `metadata.json`). +- Older GNOME releases may be available on other branches (for example upstream’s `gnome-47` or `g44`); check the repository branches if you are not on GNOME 48+. ### Features -* Popup search box -* Colors, background, borders customization -* Blurred background -* Multi-monitor support +- Popup search box outside Overview +- Colors, background, and border customization +- Optional blurred background (requires ImageMagick) +- Multi-monitor support (preferred monitor or cursor monitor) +- Primary and secondary keyboard shortcuts (configured in preferences) +- Optional panel search icon ## Blurred background -Blurred background feature requires **imagemagick** to be installed in the system which will generate the blurred image. +The blurred background option requires **ImageMagick** (`convert`) so the extension can generate a blurred copy of the desktop wallpaper. + +## Installation -### Installation +**Before installing**, run checks from the repository root: -Manual Installation: -- Clone this repo ```bash -$ git clone https://github.com/icedman/search-light +make test ``` -- Use the `Makefile` to build and install -```bash -$ cd search-light -$ make + +That runs a strict GSettings schema compile and ESLint. Fix any failures before installing. + +Manual installation: + +```bash +git clone https://github.com/icedman/search-light +cd search-light +make test +make install +gnome-extensions enable search-light@icedman.github.com ``` -From Gnome Extensions Repository +GNOME Shell **50** is Wayland-oriented; after installing or upgrading the extension, **log out and back in** (or restart GNOME Shell) so the session loads the updated code. + +If you copy files with `make install`, the **Extensions** app may not list the extension until the next login. You can also install from a zip produced by `make publish` using `gnome-extensions install --force search-light@icedman.github.com.zip` (requires `zip` or Python for the zip step; see the `Makefile`). + +From the GNOME Extensions site: [Search Light on extensions.gnome.org](https://extensions.gnome.org/extension/5489/search-light/) + +## Keybindings -Visit [repository](https://extensions.gnome.org/extension/5489/search-light/) +- Default: **Ctrl+Super+Space** (see `shortcut-search` / `secondary-shortcut-search` in preferences). If no shortcut is stored in settings, that default is used. +- **Super** is the Windows or Command key; it is often labeled “Super” on Linux keyboards. +- Set or change shortcuts under the extension’s preferences (Extensions app → Search Light → settings). -### Keybinding +## Developing and manual UI harnesses -Ctrl+Cmd+Space (change at the preference page) -Cmd - your Windows logo, or the command logo on mac. Linux also calls this the 'Super' key. +- `make build` — `glib-compile-schemas --strict` into `schemas/` +- `make lint` — ESLint +- `make test` — `build` then `lint` +- From the repo root, with a graphical session: `gjs tests/test_prefs.js` or `gjs tests/test_prefs_legacy.js` to smoke-test loading preference UI files (interactive windows). -### Credits +## Credits -Blur-My-Shell for background blurring code. +Blur-My-Shell for background blurring ideas and shader-related code. diff --git a/effects/blur_effect.js b/effects/blur_effect.js index 342160e..ebba2ef 100644 --- a/effects/blur_effect.js +++ b/effects/blur_effect.js @@ -15,7 +15,7 @@ const getTintShaderSource = (extensionDir) => { try { return Shell.get_file_contents_utf8_sync(SHADER_PATH); } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); + log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); return null; } }; diff --git a/effects/color_effect.js b/effects/color_effect.js index 674bcc1..6d995e1 100644 --- a/effects/color_effect.js +++ b/effects/color_effect.js @@ -17,7 +17,7 @@ const getColorEffectShaderSource = (extensionDir) => { try { return Shell.get_file_contents_utf8_sync(SHADER_PATH); } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); + log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); return null; } }; diff --git a/effects/easing.js b/effects/easing.js index e6aeb40..e1db07d 100644 --- a/effects/easing.js +++ b/effects/easing.js @@ -42,7 +42,7 @@ export const Bounce = { }, }; -var Back = { +export const Back = { easeIn: (t, b, c, d) => { let s = 1.70158; let postFix = (t /= d); diff --git a/effects/monochrome_effect.js b/effects/monochrome_effect.js index a04cdb5..5644cf8 100644 --- a/effects/monochrome_effect.js +++ b/effects/monochrome_effect.js @@ -18,7 +18,7 @@ const getMonochromeShaderSource = (extensionDir) => { try { return Shell.get_file_contents_utf8_sync(SHADER_PATH); } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); + log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); return null; } }; diff --git a/effects/tint_effect.js b/effects/tint_effect.js index 01c40d4..7a66955 100644 --- a/effects/tint_effect.js +++ b/effects/tint_effect.js @@ -17,7 +17,7 @@ const getTintShaderSource = (extensionDir) => { try { return Shell.get_file_contents_utf8_sync(SHADER_PATH); } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); + log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); return null; } }; diff --git a/extension.js b/extension.js index 81d5e0f..abc8f1a 100644 --- a/extension.js +++ b/extension.js @@ -18,15 +18,12 @@ */ import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -import Meta from 'gi://Meta'; import Shell from 'gi://Shell'; import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Clutter from 'gi://Clutter'; import St from 'gi://St'; -import Graphene from 'gi://Graphene'; import { trySpawnCommandLine } from 'resource:///org/gnome/shell/misc/util.js'; import { Timer } from './timer.js'; @@ -58,8 +55,6 @@ var SearchLight = GObject.registerClass( export default class SearchLightExt extends Extension { enable() { - Main.overview.graphene = Graphene; - this._style = new Style(); this._hiTimer = new Timer('hi-res timer'); @@ -169,9 +164,9 @@ export default class SearchLightExt extends Extension { this._animationSpeed = this._settings.get_double('animation-speed'); Main.overview.connectObject( - 'overview-showing', + 'showing', this._onOverviewShowing.bind(this), - 'overview-hidden', + 'hidden', this._onOverviewHidden.bind(this), this, ); @@ -184,7 +179,7 @@ export default class SearchLightExt extends Extension { global.display.connectObject( 'window-created', - (display, win) => { + () => { if (this._visible) { this.mainContainer.opacity = 0; } @@ -198,10 +193,6 @@ export default class SearchLightExt extends Extension { Main.overview.searchLight = this; - let appInfo = Gio.DesktopAppInfo.new_from_filename( - `${this.path}/apps/org.gnome.Calculator.desktop`, - ); - let _providers = []; // deferred startup for providers @@ -288,7 +279,7 @@ export default class SearchLightExt extends Extension { Main.panel._rightBox.insert_child_at_index(this._indicator, 0); this._indicator.visible = this.show_panel_icon; } catch (err) { - console.log(err); + logError(err); } } @@ -325,7 +316,7 @@ export default class SearchLightExt extends Extension { _updateBlurredBackground() { this.desktop_background = this._desktopSettings.get_string('picture-uri'); - + let uuid = GLib.get_user_name(); this.desktop_background_blurred = `/tmp/searchlight-${uuid}-bg-blurred.jpg`; @@ -334,9 +325,9 @@ export default class SearchLightExt extends Extension { // let bg = this._desktopSettings.get_string('picture-uri'); // let a = Math.floor(100 - color[3] * 100); // let rgb = this._style.hex(color); - // let cmd = `convert -scale 10% -blur 0x2.5 -resize 200% -fill "${rgb}" -tint ${a} "${bg}" ${this.desktop_background_blurred}`; + // let cmd = `convert -scale 10% -blur 0x2.5 -resize 200% -fill "${rgb}" -tint ${a} "${bg}" ${this.desktop_background_blurred}`; let cmd = `convert -scale 10% -blur 0x2.5 -resize 200% "${this.desktop_background}" ${this.desktop_background_blurred}`; - console.log(cmd); + log(cmd); trySpawnCommandLine(cmd); } } @@ -352,7 +343,7 @@ export default class SearchLightExt extends Extension { this.windowEffect = effect; } - _updatePanelIcon(disable) {} + _updatePanelIcon(_disable) {} _updateProviders() { this._removeProviders(); @@ -519,29 +510,64 @@ export default class SearchLightExt extends Extension { // this._hidePopups(); } + _findGridSearchResults(actor) { + if (!actor) { + return null; + } + if (actor.style_class === 'grid-search-results') { + return actor; + } + let c = actor.get_first_child(); + while (c) { + let found = this._findGridSearchResults(c); + if (found) { + return found; + } + c = c.get_next_sibling(); + } + return null; + } + + _actorHasActiveDrag(actor, depth) { + if (!actor || depth < 0) { + return false; + } + if ( + actor._draggable && + actor._draggable._dragState === 1 /* DragState.DRAGGING */ + ) { + return true; + } + let c = actor.get_first_child(); + while (c) { + if (this._actorHasActiveDrag(c, depth - 1)) { + return true; + } + c = c.get_next_sibling(); + } + return false; + } + _isDraggingIcon() { - // cancel all drag - let result = false; try { - if (this._searchResults) { - let grid = - this._searchResults._content.first_child.first_child.child.child; - if (grid.style_class == 'grid-search-results') { - grid.get_children().forEach((c) => { - // console.log(`${c._name} ${c._draggable._dragState}`); - if ( - c._draggable && - c._draggable._dragState == 1 /* DragState.DRAGGING */ - ) { - result = true; - } - }); + if (!this._searchResults) { + return false; + } + let grid = this._findGridSearchResults(this._searchResults); + if (!grid) { + return false; + } + let c = grid.get_first_child(); + while (c) { + if (c.visible && this._actorHasActiveDrag(c, 4)) { + return true; } + c = c.get_next_sibling(); } } catch (err) { - console.log(err); + logError(err); } - return result; + return false; } _layout() { @@ -554,27 +580,6 @@ export default class SearchLightExt extends Extension { this.height = 400 + ((this.sh * this.scaleFactor) / 2) * (this.scale_height || 0); - // initial height - let font_size = 14; - if (this.font_size) { - font_size = this.font_size_options[this.font_size]; - } - if (this.entry_font_size) { - font_size = this.entry_font_size_options[this.entry_font_size]; - } - - // let padding = { - // 14: 14 * 2.5, - // 16: 16 * 2.4, - // 18: 18 * 2.2, - // 20: 20 * 2.0, - // 22: 22 * 1.8, - // 24: 24 * 1.6, - // }; - // this.initial_height = padding[font_size] * this.scaleFactor; - // this.initial_height += font_size * 2 * this.scaleFactor; - // console.log(`${this.initial_height} ${this._entry.height}`); - this.initial_height = this._entry.height + 4 * this.scaleFactor; // position @@ -613,7 +618,7 @@ export default class SearchLightExt extends Extension { } catch (err) { // } - if (shortcut == '') { + if (shortcut === '') { shortcut = 'Space'; } @@ -631,7 +636,7 @@ export default class SearchLightExt extends Extension { } catch (err) { // } - if (shortcut == '') { + if (shortcut === '') { shortcut = 'Space'; } @@ -642,9 +647,9 @@ export default class SearchLightExt extends Extension { _queryDisplay() { let idx = this.preferred_monitor || 0; - if (idx == 0) { + if (idx === 0) { idx = Main.layoutManager.primaryIndex; - } else if (idx == Main.layoutManager.primaryIndex) { + } else if (idx === Main.layoutManager.primaryIndex) { idx = 0; } this.monitor = @@ -667,7 +672,7 @@ export default class SearchLightExt extends Extension { this.sw = this.monitor.width; this.sh = this.monitor.height; - if (this._last_monitor_count != Main.layoutManager.monitors.length) { + if (this._last_monitor_count !== Main.layoutManager.monitors.length) { this._settings.set_int( 'monitor-count', Main.layoutManager.monitors.length, @@ -792,16 +797,14 @@ export default class SearchLightExt extends Extension { } } - _updateCss(disable) { + _updateCss(_disable) { let bg = this.background_color || [0, 0, 0, 0.5]; if (this.text_color && this.text_color[3] > 0) { this.container.remove_style_class_name('light'); + } else if (0.3 * bg[0] + 0.59 * bg[1] + 0.11 * bg[2] < 0.5) { + this.container.remove_style_class_name('light'); } else { - if (0.3 * bg[0] + 0.59 * bg[1] + 0.11 * bg[2] < 0.5) { - this.container.remove_style_class_name('light'); - } else { - this.container.add_style_class_name('light'); - } + this.container.add_style_class_name('light'); } this._background.remove_effect_by_name('blur'); @@ -848,7 +851,7 @@ export default class SearchLightExt extends Extension { `\n background-image: url("${this.desktop_background_blurred}");`, ); ss.push(`\n background-size: ${sw}px ${sh}px;`); - ss.push(`\n background-position: top center;`); + ss.push('\n background-position: top center;'); // ss.push(`\n border: 2px solid red;`); this._background.style = ss.join(' '); @@ -864,10 +867,10 @@ export default class SearchLightExt extends Extension { let r = rads[Math.floor(this.border_radius)]; if (r) { let st = `StBoxLayout.search-section-content { border-radius: ${r}px !important; }`; - st = '#searchLightBlurredBackgroundImage,\n' + st; // has no effect - st = '#searchLightBlurredBackground,\n' + st; // has no effect - st = '#searchLightBox,\n' + st; - st = '#searchLight,\n' + st; + st = `#searchLightBlurredBackgroundImage,\n${st}`; // has no effect + st = `#searchLightBlurredBackground,\n${st}`; // has no effect + st = `#searchLightBox,\n${st}`; + st = `#searchLight,\n${st}`; styles.push(st); } } @@ -897,9 +900,9 @@ export default class SearchLightExt extends Extension { { let ss = []; { - let clr = this._style.rgba(this.panel_icon_color); + let panelClr = this._style.rgba(this.panel_icon_color); if (this.panel_icon_color[3] > 0) { - ss.push(`\n color: rgba(${clr}) !important;`); + ss.push(`\n color: rgba(${panelClr}) !important;`); } } styles.push(`.panel-status-indicator-icon {${ss.join(' ')}}`); @@ -986,13 +989,13 @@ export default class SearchLightExt extends Extension { }, ]); } catch (err) { - console.log(err); + logError(err); } } - _onFocusWindow(w, e) {} + _onFocusWindow(_w, _e) {} - _onKeyFocusChanged(previous) { + _onKeyFocusChanged(_previous) { if (!this._entry) return; let focus = global.stage.get_key_focus(); let appearFocused = diff --git a/keybinding.js b/keybinding.js index c427398..b273954 100644 --- a/keybinding.js +++ b/keybinding.js @@ -5,13 +5,11 @@ import Shell from 'gi://Shell'; // from https://stackoverflow.com/questions/12325405/gnome-shell-extension-key-binding export const KeyboardShortcuts = class { - constructor() {} - enable() { this._grabbers = {}; this._eventId = global.display.connect( 'accelerator-activated', - (display, action, deviceId, timestamp) => { + (_display, action, _deviceId, _timestamp) => { this._onAccelerator(action); }, ); @@ -24,8 +22,8 @@ export const KeyboardShortcuts = class { listenFor(accelerator, callback) { let action = global.display.grab_accelerator(accelerator, 0); - if (action == Meta.KeyBindingAction.NONE) { - console.log(`Unable to grab accelerator ${accelerator}`); + if (action === Meta.KeyBindingAction.NONE) { + log(`Unable to grab accelerator ${accelerator}`); return; } @@ -33,12 +31,12 @@ export const KeyboardShortcuts = class { Main.wm.allowKeybinding(name, Shell.ActionMode.ALL); this._grabbers[action] = { - name: name, - accelerator: accelerator, - callback: callback, + name, + accelerator, + callback, }; - console.log(`Grabbed ${accelerator}`); + log(`Grabbed ${accelerator}`); } unlisten() { @@ -58,7 +56,7 @@ export const KeyboardShortcuts = class { if (grabber) { grabber.callback(); } else { - console.log(`No listeners ${action}`); + log(`No listeners ${action}`); } } }; diff --git a/metadata.json b/metadata.json index 9d5f05c..fcdaef9 100644 --- a/metadata.json +++ b/metadata.json @@ -6,7 +6,7 @@ "48", "49", "50" ], "url": "https://github.com/icedman/search-light", - "schema-id": "org.gnome.shell.extensions.search-light", + "settings-schema": "org.gnome.shell.extensions.search-light", "gettext-domain": "search-light", - "version": 101 + "version": 102 } diff --git a/preferences/prefKeys.js b/preferences/prefKeys.js index 9ccc301..8eabd2f 100644 --- a/preferences/prefKeys.js +++ b/preferences/prefKeys.js @@ -27,8 +27,8 @@ export let PrefKeys = class { default_value, widget_type, value: default_value, - maps: maps, - test: test, + maps, + test, callback, options, object: null, @@ -99,7 +99,6 @@ export let PrefKeys = class { this._settings = settings; let builder = this._builder; - let self = this; let keys = this._keys; Object.keys(keys).forEach((name) => { @@ -216,7 +215,6 @@ export let PrefKeys = class { this._builderListeners = []; this._builder = builder; - let self = this; let keys = this._keys; Object.keys(keys).forEach((name) => { let key = keys[name]; @@ -235,7 +233,7 @@ export let PrefKeys = class { key.object.set_active(key.default_value); signal_id = key.object.connect('state-set', (w) => { let value = w.get_active(); - self.setValue(name, value); + this.setValue(name, value); if (key.callback) { key.callback(value); } @@ -246,14 +244,14 @@ export let PrefKeys = class { signal_id = key.object.connect('notify::selected-item', (w) => { let index = w.get_selected(); let value = key.maps && index in key.maps ? key.maps[index] : index; - self.setValue(name, value); + this.setValue(name, value); }); break; } case 'scale': { signal_id = key.object.connect('value-changed', (w) => { let value = w.get_value(); - self.setValue(name, value); + this.setValue(name, value); }); break; } @@ -261,12 +259,12 @@ export let PrefKeys = class { signal_id = key.object.connect('color-set', (w) => { let rgba = w.get_rgba(); let value = [rgba.red, rgba.green, rgba.blue, rgba.alpha]; - self.setValue(name, value); + this.setValue(name, value); }); break; } case 'button': { - signal_id = key.object.connect('clicked', (w) => { + signal_id = key.object.connect('clicked', (_w) => { if (key.callback) { key.callback(); } @@ -278,7 +276,7 @@ export let PrefKeys = class { // when do we clean this up? this._builderListeners.push({ source: key.object, - signal_id: signal_id, + signal_id, }); }); } diff --git a/prefs.js b/prefs.js index 0cc3959..8502bd7 100644 --- a/prefs.js +++ b/prefs.js @@ -6,8 +6,6 @@ import Gio from 'gi://Gio'; import { ShortcutSettingWidget } from './shortcuts.js'; -const GETTEXT_DOMAIN = 'search-light'; - import { schemaId, SettingsKeys } from './preferences/keys.js'; import { MonitorsConfig } from './monitors.js'; @@ -22,7 +20,7 @@ export default class Preferences extends ExtensionPreferences { let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); let UIFolderPath = `${this.path}/ui`; iconTheme.add_search_path(`${UIFolderPath}/icons`); - // ExtensionUtils.initTranslations(GETTEXT_DOMAIN); + // ExtensionUtils.initTranslations('search-light'); } find(n, name) { @@ -102,7 +100,7 @@ export default class Preferences extends ExtensionPreferences { // window.remove(menu_util); } - addButtonEvents(window, builder, settings) { + addButtonEvents(_window, _builder, _settings) { // } diff --git a/shortcuts.js b/shortcuts.js index 5efadb7..f5b9d53 100644 --- a/shortcuts.js +++ b/shortcuts.js @@ -109,7 +109,7 @@ export let ShortcutSettingWidget = class extends Gtk.Button { ); } - console.log('saved new shortcut'); + log('saved new shortcut'); this.emit('changed', this.shortcut); this._settings.set_strv(this._key, [this.shortcut]); diff --git a/style.js b/style.js index 731b0cb..79382f9 100644 --- a/style.js +++ b/style.js @@ -22,7 +22,7 @@ export let Style = class { try { fn.delete(null); } catch (err) { - console.log(err); + logError(err); } }); } @@ -50,7 +50,7 @@ export let Style = class { } this.style_contents[name] = content; - const [, etag] = fn.replace_contents( + fn.replace_contents( content, null, false, @@ -78,7 +78,7 @@ export let Style = class { if (g.length == 1) g += g; if (b.length == 1) b += b; let res = `#${r}${g}${b}`; - console.log(`${color} ${res}`); + log(`${color} ${res}`); return res; } }; diff --git a/timer.js b/timer.js index 9fc5dd4..9692b62 100644 --- a/timer.js +++ b/timer.js @@ -347,9 +347,9 @@ export const Timer = class { } runAnimation(array, settings) { - if (typeof func === 'object' && !array.length) { - func._time = 0; - return this.subscribe(func); + if (!Array.isArray(array)) { + array._time = 0; + return this.subscribe(array); } let duration = 0; From 4d1900dc5d158fddd600b5af488162bf5944902e Mon Sep 17 00:00:00 2001 From: Chris Ondrovic Date: Fri, 10 Apr 2026 18:50:00 -0400 Subject: [PATCH 2/2] fix: stop switch prefs clobbering GSettings; fix shortcut key controller lifecycle --- CHANGELOG.md | 8 ++++++++ preferences/prefKeys.js | 3 ++- shortcuts.js | 7 +++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4721e9..16bbe9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## ROADMAP +## release 39 + +* add GNOME 50 support (`shell-version` in metadata) +* Makefile: run nested shell tests with `gnome-shell --devkit` instead of `--nested` +* extension: drop `affectsInputRegion` when adding chrome (GNOME 50) +* fix preferences: switch toggles no longer overwrite saved GSettings on load +* fix shortcut editor: attach key controller only when creating the accelerator window + ## release 38 * fork gnome 48 from 47 diff --git a/preferences/prefKeys.js b/preferences/prefKeys.js index 8eabd2f..c078ec0 100644 --- a/preferences/prefKeys.js +++ b/preferences/prefKeys.js @@ -230,7 +230,8 @@ export let PrefKeys = class { break; } case 'switch': { - key.object.set_active(key.default_value); + // Do not set_active(default_value) here: it runs before connectSettings + // and emits state-set, which writes defaults over real GSettings values. signal_id = key.object.connect('state-set', (w) => { let value = w.get_active(); this.setValue(name, value); diff --git a/shortcuts.js b/shortcuts.js index f5b9d53..27b17a8 100644 --- a/shortcuts.js +++ b/shortcuts.js @@ -53,8 +53,6 @@ export let ShortcutSettingWidget = class extends Gtk.Button { } _onActivated(widget) { - let ctl = new Gtk.EventControllerKey(); - if (!this._editor) { this._editor = new Gtk.Window({ title: 'Accelerator', @@ -65,10 +63,11 @@ export let ShortcutSettingWidget = class extends Gtk.Button { height_request: 320, child: this.content, }); + let ctl = new Gtk.EventControllerKey(); + ctl.connect('key-pressed', this._onKeyPressed.bind(this)); + this._editor.add_controller(ctl); } - this._editor.add_controller(ctl); - ctl.connect('key-pressed', this._onKeyPressed.bind(this)); this._editor.present(); }