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