diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0a76fe3c..a735efcb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y desktop-file-utils libaccountsservice-dev libgdk-pixbuf2.0-dev libgnome-desktop-3-dev libgranite-dev libgtk-3-dev libhandy-1-dev liblightdm-gobject-1-dev ${{ matrix.mutter_pkg }} libx11-dev meson valac + apt install -y desktop-file-utils libaccountsservice-dev libgdk-pixbuf2.0-dev libgnome-desktop-3-dev libgranite-7-dev libgtk-4-dev libadwaita-1-dev liblightdm-gobject-1-dev ${{ matrix.mutter_pkg }} libx11-dev meson valac - name: Build env: DESTDIR: out diff --git a/data/Application.css b/data/Application.css index 07fab39c..66a09fd7 100644 --- a/data/Application.css +++ b/data/Application.css @@ -4,6 +4,8 @@ */ window.background { + background: transparent; + box-shadow: none; opacity: 0; transition: opacity 1s ease; } @@ -74,50 +76,50 @@ check.banana { check.blueberry { background-color: mix(@BLUEBERRY_300, @BLUEBERRY_500, 0.25); - -gtk-icon-shadow: 0 1px 1px shade(mix(@BLUEBERRY_300, @BLUEBERRY_500, 0.25), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@BLUEBERRY_300, @BLUEBERRY_500, 0.3), 0.7); } check.bubblegum { background-color: mix(@BUBBLEGUM_300, @BUBBLEGUM_500, 0.25); - -gtk-icon-shadow: 0 1px 1px shade(mix(@BUBBLEGUM_300, @BUBBLEGUM_500, 0.25), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@BUBBLEGUM_300, @BUBBLEGUM_500, 0.3), 0.7); } check.cocoa { background-color: @COCOA_300; - -gtk-icon-shadow: 0 1px 1px shade(@COCOA_300, 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(@COCOA_300, 0.7); } check.grape { background-color: mix(@GRAPE_300, @GRAPE_500, 0.5); - -gtk-icon-shadow: 0 1px 1px shade(mix(@GRAPE_300, @GRAPE_500, 0.5), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@GRAPE_300, @GRAPE_500, 0.3), 0.7); } check.latte { background-color: mix(@LATTE_300, @LATTE_500, 0.25); - -gtk-icon-shadow: 0 1px 1px shade(mix(@LATTE_300, @LATTE_500, 0.25), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@LATTE_300, @LATTE_500, 0.3), 0.7); } check.lime { background-color: mix(@LIME_300, @LIME_500, 0.25); - -gtk-icon-shadow: 0 1px 1px shade(mix(@LIME_300, @LIME_500, 0.25), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@LIME_300, @LIME_500, 0.3), 0.7); } check.mint { background-color: mix(@MINT_300, @MINT_500, 0.75); - -gtk-icon-shadow: 0 1px 1px shade(mix(@MINT_300, @MINT_500, 0.75), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@MINT_300, @MINT_500, 0.3), 0.7); } check.orange { background-color: mix(@ORANGE_300, @ORANGE_500, 0.5); - -gtk-icon-shadow: 0 1px 1px shade(mix(@ORANGE_300, @ORANGE_500, 0.5), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@ORANGE_300, @ORANGE_500, 0.3), 0.7); } check.slate { background-color: @SLATE_100; - -gtk-icon-shadow: 0 1px 1px shade(@SLATE_100, 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(@SLATE_100, 0.7); } check.strawberry { background-color: mix(@STRAWBERRY_300, @STRAWBERRY_500, 0.25); - -gtk-icon-shadow: 0 1px 1px shade(mix(@STRAWBERRY_300, @STRAWBERRY_500, 0.25), 0.3), 0.7); + -gtk-icon-shadow: 0 1px 1px shade(mix(@STRAWBERRY_300, @STRAWBERRY_500, 0.3), 0.7); } diff --git a/po/POTFILES b/po/POTFILES index df9cb99c..3f99b4b2 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -27,7 +27,6 @@ src/Settings.vala src/Cards/BaseCard.vala src/Cards/ManualCard.vala src/Cards/UserCard.vala -src/Widgets/BackgroundImage.vala src/Widgets/CapsLockRevealer.vala src/Widgets/DateTimeWidget.vala src/Widgets/PasswordEntry.vala diff --git a/src/Application.vala b/src/Application.vala index b4407717..42c78ee8 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -39,10 +39,7 @@ public class Greeter.Application : Gtk.Application { protected override void startup () { base.startup (); - var css_provider = new Gtk.CssProvider (); - css_provider.load_from_resource ("/io/elementary/greeter/Application.css"); - - Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + Granite.init (); GLib.Bus.own_name ( SESSION, @@ -135,7 +132,6 @@ public class Greeter.Application : Gtk.Application { public override void activate () { add_window (new Greeter.MainWindow (lightdm_greeter)); - active_window.show_all (); active_window.present (); } diff --git a/src/Cards/BaseCard.vala b/src/Cards/BaseCard.vala index 3401d7d6..0be9ddea 100644 --- a/src/Cards/BaseCard.vala +++ b/src/Cards/BaseCard.vala @@ -5,7 +5,7 @@ * Authors: Corentin Noël */ -public abstract class Greeter.BaseCard : Gtk.Bin { +public abstract class Greeter.BaseCard : Granite.Bin { public signal void do_connect (string? credential = null); protected const int ERROR_SHAKE_DURATION = 450; diff --git a/src/Cards/ManualCard.vala b/src/Cards/ManualCard.vala index cae3c34a..9bf6860d 100644 --- a/src/Cards/ManualCard.vala +++ b/src/Cards/ManualCard.vala @@ -22,7 +22,7 @@ public class Greeter.ManualCard : Greeter.BaseCard { hexpand = true, margin_bottom = 16 }; - label.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL); + label.add_css_class (Granite.STYLE_CLASS_H2_LABEL); username_entry = new Gtk.Entry () { hexpand = true, @@ -58,23 +58,28 @@ public class Greeter.ManualCard : Greeter.BaseCard { margin_start = 12, margin_end = 12 }; - main_box.add (form_grid); + main_box.append (form_grid); - main_box.get_style_context ().add_class (Granite.STYLE_CLASS_CARD); - main_box.get_style_context ().add_class (Granite.STYLE_CLASS_ROUNDED); + main_box.add_css_class (Granite.STYLE_CLASS_CARD); + main_box.add_css_class (Granite.STYLE_CLASS_ROUNDED); child = main_box; bind_property ("connecting", username_entry, "sensitive", INVERT_BOOLEAN); bind_property ("connecting", password_entry, "sensitive", INVERT_BOOLEAN); - username_entry.focus_out_event.connect (() => { + + var focus_controller = new Gtk.EventControllerFocus (); + focus_controller.leave.connect (() => { if (username_entry.text != "") { do_connect_username (username_entry.text); } }); + username_entry.add_controller (focus_controller); + password_entry.activate.connect (on_login); + } private void on_login () { @@ -89,14 +94,14 @@ public class Greeter.ManualCard : Greeter.BaseCard { public override void wrong_credentials () { password_entry.text = ""; - username_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_ERROR); - password_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_ERROR); - main_box.get_style_context ().add_class ("shake"); + username_entry.add_css_class (Granite.STYLE_CLASS_ERROR); + password_entry.add_css_class (Granite.STYLE_CLASS_ERROR); + main_box.add_css_class ("shake"); Timeout.add (ERROR_SHAKE_DURATION, () => { - username_entry.get_style_context ().remove_class (Gtk.STYLE_CLASS_ERROR); - password_entry.get_style_context ().remove_class (Gtk.STYLE_CLASS_ERROR); - main_box.get_style_context ().remove_class ("shake"); + username_entry.remove_css_class (Granite.STYLE_CLASS_ERROR); + password_entry.remove_css_class (Granite.STYLE_CLASS_ERROR); + main_box.remove_css_class ("shake"); connecting = false; username_entry.grab_focus_without_selecting (); @@ -112,12 +117,12 @@ public class Greeter.ManualCard : Greeter.BaseCard { username_entry.grab_focus_without_selecting (); username_entry.text = ""; - username_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_ERROR); - main_box.get_style_context ().add_class ("shake"); + username_entry.add_css_class (Granite.STYLE_CLASS_ERROR); + main_box.add_css_class ("shake"); Timeout.add (ERROR_SHAKE_DURATION, () => { - username_entry.get_style_context ().remove_class (Gtk.STYLE_CLASS_ERROR); - main_box.get_style_context ().remove_class ("shake"); + username_entry.remove_css_class (Granite.STYLE_CLASS_ERROR); + main_box.remove_css_class ("shake"); return Source.REMOVE; }); diff --git a/src/Cards/UserCard.vala b/src/Cards/UserCard.vala index 710282db..db26fa8b 100644 --- a/src/Cards/UserCard.vala +++ b/src/Cards/UserCard.vala @@ -18,7 +18,6 @@ public class Greeter.UserCard : Greeter.BaseCard { private Pantheon.AccountsService greeter_act; private Pantheon.SettingsDaemon.AccountsService settings_act; - private Gtk.GestureMultiPress click_gesture; private Gtk.Revealer form_revealer; private Gtk.Stack login_stack; private Greeter.PasswordEntry password_entry; @@ -42,7 +41,7 @@ public class Greeter.UserCard : Greeter.BaseCard { margin_start = 24, margin_end = 24, }; - username_label.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL); + username_label.add_css_class (Granite.STYLE_CLASS_H2_LABEL); password_entry = new Greeter.PasswordEntry (); @@ -53,17 +52,7 @@ public class Greeter.UserCard : Greeter.BaseCard { INVERT_BOOLEAN ); - var fingerprint_image = new Gtk.Image.from_icon_name ( - "fingerprint-symbolic", - BUTTON - ); - - bind_property ( - "use-fingerprint", - fingerprint_image, - "no-show-all", - INVERT_BOOLEAN | SYNC_CREATE - ); + var fingerprint_image = new Gtk.Image.from_icon_name ("fingerprint-symbolic"); bind_property ( "use-fingerprint", @@ -86,7 +75,7 @@ public class Greeter.UserCard : Greeter.BaseCard { password_grid.attach (new Greeter.CapsLockRevealer (), 0, 1, 3); var login_button = new Gtk.Button.with_label (_("Log In")); - login_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); + login_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); bind_property ("connecting", login_button, "sensitive", INVERT_BOOLEAN); var login_button_session_button = new Greeter.SessionButton () { @@ -94,16 +83,16 @@ public class Greeter.UserCard : Greeter.BaseCard { }; var login_box = new Gtk.Box (HORIZONTAL, 6); - login_box.add (login_button); - login_box.add (login_button_session_button); + login_box.append (login_button); + login_box.append (login_button_session_button); var disabled_box = new Gtk.Box (HORIZONTAL, 6) { halign = Gtk.Align.CENTER, margin_top = 3 }; - disabled_box.add (new Gtk.Image.from_icon_name ("changes-prevent-symbolic", MENU)); - disabled_box.add (new Gtk.Label (_("Account disabled"))); - disabled_box.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); + disabled_box.append (new Gtk.Image.from_icon_name ("changes-prevent-symbolic")); + disabled_box.append (new Gtk.Label (_("Account disabled"))); + disabled_box.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); login_stack = new Gtk.Stack () { margin_top = 12, @@ -130,29 +119,30 @@ public class Greeter.UserCard : Greeter.BaseCard { ); main_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - margin_bottom = 48 + overflow = HIDDEN }; - // in reverse order because pack_end is used - main_box.pack_end (form_revealer); - main_box.pack_end (username_label); - main_box.get_style_context ().add_class (Granite.STYLE_CLASS_CARD); - main_box.get_style_context ().add_class (Granite.STYLE_CLASS_ROUNDED); + main_box.append (username_label); + main_box.append (form_revealer); + main_box.add_css_class (Granite.STYLE_CLASS_CARD); + main_box.add_css_class (Granite.STYLE_CLASS_ROUNDED); update_collapsed_class (); - var avatar = new Hdy.Avatar (64, lightdm_user.display_name, true) { - margin_top = 6, - margin_bottom = 6, - margin_start = 6, - margin_end = 6, - loadable_icon = new FileIcon (File.new_for_path (lightdm_user.image)) - }; + var avatar = new Adw.Avatar (64, lightdm_user.display_name, true); + + var user_icon_file = File.new_for_path (lightdm_user.image); + try { + avatar.custom_image = Gdk.Texture.from_file (user_icon_file ); + } catch (Error e) { + avatar.custom_image = null; + } var avatar_overlay = new Gtk.Overlay () { halign = CENTER, valign = START, margin_top = 100, - child = avatar + child = avatar, + overflow = VISIBLE }; logged_in = new SelectionCheck () { @@ -189,19 +179,15 @@ public class Greeter.UserCard : Greeter.BaseCard { on_act_user_loaded (); - card_overlay.focus.connect ((direction) => { + card_overlay.move_focus.connect ((direction) => { if (direction == LEFT) { go_left (); - return true; } else if (direction == RIGHT) { go_right (); - return true; } - - return false; }); - click_gesture = new Gtk.GestureMultiPress (this); + var click_gesture = new Gtk.GestureClick (); click_gesture.pressed.connect ((n_press, x, y) => { if (!show_input) { focus_requested (); @@ -209,6 +195,8 @@ public class Greeter.UserCard : Greeter.BaseCard { } }); + add_controller (click_gesture); + notify["show-input"].connect (update_collapsed_class); password_entry.activate.connect (on_login); @@ -222,18 +210,26 @@ public class Greeter.UserCard : Greeter.BaseCard { } }); - grab_focus.connect (() => { - password_entry.grab_focus_without_selecting (); + var focus_controller = new Gtk.EventControllerFocus (); + focus_controller.enter.connect (() => { + if (focus_controller.is_focus) { + password_entry.grab_focus_without_selecting (); + } }); + + add_controller (focus_controller); } private void set_check_style () { // Override check's accent_color so that it *always* uses user's preferred color - logged_in.get_style_context ().add_class (accent_to_string (settings_act.accent_color)); + logged_in.add_css_class (accent_to_string (settings_act.accent_color)); } private void set_background_image () { - Greeter.BackgroundImage background_image; + var background_picture = new Gtk.Picture () { + content_fit = COVER, + height_request = 150 + }; var background_path = lightdm_user.background; var background_exists = ( @@ -248,15 +244,29 @@ public class Greeter.UserCard : Greeter.BaseCard { } if (settings_act.picture_options != 0 && background_exists) { - background_image = new Greeter.BackgroundImage.from_path (background_path); + background_picture.set_filename (background_path); } else if (settings_act.picture_options == 0 && settings_act.primary_color != null) { - background_image = new Greeter.BackgroundImage.from_color (settings_act.primary_color); + Gdk.RGBA rgba_color = {}; + rgba_color.parse (settings_act.primary_color); + + uint32 f = 0x0; + f += (uint) Math.round (rgba_color.red * 255); + f <<= 8; + f += (uint) Math.round (rgba_color.green * 255); + f <<= 8; + f += (uint) Math.round (rgba_color.blue * 255); + f <<= 8; + f += 255; + + var pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, 1, 1); + pixbuf.fill (f); + + background_picture.paintable = (Gdk.Texture.for_pixbuf (pixbuf)); } else { - background_image = new Greeter.BackgroundImage.from_path (null); + background_picture.set_filename ("/usr/share/backgrounds/elementaryos-default"); } - main_box.pack_start (background_image); - main_box.show_all (); + main_box.prepend (background_picture); } private string accent_to_string (int i) { @@ -345,9 +355,9 @@ public class Greeter.UserCard : Greeter.BaseCard { private void update_collapsed_class () { if (show_input) { - main_box.get_style_context ().remove_class ("collapsed"); + main_box.remove_css_class ("collapsed"); } else { - main_box.get_style_context ().add_class ("collapsed"); + main_box.add_css_class ("collapsed"); } } @@ -499,12 +509,12 @@ public class Greeter.UserCard : Greeter.BaseCard { } public override void wrong_credentials () { - password_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_ERROR); - main_box.get_style_context ().add_class ("shake"); + password_entry.add_css_class (Granite.STYLE_CLASS_ERROR); + main_box.add_css_class ("shake"); Timeout.add (ERROR_SHAKE_DURATION, () => { - password_entry.get_style_context ().remove_class (Gtk.STYLE_CLASS_ERROR); - main_box.get_style_context ().remove_class ("shake"); + password_entry.remove_css_class (Granite.STYLE_CLASS_ERROR); + main_box.remove_css_class ("shake"); connecting = false; password_entry.grab_focus (); @@ -512,9 +522,9 @@ public class Greeter.UserCard : Greeter.BaseCard { }); } - private class SelectionCheck : Gtk.Spinner { + private class SelectionCheck : Gtk.Widget { class construct { - set_css_name (Gtk.STYLE_CLASS_CHECK); + set_css_name ("check"); } } } diff --git a/src/MainWindow.vala b/src/MainWindow.vala index d91b7abf..1a847651 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -11,7 +11,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { private Pantheon.Desktop.Greeter? desktop_greeter; private GLib.Queue user_cards; private Gtk.SizeGroup card_size_group; - private Hdy.Carousel carousel; + private Adw.Carousel carousel; private Greeter.Settings settings; private GLib.Settings gsettings; private Gtk.Revealer datetime_revealer; @@ -23,16 +23,12 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { private bool installer_mode = false; - private Gtk.EventControllerKey key_controller; - public MainWindow (LightDM.Greeter lightdm_greeter) { Object (lightdm_greeter: lightdm_greeter); } construct { - app_paintable = true; decorated = false; - set_visual (get_screen ().get_rgba_visual ()); gsettings = new GLib.Settings ("io.elementary.greeter"); settings = new Greeter.Settings (); @@ -51,10 +47,10 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { vexpand = true }; if (lightdm_greeter.has_guest_account_hint) { - extra_login_box.add (guest_login_button); + extra_login_box.append (guest_login_button); } if (lightdm_greeter.show_manual_login_hint) { - extra_login_box.add (manual_login_button); + extra_login_box.append (manual_login_button); } datetime_widget = new Greeter.DateTimeWidget (); @@ -70,7 +66,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { var manual_card = new Greeter.ManualCard (); - carousel = new Hdy.Carousel () { + carousel = new Adw.Carousel () { allow_long_swipes = true, vexpand = true }; @@ -78,16 +74,16 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { var manual_login_stack = new Gtk.Stack () { transition_type = Gtk.StackTransitionType.CROSSFADE }; - manual_login_stack.add (carousel); - manual_login_stack.add (manual_card); + manual_login_stack.add_child (carousel); + manual_login_stack.add_child (manual_card); var main_box = new Gtk.Box (VERTICAL, 24) { margin_top = 24, margin_bottom = 24 }; - main_box.add (datetime_revealer); - main_box.add (manual_login_stack); - main_box.add (extra_login_box); + main_box.append (datetime_revealer); + main_box.append (manual_login_stack); + main_box.append (extra_login_box); child = main_box; @@ -146,9 +142,12 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { manual_card.do_connect_username.connect (do_connect_username); manual_card.do_connect.connect (do_connect); - key_controller = new Gtk.EventControllerKey (this) { + var key_controller = new Gtk.EventControllerKey () { propagation_phase = CAPTURE }; + + ((Gtk.Widget) this).add_controller (key_controller); + key_controller.key_pressed.connect ((keyval, keycode, state) => { if (!(current_card is UserCard)) { return Gdk.EVENT_PROPAGATE; @@ -181,9 +180,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { }); carousel.page_changed.connect ((index) => { - var children = carousel.get_children (); - - if (children.nth_data (index) is Greeter.UserCard) { + if (carousel.get_nth_page (index) is Greeter.UserCard) { current_user_card_index = (int) index; } }); @@ -193,7 +190,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { * at boot. TODO: Find whether boot sequence can be tweaked to fix this. */ Timeout.add (500, () => { - get_style_context ().add_class ("initialized"); + add_css_class ("initialized"); if (current_card != null) { current_card.grab_focus (); @@ -246,9 +243,9 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { public void registry_handle_global (Wl.Registry wl_registry, uint32 name, string @interface, uint32 version) { if (@interface == "io_elementary_pantheon_shell_v1") { var desktop_shell = wl_registry.bind (name, ref Pantheon.Desktop.Shell.iface, uint32.min (version, 1)); - unowned var window = get_window (); - if (window is Gdk.Wayland.Window) { - unowned var wl_surface = ((Gdk.Wayland.Window) window).get_wl_surface (); + unowned var surface = get_surface (); + if (surface is Gdk.Wayland.Surface) { + unowned var wl_surface = ((Gdk.Wayland.Surface) surface).get_wl_surface (); desktop_greeter = desktop_shell.get_greeter (wl_surface); desktop_greeter.init (); } @@ -260,7 +257,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { if (display is Gdk.X11.Display) { unowned var xdisplay = ((Gdk.X11.Display) display).get_xdisplay (); - var window = ((Gdk.X11.Window) get_window ()).get_xid (); + var window = ((Gdk.X11.Surface) get_surface ()).get_xid (); var prop = xdisplay.intern_atom ("_MUTTER_HINTS", false); @@ -407,9 +404,8 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { private void add_card (LightDM.User lightdm_user) { var user_card = new Greeter.UserCard (lightdm_user); - user_card.show_all (); - carousel.add (user_card); + carousel.append (user_card); user_card.focus_requested.connect (() => { switch_to_card (user_card); @@ -450,7 +446,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { current_card = user_card; - carousel.scroll_to (user_card); + carousel.scroll_to (user_card, true); user_card.set_settings (); user_card.show_input = true; @@ -501,7 +497,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { } carousel.interactive = false; - carousel.scroll_to (current_card); + carousel.scroll_to (current_card, true); } private void go_previous () { @@ -511,7 +507,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { unowned Greeter.UserCard? next_card = user_cards.peek_nth (current_user_card_index - 1); if (next_card != null) { - carousel.scroll_to (next_card); + carousel.scroll_to (next_card, true); } } @@ -522,7 +518,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { unowned Greeter.UserCard? next_card = user_cards.peek_nth (current_user_card_index + 1); if (next_card != null) { - carousel.scroll_to (next_card); + carousel.scroll_to (next_card, true); } } } diff --git a/src/Widgets/BackgroundImage.vala b/src/Widgets/BackgroundImage.vala deleted file mode 100644 index c52274ca..00000000 --- a/src/Widgets/BackgroundImage.vala +++ /dev/null @@ -1,89 +0,0 @@ -public class Greeter.BackgroundImage : Gtk.EventBox { - private uint last_size_hash = 0; - private Gdk.Pixbuf full_pixbuf; - private Gdk.Pixbuf fitting_pixbuf; - - construct { - height_request = 150; - } - - public BackgroundImage.from_path (string? path) { - if (path == null) { - path = "/usr/share/backgrounds/elementaryos-default"; - } - - try { - full_pixbuf = new Gdk.Pixbuf.from_file (path); - } catch (GLib.Error e) { - critical (e.message); - critical ("Fallback to default wallpaper"); - - try { - full_pixbuf = new Gdk.Pixbuf.from_file ("/usr/share/backgrounds/elementaryos-default"); - } catch (GLib.Error e) { - critical (e.message); - } - } - } - - public BackgroundImage.from_color (string color) { - full_pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, 1, 1); - - Gdk.RGBA rgba_color = {}; - rgba_color.parse (color); - - uint32 f = 0x0; - f += (uint) Math.round (rgba_color.red * 255); - f <<= 8; - f += (uint) Math.round (rgba_color.green * 255); - f <<= 8; - f += (uint) Math.round (rgba_color.blue * 255); - f <<= 8; - f += 255; - - full_pixbuf.fill (f); - } - - public override bool draw (Cairo.Context cr) { - var scale = get_scale_factor (); - var width = get_allocated_width () * scale; - var height = get_allocated_height () * scale; - var radius = 5 * scale; // Off-by-one to prevent light bleed - - var new_hash = GLib.int_hash (width) + GLib.int_hash (height); - if (new_hash != last_size_hash) { - last_size_hash = new_hash; - double full_ratio = (double)full_pixbuf.height / (double)full_pixbuf.width; - fitting_pixbuf = new Gdk.Pixbuf (full_pixbuf.colorspace, full_pixbuf.has_alpha, full_pixbuf.bits_per_sample, width, height); - - // Get a scaled pixbuf that preserves aspect ratio but is at least as big as the desired destination pixbuf - Gdk.Pixbuf scaled_pixbuf; - if ((int)(width * full_ratio) < height) { - scaled_pixbuf = full_pixbuf.scale_simple ((int)(width * (1 / full_ratio)), height, Gdk.InterpType.BILINEAR); - } else { - scaled_pixbuf = full_pixbuf.scale_simple (width, (int)(width * full_ratio), Gdk.InterpType.BILINEAR); - } - - // Find the offset we need to center the source pixbuf on the destination - int y = ((height - scaled_pixbuf.height) / 2).abs (); - int x = ((width - scaled_pixbuf.width) / 2).abs (); - - scaled_pixbuf.copy_area (x, y, width, height, fitting_pixbuf, 0, 0); - } - - cr.save (); - cr.scale (1.0 / scale, 1.0 / scale); - cr.new_sub_path (); - cr.arc (width - radius, radius, radius, -Math.PI_2, 0); - cr.line_to (width, height); - cr.line_to (0, height); - - cr.arc (radius, radius, radius, Math.PI, Math.PI + Math.PI_2); - cr.close_path (); - Gdk.cairo_set_source_pixbuf (cr, fitting_pixbuf, 0, 0); - cr.clip (); - cr.paint (); - cr.restore (); - return true; - } -} diff --git a/src/Widgets/CapsLockRevealer.vala b/src/Widgets/CapsLockRevealer.vala index 71125a50..e9154751 100644 --- a/src/Widgets/CapsLockRevealer.vala +++ b/src/Widgets/CapsLockRevealer.vala @@ -3,26 +3,28 @@ * SPDX-FileCopyrightText: 2018-2025 elementary, Inc. (https://elementary.io) */ -public class Greeter.CapsLockRevealer : Gtk.Bin { +public class Greeter.CapsLockRevealer : Granite.Bin { + private Gdk.Device device; private Gtk.Image caps_lock_image; private Gtk.Image num_lock_image; private Gtk.Label lock_label; private Gtk.Revealer revealer; construct { - caps_lock_image = new Gtk.Image.from_icon_name ("input-keyboard-capslock-symbolic", MENU); - num_lock_image = new Gtk.Image.from_icon_name ("input-keyboard-numlock-symbolic", MENU); + caps_lock_image = new Gtk.Image.from_icon_name ("input-keyboard-capslock-symbolic"); + num_lock_image = new Gtk.Image.from_icon_name ("input-keyboard-numlock-symbolic"); + lock_label = new Gtk.Label (null); - lock_label.get_style_context ().add_class (Granite.STYLE_CLASS_SMALL_LABEL); + lock_label.add_css_class (Granite.STYLE_CLASS_SMALL_LABEL); var caps_lock_box = new Gtk.Box (HORIZONTAL, 3) { halign = CENTER }; - caps_lock_box.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - caps_lock_box.add (caps_lock_image); - caps_lock_box.add (num_lock_image); - caps_lock_box.add (lock_label); + caps_lock_box.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); + caps_lock_box.append (caps_lock_image); + caps_lock_box.append (num_lock_image); + caps_lock_box.append (lock_label); revealer = new Gtk.Revealer () { child = caps_lock_box, @@ -31,20 +33,18 @@ public class Greeter.CapsLockRevealer : Gtk.Bin { child = revealer; - var keymap = Gdk.Keymap.get_for_display (Gdk.Display.get_default ()); - keymap.state_changed.connect (update_visibility); + device = Gdk.Display.get_default ().get_default_seat ().get_keyboard (); + device.changed.connect (update_visibility); - update_visibility (keymap); + update_visibility (); } - private void update_visibility (Gdk.Keymap keymap) { - var caps_lock = keymap.get_caps_lock_state (); - var num_lock = keymap.get_num_lock_state (); + private void update_visibility () { + var caps_lock = device.get_caps_lock_state (); + var num_lock = device.get_num_lock_state (); revealer.reveal_child = caps_lock || num_lock; - caps_lock_image.no_show_all = !caps_lock; - num_lock_image.no_show_all = !num_lock; caps_lock_image.visible = caps_lock; num_lock_image.visible = num_lock; diff --git a/src/Widgets/DateTimeWidget.vala b/src/Widgets/DateTimeWidget.vala index b4d4f801..238ea1ed 100644 --- a/src/Widgets/DateTimeWidget.vala +++ b/src/Widgets/DateTimeWidget.vala @@ -27,14 +27,14 @@ public class Greeter.DateTimeWidget : Gtk.Box { construct { time_label = new Gtk.Label (null); - time_label.get_style_context ().add_class ("time"); + time_label.add_css_class ("time"); date_label = new Gtk.Label (null); - date_label.get_style_context ().add_class ("date"); + date_label.add_css_class ("date"); orientation = VERTICAL; - add (time_label); - add (date_label); + append (time_label); + append (date_label); update_labels (); diff --git a/src/Widgets/PasswordEntry.vala b/src/Widgets/PasswordEntry.vala index f9bd6a26..83cb1d8b 100644 --- a/src/Widgets/PasswordEntry.vala +++ b/src/Widgets/PasswordEntry.vala @@ -29,8 +29,8 @@ public class Greeter.PasswordEntry : Gtk.Entry { visibility = false; input_purpose = Gtk.InputPurpose.PASSWORD; - icon_press.connect ((pos, event) => { - if (pos == Gtk.EntryIconPosition.SECONDARY) { + icon_press.connect ((pos) => { + if (pos == SECONDARY) { activate (); } }); diff --git a/src/Widgets/SessionButton.vala b/src/Widgets/SessionButton.vala index f21b5f52..852824d3 100644 --- a/src/Widgets/SessionButton.vala +++ b/src/Widgets/SessionButton.vala @@ -5,7 +5,7 @@ * Authors: Corentin Noël */ -public class Greeter.SessionButton : Gtk.Bin { +public class Greeter.SessionButton : Granite.Bin { construct { var menu = new GLib.Menu (); unowned var application = (Gtk.Application) GLib.Application.get_default (); @@ -18,11 +18,11 @@ public class Greeter.SessionButton : Gtk.Bin { } var menu_button = new Gtk.MenuButton () { - child = new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.BUTTON), direction = DOWN, + has_frame = false, + icon_name = "open-menu-symbolic", menu_model = menu }; - menu_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); child = menu_button; } diff --git a/src/meson.build b/src/meson.build index 7d196b8b..ebe2aa00 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,12 +1,12 @@ actservice_dep = dependency('accountsservice') gobject_dep = dependency('gobject-2.0') glib_dep = dependency('glib-2.0') -gdk_wl_dep = dependency('gdk-wayland-3.0') -gdk_x11_dep = dependency('gdk-x11-3.0') +gdk_wl_dep = dependency('gtk4-wayland') +gdk_x11_dep = dependency('gtk4-x11') gnome_desktop_dep = dependency('gnome-desktop-3.0') -gtk_dep = dependency('gtk+-3.0') -granite_dep = dependency('granite', version: '>= 5.5.0') -hdy_dep = dependency('libhandy-1', version: '>= 1.1.90') +gtk_dep = dependency('gtk4') +granite_dep = dependency('granite-7', version: '>= 7.0.0') +adw_dep = dependency('libadwaita-1', version: '>= 1.0.0') lightdm_dep = dependency('liblightdm-gobject-1') m_dep = meson.get_compiler('c').find_library('m') wl_client_dep = dependency('wayland-client') @@ -26,13 +26,12 @@ executable( 'Cards/BaseCard.vala', 'Cards/ManualCard.vala', 'Cards/UserCard.vala', - 'Widgets/BackgroundImage.vala', 'Widgets/CapsLockRevealer.vala', 'Widgets/DateTimeWidget.vala', 'Widgets/PasswordEntry.vala', 'Widgets/SessionButton.vala', config_header, - dependencies: [ actservice_dep, gobject_dep, glib_dep, gdk_wl_dep, gdk_x11_dep, gtk_dep, granite_dep, hdy_dep, lightdm_dep, m_dep, pantheon_desktop_shell_dep, wl_client_dep, x11_dep ], + dependencies: [ actservice_dep, gobject_dep, glib_dep, gdk_wl_dep, gdk_x11_dep, gtk_dep, granite_dep, adw_dep, lightdm_dep, m_dep, pantheon_desktop_shell_dep, wl_client_dep, x11_dep ], install : true, install_dir: install_path )