Skip to content

Commit ddb7019

Browse files
danirabbitzeebok
andauthored
Port to GTK4 (#106)
Co-authored-by: Ryan Kornheisl <ryan@skarva.tech>
1 parent 78d5e40 commit ddb7019

18 files changed

Lines changed: 148 additions & 175 deletions

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Install Dependencies
2525
run: |
2626
apt update
27-
apt install -y libglib2.0-dev libgtk-3-dev libpackagekit-glib2-dev libportal-dev libwingpanel-dev libaccountsservice-dev meson valac
27+
apt install -y libadwaita-1-dev libglib2.0-dev libgtk-4-dev libpackagekit-glib2-dev libportal-dev libwingpanel-9-dev libaccountsservice-dev meson valac
2828
- name: Build
2929
env:
3030
DESTDIR: out

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ jobs:
1616
GIT_USER_NAME: "elementaryBot"
1717
GIT_USER_EMAIL: "builds@elementary.io"
1818
with:
19-
release_branch: 'noble'
19+
release_branch: 'resolute'

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
You'll need the following dependencies:
99

10-
* libgranite-dev
11-
* libhandy-1-dev
12-
* libwingpanel-dev
10+
* libgranite-7-dev
11+
* libadwaita-1-dev
12+
* libwingpanel-9-dev
1313
* meson
1414
* valac
1515

meson.build

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,15 @@ datadir = prefix / get_option('datadir')
1212

1313
add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), language:'c')
1414
add_project_arguments('-DG_LOG_DOMAIN="@0@"'.format(meson.project_name()), language:'c')
15-
add_project_arguments('--vapidir=' + join_paths(meson.project_source_root(), 'vapi'), language: 'vala')
1615

17-
gdk_wl_dep = dependency('gdk-wayland-3.0')
1816
glib_dep = dependency('glib-2.0')
1917
gobject_dep = dependency('gobject-2.0')
20-
granite_dep = dependency('granite', version: '>=6.0.0')
21-
gtk_dep = dependency('gtk+-3.0')
22-
handy_dep = dependency('libhandy-1', version: '>=1.0')
18+
granite_dep = dependency('granite-7', version: '>=7.7.0')
19+
gtk_dep = dependency('gtk4')
20+
gtk_wayland_dep = dependency('gtk4-wayland')
21+
handy_dep = dependency('libadwaita-1', version: '>=1.0')
2322
packagekit_dep = dependency('packagekit-glib2')
24-
wingpanel_dep = dependency('wingpanel')
23+
wingpanel_dep = dependency('wingpanel-9')
2524
wingpanel_indicatorsdir = wingpanel_dep.get_pkgconfig_variable('indicatorsdir', define_variable: ['libdir', libdir])
2625
wl_client_dep = dependency('wayland-client')
2726
portal_dep = dependency('libportal')

src/Indicator.vala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class QuickSettings.Indicator : Wingpanel.Indicator {
2323

2424
// Prevent a race that skips automatic resource loading
2525
// https://github.com/elementary/wingpanel-indicator-bluetooth/issues/203
26-
Gtk.IconTheme.get_default ().add_resource_path ("/org/elementary/wingpanel/icons");
26+
Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).add_resource_path ("/org/elementary/wingpanel/icons");
2727

