gf-application.c 12 KB
Newer Older
1
/*
2
 * Copyright (C) 2014-2020 Alberts Muktupāvels
3
4
5
6
7
8
9
10
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
13
14
15
16
17
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

18
19
#include "config.h"

20
21
#include <glib/gi18n.h>
#include <gtk/gtk.h>
22

23
#include "gf-application.h"
24
#include "gf-confirm-display-change-dialog.h"
25
#include "backends/gf-backend.h"
26
#include "liba11y-keyboard/gf-a11y-keyboard.h"
27
#include "libaudio-device-selection/gf-audio-device-selection.h"
Balló György's avatar
Balló György committed
28
#include "libautomount-manager/gsd-automount-manager.h"
29
#include "libdesktop/gf-desktop.h"
30
#include "libend-session-dialog/gf-end-session-dialog.h"
31
#include "libidle-monitor/flashback-idle-monitor.h"
32
#include "libinput-settings/gf-input-settings.h"
33
#include "libinput-sources/gf-input-sources.h"
34
#include "libnotifications/gf-notifications.h"
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
35
#include "libpolkit/flashback-polkit.h"
36
#include "libroot-background/gf-root-background.h"
37
#include "libscreencast/gf-screencast.h"
38
#include "libscreensaver/gf-screensaver.h"
39
#include "libscreenshot/gf-screenshot.h"
40
#include "libshell/flashback-shell.h"
41
#include "libstatus-notifier-watcher/gf-status-notifier-watcher.h"
42

43
struct _GfApplication
44
{
45
46
  GObject                  parent;

47
48
  GfBackend               *backend;

49
50
51
52
53
54
55
56
57
58
  gint                     bus_name;

  GSettings               *settings;

  GtkStyleProvider        *provider;

  GsdAutomountManager     *automount;
  FlashbackIdleMonitor    *idle_monitor;
  FlashbackPolkit         *polkit;
  FlashbackShell          *shell;
59
  GfA11yKeyboard          *a11y_keyboard;
60
  GfAudioDeviceSelection  *audio_device_selection;
61
  GfDesktop               *desktop;
62
63
64
65
  GfEndSessionDialog      *dialog;
  GfInputSettings         *input_settings;
  GfInputSources          *input_sources;
  GfNotifications         *notifications;
66
  GfRootBackground        *root_background;
67
68
69
70
  GfScreencast            *screencast;
  GfScreensaver           *screensaver;
  GfScreenshot            *screenshot;
  GfStatusNotifierWatcher *status_notifier_watcher;
71
72

  GtkWidget               *display_change_dialog;
73
74
};

75
G_DEFINE_TYPE (GfApplication, gf_application, G_TYPE_OBJECT)
76

Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
77
78
79
80
81
82
83
84
85
86
87
88
89
typedef struct
{
  const char *name;
  const char *dir;
  const char *variant;
  gboolean    has_dark_variant;
} GfSupportedTheme;

static GfSupportedTheme supported_themes[] =
  {
    { "Adwaita", "Adwaita", NULL, TRUE },
    { "Adwaita-dark", "Adwaita", "dark", FALSE },
    { "HighContrast", "HighContrast", NULL, FALSE },
90
    { "HighContrastInverse", "HighContrast", "inverse", FALSE },
Dmitry Shachnev's avatar
Dmitry Shachnev committed
91
92
93
    { "Yaru", "Yaru", NULL, FALSE },
    { "Yaru-light", "Yaru", NULL, FALSE },
    { "Yaru-dark", "Yaru", NULL, FALSE },
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    { NULL, NULL, FALSE, FALSE }
  };

static char *
get_theme_resource (GfSupportedTheme *theme,
                    gboolean          prefer_dark)
{
  char *filename;
  const char *resource_base;
  char *resource;

  if (theme->variant != NULL)
    filename = g_strdup_printf ("gnome-flashback-%s.css", theme->variant);
  else if (theme->has_dark_variant && prefer_dark)
    filename = g_strdup ("gnome-flashback-dark.css");
  else
    filename = g_strdup ("gnome-flashback.css");

  resource_base = "/org/gnome/gnome-flashback/theme";
  resource = g_strdup_printf ("%s/%s/%s", resource_base, theme->dir, filename);
  g_free (filename);

  return resource;
}

static gboolean
is_theme_supported (const char        *theme_name,
                    GfSupportedTheme **theme)
{
  int i;

  for (i = 0; supported_themes[i].name != NULL; i++)
    {
      if (g_strcmp0 (supported_themes[i].name, theme_name) == 0)
        {
          *theme = &supported_themes[i];
          return TRUE;
        }
    }

  return FALSE;
}

137
138
static void
theme_changed (GtkSettings *settings,
139
140
               GParamSpec  *pspec,
               gpointer     user_data)
141
{
142
  GfApplication *application;
143
  GdkScreen *screen;
144
  gchar *theme_name;
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
145
146
  gboolean prefer_dark;
  GfSupportedTheme *theme;
147
  gchar *resource;
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
148
  guint priority;
149
  GtkCssProvider *css;
150

151
  application = GF_APPLICATION (user_data);
152
153
  screen = gdk_screen_get_default ();

154
155
156
157
158
  if (application->provider != NULL)
    {
      gtk_style_context_remove_provider_for_screen (screen, application->provider);
      g_clear_object (&application->provider);
    }
159

160
161
  g_object_get (settings,
                "gtk-theme-name", &theme_name,
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
162
                "gtk-application-prefer-dark-theme", &prefer_dark,
163
                NULL);
164

Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
165
  if (is_theme_supported (theme_name, &theme))
166
    {
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
167
168
      resource = get_theme_resource (theme, prefer_dark);
      priority = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
169
170
171
    }
  else
    {
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
172
173
      resource = g_strdup ("/org/gnome/gnome-flashback/theme/fallback.css");
      priority = GTK_STYLE_PROVIDER_PRIORITY_FALLBACK;
174
    }
175

176
177
  css = gtk_css_provider_new ();
  application->provider =  GTK_STYLE_PROVIDER (css);
178

179
180
181
  gtk_css_provider_load_from_resource (css, resource);
  gtk_style_context_add_provider_for_screen (screen, application->provider,
                                             priority);
182

183
184
  g_free (theme_name);
  g_free (resource);
185
186
187
188
189
190
}

static void
settings_changed (GSettings   *settings,
                  const gchar *key,
                  gpointer     user_data)
191
{
192
  GfApplication *application;
193
  GfMonitorManager *monitor_manager;
194

195
  application = GF_APPLICATION (user_data);
196
  monitor_manager = gf_backend_get_monitor_manager (application->backend);
197
198

#define SETTING_CHANGED(variable_name, setting_name, function_name) \
199
  if (key == NULL || g_strcmp0 (key, setting_name) == 0)            \
200
201
202
203
204
205
206
207
208
209
210
211
212
    {                                                               \
      if (g_settings_get_boolean (settings, setting_name))          \
        {                                                           \
          if (application->variable_name == NULL)                   \
            application->variable_name = function_name ();          \
        }                                                           \
      else                                                          \
        {                                                           \
          g_clear_object (&application->variable_name);             \
        }                                                           \
    }

  SETTING_CHANGED (automount, "automount-manager", gsd_automount_manager_new)
213
  SETTING_CHANGED (idle_monitor, "idle-monitor", flashback_idle_monitor_new)
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
214
  SETTING_CHANGED (polkit, "polkit", flashback_polkit_new)
215
  SETTING_CHANGED (shell, "shell", flashback_shell_new)
216
  SETTING_CHANGED (a11y_keyboard, "a11y-keyboard", gf_a11y_keyboard_new)
217
  SETTING_CHANGED (audio_device_selection, "audio-device-selection", gf_audio_device_selection_new)
218
  SETTING_CHANGED (desktop, "desktop", gf_desktop_new)
219
  SETTING_CHANGED (dialog, "end-session-dialog", gf_end_session_dialog_new)
220
  SETTING_CHANGED (input_settings, "input-settings", gf_input_settings_new)
221
  SETTING_CHANGED (input_sources, "input-sources", gf_input_sources_new)
222
  SETTING_CHANGED (notifications, "notifications", gf_notifications_new)
223
  SETTING_CHANGED (root_background, "root-background", gf_root_background_new)
224
  SETTING_CHANGED (screencast, "screencast", gf_screencast_new)
225
  SETTING_CHANGED (screensaver, "screensaver", gf_screensaver_new)
226
  SETTING_CHANGED (screenshot, "screenshot", gf_screenshot_new)
227
  SETTING_CHANGED (status_notifier_watcher, "status-notifier-watcher", gf_status_notifier_watcher_new)
228

229
230
#undef SETTING_CHANGED

231
  if (application->input_settings)
232
233
    gf_input_settings_set_monitor_manager (application->input_settings,
                                           monitor_manager);
234

235
236
237
238
239
240
  if (application->screensaver)
    {
      gf_screensaver_set_input_sources (application->screensaver,
                                        application->input_sources);
    }

241
  if (application->shell)
242
    flashback_shell_set_monitor_manager (application->shell, monitor_manager);
243
244
}

245
static void
246
gf_application_dispose (GObject *object)
247
{
248
  GfApplication *application;
249

250
  application = GF_APPLICATION (object);
251
252
253
254
255
256
257
258
259

  if (application->bus_name)
    {
      g_bus_unown_name (application->bus_name);
      application->bus_name = 0;
    }

  g_clear_object (&application->settings);

260
  g_clear_object (&application->provider);
261

262
  g_clear_object (&application->automount);
263
  g_clear_object (&application->idle_monitor);
Alberts Muktupāvels's avatar
Alberts Muktupāvels committed
264
  g_clear_object (&application->polkit);
265
  g_clear_object (&application->shell);
266
  g_clear_object (&application->a11y_keyboard);
267
  g_clear_object (&application->audio_device_selection);
268
  g_clear_object (&application->desktop);
269
  g_clear_object (&application->dialog);
270
  g_clear_object (&application->input_settings);
271
  g_clear_object (&application->input_sources);
272
  g_clear_object (&application->notifications);
273
  g_clear_object (&application->root_background);
274
  g_clear_object (&application->screencast);
275
  g_clear_object (&application->screenshot);
276
  g_clear_object (&application->screensaver);
277
  g_clear_object (&application->status_notifier_watcher);
278

279
280
  g_clear_pointer (&application->display_change_dialog, gtk_widget_destroy);

281
282
  g_clear_object (&application->backend);

283
  G_OBJECT_CLASS (gf_application_parent_class)->dispose (object);
284
285
}

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
static void
keep_changes_cb (GfConfirmDisplayChangeDialog *dialog,
                 gboolean                      keep_changes,
                 GfApplication                *application)
{
  GfMonitorManager *monitor_manager;

  monitor_manager = gf_backend_get_monitor_manager (application->backend);

  gf_monitor_manager_confirm_configuration (monitor_manager, keep_changes);
  g_clear_pointer (&application->display_change_dialog, gtk_widget_destroy);
}

static void
confirm_display_change_cb (GfMonitorManager *monitor_manager,
                           GfApplication    *application)
{
  gint timeout;

  timeout = gf_monitor_manager_get_display_configuration_timeout ();

  g_clear_pointer (&application->display_change_dialog, gtk_widget_destroy);
  application->display_change_dialog = gf_confirm_display_change_dialog_new (timeout);

  g_signal_connect (application->display_change_dialog, "keep-changes",
                    G_CALLBACK (keep_changes_cb), application);

  gtk_window_present (GTK_WINDOW (application->display_change_dialog));
}

316
static void
317
gf_application_init (GfApplication *application)
318
{
319
  GtkSettings *settings;
320
  GfMonitorManager *monitor_manager;
321

322
323
  application->backend = gf_backend_new (GF_BACKEND_TYPE_X11_CM);

324
325
326
327
  monitor_manager = gf_backend_get_monitor_manager (application->backend);
  g_signal_connect (monitor_manager, "confirm-display-change",
                    G_CALLBACK (confirm_display_change_cb), application);

328
  application->settings = g_settings_new ("org.gnome.gnome-flashback");
329
  settings = gtk_settings_get_default ();
330
331

  g_signal_connect (application->settings, "changed",
332
333
334
                    G_CALLBACK (settings_changed), application);
  g_signal_connect (settings, "notify::gtk-theme-name",
                    G_CALLBACK (theme_changed), application);
335

336
  theme_changed (settings, NULL, application);
337
  settings_changed (application->settings, NULL, application);
338
339
340
341
342
343

  application->bus_name = g_bus_own_name (G_BUS_TYPE_SESSION,
                                          "org.gnome.Shell",
                                          G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
                                          G_BUS_NAME_OWNER_FLAGS_REPLACE,
                                          NULL, NULL, NULL, NULL, NULL);
344
345
346
}

static void
347
gf_application_class_init (GfApplicationClass *application_class)
348
{
349
  GObjectClass *object_class;
350

351
  object_class = G_OBJECT_CLASS (application_class);
352

353
  object_class->dispose = gf_application_dispose;
354
355
}

356
357
GfApplication *
gf_application_new (void)
358
{
359
  return g_object_new (GF_TYPE_APPLICATION, NULL);
360
}