From 270e63b57e6c6165a8fc4525bd6b06c34911a47a Mon Sep 17 00:00:00 2001 From: Florian Müllner Date: Feb 23 2021 17:54:04 +0000 Subject: [PATCH 1/4] prefs: Support handling slide shows without GnomeDesktop GnomeDesktop is a dependency of gnome-shell itself, so it is safe to assume that it is available. However extension prefs must port to GTK4 now, and gnome-desktop is still gtk3-only at this point. In order to not let GnomeDesktop block the port, add a simplistic fallback handling for slide shows, where we simply grep the first element from the XML. --- diff --git a/prefs.js b/prefs.js index 9b2546e..f402df0 100644 --- a/prefs.js +++ b/prefs.js @@ -1,5 +1,13 @@ /* exported init, buildPrefsWidget */ -const { Gdk, GdkPixbuf, Gio, GnomeDesktop, GObject, Gtk } = imports.gi; +const { Gdk, GdkPixbuf, Gio, GObject, Gtk } = imports.gi; +const ByteArray = imports.byteArray; + +let GnomeDesktop = null; +try { + GnomeDesktop = imports.gi.GnomeDesktop; +} catch (e) { + // not compatible with GTK4 yet +} const ExtensionUtils = imports.misc.extensionUtils; @@ -132,19 +140,29 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { cr.paintWithAlpha(this._settings.get_uint('logo-opacity') / 255.0); } + _getSlideShowSlide(file, width, height) { + if (GnomeDesktop) { + const slideShow = new GnomeDesktop.BGSlideShow({ file }); + slideShow.load(); + + const [progress_, duration_, isFixed_, filename1, filename2_] = + slideShow.get_current_slide(width, height); + return Gio.File.new_for_commandline_arg(filename1); + } else { + const [, contents] = file.load_contents(null); + const str = ByteArray.toString(contents); + const [, filename1] = str.match(/(.*)<\/file>/); + return Gio.File.new_for_commandline_arg(filename1); + } + } + _createBackgroundThumbnail(width, height) { let settings = new Gio.Settings({ schema_id: BACKGROUND_SCHEMA }); let uri = settings.get_default_value('picture-uri').deep_unpack(); let file = Gio.File.new_for_commandline_arg(uri); - if (uri.endsWith('.xml')) { - let slideShow = new GnomeDesktop.BGSlideShow({ file }); - slideShow.load(); - - let [progress_, duration_, isFixed_, filename1, filename2_] = - slideShow.get_current_slide(width, height); - file = Gio.File.new_for_commandline_arg(filename1); - } + if (uri.endsWith('.xml')) + file = this._getSlideShowSlide(file, width, height); let pixbuf = GdkPixbuf.Pixbuf.new_from_file(file.get_path()); this._background = pixbuf.scale_simple( width, height, GdkPixbuf.InterpType.BILINEAR); From fdd3239a372726a736e6868b1e79166d1136bd35 Mon Sep 17 00:00:00 2001 From: Florian Müllner Date: Feb 23 2021 18:01:26 +0000 Subject: [PATCH 2/4] prefs: Don't try to use actual monitor ratio The current way for (maybe) figuring out the ratio relies on deprecated API that is no longer available in GTK4. The new API works properly on wayland, but is tied to surfaces which makes it fiddlier to use. Considering that matching the output ratio doesn't really provide any value, just show the preview at a fixed ratio of 16:9. --- diff --git a/prefs.js b/prefs.js index f402df0..aea2834 100644 --- a/prefs.js +++ b/prefs.js @@ -25,8 +25,6 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { row_spacing: 6, }); - this.connect('screen-changed', this._onScreenChanged.bind(this)); - this._settings = ExtensionUtils.getSettings(); this._settings.connect('changed', (settings, key) => { if (key === 'logo-file' || @@ -38,6 +36,8 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { this._preview = new Gtk.DrawingArea({ halign: Gtk.Align.CENTER, margin_bottom: 18, + width_request: PREVIEW_WIDTH, + height_request: PREVIEW_WIDTH * 9 / 16, }); this._preview.connect('draw', this._drawPreview.bind(this)); this.attach(this._preview, 0, 0, 2, 1); @@ -181,7 +181,7 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { } _getLogoPosition(width, height) { - let scaledBorder = this._settings.get_uint('logo-border') * this._scale; + let scaledBorder = this._settings.get_uint('logo-border'); let x, y; switch (this._settings.get_string('logo-position')) { case 'center': @@ -203,25 +203,6 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { } return [x, y]; } - - _onScreenChanged() { - let screen = this.get_screen(); - if (!screen) - return; - - let rect = screen.get_monitor_geometry(screen.get_primary_monitor()); - - // If we can't get the actual geometry (wayland), use sane fallbacks - if (rect.width === 0 || rect.height === 0) { - rect.width = PREVIEW_WIDTH; - rect.height = PREVIEW_WIDTH * 9 / 16; - } - - this._scale = PREVIEW_WIDTH / rect.width; - this._preview.set_size_request( - PREVIEW_WIDTH, - PREVIEW_WIDTH * rect.height / rect.width); - } }); function init() { From 039335b6d372374872845abbd4c8852bd4edf849 Mon Sep 17 00:00:00 2001 From: Florian Müllner Date: Feb 23 2021 18:16:58 +0000 Subject: [PATCH 3/4] prefs: Replace FileChooserButton The widget is gone in GTK4, so replace it with a regular button that launches a native FileChooserDialog. --- diff --git a/prefs.js b/prefs.js index aea2834..1316207 100644 --- a/prefs.js +++ b/prefs.js @@ -1,5 +1,5 @@ /* exported init, buildPrefsWidget */ -const { Gdk, GdkPixbuf, Gio, GObject, Gtk } = imports.gi; +const { Gdk, GdkPixbuf, Gio, GLib, GObject, Gtk } = imports.gi; const ByteArray = imports.byteArray; let GnomeDesktop = null; @@ -42,18 +42,31 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { this._preview.connect('draw', this._drawPreview.bind(this)); this.attach(this._preview, 0, 0, 2, 1); - let filter = new Gtk.FileFilter(); + const filter = new Gtk.FileFilter(); filter.add_pixbuf_formats(); - let fileChooser = new Gtk.FileChooserButton({ + this._fileChooser = new Gtk.FileChooserNative({ title: 'Select an Image', filter, + modal: true, }); - fileChooser.set_filename(this._settings.get_string('logo-file')); - fileChooser.connect('file-set', () => { - this._settings.set_string('logo-file', fileChooser.get_filename()); + this._fileChooser.connect('response', (dlg, response) => { + if (response !== Gtk.ResponseType.ACCEPT) + return; + this._settings.set_string('logo-file', dlg.get_file().get_path()); }); - this._addRow(1, 'Logo image', fileChooser); + + this._logoPicker = new Gtk.Button({ + label: '(None)', + }); + this._logoPicker.connect('clicked', () => { + this._fileChooser.transient_for = this.get_toplevel(); + this._fileChooser.show(); + }); + this._settings.connect('changed::logo-file', + this._updateLogoPicker.bind(this)); + this._updateLogoPicker(); + this._addRow(1, 'Logo image', this._logoPicker); let comboBox = new Gtk.ComboBoxText(); comboBox.append('center', 'Center'); @@ -203,6 +216,17 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { } return [x, y]; } + + _updateLogoPicker() { + const filename = this._settings.get_string('logo-file'); + this._logoPicker.label = GLib.basename(filename); + } + + on_destroy() { + if (this._fileChooser) + this._fileChooser.destroy(); + this._fileChooser = null; + } }); function init() { From a46be17dfeb53c3454812410207a8ea4eb217b76 Mon Sep 17 00:00:00 2001 From: Florian Müllner Date: Feb 23 2021 18:21:53 +0000 Subject: [PATCH 4/4] prefs: Port to GTK4 Extension preferences must use GTK4 in GNOME 40. --- diff --git a/prefs.js b/prefs.js index 1316207..a2ce27a 100644 --- a/prefs.js +++ b/prefs.js @@ -20,7 +20,10 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { _init() { super._init({ halign: Gtk.Align.CENTER, - margin: 24, + margin_top: 24, + margin_bottom: 24, + margin_start: 24, + margin_end: 24, column_spacing: 12, row_spacing: 6, }); @@ -39,7 +42,7 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { width_request: PREVIEW_WIDTH, height_request: PREVIEW_WIDTH * 9 / 16, }); - this._preview.connect('draw', this._drawPreview.bind(this)); + this._preview.set_draw_func(this._drawPreview.bind(this)); this.attach(this._preview, 0, 0, 2, 1); const filter = new Gtk.FileFilter(); @@ -60,7 +63,7 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { label: '(None)', }); this._logoPicker.connect('clicked', () => { - this._fileChooser.transient_for = this.get_toplevel(); + this._fileChooser.transient_for = this.get_root(); this._fileChooser.show(); }); this._settings.connect('changed::logo-file', @@ -136,10 +139,7 @@ class BackgroundLogoPrefsWidget extends Gtk.Grid { return adj; } - _drawPreview(preview, cr) { - let width = preview.get_allocated_width(); - let height = preview.get_allocated_height(); - + _drawPreview(preview, cr, width, height) { if (!this._background) this._createBackgroundThumbnail(width, height); Gdk.cairo_set_source_pixbuf(cr, this._background, 0, 0); @@ -233,8 +233,5 @@ function init() { } function buildPrefsWidget() { - let widget = new BackgroundLogoPrefsWidget(); - widget.show_all(); - - return widget; + return new BackgroundLogoPrefsWidget(); }