2828
EndSessionDialogServer.init ();
2929
EndSessionDialogServer.get_default ().show_dialog.connect (
@@ -45,7 +45,7 @@ public class QuickSettings.Indicator : Wingpanel.Indicator {
4545
unowned var server = EndSessionDialogServer.get_default ();
4646

4747
current_dialog = new EndSessionDialog (type);
48-
current_dialog.destroy.connect (() => {
48+
((Gtk.Widget) current_dialog).destroy.connect (() => {
4949
server.closed ();
5050
current_dialog = null;
5151
});
@@ -89,8 +89,8 @@ public class QuickSettings.Indicator : Wingpanel.Indicator {
8989
var provider = new Gtk.CssProvider ();
9090
provider.load_from_resource ("io/elementary/quick-settings/Indicator.css");
9191

92-
Gtk.StyleContext.add_provider_for_screen (
93-
Gdk.Screen.get_default (),
92+
Gtk.StyleContext.add_provider_for_display (
93+
Gdk.Display.get_default (),
9494
provider,
9595
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
9696
);

src/PopoverWidget.vala

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public class QuickSettings.PopoverWidget : Gtk.Box {
4747
row_spacing = 12,
4848
selection_mode = NONE
4949
};
50-
toggle_box.get_style_context ().add_class ("togglebox");
51-
toggle_box.add (prevent_sleep_toggle);
50+
toggle_box.add_css_class ("togglebox");
51+
toggle_box.append (prevent_sleep_toggle);
5252

5353
var text_scale = new TextScale ();
5454

@@ -57,11 +57,11 @@ public class QuickSettings.PopoverWidget : Gtk.Box {
5757
var current_user = new AvatarButton ();
5858

5959
current_user_button = new Gtk.Button () {
60-
child = current_user
60+
child = current_user,
61+
has_frame = false
6162
};
62-
current_user_button.get_style_context ().add_class ("circular");
63-
current_user_button.get_style_context ().add_class ("flat");
64-
current_user_button.get_style_context ().add_class ("no-padding");
63+
current_user_button.add_css_class (Granite.CssClass.CIRCULAR);
64+
current_user_button.add_css_class ("no-padding");
6565

6666
var session_box = new SessionBox (server_type) {
6767
halign = END,
@@ -70,15 +70,15 @@ public class QuickSettings.PopoverWidget : Gtk.Box {
7070
};
7171

7272
var bottom_box = new Gtk.Box (HORIZONTAL, 0);
73-
bottom_box.add (current_user_button);
74-
bottom_box.add (session_box);
75-
bottom_box.get_style_context ().add_class ("togglebox");
73+
bottom_box.append (current_user_button);
74+
bottom_box.append (session_box);
75+
bottom_box.add_css_class ("togglebox");
7676

7777
main_box = new Gtk.Box (VERTICAL, 0);
78-
main_box.add (toggle_box);
79-
main_box.add (scale_box);
80-
main_box.add (new Gtk.Separator (HORIZONTAL));
81-
main_box.add (bottom_box);
78+
main_box.append (toggle_box);
79+
main_box.append (scale_box);
80+
main_box.append (new Gtk.Separator (HORIZONTAL));
81+
main_box.append (bottom_box);
8282

8383
accounts_view = new UserList ();
8484

@@ -88,27 +88,25 @@ public class QuickSettings.PopoverWidget : Gtk.Box {
8888
transition_type = SLIDE_LEFT_RIGHT
8989
};
9090

91-
stack.add (main_box);
92-
stack.add (accounts_view);
91+
stack.add_child (main_box);
92+
stack.add_child (accounts_view);
9393

94-
add (stack);
94+
append (stack);
9595

9696
if (server_type == GREETER) {
9797
bottom_box.remove (current_user_button);
9898
}
9999

100100
if (server_type != GREETER) {
101101
var darkmode_button = new DarkModeToggle ();
102-
toggle_box.add (darkmode_button);
103-
show_all ();
102+
toggle_box.append (darkmode_button);
104103
}
105104

106105
setup_sensor_proxy.begin ((obj, res) => {
107106
var sensor_proxy = setup_sensor_proxy.end (res);
108107
if (sensor_proxy.has_accelerometer) {
109108
var rotation_toggle = new RotationToggle ();
110-
toggle_box.add (rotation_toggle);
111-
show_all ();
109+
toggle_box.append (rotation_toggle);
112110
};
113111
});
114112

@@ -122,18 +120,18 @@ public class QuickSettings.PopoverWidget : Gtk.Box {
122120
var glib_settings = new Settings ("io.elementary.desktop.quick-settings");
123121

124122
if (server_type == GREETER || glib_settings.get_boolean ("show-a11y")) {
125-
toggle_box.add (screen_reader);
126-
toggle_box.add (onscreen_keyboard);
123+
toggle_box.append (screen_reader);
124+
toggle_box.append (onscreen_keyboard);
127125

128-
scale_box.add (text_scale);
126+
scale_box.append (text_scale);
129127
}
130128

131129
glib_settings.changed["show-a11y"].connect (() => {
132130
if (glib_settings.get_boolean ("show-a11y") && screen_reader.parent == null) {
133-
toggle_box.add (screen_reader);
134-
toggle_box.add (onscreen_keyboard);
131+
toggle_box.append (screen_reader);
132+
toggle_box.append (onscreen_keyboard);
135133

136-
scale_box.add (text_scale);
134+
scale_box.append (text_scale);
137135
} else {
138136
toggle_box.remove (screen_reader);
139137
toggle_box.remove (onscreen_keyboard);
@@ -162,7 +160,7 @@ public class QuickSettings.PopoverWidget : Gtk.Box {
162160
new ThemedIcon ("onboard")
163161
) {
164162
badge_icon = new ThemedIcon ("system-log-out"),
165-
transient_for = (Gtk.Window) get_toplevel ()
163+
transient_for = (Gtk.Window) get_root ()
166164
};
167165
message_dialog.response.connect (message_dialog.destroy);
168166
message_dialog.present ();

src/Widgets/AvatarButton.vala

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,28 @@
33
* SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io)
44
*/
55

6-
public class QuickSettings.AvatarButton : Gtk.Box {
6+
public class QuickSettings.AvatarButton : Granite.Bin {
77
private Act.User? user = null;
8-
private Hdy.Avatar avatar;
8+
private Adw.Avatar avatar;
99

1010
construct {
11-
avatar = new Hdy.Avatar (32, null, true);
11+
avatar = new Adw.Avatar (32, null, true);
1212

1313
// We want to use the user's accent, not a random color
14-
avatar.get_style_context ().remove_class ("color1");
15-
avatar.get_style_context ().remove_class ("color2");
16-
avatar.get_style_context ().remove_class ("color3");
17-
avatar.get_style_context ().remove_class ("color4");
18-
avatar.get_style_context ().remove_class ("color5");
19-
avatar.get_style_context ().remove_class ("color6");
20-
avatar.get_style_context ().remove_class ("color7");
21-
avatar.get_style_context ().remove_class ("color8");
22-
avatar.get_style_context ().remove_class ("color9");
23-
avatar.get_style_context ().remove_class ("color10");
24-
avatar.get_style_context ().remove_class ("color11");
25-
avatar.get_style_context ().remove_class ("color12");
26-
avatar.get_style_context ().remove_class ("color13");
27-
avatar.get_style_context ().remove_class ("color14");
14+
avatar.remove_css_class ("color1");
15+
avatar.remove_css_class ("color2");
16+
avatar.remove_css_class ("color3");
17+
avatar.remove_css_class ("color4");
18+
avatar.remove_css_class ("color5");
19+
avatar.remove_css_class ("color6");
20+
avatar.remove_css_class ("color7");
21+
avatar.remove_css_class ("color8");
22+
avatar.remove_css_class ("color9");
23+
avatar.remove_css_class ("color10");
24+
avatar.remove_css_class ("color11");
25+
avatar.remove_css_class ("color12");
26+
avatar.remove_css_class ("color13");
27+
avatar.remove_css_class ("color14");
2828

2929
child = avatar;
3030

@@ -53,13 +53,12 @@
5353
}
5454
}
5555

56-
private GLib.LoadableIcon? get_avatar_icon () {
57-
var file = File.new_for_path (user.get_icon_file ());
58-
if (file.query_exists ()) {
59-
return new FileIcon (file);
56+
private Gdk.Texture? get_avatar_icon () {
57+
try {
58+
return Gdk.Texture.from_filename (user.get_icon_file ());
59+
} catch {
60+
return null;
6061
}
61-
62-
return null;
6362
}
6463

6564
private void update () {
@@ -68,6 +67,6 @@
6867
}
6968

7069
avatar.text = user.real_name;
71-
avatar.set_loadable_icon (get_avatar_icon ());
70+
avatar.custom_image = get_avatar_icon ();
7271
}
7372
}

src/Widgets/DarkModeToggle.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class QuickSettings.DarkModeToggle: SettingsToggle {
1313
construct {
1414
icon_name = "dark-mode-symbolic";
1515
settings_uri = "settings://desktop/appearance";
16-
get_style_context ().add_class ("color-scheme");
16+
add_css_class ("color-scheme");
1717

1818
var settings = new GLib.Settings ("io.elementary.settings-daemon.prefers-color-scheme");
1919

src/Widgets/EndSessionDialog.vala

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
2323
public EndSessionDialogType dialog_type { get; construct; }
2424

2525
private Gtk.CheckButton? updates_check_button;
26-
private Gtk.EventControllerKey key_controller;
2726

2827
public EndSessionDialog (QuickSettings.EndSessionDialogType type) {
2928
Object (dialog_type: type);
@@ -50,10 +49,6 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
5049
break;
5150
}
5251

53-
var image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.DIALOG) {
54-
valign = Gtk.Align.START
55-
};
56-
5752
/*
5853
* the indicator does not have a separate item for restart, that's
5954
* why we show both shutdown and restart for the restart action
@@ -71,7 +66,7 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
7166
var cancel = (Gtk.Button) add_button (_("Cancel"), Gtk.ResponseType.CANCEL);
7267

7368
var confirm = (Gtk.Button) add_button (button_text, Gtk.ResponseType.ACCEPT);
74-
confirm.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
69+
confirm.add_css_class (Granite.CssClass.DESTRUCTIVE);
7570

7671
if (dialog_type != LOGOUT) {
7772
bool has_prepared_updates = false;
@@ -86,9 +81,8 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
8681
active = true,
8782
label = _("Install pending system updates"),
8883
};
89-
updates_check_button.show ();
9084

91-
custom_bin.add (updates_check_button);
85+
custom_bin.append (updates_check_button);
9286
}
9387
}
9488

@@ -104,13 +98,15 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
10498
cancel_action.activate (null);
10599
});
106100

107-
key_controller = new Gtk.EventControllerKey (this);
101+
var key_controller = new Gtk.EventControllerKey ();
108102
key_controller.key_released.connect ((keyval, keycode, state) => {
109103
if (keyval == Gdk.Key.Escape) {
110104
cancel_action.activate (null);
111105
}
112106
});
113107

108+
((Gtk.Widget) this).add_controller (key_controller);
109+
114110
confirm.clicked.connect (() => {
115111
if (dialog_type == EndSessionDialogType.RESTART || dialog_type == EndSessionDialogType.SHUTDOWN) {
116112
if (set_offline_trigger (POWER_OFF)) {
@@ -125,7 +121,7 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
125121
destroy ();
126122
});
127123

128-
realize.connect (() => Idle.add_once (() => init_wl ()));
124+
((Gtk.Widget) this).realize.connect (() => Idle.add_once (() => init_wl ()));
129125
}
130126

131127
private bool set_offline_trigger (Pk.OfflineAction action) {
@@ -156,9 +152,9 @@ public class QuickSettings.EndSessionDialog : Granite.MessageDialog {
156152
public void registry_handle_global (Wl.Registry wl_registry, uint32 name, string @interface, uint32 version) {
157153
if (@interface == "io_elementary_pantheon_shell_v1") {
158154
var desktop_shell = wl_registry.bind<PantheonDesktop.Shell> (name, ref PantheonDesktop.Shell.iface, uint32.min (version, 1));
159-
unowned var window = get_window ();
160-
if (window is Gdk.Wayland.Window) {
161-
unowned var wl_surface = ((Gdk.Wayland.Window) window).get_wl_surface ();
155+
unowned var surface = get_surface ();
156+
if (surface is Gdk.Wayland.Surface) {
157+
unowned var wl_surface = ((Gdk.Wayland.Surface) surface).get_wl_surface ();
162158
var extended_behavior = desktop_shell.get_extended_behavior (wl_surface);
163159
extended_behavior.set_keep_above ();
164160
extended_behavior.make_centered ();

src/Widgets/PreventSleepToggle.vala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ public class QuickSettings.PreventSleepToggle: SettingsToggle {
2323

2424
if (_prevent_sleep_toggle.active && suspend_cookie == 0 && idle_cookie == 0) {
2525
suspend_cookie = application.inhibit (
26-
(Gtk.Window) get_toplevel (),
26+
(Gtk.Window) get_root (),
2727
Gtk.ApplicationInhibitFlags.SUSPEND,
2828
"Prevent session from suspending"
2929
);
3030
idle_cookie = application.inhibit (
31-
(Gtk.Window) get_toplevel (),
31+
(Gtk.Window) get_root (),
3232
Gtk.ApplicationInhibitFlags.IDLE,
3333
"Prevent session from idle"
3434
);

0 commit comments

Comments
 (0)