1 /*
2  * pluma-app.c
3  * This file is part of pluma
4  *
5  * Copyright (C) 2005-2006 - Paolo Maggi
6  * Copyright (C) 2012-2021 MATE Developers
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 /*
25  * Modified by the pluma Team, 2005. See the AUTHORS file for a
26  * list of people on the pluma Team.
27  * See the ChangeLog files for a list of changes.
28  *
29  * $Id$
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include <glib/gi18n.h>
40 #include <libpeas/peas-extension-set.h>
41 #include <gdk/gdk.h>
42 #include <gdk/gdkx.h>
43 
44 #include "pluma-app.h"
45 #include "pluma-commands.h"
46 #include "pluma-notebook.h"
47 #include "pluma-debug.h"
48 #include "pluma-utils.h"
49 #include "pluma-enum-types.h"
50 #include "pluma-dirs.h"
51 #include "pluma-settings.h"
52 #include "pluma-app-activatable.h"
53 #include "pluma-plugins-engine.h"
54 
55 #define PLUMA_PAGE_SETUP_FILE      "pluma-page-setup"
56 #define PLUMA_PRINT_SETTINGS_FILE  "pluma-print-settings"
57 
58 /* Properties */
59 enum
60 {
61     PROP_0,
62     PROP_LOCKDOWN
63 };
64 
65 struct _PlumaAppPrivate
66 {
67     GList              *windows;
68     PlumaWindow        *active_window;
69 
70     PlumaLockdownMask  lockdown;
71 
72     GtkPageSetup      *page_setup;
73     GtkPrintSettings  *print_settings;
74 
75     GSettings         *window_settings;
76 
77     PeasExtensionSet  *extensions;
78 };
79 
G_DEFINE_TYPE_WITH_PRIVATE(PlumaApp,pluma_app,G_TYPE_OBJECT)80 G_DEFINE_TYPE_WITH_PRIVATE (PlumaApp, pluma_app, G_TYPE_OBJECT)
81 
82 static void
83 pluma_app_finalize (GObject *object)
84 {
85     PlumaApp *app = PLUMA_APP (object);
86 
87     g_list_free (app->priv->windows);
88 
89     if (app->priv->page_setup)
90         g_object_unref (app->priv->page_setup);
91     if (app->priv->print_settings)
92         g_object_unref (app->priv->print_settings);
93 
94     G_OBJECT_CLASS (pluma_app_parent_class)->finalize (object);
95 }
96 
97 static void
pluma_app_dispose(GObject * object)98 pluma_app_dispose (GObject *object)
99 {
100     PlumaApp *app = PLUMA_APP (object);
101 
102     g_clear_object (&app->priv->window_settings);
103     g_clear_object (&app->priv->extensions);
104 
105     G_OBJECT_CLASS (pluma_app_parent_class)->dispose (object);
106 }
107 
108 
109 static void
pluma_app_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)110 pluma_app_get_property (GObject    *object,
111                         guint       prop_id,
112                         GValue     *value,
113                         GParamSpec *pspec)
114 {
115     PlumaApp *app = PLUMA_APP (object);
116 
117     switch (prop_id)
118     {
119         case PROP_LOCKDOWN:
120             g_value_set_flags (value, pluma_app_get_lockdown (app));
121             break;
122         default:
123             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124             break;
125     }
126 }
127 
128 static void
pluma_app_class_init(PlumaAppClass * klass)129 pluma_app_class_init (PlumaAppClass *klass)
130 {
131     GObjectClass *object_class = G_OBJECT_CLASS (klass);
132 
133     object_class->finalize = pluma_app_finalize;
134     object_class->dispose = pluma_app_dispose;
135     object_class->get_property = pluma_app_get_property;
136 
137     g_object_class_install_property (object_class,
138                                      PROP_LOCKDOWN,
139                                      g_param_spec_flags ("lockdown",
140                                                          "Lockdown",
141                                                          "The lockdown mask",
142                                                          PLUMA_TYPE_LOCKDOWN_MASK,
143                                                          0,
144                                                          G_PARAM_READABLE |
145                                                          G_PARAM_STATIC_STRINGS));
146 }
147 
148 static gboolean
ensure_user_config_dir(void)149 ensure_user_config_dir (void)
150 {
151     gchar *config_dir;
152     gboolean ret = TRUE;
153     gint res;
154 
155     config_dir = pluma_dirs_get_user_config_dir ();
156     if (config_dir == NULL)
157     {
158         g_warning ("Could not get config directory\n");
159         return FALSE;
160     }
161 
162     res = g_mkdir_with_parents (config_dir, 0755);
163     if (res < 0)
164     {
165         g_warning ("Could not create config directory\n");
166         ret = FALSE;
167     }
168 
169     g_free (config_dir);
170 
171     return ret;
172 }
173 
174 static void
load_accels(void)175 load_accels (void)
176 {
177     gchar *filename;
178 
179     filename = pluma_dirs_get_user_accels_file ();
180     if (filename != NULL)
181     {
182         pluma_debug_message (DEBUG_APP, "Loading keybindings from %s\n", filename);
183         gtk_accel_map_load (filename);
184         g_free (filename);
185     }
186 }
187 
188 static void
save_accels(void)189 save_accels (void)
190 {
191     gchar *filename;
192 
193     filename = pluma_dirs_get_user_accels_file ();
194     if (filename != NULL)
195     {
196         pluma_debug_message (DEBUG_APP, "Saving keybindings in %s\n", filename);
197         gtk_accel_map_save (filename);
198         g_free (filename);
199     }
200 }
201 
202 static gchar *
get_page_setup_file(void)203 get_page_setup_file (void)
204 {
205     gchar *config_dir;
206     gchar *setup = NULL;
207 
208     config_dir = pluma_dirs_get_user_config_dir ();
209 
210     if (config_dir != NULL)
211     {
212         setup = g_build_filename (config_dir,
213                                   PLUMA_PAGE_SETUP_FILE,
214                                   NULL);
215         g_free (config_dir);
216     }
217 
218     return setup;
219 }
220 
221 static void
load_page_setup(PlumaApp * app)222 load_page_setup (PlumaApp *app)
223 {
224     gchar *filename;
225     GError *error = NULL;
226 
227     g_return_if_fail (app->priv->page_setup == NULL);
228 
229     filename = get_page_setup_file ();
230 
231     app->priv->page_setup = gtk_page_setup_new_from_file (filename, &error);
232     if (error)
233     {
234         /* Ignore file not found error */
235         if (error->domain != G_FILE_ERROR ||
236             error->code != G_FILE_ERROR_NOENT)
237         {
238             g_warning ("%s", error->message);
239         }
240 
241         g_error_free (error);
242     }
243 
244     g_free (filename);
245 
246     /* fall back to default settings */
247     if (app->priv->page_setup == NULL)
248         app->priv->page_setup = gtk_page_setup_new ();
249 }
250 
251 static void
save_page_setup(PlumaApp * app)252 save_page_setup (PlumaApp *app)
253 {
254     gchar *filename;
255     GError *error = NULL;
256 
257     if (app->priv->page_setup == NULL)
258         return;
259 
260     filename = get_page_setup_file ();
261 
262     gtk_page_setup_to_file (app->priv->page_setup,
263                             filename,
264                             &error);
265     if (error)
266     {
267         g_warning ("%s", error->message);
268         g_error_free (error);
269     }
270 
271     g_free (filename);
272 }
273 
274 static gchar *
get_print_settings_file(void)275 get_print_settings_file (void)
276 {
277     gchar *config_dir;
278     gchar *settings = NULL;
279 
280     config_dir = pluma_dirs_get_user_config_dir ();
281 
282     if (config_dir != NULL)
283     {
284         settings = g_build_filename (config_dir,
285                                      PLUMA_PRINT_SETTINGS_FILE,
286                                      NULL);
287         g_free (config_dir);
288     }
289 
290     return settings;
291 }
292 
293 static void
load_print_settings(PlumaApp * app)294 load_print_settings (PlumaApp *app)
295 {
296     gchar *filename;
297     GError *error = NULL;
298 
299     g_return_if_fail (app->priv->print_settings == NULL);
300 
301     filename = get_print_settings_file ();
302 
303     app->priv->print_settings = gtk_print_settings_new_from_file (filename,
304                                                                   &error);
305     if (error)
306     {
307         /* Ignore file not found error */
308         if (error->domain != G_FILE_ERROR ||
309             error->code != G_FILE_ERROR_NOENT)
310         {
311             g_warning ("%s", error->message);
312         }
313 
314         g_error_free (error);
315     }
316 
317     g_free (filename);
318 
319     /* fall back to default settings */
320     if (app->priv->print_settings == NULL)
321         app->priv->print_settings = gtk_print_settings_new ();
322 }
323 
324 static void
save_print_settings(PlumaApp * app)325 save_print_settings (PlumaApp *app)
326 {
327     gchar *filename;
328     GError *error = NULL;
329 
330     if (app->priv->print_settings == NULL)
331         return;
332 
333     filename = get_print_settings_file ();
334 
335     gtk_print_settings_to_file (app->priv->print_settings,
336                                 filename,
337                                 &error);
338     if (error)
339     {
340         g_warning ("%s", error->message);
341         g_error_free (error);
342     }
343 
344     g_free (filename);
345 }
346 
347 static void
extension_added(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,PlumaApp * app)348 extension_added (PeasExtensionSet *extensions,
349                  PeasPluginInfo   *info,
350                  PeasExtension    *exten,
351                  PlumaApp         *app)
352 {
353     peas_extension_call (exten, "activate");
354 }
355 
356 static void
extension_removed(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,PlumaApp * app)357 extension_removed (PeasExtensionSet *extensions,
358                    PeasPluginInfo   *info,
359                    PeasExtension    *exten,
360                    PlumaApp         *app)
361 {
362     peas_extension_call (exten, "deactivate");
363 }
364 
365 
366 static void
pluma_app_init(PlumaApp * app)367 pluma_app_init (PlumaApp *app)
368 {
369     PlumaSettings *settings;
370 
371     app->priv = pluma_app_get_instance_private (app);
372 
373     load_accels ();
374 
375     /* Load/init settings */
376     settings = _pluma_settings_get_singleton ();
377     app->priv->window_settings = g_settings_new (PLUMA_SCHEMA_ID);
378 
379     /* initial lockdown state */
380     app->priv->lockdown = pluma_settings_get_lockdown (settings);
381 
382     app->priv->extensions = peas_extension_set_new (PEAS_ENGINE (pluma_plugins_engine_get_default ()),
383                                                     PLUMA_TYPE_APP_ACTIVATABLE,
384                                                     "app", app,
385                                                     NULL);
386 
387     g_signal_connect (app->priv->extensions, "extension-added",
388                       G_CALLBACK (extension_added),
389                       app);
390 
391     g_signal_connect (app->priv->extensions, "extension-removed",
392                       G_CALLBACK (extension_removed),
393                       app);
394 
395     peas_extension_set_call (app->priv->extensions, "activate");
396 }
397 
398 /**
399  * pluma_app_get_default:
400  *
401  * Returns the #PlumaApp object. This object is a singleton and
402  * represents the running pluma instance.
403  *
404  * Return value: (transfer none): the #PlumaApp pointer
405  */
406 PlumaApp *
pluma_app_get_default(void)407 pluma_app_get_default (void)
408 {
409     static PlumaApp *app = NULL;
410 
411     if (app != NULL)
412         return app;
413 
414     app = PLUMA_APP (g_object_new (PLUMA_TYPE_APP, NULL));
415 
416     g_object_add_weak_pointer (G_OBJECT (app), (gpointer) &app);
417 
418     return app;
419 }
420 
421 static void
set_active_window(PlumaApp * app,PlumaWindow * window)422 set_active_window (PlumaApp    *app,
423                    PlumaWindow *window)
424 {
425     app->priv->active_window = window;
426 }
427 
428 static gboolean
window_focus_in_event(PlumaWindow * window,GdkEventFocus * event,PlumaApp * app)429 window_focus_in_event (PlumaWindow   *window,
430                        GdkEventFocus *event,
431                        PlumaApp      *app)
432 {
433     /* updates active_view and active_child when a new toplevel receives focus */
434     g_return_val_if_fail (PLUMA_IS_WINDOW (window), FALSE);
435 
436     set_active_window (app, window);
437 
438     return FALSE;
439 }
440 
441 static gboolean
window_delete_event(PlumaWindow * window,GdkEvent * event,PlumaApp * app)442 window_delete_event (PlumaWindow *window,
443                      GdkEvent    *event,
444                      PlumaApp    *app)
445 {
446     PlumaWindowState ws;
447 
448     ws = pluma_window_get_state (window);
449 
450     if (ws &
451         (PLUMA_WINDOW_STATE_SAVING |
452          PLUMA_WINDOW_STATE_PRINTING |
453          PLUMA_WINDOW_STATE_SAVING_SESSION))
454             return TRUE;
455 
456     _pluma_cmd_file_quit (NULL, window);
457 
458     /* Do not destroy the window */
459     return TRUE;
460 }
461 
462 static void
window_destroy(PlumaWindow * window,PlumaApp * app)463 window_destroy (PlumaWindow *window,
464                 PlumaApp    *app)
465 {
466     app->priv->windows = g_list_remove (app->priv->windows, window);
467 
468     if (window == app->priv->active_window)
469     {
470         set_active_window (app, app->priv->windows != NULL ? app->priv->windows->data : NULL);
471     }
472 
473 /* CHECK: I don't think we have to disconnect this function, since windows
474    is being destroyed */
475 /*
476     g_signal_handlers_disconnect_by_func (window,
477                           G_CALLBACK (window_focus_in_event),
478                           app);
479     g_signal_handlers_disconnect_by_func (window,
480                           G_CALLBACK (window_destroy),
481                           app);
482 */
483     if (app->priv->windows == NULL)
484     {
485         /* Last window is gone... save some settings and exit */
486         ensure_user_config_dir ();
487 
488         save_accels ();
489         save_page_setup (app);
490         save_print_settings (app);
491 
492         gtk_main_quit ();
493     }
494 }
495 
496 /* Generates a unique string for a window role */
497 static gchar *
gen_role(void)498 gen_role (void)
499 {
500     static gint serial;
501 
502     return g_strdup_printf ("pluma-window-%" G_GINT64_FORMAT "-%d-%s",
503                             g_get_real_time (),
504                             serial++,
505                             g_get_host_name ());
506 }
507 
508 static PlumaWindow *
pluma_app_create_window_real(PlumaApp * app,gboolean set_geometry,const gchar * role)509 pluma_app_create_window_real (PlumaApp    *app,
510                               gboolean     set_geometry,
511                               const gchar *role)
512 {
513     PlumaWindow *window;
514 
515     pluma_debug (DEBUG_APP);
516 
517     /*
518      * We need to be careful here, there is a race condition:
519      * when another pluma is launched it checks active_window,
520      * so we must do our best to ensure that active_window
521      * is never NULL when at least a window exists.
522      */
523     if (app->priv->windows == NULL)
524     {
525         window = g_object_new (PLUMA_TYPE_WINDOW, NULL);
526         set_active_window (app, window);
527     }
528     else
529     {
530         window = g_object_new (PLUMA_TYPE_WINDOW, NULL);
531     }
532 
533     app->priv->windows = g_list_prepend (app->priv->windows, window);
534 
535     pluma_debug_message (DEBUG_APP, "Window created");
536 
537     if (role != NULL)
538     {
539         gtk_window_set_role (GTK_WINDOW (window), role);
540     }
541     else
542     {
543         gchar *newrole;
544 
545         newrole = gen_role ();
546         gtk_window_set_role (GTK_WINDOW (window), newrole);
547         g_free (newrole);
548     }
549 
550     if (set_geometry)
551     {
552         GdkWindowState state;
553         gint w, h;
554 
555         state = g_settings_get_int (app->priv->window_settings,
556                                     PLUMA_SETTINGS_WINDOW_STATE);
557 
558         if ((state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
559         {
560             _pluma_window_get_default_size (&w, &h);
561             gtk_window_set_default_size (GTK_WINDOW (window), w, h);
562             gtk_window_maximize (GTK_WINDOW (window));
563         }
564         else
565         {
566             g_settings_get (app->priv->window_settings,
567                             PLUMA_SETTINGS_WINDOW_SIZE,
568                             "(ii)", &w, &h);
569             gtk_window_set_default_size (GTK_WINDOW (window), w, h);
570             gtk_window_unmaximize (GTK_WINDOW (window));
571         }
572 
573         if ((state & GDK_WINDOW_STATE_STICKY ) != 0)
574             gtk_window_stick (GTK_WINDOW (window));
575         else
576             gtk_window_unstick (GTK_WINDOW (window));
577     }
578 
579     g_signal_connect (window,
580                       "focus_in_event",
581                       G_CALLBACK (window_focus_in_event),
582                       app);
583     g_signal_connect (window,
584                       "delete_event",
585                        G_CALLBACK (window_delete_event),
586                        app);
587     g_signal_connect (window,
588                       "destroy",
589                       G_CALLBACK (window_destroy),
590                       app);
591 
592     return window;
593 }
594 
595 /**
596  * pluma_app_create_window:
597  * @app: the #PlumaApp
598  * @screen: (allow-none):
599  *
600  * Create a new #PlumaWindow part of @app.
601  *
602  * Return value: (transfer none): the new #PlumaWindow
603  */
604 PlumaWindow *
pluma_app_create_window(PlumaApp * app,GdkScreen * screen)605 pluma_app_create_window (PlumaApp  *app,
606                          GdkScreen *screen)
607 {
608     PlumaWindow *window;
609 
610     window = pluma_app_create_window_real (app, TRUE, NULL);
611 
612     if (screen != NULL)
613         gtk_window_set_screen (GTK_WINDOW (window), screen);
614 
615     return window;
616 }
617 
618 /*
619  * Same as _create_window, but doesn't set the geometry.
620  * The session manager takes care of it. Used in mate-session.
621  */
622 PlumaWindow *
_pluma_app_restore_window(PlumaApp * app,const gchar * role)623 _pluma_app_restore_window (PlumaApp    *app,
624                            const gchar *role)
625 {
626     PlumaWindow *window;
627 
628     window = pluma_app_create_window_real (app, FALSE, role);
629 
630     return window;
631 }
632 
633 /**
634  * pluma_app_get_windows:
635  * @app: the #PlumaApp
636  *
637  * Returns all the windows currently present in #PlumaApp.
638  *
639  * Return value: (element-type Pluma.Window) (transfer none): the list of #PlumaWindows objects.
640  * The list should not be freed
641  */
642 const GList *
pluma_app_get_windows(PlumaApp * app)643 pluma_app_get_windows (PlumaApp *app)
644 {
645     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
646 
647     return app->priv->windows;
648 }
649 
650 /**
651  * pluma_app_get_active_window:
652  * @app: the #PlumaApp
653  *
654  * Retrives the #PlumaWindow currently active.
655  *
656  * Return value: (transfer none): the active #PlumaWindow
657  */
658 PlumaWindow *
pluma_app_get_active_window(PlumaApp * app)659 pluma_app_get_active_window (PlumaApp *app)
660 {
661     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
662 
663     /* make sure our active window is always realized:
664      * this is needed on startup if we launch two pluma fast
665      * enough that the second instance comes up before the
666      * first one shows its window.
667      */
668     if (!gtk_widget_get_realized (GTK_WIDGET (app->priv->active_window)))
669         gtk_widget_realize (GTK_WIDGET (app->priv->active_window));
670 
671     return app->priv->active_window;
672 }
673 
674 static gboolean
is_in_viewport(PlumaWindow * window,GdkScreen * screen,gint workspace,gint viewport_x,gint viewport_y)675 is_in_viewport (PlumaWindow  *window,
676                 GdkScreen    *screen,
677                 gint          workspace,
678                 gint          viewport_x,
679                 gint          viewport_y)
680 {
681     GdkWindow *gdkwindow;
682     gint ws;
683     gint sc_width, sc_height;
684     gint x, y, width, height;
685     gint vp_x, vp_y;
686 
687     /* Check for workspace match */
688     ws = pluma_utils_get_window_workspace (GTK_WINDOW (window));
689     if (ws != workspace && ws != PLUMA_ALL_WORKSPACES)
690         return FALSE;
691 
692     /* Check for viewport match */
693     gdkwindow = gtk_widget_get_window (GTK_WIDGET (window));
694     gdk_window_get_position (gdkwindow, &x, &y);
695 
696     width = gdk_window_get_width(gdkwindow);
697     height = gdk_window_get_height(gdkwindow);
698 
699     pluma_utils_get_current_viewport (screen, &vp_x, &vp_y);
700     x += vp_x;
701     y += vp_y;
702 
703     if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
704     {
705         sc_width = WidthOfScreen (gdk_x11_screen_get_xscreen (screen));
706         sc_height = HeightOfScreen (gdk_x11_screen_get_xscreen (screen));
707     }
708     else
709     {
710         return TRUE;
711     }
712 
713     return x + width * .25 >= viewport_x &&
714            x + width * .75 <= viewport_x + sc_width &&
715            y  >= viewport_y &&
716            y + height <= viewport_y + sc_height;
717 }
718 
719 /**
720  * _pluma_app_get_window_in_viewport:
721  * @app: the #PlumaApp
722  * @screen: the #GdkScreen
723  * @workspace: the workspace number
724  * @viewport_x: the viewport horizontal origin
725  * @viewport_y: the viewport vertical origin
726  *
727  * Since a workspace can be larger than the screen, it is divided into several
728  * equal parts called viewports. This function retrives the #PlumaWindow in
729  * the given viewport of the given workspace.
730  *
731  * Return value: the #PlumaWindow in the given viewport of the given workspace.
732  */
733 PlumaWindow *
_pluma_app_get_window_in_viewport(PlumaApp * app,GdkScreen * screen,gint workspace,gint viewport_x,gint viewport_y)734 _pluma_app_get_window_in_viewport (PlumaApp  *app,
735                                    GdkScreen *screen,
736                                    gint       workspace,
737                                    gint       viewport_x,
738                                    gint       viewport_y)
739 {
740     PlumaWindow *window;
741 
742     GList *l;
743 
744     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
745 
746     /* first try if the active window */
747     window = app->priv->active_window;
748 
749     g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL);
750 
751     if (is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
752         return window;
753 
754     /* otherwise try to see if there is a window on this workspace */
755     for (l = app->priv->windows; l != NULL; l = l->next)
756     {
757         window = l->data;
758 
759         if (is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
760             return window;
761     }
762 
763     /* no window on this workspace... create a new one */
764     return pluma_app_create_window (app, screen);
765 }
766 
767 /**
768  * pluma_app_get_documents:
769  * @app: the #PlumaApp
770  *
771  * Returns all the documents currently open in #PlumaApp.
772  *
773  * Return value: (element-type Pluma.Document) (transfer container):
774  * a newly allocated list of #PlumaDocument objects
775  */
776 GList *
pluma_app_get_documents(PlumaApp * app)777 pluma_app_get_documents (PlumaApp *app)
778 {
779     GList *res = NULL;
780     GList *windows;
781 
782     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
783 
784     windows = app->priv->windows;
785 
786     while (windows != NULL)
787     {
788         res = g_list_concat (res,
789                              pluma_window_get_documents (PLUMA_WINDOW (windows->data)));
790 
791         windows = g_list_next (windows);
792     }
793 
794     return res;
795 }
796 
797 /**
798  * pluma_app_get_views:
799  * @app: the #PlumaApp
800  *
801  * Returns all the views currently present in #PlumaApp.
802  *
803  * Return value: (element-type Pluma.View) (transfer container):
804  * a newly allocated list of #PlumaView objects
805  */
806 GList *
pluma_app_get_views(PlumaApp * app)807 pluma_app_get_views (PlumaApp *app)
808 {
809     GList *res = NULL;
810     GList *windows;
811 
812     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
813 
814     windows = app->priv->windows;
815 
816     while (windows != NULL)
817     {
818         res = g_list_concat (res,
819                              pluma_window_get_views (PLUMA_WINDOW (windows->data)));
820 
821         windows = g_list_next (windows);
822     }
823 
824     return res;
825 }
826 
827 /**
828  * pluma_app_get_lockdown:
829  * @app: a #PlumaApp
830  *
831  * Gets the lockdown mask (see #PlumaLockdownMask) for the application.
832  * The lockdown mask determines which functions are locked down using
833  * the MATE-wise lockdown GSettings keys.
834  **/
835 PlumaLockdownMask
pluma_app_get_lockdown(PlumaApp * app)836 pluma_app_get_lockdown (PlumaApp *app)
837 {
838     g_return_val_if_fail (PLUMA_IS_APP (app), PLUMA_LOCKDOWN_ALL);
839 
840     return app->priv->lockdown;
841 }
842 
843 static void
app_lockdown_changed(PlumaApp * app)844 app_lockdown_changed (PlumaApp *app)
845 {
846     GList *l;
847 
848     for (l = app->priv->windows; l != NULL; l = l->next)
849         _pluma_window_set_lockdown (PLUMA_WINDOW (l->data),
850                                     app->priv->lockdown);
851 
852     g_object_notify (G_OBJECT (app), "lockdown");
853 }
854 
855 void
_pluma_app_set_lockdown(PlumaApp * app,PlumaLockdownMask lockdown)856 _pluma_app_set_lockdown (PlumaApp          *app,
857                          PlumaLockdownMask  lockdown)
858 {
859     g_return_if_fail (PLUMA_IS_APP (app));
860 
861     app->priv->lockdown = lockdown;
862 
863     app_lockdown_changed (app);
864 }
865 
866 void
_pluma_app_set_lockdown_bit(PlumaApp * app,PlumaLockdownMask bit,gboolean value)867 _pluma_app_set_lockdown_bit (PlumaApp          *app,
868                              PlumaLockdownMask  bit,
869                              gboolean           value)
870 {
871     g_return_if_fail (PLUMA_IS_APP (app));
872 
873     if (value)
874         app->priv->lockdown |= bit;
875     else
876         app->priv->lockdown &= ~bit;
877 
878     app_lockdown_changed (app);
879 }
880 
881 /* Returns a copy */
882 GtkPageSetup *
_pluma_app_get_default_page_setup(PlumaApp * app)883 _pluma_app_get_default_page_setup (PlumaApp *app)
884 {
885     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
886 
887     if (app->priv->page_setup == NULL)
888         load_page_setup (app);
889 
890     return gtk_page_setup_copy (app->priv->page_setup);
891 }
892 
893 void
_pluma_app_set_default_page_setup(PlumaApp * app,GtkPageSetup * page_setup)894 _pluma_app_set_default_page_setup (PlumaApp     *app,
895                                    GtkPageSetup *page_setup)
896 {
897     g_return_if_fail (PLUMA_IS_APP (app));
898     g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
899 
900     if (app->priv->page_setup != NULL)
901         g_object_unref (app->priv->page_setup);
902 
903     app->priv->page_setup = g_object_ref (page_setup);
904 }
905 
906 /* Returns a copy */
907 GtkPrintSettings *
_pluma_app_get_default_print_settings(PlumaApp * app)908 _pluma_app_get_default_print_settings (PlumaApp *app)
909 {
910     g_return_val_if_fail (PLUMA_IS_APP (app), NULL);
911 
912     if (app->priv->print_settings == NULL)
913         load_print_settings (app);
914 
915     return gtk_print_settings_copy (app->priv->print_settings);
916 }
917 
918 void
_pluma_app_set_default_print_settings(PlumaApp * app,GtkPrintSettings * settings)919 _pluma_app_set_default_print_settings (PlumaApp         *app,
920                                        GtkPrintSettings *settings)
921 {
922     g_return_if_fail (PLUMA_IS_APP (app));
923     g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
924 
925     if (app->priv->print_settings != NULL)
926         g_object_unref (app->priv->print_settings);
927 
928     app->priv->print_settings = g_object_ref (settings);
929 }
930 
931