gp-lock-screen-applet.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /*
  2. * Copyright (C) 2020 Alberts Muktupāvels
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "config.h"
  18. #include "gp-lock-screen-applet.h"
  19. #include <gio/gdesktopappinfo.h>
  20. #include <glib/gi18n-lib.h>
  21. #include "gpab-screensaver-gen.h"
  22. struct _GpLockScreenApplet
  23. {
  24. GpActionButtonApplet parent;
  25. GDesktopAppInfo *lock_panel;
  26. GpabScreensaverGen *screensaver;
  27. };
  28. G_DEFINE_TYPE (GpLockScreenApplet,
  29. gp_lock_screen_applet,
  30. GP_TYPE_ACTION_BUTTON_APPLET)
  31. static void
  32. error_response_cb (GtkWidget *widget,
  33. int response_id,
  34. gpointer user_data)
  35. {
  36. gtk_widget_destroy (widget);
  37. }
  38. static void
  39. show_error_message (GtkWindow *parent,
  40. const char *primary_text,
  41. const char *secondary_text)
  42. {
  43. GtkWidget *dialog;
  44. dialog = gtk_message_dialog_new (parent,
  45. GTK_DIALOG_DESTROY_WITH_PARENT,
  46. GTK_MESSAGE_ERROR,
  47. GTK_BUTTONS_CLOSE,
  48. "%s",
  49. primary_text);
  50. gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
  51. "%s",
  52. secondary_text);
  53. g_signal_connect (dialog, "response", G_CALLBACK (error_response_cb), NULL);
  54. gtk_window_present (GTK_WINDOW (dialog));
  55. }
  56. static void
  57. lockdown_changed (GpLockScreenApplet *self)
  58. {
  59. GpLockdownFlags lockdowns;
  60. gboolean applet_sensitive;
  61. gboolean properties_enabled;
  62. GAction *action;
  63. lockdowns = gp_applet_get_lockdowns (GP_APPLET (self));
  64. applet_sensitive = TRUE;
  65. if ((lockdowns & GP_LOCKDOWN_FLAGS_APPLET) == GP_LOCKDOWN_FLAGS_APPLET ||
  66. (lockdowns & GP_LOCKDOWN_FLAGS_LOCK_SCREEN) == GP_LOCKDOWN_FLAGS_LOCK_SCREEN)
  67. applet_sensitive = FALSE;
  68. gtk_widget_set_sensitive (GTK_WIDGET (self), applet_sensitive);
  69. action = gp_applet_menu_lookup_action (GP_APPLET (self), "lock-screen");
  70. g_simple_action_set_enabled (G_SIMPLE_ACTION (action), applet_sensitive);
  71. properties_enabled = (lockdowns & GP_LOCKDOWN_FLAGS_LOCKED_DOWN) != GP_LOCKDOWN_FLAGS_LOCKED_DOWN &&
  72. (lockdowns & GP_LOCKDOWN_FLAGS_LOCK_SCREEN) != GP_LOCKDOWN_FLAGS_LOCK_SCREEN &&
  73. self->lock_panel != NULL;
  74. action = gp_applet_menu_lookup_action (GP_APPLET (self), "properties");
  75. g_simple_action_set_enabled (G_SIMPLE_ACTION (action), properties_enabled);
  76. }
  77. static void
  78. lockdowns_cb (GpApplet *applet,
  79. GParamSpec *pspec,
  80. GpLockScreenApplet *self)
  81. {
  82. lockdown_changed (self);
  83. }
  84. static void
  85. lock_cb (GObject *source,
  86. GAsyncResult *res,
  87. gpointer user_data)
  88. {
  89. GError *error;
  90. error = NULL;
  91. gpab_screensaver_gen_call_lock_finish (GPAB_SCREENSAVER_GEN (source),
  92. res,
  93. &error);
  94. if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
  95. {
  96. g_error_free (error);
  97. return;
  98. }
  99. if (error)
  100. {
  101. g_warning ("Could not ask screensaver to lock: %s",
  102. error->message);
  103. g_error_free (error);
  104. return;
  105. }
  106. }
  107. static void
  108. lock_screen (GpLockScreenApplet *self)
  109. {
  110. if (!self->screensaver)
  111. {
  112. g_warning ("Screensaver service not available.");
  113. return;
  114. }
  115. gpab_screensaver_gen_call_lock (self->screensaver,
  116. NULL,
  117. lock_cb,
  118. self);
  119. }
  120. static void
  121. lock_screen_cb (GSimpleAction *action,
  122. GVariant *parameter,
  123. gpointer user_data)
  124. {
  125. lock_screen (GP_LOCK_SCREEN_APPLET (user_data));
  126. }
  127. static void
  128. set_active_cb (GObject *source,
  129. GAsyncResult *res,
  130. gpointer user_data)
  131. {
  132. GError *error;
  133. error = NULL;
  134. gpab_screensaver_gen_call_set_active_finish (GPAB_SCREENSAVER_GEN (source),
  135. res,
  136. &error);
  137. if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
  138. {
  139. g_error_free (error);
  140. return;
  141. }
  142. if (error)
  143. {
  144. g_warning ("Could not ask screensaver to activate: %s",
  145. error->message);
  146. g_error_free (error);
  147. return;
  148. }
  149. }
  150. static void
  151. screensaver_cb (GSimpleAction *action,
  152. GVariant *parameter,
  153. gpointer user_data)
  154. {
  155. GpLockScreenApplet *self;
  156. self = GP_LOCK_SCREEN_APPLET (user_data);
  157. if (!self->screensaver)
  158. {
  159. g_warning ("Screensaver service not available.");
  160. return;
  161. }
  162. gpab_screensaver_gen_call_set_active (self->screensaver,
  163. TRUE,
  164. NULL,
  165. set_active_cb,
  166. self);
  167. }
  168. static void
  169. child_setup (gpointer user_data)
  170. {
  171. GAppInfo *info;
  172. const gchar *id;
  173. gint stdout_fd;
  174. gint stderr_fd;
  175. info = G_APP_INFO (user_data);
  176. id = g_app_info_get_id (info);
  177. }
  178. static void
  179. close_pid (GPid pid,
  180. gint status,
  181. gpointer user_data)
  182. {
  183. g_spawn_close_pid (pid);
  184. }
  185. static void
  186. pid_cb (GDesktopAppInfo *info,
  187. GPid pid,
  188. gpointer user_data)
  189. {
  190. g_child_watch_add (pid, close_pid, NULL);
  191. }
  192. static void
  193. properties_cb (GSimpleAction *action,
  194. GVariant *parameter,
  195. gpointer user_data)
  196. {
  197. GpLockScreenApplet *self;
  198. GSpawnFlags flags;
  199. GError *error;
  200. self = GP_LOCK_SCREEN_APPLET (user_data);
  201. g_assert (self->lock_panel != NULL);
  202. flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD;
  203. error = NULL;
  204. g_desktop_app_info_launch_uris_as_manager (self->lock_panel,
  205. NULL,
  206. NULL,
  207. flags,
  208. child_setup,
  209. self->lock_panel,
  210. pid_cb,
  211. NULL,
  212. &error);
  213. if (error != NULL)
  214. {
  215. show_error_message (NULL,
  216. _("Could not launch application"),
  217. error->message);
  218. g_error_free (error);
  219. }
  220. }
  221. static const GActionEntry lock_screen_menu_actions[] =
  222. {
  223. { "lock-screen", lock_screen_cb, NULL, NULL, NULL },
  224. { "screensaver", screensaver_cb, NULL, NULL, NULL },
  225. { "properties", properties_cb, NULL, NULL, NULL },
  226. { NULL }
  227. };
  228. static void
  229. setup_menu (GpLockScreenApplet *self)
  230. {
  231. GpApplet *applet;
  232. const char *resource;
  233. applet = GP_APPLET (self);
  234. resource = "/org/gnome/gnome-panel/modules/action-button/gp-lock-screen-menu.ui";
  235. gp_applet_setup_menu_from_resource (applet, resource, lock_screen_menu_actions);
  236. lockdown_changed (self);
  237. }
  238. static void
  239. setup_applet (GpLockScreenApplet *self)
  240. {
  241. const char *text;
  242. AtkObject *atk;
  243. setup_menu (self);
  244. gp_action_button_applet_set_icon_name (GP_ACTION_BUTTON_APPLET (self),
  245. "system-lock-screen");
  246. text = _("Protect your computer from unauthorized use");
  247. atk = gtk_widget_get_accessible (GTK_WIDGET (self));
  248. atk_object_set_name (atk, text);
  249. atk_object_set_description (atk, text);
  250. gtk_widget_set_tooltip_text (GTK_WIDGET (self), text);
  251. g_object_bind_property (self,
  252. "enable-tooltips",
  253. self,
  254. "has-tooltip",
  255. G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
  256. lockdown_changed (self);
  257. }
  258. static void
  259. screensaver_proxy_ready_cb (GObject *source_object,
  260. GAsyncResult *res,
  261. gpointer user_data)
  262. {
  263. GError *error;
  264. GpabScreensaverGen *screensaver;
  265. GpLockScreenApplet *self;
  266. error = NULL;
  267. screensaver = gpab_screensaver_gen_proxy_new_for_bus_finish (res, &error);
  268. if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
  269. {
  270. g_error_free (error);
  271. return;
  272. }
  273. self = GP_LOCK_SCREEN_APPLET (user_data);
  274. self->screensaver = screensaver;
  275. if (error)
  276. {
  277. g_warning ("%s", error->message);
  278. g_error_free (error);
  279. return;
  280. }
  281. }
  282. static void
  283. gp_lock_screen_applet_constructed (GObject *object)
  284. {
  285. G_OBJECT_CLASS (gp_lock_screen_applet_parent_class)->constructed (object);
  286. setup_applet (GP_LOCK_SCREEN_APPLET (object));
  287. }
  288. static void
  289. gp_lock_screen_applet_dispose (GObject *object)
  290. {
  291. GpLockScreenApplet *self;
  292. self = GP_LOCK_SCREEN_APPLET (object);
  293. g_clear_object (&self->lock_panel);
  294. g_clear_object (&self->screensaver);
  295. G_OBJECT_CLASS (gp_lock_screen_applet_parent_class)->dispose (object);
  296. }
  297. static void
  298. gp_lock_screen_applet_clicked (GpActionButtonApplet *applet)
  299. {
  300. lock_screen (GP_LOCK_SCREEN_APPLET (applet));
  301. }
  302. static void
  303. gp_lock_screen_applet_class_init (GpLockScreenAppletClass *self_class)
  304. {
  305. GObjectClass *object_class;
  306. GpActionButtonAppletClass *action_button_applet_class;
  307. object_class = G_OBJECT_CLASS (self_class);
  308. action_button_applet_class = GP_ACTION_BUTTON_APPLET_CLASS (self_class);
  309. object_class->constructed = gp_lock_screen_applet_constructed;
  310. object_class->dispose = gp_lock_screen_applet_dispose;
  311. action_button_applet_class->clicked = gp_lock_screen_applet_clicked;
  312. }
  313. static void
  314. gp_lock_screen_applet_init (GpLockScreenApplet *self)
  315. {
  316. self->lock_panel = g_desktop_app_info_new ("gnome-lock-panel.desktop");
  317. gpab_screensaver_gen_proxy_new_for_bus (G_BUS_TYPE_SESSION,
  318. G_DBUS_PROXY_FLAGS_NONE,
  319. "org.gnome.ScreenSaver",
  320. "/org/gnome/ScreenSaver",
  321. NULL,
  322. screensaver_proxy_ready_cb,
  323. self);
  324. g_signal_connect (self,
  325. "notify::lockdowns",
  326. G_CALLBACK (lockdowns_cb),
  327. self);
  328. }
  329. gboolean
  330. gp_lock_screen_applet_is_disabled (GpLockdownFlags flags,
  331. char **reason)
  332. {
  333. if ((flags & GP_LOCKDOWN_FLAGS_LOCK_SCREEN) != GP_LOCKDOWN_FLAGS_LOCK_SCREEN)
  334. return FALSE;
  335. *reason = g_strdup (_("Disabled because “disable-lock-screen” setting in "
  336. "“org.gnome.desktop.lockdown” GSettings schema is "
  337. "set to true."));
  338. return TRUE;
  339. }