From 24a9dc2ecb9df87f00992187877dace3328c5a48 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 27 May 2022 07:38:32 +0800 Subject: [PATCH 01/40] Port to GTK4 --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 03120f613..8fcfcfef7 100644 --- a/meson.build +++ b/meson.build @@ -26,8 +26,8 @@ add_project_arguments( gio_dep = dependency('gio-2.0') glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') -granite_dep = dependency('granite', version: '>=6.0.0') -gtk_dep = dependency('gtk+-3.0', version: '>= 3.22') +granite_dep = dependency('granite-7') +gtk_dep = dependency('gtk4') plank_dep = dependency('plank', version: '>=0.10.9') posix_dep = meson.get_compiler('vala').find_library('posix') From ad6137a5aa9e0dd89eebae6bd9d40c87f937d599 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Sun, 5 Jun 2022 15:07:05 +0300 Subject: [PATCH 02/40] Update meson --- meson.build | 1 - src/Config.vala.in | 1 - src/meson.build | 5 ----- 3 files changed, 7 deletions(-) diff --git a/meson.build b/meson.build index 8fcfcfef7..343290ea8 100644 --- a/meson.build +++ b/meson.build @@ -28,7 +28,6 @@ glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') granite_dep = dependency('granite-7') gtk_dep = dependency('gtk4') -plank_dep = dependency('plank', version: '>=0.10.9') posix_dep = meson.get_compiler('vala').find_library('posix') plug_resources = gnome.compile_resources( diff --git a/src/Config.vala.in b/src/Config.vala.in index e29e292f6..995886c21 100644 --- a/src/Config.vala.in +++ b/src/Config.vala.in @@ -1,5 +1,4 @@ namespace Constants { - public const string PLANKDATADIR = "@PLANKDATADIR@"; public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@"; public const string LOCALEDIR = "@LOCALEDIR@"; } diff --git a/src/meson.build b/src/meson.build index 842882288..234d59972 100644 --- a/src/meson.build +++ b/src/meson.build @@ -15,10 +15,7 @@ plug_files = files( switchboard_dep = dependency('switchboard-2.0') switchboard_plugsdir = switchboard_dep.get_pkgconfig_variable('plugsdir', define_variable: ['libdir', libdir]) -plank_datadir = plank_dep.get_pkgconfig_variable('pkgdatadir') - configuration = configuration_data() -configuration.set('PLANKDATADIR', plank_datadir) configuration.set('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir'))) configuration.set('GETTEXT_PACKAGE', meson.project_name() + '-plug') @@ -40,8 +37,6 @@ shared_module( granite_dep, gtk_dep, dependency('gexiv2'), - dependency('gnome-desktop-3.0'), - plank_dep, posix_dep, switchboard_dep ], From e817c47a3976306c783f122fc2424cb708b59553 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 10 Jun 2022 03:59:02 +0300 Subject: [PATCH 03/40] Fix crash --- set-wallpaper-contract/set-wallpaper.vala | 24 +-- src/Interfaces/MutterDisplayConfig.vala | 176 ++++++++++++++++++++ src/Plug.vala | 9 +- src/Views/Appearance.vala | 107 ++++++------ src/Views/Dock.vala | 190 ++++++++++++++-------- src/Views/Multitasking.vala | 21 ++- src/Views/Text.vala | 2 +- src/Views/Wallpaper.vala | 176 ++++++++++++-------- src/Widgets/WallpaperContainer.vala | 96 ++++++----- src/meson.build | 1 + 10 files changed, 551 insertions(+), 251 deletions(-) create mode 100644 src/Interfaces/MutterDisplayConfig.vala diff --git a/set-wallpaper-contract/set-wallpaper.vala b/set-wallpaper-contract/set-wallpaper.vala index a4bbc5b19..cecbad733 100644 --- a/set-wallpaper-contract/set-wallpaper.vala +++ b/set-wallpaper-contract/set-wallpaper.vala @@ -167,7 +167,6 @@ namespace SetWallpaperContractor { } public static int main (string[] args) { - Gtk.init (ref args); AccountsServiceUser? accounts_service = null; try { @@ -232,20 +231,25 @@ namespace SetWallpaperContractor { }; dialog.add_button (_("Create Slideshow"), Gtk.ResponseType.OK); dialog.set_default_response (Gtk.ResponseType.OK); - dialog.custom_bin.add (duration); - dialog.show_all (); + dialog.custom_bin.append (duration); + dialog.present (); delay_value_changed (duration, dialog.secondary_label); duration.value_changed.connect (() => delay_value_changed (duration, dialog.secondary_label)); - if (dialog.run () == Gtk.ResponseType.OK) { - dialog.destroy (); + int return_val = 1; + dialog.response.connect ((id) => { + if (id == Gtk.ResponseType.OK) { + dialog.destroy (); - var path = folder.get_child (SLIDESHOW_FILENAME).get_path (); - update_slideshow (path, files, delay_value); - return 0; - } + var path = folder.get_child (SLIDESHOW_FILENAME).get_path (); + update_slideshow (path, files, delay_value); + return_val = 0; + } else { + return_val = 1; + } + }); - return 1; + return return_val; } } diff --git a/src/Interfaces/MutterDisplayConfig.vala b/src/Interfaces/MutterDisplayConfig.vala new file mode 100644 index 000000000..181229810 --- /dev/null +++ b/src/Interfaces/MutterDisplayConfig.vala @@ -0,0 +1,176 @@ +/*- + * Copyright (c) 2018 elementary LLC. + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Authored by: Corentin Noël + */ + +[DBus (name = "org.gnome.Mutter.DisplayConfig")] +public interface MutterDisplayConfigInterface : Object { + public abstract void get_resources (out uint serial, out MutterReadDisplayCrtc[] crtcs, out MutterReadDisplayOutput[] outputs, out MutterReadDisplayMode[] modes, out int max_screen_width, out int max_screen_height) throws Error; + public abstract void apply_configuration (uint serial, bool persistent, MutterWriteDisplayCrtc[] crtcs, MutterWriteDisplayOutput[] outputs) throws Error; + public abstract int change_backlight (uint serial, uint output, int value) throws Error; + public abstract void get_crtc_gamma (uint serial, uint crtc, out uint[] red, out uint[] green, out uint[] blue) throws Error; + public abstract void set_crtc_gamma (uint serial, uint crtc, uint[] red, uint[] green, uint[] blue) throws Error; + public abstract int power_save_mode { get; set; } + public signal void monitors_changed (); + public abstract void get_current_state (out uint serial, out MutterReadMonitor[] monitors, out MutterReadLogicalMonitor[] logical_monitors, out GLib.HashTable properties) throws Error; + public abstract void apply_monitors_config (uint serial, MutterApplyMethod method, MutterWriteLogicalMonitor[] logical_monitors, GLib.HashTable properties) throws Error; +} + +[CCode (type_signature = "u")] +public enum MutterApplyMethod { + VERIFY = 0, + TEMPORARY = 1, + PERSISTENT = 2 +} + +[CCode (type_signature = "u")] +public enum DisplayTransform { + NORMAL = 0, + ROTATION_90 = 1, + ROTATION_180 = 2, + ROTATION_270 = 3, + FLIPPED = 4, + FLIPPED_ROTATION_90 = 5, + FLIPPED_ROTATION_180 = 6, + FLIPPED_ROTATION_270 = 7; + + public string to_string () { + // These values are based on the direction that the physical display has been rotated from its original position. + // They should not reflect the rotation that must be applied to the contents on screen. + switch (this) { + case ROTATION_90: + return _("Clockwise"); + case ROTATION_180: + return _("Upside-down"); + case ROTATION_270: + return _("Counterclockwise"); + case FLIPPED: + return _("Flipped"); + case FLIPPED_ROTATION_90: + return _("Flipped Clockwise"); + case FLIPPED_ROTATION_180: + return _("Flipped Upside-down"); + case FLIPPED_ROTATION_270: + return _("Flipped Counterclockwise"); + default: + return _("None"); + } + } +} + +public struct MutterReadMonitorInfo { + public string connector; + public string vendor; + public string product; + public string serial; + public uint hash { + get { + return (connector + vendor + product + serial).hash (); + } + } +} + +public struct MutterReadMonitorMode { + public string id; + public int width; + public int height; + public double frequency; + public double preferred_scale; + public double[] supported_scales; + public GLib.HashTable properties; +} + +public struct MutterReadMonitor { + public MutterReadMonitorInfo monitor; + public MutterReadMonitorMode[] modes; + public GLib.HashTable properties; +} + +public struct MutterReadLogicalMonitor { + public int x; + public int y; + public double scale; + public DisplayTransform transform; + public bool primary; + public MutterReadMonitorInfo[] monitors; + public GLib.HashTable properties; +} + +public struct MutterWriteMonitor { + public string connector; + public string monitor_mode; + public GLib.HashTable properties; +} + +public struct MutterWriteLogicalMonitor { + public int x; + public int y; + public double scale; + public DisplayTransform transform; + public bool primary; + public MutterWriteMonitor[] monitors; +} + +public struct MutterReadDisplayCrtc { + public uint id; + public int64 winsys_id; + public int x; + public int y; + public int width; + public int height; + public int current_mode; + public DisplayTransform current_transform; + public DisplayTransform[] transforms; + public GLib.HashTable properties; +} + +public struct MutterWriteDisplayCrtc { + public uint id; + public int new_mode; + public int x; + public int y; + public DisplayTransform transform; + public uint[] outputs; + public GLib.HashTable properties; +} + +public struct MutterReadDisplayOutput { + public uint id; + public int64 winsys_id; + public int current_crtc; + public uint[] possible_crtcs; + public string connector_name; + public uint[] modes; + public uint[] clones; + public GLib.HashTable properties; +} + +public struct MutterWriteDisplayOutput { + public uint id; + public GLib.HashTable properties; +} + +public struct MutterReadDisplayMode { + public uint id; + public int64 winsys_id; + public uint width; + public uint height; + public double frequency; + public uint flags; +} diff --git a/src/Plug.vala b/src/Plug.vala index fec7f070b..5b237765a 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -73,12 +73,15 @@ public class PantheonShell.Plug : Switchboard.Plug { var stack_switcher = new Gtk.StackSwitcher (); stack_switcher.stack = stack; stack_switcher.halign = Gtk.Align.CENTER; - stack_switcher.homogeneous = true; - stack_switcher.margin = 24; + // stack_switcher.homogeneous = true; + stack_switcher.margin_start = 24; + stack_switcher.margin_end = 24; + stack_switcher.margin_top = 24; + stack_switcher.margin_bottom = 24; main_grid.attach (stack_switcher, 0, 0, 1, 1); main_grid.attach (stack, 0, 1, 1, 1); - main_grid.show_all (); + // main_grid.show_all (); } return main_grid; diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala index de16374de..8d5368813 100644 --- a/src/Views/Appearance.vala +++ b/src/Views/Appearance.vala @@ -76,10 +76,12 @@ public class PantheonShell.Appearance : Gtk.Grid { var prefer_default_image = new Gtk.Image.from_resource ("/io/elementary/switchboard/plug/pantheon-shell/appearance-default.svg"); var prefer_default_card = new Gtk.Grid () { - margin = 6, + margin_top = 6, + margin_bottom = 6, + margin_end = 6, margin_start = 12 }; - prefer_default_card.add (prefer_default_image); + prefer_default_card.attach (prefer_default_image, 0, 0); unowned Gtk.StyleContext prefer_default_card_context = prefer_default_card.get_style_context (); prefer_default_card_context.add_class (Granite.STYLE_CLASS_CARD); @@ -91,19 +93,21 @@ public class PantheonShell.Appearance : Gtk.Grid { prefer_default_grid.attach (prefer_default_card, 0, 0); prefer_default_grid.attach (new Gtk.Label (_("Default")), 0, 1); - var prefer_default_radio = new Gtk.RadioButton (null) { + var prefer_default_radio = new Gtk.CheckButton () { halign = Gtk.Align.START }; prefer_default_radio.get_style_context ().add_class ("image-button"); - prefer_default_radio.add (prefer_default_grid); + prefer_default_grid.set_parent (prefer_default_radio); var prefer_dark_image = new Gtk.Image.from_resource ("/io/elementary/switchboard/plug/pantheon-shell/appearance-dark.svg"); var prefer_dark_card = new Gtk.Grid () { - margin = 6, + margin_top = 6, + margin_bottom = 6, + margin_end = 6, margin_start = 12 }; - prefer_dark_card.add (prefer_dark_image); + prefer_dark_card.attach (prefer_dark_image, 0, 0); unowned Gtk.StyleContext prefer_dark_card_context = prefer_dark_card.get_style_context (); prefer_dark_card_context.add_class (Granite.STYLE_CLASS_CARD); @@ -115,55 +119,57 @@ public class PantheonShell.Appearance : Gtk.Grid { prefer_dark_grid.attach (prefer_dark_card, 0, 0); prefer_dark_grid.attach (new Gtk.Label (_("Dark")), 0, 1); - var prefer_dark_radio = new Gtk.RadioButton.from_widget (prefer_default_radio) { + var prefer_dark_radio = new Gtk.CheckButton () { halign = Gtk.Align.START, - hexpand = true + hexpand = true, + group = prefer_default_radio }; prefer_dark_radio.get_style_context ().add_class ("image-button"); - prefer_dark_radio.add (prefer_dark_grid); + prefer_dark_grid.set_parent (prefer_dark_radio); var prefer_style_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); - prefer_style_box.add (prefer_default_radio); - prefer_style_box.add (prefer_dark_radio); + prefer_style_box.append (prefer_default_radio); + prefer_style_box.append (prefer_dark_radio); var dark_info = new Gtk.Label (_("Preferred visual style for system components. Apps may also choose to follow this preference.")) { max_width_chars = 60, wrap = true, xalign = 0 }; - dark_info.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); + dark_info.get_style_context ().add_class (Granite.STYLE_CLASS_DIM_LABEL); var schedule_label = new Granite.HeaderLabel (_("Schedule")); - var schedule_disabled_radio = new Gtk.RadioButton.with_label (null, _("Disabled")) { + var schedule_disabled_radio = new Gtk.CheckButton.with_label (_("Disabled")) { margin_bottom = 3 }; - var schedule_sunset_radio = new Gtk.RadioButton.with_label_from_widget ( - schedule_disabled_radio, - _("Sunset to Sunrise") - ); + var schedule_sunset_radio = new Gtk.CheckButton.with_label (_("Sunset to Sunrise")) { + group = schedule_disabled_radio + }; var from_label = new Gtk.Label (_("From:")); - var from_time = new Granite.Widgets.TimePicker () { + var from_time = new Granite.TimePicker () { hexpand = true, margin_end = 6 }; var to_label = new Gtk.Label (_("To:")); - var to_time = new Granite.Widgets.TimePicker () { + var to_time = new Granite.TimePicker () { hexpand = true }; var schedule_manual_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); - schedule_manual_box.add (from_label); - schedule_manual_box.add (from_time); - schedule_manual_box.add (to_label); - schedule_manual_box.add (to_time); + schedule_manual_box.append (from_label); + schedule_manual_box.append (from_time); + schedule_manual_box.append (to_label); + schedule_manual_box.append (to_time); - var schedule_manual_radio = new Gtk.RadioButton.from_widget (schedule_disabled_radio) ; + var schedule_manual_radio = new Gtk.CheckButton () { + group = schedule_disabled_radio + }; Pantheon.AccountsService? pantheon_act = null; @@ -223,15 +229,15 @@ public class PantheonShell.Appearance : Gtk.Grid { /* Connect to button_release_event so that this is only triggered * through user interaction, not if scheduling changes the selection */ - prefer_default_radio.button_release_event.connect (() => { - schedule_disabled_radio.active = true; - return Gdk.EVENT_PROPAGATE; - }); + // prefer_default_radio.button_release_event.connect (() => { + // schedule_disabled_radio.active = true; + // return Gdk.EVENT_PROPAGATE; + // }); - prefer_dark_radio.button_release_event.connect (() => { - schedule_disabled_radio.active = true; - return Gdk.EVENT_PROPAGATE; - }); + // prefer_dark_radio.button_release_event.connect (() => { + // schedule_disabled_radio.active = true; + // return Gdk.EVENT_PROPAGATE; + // }); ((GLib.DBusProxy) pantheon_act).g_properties_changed.connect ((changed, invalid) => { var color_scheme = changed.lookup_value ("PrefersColorScheme", new VariantType ("i")); @@ -267,15 +273,15 @@ public class PantheonShell.Appearance : Gtk.Grid { schedule_disabled_radio.active = true; } - schedule_disabled_radio.clicked.connect (() => { + schedule_disabled_radio.toggled.connect (() => { settings.set_string ("prefer-dark-schedule", "disabled"); }); - schedule_manual_radio.clicked.connect (() => { + schedule_manual_radio.toggled.connect (() => { settings.set_string ("prefer-dark-schedule", "manual"); }); - schedule_sunset_radio.clicked.connect (() => { + schedule_sunset_radio.toggled.connect (() => { settings.set_string ("prefer-dark-schedule", "sunset-to-sunrise"); }); @@ -325,25 +331,24 @@ public class PantheonShell.Appearance : Gtk.Grid { var auto_button = new PrefersAccentColorButton (pantheon_act, AccentColor.NO_PREFERENCE, blueberry_button); auto_button.tooltip_text = _("Automatic based on wallpaper"); - var accent_grid = new Gtk.Grid (); - accent_grid.column_spacing = 6; - accent_grid.add (blueberry_button); - accent_grid.add (mint_button); - accent_grid.add (lime_button); - accent_grid.add (banana_button); - accent_grid.add (orange_button); - accent_grid.add (strawberry_button); - accent_grid.add (bubblegum_button); - accent_grid.add (grape_button); - accent_grid.add (cocoa_button); - accent_grid.add (slate_button); - accent_grid.add (auto_button); + var accent_grid = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); + accent_grid.append (blueberry_button); + accent_grid.append (mint_button); + accent_grid.append (lime_button); + accent_grid.append (banana_button); + accent_grid.append (orange_button); + accent_grid.append (strawberry_button); + accent_grid.append (bubblegum_button); + accent_grid.append (grape_button); + accent_grid.append (cocoa_button); + accent_grid.append (slate_button); + accent_grid.append (auto_button); var accent_info = new Gtk.Label (_("Used across the system by default. Apps can always use their own accent color.")) { xalign = 0, wrap = true }; - accent_info.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); + accent_info.get_style_context ().add_class (Granite.STYLE_CLASS_DIM_LABEL); attach (accent_label, 0, 7, 2); attach (accent_info, 0, 8, 2); @@ -351,13 +356,13 @@ public class PantheonShell.Appearance : Gtk.Grid { } } - private class PrefersAccentColorButton : Gtk.RadioButton { + private class PrefersAccentColorButton : Gtk.CheckButton { public AccentColor color { get; construct; } public Pantheon.AccountsService? pantheon_act { get; construct; default = null; } private static GLib.Settings interface_settings; - public PrefersAccentColorButton (Pantheon.AccountsService? pantheon_act, AccentColor color, Gtk.RadioButton? group_member = null) { + public PrefersAccentColorButton (Pantheon.AccountsService? pantheon_act, AccentColor color, Gtk.CheckButton? group_member = null) { Object ( pantheon_act: pantheon_act, color: color, diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index 981770cb3..ab0da8870 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -25,46 +25,70 @@ public class PantheonShell.Dock : Gtk.Grid { private Gtk.Switch primary_monitor; private Gtk.Label monitor_label; private Gtk.ComboBoxText monitor; - private Plank.DockPreferences dock_preferences; + private Settings dock_preferences; + private MutterDisplayConfigInterface iface; + + private enum PlankHideTypes { + NONE, + INTELLIGENT, + AUTO, + DODGE_MAXIMIZED, + WINDOW_DODGE, + DODGE_ACTIVE + } construct { var dock_header = new Granite.HeaderLabel (_("Dock")); - weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_default (); + weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); default_theme.add_resource_path ("/io/elementary/switchboard/plug/pantheon-shell"); - var icon_size_32 = new Gtk.RadioButton (null); - icon_size_32.image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic", Gtk.IconSize.DND); + var icon_size_32 = new Gtk.CheckButton (); icon_size_32.tooltip_text = _("Small"); + var icon_size_32_image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic") { + pixel_size = 32 + }; + icon_size_32_image.set_parent (icon_size_32); - var icon_size_48 = new Gtk.RadioButton.from_widget (icon_size_32); - icon_size_48.image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic", Gtk.IconSize.DIALOG); + var icon_size_48 = new Gtk.CheckButton (); icon_size_48.tooltip_text = _("Default"); + icon_size_48.group = icon_size_32; + var icon_size_48_image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic") { + pixel_size = 48 + }; + icon_size_48_image.set_parent (icon_size_48); var image_64 = new Gtk.Image (); image_64.icon_name = "application-default-icon-symbolic"; image_64.pixel_size = 64; - var icon_size_64 = new Gtk.RadioButton.from_widget (icon_size_32); - icon_size_64.image = image_64; + var icon_size_64 = new Gtk.CheckButton (); icon_size_64.tooltip_text = _("Large"); + icon_size_64.group = icon_size_32; + image_64.set_parent (icon_size_64); - var icon_size_unsupported = new Gtk.RadioButton.from_widget (icon_size_32); + var icon_size_unsupported = new Gtk.CheckButton () { + group = icon_size_32 + }; + + var icon_size_grid = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 24); + icon_size_grid.append (icon_size_32); + icon_size_grid.append (icon_size_48); + icon_size_grid.append (icon_size_64); - var icon_size_grid = new Gtk.Grid (); - icon_size_grid.column_spacing = 24; - icon_size_grid.add (icon_size_32); - icon_size_grid.add (icon_size_48); - icon_size_grid.add (icon_size_64); + var schema_id = "net.launchpad.plank.dock.settings"; + var schema = GLib.SettingsSchemaSource.get_default ().lookup (schema_id, true); + if (schema == null) { + error ("GSettingsSchema '%s' not found", schema_id); + } - Plank.Paths.initialize ("plank", Constants.PLANKDATADIR); - dock_preferences = new Plank.DockPreferences ("dock1"); + dock_preferences = new Settings.full (schema, null, "/net/launchpad/plank/docks/dock1/"); var pressure_switch = new Gtk.Switch (); pressure_switch.halign = Gtk.Align.START; pressure_switch.valign = Gtk.Align.CENTER; - dock_preferences.bind_property ("PressureReveal", pressure_switch, "active", GLib.BindingFlags.SYNC_CREATE | GLib.BindingFlags.BIDIRECTIONAL); + dock_preferences.bind ("pressure-reveal", pressure_switch, "active", GLib.SettingsBindFlags.DEFAULT); var hide_mode = new Gtk.ComboBoxText (); hide_mode.append_text (_("Focused window is maximized")); @@ -72,35 +96,36 @@ public class PantheonShell.Dock : Gtk.Grid { hide_mode.append_text (_("Any window overlaps the dock")); hide_mode.append_text (_("Not being used")); - Plank.HideType[] hide_mode_ids = {Plank.HideType.DODGE_MAXIMIZED, Plank.HideType.INTELLIGENT, Plank.HideType.WINDOW_DODGE, Plank.HideType.AUTO}; + PlankHideTypes[] hide_mode_ids = {PlankHideTypes.DODGE_MAXIMIZED, PlankHideTypes.INTELLIGENT, PlankHideTypes.WINDOW_DODGE, PlankHideTypes.AUTO}; var hide_switch = new Gtk.Switch (); hide_switch.halign = Gtk.Align.START; hide_switch.valign = Gtk.Align.CENTER; - var hide_none = (dock_preferences.HideMode != Plank.HideType.NONE); + var hide_none = (dock_preferences.get_enum ("hide-mode") != PlankHideTypes.NONE); hide_switch.active = hide_none; if (hide_none) { - for (int i = 0; i < hide_mode_ids.length; i++) { - if (hide_mode_ids[i] == dock_preferences.HideMode) + for (var i = 0; i < hide_mode_ids.length; i++) { + if (hide_mode_ids[i] == dock_preferences.get_enum ("hide-mode")) { hide_mode.active = i; + } } } else { hide_mode.sensitive = false; } - hide_mode.changed.connect (() => { - dock_preferences.HideMode = hide_mode_ids[hide_mode.active]; - }); - hide_switch.bind_property ("active", pressure_switch, "sensitive", BindingFlags.SYNC_CREATE); hide_switch.bind_property ("active", hide_mode, "sensitive", BindingFlags.DEFAULT); + hide_mode.changed.connect (() => { + dock_preferences.set_enum ("hide-mode", hide_mode_ids[hide_mode.active]); + }); + hide_switch.notify["active"].connect (() => { if (hide_switch.active) { - dock_preferences.HideMode = hide_mode_ids[hide_mode.active]; + dock_preferences.set_enum ("hide-mode", hide_mode_ids[hide_mode.active]); } else { - dock_preferences.HideMode = Plank.HideType.NONE; + dock_preferences.set_enum ("hide-mode", PlankHideTypes.NONE); } }); @@ -108,45 +133,51 @@ public class PantheonShell.Dock : Gtk.Grid { primary_monitor_label = new Gtk.Label (_("Primary display:")); primary_monitor_label.halign = Gtk.Align.END; - primary_monitor_label.no_show_all = true; + // primary_monitor_label.no_show_all = true; monitor_label = new Gtk.Label (_("Display:")); - monitor_label.no_show_all = true; + // monitor_label.no_show_all = true; monitor_label.halign = Gtk.Align.END; primary_monitor = new Gtk.Switch (); - primary_monitor.no_show_all = true; + // primary_monitor.no_show_all = true; primary_monitor.notify["active"].connect (() => { if (primary_monitor.active == true) { - dock_preferences.Monitor = ""; + dock_preferences.set_string ("monitor", ""); monitor_label.sensitive = false; monitor.sensitive = false; } else { var plug_names = get_monitor_plug_names (get_display ()); if (plug_names.length > monitor.active) - dock_preferences.Monitor = plug_names[monitor.active]; + dock_preferences.set_string ("monitor", plug_names[monitor.active]); monitor_label.sensitive = true; monitor.sensitive = true; } }); - primary_monitor.active = (dock_preferences.Monitor == ""); + primary_monitor.active = (dock_preferences.get_string ("monitor") == ""); monitor.notify["active"].connect (() => { if (monitor.active >= 0 && primary_monitor.active == false) { var plug_names = get_monitor_plug_names (get_display ()); if (plug_names.length > monitor.active) - dock_preferences.Monitor = plug_names[monitor.active]; + dock_preferences.set_string ("monitor", plug_names[monitor.active]); } }); - get_screen ().monitors_changed.connect (() => {check_for_screens ();}); + try { + iface = Bus.get_proxy_sync (BusType.SESSION, "org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig"); + } catch (Error e) { + critical (e.message); + } + + iface.monitors_changed.connect (() => {check_for_screens ();}); var icon_label = new Gtk.Label (_("Icon size:")); icon_label.halign = Gtk.Align.END; var hide_label = new Gtk.Label (_("Hide when:")); hide_label.halign = Gtk.Align.END; var primary_monitor_grid = new Gtk.Grid (); - primary_monitor_grid.add (primary_monitor); + primary_monitor_grid.attach (primary_monitor, 0, 0); var pressure_label = new Gtk.Label (_("Pressure reveal:")); pressure_label.halign = Gtk.Align.END; @@ -185,7 +216,7 @@ public class PantheonShell.Dock : Gtk.Grid { check_for_screens (); - switch (dock_preferences.IconSize) { + switch (dock_preferences.get_int ("icon-size")) { case 32: icon_size_32.active = true; break; @@ -201,15 +232,15 @@ public class PantheonShell.Dock : Gtk.Grid { } icon_size_32.toggled.connect (() => { - dock_preferences.IconSize = 32; + dock_preferences.set_int ("icon-size", 32); }); icon_size_48.toggled.connect (() => { - dock_preferences.IconSize = 48; + dock_preferences.set_int ("icon-size", 48); }); icon_size_64.toggled.connect (() => { - dock_preferences.IconSize = 64; + dock_preferences.set_int ("icon-size", 64); }); var panel_settings = new GLib.Settings (PANEL_SCHEMA); @@ -220,29 +251,55 @@ public class PantheonShell.Dock : Gtk.Grid { int i = 0; int primary_screen = 0; var default_display = get_display (); - var default_screen = get_screen (); + // var default_screen = get_screen (); monitor.remove_all (); try { - var screen = new Gnome.RRScreen (default_screen); - for (i = 0; i < default_display.get_n_monitors () ; i++) { - var monitor_plug_name = default_display.get_monitor (i).model; - - if (monitor_plug_name != null) { - unowned Gnome.RROutput output = screen.get_output_by_name (monitor_plug_name); - if (output != null && output.get_display_name () != null && output.get_display_name () != "") { - monitor.append_text (output.get_display_name ()); - if (output.get_is_primary () == true) { - primary_screen = i; - } - continue; - } - } + // var screen = new Gnome.RRScreen (default_screen); + // for (i = 0; i < default_display.get_n_monitors () ; i++) { + // var monitor_plug_name = default_display.get_monitor (i).model; + + // if (monitor_plug_name != null) { + // unowned Gnome.RROutput output = screen.get_output_by_name (monitor_plug_name); + // if (output != null && output.get_display_name () != null && output.get_display_name () != "") { + // monitor.append_text (output.get_display_name ()); + // if (output.get_is_primary () == true) { + // primary_screen = i; + // } + // continue; + // } + // } + + // monitor.append_text (_("Monitor %d").printf (i + 1) ); + // } + + // the following code was taken from switchboard-plug-display + + MutterReadMonitor[] mutter_monitors; + MutterReadLogicalMonitor[] mutter_logical_monitors; + GLib.HashTable properties; + uint current_serial; + + try { + iface.get_current_state (out current_serial, out mutter_monitors, out mutter_logical_monitors, out properties); + } catch (Error e) { + critical (e.message); + } + + foreach (var mutter_monitor in mutter_monitors) { + var display_name_variant = mutter_monitor.properties.lookup ("display-name"); + if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { + monitor.append_text (display_name_variant.get_string ()); + // var is_preferred = mutter_monitor.modes.properties.lookup ("is-preferred");; + // if (is_preferred.get_boolean () == true) { + // primary_screen = i; + // } - monitor.append_text (_("Monitor %d").printf (i + 1) ); + i++; + } } } catch (Error e) { critical (e.message); - for (i = 0; i < default_display.get_n_monitors () ; i ++) { + for (i = 0; i < default_display.get_monitors ().get_n_items () ; i ++) { monitor.append_text (_("Display %d").printf (i + 1)); } } @@ -251,11 +308,11 @@ public class PantheonShell.Dock : Gtk.Grid { primary_monitor_label.hide (); primary_monitor.hide (); monitor_label.hide (); - monitor.no_show_all = true; + // monitor.no_show_all = true; monitor.hide (); } else { - if (dock_preferences.Monitor != "") { - monitor.active = find_monitor_number (get_display (), dock_preferences.Monitor); + if (dock_preferences.get_string ("monitor") != "") { + monitor.active = find_monitor_number (get_display (), dock_preferences.get_string ("monitor")); } else { monitor.active = primary_screen; } @@ -268,27 +325,28 @@ public class PantheonShell.Dock : Gtk.Grid { } static string[] get_monitor_plug_names (Gdk.Display display) { - int n_monitors = display.get_n_monitors (); + var monitors = display.get_monitors (); + var n_monitors = monitors.get_n_items (); var result = new string[n_monitors]; for (int i = 0; i < n_monitors; i++) { - result[i] = display.get_monitor (i).model; + result[i] = ((Gdk.Monitor) monitors.get_item (i)).model; } return result; } static int find_monitor_number (Gdk.Display display, string plug_name) { - int n_monitors = display.get_n_monitors (); + var monitors = display.get_monitors (); - for (int i = 0; i < n_monitors; i++) { - var monitor = display.get_monitor (i); + for (int i = 0; i < monitors.get_n_items (); i++) { + var monitor = (Gdk.Monitor) monitors.get_item (i); var name = monitor.get_model (); if (plug_name == name) return i; } - return display.get_n_monitors (); + return (int) monitors.get_n_items (); } } diff --git a/src/Views/Multitasking.vala b/src/Views/Multitasking.vala index d905d5937..0157f5241 100644 --- a/src/Views/Multitasking.vala +++ b/src/Views/Multitasking.vala @@ -80,18 +80,18 @@ public class PantheonShell.Multitasking : Gtk.Grid { var cc_label = new Gtk.Label (_("Custom command:")); - var cc_grid = new Gtk.Grid (); - cc_grid.column_spacing = column_spacing; - cc_grid.halign = Gtk.Align.END; - cc_grid.margin_top = 24; - cc_grid.add (cc_label); - cc_grid.add (custom_command); + var cc_grid = new Gtk.Box (Gtk.Orientation.HORIZONTAL, column_spacing) { + halign = Gtk.Align.END, + margin_top = 24 + }; + cc_grid.append (cc_label); + cc_grid.append (custom_command); var cc_sizegroup = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); cc_sizegroup.add_widget (icon); cc_sizegroup.add_widget (custom_command); - custom_command_revealer.add (cc_grid); + custom_command_revealer.child = cc_grid; var workspaces_label = new Gtk.Label (_("Move windows to a new workspace:")) { halign = Gtk.Align.END, @@ -102,13 +102,12 @@ public class PantheonShell.Multitasking : Gtk.Grid { var fullscreen_checkbutton = new Gtk.CheckButton.with_label (_("When entering fullscreen")); var maximize_checkbutton = new Gtk.CheckButton.with_label (_("When maximizing")); - var checkbutton_grid = new Gtk.Grid () { - column_spacing = 12, + var checkbutton_grid = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12) { margin_top = 36, margin_bottom = 12 }; - checkbutton_grid.add (fullscreen_checkbutton); - checkbutton_grid.add (maximize_checkbutton); + checkbutton_grid.append (fullscreen_checkbutton); + checkbutton_grid.append (maximize_checkbutton); var animations_label = new Gtk.Label (_("Window animations:")) { halign = Gtk.Align.END diff --git a/src/Views/Text.vala b/src/Views/Text.vala index bda47c536..c69599c94 100644 --- a/src/Views/Text.vala +++ b/src/Views/Text.vala @@ -63,7 +63,7 @@ public class PantheonShell.Text : Gtk.Grid { wrap = true, xalign = 0 }; - dyslexia_font_description_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); + dyslexia_font_description_label.get_style_context ().add_class (Granite.STYLE_CLASS_DIM_LABEL); column_spacing = 12; halign = Gtk.Align.CENTER; diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index d46733124..d5ed226cd 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -81,7 +81,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { wallpaper_view = new Gtk.FlowBox (); wallpaper_view.activate_on_single_click = true; - wallpaper_view.get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW); + wallpaper_view.get_style_context ().add_class (Granite.STYLE_CLASS_VIEW); wallpaper_view.homogeneous = true; wallpaper_view.selection_mode = Gtk.SelectionMode.SINGLE; wallpaper_view.child_activated.connect (update_checked_wallpaper); @@ -89,16 +89,22 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var color = settings.get_string ("primary-color"); create_solid_color_container (color); - Gtk.TargetEntry e = {"text/uri-list", 0, 0}; - wallpaper_view.drag_data_received.connect (on_drag_data_received); - Gtk.drag_dest_set (wallpaper_view, Gtk.DestDefaults.ALL, {e}, Gdk.DragAction.COPY); + // Gtk.TargetEntry e = {"text/uri-list", 0, 0}; + // wallpaper_view.drag_data_received.connect (on_drag_data_received); + // Gtk.drag_dest_set (wallpaper_view, Gtk.DestDefaults.ALL, {e}, Gdk.DragAction.COPY); - wallpaper_scrolled_window = new Gtk.ScrolledWindow (null, null); - wallpaper_scrolled_window.expand = true; - wallpaper_scrolled_window.add (wallpaper_view); + wallpaper_scrolled_window = new Gtk.ScrolledWindow () { + hexpand = true, + vexpand = true, + child = wallpaper_view + }; - var add_wallpaper_button = new Gtk.Button.with_label (_("Import Photo…")); - add_wallpaper_button.margin = 12; + var add_wallpaper_button = new Gtk.Button.with_label (_("Import Photo…")) { + margin_start = 12, + margin_end = 12, + margin_top = 12, + margin_bottom = 12 + }; combo = new Gtk.ComboBoxText (); combo.valign = Gtk.Align.CENTER; @@ -112,9 +118,12 @@ public class PantheonShell.Wallpaper : Gtk.Grid { rgba_color = { 1, 1, 1, 1 }; } - color_button = new Gtk.ColorButton (); - color_button.margin = 12; - color_button.margin_start = 0; + color_button = new Gtk.ColorButton () { + margin_start = 0, + margin_end = 12, + margin_top = 12, + margin_bottom = 12 + }; color_button.rgba = rgba_color; color_button.color_set.connect (update_color); @@ -126,7 +135,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { load_settings (); var actionbar = new Gtk.ActionBar (); - actionbar.get_style_context ().add_class (Gtk.STYLE_CLASS_INLINE_TOOLBAR); + actionbar.get_style_context ().add_class ("inline-toolbar"); actionbar.pack_start (add_wallpaper_button); actionbar.pack_end (color_button); actionbar.pack_end (combo); @@ -142,7 +151,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var filter = new Gtk.FileFilter (); filter.add_mime_type ("image/*"); - var preview_area = new Granite.AsyncImage (false); + var preview_area = new Gtk.Image (); preview_area.pixel_size = 256; preview_area.margin_end = 12; @@ -153,33 +162,47 @@ public class PantheonShell.Wallpaper : Gtk.Grid { ); chooser.filter = filter; chooser.select_multiple = true; - chooser.set_preview_widget (preview_area); - - chooser.update_preview.connect (() => { - string uri = chooser.get_preview_uri (); - - if (uri != null && uri.has_prefix ("file://") == true) { - var file = GLib.File.new_for_uri (uri); - preview_area.set_from_gicon_async.begin (new FileIcon (file), 256); - preview_area.show (); - } else { - preview_area.hide (); - } - }); + // chooser.set_preview_widget (preview_area); + + // chooser.update_preview.connect (() => { + // string uri = chooser.get_preview_uri (); + + // if (uri != null && uri.has_prefix ("file://") == true) { + // var file = GLib.File.new_for_uri (uri); + // preview_area.set_from_gicon_async.begin (new FileIcon (file), 256); + // preview_area.show (); + // } else { + // preview_area.hide (); + // } + // }); + + chooser.show (); + + chooser.response.connect ((id) => { + if (id == Gtk.ResponseType.ACCEPT) { + ListModel files = chooser.get_files (); + // foreach (unowned string uri in uris) { + // var file = GLib.File.new_for_uri (uri); + // string local_uri = uri; + // var dest = copy_for_library (file); + // if (dest != null) { + // local_uri = dest.get_uri (); + // } + + // add_wallpaper_from_file (file, local_uri); + // } + for (var iter = 0; iter < files.get_n_items (); iter++) { + var file = (File) files.get_item (iter); + string local_uri = file.get_uri (); + var dest = copy_for_library (file); + if (dest != null) { + local_uri = dest.get_uri (); + } - if (chooser.run () == Gtk.ResponseType.ACCEPT) { - SList uris = chooser.get_uris (); - foreach (unowned string uri in uris) { - var file = GLib.File.new_for_uri (uri); - string local_uri = uri; - var dest = copy_for_library (file); - if (dest != null) { - local_uri = dest.get_uri (); + add_wallpaper_from_file (file, local_uri); } - - add_wallpaper_from_file (file, local_uri); } - } + }); chooser.destroy (); } @@ -265,7 +288,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { if (finished) { set_combo_disabled_if_necessary (); create_solid_color_container (color_button.rgba.to_string ()); - wallpaper_view.add (solid_color); + wallpaper_view.append (solid_color); wallpaper_view.select_child (solid_color); if (active_wallpaper != null) { @@ -287,8 +310,18 @@ public class PantheonShell.Wallpaper : Gtk.Grid { if (active_wallpaper == solid_color) { active_wallpaper.checked = false; - foreach (var child in wallpaper_view.get_children ()) { - var container = (WallpaperContainer) child; + // foreach (var child in wallpaper_view.get_children ()) { + // var container = (WallpaperContainer) child; + // if (container.uri == current_wallpaper_path) { + // container.checked = true; + // wallpaper_view.select_child (container); + // active_wallpaper = container; + // break; + // } + // } + var children = wallpaper_view.observe_children (); + for (var iter = 0; iter < children.get_n_items (); iter++) { + var container = (WallpaperContainer) children.get_item (iter); if (container.uri == current_wallpaper_path) { container.checked = true; wallpaper_view.select_child (container); @@ -366,7 +399,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { if (toplevel_folder) { create_solid_color_container (color_button.rgba.to_string ()); - wallpaper_view.add (solid_color); + wallpaper_view.append (solid_color); finished = true; if (settings.get_string ("picture-options") == "none") { @@ -396,12 +429,15 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } solid_color = new SolidColorContainer (color); - solid_color.show_all (); + // solid_color.show_all (); } private void clean_wallpapers () { - foreach (var child in wallpaper_view.get_children ()) { - child.destroy (); + // foreach (var child in wallpaper_view.get_children ()) { + // child.destroy (); + // } + while (wallpaper_view.get_last_child () != null) { + wallpaper_view.get_last_child ().destroy (); } solid_color = null; @@ -489,34 +525,34 @@ public class PantheonShell.Wallpaper : Gtk.Grid { return dest; } - private void on_drag_data_received (Gtk.Widget widget, Gdk.DragContext ctx, int x, int y, Gtk.SelectionData sel, uint information, uint timestamp) { - if (sel.get_length () > 0) { - try { - var file = File.new_for_uri (sel.get_uris ()[0]); - var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); + // private void on_drag_data_received (Gtk.Widget widget, Gdk.DragContext ctx, int x, int y, Gtk.SelectionData sel, uint information, uint timestamp) { + // if (sel.get_length () > 0) { + // try { + // var file = File.new_for_uri (sel.get_uris ()[0]); + // var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); - if (!IOHelper.is_valid_file_type (info)) { - Gtk.drag_finish (ctx, false, false, timestamp); - return; - } + // if (!IOHelper.is_valid_file_type (info)) { + // Gtk.drag_finish (ctx, false, false, timestamp); + // return; + // } - string local_uri = file.get_uri (); - var dest = copy_for_library (file); - if (dest != null) { - local_uri = dest.get_uri (); - } + // string local_uri = file.get_uri (); + // var dest = copy_for_library (file); + // if (dest != null) { + // local_uri = dest.get_uri (); + // } - add_wallpaper_from_file (file, local_uri); + // add_wallpaper_from_file (file, local_uri); - Gtk.drag_finish (ctx, true, false, timestamp); - } catch (Error e) { - warning (e.message); - } - } + // Gtk.drag_finish (ctx, true, false, timestamp); + // } catch (Error e) { + // warning (e.message); + // } + // } - Gtk.drag_finish (ctx, false, false, timestamp); - return; - } + // Gtk.drag_finish (ctx, false, false, timestamp); + // return; + // } private void add_wallpaper_from_file (GLib.File file, string uri) { try { @@ -524,9 +560,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); var thumb_valid = info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID); var wallpaper = new WallpaperContainer (uri, thumb_path, thumb_valid); - wallpaper_view.add (wallpaper); + wallpaper_view.append (wallpaper); - wallpaper.show_all (); + // wallpaper.show_all (); wallpaper.trash.connect (() => { var new_file = File.new_for_uri (uri); diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index ac5e043e4..59d957eca 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -24,10 +24,11 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { private const int THUMB_WIDTH = 162; private const int THUMB_HEIGHT = 100; - private Gtk.Grid card_box; - private Gtk.Menu context_menu; + private Gtk.Box card_box; + private Gtk.Popover context_menu; + private Gtk.GestureClick overlay_event_controller; private Gtk.Revealer check_revealer; - private Granite.AsyncImage image; + private Gtk.Image image; public string? thumb_path { get; construct set; } public bool thumb_valid { get; construct; } @@ -81,42 +82,53 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { var provider = new Gtk.CssProvider (); provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/plug.css"); - Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - image = new Granite.AsyncImage (); + image = new Gtk.Image (); image.halign = Gtk.Align.CENTER; image.valign = Gtk.Align.CENTER; image.get_style_context ().set_scale (1); // We need an extra grid to not apply a scale == 1 to the "card" style. - card_box = new Gtk.Grid (); + card_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { + margin_start = 9, + margin_end = 9, + margin_top = 9, + margin_bottom = 9 + }; card_box.get_style_context ().add_class ("card"); - card_box.add (image); - card_box.margin = 9; - - var check = new Gtk.Image.from_icon_name ("selection-checked", Gtk.IconSize.LARGE_TOOLBAR); - check.halign = Gtk.Align.START; - check.valign = Gtk.Align.START; - - check_revealer = new Gtk.Revealer (); - check_revealer.transition_type = Gtk.RevealerTransitionType.CROSSFADE; - check_revealer.add (check); - - var overlay = new Gtk.Overlay (); - overlay.add (card_box); + card_box.append (image); + + var check = new Gtk.Image.from_icon_name ("selection-checked") { + pixel_size = 24, + halign = Gtk.Align.START, + valign = Gtk.Align.START + }; + + check_revealer = new Gtk.Revealer () { + transition_type = Gtk.RevealerTransitionType.CROSSFADE, + child = check + }; + + var overlay = new Gtk.Overlay () { + child = card_box + }; overlay.add_overlay (check_revealer); - var event_box = new Gtk.EventBox (); - event_box.add (overlay); + overlay_event_controller = new Gtk.GestureClick (); + overlay.add_controller (overlay_event_controller); halign = Gtk.Align.CENTER; valign = Gtk.Align.CENTER; - margin = 6; - add (event_box); + margin_start = 6; + margin_end = 6; + margin_top = 6; + margin_bottom = 6; + child = overlay; if (uri != null) { - var move_to_trash = new Gtk.MenuItem.with_label (_("Remove")); - move_to_trash.activate.connect (() => trash ()); + var move_to_trash = new Gtk.Button.with_label (_("Remove")); + move_to_trash.clicked.connect (() => trash ()); var file = File.new_for_uri (uri); file.query_info_async.begin (GLib.FileAttribute.ACCESS_CAN_DELETE, 0, Priority.DEFAULT, null, (obj, res) => { @@ -128,16 +140,18 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } }); - context_menu = new Gtk.Menu (); - context_menu.append (move_to_trash); - context_menu.show_all (); + context_menu = new Gtk.Popover () { + child = move_to_trash + }; + // context_menu.append (move_to_trash); + // context_menu.show_all (); } activate.connect (() => { checked = true; }); - event_box.button_press_event.connect (show_context_menu); + overlay_event_controller.pressed.connect (show_context_menu); try { if (uri != null) { @@ -191,12 +205,13 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } } - private bool show_context_menu (Gtk.Widget sender, Gdk.EventButton evt) { - if (evt.type == Gdk.EventType.BUTTON_PRESS && evt.button == 3) { - context_menu.popup_at_pointer (null); - return Gdk.EVENT_STOP; + private void show_context_menu (int n_press, double x, double y) { + var evt = overlay_event_controller.get_current_event (); + if (evt.get_event_type () == Gdk.EventType.BUTTON_PRESS && evt.get_modifier_state () == Gdk.ModifierType.BUTTON3_MASK) { + context_menu.popup (); + // return Gdk.EVENT_STOP; } - return Gdk.EVENT_PROPAGATE; + // return Gdk.EVENT_PROPAGATE; } private async void update_thumb () { @@ -204,11 +219,14 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { return; } - try { - yield image.set_from_file_async (File.new_for_path (thumb_path), THUMB_WIDTH, THUMB_HEIGHT, false); - } catch (Error e) { - warning (e.message); - } + // try { + // yield image.set_from_file_async (File.new_for_path (thumb_path), THUMB_WIDTH, THUMB_HEIGHT, false); + // } catch (Error e) { + // warning (e.message); + // } + image.set_from_file (thumb_path); + image.width_request = THUMB_WIDTH; + image.height_request = THUMB_HEIGHT; load_artist_tooltip (); } diff --git a/src/meson.build b/src/meson.build index 234d59972..88062115d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,6 +3,7 @@ plug_files = files( 'PantheonAccountsServicePlugin.vala', 'Plug.vala', 'ThumbnailGenerator.vala', + 'Interfaces/MutterDisplayConfig.vala', 'Views/Appearance.vala', 'Views/Dock.vala', 'Views/Multitasking.vala', From 8bf9ccf51e21477547f5fc13da6842905fa90814 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 10 Jun 2022 04:53:13 +0300 Subject: [PATCH 04/40] Fix Appearance Page --- data/appearance-styles.css | 46 +++++++++++++++++++++++++++++++ data/icons.gresource.xml | 1 + data/plug.css | 9 ------ src/Plug.vala | 25 +++++++++++------ src/Views/Appearance.vala | 56 ++++++++++++++++++-------------------- 5 files changed, 89 insertions(+), 48 deletions(-) create mode 100644 data/appearance-styles.css diff --git a/data/appearance-styles.css b/data/appearance-styles.css new file mode 100644 index 000000000..6a2c0369e --- /dev/null +++ b/data/appearance-styles.css @@ -0,0 +1,46 @@ +/* +* Copyright 2020 elementary, Inc. (https://elementary.io) +* +* 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 the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA. +*/ + +checkbutton .card { + background-position: center; + background-repeat: no-repeat; + background-size: 112px 80px, cover; + min-width: 112px; + min-height: 80px; +} + +checkbutton .card.prefer-default { + background-image: + url("resource:///io/elementary/switchboard/plug/pantheon-shell/appearance-default.svg"), + linear-gradient( + to bottom, + alpha(@accent_color_300, 0.1), + alpha(@accent_color_500, 0.1) + ); +} + +checkbutton .card.prefer-dark { + background-image: + url("resource:///io/elementary/switchboard/plug/pantheon-shell/appearance-dark.svg"), + linear-gradient( + to bottom, + alpha(@accent_color_300, 0.1), + alpha(@accent_color_500, 0.1) + ); +} diff --git a/data/icons.gresource.xml b/data/icons.gresource.xml index ab09d8a0d..516bf762f 100644 --- a/data/icons.gresource.xml +++ b/data/icons.gresource.xml @@ -10,5 +10,6 @@ appearance-default.svg appearance-dark.svg plug.css + appearance-styles.css diff --git a/data/plug.css b/data/plug.css index 93a91942a..f6f3eca66 100644 --- a/data/plug.css +++ b/data/plug.css @@ -71,12 +71,3 @@ 0 0 0 1px alpha (#000, 0.05), 0 3px 3px alpha (#000, 0.22); } - -radiobutton .card { - background-image: - linear-gradient( - to bottom, - alpha (@accent_color_300, 0.1), - alpha (@accent_color_500, 0.1) - ); -} diff --git a/src/Plug.vala b/src/Plug.vala index 5b237765a..ec64999e6 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -70,18 +70,25 @@ public class PantheonShell.Plug : Switchboard.Plug { stack.add_titled (multitasking, "multitasking", _("Multitasking")); - var stack_switcher = new Gtk.StackSwitcher (); - stack_switcher.stack = stack; - stack_switcher.halign = Gtk.Align.CENTER; - // stack_switcher.homogeneous = true; - stack_switcher.margin_start = 24; - stack_switcher.margin_end = 24; - stack_switcher.margin_top = 24; - stack_switcher.margin_bottom = 24; + var stack_switcher = new Gtk.StackSwitcher () { + stack = stack, + halign = Gtk.Align.CENTER, + margin_start = 24, + margin_end = 24, + margin_top = 24, + margin_bottom = 24 + }; + + var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); + var switcher_toggles = stack_switcher.observe_children (); + if (size_group.get_widgets ().length () == 0) { + for (var index = 0; index < switcher_toggles.get_n_items (); index++) { + size_group.add_widget ((Gtk.ToggleButton) switcher_toggles.get_item (index)); + } + } main_grid.attach (stack_switcher, 0, 0, 1, 1); main_grid.attach (stack, 0, 1, 1, 1); - // main_grid.show_all (); } return main_grid; diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala index 8d5368813..a39fca450 100644 --- a/src/Views/Appearance.vala +++ b/src/Views/Appearance.vala @@ -65,7 +65,7 @@ public class PantheonShell.Appearance : Gtk.Grid { } construct { - column_spacing = 7; // Off by one with Gtk.RadioButton + column_spacing = 7; // Off by one with Gtk.CheckButton halign = Gtk.Align.CENTER; row_spacing = 6; margin_start = margin_end = 12; @@ -73,7 +73,13 @@ public class PantheonShell.Appearance : Gtk.Grid { var dark_label = new Granite.HeaderLabel (_("Style")); - var prefer_default_image = new Gtk.Image.from_resource ("/io/elementary/switchboard/plug/pantheon-shell/appearance-default.svg"); + var css_provider = new Gtk.CssProvider (); + css_provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/appearance-styles.css"); + + var prefer_default_radio = new Gtk.CheckButton () { + halign = Gtk.Align.START + }; + prefer_default_radio.add_css_class ("image-button"); var prefer_default_card = new Gtk.Grid () { margin_top = 6, @@ -81,25 +87,24 @@ public class PantheonShell.Appearance : Gtk.Grid { margin_end = 6, margin_start = 12 }; - prefer_default_card.attach (prefer_default_image, 0, 0); - - unowned Gtk.StyleContext prefer_default_card_context = prefer_default_card.get_style_context (); - prefer_default_card_context.add_class (Granite.STYLE_CLASS_CARD); - prefer_default_card_context.add_class (Granite.STYLE_CLASS_ROUNDED); + prefer_default_card.add_css_class (Granite.STYLE_CLASS_CARD); + prefer_default_card.add_css_class (Granite.STYLE_CLASS_ROUNDED); + prefer_default_card.add_css_class ("prefer-default"); + prefer_default_card.get_style_context ().add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); var prefer_default_grid = new Gtk.Grid () { row_spacing = 6 }; prefer_default_grid.attach (prefer_default_card, 0, 0); prefer_default_grid.attach (new Gtk.Label (_("Default")), 0, 1); - - var prefer_default_radio = new Gtk.CheckButton () { - halign = Gtk.Align.START - }; - prefer_default_radio.get_style_context ().add_class ("image-button"); prefer_default_grid.set_parent (prefer_default_radio); - var prefer_dark_image = new Gtk.Image.from_resource ("/io/elementary/switchboard/plug/pantheon-shell/appearance-dark.svg"); + var prefer_dark_radio = new Gtk.CheckButton () { + halign = Gtk.Align.START, + hexpand = true, + group = prefer_default_radio + }; + prefer_dark_radio.add_css_class ("image-button"); var prefer_dark_card = new Gtk.Grid () { margin_top = 6, @@ -107,24 +112,16 @@ public class PantheonShell.Appearance : Gtk.Grid { margin_end = 6, margin_start = 12 }; - prefer_dark_card.attach (prefer_dark_image, 0, 0); - - unowned Gtk.StyleContext prefer_dark_card_context = prefer_dark_card.get_style_context (); - prefer_dark_card_context.add_class (Granite.STYLE_CLASS_CARD); - prefer_dark_card_context.add_class (Granite.STYLE_CLASS_ROUNDED); + prefer_dark_card.add_css_class (Granite.STYLE_CLASS_CARD); + prefer_dark_card.add_css_class (Granite.STYLE_CLASS_ROUNDED); + prefer_dark_card.add_css_class ("prefer-dark"); + prefer_dark_card.get_style_context ().add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); var prefer_dark_grid = new Gtk.Grid () { row_spacing = 6 }; prefer_dark_grid.attach (prefer_dark_card, 0, 0); prefer_dark_grid.attach (new Gtk.Label (_("Dark")), 0, 1); - - var prefer_dark_radio = new Gtk.CheckButton () { - halign = Gtk.Align.START, - hexpand = true, - group = prefer_default_radio - }; - prefer_dark_radio.get_style_context ().add_class ("image-button"); prefer_dark_grid.set_parent (prefer_dark_radio); var prefer_style_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); @@ -136,7 +133,7 @@ public class PantheonShell.Appearance : Gtk.Grid { wrap = true, xalign = 0 }; - dark_info.get_style_context ().add_class (Granite.STYLE_CLASS_DIM_LABEL); + dark_info.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); var schedule_label = new Granite.HeaderLabel (_("Schedule")); @@ -348,7 +345,7 @@ public class PantheonShell.Appearance : Gtk.Grid { xalign = 0, wrap = true }; - accent_info.get_style_context ().add_class (Granite.STYLE_CLASS_DIM_LABEL); + accent_info.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); attach (accent_label, 0, 7, 2); attach (accent_info, 0, 8, 2); @@ -377,9 +374,8 @@ public class PantheonShell.Appearance : Gtk.Grid { } construct { - unowned Gtk.StyleContext context = get_style_context (); - context.add_class (Granite.STYLE_CLASS_COLOR_BUTTON); - context.add_class (color.to_string ()); + add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON); + add_css_class (color.to_string ()); realize.connect (() => { active = color == pantheon_act.prefers_accent_color; From 0f9c46aab9cb504ef6aa375875e3803f969676cd Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 10 Jun 2022 05:23:42 +0300 Subject: [PATCH 05/40] Fix DND --- src/Views/Wallpaper.vala | 82 ++++++++++------------------- src/Widgets/WallpaperContainer.vala | 21 +++----- 2 files changed, 34 insertions(+), 69 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index d5ed226cd..0be6f3346 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -79,11 +79,12 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - wallpaper_view = new Gtk.FlowBox (); - wallpaper_view.activate_on_single_click = true; - wallpaper_view.get_style_context ().add_class (Granite.STYLE_CLASS_VIEW); - wallpaper_view.homogeneous = true; - wallpaper_view.selection_mode = Gtk.SelectionMode.SINGLE; + wallpaper_view = new Gtk.FlowBox () { + activate_on_single_click = true, + homogeneous = true, + selection_mode = Gtk.SelectionMode.SINGLE + }; + wallpaper_view.add_css_class (Granite.STYLE_CLASS_VIEW); wallpaper_view.child_activated.connect (update_checked_wallpaper); var color = settings.get_string ("primary-color"); @@ -92,6 +93,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { // Gtk.TargetEntry e = {"text/uri-list", 0, 0}; // wallpaper_view.drag_data_received.connect (on_drag_data_received); // Gtk.drag_dest_set (wallpaper_view, Gtk.DestDefaults.ALL, {e}, Gdk.DragAction.COPY); + var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY); + wallpaper_view.add_controller (drop_target); + drop_target.on_drop.connect (on_drag_data_received); wallpaper_scrolled_window = new Gtk.ScrolledWindow () { hexpand = true, @@ -135,7 +139,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { load_settings (); var actionbar = new Gtk.ActionBar (); - actionbar.get_style_context ().add_class ("inline-toolbar"); + actionbar.add_css_class ("inline-toolbar"); actionbar.pack_start (add_wallpaper_button); actionbar.pack_end (color_button); actionbar.pack_end (combo); @@ -181,16 +185,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { chooser.response.connect ((id) => { if (id == Gtk.ResponseType.ACCEPT) { ListModel files = chooser.get_files (); - // foreach (unowned string uri in uris) { - // var file = GLib.File.new_for_uri (uri); - // string local_uri = uri; - // var dest = copy_for_library (file); - // if (dest != null) { - // local_uri = dest.get_uri (); - // } - - // add_wallpaper_from_file (file, local_uri); - // } for (var iter = 0; iter < files.get_n_items (); iter++) { var file = (File) files.get_item (iter); string local_uri = file.get_uri (); @@ -310,15 +304,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { if (active_wallpaper == solid_color) { active_wallpaper.checked = false; - // foreach (var child in wallpaper_view.get_children ()) { - // var container = (WallpaperContainer) child; - // if (container.uri == current_wallpaper_path) { - // container.checked = true; - // wallpaper_view.select_child (container); - // active_wallpaper = container; - // break; - // } - // } var children = wallpaper_view.observe_children (); for (var iter = 0; iter < children.get_n_items (); iter++) { var container = (WallpaperContainer) children.get_item (iter); @@ -429,13 +414,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } solid_color = new SolidColorContainer (color); - // solid_color.show_all (); } private void clean_wallpapers () { - // foreach (var child in wallpaper_view.get_children ()) { - // child.destroy (); - // } while (wallpaper_view.get_last_child () != null) { wallpaper_view.get_last_child ().destroy (); } @@ -525,34 +506,27 @@ public class PantheonShell.Wallpaper : Gtk.Grid { return dest; } - // private void on_drag_data_received (Gtk.Widget widget, Gdk.DragContext ctx, int x, int y, Gtk.SelectionData sel, uint information, uint timestamp) { - // if (sel.get_length () > 0) { - // try { - // var file = File.new_for_uri (sel.get_uris ()[0]); - // var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); - - // if (!IOHelper.is_valid_file_type (info)) { - // Gtk.drag_finish (ctx, false, false, timestamp); - // return; - // } + private bool on_drag_data_received (Gtk.DropTarget controller, Value val, double x, double y) { + var drop_target = (Gtk.DropTarget) controller; + var file_list = (Gdk.FileList) val; + file_list.get_files ().foreach ((file) => { + var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); - // string local_uri = file.get_uri (); - // var dest = copy_for_library (file); - // if (dest != null) { - // local_uri = dest.get_uri (); - // } + if (!IOHelper.is_valid_file_type (info)) { + drop_target.reject (); + } - // add_wallpaper_from_file (file, local_uri); + string local_uri = file.get_uri (); + var dest = copy_for_library (file); + if (dest != null) { + local_uri = dest.get_uri (); + } - // Gtk.drag_finish (ctx, true, false, timestamp); - // } catch (Error e) { - // warning (e.message); - // } - // } + add_wallpaper_from_file (file, local_uri); + }); - // Gtk.drag_finish (ctx, false, false, timestamp); - // return; - // } + return false; + } private void add_wallpaper_from_file (GLib.File file, string uri) { try { @@ -562,8 +536,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var wallpaper = new WallpaperContainer (uri, thumb_path, thumb_valid); wallpaper_view.append (wallpaper); - // wallpaper.show_all (); - wallpaper.trash.connect (() => { var new_file = File.new_for_uri (uri); new_file.delete_async.begin (); diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index 59d957eca..ab0900095 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -72,10 +72,9 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } construct { - var style_context = get_style_context (); - style_context.add_class ("wallpaper-container"); + add_css_class ("wallpaper-container"); - scale = style_context.get_scale (); + scale = get_style_context ().get_scale (); height_request = THUMB_HEIGHT + 18; width_request = THUMB_WIDTH + 18; @@ -84,9 +83,10 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/plug.css"); Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - image = new Gtk.Image (); - image.halign = Gtk.Align.CENTER; - image.valign = Gtk.Align.CENTER; + image = new Gtk.Image () { + halign = Gtk.Align.CENTER, + valign = Gtk.Align.CENTER + }; image.get_style_context ().set_scale (1); // We need an extra grid to not apply a scale == 1 to the "card" style. @@ -96,7 +96,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { margin_top = 9, margin_bottom = 9 }; - card_box.get_style_context ().add_class ("card"); + card_box.add_css_class ("card"); card_box.append (image); var check = new Gtk.Image.from_icon_name ("selection-checked") { @@ -143,8 +143,6 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { context_menu = new Gtk.Popover () { child = move_to_trash }; - // context_menu.append (move_to_trash); - // context_menu.show_all (); } activate.connect (() => { @@ -219,11 +217,6 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { return; } - // try { - // yield image.set_from_file_async (File.new_for_path (thumb_path), THUMB_WIDTH, THUMB_HEIGHT, false); - // } catch (Error e) { - // warning (e.message); - // } image.set_from_file (thumb_path); image.width_request = THUMB_WIDTH; image.height_request = THUMB_HEIGHT; From b8f8d97a5bb84985eff5167881caa34afe425cb2 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 10 Jun 2022 08:18:54 +0300 Subject: [PATCH 06/40] Fix hang --- src/Views/Wallpaper.vala | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 0be6f3346..a8784be0c 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -90,9 +90,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var color = settings.get_string ("primary-color"); create_solid_color_container (color); - // Gtk.TargetEntry e = {"text/uri-list", 0, 0}; - // wallpaper_view.drag_data_received.connect (on_drag_data_received); - // Gtk.drag_dest_set (wallpaper_view, Gtk.DestDefaults.ALL, {e}, Gdk.DragAction.COPY); var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY); wallpaper_view.add_controller (drop_target); drop_target.on_drop.connect (on_drag_data_received); @@ -417,8 +414,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private void clean_wallpapers () { - while (wallpaper_view.get_last_child () != null) { - wallpaper_view.get_last_child ().destroy (); + var children = wallpaper_view.observe_children (); + for (var index = 0; index < children.get_n_items (); index++) { + ((Gtk.Widget) children.get_item (index)).destroy (); } solid_color = null; @@ -510,19 +508,23 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var drop_target = (Gtk.DropTarget) controller; var file_list = (Gdk.FileList) val; file_list.get_files ().foreach ((file) => { - var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); + try { + var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); - if (!IOHelper.is_valid_file_type (info)) { - drop_target.reject (); - } + if (!IOHelper.is_valid_file_type (info)) { + drop_target.reject (); + } - string local_uri = file.get_uri (); - var dest = copy_for_library (file); - if (dest != null) { - local_uri = dest.get_uri (); - } + string local_uri = file.get_uri (); + var dest = copy_for_library (file); + if (dest != null) { + local_uri = dest.get_uri (); + } - add_wallpaper_from_file (file, local_uri); + add_wallpaper_from_file (file, local_uri); + } catch (Error e) { + warning (e.message); + } }); return false; From 4dfb53896d35f5de732e84de24ecb1370e7ebc5e Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 10 Jun 2022 09:14:22 +0300 Subject: [PATCH 07/40] Fix regressions --- data/plug.css | 10 +-- src/Views/Appearance.vala | 2 + src/Views/Dock.vala | 133 +++++++++++++++++--------------------- 3 files changed, 67 insertions(+), 78 deletions(-) diff --git a/data/plug.css b/data/plug.css index f6f3eca66..9b54c2a42 100644 --- a/data/plug.css +++ b/data/plug.css @@ -60,14 +60,14 @@ .wallpaper-container .card:checked { box-shadow: - 0 0 0 4px alpha (@text_color, 0.2), - 0 0 0 1px alpha (#000, 0.05), - 0 3px 3px alpha (#000, 0.22); + 0 0 0 4px alpha(@text_color, 0.2), + 0 0 0 1px alpha(#000, 0.05), + 0 3px 3px alpha(#000, 0.22); } .wallpaper-container:focus .card { box-shadow: 0 0 0 4px @colorAccent, - 0 0 0 1px alpha (#000, 0.05), - 0 3px 3px alpha (#000, 0.22); + 0 0 0 1px alpha(#000, 0.05), + 0 3px 3px alpha(#000, 0.22); } diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala index a39fca450..6faf008a1 100644 --- a/src/Views/Appearance.vala +++ b/src/Views/Appearance.vala @@ -58,6 +58,8 @@ public class PantheonShell.Appearance : Gtk.Grid { return "cocoa"; case GRAY: return "slate"; + case NO_PREFERENCE: + return "no preference"; } return "auto"; diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index ab0da8870..208a03592 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -43,28 +43,32 @@ public class PantheonShell.Dock : Gtk.Grid { weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); default_theme.add_resource_path ("/io/elementary/switchboard/plug/pantheon-shell"); - var icon_size_32 = new Gtk.CheckButton (); - icon_size_32.tooltip_text = _("Small"); + var icon_size_32 = new Gtk.CheckButton () { + tooltip_text = _("Small") + }; var icon_size_32_image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic") { pixel_size = 32 }; icon_size_32_image.set_parent (icon_size_32); - var icon_size_48 = new Gtk.CheckButton (); - icon_size_48.tooltip_text = _("Default"); + var icon_size_48 = new Gtk.CheckButton () { + tooltip_text = _("Default") + }; icon_size_48.group = icon_size_32; var icon_size_48_image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic") { pixel_size = 48 }; icon_size_48_image.set_parent (icon_size_48); - var image_64 = new Gtk.Image (); - image_64.icon_name = "application-default-icon-symbolic"; - image_64.pixel_size = 64; + var image_64 = new Gtk.Image () { + icon_name = "application-default-icon-symbolic", + pixel_size = 64 + }; - var icon_size_64 = new Gtk.CheckButton (); - icon_size_64.tooltip_text = _("Large"); - icon_size_64.group = icon_size_32; + var icon_size_64 = new Gtk.CheckButton () { + tooltip_text = _("Large"), + group = icon_size_32 + }; image_64.set_parent (icon_size_64); var icon_size_unsupported = new Gtk.CheckButton () { @@ -84,9 +88,10 @@ public class PantheonShell.Dock : Gtk.Grid { dock_preferences = new Settings.full (schema, null, "/net/launchpad/plank/docks/dock1/"); - var pressure_switch = new Gtk.Switch (); - pressure_switch.halign = Gtk.Align.START; - pressure_switch.valign = Gtk.Align.CENTER; + var pressure_switch = new Gtk.Switch () { + halign = Gtk.Align.START, + valign = Gtk.Align.CENTER + }; dock_preferences.bind ("pressure-reveal", pressure_switch, "active", GLib.SettingsBindFlags.DEFAULT); @@ -98,9 +103,10 @@ public class PantheonShell.Dock : Gtk.Grid { PlankHideTypes[] hide_mode_ids = {PlankHideTypes.DODGE_MAXIMIZED, PlankHideTypes.INTELLIGENT, PlankHideTypes.WINDOW_DODGE, PlankHideTypes.AUTO}; - var hide_switch = new Gtk.Switch (); - hide_switch.halign = Gtk.Align.START; - hide_switch.valign = Gtk.Align.CENTER; + var hide_switch = new Gtk.Switch () { + halign = Gtk.Align.START, + valign = Gtk.Align.CENTER + }; var hide_none = (dock_preferences.get_enum ("hide-mode") != PlankHideTypes.NONE); hide_switch.active = hide_none; @@ -131,16 +137,15 @@ public class PantheonShell.Dock : Gtk.Grid { monitor = new Gtk.ComboBoxText (); - primary_monitor_label = new Gtk.Label (_("Primary display:")); - primary_monitor_label.halign = Gtk.Align.END; - // primary_monitor_label.no_show_all = true; + primary_monitor_label = new Gtk.Label (_("Primary display:")) { + halign = Gtk.Align.END + }; - monitor_label = new Gtk.Label (_("Display:")); - // monitor_label.no_show_all = true; - monitor_label.halign = Gtk.Align.END; + monitor_label = new Gtk.Label (_("Display:")) { + halign = Gtk.Align.END + }; primary_monitor = new Gtk.Switch (); - // primary_monitor.no_show_all = true; primary_monitor.notify["active"].connect (() => { if (primary_monitor.active == true) { dock_preferences.set_string ("monitor", ""); @@ -172,14 +177,17 @@ public class PantheonShell.Dock : Gtk.Grid { iface.monitors_changed.connect (() => {check_for_screens ();}); - var icon_label = new Gtk.Label (_("Icon size:")); - icon_label.halign = Gtk.Align.END; - var hide_label = new Gtk.Label (_("Hide when:")); - hide_label.halign = Gtk.Align.END; + var icon_label = new Gtk.Label (_("Icon size:")) { + halign = Gtk.Align.END + }; + var hide_label = new Gtk.Label (_("Hide when:")) { + halign = Gtk.Align.END + }; var primary_monitor_grid = new Gtk.Grid (); primary_monitor_grid.attach (primary_monitor, 0, 0); - var pressure_label = new Gtk.Label (_("Pressure reveal:")); - pressure_label.halign = Gtk.Align.END; + var pressure_label = new Gtk.Label (_("Pressure reveal:")) { + halign = Gtk.Align.END + }; var panel_header = new Granite.HeaderLabel (_("Panel")) { margin_top = 12 @@ -251,52 +259,17 @@ public class PantheonShell.Dock : Gtk.Grid { int i = 0; int primary_screen = 0; var default_display = get_display (); - // var default_screen = get_screen (); monitor.remove_all (); - try { - // var screen = new Gnome.RRScreen (default_screen); - // for (i = 0; i < default_display.get_n_monitors () ; i++) { - // var monitor_plug_name = default_display.get_monitor (i).model; - - // if (monitor_plug_name != null) { - // unowned Gnome.RROutput output = screen.get_output_by_name (monitor_plug_name); - // if (output != null && output.get_display_name () != null && output.get_display_name () != "") { - // monitor.append_text (output.get_display_name ()); - // if (output.get_is_primary () == true) { - // primary_screen = i; - // } - // continue; - // } - // } - - // monitor.append_text (_("Monitor %d").printf (i + 1) ); - // } - - // the following code was taken from switchboard-plug-display - - MutterReadMonitor[] mutter_monitors; - MutterReadLogicalMonitor[] mutter_logical_monitors; - GLib.HashTable properties; - uint current_serial; - - try { - iface.get_current_state (out current_serial, out mutter_monitors, out mutter_logical_monitors, out properties); - } catch (Error e) { - critical (e.message); - } - foreach (var mutter_monitor in mutter_monitors) { - var display_name_variant = mutter_monitor.properties.lookup ("display-name"); - if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { - monitor.append_text (display_name_variant.get_string ()); - // var is_preferred = mutter_monitor.modes.properties.lookup ("is-preferred");; - // if (is_preferred.get_boolean () == true) { - // primary_screen = i; - // } + // the following code was taken from switchboard-plug-display - i++; - } - } + MutterReadMonitor[] mutter_monitors; + MutterReadLogicalMonitor[] mutter_logical_monitors; + GLib.HashTable properties; + uint current_serial; + + try { + iface.get_current_state (out current_serial, out mutter_monitors, out mutter_logical_monitors, out properties); } catch (Error e) { critical (e.message); for (i = 0; i < default_display.get_monitors ().get_n_items () ; i ++) { @@ -304,11 +277,25 @@ public class PantheonShell.Dock : Gtk.Grid { } } + foreach (var mutter_monitor in mutter_monitors) { + var display_name_variant = mutter_monitor.properties.lookup ("display-name"); + if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { + monitor.append_text (display_name_variant.get_string ()); + // var is_preferred = mutter_monitor.properties.lookup ("is-preferred");; + // if (is_preferred.get_boolean () == true) { + // primary_screen = i; + // } + + i++; + } + + monitor.append_text (_("Monitor %d").printf (i + 1) ); + } + if (i <= 1) { primary_monitor_label.hide (); primary_monitor.hide (); monitor_label.hide (); - // monitor.no_show_all = true; monitor.hide (); } else { if (dock_preferences.get_string ("monitor") != "") { From 0170b5d0b4e8227018afab5e42457d65309b835e Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 10 Jun 2022 14:57:58 +0300 Subject: [PATCH 08/40] Draft Gnome.RRScreen replacement --- src/Views/Dock.vala | 51 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index 208a03592..f27c2e816 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -256,7 +256,7 @@ public class PantheonShell.Dock : Gtk.Grid { } private void check_for_screens () { - int i = 0; + int i; int primary_screen = 0; var default_display = get_display (); monitor.remove_all (); @@ -277,21 +277,48 @@ public class PantheonShell.Dock : Gtk.Grid { } } - foreach (var mutter_monitor in mutter_monitors) { - var display_name_variant = mutter_monitor.properties.lookup ("display-name"); - if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { - monitor.append_text (display_name_variant.get_string ()); - // var is_preferred = mutter_monitor.properties.lookup ("is-preferred");; - // if (is_preferred.get_boolean () == true) { - // primary_screen = i; - // } + for (i = 0; i < mutter_monitors.length; i++) { + var mutter_monitor = mutter_monitors[i]; + var logical_monitor = mutter_logical_monitors[i]; + + if (mutter_monitor.monitor.connector == logical_monitor.monitors[0].connector) { + var display_name_variant = mutter_monitor.properties.lookup ("display-name"); + if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { + monitor.append_text (display_name_variant.get_string ()); + if (logical_monitor.primary) { + primary_screen = i; + continue; + } + } - i++; + monitor.append_text (_("Monitor %d").printf (i + 1)); } - - monitor.append_text (_("Monitor %d").printf (i + 1) ); } + // foreach (var mutter_monitor in mutter_monitors) { + // var display_name_variant = mutter_monitor.properties.lookup ("display-name"); + // print ("%s\n", mutter_monitor.monitor.connector.to_string ()); + // if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { + // monitor.append_text (display_name_variant.get_string ()); + // // var is_preferred = mutter_monitor.properties.lookup ("is-preferred");; + // // if (is_preferred.get_boolean () == true) { + // // primary_screen = i; + // // } + + // i++; + // } + + // monitor.append_text (_("Monitor %d").printf (i + 1) ); + // } + + // foreach (var logical_monitor in mutter_logical_monitors) { + // // var display_name_variant = logical_monitor.properties.lookup ("display-name"); + // print ("%s\n", logical_monitor.monitors[0].connector.to_string ()); + // // logical_monitor.properties.get_keys ().foreach ((key) => { + // // print ("%s\n", key); + // // }); + // } + if (i <= 1) { primary_monitor_label.hide (); primary_monitor.hide (); From 51956dbd835d407aa9d96bee81a851665621439f Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Sat, 11 Jun 2022 10:29:11 +0800 Subject: [PATCH 09/40] Fix CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df09089f7..9b0b2e66e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y libgnome-desktop-3-dev libgranite-dev libgtk-3-dev libplank-dev libswitchboard-2.0-dev libgexiv2-dev meson valac + apt install -y libgranite-7-dev libgtk-4-dev libswitchboard-2.0-dev libgexiv2-dev meson valac - name: Build env: DESTDIR: out From 1e84d2d2b90ab3ffdbca3505c312c05aee32edd8 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Sun, 12 Jun 2022 14:14:41 +0800 Subject: [PATCH 10/40] Fix CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9b0b2e66e..c99f4e1db 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest container: - image: elementary/docker:unstable + image: elementary/docker:next-unstable steps: - uses: actions/checkout@v1 From 97055d5f5256988302779435d3ac5de30720cfff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 14 Jun 2022 12:26:59 -0700 Subject: [PATCH 11/40] Bump libs --- .github/workflows/main.yml | 2 +- README.md | 8 +++----- src/meson.build | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c99f4e1db..b0681283d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y libgranite-7-dev libgtk-4-dev libswitchboard-2.0-dev libgexiv2-dev meson valac + apt install -y libgranite-7-dev libgtk-4-dev libswitchboard-3-dev libgexiv2-dev meson valac - name: Build env: DESTDIR: out diff --git a/README.md b/README.md index 6d37d1488..ccd580172 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,11 @@ You'll need the following dependencies: * gnome-settings-daemon-dev -* libswitchboard-2.0-dev -* libgnome-desktop-3-dev +* libswitchboard-3-dev * libgee-0.8-dev * libgexiv2-dev -* libgtk-3-dev (>= 3.22) -* libplank-dev -* libgranite-dev +* libgtk-4-dev +* libgranite-7-dev * meson * valac diff --git a/src/meson.build b/src/meson.build index 88062115d..b9f92515c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -13,7 +13,7 @@ plug_files = files( 'Widgets/WallpaperContainer.vala', ) -switchboard_dep = dependency('switchboard-2.0') +switchboard_dep = dependency('switchboard-3') switchboard_plugsdir = switchboard_dep.get_pkgconfig_variable('plugsdir', define_variable: ['libdir', libdir]) configuration = configuration_data() From 19afeb3205e8d3681b035f29cf544d5beac8c1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 14 Jun 2022 16:59:42 -0700 Subject: [PATCH 12/40] Fix wallpaper thumbs --- data/plug.css | 10 +++---- src/Widgets/WallpaperContainer.vala | 42 +++++++++-------------------- 2 files changed, 17 insertions(+), 35 deletions(-) diff --git a/data/plug.css b/data/plug.css index 9b54c2a42..8a71b1c44 100644 --- a/data/plug.css +++ b/data/plug.css @@ -41,8 +41,8 @@ ), linear-gradient( to bottom, - alpha (@accent_color_500, 0.1), - alpha (@accent_color_500, 0.1) + alpha(@accent_color_500, 0.1), + alpha(@accent_color_500, 0.1) ); background-repeat: no-repeat; background-position: -32px -32px, -32px calc(100% + 32px), calc(100% + 32px) -32px, calc(100% + 32px) calc(100% + 32px), 0; @@ -54,8 +54,8 @@ } .wallpaper-container .card { - border-radius: 1px; - border: none; + margin: 9px; + min-height: 128px; } .wallpaper-container .card:checked { @@ -67,7 +67,7 @@ .wallpaper-container:focus .card { box-shadow: - 0 0 0 4px @colorAccent, + 0 0 0 4px @selected_bg_color, 0 0 0 1px alpha(#000, 0.05), 0 3px 3px alpha(#000, 0.22); } diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index ab0900095..e4cde0ab3 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -28,7 +28,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { private Gtk.Popover context_menu; private Gtk.GestureClick overlay_event_controller; private Gtk.Revealer check_revealer; - private Gtk.Image image; + private Gtk.Picture image; public string? thumb_path { get; construct set; } public bool thumb_valid { get; construct; } @@ -72,31 +72,19 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } construct { - add_css_class ("wallpaper-container"); - - scale = get_style_context ().get_scale (); - - height_request = THUMB_HEIGHT + 18; - width_request = THUMB_WIDTH + 18; - var provider = new Gtk.CssProvider (); provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/plug.css"); Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - image = new Gtk.Image () { - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER + image = new Gtk.Picture () { + can_shrink = true }; - image.get_style_context ().set_scale (1); - // We need an extra grid to not apply a scale == 1 to the "card" style. card_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - margin_start = 9, - margin_end = 9, - margin_top = 9, - margin_bottom = 9 + overflow = Gtk.Overflow.HIDDEN }; - card_box.add_css_class ("card"); + card_box.add_css_class (Granite.STYLE_CLASS_CARD); + card_box.add_css_class (Granite.STYLE_CLASS_ROUNDED); card_box.append (image); var check = new Gtk.Image.from_icon_name ("selection-checked") { @@ -111,19 +99,15 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { }; var overlay = new Gtk.Overlay () { - child = card_box + child = card_box, + halign = Gtk.Align.CENTER }; overlay.add_overlay (check_revealer); overlay_event_controller = new Gtk.GestureClick (); overlay.add_controller (overlay_event_controller); - halign = Gtk.Align.CENTER; - valign = Gtk.Align.CENTER; - margin_start = 6; - margin_end = 6; - margin_top = 6; - margin_bottom = 6; + add_css_class ("wallpaper-container"); child = overlay; if (uri != null) { @@ -151,6 +135,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { overlay_event_controller.pressed.connect (show_context_menu); + scale = get_style_context ().get_scale (); try { if (uri != null) { if (thumb_path != null && thumb_valid) { @@ -159,8 +144,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { generate_and_load_thumb (); } } else { - thumb = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH * scale, THUMB_HEIGHT * scale); - image.gicon = thumb; + image.set_pixbuf (new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH * scale, THUMB_HEIGHT * scale)); } } catch (Error e) { critical ("Failed to load wallpaper thumbnail: %s", e.message); @@ -217,9 +201,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { return; } - image.set_from_file (thumb_path); - image.width_request = THUMB_WIDTH; - image.height_request = THUMB_HEIGHT; + image.set_filename (thumb_path); load_artist_tooltip (); } From 8f1e8663742bec33b6243c308d8f2826c313da02 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Tue, 21 Jun 2022 20:40:53 +0800 Subject: [PATCH 13/40] Update dock --- src/Views/Dock.vala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index f27c2e816..d6346150a 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -281,10 +281,9 @@ public class PantheonShell.Dock : Gtk.Grid { var mutter_monitor = mutter_monitors[i]; var logical_monitor = mutter_logical_monitors[i]; - if (mutter_monitor.monitor.connector == logical_monitor.monitors[0].connector) { - var display_name_variant = mutter_monitor.properties.lookup ("display-name"); - if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { - monitor.append_text (display_name_variant.get_string ()); + if (mutter_monitor.monitor in logical_monitor.monitors) { + if (mutter_monitor.monitor.connector != null && mutter_monitor.monitor.connector != "") { + monitor.append_text (mutter_monitor.monitor.connector); if (logical_monitor.primary) { primary_screen = i; continue; From f35fe4467c09bccf394f928356cb8cbdb3a564fd Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Sat, 2 Jul 2022 18:09:43 +0800 Subject: [PATCH 14/40] Fix regressions --- src/Views/Multitasking.vala | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Views/Multitasking.vala b/src/Views/Multitasking.vala index c4e097d96..cb91146f8 100644 --- a/src/Views/Multitasking.vala +++ b/src/Views/Multitasking.vala @@ -46,13 +46,12 @@ public class PantheonShell.Multitasking : Gtk.Box { var fullscreen_checkbutton = new Gtk.CheckButton.with_label (_("When entering fullscreen")); var maximize_checkbutton = new Gtk.CheckButton.with_label (_("When maximizing")); - var checkbutton_grid = new Gtk.Grid () { - column_spacing = 12, + var checkbutton_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12) { margin_top = 12, margin_bottom = 12 }; - checkbutton_grid.append (fullscreen_checkbutton); - checkbutton_grid.append (maximize_checkbutton); + checkbutton_box.append (fullscreen_checkbutton); + checkbutton_box.append (maximize_checkbutton); var animations_label = new Gtk.Label (_("Window animations:")) { halign = Gtk.Align.END @@ -76,16 +75,16 @@ public class PantheonShell.Multitasking : Gtk.Box { grid.attach (bottomleft, 0, 3, 2); grid.attach (bottomright, 0, 4, 2); grid.attach (workspaces_label, 0, 6); - grid.attach (checkbutton_grid, 1, 6); + grid.attach (checkbutton_box, 1, 6); grid.attach (animations_label, 0, 7); grid.attach (animations_switch, 1, 7); - var scrolled = new Gtk.ScrolledWindow (null, null) { - hscrollbar_policy = Gtk.PolicyType.NEVER + var scrolled = new Gtk.ScrolledWindow () { + hscrollbar_policy = Gtk.PolicyType.NEVER, + child = grid }; - scrolled.add (grid); - add (scrolled); + append (scrolled); var animations_settings = new GLib.Settings (ANIMATIONS_SCHEMA); animations_settings.bind (ANIMATIONS_KEY, animations_switch, "active", SettingsBindFlags.DEFAULT); @@ -146,9 +145,9 @@ public class PantheonShell.Multitasking : Gtk.Box { var command_revealer = new Gtk.Revealer () { margin_top = 6, - transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN + transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN, + child = command_entry }; - command_revealer.add (command_entry); margin_bottom = 12; column_spacing = 12; From c75a4a7f7c74fbade847a29b41e4026da257bee1 Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Sat, 9 Jul 2022 20:03:03 +0800 Subject: [PATCH 15/40] Use Clamp --- meson.build | 4 ++-- src/Views/Appearance.vala | 17 +++++++++++++---- src/Views/Dock.vala | 18 +++++++++++++----- src/Views/Multitasking.vala | 23 +++++++++++++++-------- src/Views/Text.vala | 17 +++++++++++++---- src/meson.build | 2 +- 6 files changed, 57 insertions(+), 24 deletions(-) diff --git a/meson.build b/meson.build index 5ac1b71f4..837d14238 100644 --- a/meson.build +++ b/meson.build @@ -27,8 +27,8 @@ gio_dep = dependency('gio-2.0') glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') -granite_dep = dependency('granite', version: '>=6.0.0') -gtk_dep = dependency('gtk+-3.0', version: '>= 3.22') +granite_dep = dependency('granite-7') +gtk_dep = dependency('gtk4') adw_dep = dependency ('libadwaita-1') posix_dep = meson.get_compiler('vala').find_library('posix') diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala index 92d8f2598..0b63dfe40 100644 --- a/src/Views/Appearance.vala +++ b/src/Views/Appearance.vala @@ -18,7 +18,7 @@ * */ -public class PantheonShell.Appearance : Gtk.Box { +public class PantheonShell.Appearance : Gtk.Widget { private const string INTERFACE_SCHEMA = "org.gnome.desktop.interface"; private const string STYLESHEET_KEY = "gtk-theme"; private const string STYLESHEET_PREFIX = "io.elementary.stylesheet."; @@ -66,6 +66,10 @@ public class PantheonShell.Appearance : Gtk.Box { } } + static construct { + set_layout_manager_type (typeof (Gtk.BinLayout)); + } + construct { var dark_label = new Granite.HeaderLabel (_("Style")); @@ -355,10 +359,15 @@ public class PantheonShell.Appearance : Gtk.Box { grid.attach (accent_grid, 0, 9, 2); } - var clamp = new Hdy.Clamp (); - clamp.add (grid); + var clamp = new Adw.Clamp () { + child = grid + }; + + clamp.set_parent (this); + } - add (clamp); + ~Appearance () { + this.get_last_child ().unparent (); } private class PrefersAccentColorButton : Gtk.CheckButton { diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index 5e6d778ed..14b010a23 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -17,7 +17,7 @@ * Boston, MA 02110-1301 USA */ -public class PantheonShell.Dock : Gtk.Box { +public class PantheonShell.Dock : Gtk.Widget { private const string PANEL_SCHEMA = "io.elementary.desktop.wingpanel"; private const string TRANSLUCENCY_KEY = "use-transparency"; @@ -37,6 +37,10 @@ public class PantheonShell.Dock : Gtk.Box { DODGE_ACTIVE } + static construct { + set_layout_manager_type (typeof (Gtk.BinLayout)); + } + construct { var dock_header = new Granite.HeaderLabel (_("Dock")); @@ -212,7 +216,7 @@ public class PantheonShell.Dock : Gtk.Box { }; grid.attach (dock_header, 0, 0, 3); grid.attach (icon_label, 0, 1); - grid.attach (icon_size_box, 1, 1, 2); + grid.attach (icon_size_grid, 1, 1, 2); grid.attach (hide_label, 0, 2); grid.attach (hide_mode, 1, 2); grid.attach (hide_switch, 2, 2); @@ -226,10 +230,11 @@ public class PantheonShell.Dock : Gtk.Box { grid.attach (translucency_label, 0, 7); grid.attach (translucency_switch, 1, 7); - var clamp = new Hdy.Clamp (); - clamp.add (grid); + var clamp = new Adw.Clamp () { + child = grid + }; - add (clamp); + clamp.set_parent (this); check_for_screens (); @@ -371,4 +376,7 @@ public class PantheonShell.Dock : Gtk.Box { return (int) monitors.get_n_items (); } + ~Dock () { + this.get_last_child ().unparent (); + } } diff --git a/src/Views/Multitasking.vala b/src/Views/Multitasking.vala index afe30f092..ca3ed9b51 100644 --- a/src/Views/Multitasking.vala +++ b/src/Views/Multitasking.vala @@ -19,11 +19,15 @@ * Authored by: Tom Beckmann */ -public class PantheonShell.Multitasking : Gtk.Box { +public class PantheonShell.Multitasking : Gtk.Widget { private GLib.Settings behavior_settings; private const string ANIMATIONS_SCHEMA = "org.pantheon.desktop.gala.animations"; private const string ANIMATIONS_KEY = "enable-animations"; + static construct { + set_layout_manager_type (typeof (Gtk.BinLayout)); + } + construct { var hotcorner_title = new Gtk.Label (_("When the pointer enters a display corner")) { halign = Gtk.Align.START, @@ -73,21 +77,20 @@ public class PantheonShell.Multitasking : Gtk.Box { grid.attach (bottomleft, 0, 3, 2); grid.attach (bottomright, 0, 4, 2); grid.attach (workspaces_label, 0, 6, 2); - grid.attach (checkbutton_grid, 0, 7, 2); + grid.attach (checkbutton_box, 0, 7, 2); grid.attach (animations_label, 0, 8); grid.attach (animations_switch, 1, 8); - var clamp = new Hdy.Clamp (); - clamp.add (grid); + var clamp = new Adw.Clamp () { + child = grid + }; var scrolled = new Gtk.ScrolledWindow () { hscrollbar_policy = Gtk.PolicyType.NEVER, - child = grid + child = clamp }; - scrolled.add (clamp); - - append (scrolled); + scrolled.set_parent (this); var animations_settings = new GLib.Settings (ANIMATIONS_SCHEMA); animations_settings.bind (ANIMATIONS_KEY, animations_switch, "active", SettingsBindFlags.DEFAULT); @@ -97,6 +100,10 @@ public class PantheonShell.Multitasking : Gtk.Box { behavior_settings.bind ("move-maximized-workspace", maximize_checkbutton, "active", GLib.SettingsBindFlags.DEFAULT); } + ~Multitasking () { + this.get_last_child ().unparent (); + } + private class HotcornerControl : Gtk.Grid { public string label { get; construct; } public string position { get; construct; } diff --git a/src/Views/Text.vala b/src/Views/Text.vala index aba8c9d7d..fadf971d9 100644 --- a/src/Views/Text.vala +++ b/src/Views/Text.vala @@ -18,7 +18,7 @@ * */ -public class PantheonShell.Text : Gtk.Box { +public class PantheonShell.Text : Gtk.Widget { private const string DYSLEXIA_KEY = "dyslexia-friendly-support"; private const string FONT_KEY = "font-name"; private const string DOCUMENT_FONT_KEY = "document-font-name"; @@ -30,6 +30,10 @@ public class PantheonShell.Text : Gtk.Box { private uint scale_timeout; + static construct { + set_layout_manager_type (typeof (Gtk.BinLayout)); + } + construct { var size_label = new Gtk.Label (_("Size:")) { halign = Gtk.Align.END @@ -78,10 +82,11 @@ public class PantheonShell.Text : Gtk.Box { grid.attach (dyslexia_font_switch, 1, 1); grid.attach (dyslexia_font_description_label, 1, 2, 2); - var clamp = new Hdy.Clamp (); - clamp.add (grid); + var clamp = new Adw.Clamp () { + child = grid + }; - add (clamp); + clamp.set_parent (this); var interface_settings = new Settings ("org.gnome.desktop.interface"); interface_settings.bind ("text-scaling-factor", size_adjustment, "value", SettingsBindFlags.GET); @@ -117,4 +122,8 @@ public class PantheonShell.Text : Gtk.Box { } }); } + + ~Text () { + this.get_last_child ().unparent (); + } } diff --git a/src/meson.build b/src/meson.build index ed2326331..529826fd5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -37,7 +37,7 @@ shared_module( gobject_dep, granite_dep, gtk_dep, - hdy_dep, + adw_dep, dependency('gexiv2'), posix_dep, switchboard_dep From 1b3f3d49a5e75b2b1516c7aff3d715cd1ce60b9a Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 5 Aug 2022 14:51:17 +0800 Subject: [PATCH 16/40] Unsupport preview --- src/Views/Wallpaper.vala | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index a8784be0c..a68d3a22e 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -152,10 +152,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var filter = new Gtk.FileFilter (); filter.add_mime_type ("image/*"); - var preview_area = new Gtk.Image (); - preview_area.pixel_size = 256; - preview_area.margin_end = 12; - var chooser = new Gtk.FileChooserNative ( _("Import Photo"), null, Gtk.FileChooserAction.OPEN, _("Import"), @@ -163,19 +159,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { ); chooser.filter = filter; chooser.select_multiple = true; - // chooser.set_preview_widget (preview_area); - - // chooser.update_preview.connect (() => { - // string uri = chooser.get_preview_uri (); - - // if (uri != null && uri.has_prefix ("file://") == true) { - // var file = GLib.File.new_for_uri (uri); - // preview_area.set_from_gicon_async.begin (new FileIcon (file), 256); - // preview_area.show (); - // } else { - // preview_area.hide (); - // } - // }); chooser.show (); From 8b275237e510340081abbff4a7ba5f19b5acd43e Mon Sep 17 00:00:00 2001 From: ZenitsuDev Date: Fri, 5 Aug 2022 22:15:56 +0800 Subject: [PATCH 17/40] Simplify getting display names --- src/Interfaces/MutterDisplayConfig.vala | 176 ------------------------ src/Views/Dock.vala | 112 +++++---------- src/meson.build | 1 - 3 files changed, 31 insertions(+), 258 deletions(-) delete mode 100644 src/Interfaces/MutterDisplayConfig.vala diff --git a/src/Interfaces/MutterDisplayConfig.vala b/src/Interfaces/MutterDisplayConfig.vala deleted file mode 100644 index 181229810..000000000 --- a/src/Interfaces/MutterDisplayConfig.vala +++ /dev/null @@ -1,176 +0,0 @@ -/*- - * Copyright (c) 2018 elementary LLC. - * - * This software is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this software; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Authored by: Corentin Noël - */ - -[DBus (name = "org.gnome.Mutter.DisplayConfig")] -public interface MutterDisplayConfigInterface : Object { - public abstract void get_resources (out uint serial, out MutterReadDisplayCrtc[] crtcs, out MutterReadDisplayOutput[] outputs, out MutterReadDisplayMode[] modes, out int max_screen_width, out int max_screen_height) throws Error; - public abstract void apply_configuration (uint serial, bool persistent, MutterWriteDisplayCrtc[] crtcs, MutterWriteDisplayOutput[] outputs) throws Error; - public abstract int change_backlight (uint serial, uint output, int value) throws Error; - public abstract void get_crtc_gamma (uint serial, uint crtc, out uint[] red, out uint[] green, out uint[] blue) throws Error; - public abstract void set_crtc_gamma (uint serial, uint crtc, uint[] red, uint[] green, uint[] blue) throws Error; - public abstract int power_save_mode { get; set; } - public signal void monitors_changed (); - public abstract void get_current_state (out uint serial, out MutterReadMonitor[] monitors, out MutterReadLogicalMonitor[] logical_monitors, out GLib.HashTable properties) throws Error; - public abstract void apply_monitors_config (uint serial, MutterApplyMethod method, MutterWriteLogicalMonitor[] logical_monitors, GLib.HashTable properties) throws Error; -} - -[CCode (type_signature = "u")] -public enum MutterApplyMethod { - VERIFY = 0, - TEMPORARY = 1, - PERSISTENT = 2 -} - -[CCode (type_signature = "u")] -public enum DisplayTransform { - NORMAL = 0, - ROTATION_90 = 1, - ROTATION_180 = 2, - ROTATION_270 = 3, - FLIPPED = 4, - FLIPPED_ROTATION_90 = 5, - FLIPPED_ROTATION_180 = 6, - FLIPPED_ROTATION_270 = 7; - - public string to_string () { - // These values are based on the direction that the physical display has been rotated from its original position. - // They should not reflect the rotation that must be applied to the contents on screen. - switch (this) { - case ROTATION_90: - return _("Clockwise"); - case ROTATION_180: - return _("Upside-down"); - case ROTATION_270: - return _("Counterclockwise"); - case FLIPPED: - return _("Flipped"); - case FLIPPED_ROTATION_90: - return _("Flipped Clockwise"); - case FLIPPED_ROTATION_180: - return _("Flipped Upside-down"); - case FLIPPED_ROTATION_270: - return _("Flipped Counterclockwise"); - default: - return _("None"); - } - } -} - -public struct MutterReadMonitorInfo { - public string connector; - public string vendor; - public string product; - public string serial; - public uint hash { - get { - return (connector + vendor + product + serial).hash (); - } - } -} - -public struct MutterReadMonitorMode { - public string id; - public int width; - public int height; - public double frequency; - public double preferred_scale; - public double[] supported_scales; - public GLib.HashTable properties; -} - -public struct MutterReadMonitor { - public MutterReadMonitorInfo monitor; - public MutterReadMonitorMode[] modes; - public GLib.HashTable properties; -} - -public struct MutterReadLogicalMonitor { - public int x; - public int y; - public double scale; - public DisplayTransform transform; - public bool primary; - public MutterReadMonitorInfo[] monitors; - public GLib.HashTable properties; -} - -public struct MutterWriteMonitor { - public string connector; - public string monitor_mode; - public GLib.HashTable properties; -} - -public struct MutterWriteLogicalMonitor { - public int x; - public int y; - public double scale; - public DisplayTransform transform; - public bool primary; - public MutterWriteMonitor[] monitors; -} - -public struct MutterReadDisplayCrtc { - public uint id; - public int64 winsys_id; - public int x; - public int y; - public int width; - public int height; - public int current_mode; - public DisplayTransform current_transform; - public DisplayTransform[] transforms; - public GLib.HashTable properties; -} - -public struct MutterWriteDisplayCrtc { - public uint id; - public int new_mode; - public int x; - public int y; - public DisplayTransform transform; - public uint[] outputs; - public GLib.HashTable properties; -} - -public struct MutterReadDisplayOutput { - public uint id; - public int64 winsys_id; - public int current_crtc; - public uint[] possible_crtcs; - public string connector_name; - public uint[] modes; - public uint[] clones; - public GLib.HashTable properties; -} - -public struct MutterWriteDisplayOutput { - public uint id; - public GLib.HashTable properties; -} - -public struct MutterReadDisplayMode { - public uint id; - public int64 winsys_id; - public uint width; - public uint height; - public double frequency; - public uint flags; -} diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index 14b010a23..d8689fcf6 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -24,9 +24,8 @@ public class PantheonShell.Dock : Gtk.Widget { private Gtk.Label primary_monitor_label; private Gtk.Switch primary_monitor; private Gtk.Label monitor_label; - private Gtk.ComboBoxText monitor; + private Gtk.ComboBoxText monitor_combo; private Settings dock_preferences; - private MutterDisplayConfigInterface iface; private enum PlankHideTypes { NONE, @@ -141,7 +140,7 @@ public class PantheonShell.Dock : Gtk.Widget { } }); - monitor = new Gtk.ComboBoxText (); + monitor_combo = new Gtk.ComboBoxText (); primary_monitor_label = new Gtk.Label (_("Primary display:")) { halign = Gtk.Align.END @@ -156,33 +155,25 @@ public class PantheonShell.Dock : Gtk.Widget { if (primary_monitor.active == true) { dock_preferences.set_string ("monitor", ""); monitor_label.sensitive = false; - monitor.sensitive = false; + monitor_combo.sensitive = false; } else { var plug_names = get_monitor_plug_names (get_display ()); if (plug_names.length > monitor.active) dock_preferences.set_string ("monitor", plug_names[monitor.active]); monitor_label.sensitive = true; - monitor.sensitive = true; + monitor_combo.sensitive = true; } }); primary_monitor.active = (dock_preferences.get_string ("monitor") == ""); - monitor.notify["active"].connect (() => { - if (monitor.active >= 0 && primary_monitor.active == false) { + monitor_combo.notify["active"].connect (() => { + if (monitor_combo.active >= 0 && primary_monitor.active == false) { var plug_names = get_monitor_plug_names (get_display ()); - if (plug_names.length > monitor.active) - dock_preferences.set_string ("monitor", plug_names[monitor.active]); + if (plug_names.length > monitor_combo.active) + dock_preferences.set_string ("monitor", plug_names[monitor_combo.active]); } }); - try { - iface = Bus.get_proxy_sync (BusType.SESSION, "org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig"); - } catch (Error e) { - critical (e.message); - } - - iface.monitors_changed.connect (() => {check_for_screens ();}); - var icon_label = new Gtk.Label (_("Icon size:")) { halign = Gtk.Align.END }; @@ -223,7 +214,7 @@ public class PantheonShell.Dock : Gtk.Widget { grid.attach (primary_monitor_label, 0, 3); grid.attach (primary_monitor_grid, 1, 3); grid.attach (monitor_label, 0, 4); - grid.attach (monitor, 1, 4); + grid.attach (monitor_combo, 1, 4); grid.attach (pressure_label, 0, 5); grid.attach (pressure_switch, 1, 5); grid.attach (panel_header, 0, 6, 3); @@ -236,7 +227,13 @@ public class PantheonShell.Dock : Gtk.Widget { clamp.set_parent (this); - check_for_screens (); + var display = get_display (); + var monitors_list = display.get_monitors (); + monitors_list.items_changed.connect (() => { + check_for_screens (monitors_list); + ); + + check_for_screens (monitors_list); switch (dock_preferences.get_int ("icon-size")) { case 32: @@ -269,85 +266,38 @@ public class PantheonShell.Dock : Gtk.Widget { panel_settings.bind (TRANSLUCENCY_KEY, translucency_switch, "active", SettingsBindFlags.DEFAULT); } - private void check_for_screens () { - int i; + private void check_for_screens (ListModel monitors) { + int index = 0; int primary_screen = 0; - var default_display = get_display (); - monitor.remove_all (); - - // the following code was taken from switchboard-plug-display - - MutterReadMonitor[] mutter_monitors; - MutterReadLogicalMonitor[] mutter_logical_monitors; - GLib.HashTable properties; - uint current_serial; - - try { - iface.get_current_state (out current_serial, out mutter_monitors, out mutter_logical_monitors, out properties); - } catch (Error e) { - critical (e.message); - for (i = 0; i < default_display.get_monitors ().get_n_items () ; i ++) { - monitor.append_text (_("Display %d").printf (i + 1)); - } - } + monitor_combo.remove_all (); - for (i = 0; i < mutter_monitors.length; i++) { - var mutter_monitor = mutter_monitors[i]; - var logical_monitor = mutter_logical_monitors[i]; - - if (mutter_monitor.monitor in logical_monitor.monitors) { - if (mutter_monitor.monitor.connector != null && mutter_monitor.monitor.connector != "") { - monitor.append_text (mutter_monitor.monitor.connector); - if (logical_monitor.primary) { - primary_screen = i; - continue; - } - } + // TODO: get primary display - monitor.append_text (_("Monitor %d").printf (i + 1)); + for (index = 0; index < monitors.get_n_items (); index++) { + var monitor = (Gdk.Monitor) monitors.get_item (index); + if (monitor.connector != null || monitor.connector != "") { + monitor_combo.append_text (monitor.connector); + } else { + monitor_combo.append_text ("Display %d", index + 1); } } - // foreach (var mutter_monitor in mutter_monitors) { - // var display_name_variant = mutter_monitor.properties.lookup ("display-name"); - // print ("%s\n", mutter_monitor.monitor.connector.to_string ()); - // if (display_name_variant.get_string () != null && display_name_variant.get_string () != "") { - // monitor.append_text (display_name_variant.get_string ()); - // // var is_preferred = mutter_monitor.properties.lookup ("is-preferred");; - // // if (is_preferred.get_boolean () == true) { - // // primary_screen = i; - // // } - - // i++; - // } - - // monitor.append_text (_("Monitor %d").printf (i + 1) ); - // } - - // foreach (var logical_monitor in mutter_logical_monitors) { - // // var display_name_variant = logical_monitor.properties.lookup ("display-name"); - // print ("%s\n", logical_monitor.monitors[0].connector.to_string ()); - // // logical_monitor.properties.get_keys ().foreach ((key) => { - // // print ("%s\n", key); - // // }); - // } - - if (i <= 1) { + if (index <= 1) { primary_monitor_label.hide (); primary_monitor.hide (); monitor_label.hide (); - monitor.hide (); + monitor_combo.hide (); } else { if (dock_preferences.get_string ("monitor") != "") { - monitor.active = find_monitor_number (get_display (), dock_preferences.get_string ("monitor")); + monitor_combo.active = find_monitor_number (get_display (), dock_preferences.get_string ("monitor")); } else { - monitor.active = primary_screen; + monitor_combo.active = primary_screen; } primary_monitor_label.show (); primary_monitor.show (); monitor_label.show (); - monitor.show (); + monitor_combo.show (); } } diff --git a/src/meson.build b/src/meson.build index 529826fd5..a13bf841d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,7 +3,6 @@ plug_files = files( 'PantheonAccountsServicePlugin.vala', 'Plug.vala', 'ThumbnailGenerator.vala', - 'Interfaces/MutterDisplayConfig.vala', 'Views/Appearance.vala', 'Views/Dock.vala', 'Views/Multitasking.vala', From 61423dee03957c23652a352dcc95129e8f9184aa Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Tue, 9 Aug 2022 09:08:26 +0100 Subject: [PATCH 18/40] Fix Dock.vala compilation --- src/Views/Dock.vala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index d8689fcf6..19352131e 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -158,8 +158,10 @@ public class PantheonShell.Dock : Gtk.Widget { monitor_combo.sensitive = false; } else { var plug_names = get_monitor_plug_names (get_display ()); - if (plug_names.length > monitor.active) - dock_preferences.set_string ("monitor", plug_names[monitor.active]); + if (plug_names.length > monitor_combo.active) { + dock_preferences.set_string ("monitor", plug_names[monitor_combo.active]); + } + monitor_label.sensitive = true; monitor_combo.sensitive = true; } @@ -231,7 +233,7 @@ public class PantheonShell.Dock : Gtk.Widget { var monitors_list = display.get_monitors (); monitors_list.items_changed.connect (() => { check_for_screens (monitors_list); - ); + }); check_for_screens (monitors_list); @@ -278,7 +280,7 @@ public class PantheonShell.Dock : Gtk.Widget { if (monitor.connector != null || monitor.connector != "") { monitor_combo.append_text (monitor.connector); } else { - monitor_combo.append_text ("Display %d", index + 1); + monitor_combo.insert_text (index + 1, "Display %d"); } } From 9c5e18740ae54fc7de10f3682bed27bd34984c5d Mon Sep 17 00:00:00 2001 From: lenemter Date: Thu, 11 Aug 2022 17:53:38 +0900 Subject: [PATCH 19/40] Merge branch 'master' into gtk4 --- src/Plug.vala | 2 +- src/Views/Wallpaper.vala | 2 +- src/Widgets/WallpaperContainer.vala | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Plug.vala b/src/Plug.vala index 60322a952..994d89913 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -38,7 +38,7 @@ public class PantheonShell.Plug : Switchboard.Plug { var provider = new Gtk.CssProvider (); provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/plug.css"); - Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); // DEPRECATED settings.set ("desktop/wallpaper", "wallpaper"); diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index d2892050b..0949897f1 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -602,7 +602,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private void undo_removal () { - wallpaper_view.add (wallpaper_for_removal); + wallpaper_view.append (wallpaper_for_removal); wallpaper_for_removal = null; } } diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index 81c1c3f0b..1d061d554 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -72,10 +72,6 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } construct { - var provider = new Gtk.CssProvider (); - provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/plug.css"); - Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - image = new Gtk.Picture () { can_shrink = true }; From 8e07beeda704ebce87ade7b7c7feebee16ffa217 Mon Sep 17 00:00:00 2001 From: lenemter Date: Thu, 11 Aug 2022 17:54:46 +0900 Subject: [PATCH 20/40] Fix lint --- src/Views/Wallpaper.vala | 2 +- src/Widgets/WallpaperContainer.vala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 0949897f1..9f26c9da8 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -105,7 +105,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { view_overlay = new Gtk.Overlay () { child = wallpaper_scrolled_window }; - + var add_wallpaper_button = new Gtk.Button.with_label (_("Import Photo…")) { margin_start = 12, margin_end = 12, diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index 1d061d554..e415334a0 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -75,7 +75,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { image = new Gtk.Picture () { can_shrink = true }; - + card_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { overflow = Gtk.Overflow.HIDDEN }; From db6adb20d405062cac5584ce6f456fecf3c3ce77 Mon Sep 17 00:00:00 2001 From: lenemter Date: Thu, 11 Aug 2022 20:04:32 +0900 Subject: [PATCH 21/40] Fix solid color container --- src/Widgets/SolidColorContainer.vala | 2 ++ src/Widgets/WallpaperContainer.vala | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Widgets/SolidColorContainer.vala b/src/Widgets/SolidColorContainer.vala index ba14817be..29162101c 100644 --- a/src/Widgets/SolidColorContainer.vala +++ b/src/Widgets/SolidColorContainer.vala @@ -34,7 +34,9 @@ public class PantheonShell.SolidColorContainer : WallpaperContainer { } construct { + var thumb = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH, THUMB_HEIGHT); thumb.fill (rgba_to_pixel (rgba)); + image.set_pixbuf (thumb); } // Borrowed from diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index e415334a0..0942955d4 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -21,19 +21,18 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { public signal void trash (); - private const int THUMB_WIDTH = 162; - private const int THUMB_HEIGHT = 100; + protected const int THUMB_WIDTH = 162; + protected const int THUMB_HEIGHT = 100; private Gtk.Box card_box; private Gtk.Popover context_menu; private Gtk.GestureClick overlay_event_controller; private Gtk.Revealer check_revealer; - private Gtk.Picture image; + protected Gtk.Picture image; public string? thumb_path { get; construct set; } public bool thumb_valid { get; construct; } public string uri { get; construct; } - public Gdk.Pixbuf thumb { get; set; } private int scale; From 20ce586618824d5309542c39fd4a35faf3f1162b Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 12 Aug 2022 00:20:52 +0900 Subject: [PATCH 22/40] Wallpapers cleanup, improvements and fixes --- src/Plug.vala | 2 +- src/Views/Wallpaper.vala | 72 ++++++++++++---------------- src/Widgets/SolidColorContainer.vala | 2 +- src/Widgets/WallpaperContainer.vala | 8 +++- 4 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/Plug.vala b/src/Plug.vala index 994d89913..b0a244ac2 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -56,7 +56,7 @@ public class PantheonShell.Plug : Switchboard.Plug { if (main_grid == null) { main_grid = new Gtk.Grid (); - wallpaper_view = new Wallpaper (this); + wallpaper_view = new Wallpaper (); var multitasking = new Multitasking (); var appearance = new Appearance (); diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 9f26c9da8..93bb1d3ae 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -23,11 +23,6 @@ interface PantheonShell.AccountsServiceUser : Object { } public class PantheonShell.Wallpaper : Gtk.Grid { - public enum ColumnType { - ICON, - NAME - } - private const string [] REQUIRED_FILE_ATTRS = { FileAttribute.STANDARD_NAME, FileAttribute.STANDARD_TYPE, @@ -39,7 +34,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { FileAttribute.THUMBNAIL_IS_VALID }; - public Switchboard.Plug plug { get; construct set; } private GLib.Settings settings; //Instance of the AccountsServices-Interface for this user @@ -61,10 +55,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { private bool prevent_update_mode = false; // When restoring the combo state, don't trigger the update. private bool finished; // Shows that we got or wallpapers together - public Wallpaper (Switchboard.Plug _plug) { - Object (plug: _plug); - } - construct { settings = new GLib.Settings ("org.gnome.desktop.background"); @@ -113,8 +103,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { margin_bottom = 12 }; - combo = new Gtk.ComboBoxText (); - combo.valign = Gtk.Align.CENTER; + combo = new Gtk.ComboBoxText () { + valign = Gtk.Align.CENTER + }; combo.append ("centered", _("Centered")); combo.append ("zoom", _("Zoom")); combo.append ("spanned", _("Spanned")); @@ -129,16 +120,11 @@ public class PantheonShell.Wallpaper : Gtk.Grid { margin_start = 0, margin_end = 12, margin_top = 12, - margin_bottom = 12 + margin_bottom = 12, + rgba = rgba_color }; - color_button.rgba = rgba_color; color_button.color_set.connect (update_color); - var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); - size_group.add_widget (add_wallpaper_button); - size_group.add_widget (combo); - size_group.add_widget (color_button); - load_settings (); var actionbar = new Gtk.ActionBar (); @@ -147,9 +133,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { actionbar.pack_end (color_button); actionbar.pack_end (combo); - attach (separator, 0, 0, 1, 1); - attach (view_overlay, 0, 1, 1, 1); - attach (actionbar, 0, 2, 1, 1); + attach (separator, 0, 0); + attach (view_overlay, 0, 1); + attach (actionbar, 0, 2); add_wallpaper_button.clicked.connect (show_wallpaper_chooser); } @@ -162,9 +148,10 @@ public class PantheonShell.Wallpaper : Gtk.Grid { _("Import Photo"), null, Gtk.FileChooserAction.OPEN, _("Import"), _("Cancel") - ); - chooser.filter = filter; - chooser.select_multiple = true; + ) { + filter = filter, + select_multiple = true + }; chooser.show (); @@ -193,12 +180,12 @@ public class PantheonShell.Wallpaper : Gtk.Grid { // about it anymore. The previous state should be loaded instead here. string picture_options = settings.get_string ("picture-options"); if (picture_options == "none") { - combo.set_sensitive (false); + combo.sensitive = false; picture_options = "zoom"; } prevent_update_mode = true; - combo.set_active_id (picture_options); + combo.active_id = picture_options; current_wallpaper_path = settings.get_string ("picture-uri"); } @@ -243,7 +230,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { update_accountsservice (); if (active_wallpaper == solid_color) { - combo.set_sensitive (true); + combo.sensitive = true; settings.set_string ("picture-options", combo.get_active_id ()); } @@ -308,7 +295,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { private void set_combo_disabled_if_necessary () { if (active_wallpaper != solid_color) { - combo.set_sensitive (false); + combo.sensitive = false; settings.set_string ("picture-options", "none"); } } @@ -403,9 +390,11 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private void clean_wallpapers () { - var children = wallpaper_view.observe_children (); - for (var index = 0; index < children.get_n_items (); index++) { - ((Gtk.Widget) children.get_item (index)).destroy (); + var child = wallpaper_view.get_first_child (); + while (child != null) { + wallpaper_view.remove (child); + child.destroy (); + child = wallpaper_view.get_first_child (); } solid_color = null; @@ -496,14 +485,13 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private bool on_drag_data_received (Gtk.DropTarget controller, Value val, double x, double y) { - var drop_target = (Gtk.DropTarget) controller; var file_list = (Gdk.FileList) val; - file_list.get_files ().foreach ((file) => { + foreach (var file in file_list.get_files ()) { try { - var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); + var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), FileQueryInfoFlags.NONE); if (!IOHelper.is_valid_file_type (info)) { - drop_target.reject (); + continue; } string local_uri = file.get_uri (); @@ -516,9 +504,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } catch (Error e) { warning (e.message); } - }); + } - return false; + return true; } private void add_wallpaper_from_file (GLib.File file, string uri) { @@ -528,7 +516,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } try { - var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), 0); + var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), FileQueryInfoFlags.NONE); var thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); var thumb_valid = info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID); var wallpaper = new WallpaperContainer (uri, thumb_path, thumb_valid); @@ -558,12 +546,12 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private void send_undo_toast () { - var children = wallpaper_view.observe_children (); - for (var index = 0; index < children.get_n_items (); index++) { - var child = (Gtk.Widget) children.get_item (index); + var child = view_overlay.get_first_child (); + while (child != null) { if (child is Granite.Toast) { child.destroy (); } + child = view_overlay.get_first_child (); } if (wallpaper_for_removal != null) { diff --git a/src/Widgets/SolidColorContainer.vala b/src/Widgets/SolidColorContainer.vala index 29162101c..9ad944387 100644 --- a/src/Widgets/SolidColorContainer.vala +++ b/src/Widgets/SolidColorContainer.vala @@ -20,7 +20,7 @@ public class PantheonShell.SolidColorContainer : WallpaperContainer { public string color { get; construct; } - public Gdk.RGBA rgba { + private Gdk.RGBA rgba { get { Gdk.RGBA rgba = {}; rgba.parse (color); diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index 0942955d4..b55982917 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -176,7 +176,13 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } if (metadata.has_exif ()) { - var artist_name = metadata.get_tag_string ("Exif.Image.Artist"); + string? artist_name = null; + try { + artist_name = metadata.try_get_tag_string ("Exif.Image.Artist"); + } catch (Error e) { + warning (e.message); + } + if (artist_name != null) { set_tooltip_text (_("Artist: %s").printf (artist_name)); } From db8cef7e5c9370d7d6cb0144bc675eb1b611aa2a Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 12 Aug 2022 00:23:43 +0900 Subject: [PATCH 23/40] Remove toast before destoying --- src/Views/Wallpaper.vala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 93bb1d3ae..068d8a61e 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -549,6 +549,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var child = view_overlay.get_first_child (); while (child != null) { if (child is Granite.Toast) { + view_overlay.remove_overlay (child); child.destroy (); } child = view_overlay.get_first_child (); From 37113786cb91bb33846f4f0e39a64a71ba31d284 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 12 Aug 2022 01:18:51 +0900 Subject: [PATCH 24/40] Fix keyboard style changing --- src/Views/Appearance.vala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala index b50ea1a31..f08351b78 100644 --- a/src/Views/Appearance.vala +++ b/src/Views/Appearance.vala @@ -230,6 +230,24 @@ public class PantheonShell.Appearance : Gtk.Widget { pantheon_act.prefers_color_scheme = Granite.Settings.ColorScheme.DARK; }); + var prefer_default_radio_controller = new Gtk.EventControllerFocus (); + prefer_default_radio_controller.enter.connect (() => { + // Check if selection changed + if (pantheon_act.prefers_color_scheme != Granite.Settings.ColorScheme.NO_PREFERENCE) { + schedule_disabled_radio.active = true; + } + }); + prefer_default_radio.add_controller (prefer_default_radio_controller); + + var prefer_dark_radio_controller = new Gtk.EventControllerFocus (); + prefer_dark_radio_controller.enter.connect (() => { + // Check if selection changed + if (pantheon_act.prefers_color_scheme != Granite.Settings.ColorScheme.DARK) { + schedule_disabled_radio.active = true; + } + }); + prefer_dark_radio.add_controller (prefer_dark_radio_controller); + ((GLib.DBusProxy) pantheon_act).g_properties_changed.connect ((changed, invalid) => { var color_scheme = changed.lookup_value ("PrefersColorScheme", new VariantType ("i")); if (color_scheme != null) { From 7192f8c26013c7ef59ec46b91b62f604eb340ddb Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 12 Aug 2022 01:40:50 +0900 Subject: [PATCH 25/40] Style dock size check buttons --- src/Views/Dock.vala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Views/Dock.vala b/src/Views/Dock.vala index 19352131e..d9effb47c 100644 --- a/src/Views/Dock.vala +++ b/src/Views/Dock.vala @@ -49,6 +49,7 @@ public class PantheonShell.Dock : Gtk.Widget { var icon_size_32 = new Gtk.CheckButton () { tooltip_text = _("Small") }; + icon_size_32.add_css_class ("image-button"); var icon_size_32_image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic") { pixel_size = 32 }; @@ -57,21 +58,22 @@ public class PantheonShell.Dock : Gtk.Widget { var icon_size_48 = new Gtk.CheckButton () { tooltip_text = _("Default") }; + icon_size_48.add_css_class ("image-button"); icon_size_48.group = icon_size_32; var icon_size_48_image = new Gtk.Image.from_icon_name ("application-default-icon-symbolic") { pixel_size = 48 }; icon_size_48_image.set_parent (icon_size_48); - var image_64 = new Gtk.Image () { - icon_name = "application-default-icon-symbolic", - pixel_size = 64 - }; - var icon_size_64 = new Gtk.CheckButton () { tooltip_text = _("Large"), group = icon_size_32 }; + icon_size_64.add_css_class ("image-button"); + var image_64 = new Gtk.Image () { + icon_name = "application-default-icon-symbolic", + pixel_size = 64 + }; image_64.set_parent (icon_size_64); var icon_size_unsupported = new Gtk.CheckButton () { From abdaafc7d2551ea44a4ddeeb18b995de285ce361 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 12 Aug 2022 01:50:38 +0900 Subject: [PATCH 26/40] Fix auto accent color --- src/Views/Appearance.vala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Views/Appearance.vala b/src/Views/Appearance.vala index f08351b78..13b3466bc 100644 --- a/src/Views/Appearance.vala +++ b/src/Views/Appearance.vala @@ -397,7 +397,11 @@ public class PantheonShell.Appearance : Gtk.Widget { construct { add_css_class (Granite.STYLE_CLASS_COLOR_BUTTON); - add_css_class (color.to_string ()); + if (color == AccentColor.NO_PREFERENCE) { + add_css_class ("auto"); + } else { + add_css_class (color.to_string ()); + } realize.connect (() => { active = color == pantheon_act.prefers_accent_color; From 034f527f7a0ae8378460de70e04e005deaaa98b5 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 12 Aug 2022 01:52:33 +0900 Subject: [PATCH 27/40] Fix size_group --- src/Views/Wallpaper.vala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 068d8a61e..477b10233 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -125,6 +125,11 @@ public class PantheonShell.Wallpaper : Gtk.Grid { }; color_button.color_set.connect (update_color); + var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); + size_group.add_widget (add_wallpaper_button); + size_group.add_widget (combo); + size_group.add_widget (color_button); + load_settings (); var actionbar = new Gtk.ActionBar (); From d0ea7460c97d7553e3bf9bfcad3f1a2a202fff32 Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 24 Aug 2022 20:18:01 +0900 Subject: [PATCH 28/40] Use CheckButton as selection check --- data/Check.css | 5 ++ data/check.svg | 120 ---------------------------- data/icons.gresource.xml | 2 +- data/plug.css | 8 -- src/Widgets/WallpaperContainer.vala | 21 ++++- 5 files changed, 24 insertions(+), 132 deletions(-) create mode 100644 data/Check.css delete mode 100644 data/check.svg diff --git a/data/Check.css b/data/Check.css new file mode 100644 index 000000000..3c9a18ad5 --- /dev/null +++ b/data/Check.css @@ -0,0 +1,5 @@ +check { + min-height: 20px; + min-width: 20px; + -gtk-icon-transform: scale(0.6); +} diff --git a/data/check.svg b/data/check.svg deleted file mode 100644 index c43b1fbcd..000000000 --- a/data/check.svg +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/data/icons.gresource.xml b/data/icons.gresource.xml index 6c1b3c3d5..770cea612 100644 --- a/data/icons.gresource.xml +++ b/data/icons.gresource.xml @@ -9,7 +9,7 @@ application-default-icon/64-symbolic.svg appearance-default.svg appearance-dark.svg - check.svg + Check.css plug.css appearance-styles.css diff --git a/data/plug.css b/data/plug.css index fe4855f51..389c1944b 100644 --- a/data/plug.css +++ b/data/plug.css @@ -57,14 +57,6 @@ background-color: transparent; } -.wallpaper-container .check { - border-radius: 50%; - min-width: 18px; - min-height: 18px; - background-color: @accent_color; - -gtk-icon-shadow: 0 1px 1px shade(@accent_color, 0.7); -} - .wallpaper-container .card { margin: 9px; min-height: 128px; diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index a9c7f9ef4..32c2ff711 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -24,6 +24,9 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { protected const int THUMB_WIDTH = 162; protected const int THUMB_HEIGHT = 100; + private static Gtk.CssProvider check_css_provider; + private static Gtk.CheckButton check_group; // Check used for turning CheckButtons into RadioButtons + private Gtk.Box card_box; private Gtk.Popover context_menu; private Gtk.GestureClick overlay_event_controller; @@ -71,6 +74,13 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { Object (uri: uri, thumb_path: thumb_path, thumb_valid: thumb_valid); } + static construct { + check_css_provider = new Gtk.CssProvider (); + check_css_provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/Check.css"); + + check_group = new Gtk.CheckButton (); + } + construct { image = new Gtk.Picture () { can_shrink = true @@ -83,12 +93,17 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { card_box.add_css_class (Granite.STYLE_CLASS_ROUNDED); card_box.append (image); - var check = new Gtk.Image.from_resource ("/io/elementary/switchboard/plug/pantheon-shell/check.svg") { + var check = new Gtk.CheckButton () { halign = Gtk.Align.START, valign = Gtk.Align.START, - can_focus = false + focusable = false, + active = true, + group = check_group }; - check.add_css_class ("check"); + check.notify["active"].connect (() => { + check.active = true; + }); + check.get_style_context ().add_provider (check_css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER); check_revealer = new Gtk.Revealer () { transition_type = Gtk.RevealerTransitionType.CROSSFADE, From 112230fce8d6640c92a88a2ad6c3a03b827ef239 Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 24 Aug 2022 20:24:09 +0900 Subject: [PATCH 29/40] Remove word --- src/Widgets/WallpaperContainer.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index 32c2ff711..15a5509dd 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -25,7 +25,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { protected const int THUMB_HEIGHT = 100; private static Gtk.CssProvider check_css_provider; - private static Gtk.CheckButton check_group; // Check used for turning CheckButtons into RadioButtons + private static Gtk.CheckButton check_group; // used for turning CheckButtons into RadioButtons private Gtk.Box card_box; private Gtk.Popover context_menu; From 980cae530ca35df3afea9411d68cd86f2b16fe8e Mon Sep 17 00:00:00 2001 From: lenemter Date: Wed, 24 Aug 2022 23:16:42 +0900 Subject: [PATCH 30/40] "Fix" wallpaper popover --- src/Views/Wallpaper.vala | 6 +++--- src/Widgets/SolidColorContainer.vala | 4 ++-- src/Widgets/WallpaperContainer.vala | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index b3bc75b2e..01b75a563 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -604,13 +604,13 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private void send_undo_toast () { - var child = view_overlay.get_first_child (); - while (child != null) { + var children = view_overlay.observe_children (); + for (int i = 0; i < children.get_n_items (); i++) { + var child = (Gtk.Widget) children.get_item (i); if (child is Granite.Toast) { view_overlay.remove_overlay (child); child.destroy (); } - child = view_overlay.get_first_child (); } if (wallpaper_for_removal != null) { diff --git a/src/Widgets/SolidColorContainer.vala b/src/Widgets/SolidColorContainer.vala index 9ad944387..a9151f28c 100644 --- a/src/Widgets/SolidColorContainer.vala +++ b/src/Widgets/SolidColorContainer.vala @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015-2016 elementary LLC. + * Copyright 2015-2022 elementary, Inc. (https://elementary.io) * * 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 @@ -40,7 +40,7 @@ public class PantheonShell.SolidColorContainer : WallpaperContainer { } // Borrowed from - // https://github.com/GNOME/california/blob/master/src/util/util-gfx.vala + // https://gitlab.gnome.org/Archive/california/-/blob/master/src/util/util-gfx.vala private static uint32 rgba_to_pixel (Gdk.RGBA rgba) { return (uint32) fp_to_uint8 (rgba.red) << 24 | (uint32) fp_to_uint8 (rgba.green) << 16 diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index 15a5509dd..a320e42c8 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -36,14 +36,15 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { public string? thumb_path { get; construct set; } public bool thumb_valid { get; construct; } public string uri { get; construct; } - public uint64 creation_date = 0; + public uint64 creation_date { get; construct; default = 0; } private int scale; public bool checked { get { return Gtk.StateFlags.CHECKED in get_state_flags (); - } set { + } + set { if (value) { card_box.set_state_flags (Gtk.StateFlags.CHECKED, false); check_revealer.reveal_child = true; @@ -59,7 +60,8 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { public bool selected { get { return Gtk.StateFlags.SELECTED in get_state_flags (); - } set { + } + set { if (value) { set_state_flags (Gtk.StateFlags.SELECTED, false); } else { @@ -117,7 +119,9 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { overlay.add_overlay (check_revealer); - overlay_event_controller = new Gtk.GestureClick (); + overlay_event_controller = new Gtk.GestureClick () { + button = Gdk.BUTTON_SECONDARY + }; overlay.add_controller (overlay_event_controller); add_css_class ("wallpaper-container"); @@ -139,6 +143,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { context_menu = new Gtk.Popover () { child = move_to_trash }; + context_menu.set_parent (this); } activate.connect (() => { @@ -206,12 +211,7 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } private void show_context_menu (int n_press, double x, double y) { - var evt = overlay_event_controller.get_current_event (); - if (evt.get_event_type () == Gdk.EventType.BUTTON_PRESS && evt.get_modifier_state () == Gdk.ModifierType.BUTTON3_MASK) { - context_menu.popup (); - // return Gdk.EVENT_STOP; - } - // return Gdk.EVENT_PROPAGATE; + context_menu.popup (); } private async void update_thumb () { From 8c4b3c3a182340ee92c6b82993c8325c6260d491 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Sun, 28 Aug 2022 06:53:09 +0100 Subject: [PATCH 31/40] Silence some terminal warnings re css parsing (#332) --- data/plug.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/plug.css b/data/plug.css index 389c1944b..2a82f61d8 100644 --- a/data/plug.css +++ b/data/plug.css @@ -72,15 +72,15 @@ .wallpaper-container:focus .card { box-shadow: 0 0 0 4px @accent_color, - 0 0 0 1px alpha (#000, 0.05), - 0 3px 3px alpha (#000, 0.22); + 0 0 0 1px alpha(#000, 0.05), + 0 3px 3px alpha(#000, 0.22); } radiobutton .card { background-image: linear-gradient( to bottom, - alpha (@accent_color_300, 0.1), - alpha (@accent_color_500, 0.1) + alpha(@accent_color_300, 0.1), + alpha(@accent_color_500, 0.1) ); } From 81d9fa3bd4d30f5b17c0d813799447efebd8672f Mon Sep 17 00:00:00 2001 From: lenemter Date: Sun, 28 Aug 2022 18:41:57 +0900 Subject: [PATCH 32/40] Wallpapers: dont keep aspect ratio, add spacing --- src/Views/Wallpaper.vala | 4 +++- src/Widgets/WallpaperContainer.vala | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 01b75a563..984330049 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -73,8 +73,10 @@ public class PantheonShell.Wallpaper : Gtk.Grid { wallpaper_view = new Gtk.FlowBox () { activate_on_single_click = true, + selection_mode = Gtk.SelectionMode.SINGLE, homogeneous = true, - selection_mode = Gtk.SelectionMode.SINGLE + row_spacing = 18, + column_spacing = 18 }; wallpaper_view.add_css_class (Granite.STYLE_CLASS_VIEW); wallpaper_view.child_activated.connect (update_checked_wallpaper); diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index a320e42c8..e136f9e2e 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -85,7 +85,8 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { construct { image = new Gtk.Picture () { - can_shrink = true + can_shrink = true, + keep_aspect_ratio = false }; card_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { From edf706a174c3e0388be2b974226f1c01184d7f64 Mon Sep 17 00:00:00 2001 From: lenemter Date: Sun, 28 Aug 2022 22:39:16 +0900 Subject: [PATCH 33/40] Clean up wallpapers --- src/Views/Wallpaper.vala | 163 ++++++++++++--------------- src/Widgets/WallpaperContainer.vala | 169 +++++++++++++--------------- 2 files changed, 152 insertions(+), 180 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 984330049..f6e244cfd 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2015-2016 elementary LLC. +/* + * Copyright 2015-2022 elementary, Inc. (https://elementary.io) * * 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 @@ -22,7 +22,7 @@ interface PantheonShell.AccountsServiceUser : Object { public abstract string background_file { owned get; set; } } -public class PantheonShell.Wallpaper : Gtk.Grid { +public class PantheonShell.Wallpaper : Gtk.Box { private const string [] REQUIRED_FILE_ATTRS = { FileAttribute.STANDARD_NAME, FileAttribute.STANDARD_TYPE, @@ -34,9 +34,9 @@ public class PantheonShell.Wallpaper : Gtk.Grid { FileAttribute.THUMBNAIL_IS_VALID }; - private GLib.Settings settings; + private static GLib.Settings settings; - //Instance of the AccountsServices-Interface for this user + // Instance of the AccountsServices-Interface for this user private AccountsServiceUser? accountsservice = null; private Gtk.ScrolledWindow wallpaper_scrolled_window; @@ -45,7 +45,30 @@ public class PantheonShell.Wallpaper : Gtk.Grid { private Gtk.ComboBoxText combo; private Gtk.ColorButton color_button; - private WallpaperContainer active_wallpaper = null; + private WallpaperContainer _active_wallpaper = null; + private WallpaperContainer active_wallpaper { + get { + return _active_wallpaper; + } + set { + if (_active_wallpaper != null) { + _active_wallpaper.checked = false; + } + _active_wallpaper = value; + wallpaper_view.select_child (_active_wallpaper); + _active_wallpaper.checked = true; + + if (_active_wallpaper is SolidColorContainer) { + combo.sensitive = false; + settings.set_string ("primary-color", solid_color.color); + settings.set_string ("picture-options", "none"); + } else { + combo.sensitive = true; + settings.set_string ("picture-options", combo.active_id); + } + } + } + private SolidColorContainer solid_color = null; private WallpaperContainer wallpaper_for_removal = null; @@ -55,13 +78,15 @@ public class PantheonShell.Wallpaper : Gtk.Grid { private bool prevent_update_mode = false; // When restoring the combo state, don't trigger the update. private bool finished; // Shows that we got or wallpapers together - construct { + static construct { settings = new GLib.Settings ("org.gnome.desktop.background"); + } + construct { // DBus connection needed in update_wallpaper for // passing the wallpaper-information to accountsservice. - try { - int uid = (int)Posix.getuid (); + try { + int uid = (int) Posix.getuid (); accountsservice = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.Accounts", "/org/freedesktop/Accounts/User%i".printf (uid)); @@ -79,8 +104,8 @@ public class PantheonShell.Wallpaper : Gtk.Grid { column_spacing = 18 }; wallpaper_view.add_css_class (Granite.STYLE_CLASS_VIEW); - wallpaper_view.child_activated.connect (update_checked_wallpaper); wallpaper_view.set_sort_func (wallpapers_sort_function); + wallpaper_view.child_activated.connect (update_checked_wallpaper); var color = settings.get_string ("primary-color"); create_solid_color_container (color); @@ -120,7 +145,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } color_button = new Gtk.ColorButton () { - margin_start = 0, + margin_start = 6, margin_end = 12, margin_top = 12, margin_bottom = 12, @@ -141,9 +166,10 @@ public class PantheonShell.Wallpaper : Gtk.Grid { actionbar.pack_end (color_button); actionbar.pack_end (combo); - attach (separator, 0, 0); - attach (view_overlay, 0, 1); - attach (actionbar, 0, 2); + orientation = Gtk.Orientation.VERTICAL; + append (separator); + append (view_overlay); + append (actionbar); add_wallpaper_button.clicked.connect (show_wallpaper_chooser); } @@ -153,17 +179,19 @@ public class PantheonShell.Wallpaper : Gtk.Grid { filter.add_mime_type ("image/*"); var chooser = new Gtk.FileChooserNative ( - _("Import Photo"), null, Gtk.FileChooserAction.OPEN, + _("Import Photo !"), + (Gtk.Window) get_root (), + Gtk.FileChooserAction.OPEN, _("Import"), _("Cancel") ) { filter = filter, - select_multiple = true + select_multiple = true, + modal = true }; - chooser.show (); - chooser.response.connect ((id) => { + chooser.destroy (); if (id == Gtk.ResponseType.ACCEPT) { ListModel files = chooser.get_files (); for (var iter = 0; iter < files.get_n_items (); iter++) { @@ -174,12 +202,12 @@ public class PantheonShell.Wallpaper : Gtk.Grid { local_uri = dest.get_uri (); } - add_wallpaper_from_file (file, local_uri); + add_wallpaper_from_file (local_uri); } } }); - chooser.destroy (); + chooser.show (); } private void load_settings () { @@ -230,49 +258,30 @@ public class PantheonShell.Wallpaper : Gtk.Grid { accountsservice.background_file = path; } - private void update_checked_wallpaper (Gtk.FlowBox box, Gtk.FlowBoxChild child) { - var children = (WallpaperContainer) wallpaper_view.get_selected_children ().data; + private void update_checked_wallpaper () { + var selected_child = (WallpaperContainer) wallpaper_view.get_selected_children ().data; - if (!(children is SolidColorContainer)) { - current_wallpaper_path = children.uri; + if (!(selected_child is SolidColorContainer)) { + current_wallpaper_path = selected_child.uri; update_accountsservice (); - - if (active_wallpaper == solid_color) { - combo.sensitive = true; - settings.set_string ("picture-options", combo.get_active_id ()); - } - - } else { - set_combo_disabled_if_necessary (); - settings.set_string ("primary-color", solid_color.color); } // We don't do gradient backgrounds, reset the key that might interfere settings.reset ("color-shading-type"); - children.checked = true; - - if (active_wallpaper != null && active_wallpaper != children) { - active_wallpaper.checked = false; - } - - active_wallpaper = children; + active_wallpaper = selected_child; } private void update_color () { if (finished) { - set_combo_disabled_if_necessary (); - create_solid_color_container (color_button.rgba.to_string ()); - wallpaper_view.append (solid_color); - wallpaper_view.select_child (solid_color); - - if (active_wallpaper != null) { - active_wallpaper.checked = false; + if (active_wallpaper != solid_color) { + combo.sensitive = false; } + create_solid_color_container (color_button.rgba.to_string ()); + wallpaper_view.prepend (solid_color); + active_wallpaper = solid_color; - active_wallpaper.checked = true; - settings.set_string ("primary-color", solid_color.color); } } @@ -289,8 +298,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { for (var iter = 0; iter < children.get_n_items (); iter++) { var container = (WallpaperContainer) children.get_item (iter); if (container.uri == current_wallpaper_path) { - container.checked = true; - wallpaper_view.select_child (container); active_wallpaper = container; break; } @@ -301,13 +308,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } } - private void set_combo_disabled_if_necessary () { - if (active_wallpaper != solid_color) { - combo.sensitive = false; - settings.set_string ("picture-options", "none"); - } - } - public void update_wallpaper_folder () { if (last_cancellable != null) { last_cancellable.cancel (); @@ -360,17 +360,15 @@ public class PantheonShell.Wallpaper : Gtk.Grid { var file = directory.resolve_relative_path (file_info.get_name ()); string uri = file.get_uri (); - add_wallpaper_from_file (file, uri); + add_wallpaper_from_file (uri); } if (toplevel_folder) { create_solid_color_container (color_button.rgba.to_string ()); - wallpaper_view.append (solid_color); + wallpaper_view.prepend (solid_color); finished = true; if (settings.get_string ("picture-options") == "none") { - wallpaper_view.select_child (solid_color); - solid_color.checked = true; active_wallpaper = solid_color; } @@ -389,7 +387,6 @@ public class PantheonShell.Wallpaper : Gtk.Grid { private void create_solid_color_container (string color) { if (solid_color != null) { - wallpaper_view.unselect_child (solid_color); wallpaper_view.remove (solid_color); solid_color.destroy (); } @@ -517,7 +514,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { local_uri = dest.get_uri (); } - add_wallpaper_from_file (file, local_uri); + add_wallpaper_from_file (local_uri); } catch (Error e) { warning (e.message); } @@ -526,36 +523,24 @@ public class PantheonShell.Wallpaper : Gtk.Grid { return true; } - private void add_wallpaper_from_file (GLib.File file, string uri) { + private void add_wallpaper_from_file (string uri) { // don't load 'removed' wallpaper on plug reload if (wallpaper_for_removal != null && wallpaper_for_removal.uri == uri) { return; } - try { - var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), FileQueryInfoFlags.NONE); - var thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); - var thumb_valid = info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID); - var wallpaper = new WallpaperContainer (uri, thumb_path, thumb_valid); - wallpaper_view.append (wallpaper); - - wallpaper.trash.connect (() => { - send_undo_toast (); - mark_for_removal (wallpaper); - }); - - // Select the wallpaper if it is the current wallpaper - if (current_wallpaper_path.has_suffix (uri) && settings.get_string ("picture-options") != "none") { - this.wallpaper_view.select_child (wallpaper); - // Set the widget activated without activating it - wallpaper.checked = true; - active_wallpaper = wallpaper; - } - } catch (Error e) { - critical ("Unable to add wallpaper: %s", e.message); - } + var wallpaper = new WallpaperContainer (uri); + wallpaper_view.prepend (wallpaper); - wallpaper_view.invalidate_sort (); + wallpaper.trash.connect (() => { + send_undo_toast (); + mark_for_removal (wallpaper); + }); + + // Select the wallpaper if it is the current wallpaper + if (current_wallpaper_path == uri && settings.get_string ("picture-options") != "none") { + active_wallpaper = wallpaper; + } } public void cancel_thumbnail_generation () { @@ -651,7 +636,7 @@ public class PantheonShell.Wallpaper : Gtk.Grid { } private void undo_removal () { - wallpaper_view.append (wallpaper_for_removal); + wallpaper_view.prepend (wallpaper_for_removal); wallpaper_for_removal = null; } } diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala index e136f9e2e..6b96f21c8 100644 --- a/src/Widgets/WallpaperContainer.vala +++ b/src/Widgets/WallpaperContainer.vala @@ -27,53 +27,32 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { private static Gtk.CssProvider check_css_provider; private static Gtk.CheckButton check_group; // used for turning CheckButtons into RadioButtons - private Gtk.Box card_box; private Gtk.Popover context_menu; - private Gtk.GestureClick overlay_event_controller; private Gtk.Revealer check_revealer; protected Gtk.Picture image; - public string? thumb_path { get; construct set; } - public bool thumb_valid { get; construct; } public string uri { get; construct; } - public uint64 creation_date { get; construct; default = 0; } - private int scale; + private bool thumb_valid { get; set; default = false; } + private string? thumb_path { get; set; } + public uint64 creation_date { get; set; default = 0; } // in unix time public bool checked { get { - return Gtk.StateFlags.CHECKED in get_state_flags (); + return check_revealer.reveal_child; } set { + check_revealer.reveal_child = value; if (value) { - card_box.set_state_flags (Gtk.StateFlags.CHECKED, false); - check_revealer.reveal_child = true; + set_state_flags (Gtk.StateFlags.CHECKED, false); } else { - card_box.unset_state_flags (Gtk.StateFlags.CHECKED); - check_revealer.reveal_child = false; + unset_state_flags (Gtk.StateFlags.CHECKED); } - - queue_draw (); } } - public bool selected { - get { - return Gtk.StateFlags.SELECTED in get_state_flags (); - } - set { - if (value) { - set_state_flags (Gtk.StateFlags.SELECTED, false); - } else { - unset_state_flags (Gtk.StateFlags.SELECTED); - } - - queue_draw (); - } - } - - public WallpaperContainer (string uri, string? thumb_path, bool thumb_valid) { - Object (uri: uri, thumb_path: thumb_path, thumb_valid: thumb_valid); + public WallpaperContainer (string uri) { + Object (uri: uri); } static construct { @@ -88,13 +67,8 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { can_shrink = true, keep_aspect_ratio = false }; - - card_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - overflow = Gtk.Overflow.HIDDEN - }; - card_box.add_css_class (Granite.STYLE_CLASS_CARD); - card_box.add_css_class (Granite.STYLE_CLASS_ROUNDED); - card_box.append (image); + image.add_css_class (Granite.STYLE_CLASS_CARD); + image.add_css_class (Granite.STYLE_CLASS_ROUNDED); var check = new Gtk.CheckButton () { halign = Gtk.Align.START, @@ -103,9 +77,6 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { active = true, group = check_group }; - check.notify["active"].connect (() => { - check.active = true; - }); check.get_style_context ().add_provider (check_css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER); check_revealer = new Gtk.Revealer () { @@ -114,13 +85,12 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { }; var overlay = new Gtk.Overlay () { - child = card_box, + child = image, halign = Gtk.Align.CENTER }; - overlay.add_overlay (check_revealer); - overlay_event_controller = new Gtk.GestureClick () { + var overlay_event_controller = new Gtk.GestureClick () { button = Gdk.BUTTON_SECONDARY }; overlay.add_controller (overlay_event_controller); @@ -128,32 +98,46 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { add_css_class ("wallpaper-container"); child = overlay; - if (uri != null) { - var move_to_trash = new Gtk.Button.with_label (_("Remove")); - move_to_trash.clicked.connect (() => trash ()); + // Context menu + var move_to_trash = new Gtk.Button.with_label (_("Remove")) { + sensitive = false + }; + + var context_menu_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + context_menu_box.append (move_to_trash); + + context_menu = new Gtk.Popover () { + child = context_menu_box, + autohide = true + }; + context_menu.set_parent (this); + // load file info + if (uri != null) { var file = File.new_for_uri (uri); try { var info = file.query_info ("*", FileQueryInfoFlags.NONE); + load_thumb_info (info); creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED); move_to_trash.sensitive = info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE); } catch (Error e) { critical (e.message); } - - context_menu = new Gtk.Popover () { - child = move_to_trash - }; - context_menu.set_parent (this); } - activate.connect (() => { - checked = true; + // signals + check.notify["active"].connect (() => { + check.active = true; }); - overlay_event_controller.pressed.connect (show_context_menu); + overlay_event_controller.pressed.connect (() => { + context_menu.popup (); + }); + + move_to_trash.clicked.connect (() => trash ()); - scale = get_style_context ().get_scale (); + // load thumb + var scale = get_style_context ().get_scale (); try { if (uri != null) { if (thumb_path != null && thumb_valid) { @@ -162,7 +146,9 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { generate_and_load_thumb (); } } else { - image.set_pixbuf (new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH * scale, THUMB_HEIGHT * scale)); + image.set_pixbuf ( + new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH * scale, THUMB_HEIGHT * scale) + ); } } catch (Error e) { critical ("Failed to load wallpaper thumbnail: %s", e.message); @@ -170,58 +156,59 @@ public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { } } + private void load_thumb_info (FileInfo info) { + thumb_valid = info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID); + thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); + } + private void generate_and_load_thumb () { + var scale = get_style_context ().get_scale (); ThumbnailGenerator.get_default ().get_thumbnail (uri, THUMB_WIDTH * scale, () => { try { var file = File.new_for_uri (uri); - var info = file.query_info (FileAttribute.THUMBNAIL_PATH + "," + FileAttribute.THUMBNAIL_IS_VALID, 0); - thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); + var info = file.query_info ( + string.join (",", FileAttribute.THUMBNAIL_PATH, FileAttribute.THUMBNAIL_IS_VALID), + FileQueryInfoFlags.NONE + ); + load_thumb_info (info); update_thumb.begin (); } catch (Error e) { - warning ("Error loading thumbnail for '%s': %s", uri, e.message); + warning ("Error loading thumbnail for \"%s\": %s", uri, e.message); } }); } - private void load_artist_tooltip () { - if (uri != null) { - string path = ""; - GExiv2.Metadata metadata; - try { - path = Filename.from_uri (uri); - metadata = new GExiv2.Metadata (); - metadata.open_path (path); - } catch (Error e) { - warning ("Error parsing exif metadata of \"%s\": %s", path, e.message); - return; - } - - if (metadata.has_exif ()) { - string? artist_name = null; - try { - artist_name = metadata.try_get_tag_string ("Exif.Image.Artist"); - } catch (Error e) { - warning (e.message); - } - - if (artist_name != null) { - set_tooltip_text (_("Artist: %s").printf (artist_name)); - } - } + private async void update_thumb () { + if (!thumb_valid || thumb_path == null) { + return; } - } - private void show_context_menu (int n_press, double x, double y) { - context_menu.popup (); + image.set_filename (thumb_path); + + load_artist_tooltip (); } - private async void update_thumb () { - if (thumb_path == null) { + private void load_artist_tooltip () { + var metadata = new GExiv2.Metadata (); + try { + var path = Filename.from_uri (uri); + metadata.open_path (path); + } catch (Error e) { + warning ("Error parsing exif metadata of \"%s\": %s", uri, e.message); return; } - image.set_filename (thumb_path); + if (metadata.has_exif ()) { + string? artist_name = null; + try { + artist_name = metadata.try_get_tag_string ("Exif.Image.Artist"); + } catch (Error e) { + warning (e.message); + } - load_artist_tooltip (); + if (artist_name != null) { + set_tooltip_text (_("Artist: %s").printf (artist_name)); + } + } } } From b7c52dad7dac950169e572e99ebbdad24b19c0dd Mon Sep 17 00:00:00 2001 From: lenemter Date: Sun, 28 Aug 2022 22:41:16 +0900 Subject: [PATCH 34/40] Fix FileChooser title --- src/Views/Wallpaper.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index f6e244cfd..357961b71 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -179,7 +179,7 @@ public class PantheonShell.Wallpaper : Gtk.Box { filter.add_mime_type ("image/*"); var chooser = new Gtk.FileChooserNative ( - _("Import Photo !"), + _("Import Photo"), (Gtk.Window) get_root (), Gtk.FileChooserAction.OPEN, _("Import"), From b9a710d15bdc55a852c08c1ac3f080aa4bb1f896 Mon Sep 17 00:00:00 2001 From: lenemter Date: Sun, 4 Sep 2022 00:52:29 +0900 Subject: [PATCH 35/40] Add libadwaita-1-dev to dependencies --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b0681283d..4c3b77be0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y libgranite-7-dev libgtk-4-dev libswitchboard-3-dev libgexiv2-dev meson valac + apt install -y libgranite-7-dev libgtk-4-dev libadwaita-1-dev libswitchboard-3-dev libgexiv2-dev meson valac - name: Build env: DESTDIR: out From a5c734290c181500dac953f71212c8ead3cc2a95 Mon Sep 17 00:00:00 2001 From: lenemter Date: Sat, 10 Sep 2022 00:44:17 +0900 Subject: [PATCH 36/40] Refactor wallpaper view (#335) * Refactor wallpaper view * Remove one blank line * Skeleton XMLContainer class * Add XMLContainer to Potfiles --- po/POTFILES | 6 +- src/IOHelper.vala | 42 --- src/Plug.vala | 2 +- src/Views/Wallpaper.vala | 488 ++++++++++++--------------- src/Widgets/GenericContainer.vala | 123 +++++++ src/Widgets/ImageContainer.vala | 103 ++++++ src/Widgets/SolidColorContainer.vala | 23 +- src/Widgets/UriContainer.vala | 37 ++ src/Widgets/WallpaperContainer.vala | 214 ------------ src/Widgets/XMLContainer.vala | 32 ++ src/meson.build | 6 +- 11 files changed, 537 insertions(+), 539 deletions(-) delete mode 100644 src/IOHelper.vala create mode 100644 src/Widgets/GenericContainer.vala create mode 100644 src/Widgets/ImageContainer.vala create mode 100644 src/Widgets/UriContainer.vala delete mode 100644 src/Widgets/WallpaperContainer.vala create mode 100644 src/Widgets/XMLContainer.vala diff --git a/po/POTFILES b/po/POTFILES index c0b6b5220..e33f42161 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -1,4 +1,3 @@ -src/IOHelper.vala src/Plug.vala src/ThumbnailGenerator.vala src/Translations.vala @@ -7,6 +6,9 @@ src/Views/Dock.vala src/Views/Multitasking.vala src/Views/Text.vala src/Views/Wallpaper.vala +src/Widgets/GenericContainer.vala +src/Widgets/ImageContainer.vala src/Widgets/SolidColorContainer.vala -src/Widgets/WallpaperContainer.vala +src/Widgets/UriContainer.vala +src/Widgets/XMLContainer.vala set-wallpaper-contract/set-wallpaper.vala diff --git a/src/IOHelper.vala b/src/IOHelper.vala deleted file mode 100644 index 6c33e4887..000000000 --- a/src/IOHelper.vala +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * Copyright (c) 2017-2018 elementary LLC. - * - * 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 - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -public class PantheonShell.IOHelper : GLib.Object { - private const string[] ACCEPTED_TYPES = { - "image/jpeg", - "image/png", - "image/tiff", - "image/svg+xml", - "image/gif" - }; - - // Check if the filename has a picture file extension. - public static bool is_valid_file_type (GLib.FileInfo file_info) { - // Check for correct file type, don't try to load directories and such - if (file_info.get_file_type () != GLib.FileType.REGULAR) { - return false; - } - - foreach (var type in ACCEPTED_TYPES) { - if (GLib.ContentType.equals (file_info.get_content_type (), type)) { - return true; - } - } - - return false; - } -} diff --git a/src/Plug.vala b/src/Plug.vala index b0a244ac2..cce3b9ea5 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -99,7 +99,7 @@ public class PantheonShell.Plug : Switchboard.Plug { } public override void shown () { - wallpaper_view.update_wallpaper_folder (); + wallpaper_view.load_wallpapers (); } public override void hidden () { diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 357961b71..41b36eb41 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -34,10 +34,18 @@ public class PantheonShell.Wallpaper : Gtk.Box { FileAttribute.THUMBNAIL_IS_VALID }; + private const string [] ALLOWED_MIMETYPES = { + "image/jpeg", + "image/png", + "image/tiff", + "image/svg+xml", + "image/gif" + }; + private static GLib.Settings settings; // Instance of the AccountsServices-Interface for this user - private AccountsServiceUser? accountsservice = null; + private static AccountsServiceUser? accountsservice = null; private Gtk.ScrolledWindow wallpaper_scrolled_window; private Gtk.FlowBox wallpaper_view; @@ -45,57 +53,35 @@ public class PantheonShell.Wallpaper : Gtk.Box { private Gtk.ComboBoxText combo; private Gtk.ColorButton color_button; - private WallpaperContainer _active_wallpaper = null; - private WallpaperContainer active_wallpaper { - get { - return _active_wallpaper; - } - set { - if (_active_wallpaper != null) { - _active_wallpaper.checked = false; - } - _active_wallpaper = value; - wallpaper_view.select_child (_active_wallpaper); - _active_wallpaper.checked = true; - - if (_active_wallpaper is SolidColorContainer) { - combo.sensitive = false; - settings.set_string ("primary-color", solid_color.color); - settings.set_string ("picture-options", "none"); - } else { - combo.sensitive = true; - settings.set_string ("picture-options", combo.active_id); - } - } - } + private GenericContainer? previous_wallpaper { get; set; default = null; } private SolidColorContainer solid_color = null; - private WallpaperContainer wallpaper_for_removal = null; + private UriContainer? wallpaper_for_removal = null; private Cancellable last_cancellable; - private string current_wallpaper_path; - private bool prevent_update_mode = false; // When restoring the combo state, don't trigger the update. - private bool finished; // Shows that we got or wallpapers together - static construct { settings = new GLib.Settings ("org.gnome.desktop.background"); - } - construct { // DBus connection needed in update_wallpaper for // passing the wallpaper-information to accountsservice. try { int uid = (int) Posix.getuid (); - accountsservice = Bus.get_proxy_sync (BusType.SYSTEM, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts/User%i".printf (uid)); - } catch (Error e) { + accountsservice = Bus.get_proxy_sync ( + BusType.SYSTEM, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts/User%i".printf (uid) + ); + } catch (IOError e) { warning (e.message); } + } + construct { var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); + var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY); + wallpaper_view = new Gtk.FlowBox () { activate_on_single_click = true, selection_mode = Gtk.SelectionMode.SINGLE, @@ -105,14 +91,7 @@ public class PantheonShell.Wallpaper : Gtk.Box { }; wallpaper_view.add_css_class (Granite.STYLE_CLASS_VIEW); wallpaper_view.set_sort_func (wallpapers_sort_function); - wallpaper_view.child_activated.connect (update_checked_wallpaper); - - var color = settings.get_string ("primary-color"); - create_solid_color_container (color); - - var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY); wallpaper_view.add_controller (drop_target); - drop_target.on_drop.connect (on_drag_data_received); wallpaper_scrolled_window = new Gtk.ScrolledWindow () { hexpand = true, @@ -124,7 +103,7 @@ public class PantheonShell.Wallpaper : Gtk.Box { child = wallpaper_scrolled_window }; - var add_wallpaper_button = new Gtk.Button.with_label (_("Import Photo…")) { + var import_button = new Gtk.Button.with_label (_("Import Photo…")) { margin_start = 12, margin_end = 12, margin_top = 12, @@ -137,32 +116,22 @@ public class PantheonShell.Wallpaper : Gtk.Box { combo.append ("centered", _("Centered")); combo.append ("zoom", _("Zoom")); combo.append ("spanned", _("Spanned")); - combo.changed.connect (update_mode); - - Gdk.RGBA rgba_color = {}; - if (!rgba_color.parse (color)) { - rgba_color = { 1, 1, 1, 1 }; - } color_button = new Gtk.ColorButton () { margin_start = 6, margin_end = 12, margin_top = 12, - margin_bottom = 12, - rgba = rgba_color + margin_bottom = 12 }; - color_button.color_set.connect (update_color); var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); - size_group.add_widget (add_wallpaper_button); + size_group.add_widget (import_button); size_group.add_widget (combo); size_group.add_widget (color_button); - load_settings (); - var actionbar = new Gtk.ActionBar (); actionbar.add_css_class ("inline-toolbar"); - actionbar.pack_start (add_wallpaper_button); + actionbar.pack_start (import_button); actionbar.pack_end (color_button); actionbar.pack_end (combo); @@ -171,12 +140,48 @@ public class PantheonShell.Wallpaper : Gtk.Box { append (view_overlay); append (actionbar); - add_wallpaper_button.clicked.connect (show_wallpaper_chooser); + load_settings (); + + // connect signals + drop_target.on_drop.connect (on_drag_data_received); + wallpaper_view.child_activated.connect (update_checked_wallpaper); + import_button.clicked.connect (show_wallpaper_chooser); + combo.changed.connect (() => { + settings.set_string ("picture-options", combo.get_active_id ()); + }); + color_button.color_set.connect (() => { + settings.set_string ("primary-color", color_button.rgba.to_string ()); + wallpaper_view.child_activated (solid_color); + }); + } + + private void load_settings () { + // TODO: need to store the previous state, before changing to none + // when a solid color is selected, because the combobox doesn't know + // about it anymore. The previous state should be loaded instead here. + + var picture_options = settings.get_string ("picture-options"); + if (picture_options == "none") { + combo.sensitive = false; + picture_options = "zoom"; + } + + combo.active_id = picture_options; + + // load color button + var color = settings.get_string ("primary-color"); + Gdk.RGBA rgba_color = {}; + if (!rgba_color.parse (color)) { + rgba_color = { 1, 1, 1, 1 }; + } + color_button.rgba = rgba_color; } private void show_wallpaper_chooser () { var filter = new Gtk.FileFilter (); - filter.add_mime_type ("image/*"); + foreach (var type in ALLOWED_MIMETYPES) { + filter.add_mime_type (type); + } var chooser = new Gtk.FileChooserNative ( _("Import Photo"), @@ -193,16 +198,16 @@ public class PantheonShell.Wallpaper : Gtk.Box { chooser.response.connect ((id) => { chooser.destroy (); if (id == Gtk.ResponseType.ACCEPT) { - ListModel files = chooser.get_files (); + var files = chooser.get_files (); for (var iter = 0; iter < files.get_n_items (); iter++) { var file = (File) files.get_item (iter); - string local_uri = file.get_uri (); + var local_uri = file.get_uri (); var dest = copy_for_library (file); if (dest != null) { local_uri = dest.get_uri (); } - add_wallpaper_from_file (local_uri); + add_wallpaper_from_uri (local_uri); } } }); @@ -210,105 +215,79 @@ public class PantheonShell.Wallpaper : Gtk.Box { chooser.show (); } - private void load_settings () { - // TODO: need to store the previous state, before changing to none - // when a solid color is selected, because the combobox doesn't know - // about it anymore. The previous state should be loaded instead here. - string picture_options = settings.get_string ("picture-options"); - if (picture_options == "none") { - combo.sensitive = false; - picture_options = "zoom"; + private void update_checked_wallpaper (Gtk.FlowBoxChild _selected_child) { + // We don't do gradient backgrounds, reset the key that might interfere + settings.reset ("color-shading-type"); + + if (previous_wallpaper != null) { + previous_wallpaper.checked = false; } - prevent_update_mode = true; - combo.active_id = picture_options; + var selected_child = (GenericContainer) _selected_child; + previous_wallpaper = selected_child; - current_wallpaper_path = settings.get_string ("picture-uri"); + selected_child.checked = true; + + if (selected_child is SolidColorContainer) { + combo.sensitive = false; + + settings.set_string ("picture-options", "none"); + } else if (selected_child is UriContainer) { + combo.sensitive = true; + + settings.set_string ("picture-uri", ((UriContainer) selected_child).uri); + settings.set_string ("picture-options", combo.active_id); + update_accountsservice (); + } } /* * This integrates with LightDM */ - private void update_accountsservice () { - var file = File.new_for_uri (current_wallpaper_path); - string uri = file.get_uri (); - string path = file.get_path (); - - bool path_has_prefix_bg_dir = false; - foreach (unowned string directory in get_bg_directories ()) { - if (path.has_prefix (directory)) { - path_has_prefix_bg_dir = true; - break; - } - } - - if (!path_has_prefix_bg_dir) { - var local_file = copy_for_library (file); - if (local_file != null) { - uri = local_file.get_uri (); - } - } + private void update_accountsservice () { + var file = File.new_for_uri (settings.get_string ("picture-uri")); + var path = file.get_path (); var greeter_file = copy_for_greeter (file); if (greeter_file != null) { path = greeter_file.get_path (); } - settings.set_string ("picture-uri", uri); accountsservice.background_file = path; } - private void update_checked_wallpaper () { - var selected_child = (WallpaperContainer) wallpaper_view.get_selected_children ().data; - - if (!(selected_child is SolidColorContainer)) { - current_wallpaper_path = selected_child.uri; - update_accountsservice (); - } - - // We don't do gradient backgrounds, reset the key that might interfere - settings.reset ("color-shading-type"); - - active_wallpaper = selected_child; - } - - private void update_color () { - if (finished) { - if (active_wallpaper != solid_color) { - combo.sensitive = false; - } - - create_solid_color_container (color_button.rgba.to_string ()); - wallpaper_view.prepend (solid_color); - - active_wallpaper = solid_color; - } - } - - private void update_mode () { - if (!prevent_update_mode) { - settings.set_string ("picture-options", combo.get_active_id ()); + public void load_wallpapers () { + clean_wallpapers (); - // Changing the mode, while a solid color is selected, change focus to the - // wallpaper tile. - if (active_wallpaper == solid_color) { - active_wallpaper.checked = false; + load_wallpapers_from_folders.begin ((obj, res) => { + solid_color = new SolidColorContainer (); + wallpaper_view.append (solid_color); + // Select current wallpaper + if (settings.get_string ("picture-options") == "none") { + wallpaper_view.child_activated (solid_color); + } else { var children = wallpaper_view.observe_children (); - for (var iter = 0; iter < children.get_n_items (); iter++) { - var container = (WallpaperContainer) children.get_item (iter); - if (container.uri == current_wallpaper_path) { - active_wallpaper = container; - break; + for (var i = 0; i < children.get_n_items (); i++) { + var child = (GenericContainer) children.get_item (i); + if (child is UriContainer && settings.get_string ("picture-uri") == ((UriContainer) child).uri) { + wallpaper_view.child_activated (child); } } } - } else { - prevent_update_mode = false; + }); + } + + private void clean_wallpapers () { + var child = wallpaper_view.get_first_child (); + while (child != null) { + wallpaper_view.remove (child); + child.destroy (); + child = wallpaper_view.get_first_child (); } } - public void update_wallpaper_folder () { + private async void load_wallpapers_from_folders () { if (last_cancellable != null) { last_cancellable.cancel (); } @@ -316,29 +295,26 @@ public class PantheonShell.Wallpaper : Gtk.Box { var cancellable = new Cancellable (); last_cancellable = cancellable; - clean_wallpapers (); - foreach (unowned string directory in get_bg_directories ()) { - load_wallpapers.begin (directory, cancellable); + yield load_wallpapers_from_folder (directory); } } - private async void load_wallpapers (string basefolder, Cancellable cancellable, bool toplevel_folder = true) { - if (cancellable.is_cancelled ()) { + private async void load_wallpapers_from_folder (string folder) { + if (last_cancellable.is_cancelled ()) { return; } - var directory = File.new_for_path (basefolder); - + var directory = File.new_for_path (folder); try { // Enumerator object that will let us read through the wallpapers asynchronously var attrs = string.joinv (",", REQUIRED_FILE_ATTRS); - var e = yield directory.enumerate_children_async (attrs, 0, Priority.DEFAULT); - FileInfo file_info; + var e = yield directory.enumerate_children_async (attrs, FileQueryInfoFlags.NONE, Priority.DEFAULT); + FileInfo? file_info = null; // Loop through and add each wallpaper in the batch while ((file_info = e.next_file ()) != null) { - if (cancellable.is_cancelled ()) { + if (last_cancellable.is_cancelled ()) { ThumbnailGenerator.get_default ().dequeue_all (); return; } @@ -350,69 +326,30 @@ public class PantheonShell.Wallpaper : Gtk.Box { if (file_info.get_file_type () == FileType.DIRECTORY) { // Spawn off another loader for the subdirectory var subdir = directory.resolve_relative_path (file_info.get_name ()); - yield load_wallpapers (subdir.get_path (), cancellable, false); - continue; - } else if (!IOHelper.is_valid_file_type (file_info)) { - // Skip non-picture files + yield load_wallpapers_from_folder (subdir.get_path ()); continue; } var file = directory.resolve_relative_path (file_info.get_name ()); - string uri = file.get_uri (); - - add_wallpaper_from_file (uri); - } - - if (toplevel_folder) { - create_solid_color_container (color_button.rgba.to_string ()); - wallpaper_view.prepend (solid_color); - finished = true; + var uri = file.get_uri (); - if (settings.get_string ("picture-options") == "none") { - active_wallpaper = solid_color; - } - - if (active_wallpaper != null) { - Gtk.Allocation alloc; - active_wallpaper.get_allocation (out alloc); - wallpaper_scrolled_window.get_vadjustment ().value = alloc.y; - } + add_wallpaper_from_uri (uri); } - } catch (Error err) { - if (!(err is IOError.NOT_FOUND)) { - warning (err.message); + } catch (Error e) { + if (!(e is IOError.NOT_FOUND)) { + warning (e.message); } } } - private void create_solid_color_container (string color) { - if (solid_color != null) { - wallpaper_view.remove (solid_color); - solid_color.destroy (); - } - - solid_color = new SolidColorContainer (color); - } - - private void clean_wallpapers () { - var child = wallpaper_view.get_first_child (); - while (child != null) { - wallpaper_view.remove (child); - child.destroy (); - child = wallpaper_view.get_first_child (); - } - - solid_color = null; - } - private static string get_local_bg_directory () { - return Path.build_filename (Environment.get_user_data_dir (), "backgrounds") + "/"; + return Path.build_filename (Environment.get_user_data_dir (), "backgrounds"); } private static string[] get_system_bg_directories () { string[] directories = {}; foreach (unowned string data_dir in Environment.get_system_data_dirs ()) { - var system_background_dir = Path.build_filename (data_dir, "backgrounds") + "/"; + var system_background_dir = Path.build_filename (data_dir, "backgrounds"); if (FileUtils.test (system_background_dir, FileTest.EXISTS)) { debug ("Found system background directory: %s", system_background_dir); directories += system_background_dir; @@ -442,10 +379,9 @@ public class PantheonShell.Wallpaper : Gtk.Box { private static File? copy_for_library (File source) { File? dest = null; - string local_bg_directory = get_local_bg_directory (); + var local_bg_directory = get_local_bg_directory (); try { - File folder = File.new_for_path (local_bg_directory); - folder.make_directory_with_parents (); + File.new_for_path (local_bg_directory).make_directory_with_parents (); } catch (Error e) { if (e is GLib.IOError.EXISTS) { debug ("Local background directory already exists"); @@ -469,6 +405,7 @@ public class PantheonShell.Wallpaper : Gtk.Box { private static File? copy_for_greeter (File source) { File? dest = null; + try { string greeter_data_dir = Path.build_filename (Environment.get_variable ("XDG_GREETER_DATA_DIR"), "wallpaper"); if (greeter_data_dir == "") { @@ -498,96 +435,65 @@ public class PantheonShell.Wallpaper : Gtk.Box { return dest; } - private bool on_drag_data_received (Gtk.DropTarget controller, Value val, double x, double y) { + private bool on_drag_data_received (Value val, double x, double y) { var file_list = (Gdk.FileList) val; foreach (var file in file_list.get_files ()) { - try { - var info = file.query_info (string.joinv (",", REQUIRED_FILE_ATTRS), FileQueryInfoFlags.NONE); - - if (!IOHelper.is_valid_file_type (info)) { - continue; - } - - string local_uri = file.get_uri (); - var dest = copy_for_library (file); - if (dest != null) { - local_uri = dest.get_uri (); - } - - add_wallpaper_from_file (local_uri); - } catch (Error e) { - warning (e.message); + var local_uri = file.get_uri (); + var dest = copy_for_library (file); + if (dest != null) { + local_uri = dest.get_uri (); } + + add_wallpaper_from_uri (local_uri); } return true; } - private void add_wallpaper_from_file (string uri) { - // don't load 'removed' wallpaper on plug reload - if (wallpaper_for_removal != null && wallpaper_for_removal.uri == uri) { + private void add_wallpaper_from_uri (string uri) { + var file = File.new_for_uri (uri); + + string? mime_type; + try { + var file_info = file.query_info (FileAttribute.STANDARD_CONTENT_TYPE, FileQueryInfoFlags.NONE, null); + mime_type = file_info.get_content_type ().to_ascii (); + } catch (Error e) { + warning ("Could not get mime type for file \"%s\": %s", uri, e.message); return; } - var wallpaper = new WallpaperContainer (uri); - wallpaper_view.prepend (wallpaper); - - wallpaper.trash.connect (() => { - send_undo_toast (); - mark_for_removal (wallpaper); - }); - - // Select the wallpaper if it is the current wallpaper - if (current_wallpaper_path == uri && settings.get_string ("picture-options") != "none") { - active_wallpaper = wallpaper; + if (!(mime_type in ALLOWED_MIMETYPES)) { + warning ("File with not allowed mimetype: %s, %s", uri, mime_type); + return; } - } - public void cancel_thumbnail_generation () { - if (last_cancellable != null) { - last_cancellable.cancel (); + // don't load 'removed' wallpaper on plug reload + if (wallpaper_for_removal != null && wallpaper_for_removal.uri == uri) { + return; } - } - private int wallpapers_sort_function (Gtk.FlowBoxChild _child1, Gtk.FlowBoxChild _child2) { - var child1 = (WallpaperContainer) _child1; - var child2 = (WallpaperContainer) _child2; - var uri1 = child1.uri; - var uri2 = child2.uri; + UriContainer wallpaper; + if (mime_type.has_prefix ("image/")) { + wallpaper = new ImageContainer (uri); - if (uri1 == null || uri2 == null) { - return 0; - } + // TODO: https://github.com/elementary/switchboard-plug-pantheon-shell/issues/296 + // } else if (mime_type == "application/xml") { + // wallpaper = new XMLContainer (uri); + // ... - var uri1_is_system = false; - var uri2_is_system = false; - foreach (var bg_dir in get_system_bg_directories ()) { - bg_dir = "file://" + bg_dir; - uri1_is_system = uri1.has_prefix (bg_dir) || uri1_is_system; - uri2_is_system = uri2.has_prefix (bg_dir) || uri2_is_system; - } - - // Sort system wallpapers last - if (uri1_is_system && !uri2_is_system) { - return 1; - } else if (!uri1_is_system && uri2_is_system) { - return -1; + } else { + // Fixes Use of possibly unassigned local variable `wallpaper' + // However, the file should never get here since it's been filtered before + warning ("Filtered file %s of unknown type %s", uri, mime_type); + return; } - var child1_date = child1.creation_date; - var child2_date = child2.creation_date; - - // sort by filename if creation dates are equal - if (child1_date == child2_date) { - return uri1.collate (uri2); - } + wallpaper_view.append (wallpaper); - // sort recently added first - if (child1_date >= child2_date) { - return -1; - } else { - return 1; - } + wallpaper.trash.connect (() => { + send_undo_toast (); + mark_for_removal (wallpaper); + }); } private void send_undo_toast () { @@ -623,7 +529,7 @@ public class PantheonShell.Wallpaper : Gtk.Box { toast.send_notification (); } - private void mark_for_removal (WallpaperContainer wallpaper) { + private void mark_for_removal (UriContainer wallpaper) { wallpaper_view.remove (wallpaper); wallpaper_for_removal = wallpaper; } @@ -636,7 +542,57 @@ public class PantheonShell.Wallpaper : Gtk.Box { } private void undo_removal () { - wallpaper_view.prepend (wallpaper_for_removal); + wallpaper_view.append (wallpaper_for_removal); wallpaper_for_removal = null; } + + private int wallpapers_sort_function (Gtk.FlowBoxChild _child1, Gtk.FlowBoxChild _child2) { + var child1 = (GenericContainer) _child1; + var child2 = (GenericContainer) _child2; + + if (child1 is SolidColorContainer) { + return 1; + } else if (child2 is SolidColorContainer) { + return -1; + } + + var uri1 = ((UriContainer) child1).uri; + var uri2 = ((UriContainer) child2).uri; + + var uri1_is_system = false; + var uri2_is_system = false; + foreach (var bg_dir in get_system_bg_directories ()) { + bg_dir = "file://" + bg_dir; + uri1_is_system = uri1.has_prefix (bg_dir) || uri1_is_system; + uri2_is_system = uri2.has_prefix (bg_dir) || uri2_is_system; + } + + // Sort system wallpapers last + if (uri1_is_system && !uri2_is_system) { + return 1; + } else if (!uri1_is_system && uri2_is_system) { + return -1; + } + + var child1_date = ((UriContainer) child1).creation_date; + var child2_date = ((UriContainer) child2).creation_date; + + // sort by filename if creation dates are equal + if (child1_date == child2_date) { + return uri1.collate (uri2); + } + + // sort recently added first + if (child1_date >= child2_date) { + return -1; + } else { + return 1; + } + } + + public void cancel_thumbnail_generation () { + if (last_cancellable != null) { + last_cancellable.cancel (); + } + } } diff --git a/src/Widgets/GenericContainer.vala b/src/Widgets/GenericContainer.vala new file mode 100644 index 000000000..3a3f6625f --- /dev/null +++ b/src/Widgets/GenericContainer.vala @@ -0,0 +1,123 @@ +/*- + * Copyright 2022 elementary, Inc. (https://elementary.io) + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authored by: Erasmo Marín + * + */ + +public class PantheonShell.GenericContainer : Gtk.FlowBoxChild { + public signal void trash (); + + protected const int THUMB_WIDTH = 162; + protected const int THUMB_HEIGHT = 100; + + private static Gtk.CssProvider check_css_provider; + private static Gtk.CheckButton check_group; // used for turning CheckButtons into RadioButtons + + protected Gtk.Box card_box; + protected Gtk.Picture image; + private Gtk.Revealer check_revealer; + protected Gtk.Overlay overlay; + protected Gtk.Box context_menu_box; + protected Gtk.Popover context_menu; + protected Gtk.Button move_to_trash; + + public bool checked { + get { + return check_revealer.reveal_child; + } + set { + check_revealer.reveal_child = value; + if (value) { + card_box.set_state_flags (Gtk.StateFlags.CHECKED, false); + } else { + card_box.unset_state_flags (Gtk.StateFlags.CHECKED); + } + } + } + + static construct { + check_css_provider = new Gtk.CssProvider (); + check_css_provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/Check.css"); + + check_group = new Gtk.CheckButton (); + } + + construct { + image = new Gtk.Picture () { + can_shrink = true, + keep_aspect_ratio = false + }; + + card_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); + card_box.append (image); + card_box.add_css_class (Granite.STYLE_CLASS_CARD); + card_box.add_css_class (Granite.STYLE_CLASS_ROUNDED); + + var check = new Gtk.CheckButton () { + halign = Gtk.Align.START, + valign = Gtk.Align.START, + focusable = false, + active = true, + group = check_group + }; + check.get_style_context ().add_provider (check_css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER); + + check_revealer = new Gtk.Revealer () { + transition_type = Gtk.RevealerTransitionType.CROSSFADE, + child = check + }; + + overlay = new Gtk.Overlay () { + child = card_box, + halign = Gtk.Align.CENTER + }; + overlay.add_overlay (check_revealer); + + var overlay_event_controller = new Gtk.GestureClick () { + button = Gdk.BUTTON_SECONDARY + }; + overlay.add_controller (overlay_event_controller); + + add_css_class ("wallpaper-container"); + child = overlay; + + // Context menu + move_to_trash = new Gtk.Button.with_label (_("Remove")) { + sensitive = false + }; + + context_menu_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + context_menu_box.append (move_to_trash); + + context_menu = new Gtk.Popover () { + child = context_menu_box, + autohide = true + }; + context_menu.set_parent (this); + + // signals + check.notify["active"].connect (() => { + check.active = true; + }); + + overlay_event_controller.pressed.connect (() => { + context_menu.popup (); + }); + + move_to_trash.clicked.connect (() => trash ()); + } +} diff --git a/src/Widgets/ImageContainer.vala b/src/Widgets/ImageContainer.vala new file mode 100644 index 000000000..a3d4e3071 --- /dev/null +++ b/src/Widgets/ImageContainer.vala @@ -0,0 +1,103 @@ +/*- + * Copyright 2015-2022 elementary, Inc. (https://elementary.io) + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authored by: Erasmo Marín + * + */ + +public class PantheonShell.ImageContainer : UriContainer { + private bool thumb_valid { get; set; default = false; } + private string? thumb_path { get; set; default = null; } + + public ImageContainer (string uri) { + Object (uri: uri); + } + + construct { + // load file info + var file = File.new_for_uri (uri); + try { + var info = file.query_info ("*", FileQueryInfoFlags.NONE); + load_thumb_info (info); + move_to_trash.sensitive = info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE); + } catch (Error e) { + critical (e.message); + } + + // load thumb + if (thumb_valid && thumb_path != null) { + update_thumb.begin (); + } else { + generate_and_load_thumb (); + } + } + + private void load_thumb_info (FileInfo info) { + thumb_valid = info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID); + thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); + } + + private async void update_thumb () { + if (!thumb_valid || thumb_path == null) { + return; + } + + image.set_filename (thumb_path); + + load_artist_tooltip (); + } + + private void generate_and_load_thumb () { + var scale = get_style_context ().get_scale (); + ThumbnailGenerator.get_default ().get_thumbnail (uri, THUMB_WIDTH * scale, () => { + try { + var file = File.new_for_uri (uri); + var info = file.query_info ( + string.join (",", FileAttribute.THUMBNAIL_PATH, FileAttribute.THUMBNAIL_IS_VALID), + FileQueryInfoFlags.NONE + ); + load_thumb_info (info); + update_thumb.begin (); + } catch (Error e) { + warning ("Error loading thumbnail for \"%s\": %s", uri, e.message); + } + }); + } + + private void load_artist_tooltip () { + var metadata = new GExiv2.Metadata (); + try { + var path = Filename.from_uri (uri); + metadata.open_path (path); + } catch (Error e) { + warning ("Error parsing exif metadata of \"%s\": %s", uri, e.message); + return; + } + + if (metadata.has_exif ()) { + string? artist_name = null; + try { + artist_name = metadata.try_get_tag_string ("Exif.Image.Artist"); + } catch (Error e) { + warning (e.message); + } + + if (artist_name != null) { + set_tooltip_text (_("Artist: %s").printf (artist_name)); + } + } + } +} diff --git a/src/Widgets/SolidColorContainer.vala b/src/Widgets/SolidColorContainer.vala index a9151f28c..8f62884ca 100644 --- a/src/Widgets/SolidColorContainer.vala +++ b/src/Widgets/SolidColorContainer.vala @@ -18,22 +18,21 @@ * */ -public class PantheonShell.SolidColorContainer : WallpaperContainer { - public string color { get; construct; } - private Gdk.RGBA rgba { - get { - Gdk.RGBA rgba = {}; - rgba.parse (color); - - return rgba; - } - } +public class PantheonShell.SolidColorContainer : GenericContainer { + private static GLib.Settings settings; - public SolidColorContainer (string color_value) { - Object (color: color_value); + static construct { + settings = new GLib.Settings ("org.gnome.desktop.background"); } construct { + fill_thumb (); + settings.changed["primary-color"].connect (fill_thumb); + } + + private void fill_thumb () { + Gdk.RGBA rgba = {}; + rgba.parse (settings.get_string ("primary-color")); var thumb = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH, THUMB_HEIGHT); thumb.fill (rgba_to_pixel (rgba)); image.set_pixbuf (thumb); diff --git a/src/Widgets/UriContainer.vala b/src/Widgets/UriContainer.vala new file mode 100644 index 000000000..bef45e6ee --- /dev/null +++ b/src/Widgets/UriContainer.vala @@ -0,0 +1,37 @@ +/*- + * Copyright 2022 elementary, Inc. (https://elementary.io) + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +public class PantheonShell.UriContainer : GenericContainer { + public string uri { get; construct; } + + public uint64 creation_date { get; set; default = 0; } // in unix time + + public UriContainer (string uri) { + Object (uri: uri); + } + + construct { + var file = File.new_for_uri (uri); + try { + var info = file.query_info (FileAttribute.TIME_CREATED, FileQueryInfoFlags.NONE); + creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED); + } catch (Error e) { + critical (e.message); + } + } +} diff --git a/src/Widgets/WallpaperContainer.vala b/src/Widgets/WallpaperContainer.vala deleted file mode 100644 index 6b96f21c8..000000000 --- a/src/Widgets/WallpaperContainer.vala +++ /dev/null @@ -1,214 +0,0 @@ -/*- - * Copyright 2015-2022 elementary, Inc. (https://elementary.io) - * - * 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 - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Authored by: Erasmo Marín - * - */ - -public class PantheonShell.WallpaperContainer : Gtk.FlowBoxChild { - public signal void trash (); - - protected const int THUMB_WIDTH = 162; - protected const int THUMB_HEIGHT = 100; - - private static Gtk.CssProvider check_css_provider; - private static Gtk.CheckButton check_group; // used for turning CheckButtons into RadioButtons - - private Gtk.Popover context_menu; - private Gtk.Revealer check_revealer; - protected Gtk.Picture image; - - public string uri { get; construct; } - - private bool thumb_valid { get; set; default = false; } - private string? thumb_path { get; set; } - public uint64 creation_date { get; set; default = 0; } // in unix time - - public bool checked { - get { - return check_revealer.reveal_child; - } - set { - check_revealer.reveal_child = value; - if (value) { - set_state_flags (Gtk.StateFlags.CHECKED, false); - } else { - unset_state_flags (Gtk.StateFlags.CHECKED); - } - } - } - - public WallpaperContainer (string uri) { - Object (uri: uri); - } - - static construct { - check_css_provider = new Gtk.CssProvider (); - check_css_provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/Check.css"); - - check_group = new Gtk.CheckButton (); - } - - construct { - image = new Gtk.Picture () { - can_shrink = true, - keep_aspect_ratio = false - }; - image.add_css_class (Granite.STYLE_CLASS_CARD); - image.add_css_class (Granite.STYLE_CLASS_ROUNDED); - - var check = new Gtk.CheckButton () { - halign = Gtk.Align.START, - valign = Gtk.Align.START, - focusable = false, - active = true, - group = check_group - }; - check.get_style_context ().add_provider (check_css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER); - - check_revealer = new Gtk.Revealer () { - transition_type = Gtk.RevealerTransitionType.CROSSFADE, - child = check - }; - - var overlay = new Gtk.Overlay () { - child = image, - halign = Gtk.Align.CENTER - }; - overlay.add_overlay (check_revealer); - - var overlay_event_controller = new Gtk.GestureClick () { - button = Gdk.BUTTON_SECONDARY - }; - overlay.add_controller (overlay_event_controller); - - add_css_class ("wallpaper-container"); - child = overlay; - - // Context menu - var move_to_trash = new Gtk.Button.with_label (_("Remove")) { - sensitive = false - }; - - var context_menu_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - context_menu_box.append (move_to_trash); - - context_menu = new Gtk.Popover () { - child = context_menu_box, - autohide = true - }; - context_menu.set_parent (this); - - // load file info - if (uri != null) { - var file = File.new_for_uri (uri); - try { - var info = file.query_info ("*", FileQueryInfoFlags.NONE); - load_thumb_info (info); - creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED); - move_to_trash.sensitive = info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE); - } catch (Error e) { - critical (e.message); - } - } - - // signals - check.notify["active"].connect (() => { - check.active = true; - }); - - overlay_event_controller.pressed.connect (() => { - context_menu.popup (); - }); - - move_to_trash.clicked.connect (() => trash ()); - - // load thumb - var scale = get_style_context ().get_scale (); - try { - if (uri != null) { - if (thumb_path != null && thumb_valid) { - update_thumb.begin (); - } else { - generate_and_load_thumb (); - } - } else { - image.set_pixbuf ( - new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, THUMB_WIDTH * scale, THUMB_HEIGHT * scale) - ); - } - } catch (Error e) { - critical ("Failed to load wallpaper thumbnail: %s", e.message); - return; - } - } - - private void load_thumb_info (FileInfo info) { - thumb_valid = info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID); - thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH); - } - - private void generate_and_load_thumb () { - var scale = get_style_context ().get_scale (); - ThumbnailGenerator.get_default ().get_thumbnail (uri, THUMB_WIDTH * scale, () => { - try { - var file = File.new_for_uri (uri); - var info = file.query_info ( - string.join (",", FileAttribute.THUMBNAIL_PATH, FileAttribute.THUMBNAIL_IS_VALID), - FileQueryInfoFlags.NONE - ); - load_thumb_info (info); - update_thumb.begin (); - } catch (Error e) { - warning ("Error loading thumbnail for \"%s\": %s", uri, e.message); - } - }); - } - - private async void update_thumb () { - if (!thumb_valid || thumb_path == null) { - return; - } - - image.set_filename (thumb_path); - - load_artist_tooltip (); - } - - private void load_artist_tooltip () { - var metadata = new GExiv2.Metadata (); - try { - var path = Filename.from_uri (uri); - metadata.open_path (path); - } catch (Error e) { - warning ("Error parsing exif metadata of \"%s\": %s", uri, e.message); - return; - } - - if (metadata.has_exif ()) { - string? artist_name = null; - try { - artist_name = metadata.try_get_tag_string ("Exif.Image.Artist"); - } catch (Error e) { - warning (e.message); - } - - if (artist_name != null) { - set_tooltip_text (_("Artist: %s").printf (artist_name)); - } - } - } -} diff --git a/src/Widgets/XMLContainer.vala b/src/Widgets/XMLContainer.vala new file mode 100644 index 000000000..9fffef156 --- /dev/null +++ b/src/Widgets/XMLContainer.vala @@ -0,0 +1,32 @@ +/*- + * Copyright 2022 elementary, Inc. (https://elementary.io) + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +public class PantheonShell.XMLContainer : UriContainer { + public XMLContainer (string uri) { + Object (uri: uri); + } + + construct { + // FIXME: https://github.com/elementary/switchboard-plug-pantheon-shell/issues/296 + // parse_file (); + // create_collage (); + // create_overlay_icon (); + // add_tooltip (); + // ... + } +} diff --git a/src/meson.build b/src/meson.build index a13bf841d..26e5055ec 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,4 @@ plug_files = files( - 'IOHelper.vala', 'PantheonAccountsServicePlugin.vala', 'Plug.vala', 'ThumbnailGenerator.vala', @@ -8,8 +7,11 @@ plug_files = files( 'Views/Multitasking.vala', 'Views/Text.vala', 'Views/Wallpaper.vala', + 'Widgets/GenericContainer.vala', + 'Widgets/ImageContainer.vala', 'Widgets/SolidColorContainer.vala', - 'Widgets/WallpaperContainer.vala', + 'Widgets/UriContainer.vala', + 'Widgets/XMLContainer.vala', ) switchboard_dep = dependency('switchboard-3') From d6566870db2e6c70ae0bf5a884f2068032061925 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 23 Sep 2022 16:09:07 +0900 Subject: [PATCH 37/40] Fix undo toast --- src/Views/Wallpaper.vala | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Views/Wallpaper.vala b/src/Views/Wallpaper.vala index 41b36eb41..f87d51d95 100644 --- a/src/Views/Wallpaper.vala +++ b/src/Views/Wallpaper.vala @@ -519,9 +519,13 @@ public class PantheonShell.Wallpaper : Gtk.Box { var toast_revealer = (Gtk.Revealer) toast.get_first_child (); toast_revealer.notify["reveal-child"].connect (() => { - if (!toast_revealer.reveal_child && wallpaper_for_removal != null) { - confirm_removal (); - } + // give some time for undo action to emit + Idle.add (() => { + if (!toast_revealer.reveal_child && wallpaper_for_removal != null) { + confirm_removal (); + } + return Source.REMOVE; + }); }); view_overlay.add_overlay (toast); @@ -530,8 +534,8 @@ public class PantheonShell.Wallpaper : Gtk.Box { } private void mark_for_removal (UriContainer wallpaper) { - wallpaper_view.remove (wallpaper); wallpaper_for_removal = wallpaper; + wallpaper.hide (); } private void confirm_removal () { @@ -542,7 +546,7 @@ public class PantheonShell.Wallpaper : Gtk.Box { } private void undo_removal () { - wallpaper_view.append (wallpaper_for_removal); + wallpaper_for_removal.show (); wallpaper_for_removal = null; } From fc546ec771442473bd6a7c292b71f3c0a47b3a77 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 23 Sep 2022 16:17:07 +0900 Subject: [PATCH 38/40] Use box instead of grid --- src/Plug.vala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Plug.vala b/src/Plug.vala index cce3b9ea5..0e0bdf6db 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -20,7 +20,7 @@ public class PantheonShell.Plug : Switchboard.Plug { private Gtk.Stack stack; - private Gtk.Grid main_grid; + private Gtk.Box main_box; private Wallpaper wallpaper_view; @@ -53,8 +53,8 @@ public class PantheonShell.Plug : Switchboard.Plug { } public override Gtk.Widget get_widget () { - if (main_grid == null) { - main_grid = new Gtk.Grid (); + if (main_box == null) { + main_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); wallpaper_view = new Wallpaper (); @@ -91,11 +91,11 @@ public class PantheonShell.Plug : Switchboard.Plug { } } - main_grid.attach (stack_switcher, 0, 0, 1, 1); - main_grid.attach (stack, 0, 1, 1, 1); + main_box.append (stack_switcher); + main_box.append (stack); } - return main_grid; + return main_box; } public override void shown () { From 358168a37083528ad0d1c63fcd5582d8d9f08d58 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 2 Dec 2022 20:46:25 +0900 Subject: [PATCH 39/40] Fix popover styling --- data/Check.css | 19 +++++++++++++++++++ data/RemoveButton.css | 22 ++++++++++++++++++++++ data/icons.gresource.xml | 1 + src/Widgets/GenericContainer.vala | 18 +++++++++++++++--- 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 data/RemoveButton.css diff --git a/data/Check.css b/data/Check.css index 3c9a18ad5..9f58c21a8 100644 --- a/data/Check.css +++ b/data/Check.css @@ -1,3 +1,22 @@ +/* +* Copyright 2022 elementary, Inc. (https://elementary.io) +* +* 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 the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA. +*/ + check { min-height: 20px; min-width: 20px; diff --git a/data/RemoveButton.css b/data/RemoveButton.css new file mode 100644 index 000000000..21cdbca12 --- /dev/null +++ b/data/RemoveButton.css @@ -0,0 +1,22 @@ +/* +* Copyright 2022 elementary, Inc. (https://elementary.io) +* +* 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 the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA. +*/ + +.remove-button { + transition: background-color 0s; +} diff --git a/data/icons.gresource.xml b/data/icons.gresource.xml index 770cea612..12371cadb 100644 --- a/data/icons.gresource.xml +++ b/data/icons.gresource.xml @@ -10,6 +10,7 @@ appearance-default.svg appearance-dark.svg Check.css + RemoveButton.css plug.css appearance-styles.css diff --git a/src/Widgets/GenericContainer.vala b/src/Widgets/GenericContainer.vala index 3a3f6625f..5d340522f 100644 --- a/src/Widgets/GenericContainer.vala +++ b/src/Widgets/GenericContainer.vala @@ -25,6 +25,7 @@ public class PantheonShell.GenericContainer : Gtk.FlowBoxChild { protected const int THUMB_HEIGHT = 100; private static Gtk.CssProvider check_css_provider; + private static Gtk.CssProvider move_to_trash_provider; private static Gtk.CheckButton check_group; // used for turning CheckButtons into RadioButtons protected Gtk.Box card_box; @@ -53,6 +54,9 @@ public class PantheonShell.GenericContainer : Gtk.FlowBoxChild { check_css_provider = new Gtk.CssProvider (); check_css_provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/Check.css"); + move_to_trash_provider = new Gtk.CssProvider (); + move_to_trash_provider.load_from_resource ("/io/elementary/switchboard/plug/pantheon-shell/RemoveButton.css"); + check_group = new Gtk.CheckButton (); } @@ -96,11 +100,19 @@ public class PantheonShell.GenericContainer : Gtk.FlowBoxChild { child = overlay; // Context menu - move_to_trash = new Gtk.Button.with_label (_("Remove")) { + move_to_trash = new Gtk.Button () { + child = new Granite.AccelLabel (_("Remove")), sensitive = false }; - - context_menu_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + move_to_trash.get_style_context ().add_provider (move_to_trash_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + move_to_trash.add_css_class (Granite.STYLE_CLASS_MENUITEM); + // remove background-color transition so it looks identical to menu item + move_to_trash.add_css_class ("remove-button"); + + context_menu_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { + margin_top = 3, + margin_bottom = 3 + }; context_menu_box.append (move_to_trash); context_menu = new Gtk.Popover () { From f0b6ef4cea39a2213006b84cfa5fdf34fb3d3792 Mon Sep 17 00:00:00 2001 From: lenemter Date: Fri, 2 Dec 2022 21:03:44 +0900 Subject: [PATCH 40/40] Fix popover position --- src/Widgets/GenericContainer.vala | 22 +++++++++++++--------- src/Widgets/ImageContainer.vala | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Widgets/GenericContainer.vala b/src/Widgets/GenericContainer.vala index 5d340522f..b81a5c724 100644 --- a/src/Widgets/GenericContainer.vala +++ b/src/Widgets/GenericContainer.vala @@ -34,7 +34,7 @@ public class PantheonShell.GenericContainer : Gtk.FlowBoxChild { protected Gtk.Overlay overlay; protected Gtk.Box context_menu_box; protected Gtk.Popover context_menu; - protected Gtk.Button move_to_trash; + protected Gtk.Button move_to_trash_button; public bool checked { get { @@ -100,36 +100,40 @@ public class PantheonShell.GenericContainer : Gtk.FlowBoxChild { child = overlay; // Context menu - move_to_trash = new Gtk.Button () { + move_to_trash_button = new Gtk.Button () { child = new Granite.AccelLabel (_("Remove")), sensitive = false }; - move_to_trash.get_style_context ().add_provider (move_to_trash_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - move_to_trash.add_css_class (Granite.STYLE_CLASS_MENUITEM); + move_to_trash_button.get_style_context ().add_provider (move_to_trash_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + move_to_trash_button.add_css_class (Granite.STYLE_CLASS_MENUITEM); // remove background-color transition so it looks identical to menu item - move_to_trash.add_css_class ("remove-button"); + move_to_trash_button.add_css_class ("remove-button"); context_menu_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { margin_top = 3, margin_bottom = 3 }; - context_menu_box.append (move_to_trash); + context_menu_box.append (move_to_trash_button); context_menu = new Gtk.Popover () { child = context_menu_box, autohide = true }; - context_menu.set_parent (this); + context_menu.set_parent (overlay); // signals check.notify["active"].connect (() => { check.active = true; }); - overlay_event_controller.pressed.connect (() => { + overlay_event_controller.pressed.connect ((n_press, x, y) => { + var rect = Gdk.Rectangle (); + rect = {(int) x, (int) y, 1, 1}; + + context_menu.pointing_to = rect; context_menu.popup (); }); - move_to_trash.clicked.connect (() => trash ()); + move_to_trash_button.clicked.connect (() => trash ()); } } diff --git a/src/Widgets/ImageContainer.vala b/src/Widgets/ImageContainer.vala index a3d4e3071..5c87df97a 100644 --- a/src/Widgets/ImageContainer.vala +++ b/src/Widgets/ImageContainer.vala @@ -32,7 +32,7 @@ public class PantheonShell.ImageContainer : UriContainer { try { var info = file.query_info ("*", FileQueryInfoFlags.NONE); load_thumb_info (info); - move_to_trash.sensitive = info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE); + move_to_trash_button.sensitive = info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE); } catch (Error e) { critical (e.message); }