From d674a6354adf0c4ed23ff46ea2729a3d1071ef61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 22 Apr 2025 11:42:23 -0700 Subject: [PATCH 1/8] Update deps --- .github/workflows/main.yml | 2 +- meson.build | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 60011682..231894cf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,7 +23,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y gobject-introspection libglib2.0-dev libgranite-dev libwingpanel-dev meson valac + apt install -y gobject-introspection libglib2.0-dev libgranite-7-dev libwingpanel-8-dev meson valac - name: Build env: DESTDIR: out diff --git a/meson.build b/meson.build index 534476b4..5a758eb0 100644 --- a/meson.build +++ b/meson.build @@ -23,7 +23,7 @@ gresource = gnome.compile_resources( source_dir: 'data' ) -wingpanel_dep = dependency('wingpanel') +wingpanel_dep = dependency('wingpanel-8') wingpanel_indicatorsdir = wingpanel_dep.get_variable('indicatorsdir', pkgconfig_define: ['libdir', libdir]) config_data = configuration_data() @@ -52,8 +52,8 @@ shared_module( dependencies: [ dependency('glib-2.0'), dependency('gobject-2.0'), - dependency('granite', version: '>=6.0.0'), - dependency('gtk+-3.0'), + dependency('granite-7', version: '>=7.0.0'), + dependency('gtk4'), wingpanel_dep ], install: true, From 1d94301222a163a1fc84654cdc439b1c8ad65c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 22 Apr 2025 11:49:01 -0700 Subject: [PATCH 2/8] PopoverWidget: port to GTK4 --- src/Widgets/PopoverWidget.vala | 53 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/Widgets/PopoverWidget.vala b/src/Widgets/PopoverWidget.vala index 94f68ca1..a30e9643 100644 --- a/src/Widgets/PopoverWidget.vala +++ b/src/Widgets/PopoverWidget.vala @@ -39,53 +39,54 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { } construct { - orientation = Gtk.Orientation.VERTICAL; + orientation = VERTICAL; main_switch = new Granite.SwitchModelButton (_("Bluetooth")) { active = object_manager.get_global_state () }; - main_switch.get_style_context ().add_class (Granite.STYLE_CLASS_H4_LABEL); + main_switch.add_css_class (Granite.STYLE_CLASS_H4_LABEL); devices_list = new Gtk.ListBox (); devices_list.set_sort_func ((Gtk.ListBoxSortFunc) compare_rows); - var scroll_box = new Gtk.ScrolledWindow (null, null); - scroll_box.max_content_height = 512; - scroll_box.propagate_natural_height = true; - scroll_box.hscrollbar_policy = Gtk.PolicyType.NEVER; - scroll_box.add (devices_list); + var scroll_box = new Gtk.ScrolledWindow () { + child = devices_list, + max_content_height = 512, + propagate_natural_height = true, + hscrollbar_policy = NEVER + }; - var revealer_content_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL) { + var revealer_content_separator = new Gtk.Separator (HORIZONTAL) { margin_top = 3, margin_bottom = 3 }; - var revealer_content = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - revealer_content.add (revealer_content_separator); - revealer_content.add (scroll_box); + var revealer_content = new Gtk.Box (VERTICAL, 0); + revealer_content.append (revealer_content_separator); + revealer_content.append (scroll_box); - revealer = new Gtk.Revealer (); - revealer.add (revealer_content); + revealer = new Gtk.Revealer () { + child = revealer_content + }; var show_settings_button = new Gtk.ModelButton (); show_settings_button.text = _("Bluetooth Settings…"); - add (main_switch); - add (revealer); + append (main_switch); + append (revealer); if (is_in_session) { - var settings_button_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL) { + var settings_button_separator = new Gtk.Separator (HORIZONTAL) { margin_top = 3, margin_bottom = 3 }; - add (settings_button_separator); - add (show_settings_button); + append (settings_button_separator); + append (show_settings_button); } main_switch.active = object_manager.get_global_state (); update_ui_state (object_manager.get_global_state ()); - show_all (); devices_list.row_activated.connect ((row) => { ((Widgets.Device) row).toggle_device.begin (); @@ -159,7 +160,7 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { } private void update_devices_box_visible () { - if (devices_list.get_children () != null) { + if (devices_list.get_row_at_index (0) != null) { revealer.reveal_child = main_switch.active; } else { revealer.reveal_child = false; @@ -168,8 +169,7 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { private void add_device (BluetoothIndicator.Services.Device device) { var device_widget = new Widgets.Device (device, obex_manager); - devices_list.add (device_widget); - devices_list.show_all (); + devices_list.append (device_widget); update_devices_box_visible (); @@ -179,11 +179,12 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { } private void remove_device (BluetoothIndicator.Services.Device device) { - devices_list.get_children ().foreach ((row) => { - var device_child = (Widgets.Device) ((Gtk.ListBoxRow) row); + for (int i = 0; devices_list.get_row_at_index (i) != null; i++) { + var device_child = (Widgets.Device) devices_list.get_row_at_index (i); if (device_child != null && device_child.device.address == device.address) { - row.destroy (); + device_child.destroy (); + return; } - }); + } } } From 3ad7303a027ecd495540f560695ede4aa33ae325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 22 Apr 2025 11:53:13 -0700 Subject: [PATCH 3/8] Device: port to GTK4 --- src/Widgets/Device.vala | 50 ++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/Widgets/Device.vala b/src/Widgets/Device.vala index 826036f4..a0fb01e2 100644 --- a/src/Widgets/Device.vala +++ b/src/Widgets/Device.vala @@ -45,21 +45,21 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { obex_manager.transfer_active.connect (on_obex_transfer_active); name_label = new Gtk.Label (null) { - halign = Gtk.Align.START, + halign = START, use_markup = true, - valign = Gtk.Align.END, + valign = END, vexpand = true }; status_label = new Gtk.Label (_("Not Connected")) { - halign = Gtk.Align.START, - valign = Gtk.Align.START, + halign = START, + valign = START, vexpand = true }; spinner = new Gtk.Spinner () { - halign = Gtk.Align.START, - valign = Gtk.Align.START, + halign = START, + valign = START, hexpand = true }; @@ -67,16 +67,18 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { size_group.add_widget (status_label); size_group.add_widget (spinner); - icon_image = new Gtk.Image.from_icon_name (device.icon == null ? DEFAULT_ICON : device.icon, Gtk.IconSize.DIALOG); + icon_image = new Gtk.Image.from_icon_name (device.icon == null ? DEFAULT_ICON : device.icon) { + pixel_size = 48 + }; - status_image = new Gtk.Image.from_icon_name ("emblem-disabled", Gtk.IconSize.MENU) { - halign = Gtk.Align.END, - valign = Gtk.Align.END + status_image = new Gtk.Image.from_icon_name ("emblem-disabled") { + halign = END, + valign = END }; progress_label = new Gtk.Label (null) { - halign = Gtk.Align.START, - valign = Gtk.Align.END, + halign = START, + valign = END, use_markup = true, hexpand = true }; @@ -87,8 +89,8 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { file_label = new Gtk.Label (null) { ellipsize = Pango.EllipsizeMode.MIDDLE, - halign = Gtk.Align.START, - valign = Gtk.Align.END, + halign = START, + valign = END, use_markup = true, hexpand = true }; @@ -99,14 +101,15 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { content_grid.attach (progress_label, 0, 2); progress_revealer = new Gtk.Revealer () { - transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN, + child = content_grid, + transition_type = SLIDE_DOWN, margin_start = 5, margin_end = 5 }; - progress_revealer.add (content_grid); - var overlay = new Gtk.Overlay (); - overlay.add (icon_image); + var overlay = new Gtk.Overlay () { + child = icon_image + }; overlay.add_overlay (status_image); var grid = new Gtk.Grid () { @@ -121,12 +124,13 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { var box_grid = new Gtk.Grid (); box_grid.attach (grid, 0, 0); box_grid.attach (progress_revealer, 0, 1); - add (box_grid); + + child = box_grid; ((DBusProxy) device).g_properties_changed.connect (update_status); update_status (); - get_style_context ().add_class (Gtk.STYLE_CLASS_MENUITEM); + add_css_class (Granite.STYLE_CLASS_MENUITEM); selectable = false; obex_manager.active_transfers.foreach ((transfer, address)=> { on_obex_transfer_added (address, transfer); @@ -210,11 +214,11 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { } return; } - if (spinner.active) { + if (spinner.spinning) { return; } - spinner.active = true; + spinner.spinning = true; status_image.icon_name = "emblem-mixed"; try { if (!device.connected) { @@ -230,7 +234,7 @@ public class BluetoothIndicator.Widgets.Device : Gtk.ListBoxRow { status_image.icon_name = "emblem-error"; } - spinner.active = false; + spinner.spinning = false; } private void update_status () { From 8797c2e2c1a0d9d0ce5413136755c273704f93ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 22 Apr 2025 11:57:08 -0700 Subject: [PATCH 4/8] DisplayWidget: port to gtk4 --- src/Widgets/DisplayWidget.vala | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Widgets/DisplayWidget.vala b/src/Widgets/DisplayWidget.vala index 24cce18d..00b4bdf4 100644 --- a/src/Widgets/DisplayWidget.vala +++ b/src/Widgets/DisplayWidget.vala @@ -27,15 +27,15 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { construct { // Prevent a race that skips automatic resource loading // https://github.com/elementary/wingpanel-indicator-bluetooth/issues/203 - Gtk.IconTheme.get_default ().add_resource_path ("/org/elementary/wingpanel/icons"); + Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).add_resource_path ("/org/elementary/wingpanel/icons"); var provider = new Gtk.CssProvider (); provider.load_from_resource ("io/elementary/wingpanel/bluetooth/indicator.css"); - style_context = get_style_context (); - style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - style_context.add_class ("bluetooth-icon"); - style_context.add_class ("disabled"); + Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + add_css_class ("bluetooth-icon"); + add_css_class ("disabled"); object_manager.global_state_changed.connect ((state, connected) => { set_icon (); @@ -47,17 +47,17 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { object_manager.notify["retrieve-finished"].connect (set_icon); } - button_press_event.connect ((e) => { - if (e.button == Gdk.BUTTON_MIDDLE) { - object_manager.settings.set_boolean ( - "bluetooth-enabled", - !object_manager.settings.get_boolean ("bluetooth-enabled") - ); - return Gdk.EVENT_STOP; - } - - return Gdk.EVENT_PROPAGATE; + var gesture_click = new Gtk.GestureClick () { + button = Gdk.BUTTON_MIDDLE + }; + gesture_click.pressed.connect (() => { + object_manager.settings.set_boolean ( + "bluetooth-enabled", + !object_manager.settings.get_boolean ("bluetooth-enabled") + ); }); + + add_controller (gesture_click); } private void set_icon () { @@ -79,7 +79,7 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { style_context.remove_class ("disabled"); context = _("Middle-click to turn Bluetooth off"); if (connected) { - style_context.add_class ("paired"); + add_css_class ("paired"); description = _("Bluetooth connected"); } else { style_context.remove_class ("paired"); @@ -87,7 +87,7 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { } } else { style_context.remove_class ("paired"); - style_context.add_class ("disabled"); + add_css_class ("disabled"); description = _("Bluetooth is off"); context = _("Middle-click to turn Bluetooth on"); } From 92d1747208dbb4d35bf831a80df6220bae11f77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 22 Apr 2025 12:58:17 -0700 Subject: [PATCH 5/8] Replace ModelButton --- src/Widgets/PopoverWidget.vala | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Widgets/PopoverWidget.vala b/src/Widgets/PopoverWidget.vala index 1604fcb8..fd952f0d 100644 --- a/src/Widgets/PopoverWidget.vala +++ b/src/Widgets/PopoverWidget.vala @@ -57,8 +57,9 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { child = revealer_content }; - var show_settings_button = new Gtk.ModelButton (); - show_settings_button.text = _("Bluetooth Settings…"); + var show_settings_button = new PopoverMenuitem () { + text = _("Bluetooth Settings…") + }; append (main_switch); append (revealer); @@ -175,4 +176,31 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { } } } + + private class PopoverMenuitem : Gtk.Button { + public string text { + set { + child = new Granite.AccelLabel (value) { + action_name = this.action_name + }; + + update_property (Gtk.AccessibleProperty.LABEL, value, -1); + } + } + + class construct { + set_css_name ("modelbutton"); + } + + construct { + accessible_role = MENU_ITEM; + + clicked.connect (() => { + var popover = (Gtk.Popover) get_ancestor (typeof (Gtk.Popover)); + if (popover != null) { + popover.popdown (); + } + }); + } + } } From c581d2ce40aae0a97d1c939461580200a726da2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 22 Apr 2025 13:00:27 -0700 Subject: [PATCH 6/8] Can't subclass Gtk.Spinner --- src/Widgets/DisplayWidget.vala | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Widgets/DisplayWidget.vala b/src/Widgets/DisplayWidget.vala index 63943417..8144f6d5 100644 --- a/src/Widgets/DisplayWidget.vala +++ b/src/Widgets/DisplayWidget.vala @@ -3,14 +3,20 @@ * SPDX-FileCopyrightText: 2015-2025 elementary, Inc. (https://elementary.io) */ -public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { +public class BluetoothIndicator.Widgets.DisplayWidget : Granite.Bin { public BluetoothIndicator.Services.ObjectManager object_manager { get; construct; } + private Gtk.Spinner spinner; + public DisplayWidget (BluetoothIndicator.Services.ObjectManager object_manager) { Object (object_manager: object_manager); } construct { + spinner = new Gtk.Spinner (); + + child = spinner; + // Prevent a race that skips automatic resource loading // https://github.com/elementary/wingpanel-indicator-bluetooth/issues/203 Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).add_resource_path ("/org/elementary/wingpanel/icons"); @@ -20,8 +26,8 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - add_css_class ("bluetooth-icon"); - add_css_class ("disabled"); + spinner.add_css_class ("bluetooth-icon"); + spinner.add_css_class ("disabled"); object_manager.global_state_changed.connect ((state, connected) => { set_icon (); @@ -62,18 +68,18 @@ public class BluetoothIndicator.Widgets.DisplayWidget : Gtk.Spinner { string context; if (state) { - remove_css_class ("disabled"); + spinner.remove_css_class ("disabled"); context = _("Middle-click to turn Bluetooth off"); if (connected) { - add_css_class ("paired"); + spinner.add_css_class ("paired"); description = _("Bluetooth connected"); } else { - remove_css_class ("paired"); + spinner.remove_css_class ("paired"); description = _("Bluetooth is on"); } } else { - remove_css_class ("paired"); - add_css_class ("disabled"); + spinner.remove_css_class ("paired"); + spinner.add_css_class ("disabled"); description = _("Bluetooth is off"); context = _("Middle-click to turn Bluetooth on"); } From 406ea0838057af0a738c721df93aa2f73ad9e609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Mon, 28 Apr 2025 11:27:00 -0700 Subject: [PATCH 7/8] Use Wingpanel.PopoverMenuItem --- src/Widgets/PopoverWidget.vala | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/Widgets/PopoverWidget.vala b/src/Widgets/PopoverWidget.vala index fd952f0d..46080b80 100644 --- a/src/Widgets/PopoverWidget.vala +++ b/src/Widgets/PopoverWidget.vala @@ -57,7 +57,7 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { child = revealer_content }; - var show_settings_button = new PopoverMenuitem () { + var show_settings_button = new Wingpanel.PopoverMenuItem () { text = _("Bluetooth Settings…") }; @@ -176,31 +176,4 @@ public class BluetoothIndicator.Widgets.PopoverWidget : Gtk.Box { } } } - - private class PopoverMenuitem : Gtk.Button { - public string text { - set { - child = new Granite.AccelLabel (value) { - action_name = this.action_name - }; - - update_property (Gtk.AccessibleProperty.LABEL, value, -1); - } - } - - class construct { - set_css_name ("modelbutton"); - } - - construct { - accessible_role = MENU_ITEM; - - clicked.connect (() => { - var popover = (Gtk.Popover) get_ancestor (typeof (Gtk.Popover)); - if (popover != null) { - popover.popdown (); - } - }); - } - } } From 2444bd24859043d625d0b6d22251e4edc947d77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Mon, 11 Aug 2025 16:45:57 -0700 Subject: [PATCH 8/8] Update README, RDNN --- README.md | 4 ++-- data/bluetooth.metainfo.xml.in | 4 ++-- meson.build | 4 ++-- ...etooth-indicator.pot => io.elementary.panel.bluetooth.pot} | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename po/{bluetooth-indicator.pot => io.elementary.panel.bluetooth.pot} (100%) diff --git a/README.md b/README.md index 65d7d894..d87b6304 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ You'll need the following dependencies: gobject-introspection libglib2.0-dev - libgranite-dev >= 6.0.0 - libwingpanel-dev + libgranite-7-dev >= 7.0.0 + libwingpanel-8-dev meson >= 0.58.0 valac diff --git a/data/bluetooth.metainfo.xml.in b/data/bluetooth.metainfo.xml.in index 4a964505..6ffa2ca3 100644 --- a/data/bluetooth.metainfo.xml.in +++ b/data/bluetooth.metainfo.xml.in @@ -1,8 +1,8 @@ - io.elementary.wingpanel.bluetooth - bluetooth-indicator + io.elementary.panel.bluetooth + io.elementary.panel.bluetooth io.elementary.wingpanel CC0-1.0 LGPL-2.1 diff --git a/meson.build b/meson.build index 5a758eb0..ff461079 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,7 @@ project( meson_version : '>= 0.58' ) -gettext_name = meson.project_name() + '-indicator' +gettext_name = 'io.elementary.panel.' + meson.project_name() gnome = import('gnome') i18n = import('i18n') @@ -15,7 +15,7 @@ libdir = prefix / get_option('libdir') add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format(gettext_name), language:'c') -add_project_arguments('-DG_LOG_DOMAIN="io.elementary.wingpanel.bluetooth"', language:'c') +add_project_arguments('-DG_LOG_DOMAIN="io.elementary.panel.bluetooth"', language:'c') gresource = gnome.compile_resources( 'gresource', diff --git a/po/bluetooth-indicator.pot b/po/io.elementary.panel.bluetooth.pot similarity index 100% rename from po/bluetooth-indicator.pot rename to po/io.elementary.panel.bluetooth.pot