diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e2d7354..6dcfb8a8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y desktop-file-utils libgdk-pixbuf-2.0-dev libgnome-desktop-3-dev libgranite-dev libgtk-3-dev libhandy-1-dev libjson-glib-dev liblightdm-gobject-1-dev ${{ matrix.mutter_pkg }} libsoup-3.0-dev libx11-dev ${{ matrix.lightdm_vala }} meson valac + apt install -y desktop-file-utils libaccountsservice-dev libgdk-pixbuf-2.0-dev libgnome-desktop-3-dev libgranite-dev libgtk-3-dev libhandy-1-dev libjson-glib-dev liblightdm-gobject-1-dev ${{ matrix.mutter_pkg }} libsoup-3.0-dev libx11-dev ${{ matrix.lightdm_vala }} meson valac - name: Build env: DESTDIR: out @@ -50,7 +50,7 @@ jobs: - uses: actions/checkout@v7 - name: Install Dependencies run: | - dnf install -y desktop-file-utils gdk-pixbuf2-devel gnome-desktop3-devel granite-devel gtk3-devel libhandy-devel lightdm-gobject-devel mutter-devel libX11-devel meson valac + dnf install -y accountsservice-devel desktop-file-utils gdk-pixbuf2-devel gnome-desktop3-devel granite-devel gtk3-devel libhandy-devel lightdm-gobject-devel mutter-devel libX11-devel meson valac - name: Build env: DESTDIR: out @@ -69,7 +69,7 @@ jobs: run: | zypper addrepo https://download.opensuse.org/repositories/X11:Pantheon/16.0/X11:Pantheon.repo zypper --gpg-auto-import-keys refresh - zypper --non-interactive install tar git desktop-file-utils gdk-pixbuf-devel libgnome-desktop-3-devel granite6-devel gtk3-devel libhandy-devel lightdm-gobject-devel mutter-devel meson vala gcc + zypper --non-interactive install accountsservice-devel accountsservice-vala tar git desktop-file-utils gdk-pixbuf-devel libgnome-desktop-3-devel granite6-devel gtk3-devel libhandy-devel lightdm-gobject-devel mutter-devel meson vala gcc - uses: actions/checkout@v7 - name: Build env: diff --git a/src/Application.vala b/src/Application.vala index ba7440ee..162211b5 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -1,5 +1,5 @@ /* - * Copyright 2018-2024 elementary, Inc. (https://elementary.io) + * Copyright 2018-2026 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 @@ -111,6 +111,9 @@ public class Greeter.Application : Gtk.Application { } public static int main (string[] args) { + // Connect to UserManager as early as possible + Act.UserManager.get_default (); + return new Greeter.Application ().run (args); } } diff --git a/src/Cards/BaseCard.vala b/src/Cards/BaseCard.vala index 2128e511..d7d61392 100644 --- a/src/Cards/BaseCard.vala +++ b/src/Cards/BaseCard.vala @@ -1,19 +1,19 @@ /* * SPDX-License-Identifier: GPL-2.0-or-later - * SPDX-FileCopyrightText: 2018-2025 elementary, Inc. (https://elementary.io) + * SPDX-FileCopyrightText: 2018-2026 elementary, Inc. (https://elementary.io) * * Authors: Corentin Noël */ public abstract class Greeter.BaseCard : Gtk.Bin { - public signal void do_connect (string? credential = null); + public signal void start_authentication (string username); + public signal void provide_credential (string credential); public signal void go_left (); public signal void go_right (); protected const int ERROR_SHAKE_DURATION = 450; public bool connecting { get; set; default = false; } - public bool need_password { get; set; default = false; } public bool use_fingerprint { get; set; default = false; } construct { @@ -34,5 +34,8 @@ public abstract class Greeter.BaseCard : Gtk.Bin { return base.focus (direction); } + public virtual void on_selected () {} + public virtual void on_deselected () {} + public abstract void wrong_credentials (); } diff --git a/src/Cards/ManualCard.vala b/src/Cards/ManualCard.vala index cae3c34a..1084d447 100644 --- a/src/Cards/ManualCard.vala +++ b/src/Cards/ManualCard.vala @@ -1,11 +1,9 @@ /* - * Copyright 2018-2023 elementary, Inc. (https://elementary.io) + * Copyright 2018-2026 elementary, Inc. (https://elementary.io) * SPDX-License-Identifier: GPL-2.0-or-later */ public class Greeter.ManualCard : Greeter.BaseCard { - public signal void do_connect_username (string username); - private Greeter.PasswordEntry password_entry; private Gtk.Entry username_entry; private Gtk.Box main_box; @@ -70,7 +68,7 @@ public class Greeter.ManualCard : Greeter.BaseCard { username_entry.focus_out_event.connect (() => { if (username_entry.text != "") { - do_connect_username (username_entry.text); + start_authentication (username_entry.text); } }); @@ -83,7 +81,7 @@ public class Greeter.ManualCard : Greeter.BaseCard { } connecting = true; - do_connect (password_entry.text); + provide_credential (password_entry.text); } public override void wrong_credentials () { diff --git a/src/Cards/UserCard.vala b/src/Cards/UserCard.vala index d60d00cd..d620a3cd 100644 --- a/src/Cards/UserCard.vala +++ b/src/Cards/UserCard.vala @@ -1,13 +1,20 @@ /* - * Copyright 2018-2025 elementary, Inc. (https://elementary.io) + * Copyright 2018-2026 elementary, Inc. (https://elementary.io) * SPDX-License-Identifier: GPL-3.0-or-later * * Authors: Corentin Noël */ public class Greeter.UserCard : Greeter.BaseCard { - public LightDM.User lightdm_user { get; construct; } - public bool show_input { get; set; default = false; } + private const int PASSWORD_MODE_REGULAR = 0; + private const int PASSWORD_MODE_SET_AT_NEXT_LOGIN = 1; + private const int PASSWORD_MODE_NO_PASSWORD = 2; + + /** + * We use Act.User instead of LightDM.User because lightdm is unmaintained + * and lacks some fields from Act.User such as `password_mode`. + */ + public Act.User user { get; construct; } public bool is_24h { get; set; default = true; } // TODO: In Gtk4 remove this gesture and move it to MainWindow public Gtk.GestureMultiPress click_gesture { get; private set; } @@ -15,7 +22,6 @@ public class Greeter.UserCard : Greeter.BaseCard { private Pantheon.AccountsService greeter_act; private Pantheon.SettingsDaemon.AccountsService settings_act; - private Gtk.Label username_label; private Gtk.Revealer form_revealer; private Gtk.Stack login_stack; private Greeter.PasswordEntry password_entry; @@ -23,14 +29,12 @@ public class Greeter.UserCard : Greeter.BaseCard { private SelectionCheck logged_in; - public UserCard (LightDM.User lightdm_user) { - Object (lightdm_user: lightdm_user); + public UserCard (Act.User user) requires (user.is_loaded) { + Object (user: user); } construct { - need_password = true; - - username_label = new Gtk.Label (lightdm_user.display_name) { + var username_label = new Gtk.Label (user.real_name) { hexpand = true, margin_top = 24, margin_bottom = 12, @@ -38,6 +42,7 @@ public class Greeter.UserCard : Greeter.BaseCard { margin_end = 24, }; username_label.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL); + user.bind_property ("locked", username_label, "sensitive", SYNC_CREATE); password_entry = new Greeter.PasswordEntry (); bind_property ("connecting", password_entry, "sensitive", INVERT_BOOLEAN); @@ -59,7 +64,9 @@ public class Greeter.UserCard : Greeter.BaseCard { password_grid.attach (password_session_button, 2, 0); password_grid.attach (new Greeter.CapsLockRevealer (), 0, 1, 3); - var login_button = new Gtk.Button.with_label (_("Log In")); + var login_button = new Gtk.Button.with_label (_("Log In")) { + hexpand = true + }; login_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); bind_property ("connecting", login_button, "sensitive", INVERT_BOOLEAN); @@ -86,16 +93,15 @@ public class Greeter.UserCard : Greeter.BaseCard { margin_end = 24 }; login_stack.add_named (password_grid, "password"); - login_stack.add_named (login_button, "button"); + login_stack.add_named (login_box, "button"); login_stack.add_named (disabled_box, "disabled"); form_revealer = new Gtk.Revealer () { margin_bottom = 12, - reveal_child = true, + reveal_child = false, transition_type = SLIDE_DOWN, child = login_stack }; - bind_property ("show-input", form_revealer, "reveal-child", SYNC_CREATE); main_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { margin_bottom = 48 @@ -105,15 +111,14 @@ public class Greeter.UserCard : Greeter.BaseCard { 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.get_style_context ().add_class ("collapsed"); - update_collapsed_class (); - - var avatar = new Hdy.Avatar (64, lightdm_user.display_name, true) { + var avatar = new Hdy.Avatar (64, user.real_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)) + loadable_icon = new FileIcon (File.new_for_path (user.icon_file)) }; var avatar_overlay = new Gtk.Overlay () { @@ -128,7 +133,7 @@ public class Greeter.UserCard : Greeter.BaseCard { valign = END }; - if (lightdm_user.logged_in) { + if (user.is_logged_in ()) { avatar_overlay.add_overlay (logged_in); password_session_button.sensitive = false; @@ -149,18 +154,20 @@ public class Greeter.UserCard : Greeter.BaseCard { child = card_overlay; - connect_to_dbus_interfaces (); - lightdm_user.changed.connect (update_is_locked_ui); - notify["need-password"].connect (update_is_locked_ui); + show_all (); - click_gesture = new Gtk.GestureMultiPress (this); + user.notify["locked"].connect (update_is_locked_ui); + user.notify["password-mode"].connect (update_is_locked_ui); + update_is_locked_ui (); - notify["show-input"].connect (update_collapsed_class); + click_gesture = new Gtk.GestureMultiPress (this); password_entry.activate.connect (on_login); login_button.clicked.connect (on_login); grab_focus.connect (password_entry.grab_focus_without_selecting); + + connect_to_dbus_interfaces (); } private void set_check_style () { @@ -168,24 +175,27 @@ public class Greeter.UserCard : Greeter.BaseCard { logged_in.get_style_context ().add_class (accent_to_string (settings_act.accent_color)); } + private string generate_background_image_path () { + if (settings_act.picture_options == 0) { + return ""; + } + + var path = Path.build_filename ("/", "var", "lib", "lightdm-data", user.user_name, "wallpaper"); + if (FileUtils.test (path, EXISTS) && FileUtils.test (path, IS_REGULAR)) { + return path; + } + + return "/usr/share/backgrounds/elementaryos-default"; + } + private void set_background_image () { Greeter.BackgroundImage background_image; - var background_path = lightdm_user.background; - var background_exists = ( - background_path != null && - FileUtils.test (background_path, EXISTS) && - FileUtils.test (background_path, IS_REGULAR) - ); - - if (!background_exists) { - background_path = Path.build_filename ("/", "var", "lib", "lightdm-data", lightdm_user.name, "wallpaper"); - background_exists = FileUtils.test (background_path, EXISTS) && FileUtils.test (background_path, IS_REGULAR); - } + var background_path = generate_background_image_path (); - if (settings_act.picture_options != 0 && background_exists) { + if (settings_act.picture_options != 0) { background_image = new Greeter.BackgroundImage.from_path (background_path); - } else if (settings_act.picture_options == 0 && settings_act.primary_color != null) { + } else if (settings_act.primary_color != null) { background_image = new Greeter.BackgroundImage.from_color (settings_act.primary_color); } else { background_image = new Greeter.BackgroundImage.from_path (null); @@ -223,7 +233,7 @@ public class Greeter.UserCard : Greeter.BaseCard { } private void connect_to_dbus_interfaces () { - var account_path = "/org/freedesktop/Accounts/User%d".printf ((int )lightdm_user.uid); + var account_path = "/org/freedesktop/Accounts/User%d".printf (user.uid); try { greeter_act = Bus.get_proxy_sync ( SYSTEM, @@ -246,18 +256,12 @@ public class Greeter.UserCard : Greeter.BaseCard { set_background_image (); set_check_style (); - update_is_locked_ui (); } private void update_is_locked_ui () { - // lightdm_user.is_locked prints warnings so let's use a getter method here - var is_locked = lightdm_user.get_is_locked (); - - username_label.sensitive = !is_locked; - - if (is_locked) { + if (user.locked) { login_stack.visible_child_name = "disabled"; - } else if (need_password) { + } else if (user.password_mode != PASSWORD_MODE_NO_PASSWORD) { login_stack.visible_child_name = "password"; } else { login_stack.visible_child_name = "button"; @@ -270,22 +274,15 @@ public class Greeter.UserCard : Greeter.BaseCard { } connecting = true; - if (need_password) { - do_connect (password_entry.text); - } else { - do_connect (); - } - } - private void update_collapsed_class () { - if (show_input) { - main_box.get_style_context ().remove_class ("collapsed"); + if (user.password_mode != PASSWORD_MODE_NO_PASSWORD) { + provide_credential (password_entry.text); } else { - main_box.get_style_context ().add_class ("collapsed"); + start_authentication (user.user_name); } } - public void set_settings () { + private void set_settings () { set_keyboard_layouts (); set_mouse_touchpad_settings (); set_interface_settings (); @@ -378,7 +375,7 @@ public class Greeter.UserCard : Greeter.BaseCard { var background_settings = new GLib.Settings ("org.gnome.desktop.background"); background_settings.set_enum ("picture-options", settings_act.picture_options); - set_or_reset_settings_key (background_settings, "picture-uri", lightdm_user.background); + set_or_reset_settings_key (background_settings, "picture-uri", generate_background_image_path ()); set_or_reset_settings_key (background_settings, "primary-color", settings_act.primary_color); } @@ -426,6 +423,23 @@ public class Greeter.UserCard : Greeter.BaseCard { SettingsPortal.get_default ().prefers_color_scheme = greeter_act.prefers_color_scheme; } + public override void on_selected () { + form_revealer.reveal_child = true; + main_box.get_style_context ().remove_class ("collapsed"); + + set_settings (); + grab_focus (); + + if (user.password_mode != PASSWORD_MODE_NO_PASSWORD) { + start_authentication (user.user_name); + } + } + + public override void on_deselected () { + form_revealer.reveal_child = false; + main_box.get_style_context ().add_class ("collapsed"); + } + public override void wrong_credentials () { password_entry.get_style_context ().add_class (Gtk.STYLE_CLASS_ERROR); main_box.get_style_context ().add_class ("shake"); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 616ae938..db87a78e 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: GPL-2.0-or-later - * SPDX-FileCopyrightText: 2018-2025 elementary, Inc. (https://elementary.io) + * SPDX-FileCopyrightText: 2018-2026 elementary, Inc. (https://elementary.io) * * Authors: Corentin Noël */ @@ -16,7 +16,6 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { private GLib.Settings gsettings; private Gtk.Revealer datetime_revealer; private Greeter.DateTimeWidget datetime_widget; - private unowned LightDM.UserList lightdm_user_list; private int current_user_card_index = -1; private unowned Greeter.BaseCard? current_card = null; @@ -92,31 +91,17 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { child = main_box; manual_login_button.toggled.connect (() => { - if (manual_login_button.active) { - if (lightdm_greeter.in_authentication) { - try { - lightdm_greeter.cancel_authentication (); - } catch (Error e) { - critical (e.message); - } - } + cancel_authentication (); + if (manual_login_button.active) { manual_login_stack.visible_child = manual_card; current_card = manual_card; } else { - if (lightdm_greeter.in_authentication) { - try { - lightdm_greeter.cancel_authentication (); - } catch (Error e) { - critical (e.message); - } - } - manual_login_stack.visible_child = carousel; current_card = user_cards.peek_nth (current_user_card_index); try { - lightdm_greeter.authenticate (((UserCard) current_card).lightdm_user.name); + lightdm_greeter.authenticate (((UserCard) current_card).user.user_name); } catch (Error e) { critical (e.message); } @@ -138,13 +123,17 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { lightdm_greeter.bind_property ("hide-users-hint", manual_login_button, "sensitive", GLib.BindingFlags.SYNC_CREATE | GLib.BindingFlags.INVERT_BOOLEAN); lightdm_greeter.bind_property ("hide-users-hint", manual_login_button, "active", GLib.BindingFlags.SYNC_CREATE); - lightdm_user_list = LightDM.UserList.get_instance (); - lightdm_user_list.user_added.connect (() => { - load_users.begin (); - }); + unowned var user_manager = Act.UserManager.get_default (); + user_manager.user_added.connect (() => load_users.begin ()); + + if (user_manager.is_loaded) { + load_users.begin (show_greeter_window); + } else { + user_manager.notify["is-loaded"].connect (() => load_users.begin (show_greeter_window)); + } - manual_card.do_connect_username.connect (do_connect_username); - manual_card.do_connect.connect (do_connect); + manual_card.start_authentication.connect (do_connect_username); + manual_card.provide_credential.connect (do_connect); key_controller = new Gtk.EventControllerKey (this) { propagation_phase = CAPTURE @@ -182,21 +171,6 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { carousel.page_changed.connect (handle_page_changed); - load_users.begin (() => { - /* A significant delay is required in order for the window and card to be focused at - * at boot. TODO: Find whether boot sequence can be tweaked to fix this. - */ - Timeout.add (500, () => { - get_style_context ().add_class ("initialized"); - - if (current_card != null) { - current_card.grab_focus (); - } - - return Source.REMOVE; - }); - }); - maximize (); if (settings.activate_numlock) { @@ -210,6 +184,19 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { main_box.realize.connect (init_panel); } + /* A significant delay is required in order for the window and card to be focused at boot. + * TODO: Find whether boot sequence can be tweaked to fix this. + */ + private void show_greeter_window () { + Timeout.add (500, () => { + get_style_context ().add_class ("initialized"); + + current_card?.grab_focus (); + + return Source.REMOVE; + }); + } + private void init_panel () { if (Gdk.Display.get_default () is Gdk.Wayland.Display) { // We have to wrap in Idle otherwise the Meta.Window of the WaylandSurface in Gala is still null @@ -292,7 +279,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { private void authentication_complete () { var user_card = current_card as Greeter.UserCard; if (user_card != null) { - gsettings.set_string ("last-user", user_card.lightdm_user.name); + gsettings.set_string ("last-user", user_card.user.user_name); } if (lightdm_greeter.is_authenticated) { @@ -330,7 +317,7 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { if (user_card != null) { try { - lightdm_greeter.authenticate (user_card.lightdm_user.name); + lightdm_greeter.authenticate (user_card.user.user_name); } catch (Error e) { critical (e.message); } @@ -341,35 +328,32 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { carousel.interactive = true; } - private async void load_users () { + private async void load_users () requires (Act.UserManager.get_default ().is_loaded) { // Check if the installer is installed var installer_desktop = new DesktopAppInfo ("io.elementary.installer.desktop"); if (installer_desktop != null) { installer_mode = true; } - if (lightdm_user_list.length > 0) { - datetime_revealer.reveal_child = true; + var users_list = Act.UserManager.get_default ().list_users (); + if (users_list.length () > 0) { + users_list.foreach (add_card); - lightdm_user_list.users.foreach ((user) => { - add_card (user); - }); + datetime_revealer.reveal_child = true; unowned string? select_user = lightdm_greeter.select_user_hint; var user_to_select = select_user != null ? select_user : gsettings.get_string ("last-user"); - bool user_selected = false; + var user_selected = false; user_cards.head.foreach ((card) => { - if (card.lightdm_user.name == user_to_select) { + if (card.user.user_name == user_to_select) { carousel.scroll_to (card); user_selected = true; } }); if (!user_selected) { - unowned var user_card = user_cards.peek_head (); - user_card.show_input = true; - carousel.scroll_to (user_card); + carousel.scroll_to (user_cards.peek_head ()); } } else { datetime_revealer.reveal_child = false; @@ -399,19 +383,12 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { } } - private void add_card (LightDM.User lightdm_user) { - var user_card = new Greeter.UserCard (lightdm_user); + private void add_card (Act.User user) { + var user_card = new Greeter.UserCard (user); user_card.show_all (); - user_card.do_connect.connect (do_connect); - user_card.click_gesture.pressed.connect ((gesture, n_press, x, y) => { - assert (gesture.widget is UserCard); - - var _user_card = (UserCard) gesture.widget; - if (!_user_card.show_input) { - carousel.scroll_to (_user_card); - _user_card.grab_focus (); - } - }); + user_card.start_authentication.connect (do_connect_username); + user_card.provide_credential.connect (do_connect); + user_card.click_gesture.pressed.connect ((gesture, n_press, x, y) => carousel.scroll_to (gesture.widget)); user_card.go_left.connect (() => { if (Gtk.StateFlags.DIR_LTR in get_state_flags ()) { go_previous (); @@ -434,32 +411,24 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { } private void handle_page_changed (uint index) { - if (index == current_user_card_index) { - return; - } + cancel_authentication (); unowned var user_card = user_cards.peek_nth (index); if (user_card == null) { return; } - if (current_card != null && current_card is UserCard) { - ((UserCard) current_card).show_input = false; - } + current_card?.on_deselected (); current_user_card_index = (int) index; current_card = user_card; datetime_widget.is_24h = user_card.is_24h; - user_card.set_settings (); - user_card.show_input = true; - user_card.grab_focus (); - - if (user_card.lightdm_user.session != null) { - application.activate_action ("select-session", new GLib.Variant.string (user_card.lightdm_user.session)); - } + user_card.on_selected (); + } + private void cancel_authentication () { if (lightdm_greeter.in_authentication) { try { lightdm_greeter.cancel_authentication (); @@ -467,22 +436,10 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { critical (e.message); } } - - try { - lightdm_greeter.authenticate (user_card.lightdm_user.name); - } catch (Error e) { - critical (e.message); - } } private void do_connect_username (string username) { - if (lightdm_greeter.in_authentication) { - try { - lightdm_greeter.cancel_authentication (); - } catch (Error e) { - critical (e.message); - } - } + cancel_authentication (); try { lightdm_greeter.authenticate (username); @@ -491,17 +448,14 @@ public class Greeter.MainWindow : Gtk.ApplicationWindow { } } - private void do_connect (string? credential) { - if (credential != null) { - try { - lightdm_greeter.respond (credential); - } catch (Error e) { - critical (e.message); - } + private void do_connect (string credential) { + try { + lightdm_greeter.respond (credential); + } catch (Error e) { + critical (e.message); } carousel.interactive = false; - carousel.scroll_to (current_card); } private void go_previous () { diff --git a/src/meson.build b/src/meson.build index 4b5059d6..50c87f9d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,3 +1,4 @@ +accountsservice_dep = dependency('accountsservice') gobject_dep = dependency('gobject-2.0') glib_dep = dependency('glib-2.0') gdk_wl_dep = dependency('gdk-wayland-3.0') @@ -31,7 +32,7 @@ executable( 'Widgets/PasswordEntry.vala', 'Widgets/SessionButton.vala', config_header, - dependencies: [ 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: [ accountsservice_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 ], install : true, install_dir: install_path )