Bug Summary

File:core/prefs.c
Warning:line 1300, column 30
The right operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name prefs.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I ./include -D CROMA_LIBEXECDIR="/usr/libexec" -D HOST_ALIAS="" -D CROMA_LOCALEDIR="/usr/share/locale" -D CROMA_PKGDATADIR="/usr/share/croma" -D CROMA_DATADIR="/usr/share" -D G_LOG_DOMAIN="croma" -D SN_API_NOT_YET_FROZEN=1 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D _REENTRANT -D _REENTRANT -I /usr/include/startup-notification-1.0 -I /usr/include/libgtop-2.0 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-08-05-233600-31145-1 -x c core/prefs.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3/* Croma preferences */
4
5/*
6 * Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc.
7 * Copyright (C) 2006 Elijah Newren
8 * Copyright (C) 2008 Thomas Thurman
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 * 02110-1301, USA.
24 */
25
26#include <config.h>
27#include "prefs.h"
28#include "ui.h"
29#include "util.h"
30#include <cdk/cdk.h>
31#include <gio/gio.h>
32#include <string.h>
33#include <stdlib.h>
34
35#define MAX_REASONABLE_WORKSPACES36 36
36
37#define MAX_COMMANDS(32 + 2) (32 + NUM_EXTRA_COMMANDS2)
38#define NUM_EXTRA_COMMANDS2 2
39#define SCREENSHOT_COMMAND_IDX((32 + 2) - 2) (MAX_COMMANDS(32 + 2) - 2)
40#define WIN_SCREENSHOT_COMMAND_IDX((32 + 2) - 1) (MAX_COMMANDS(32 + 2) - 1)
41
42/* If you add a key, it needs updating in init() and in the GSettings
43 * notify listener and of course in the .gschema file.
44 *
45 * Keys which are handled by one of the unified handlers below are
46 * not given a name here, because the purpose of the unified handlers
47 * is that keys should be referred to exactly once.
48 */
49#define KEY_GENERAL_SCHEMA"org.cafe.Croma.general" "org.cafe.Croma.general"
50#define KEY_GENERAL_TITLEBAR_FONT"titlebar-font" "titlebar-font"
51#define KEY_GENERAL_NUM_WORKSPACES"num-workspaces" "num-workspaces"
52#define KEY_GENERAL_COMPOSITOR"compositing-manager" "compositing-manager"
53#define KEY_GENERAL_COMPOSITOR_FAST_ALT_TAB"compositing-fast-alt-tab" "compositing-fast-alt-tab"
54#define KEY_GENERAL_CENTER_NEW_WINDOWS"center-new-windows" "center-new-windows"
55#define KEY_GENERAL_ICON_SIZE"icon-size" "icon-size"
56#define KEY_GENERAL_ALT_TAB_MAX_COLUMNS"alt-tab-max-columns" "alt-tab-max-columns"
57#define KEY_GENERAL_ALT_TAB_EXPAND_TO_FIT_TITLE"alt-tab-expand-to-fit-title" "alt-tab-expand-to-fit-title"
58
59#define KEY_COMMAND_SCHEMA"org.cafe.Croma.keybinding-commands" "org.cafe.Croma.keybinding-commands"
60#define KEY_COMMAND_PREFIX"command-" "command-"
61
62#define KEY_SCREEN_BINDINGS_SCHEMA"org.cafe.Croma.global-keybindings" "org.cafe.Croma.global-keybindings"
63
64#define KEY_WINDOW_BINDINGS_SCHEMA"org.cafe.Croma.window-keybindings" "org.cafe.Croma.window-keybindings"
65
66#define KEY_WORKSPACE_NAME_SCHEMA"org.cafe.Croma.workspace-names" "org.cafe.Croma.workspace-names"
67#define KEY_WORKSPACE_NAME_PREFIX"name-" "name-"
68
69#define KEY_CAFE_INTERFACE_SCHEMA"org.cafe.interface" "org.cafe.interface"
70#define KEY_CAFE_INTERFACE_ACCESSIBILITY"accessibility" "accessibility"
71#define KEY_CAFE_INTERFACE_ENABLE_ANIMATIONS"enable-animations" "enable-animations"
72
73#define KEY_CAFE_TERMINAL_SCHEMA"org.cafe.applications-terminal" "org.cafe.applications-terminal"
74#define KEY_CAFE_TERMINAL_COMMAND"exec" "exec"
75
76#define KEY_CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse" "org.cafe.peripherals-mouse"
77#define KEY_CAFE_MOUSE_CURSOR_THEME"cursor-theme" "cursor-theme"
78#define KEY_CAFE_MOUSE_CURSOR_SIZE"cursor-size" "cursor-size"
79
80#define SETTINGS(s)g_hash_table_lookup (settings_schemas, (s)) g_hash_table_lookup (settings_schemas, (s))
81
82static GSettings *settings_general;
83static GSettings *settings_command;
84static GSettings *settings_screen_bindings;
85static GSettings *settings_window_bindings;
86static GSettings *settings_workspace_names;
87static GSettings *settings_cafe_interface;
88static GSettings *settings_cafe_terminal;
89static GSettings *settings_cafe_mouse;
90static GHashTable *settings_schemas;
91
92static GList *changes = NULL((void*)0);
93static guint changed_idle;
94static GList *listeners = NULL((void*)0);
95
96static gboolean use_system_font = FALSE(0);
97static PangoFontDescription *titlebar_font = NULL((void*)0);
98static MetaVirtualModifier mouse_button_mods = Mod1Mask(1<<3);
99static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
100static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
101static gboolean raise_on_click = TRUE(!(0));
102static gboolean attach_modal_dialogs = FALSE(0);
103static char* current_theme = NULL((void*)0);
104static int num_workspaces = 4;
105static MetaWrapStyle wrap_style = META_WRAP_NONE;
106static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE;
107static MetaActionTitlebar action_middle_click_titlebar = META_ACTION_TITLEBAR_LOWER;
108static MetaActionTitlebar action_right_click_titlebar = META_ACTION_TITLEBAR_MENU;
109static gboolean application_based = FALSE(0);
110static gboolean disable_workarounds = FALSE(0);
111static gboolean auto_raise = FALSE(0);
112static gboolean auto_raise_delay = 500;
113static gboolean provide_visual_bell = FALSE(0);
114static gboolean bell_is_audible = TRUE(!(0));
115static gboolean reduced_resources = FALSE(0);
116static gboolean cafe_accessibility = FALSE(0);
117static gboolean cafe_animations = TRUE(!(0));
118static char *cursor_theme = NULL((void*)0);
119static int cursor_size = 24;
120static int icon_size = META_DEFAULT_ICON_SIZE48;
121static int alt_tab_max_columns = META_DEFAULT_ALT_TAB_MAX_COLUMNS5;
122static gboolean alt_tab_expand_to_fit_title = META_DEFAULT_ALT_TAB_EXPAND_TO_FIT_TITLE(0);
123static gboolean use_force_compositor_manager = FALSE(0);
124static gboolean force_compositor_manager = FALSE(0);
125static gboolean compositing_manager = FALSE(0);
126static gboolean compositing_fast_alt_tab = FALSE(0);
127static gboolean resize_with_right_button = FALSE(0);
128static gboolean show_tab_border = FALSE(0);
129static gboolean center_new_windows = FALSE(0);
130static gboolean force_fullscreen = TRUE(!(0));
131static gboolean allow_tiling = FALSE(0);
132static gboolean allow_top_tiling = TRUE(!(0));
133static gboolean allow_tile_cycling = TRUE(!(0));
134static GList *show_desktop_skip_list = NULL((void*)0);
135
136static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
137static MetaButtonLayout button_layout;
138
139/* The screenshot commands are at the end */
140static char *commands[MAX_COMMANDS(32 + 2)] = { NULL((void*)0), };
141
142static char *terminal_command = NULL((void*)0);
143
144static char *workspace_names[MAX_REASONABLE_WORKSPACES36] = { NULL((void*)0), };
145
146static gboolean handle_preference_update_enum (const gchar *key, GSettings *settings);
147
148static gboolean update_key_binding (const char *name,
149 gchar *value);
150static gboolean update_command (const char *name,
151 const char *value);
152static gboolean update_workspace_name (const char *name,
153 const char *value);
154
155static void change_notify (GSettings *settings,
156 gchar *key,
157 gpointer user_data);
158
159static char* settings_key_for_workspace_name (int i);
160
161static void queue_changed (MetaPreference pref);
162
163#if 0
164static void cleanup_error (GError **error);
165#endif
166
167static void maybe_give_disable_workarounds_warning (void);
168
169static void titlebar_handler (MetaPreference, const gchar*, gboolean*);
170static void theme_name_handler (MetaPreference, const gchar*, gboolean*);
171static void mouse_button_mods_handler (MetaPreference, const gchar*, gboolean*);
172static void button_layout_handler (MetaPreference, const gchar*, gboolean*);
173static void show_desktop_skip_list_handler (MetaPreference, const gchar*, gboolean*);
174
175static gboolean update_binding (MetaKeyPref *binding,
176 gchar *value);
177
178static void init_bindings (GSettings *);
179static void init_screen_bindings (void);
180static void init_window_bindings (void);
181static void init_commands (void);
182static void init_workspace_names (void);
183
184static MetaPlacementMode placement_mode = META_PLACEMENT_MODE_AUTOMATIC;
185
186typedef struct
187{
188 MetaPrefsChangedFunc func;
189 gpointer data;
190} MetaPrefsListener;
191
192/**
193 * The details of one preference which is constrained to be
194 * one of a small number of string values-- in other words,
195 * an enumeration.
196 *
197 * We could have done this other ways. One particularly attractive
198 * possibility would have been to represent the entire symbol table
199 * as a space-separated string literal in the list of symtabs, so
200 * the focus mode enums could have been represented simply by
201 * "click sloppy mouse". However, the simplicity gained would have
202 * been outweighed by the bugs caused when the ordering of the enum
203 * strings got out of sync with the actual enum statement. Also,
204 * there is existing library code to use this kind of symbol tables.
205 *
206 * Other things we might consider doing to clean this up in the
207 * future include:
208 *
209 * - most of the keys begin with the same prefix, and perhaps we
210 * could assume it if they don't start with a slash
211 *
212 * - there are several cases where a single identifier could be used
213 * to generate an entire entry, and perhaps this could be done
214 * with a macro. (This would reduce clarity, however, and is
215 * probably a bad thing.)
216 *
217 * - these types all begin with a gchar* (and contain a MetaPreference)
218 * and we can factor out the repeated code in the handlers by taking
219 * advantage of this using some kind of union arrangement.
220 */
221typedef struct
222{
223 gchar *key;
224 gchar *schema;
225 MetaPreference pref;
226 gint *target;
227} MetaEnumPreference;
228
229typedef struct
230{
231 gchar *key;
232 gchar *schema;
233 MetaPreference pref;
234 gboolean *target;
235 gboolean becomes_true_on_destruction;
236} MetaBoolPreference;
237
238typedef struct
239{
240 gchar *key;
241 gchar *schema;
242 MetaPreference pref;
243
244 /**
245 * A handler. Many of the string preferences aren't stored as
246 * strings and need parsing; others of them have default values
247 * which can't be solved in the general case. If you include a
248 * function pointer here, it will be called before the string
249 * value is written out to the target variable.
250 *
251 * The function is passed two arguments: the preference, and
252 * the new string as a gchar*. It returns a gboolean;
253 * only if this is true, the listeners will be informed that
254 * the preference has changed.
255 *
256 * This may be NULL. If it is, see "target", below.
257 */
258 void (*handler) (MetaPreference pref,
259 const gchar *string_value,
260 gboolean *inform_listeners);
261
262 /**
263 * Where to write the incoming string.
264 *
265 * This must be NULL if the handler is non-NULL.
266 * If the incoming string is NULL, no change will be made.
267 */
268 gchar **target;
269
270} MetaStringPreference;
271
272#define METAINTPREFERENCE_NO_CHANGE_ON_DESTROY(-2147483647 -1) G_MININT(-2147483647 -1)
273
274typedef struct
275{
276 gchar *key;
277 gchar *schema;
278 MetaPreference pref;
279 gint *target;
280 /**
281 * Minimum and maximum values of the integer.
282 * If the new value is out of bounds, it will be discarded with a warning.
283 */
284 gint minimum, maximum;
285 /**
286 * Value to use if the key is destroyed.
287 * If this is METAINTPREFERENCE_NO_CHANGE_ON_DESTROY, it will
288 * not be changed when the key is destroyed.
289 */
290 gint value_if_destroyed;
291} MetaIntPreference;
292
293/* FIXMEs: */
294/* @@@ Don't use NULL lines at the end; glib can tell you how big it is */
295/* @@@ /apps/croma/general should be assumed if first char is not / */
296/* @@@ Will it ever be possible to merge init and update? If not, why not? */
297
298static MetaEnumPreference preferences_enum[] =
299 {
300 { "focus-new-windows",
301 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
302 META_PREF_FOCUS_NEW_WINDOWS,
303 (gint *) &focus_new_windows,
304 },
305 { "focus-mode",
306 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
307 META_PREF_FOCUS_MODE,
308 (gint *) &focus_mode,
309 },
310 { "wrap-style",
311 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
312 META_PREF_WRAP_STYLE,
313 (gint *) &wrap_style,
314 },
315 { "visual-bell-type",
316 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
317 META_PREF_VISUAL_BELL_TYPE,
318 (gint *) &visual_bell_type,
319 },
320 { "action-double-click-titlebar",
321 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
322 META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
323 (gint *) &action_double_click_titlebar,
324 },
325 { "action-middle-click-titlebar",
326 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
327 META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
328 (gint *) &action_middle_click_titlebar,
329 },
330 { "action-right-click-titlebar",
331 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
332 META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
333 (gint *) &action_right_click_titlebar,
334 },
335 { "placement-mode",
336 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
337 META_PREF_PLACEMENT_MODE,
338 (gint *) &placement_mode,
339 },
340 { NULL((void*)0), NULL((void*)0), 0, NULL((void*)0) },
341 };
342
343static MetaBoolPreference preferences_bool[] =
344 {
345 { "raise-on-click",
346 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
347 META_PREF_RAISE_ON_CLICK,
348 &raise_on_click,
349 TRUE(!(0)),
350 },
351 { "titlebar-uses-system-font",
352 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
353 META_PREF_TITLEBAR_FONT, /* note! shares a pref */
354 &use_system_font,
355 TRUE(!(0)),
356 },
357 { "application-based",
358 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
359 META_PREF_APPLICATION_BASED,
360 NULL((void*)0), /* feature is known but disabled */
361 FALSE(0),
362 },
363 { "disable-workarounds",
364 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
365 META_PREF_DISABLE_WORKAROUNDS,
366 &disable_workarounds,
367 FALSE(0),
368 },
369 { "auto-raise",
370 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
371 META_PREF_AUTO_RAISE,
372 &auto_raise,
373 FALSE(0),
374 },
375 { "visual-bell",
376 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
377 META_PREF_VISUAL_BELL,
378 &provide_visual_bell, /* FIXME: change the name: it's confusing */
379 FALSE(0),
380 },
381 { "audible-bell",
382 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
383 META_PREF_AUDIBLE_BELL,
384 &bell_is_audible, /* FIXME: change the name: it's confusing */
385 FALSE(0),
386 },
387 { "reduced-resources",
388 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
389 META_PREF_REDUCED_RESOURCES,
390 &reduced_resources,
391 FALSE(0),
392 },
393 { "accessibility",
394 KEY_CAFE_INTERFACE_SCHEMA"org.cafe.interface",
395 META_PREF_CAFE_ACCESSIBILITY,
396 &cafe_accessibility,
397 FALSE(0),
398 },
399 { "enable-animations",
400 KEY_CAFE_INTERFACE_SCHEMA"org.cafe.interface",
401 META_PREF_CAFE_ANIMATIONS,
402 &cafe_animations,
403 TRUE(!(0)),
404 },
405 { KEY_GENERAL_COMPOSITOR"compositing-manager",
406 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
407 META_PREF_COMPOSITING_MANAGER,
408 &compositing_manager,
409 FALSE(0),
410 },
411 { "compositing-fast-alt-tab",
412 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
413 META_PREF_COMPOSITING_FAST_ALT_TAB,
414 &compositing_fast_alt_tab,
415 FALSE(0),
416 },
417 { "resize-with-right-button",
418 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
419 META_PREF_RESIZE_WITH_RIGHT_BUTTON,
420 &resize_with_right_button,
421 FALSE(0),
422 },
423 { "show-tab-border",
424 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
425 META_PREF_SHOW_TAB_BORDER,
426 &show_tab_border,
427 FALSE(0),
428 },
429 { "center-new-windows",
430 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
431 META_PREF_CENTER_NEW_WINDOWS,
432 &center_new_windows,
433 FALSE(0),
434 },
435 { "allow-tiling",
436 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
437 META_PREF_ALLOW_TILING,
438 &allow_tiling,
439 FALSE(0),
440 },
441 { "allow-top-tiling",
442 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
443 META_PREF_ALLOW_TOP_TILING,
444 &allow_top_tiling,
445 FALSE(0),
446 },
447 { "allow-tile-cycling",
448 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
449 META_PREF_ALLOW_TILE_CYCLING,
450 &allow_tile_cycling,
451 FALSE(0),
452 },
453 { "alt-tab-expand-to-fit-title",
454 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
455 META_PREF_ALT_TAB_EXPAND_TO_FIT_TITLE,
456 &alt_tab_expand_to_fit_title,
457 META_DEFAULT_ALT_TAB_EXPAND_TO_FIT_TITLE(0),
458 },
459 { NULL((void*)0), NULL((void*)0), 0, NULL((void*)0), FALSE(0) },
460 };
461
462static MetaStringPreference preferences_string[] =
463 {
464 { "mouse-button-modifier",
465 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
466 META_PREF_MOUSE_BUTTON_MODS,
467 mouse_button_mods_handler,
468 NULL((void*)0),
469 },
470 { "theme",
471 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
472 META_PREF_THEME,
473 theme_name_handler,
474 NULL((void*)0),
475 },
476 { KEY_GENERAL_TITLEBAR_FONT"titlebar-font",
477 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
478 META_PREF_TITLEBAR_FONT,
479 titlebar_handler,
480 NULL((void*)0),
481 },
482 { KEY_CAFE_TERMINAL_COMMAND"exec",
483 KEY_CAFE_TERMINAL_SCHEMA"org.cafe.applications-terminal",
484 META_PREF_TERMINAL_COMMAND,
485 NULL((void*)0),
486 &terminal_command,
487 },
488 { "button-layout",
489 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
490 META_PREF_BUTTON_LAYOUT,
491 button_layout_handler,
492 NULL((void*)0),
493 },
494 { "cursor-theme",
495 KEY_CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse",
496 META_PREF_CURSOR_THEME,
497 NULL((void*)0),
498 &cursor_theme,
499 },
500 { "show-desktop-skip-list",
501 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
502 META_PREF_SHOW_DESKTOP_SKIP_LIST,
503 &show_desktop_skip_list_handler,
504 NULL((void*)0),
505 },
506 { NULL((void*)0), NULL((void*)0), 0, NULL((void*)0), NULL((void*)0) },
507 };
508
509static MetaIntPreference preferences_int[] =
510 {
511 { "num-workspaces",
512 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
513 META_PREF_NUM_WORKSPACES,
514 &num_workspaces,
515 /* I would actually recommend we change the destroy value to 4
516 * and get rid of METAINTPREFERENCE_NO_CHANGE_ON_DESTROY entirely.
517 * -- tthurman
518 */
519 1, MAX_REASONABLE_WORKSPACES36, METAINTPREFERENCE_NO_CHANGE_ON_DESTROY(-2147483647 -1),
520 },
521 { "auto-raise-delay",
522 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
523 META_PREF_AUTO_RAISE_DELAY,
524 &auto_raise_delay,
525 0, 10000, 0,
526 /* @@@ Get rid of MAX_REASONABLE_AUTO_RAISE_DELAY */
527 },
528 { "cursor-size",
529 KEY_CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse",
530 META_PREF_CURSOR_SIZE,
531 &cursor_size,
532 1, 128, 24,
533 },
534 { "icon-size",
535 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
536 META_PREF_ICON_SIZE,
537 &icon_size,
538 META_MIN_ICON_SIZE8, META_MAX_ICON_SIZE256, META_DEFAULT_ICON_SIZE48,
539 },
540 { "alt-tab-max-columns",
541 KEY_GENERAL_SCHEMA"org.cafe.Croma.general",
542 META_PREF_ALT_TAB_MAX_COLUMNS,
543 &alt_tab_max_columns,
544 META_MIN_ALT_TAB_MAX_COLUMNS1,
545 META_MAX_ALT_TAB_MAX_COLUMNS64,
546 META_DEFAULT_ALT_TAB_MAX_COLUMNS5,
547 },
548 { NULL((void*)0), NULL((void*)0), 0, NULL((void*)0), 0, 0, 0, },
549 };
550
551static void
552handle_preference_init_enum (void)
553{
554 MetaEnumPreference *cursor = preferences_enum;
555
556 while (cursor->key!=NULL((void*)0))
557 {
558 gint value;
559
560 if (cursor->target==NULL((void*)0))
561 {
562 ++cursor;
563 continue;
564 }
565
566 value = g_settings_get_enum (SETTINGS (cursor->schema)g_hash_table_lookup (settings_schemas, (cursor->schema)),
567 cursor->key);
568 *cursor->target = value;
569
570 ++cursor;
571 }
572}
573
574static void
575handle_preference_init_bool (void)
576{
577 MetaBoolPreference *cursor = preferences_bool;
578
579 while (cursor->key!=NULL((void*)0))
580 {
581 if (cursor->target!=NULL((void*)0))
582 *cursor->target = g_settings_get_boolean (SETTINGS (cursor->schema)g_hash_table_lookup (settings_schemas, (cursor->schema)), cursor->key);
583
584 ++cursor;
585 }
586
587 maybe_give_disable_workarounds_warning ();
588}
589
590static void
591handle_preference_init_string (void)
592{
593 MetaStringPreference *cursor = preferences_string;
594
595 while (cursor->key!=NULL((void*)0))
596 {
597 gchar *value;
598 gboolean dummy = TRUE(!(0));
599
600 /* the string "value" will be newly allocated */
601 value = g_settings_get_string (SETTINGS (cursor->schema)g_hash_table_lookup (settings_schemas, (cursor->schema)),
602 cursor->key);
603
604 if (cursor->handler)
605 {
606 if (cursor->target)
607 meta_bug ("%s has both a target and a handler\n", cursor->key);
608
609 cursor->handler (cursor->pref, value, &dummy);
610
611 g_free (value);
612 }
613 else if (cursor->target)
614 {
615 if (*(cursor->target))
616 g_free (*(cursor->target));
617
618 *(cursor->target) = value;
619 }
620
621 ++cursor;
622 }
623}
624
625static void
626handle_preference_init_int (void)
627{
628 MetaIntPreference *cursor = preferences_int;
629
630
631 while (cursor->key!=NULL((void*)0))
632 {
633 gint value;
634
635 value = g_settings_get_int (SETTINGS (cursor->schema)g_hash_table_lookup (settings_schemas, (cursor->schema)),
636 cursor->key);
637
638 if (value < cursor->minimum || value > cursor->maximum)
639 {
640 /* FIXME: check if this can be avoided by GSettings */
641 meta_warning (_("%d stored in GSettings key %s is out of range %d to %d\n")dgettext ("croma", "%d stored in GSettings key %s is out of range %d to %d\n"
)
,
642 value, cursor->key, cursor->minimum, cursor->maximum);
643 /* Former behaviour for out-of-range values was:
644 * - number of workspaces was clamped;
645 * - auto raise delay was always reset to zero even if too high!;
646 * - cursor size was ignored.
647 *
648 * These seem to be meaningless variations. If they did
649 * have meaning we could have put them into MetaIntPreference.
650 * The last of these is the closest to how we behave for
651 * other types, so I think we should standardise on that.
652 */
653 }
654 else if (cursor->target)
655 *cursor->target = value;
656
657 ++cursor;
658 }
659}
660
661static gboolean
662handle_preference_update_enum (const gchar *key, GSettings *settings)
663{
664 MetaEnumPreference *cursor = preferences_enum;
665 gint old_value;
666
667 while (cursor->key!=NULL((void*)0) && strcmp (key, cursor->key)!=0)
668 ++cursor;
669
670 if (cursor->key==NULL((void*)0))
671 /* Didn't recognise that key. */
672 return FALSE(0);
673
674 /* We need to know whether the value changes, so
675 * store the current value away.
676 */
677
678 old_value = * ((gint *) cursor->target);
679
680 /* Now look it up... */
681 *cursor->target = g_settings_get_enum (settings, key);
682
683 /* Did it change? If so, tell the listeners about it. */
684
685 if (old_value != *((gint *) cursor->target))
686 queue_changed (cursor->pref);
687
688 return TRUE(!(0));
689}
690
691static gboolean
692handle_preference_update_bool (const gchar *key, GSettings *settings)
693{
694 MetaBoolPreference *cursor = preferences_bool;
695 gboolean old_value;
696
697 while (cursor->key!=NULL((void*)0) && strcmp (key, cursor->key)!=0)
698 ++cursor;
699
700 if (cursor->key==NULL((void*)0))
701 /* Didn't recognise that key. */
702 return FALSE(0);
703
704 if (cursor->target==NULL((void*)0))
705 /* No work for us to do. */
706 return TRUE(!(0));
707
708 /* We need to know whether the value changes, so
709 * store the current value away.
710 */
711
712 old_value = * ((gboolean *) cursor->target);
713
714 /* Now look it up... */
715
716 *((gboolean *) cursor->target) = g_settings_get_boolean (settings, key);
717
718 /* Did it change? If so, tell the listeners about it. */
719
720 if (old_value != *((gboolean *) cursor->target))
721 queue_changed (cursor->pref);
722
723 if (cursor->pref==META_PREF_DISABLE_WORKAROUNDS)
724 maybe_give_disable_workarounds_warning ();
725
726 return TRUE(!(0));
727}
728
729static gboolean
730handle_preference_update_string (const gchar *key, GSettings *settings)
731{
732 MetaStringPreference *cursor = preferences_string;
733 gchar *value;
734 gboolean inform_listeners = TRUE(!(0));
735
736 while (cursor->key!=NULL((void*)0) && strcmp (key, cursor->key)!=0)
737 ++cursor;
738
739 if (cursor->key==NULL((void*)0))
740 /* Didn't recognise that key. */
741 return FALSE(0);
742
743 value = g_settings_get_string (settings, key);
744
745 if (cursor->handler)
746 cursor->handler (cursor->pref, value, &inform_listeners);
747 else if (cursor->target)
748 {
749 if (*(cursor->target))
750 g_free(*(cursor->target));
751
752 if (value!=NULL((void*)0))
753 *(cursor->target) = g_strdup (value)g_strdup_inline (value);
754 else
755 *(cursor->target) = NULL((void*)0);
756
757 inform_listeners =
758 (value==NULL((void*)0) && *(cursor->target)==NULL((void*)0)) ||
759 (value!=NULL((void*)0) && *(cursor->target)!=NULL((void*)0) &&
760 strcmp (value, *(cursor->target))==0);
761 }
762
763 if (inform_listeners)
764 queue_changed (cursor->pref);
765
766 g_free (value);
767
768 return TRUE(!(0));
769}
770
771static gboolean
772handle_preference_update_int (const gchar *key, GSettings *settings)
773{
774 MetaIntPreference *cursor = preferences_int;
775 gint value;
776
777 while (cursor->key!=NULL((void*)0) && strcmp (key, cursor->key)!=0)
778 ++cursor;
779
780 if (cursor->key==NULL((void*)0))
781 /* Didn't recognise that key. */
782 return FALSE(0);
783
784 if (cursor->target==NULL((void*)0))
785 /* No work for us to do. */
786 return TRUE(!(0));
787
788 value = g_settings_get_int (settings, key);
789
790 if (value < cursor->minimum || value > cursor->maximum)
791 {
792 /* FIXME! GSettings, instead of CafeConf, has Minimum/Maximun in schema!
793 * But some preferences depends on costants for minimum/maximum values */
794 meta_warning (_("%d stored in GSettings key %s is out of range %d to %d\n")dgettext ("croma", "%d stored in GSettings key %s is out of range %d to %d\n"
)
,
795 value, cursor->key,
796 cursor->minimum, cursor->maximum);
797 return TRUE(!(0));
798 }
799
800 /* Did it change? If so, tell the listeners about it. */
801
802 if (*cursor->target != value)
803 {
804 *cursor->target = value;
805 queue_changed (cursor->pref);
806 }
807
808 return TRUE(!(0));
809
810}
811
812
813/****************************************************************************/
814/* Listeners. */
815/****************************************************************************/
816
817void
818meta_prefs_add_listener (MetaPrefsChangedFunc func,
819 gpointer data)
820{
821 MetaPrefsListener *l;
822
823 l = g_new (MetaPrefsListener, 1)((MetaPrefsListener *) g_malloc_n ((1), sizeof (MetaPrefsListener
)))
;
824 l->func = func;
825 l->data = data;
826
827 listeners = g_list_prepend (listeners, l);
828}
829
830void
831meta_prefs_remove_listener (MetaPrefsChangedFunc func,
832 gpointer data)
833{
834 GList *tmp;
835
836 tmp = listeners;
837 while (tmp != NULL((void*)0))
838 {
839 MetaPrefsListener *l = tmp->data;
840
841 if (l->func == func &&
842 l->data == data)
843 {
844 g_free (l);
845 listeners = g_list_delete_link (listeners, tmp);
846
847 return;
848 }
849
850 tmp = tmp->next;
851 }
852
853 meta_bug ("Did not find listener to remove\n");
854}
855
856static void
857emit_changed (MetaPreference pref)
858{
859 GList *tmp;
860 GList *copy;
861
862 meta_topicmeta_topic_real (META_DEBUG_PREFS, "Notifying listeners that pref %s changed\n",
863 meta_preference_to_string (pref));
864
865 copy = g_list_copy (listeners);
866
867 tmp = copy;
868
869 while (tmp != NULL((void*)0))
870 {
871 MetaPrefsListener *l = tmp->data;
872
873 (* l->func) (pref, l->data);
874
875 tmp = tmp->next;
876 }
877
878 g_list_free (copy);
879}
880
881static gboolean
882changed_idle_handler (gpointer data)
883{
884 GList *tmp;
885 GList *copy;
886
887 changed_idle = 0;
888
889 copy = g_list_copy (changes); /* reentrancy paranoia */
890
891 g_list_free (changes);
892 changes = NULL((void*)0);
893
894 tmp = copy;
895 while (tmp != NULL((void*)0))
896 {
897 MetaPreference pref = GPOINTER_TO_INT (tmp->data)((gint) (glong) (tmp->data));
898
899 emit_changed (pref);
900
901 tmp = tmp->next;
902 }
903
904 g_list_free (copy);
905
906 return FALSE(0);
907}
908
909static void
910queue_changed (MetaPreference pref)
911{
912 meta_topicmeta_topic_real (META_DEBUG_PREFS, "Queueing change of pref %s\n",
913 meta_preference_to_string (pref));
914
915 if (g_list_find (changes, GINT_TO_POINTER (pref)((gpointer) (glong) (pref))) == NULL((void*)0))
916 changes = g_list_prepend (changes, GINT_TO_POINTER (pref)((gpointer) (glong) (pref)));
917 else
918 meta_topicmeta_topic_real (META_DEBUG_PREFS, "Change of pref %s was already pending\n",
919 meta_preference_to_string (pref));
920
921 /* add idle at priority below the GSettings notify idle */
922 /* FIXME is this needed for GSettings too? */
923 if (changed_idle == 0)
924 changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY(200 + 10),
925 changed_idle_handler, NULL((void*)0), NULL((void*)0));
926}
927
928
929/****************************************************************************/
930/* Initialisation. */
931/****************************************************************************/
932
933void
934meta_prefs_init (void)
935{
936 if (settings_general != NULL((void*)0))
937 return;
938
939 /* returns references which we hold forever */
940 settings_general = g_settings_new (KEY_GENERAL_SCHEMA"org.cafe.Croma.general");
941 settings_command = g_settings_new (KEY_COMMAND_SCHEMA"org.cafe.Croma.keybinding-commands");
942 settings_screen_bindings = g_settings_new (KEY_SCREEN_BINDINGS_SCHEMA"org.cafe.Croma.global-keybindings");
943 settings_window_bindings = g_settings_new (KEY_WINDOW_BINDINGS_SCHEMA"org.cafe.Croma.window-keybindings");
944 settings_workspace_names = g_settings_new (KEY_WORKSPACE_NAME_SCHEMA"org.cafe.Croma.workspace-names");
945 settings_cafe_interface = g_settings_new (KEY_CAFE_INTERFACE_SCHEMA"org.cafe.interface");
946 settings_cafe_terminal = g_settings_new (KEY_CAFE_TERMINAL_SCHEMA"org.cafe.applications-terminal");
947 settings_cafe_mouse = g_settings_new (KEY_CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse");
948
949 settings_schemas = g_hash_table_new_full (g_str_hash, g_str_equal, NULL((void*)0), g_object_unref);
950 g_hash_table_insert (settings_schemas, KEY_GENERAL_SCHEMA"org.cafe.Croma.general", settings_general);
951 g_hash_table_insert (settings_schemas, KEY_COMMAND_SCHEMA"org.cafe.Croma.keybinding-commands", settings_command);
952 g_hash_table_insert (settings_schemas, KEY_SCREEN_BINDINGS_SCHEMA"org.cafe.Croma.global-keybindings", settings_screen_bindings);
953 g_hash_table_insert (settings_schemas, KEY_WINDOW_BINDINGS_SCHEMA"org.cafe.Croma.window-keybindings", settings_window_bindings);
954 g_hash_table_insert (settings_schemas, KEY_WORKSPACE_NAME_SCHEMA"org.cafe.Croma.workspace-names", settings_workspace_names);
955 g_hash_table_insert (settings_schemas, KEY_CAFE_INTERFACE_SCHEMA"org.cafe.interface", settings_cafe_interface);
956 g_hash_table_insert (settings_schemas, KEY_CAFE_TERMINAL_SCHEMA"org.cafe.applications-terminal", settings_cafe_terminal);
957 g_hash_table_insert (settings_schemas, KEY_CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse", settings_cafe_mouse);
958
959 g_signal_connect (settings_general, "changed", G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_general), ("changed"), (((GCallback
) (change_notify))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
960 g_signal_connect (settings_command, "changed", G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_command), ("changed"), (((GCallback
) (change_notify))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
961 g_signal_connect (settings_screen_bindings, "changed", G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_screen_bindings), ("changed"
), (((GCallback) (change_notify))), (((void*)0)), ((void*)0),
(GConnectFlags) 0)
;
962 g_signal_connect (settings_window_bindings, "changed", G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_window_bindings), ("changed"
), (((GCallback) (change_notify))), (((void*)0)), ((void*)0),
(GConnectFlags) 0)
;
963 g_signal_connect (settings_workspace_names, "changed", G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_workspace_names), ("changed"
), (((GCallback) (change_notify))), (((void*)0)), ((void*)0),
(GConnectFlags) 0)
;
964
965 g_signal_connect (settings_cafe_interface, "changed::" KEY_CAFE_INTERFACE_ACCESSIBILITY, G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_cafe_interface), ("changed::"
"accessibility"), (((GCallback) (change_notify))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
;
966 g_signal_connect (settings_cafe_interface, "changed::" KEY_CAFE_INTERFACE_ENABLE_ANIMATIONS, G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_cafe_interface), ("changed::"
"enable-animations"), (((GCallback) (change_notify))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
967 g_signal_connect (settings_cafe_terminal, "changed::" KEY_CAFE_TERMINAL_COMMAND, G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_cafe_terminal), ("changed::"
"exec"), (((GCallback) (change_notify))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
968 g_signal_connect (settings_cafe_mouse, "changed::" KEY_CAFE_MOUSE_CURSOR_THEME, G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_cafe_mouse), ("changed::" "cursor-theme"
), (((GCallback) (change_notify))), (((void*)0)), ((void*)0),
(GConnectFlags) 0)
;
969 g_signal_connect (settings_cafe_mouse, "changed::" KEY_CAFE_MOUSE_CURSOR_SIZE, G_CALLBACK (change_notify), NULL)g_signal_connect_data ((settings_cafe_mouse), ("changed::" "cursor-size"
), (((GCallback) (change_notify))), (((void*)0)), ((void*)0),
(GConnectFlags) 0)
;
970
971 /* Pick up initial values. */
972
973 handle_preference_init_enum ();
974 handle_preference_init_bool ();
975 handle_preference_init_string ();
976 handle_preference_init_int ();
977
978 init_screen_bindings ();
979 init_window_bindings ();
980 init_commands ();
981 init_workspace_names ();
982}
983
984/****************************************************************************/
985/* Updates. */
986/****************************************************************************/
987
988gboolean (*preference_update_handler[]) (const gchar*, GSettings*) = {
989 handle_preference_update_enum,
990 handle_preference_update_bool,
991 handle_preference_update_string,
992 handle_preference_update_int,
993 NULL((void*)0)
994};
995
996static void
997change_notify (GSettings *settings,
998 gchar *key,
999 gpointer user_data)
1000{
1001 gint i=0;
1002
1003 /* First, search for a handler that might know what to do. */
1004
1005 /* FIXME: When this is all working, since the first item in every
1006 * array is the gchar* of the key, there's no reason we can't
1007 * find the correct record for that key here and save code duplication.
1008 */
1009
1010 while (preference_update_handler[i]!=NULL((void*)0))
1011 {
1012 if (preference_update_handler[i] (key, settings))
1013 return; /* Get rid of this eventually */
1014
1015 i++;
1016 }
1017
1018 gchar *schema_name = NULL((void*)0);
1019 g_object_get (settings, "schema-id", &schema_name, NULL((void*)0));
1020
1021 if (g_strcmp0 (schema_name, KEY_WINDOW_BINDINGS_SCHEMA"org.cafe.Croma.window-keybindings") == 0 ||
1022 g_strcmp0 (schema_name, KEY_SCREEN_BINDINGS_SCHEMA"org.cafe.Croma.global-keybindings") == 0)
1023 {
1024 gchar *str;
1025 str = g_settings_get_string (settings, key);
1026
1027 if (update_key_binding (key, str))
1028 queue_changed (META_PREF_KEYBINDINGS);
1029
1030 g_free(str);
1031 }
1032 else if (g_strcmp0 (schema_name, KEY_COMMAND_SCHEMA"org.cafe.Croma.keybinding-commands") == 0)
1033 {
1034 gchar *str;
1035 str = g_settings_get_string (settings, key);
1036
1037 if (update_command (key, str))
1038 queue_changed (META_PREF_COMMANDS);
1039
1040 g_free(str);
1041 }
1042 else if (g_strcmp0 (schema_name, KEY_WORKSPACE_NAME_SCHEMA"org.cafe.Croma.workspace-names") == 0)
1043 {
1044 gchar *str;
1045 str = g_settings_get_string (settings, key);
1046
1047 if (update_workspace_name (key, str))
1048 queue_changed (META_PREF_WORKSPACE_NAMES);
1049
1050 g_free(str);
1051 }
1052 else
1053 {
1054 /* Is this possible with GSettings? I dont think so! */
1055 meta_topicmeta_topic_real (META_DEBUG_PREFS, "Key %s doesn't mean anything to Croma\n",
1056 key);
1057 }
1058 g_free (schema_name);
1059}
1060
1061#if 0
1062static void
1063cleanup_error (GError **error)
1064{
1065 if (*error)
1066 {
1067 meta_warning ("%s\n", (*error)->message);
1068
1069 g_error_free (*error);
1070 *error = NULL((void*)0);
1071 }
1072}
1073#endif
1074
1075/**
1076 * Special case: give a warning the first time disable_workarounds
1077 * is turned on.
1078 */
1079static void
1080maybe_give_disable_workarounds_warning (void)
1081{
1082 static gboolean first_disable = TRUE(!(0));
1083
1084 if (first_disable && disable_workarounds)
1085 {
1086 first_disable = FALSE(0);
1087
1088 meta_warning (_("Workarounds for broken applications disabled. "dgettext ("croma", "Workarounds for broken applications disabled. "
"Some applications may not behave properly.\n")
1089 "Some applications may not behave properly.\n")dgettext ("croma", "Workarounds for broken applications disabled. "
"Some applications may not behave properly.\n")
);
1090 }
1091}
1092
1093MetaVirtualModifier
1094meta_prefs_get_mouse_button_mods (void)
1095{
1096 return mouse_button_mods;
1097}
1098
1099MetaFocusMode
1100meta_prefs_get_focus_mode (void)
1101{
1102 return focus_mode;
1103}
1104
1105MetaFocusNewWindows
1106meta_prefs_get_focus_new_windows (void)
1107{
1108 return focus_new_windows;
1109}
1110
1111gboolean
1112meta_prefs_get_attach_modal_dialogs (void)
1113{
1114 return attach_modal_dialogs;
1115}
1116
1117gboolean
1118meta_prefs_get_raise_on_click (void)
1119{
1120 return raise_on_click;
1121}
1122
1123const char*
1124meta_prefs_get_theme (void)
1125{
1126 return current_theme;
1127}
1128
1129const char*
1130meta_prefs_get_cursor_theme (void)
1131{
1132 return cursor_theme;
1133}
1134
1135int
1136meta_prefs_get_cursor_size (void)
1137{
1138 CdkWindow *window = cdk_get_default_root_window ();
1139 gint scale = cdk_window_get_scale_factor (window);
1140
1141 return cursor_size * scale;
1142}
1143
1144int
1145meta_prefs_get_icon_size (void)
1146{
1147 CdkWindow *window = cdk_get_default_root_window ();
1148 gint scale = cdk_window_get_scale_factor (window);
1149
1150 return icon_size * scale;
1151}
1152
1153int
1154meta_prefs_get_alt_tab_max_columns (void)
1155{
1156 return alt_tab_max_columns;
1157}
1158
1159gboolean
1160meta_prefs_get_alt_tab_expand_to_fit_title (void)
1161{
1162 return alt_tab_expand_to_fit_title;
1163}
1164
1165gboolean
1166meta_prefs_is_in_skip_list (char *class)
1167{
1168 GList *item;
1169
1170 for (item = show_desktop_skip_list; item; item = item->next)
1171 {
1172 if (!g_ascii_strcasecmp (class, item->data))
1173 return TRUE(!(0));
1174 }
1175 return FALSE(0);
1176}
1177
1178/****************************************************************************/
1179/* Handlers for string preferences. */
1180/****************************************************************************/
1181
1182static void
1183titlebar_handler (MetaPreference pref,
1184 const gchar *string_value,
1185 gboolean *inform_listeners)
1186{
1187 PangoFontDescription *new_desc = NULL((void*)0);
1188
1189 if (string_value)
1190 new_desc = pango_font_description_from_string (string_value);
1191
1192 if (new_desc == NULL((void*)0))
1193 {
1194 meta_warning (_("Could not parse font description "dgettext ("croma", "Could not parse font description " "\"%s\" from GSettings key %s\n"
)
1195 "\"%s\" from GSettings key %s\n")dgettext ("croma", "Could not parse font description " "\"%s\" from GSettings key %s\n"
)
,
1196 string_value ? string_value : "(null)",
1197 KEY_GENERAL_TITLEBAR_FONT"titlebar-font");
1198
1199 *inform_listeners = FALSE(0);
1200
1201 return;
1202 }
1203
1204 /* Is the new description the same as the old? */
1205
1206 if (titlebar_font &&
1207 pango_font_description_equal (new_desc, titlebar_font))
1208 {
1209 pango_font_description_free (new_desc);
1210 *inform_listeners = FALSE(0);
1211 return;
1212 }
1213
1214 /* No, so free the old one and put ours in instead. */
1215
1216 if (titlebar_font)
1217 pango_font_description_free (titlebar_font);
1218
1219 titlebar_font = new_desc;
1220
1221}
1222
1223static void
1224theme_name_handler (MetaPreference pref,
1225 const gchar *string_value,
1226 gboolean *inform_listeners)
1227{
1228 g_free (current_theme);
1229
1230 /* Fallback crackrock */
1231 if (string_value == NULL((void*)0))
1232 current_theme = g_strdup ("ClearlooksRe_ctk")g_strdup_inline ("ClearlooksRe_ctk");
1233 else
1234 current_theme = g_strdup (string_value)g_strdup_inline (string_value);
1235}
1236
1237static void
1238mouse_button_mods_handler (MetaPreference pref,
1239 const gchar *string_value,
1240 gboolean *inform_listeners)
1241{
1242 MetaVirtualModifier mods;
1243
1244 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1245 "Mouse button modifier has new GSettings value \"%s\"\n",
1246 string_value);
1247 if (string_value && meta_ui_parse_modifier (string_value, &mods))
1248 {
1249 mouse_button_mods = mods;
1250 }
1251 else
1252 {
1253 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1254 "Failed to parse new GSettings value\n");
1255
1256 meta_warning (_("\"%s\" found in configuration database is "dgettext ("croma", "\"%s\" found in configuration database is "
"not a valid value for mouse button modifier\n")
1257 "not a valid value for mouse button modifier\n")dgettext ("croma", "\"%s\" found in configuration database is "
"not a valid value for mouse button modifier\n")
,
1258 string_value);
1259
1260 *inform_listeners = FALSE(0);
1261 }
1262}
1263
1264static void
1265show_desktop_skip_list_handler (MetaPreference pref,
1266 const gchar *string_value,
1267 gboolean *inform_listeners)
1268{
1269 gchar **tokens;
1270 gchar **tok;
1271 GList *item;
1272
1273 if (show_desktop_skip_list)
1274 {
1275 for (item = show_desktop_skip_list; item; item = item->next)
1276 g_free (item->data);
1277 g_list_free (show_desktop_skip_list);
1278 show_desktop_skip_list = NULL((void*)0);
1279 }
1280
1281 if (!(tokens = g_strsplit (string_value, ",", -1)))
1282 return;
1283 for (tok = tokens; tok && *tok; tok++)
1284 {
1285 gchar *stripped = g_strstrip (g_strdup (*tok))g_strchomp (g_strchug (g_strdup_inline (*tok)));
1286 show_desktop_skip_list = g_list_prepend (show_desktop_skip_list, stripped);
1287 }
1288 g_strfreev (tokens);
1289}
1290
1291static gboolean
1292button_layout_equal (const MetaButtonLayout *a,
1293 const MetaButtonLayout *b)
1294{
1295 int i;
1296
1297 i = 0;
5
The value 0 is assigned to 'i'
1298 while (i < MAX_BUTTONS_PER_CORNERMETA_BUTTON_FUNCTION_LAST)
6
Loop condition is true. Entering loop body
1299 {
1300 if (a->left_buttons[i] != b->left_buttons[i])
7
The right operand of '!=' is a garbage value
1301 return FALSE(0);
1302 if (a->right_buttons[i] != b->right_buttons[i])
1303 return FALSE(0);
1304 if (a->left_buttons_has_spacer[i] != b->left_buttons_has_spacer[i])
1305 return FALSE(0);
1306 if (a->right_buttons_has_spacer[i] != b->right_buttons_has_spacer[i])
1307 return FALSE(0);
1308 ++i;
1309 }
1310
1311 return TRUE(!(0));
1312}
1313
1314static MetaButtonFunction
1315button_function_from_string (const char *str)
1316{
1317 /* FIXME: g_settings_get_enum is the obvious way to do this */
1318
1319 if (strcmp (str, "menu") == 0)
1320 return META_BUTTON_FUNCTION_MENU;
1321 else if (strcmp (str, "appmenu") == 0)
1322 return META_BUTTON_FUNCTION_APPMENU;
1323 else if (strcmp (str, "minimize") == 0)
1324 return META_BUTTON_FUNCTION_MINIMIZE;
1325 else if (strcmp (str, "maximize") == 0)
1326 return META_BUTTON_FUNCTION_MAXIMIZE;
1327 else if (strcmp (str, "close") == 0)
1328 return META_BUTTON_FUNCTION_CLOSE;
1329 else if (strcmp (str, "shade") == 0)
1330 return META_BUTTON_FUNCTION_SHADE;
1331 else if (strcmp (str, "above") == 0)
1332 return META_BUTTON_FUNCTION_ABOVE;
1333 else if (strcmp (str, "stick") == 0)
1334 return META_BUTTON_FUNCTION_STICK;
1335 else
1336 /* don't know; give up */
1337 return META_BUTTON_FUNCTION_LAST;
1338}
1339
1340static MetaButtonFunction
1341button_opposite_function (MetaButtonFunction ofwhat)
1342{
1343 switch (ofwhat)
1344 {
1345 case META_BUTTON_FUNCTION_SHADE:
1346 return META_BUTTON_FUNCTION_UNSHADE;
1347 case META_BUTTON_FUNCTION_UNSHADE:
1348 return META_BUTTON_FUNCTION_SHADE;
1349
1350 case META_BUTTON_FUNCTION_ABOVE:
1351 return META_BUTTON_FUNCTION_UNABOVE;
1352 case META_BUTTON_FUNCTION_UNABOVE:
1353 return META_BUTTON_FUNCTION_ABOVE;
1354
1355 case META_BUTTON_FUNCTION_STICK:
1356 return META_BUTTON_FUNCTION_UNSTICK;
1357 case META_BUTTON_FUNCTION_UNSTICK:
1358 return META_BUTTON_FUNCTION_STICK;
1359
1360 default:
1361 return META_BUTTON_FUNCTION_LAST;
1362 }
1363}
1364
1365static void
1366button_layout_handler (MetaPreference pref,
1367 const gchar *string_value,
1368 gboolean *inform_listeners)
1369{
1370 MetaButtonLayout new_layout;
1371 char **sides = NULL((void*)0);
1372 int i;
1373
1374 /* We need to ignore unknown button functions, for
1375 * compat with future versions
1376 */
1377
1378 if (string_value)
1
Assuming 'string_value' is null
1379 sides = g_strsplit (string_value, ":", 2);
1380
1381 if (sides
1.1
'sides' is equal to NULL
!= NULL((void*)0) && sides[0] != NULL((void*)0))
1382 {
1383 char **buttons;
1384 int b;
1385 gboolean used[META_BUTTON_FUNCTION_LAST];
1386
1387 i = 0;
1388 while (i < META_BUTTON_FUNCTION_LAST)
1389 {
1390 used[i] = FALSE(0);
1391 new_layout.left_buttons_has_spacer[i] = FALSE(0);
1392 ++i;
1393 }
1394
1395 buttons = g_strsplit (sides[0], ",", -1);
1396 i = 0;
1397 b = 0;
1398 while (buttons[b] != NULL((void*)0))
1399 {
1400 MetaButtonFunction f = button_function_from_string (buttons[b]);
1401 if (i > 0 && strcmp("spacer", buttons[b]) == 0)
1402 {
1403 new_layout.left_buttons_has_spacer[i-1] = TRUE(!(0));
1404 f = button_opposite_function (f);
1405
1406 if (f != META_BUTTON_FUNCTION_LAST)
1407 {
1408 new_layout.left_buttons_has_spacer[i-2] = TRUE(!(0));
1409 }
1410 }
1411 else
1412 {
1413 if (f != META_BUTTON_FUNCTION_LAST && !used[f])
1414 {
1415 new_layout.left_buttons[i] = f;
1416 used[f] = TRUE(!(0));
1417 ++i;
1418
1419 f = button_opposite_function (f);
1420
1421 if (f != META_BUTTON_FUNCTION_LAST)
1422 new_layout.left_buttons[i++] = f;
1423
1424 }
1425 else
1426 {
1427 meta_topicmeta_topic_real (META_DEBUG_PREFS, "Ignoring unknown or already-used button name \"%s\"\n",
1428 buttons[b]);
1429 }
1430 }
1431
1432 ++b;
1433 }
1434
1435 new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
1436 new_layout.left_buttons_has_spacer[i] = FALSE(0);
1437
1438 g_strfreev (buttons);
1439 }
1440
1441 if (sides
1.2
'sides' is equal to NULL
!= NULL((void*)0) && sides[0] != NULL((void*)0) && sides[1] != NULL((void*)0))
1442 {
1443 char **buttons;
1444 int b;
1445 gboolean used[META_BUTTON_FUNCTION_LAST];
1446
1447 i = 0;
1448 while (i < META_BUTTON_FUNCTION_LAST)
1449 {
1450 used[i] = FALSE(0);
1451 new_layout.right_buttons_has_spacer[i] = FALSE(0);
1452 ++i;
1453 }
1454
1455 buttons = g_strsplit (sides[1], ",", -1);
1456 i = 0;
1457 b = 0;
1458 while (buttons[b] != NULL((void*)0))
1459 {
1460 MetaButtonFunction f = button_function_from_string (buttons[b]);
1461 if (i > 0 && strcmp("spacer", buttons[b]) == 0)
1462 {
1463 new_layout.right_buttons_has_spacer[i-1] = TRUE(!(0));
1464 f = button_opposite_function (f);
1465 if (f != META_BUTTON_FUNCTION_LAST)
1466 {
1467 new_layout.right_buttons_has_spacer[i-2] = TRUE(!(0));
1468 }
1469 }
1470 else
1471 {
1472 if (f != META_BUTTON_FUNCTION_LAST && !used[f])
1473 {
1474 new_layout.right_buttons[i] = f;
1475 used[f] = TRUE(!(0));
1476 ++i;
1477
1478 f = button_opposite_function (f);
1479
1480 if (f != META_BUTTON_FUNCTION_LAST)
1481 new_layout.right_buttons[i++] = f;
1482
1483 }
1484 else
1485 {
1486 meta_topicmeta_topic_real (META_DEBUG_PREFS, "Ignoring unknown or already-used button name \"%s\"\n",
1487 buttons[b]);
1488 }
1489 }
1490
1491 ++b;
1492 }
1493
1494 new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1495 new_layout.right_buttons_has_spacer[i] = FALSE(0);
1496
1497 g_strfreev (buttons);
1498 }
1499
1500 g_strfreev (sides);
1501
1502 /* Invert the button layout for RTL languages */
1503 if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
2
Assuming the condition is false
3
Taking false branch
1504 {
1505 MetaButtonLayout rtl_layout;
1506 int j;
1507
1508 for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
1509 for (j = 0; j < i; j++)
1510 {
1511 rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
1512 if (j == 0)
1513 rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
1514 else
1515 rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
1516 }
1517 rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
1518 rtl_layout.right_buttons_has_spacer[j] = FALSE(0);
1519
1520 for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
1521 for (j = 0; j < i; j++)
1522 {
1523 rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
1524 if (j == 0)
1525 rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
1526 else
1527 rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
1528 }
1529 rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
1530 rtl_layout.left_buttons_has_spacer[j] = FALSE(0);
1531
1532 new_layout = rtl_layout;
1533 }
1534
1535 if (button_layout_equal (&button_layout, &new_layout))
4
Calling 'button_layout_equal'
1536 {
1537 /* Same as before, so duck out */
1538 *inform_listeners = FALSE(0);
1539 }
1540 else
1541 {
1542 button_layout = new_layout;
1543 }
1544}
1545
1546const PangoFontDescription*
1547meta_prefs_get_titlebar_font (void)
1548{
1549 if (use_system_font)
1550 return NULL((void*)0);
1551 else
1552 return titlebar_font;
1553}
1554
1555int
1556meta_prefs_get_num_workspaces (void)
1557{
1558 return num_workspaces;
1559}
1560
1561MetaWrapStyle
1562meta_prefs_get_wrap_style (void)
1563{
1564 return wrap_style;
1565}
1566
1567gboolean
1568meta_prefs_get_application_based (void)
1569{
1570 return FALSE(0); /* For now, we never want this to do anything */
1571
1572 return application_based;
1573}
1574
1575gboolean
1576meta_prefs_get_disable_workarounds (void)
1577{
1578 return disable_workarounds;
1579}
1580
1581#define MAX_REASONABLE_AUTO_RAISE_DELAY10000 10000
1582
1583#ifdef WITH_VERBOSE_MODE1
1584const char*
1585meta_preference_to_string (MetaPreference pref)
1586{
1587 /* FIXME: another case for g_settings_get_enum */
1588 switch (pref)
1589 {
1590 case META_PREF_MOUSE_BUTTON_MODS:
1591 return "MOUSE_BUTTON_MODS";
1592
1593 case META_PREF_FOCUS_MODE:
1594 return "FOCUS_MODE";
1595
1596 case META_PREF_FOCUS_NEW_WINDOWS:
1597 return "FOCUS_NEW_WINDOWS";
1598
1599 case META_PREF_ATTACH_MODAL_DIALOGS:
1600 return "ATTACH_MODAL_DIALOGS";
1601
1602 case META_PREF_RAISE_ON_CLICK:
1603 return "RAISE_ON_CLICK";
1604
1605 case META_PREF_THEME:
1606 return "THEME";
1607
1608 case META_PREF_TITLEBAR_FONT:
1609 return "TITLEBAR_FONT";
1610
1611 case META_PREF_NUM_WORKSPACES:
1612 return "NUM_WORKSPACES";
1613
1614 case META_PREF_WRAP_STYLE:
1615 return "WRAP_STYLE";
1616
1617 case META_PREF_APPLICATION_BASED:
1618 return "APPLICATION_BASED";
1619
1620 case META_PREF_KEYBINDINGS:
1621 return "KEYBINDINGS";
1622
1623 case META_PREF_DISABLE_WORKAROUNDS:
1624 return "DISABLE_WORKAROUNDS";
1625
1626 case META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR:
1627 return "ACTION_DOUBLE_CLICK_TITLEBAR";
1628
1629 case META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR:
1630 return "ACTION_MIDDLE_CLICK_TITLEBAR";
1631
1632 case META_PREF_ACTION_RIGHT_CLICK_TITLEBAR:
1633 return "ACTION_RIGHT_CLICK_TITLEBAR";
1634
1635 case META_PREF_AUTO_RAISE:
1636 return "AUTO_RAISE";
1637
1638 case META_PREF_AUTO_RAISE_DELAY:
1639 return "AUTO_RAISE_DELAY";
1640
1641 case META_PREF_COMMANDS:
1642 return "COMMANDS";
1643
1644 case META_PREF_TERMINAL_COMMAND:
1645 return "TERMINAL_COMMAND";
1646
1647 case META_PREF_BUTTON_LAYOUT:
1648 return "BUTTON_LAYOUT";
1649
1650 case META_PREF_WORKSPACE_NAMES:
1651 return "WORKSPACE_NAMES";
1652
1653 case META_PREF_VISUAL_BELL:
1654 return "VISUAL_BELL";
1655
1656 case META_PREF_AUDIBLE_BELL:
1657 return "AUDIBLE_BELL";
1658
1659 case META_PREF_VISUAL_BELL_TYPE:
1660 return "VISUAL_BELL_TYPE";
1661
1662 case META_PREF_REDUCED_RESOURCES:
1663 return "REDUCED_RESOURCES";
1664
1665 case META_PREF_CAFE_ACCESSIBILITY:
1666 return "CAFE_ACCESSIBILTY";
1667
1668 case META_PREF_CAFE_ANIMATIONS:
1669 return "CAFE_ANIMATIONS";
1670
1671 case META_PREF_CURSOR_THEME:
1672 return "CURSOR_THEME";
1673
1674 case META_PREF_CURSOR_SIZE:
1675 return "CURSOR_SIZE";
1676
1677 case META_PREF_ICON_SIZE:
1678 return "ICON_SIZE";
1679
1680 case META_PREF_ALT_TAB_MAX_COLUMNS:
1681 return "ALT_TAB_MAX_COLUMNS";
1682
1683 case META_PREF_ALT_TAB_EXPAND_TO_FIT_TITLE:
1684 return "ALT_TAB_EXPAND_TO_FIT_TITLE";
1685
1686 case META_PREF_COMPOSITING_MANAGER:
1687 return "COMPOSITING_MANAGER";
1688
1689 case META_PREF_COMPOSITING_FAST_ALT_TAB:
1690 return "COMPOSITING_FAST_ALT_TAB";
1691
1692 case META_PREF_CENTER_NEW_WINDOWS:
1693 return "CENTER_NEW_WINDOWS";
1694
1695 case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
1696 return "RESIZE_WITH_RIGHT_BUTTON";
1697
1698 case META_PREF_SHOW_TAB_BORDER:
1699 return "SHOW_TAB_BORDER";
1700
1701 case META_PREF_FORCE_FULLSCREEN:
1702 return "FORCE_FULLSCREEN";
1703
1704 case META_PREF_ALLOW_TILING:
1705 return "ALLOW_TILING";
1706
1707 case META_PREF_ALLOW_TOP_TILING:
1708 return "ALLOW_TOP_TILING";
1709
1710 case META_PREF_ALLOW_TILE_CYCLING:
1711 return "ALLOW_TILE_CYCLING";
1712
1713 case META_PREF_PLACEMENT_MODE:
1714 return "PLACEMENT_MODE";
1715
1716 case META_PREF_SHOW_DESKTOP_SKIP_LIST:
1717 return "SHOW_DESKTOP_SKIP_LIST";
1718 }
1719
1720 return "(unknown)";
1721}
1722#endif /* WITH_VERBOSE_MODE */
1723
1724void
1725meta_prefs_set_num_workspaces (int n_workspaces)
1726{
1727 if (n_workspaces < 1)
1728 n_workspaces = 1;
1729 if (n_workspaces > MAX_REASONABLE_WORKSPACES36)
1730 n_workspaces = MAX_REASONABLE_WORKSPACES36;
1731
1732 g_settings_set_int (settings_general,
1733 KEY_GENERAL_NUM_WORKSPACES"num-workspaces",
1734 n_workspaces);
1735
1736}
1737
1738#define keybind(name, handler, param, flags) \
1739 { #name, NULL((void*)0), !!(flags & BINDING_REVERSES0x02), !!(flags & BINDING_PER_WINDOW0x01) },
1740static MetaKeyPref key_bindings[] = {
1741#include "all-keybindings.h"
1742 { .add_shift = FALSE(0) }
1743};
1744#undef keybind
1745
1746static void
1747init_bindings (GSettings *settings)
1748{
1749 GSettingsSchema *schema;
1750 gchar **list = NULL((void*)0);
1751 gchar *str_val = NULL((void*)0);
1752
1753 g_object_get (settings, "settings-schema", &schema, NULL((void*)0));
1754 list = g_settings_schema_list_keys (schema);
1755 g_settings_schema_unref (schema);
1756
1757 while (*list != NULL((void*)0))
1758 {
1759 str_val = g_settings_get_string (settings, *list);
1760 update_key_binding (*list, str_val);
1761 list++;
1762 }
1763
1764 g_free (str_val);
1765}
1766
1767static void
1768init_screen_bindings (void)
1769{
1770 init_bindings (settings_screen_bindings);
1771}
1772
1773static void
1774init_window_bindings (void)
1775{
1776 init_bindings (settings_window_bindings);
1777}
1778
1779static void
1780init_commands (void)
1781{
1782 GSettingsSchema *schema;
1783 gchar **list = NULL((void*)0);
1784 gchar *str_val = NULL((void*)0);
1785
1786 g_object_get (settings_command, "settings-schema", &schema, NULL((void*)0));
1787 list = g_settings_schema_list_keys (schema);
1788 g_settings_schema_unref (schema);
1789
1790 while (*list != NULL((void*)0))
1791 {
1792 str_val = g_settings_get_string (settings_command, *list);
1793 update_command (*list, str_val);
1794 list++;
1795 }
1796
1797 g_free (str_val);
1798}
1799
1800static void
1801init_workspace_names (void)
1802{
1803 GSettingsSchema *schema;
1804 gchar **list = NULL((void*)0);
1805 gchar *str_val = NULL((void*)0);
1806
1807 g_object_get (settings_workspace_names, "settings-schema", &schema, NULL((void*)0));
1808 list = g_settings_schema_list_keys (schema);
1809 g_settings_schema_unref (schema);
1810
1811 while (*list != NULL((void*)0))
1812 {
1813 str_val = g_settings_get_string (settings_workspace_names, *list);
1814 update_workspace_name (*list, str_val);
1815 list++;
1816 }
1817
1818 g_free (str_val);
1819}
1820
1821static gboolean
1822update_binding (MetaKeyPref *binding,
1823 gchar *value)
1824{
1825 unsigned int keysym;
1826 unsigned int keycode;
1827 MetaVirtualModifier mods;
1828 MetaKeyCombo *combo;
1829 gboolean changed;
1830
1831 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1832 "Binding \"%s\" has new GSettings value \"%s\"\n",
1833 binding->name, value ? value : "none");
1834
1835 keysym = 0;
1836 keycode = 0;
1837 mods = 0;
1838 if (value)
1839 {
1840 if (!meta_ui_parse_accelerator (value, &keysym, &keycode, &mods))
1841 {
1842 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1843 "Failed to parse new GSettings value\n");
1844 meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n")dgettext ("croma", "\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"
)
,
1845 value, binding->name);
1846
1847 return FALSE(0);
1848 }
1849 }
1850
1851 /* If there isn't already a first element, make one. */
1852 if (!binding->bindings)
1853 {
1854 MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
1855 binding->bindings = g_slist_alloc();
1856 binding->bindings->data = blank;
1857 }
1858
1859 combo = binding->bindings->data;
1860
1861 /* Bug 329676: Bindings which can be shifted must not have no modifiers,
1862 * nor only SHIFT as a modifier.
1863 */
1864
1865 if (binding->add_shift &&
1866 0 != keysym &&
1867 (META_VIRTUAL_SHIFT_MASK == mods || 0 == mods))
1868 {
1869 gchar *old_setting;
1870
1871 meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
1872 "such as Ctrl or Alt.\n",
1873 binding->name,
1874 value);
1875
1876 old_setting = meta_ui_accelerator_name (combo->keysym,
1877 combo->modifiers);
1878
1879 if (!strcmp(old_setting, value))
1880 {
1881 /* We were about to set it to the same value
1882 * that it had originally! This must be caused
1883 * by getting an invalid string back from
1884 * meta_ui_accelerator_name. Bail out now
1885 * so we don't get into an infinite loop.
1886 */
1887 g_free (old_setting);
1888 return TRUE(!(0));
1889 }
1890
1891 meta_warning ("Reverting \"%s\" to %s.\n",
1892 binding->name,
1893 old_setting);
1894
1895 /* FIXME: add_shift is currently screen_bindings only, but
1896 * there's no really good reason it should always be.
1897 * So we shouldn't blindly add KEY_SCREEN_BINDINGS_PREFIX
1898 * onto here.
1899 */
1900 g_settings_set_string(settings_screen_bindings,
1901 binding->name,
1902 old_setting);
1903
1904 g_free (old_setting);
1905
1906 /* The call to g_settings_set_string() will cause this function
1907 * to be called again with the new value, so there's no need to
1908 * carry on.
1909 */
1910 return TRUE(!(0));
1911 }
1912
1913 changed = FALSE(0);
1914 if (keysym != combo->keysym ||
1915 keycode != combo->keycode ||
1916 mods != combo->modifiers)
1917 {
1918 changed = TRUE(!(0));
1919
1920 combo->keysym = keysym;
1921 combo->keycode = keycode;
1922 combo->modifiers = mods;
1923
1924 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1925 "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
1926 binding->name, combo->keysym, combo->keycode,
1927 combo->modifiers);
1928 }
1929 else
1930 {
1931 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1932 "Keybinding for \"%s\" is unchanged\n", binding->name);
1933 }
1934
1935 return changed;
1936}
1937
1938static const gchar*
1939relative_key (const gchar* key)
1940{
1941 const gchar* end;
1942
1943 end = strrchr (key, '/');
1944
1945 ++end;
1946
1947 return end;
1948}
1949
1950/* Return value is TRUE if a preference changed and we need to
1951 * notify
1952 */
1953static gboolean
1954find_and_update_binding (MetaKeyPref *bindings,
1955 const char *name,
1956 gchar *value)
1957{
1958 const char *key;
1959 int i;
1960
1961 if (*name == '/')
1962 key = relative_key (name);
1963 else
1964 key = name;
1965
1966 i = 0;
1967 while (bindings[i].name &&
1968 strcmp (key, bindings[i].name) != 0)
1969 ++i;
1970
1971 if (bindings[i].name)
1972 return update_binding (&bindings[i], value);
1973 else
1974 return FALSE(0);
1975}
1976
1977static gboolean
1978update_key_binding (const char *name,
1979 gchar *value)
1980{
1981 return find_and_update_binding (key_bindings, name, value);
1982}
1983
1984static gboolean
1985update_command (const char *name,
1986 const char *value)
1987{
1988 char *p;
1989 int i;
1990
1991 p = strrchr (name, '-');
1992 if (p == NULL((void*)0))
1993 {
1994 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
1995 "Command %s has no dash?\n", name);
1996 return FALSE(0);
1997 }
1998
1999 ++p;
2000
2001 if (g_ascii_isdigit (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0))
2002 {
2003 i = atoi (p);
2004 i -= 1; /* count from 0 not 1 */
2005 }
2006 else
2007 {
2008 if (strcmp (name, "command-screenshot") == 0)
2009 {
2010 i = SCREENSHOT_COMMAND_IDX((32 + 2) - 2);
2011 }
2012 else if (strcmp (name, "command-window-screenshot") == 0)
2013 {
2014 i = WIN_SCREENSHOT_COMMAND_IDX((32 + 2) - 1);
2015 }
2016 else
2017 {
2018 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
2019 "Command %s doesn't end in number?\n", name);
2020 return FALSE(0);
2021 }
2022 }
2023
2024 if (i >= MAX_COMMANDS(32 + 2))
2025 {
2026 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
2027 "Command %d is too highly numbered, ignoring\n", i);
2028 return FALSE(0);
2029 }
2030
2031 if ((commands[i] == NULL((void*)0) && value == NULL((void*)0)) ||
2032 (commands[i] && value && strcmp (commands[i], value) == 0))
2033 {
2034 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
2035 "Command %d is unchanged\n", i);
2036 return FALSE(0);
2037 }
2038
2039 g_free (commands[i]);
2040 commands[i] = g_strdup (value)g_strdup_inline (value);
2041
2042 meta_topicmeta_topic_real (META_DEBUG_KEYBINDINGS,
2043 "Updated command %d to \"%s\"\n",
2044 i, commands[i] ? commands[i] : "none");
2045
2046 return TRUE(!(0));
2047}
2048
2049const char*
2050meta_prefs_get_command (int i)
2051{
2052 g_return_val_if_fail (i >= 0 && i < MAX_COMMANDS, NULL)do { if ((i >= 0 && i < (32 + 2))) { } else { g_return_if_fail_warning
("croma", ((const char*) (__func__)), "i >= 0 && i < MAX_COMMANDS"
); return (((void*)0)); } } while (0)
;
2053
2054 return commands[i];
2055}
2056
2057char*
2058meta_prefs_get_settings_key_for_command (int i)
2059{
2060 char *key;
2061
2062 switch (i)
2063 {
2064 case SCREENSHOT_COMMAND_IDX((32 + 2) - 2):
2065 key = g_strdup (KEY_COMMAND_PREFIX "screenshot")g_strdup_inline ("command-" "screenshot");
2066 break;
2067 case WIN_SCREENSHOT_COMMAND_IDX((32 + 2) - 1):
2068 key = g_strdup (KEY_COMMAND_PREFIX "window-screenshot")g_strdup_inline ("command-" "window-screenshot");
2069 break;
2070 default:
2071 key = g_strdup_printf (KEY_COMMAND_PREFIX"command-""%d", i + 1);
2072 break;
2073 }
2074
2075 return key;
2076}
2077
2078const char*
2079meta_prefs_get_terminal_command (void)
2080{
2081 return terminal_command;
2082}
2083
2084const char*
2085meta_prefs_get_settings_key_for_terminal_command (void)
2086{
2087 return KEY_CAFE_TERMINAL_COMMAND"exec";
2088}
2089
2090static gboolean
2091update_workspace_name (const char *name,
2092 const char *value)
2093{
2094 char *p;
2095 int i;
2096
2097 p = strrchr (name, '-');
2098 if (p == NULL((void*)0))
2099 {
2100 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2101 "Workspace name %s has no dash?\n", name);
2102 return FALSE(0);
2103 }
2104
2105 ++p;
2106
2107 if (!g_ascii_isdigit (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0))
2108 {
2109 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2110 "Workspace name %s doesn't end in number?\n", name);
2111 return FALSE(0);
2112 }
2113
2114 i = atoi (p);
2115 i -= 1; /* count from 0 not 1 */
2116
2117 if (i >= MAX_REASONABLE_WORKSPACES36)
2118 {
2119 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2120 "Workspace name %d is too highly numbered, ignoring\n", i);
2121 return FALSE(0);
2122 }
2123
2124 if (workspace_names[i] && value && strcmp (workspace_names[i], value) == 0)
2125 {
2126 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2127 "Workspace name %d is unchanged\n", i);
2128 return FALSE(0);
2129 }
2130
2131 /* This is a bad hack. We have to treat empty string as
2132 * "unset" because the root window property can't contain
2133 * null. So it gets empty string instead and we don't want
2134 * that to result in setting the empty string as a value that
2135 * overrides "unset".
2136 */
2137 if (value != NULL((void*)0) && *value != '\0')
2138 {
2139 g_free (workspace_names[i]);
2140 workspace_names[i] = g_strdup (value)g_strdup_inline (value);
2141 }
2142 else
2143 {
2144 /* use a default name */
2145 char *d;
2146
2147 d = g_strdup_printf (_("Workspace %d")dgettext ("croma", "Workspace %d"), i + 1);
2148 if (workspace_names[i] && strcmp (workspace_names[i], d) == 0)
2149 {
2150 g_free (d);
2151 return FALSE(0);
2152 }
2153 else
2154 {
2155 g_free (workspace_names[i]);
2156 workspace_names[i] = d;
2157 }
2158 }
2159
2160 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2161 "Updated workspace name %d to \"%s\"\n",
2162 i, workspace_names[i] ? workspace_names[i] : "none");
2163
2164 return TRUE(!(0));
2165}
2166
2167const char*
2168meta_prefs_get_workspace_name (int i)
2169{
2170 g_return_val_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES, NULL)do { if ((i >= 0 && i < 36)) { } else { g_return_if_fail_warning
("croma", ((const char*) (__func__)), "i >= 0 && i < MAX_REASONABLE_WORKSPACES"
); return (((void*)0)); } } while (0)
;
2171
2172 g_assert (workspace_names[i] != NULL)do { if (workspace_names[i] != ((void*)0)) ; else g_assertion_message_expr
("croma", "core/prefs.c", 2172, ((const char*) (__func__)), "workspace_names[i] != NULL"
); } while (0)
;
2173
2174 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2175 "Getting workspace name for %d: \"%s\"\n",
2176 i, workspace_names[i]);
2177
2178 return workspace_names[i];
2179}
2180
2181void
2182meta_prefs_change_workspace_name (int i,
2183 const char *name)
2184{
2185 char *key;
2186
2187 g_return_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES)do { if ((i >= 0 && i < 36)) { } else { g_return_if_fail_warning
("croma", ((const char*) (__func__)), "i >= 0 && i < MAX_REASONABLE_WORKSPACES"
); return; } } while (0)
;
2188
2189 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2190 "Changing name of workspace %d to %s\n",
2191 i, name ? name : "none");
2192
2193 if (name && *name == '\0')
2194 name = NULL((void*)0);
2195
2196 if ((name == NULL((void*)0) && workspace_names[i] == NULL((void*)0)) ||
2197 (name && workspace_names[i] && strcmp (name, workspace_names[i]) == 0))
2198 {
2199 meta_topicmeta_topic_real (META_DEBUG_PREFS,
2200 "Workspace %d already has name %s\n",
2201 i, name ? name : "none");
2202 return;
2203 }
2204
2205 key = settings_key_for_workspace_name (i);
2206
2207 if (name != NULL((void*)0))
2208 g_settings_set_string (settings_workspace_names,
2209 key,
2210 name);
2211 else
2212 g_settings_set_string (settings_workspace_names,
2213 key,
2214 "");
2215
2216 g_free (key);
2217}
2218
2219static char*
2220settings_key_for_workspace_name (int i)
2221{
2222 char *key;
2223
2224 key = g_strdup_printf (KEY_WORKSPACE_NAME_PREFIX"name-""%d", i + 1);
2225
2226 return key;
2227}
2228
2229void
2230meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p)
2231{
2232 *button_layout_p = button_layout;
2233}
2234
2235gboolean
2236meta_prefs_get_visual_bell (void)
2237{
2238 return provide_visual_bell;
2239}
2240
2241gboolean
2242meta_prefs_bell_is_audible (void)
2243{
2244 return bell_is_audible;
2245}
2246
2247MetaVisualBellType
2248meta_prefs_get_visual_bell_type (void)
2249{
2250 return visual_bell_type;
2251}
2252
2253void
2254meta_prefs_get_key_bindings (const MetaKeyPref **bindings,
2255 int *n_bindings)
2256{
2257
2258 *bindings = key_bindings;
2259 *n_bindings = (int) G_N_ELEMENTS (key_bindings)(sizeof (key_bindings) / sizeof ((key_bindings)[0])) - 1;
2260}
2261
2262MetaActionTitlebar
2263meta_prefs_get_action_double_click_titlebar (void)
2264{
2265 return action_double_click_titlebar;
2266}
2267
2268MetaActionTitlebar
2269meta_prefs_get_action_middle_click_titlebar (void)
2270{
2271 return action_middle_click_titlebar;
2272}
2273
2274MetaActionTitlebar
2275meta_prefs_get_action_right_click_titlebar (void)
2276{
2277 return action_right_click_titlebar;
2278}
2279
2280gboolean
2281meta_prefs_get_auto_raise (void)
2282{
2283 return auto_raise;
2284}
2285
2286int
2287meta_prefs_get_auto_raise_delay (void)
2288{
2289 return auto_raise_delay;
2290}
2291
2292gboolean
2293meta_prefs_get_reduced_resources (void)
2294{
2295 return reduced_resources;
2296}
2297
2298gboolean
2299meta_prefs_get_cafe_accessibility ()
2300{
2301 return cafe_accessibility;
2302}
2303
2304gboolean
2305meta_prefs_get_cafe_animations ()
2306{
2307 return cafe_animations;
2308}
2309
2310MetaKeyBindingAction
2311meta_prefs_get_keybinding_action (const char *name)
2312{
2313 int i;
2314
2315 i = G_N_ELEMENTS (key_bindings)(sizeof (key_bindings) / sizeof ((key_bindings)[0])) - 2; /* -2 for dummy entry at end */
2316 while (i >= 0)
2317 {
2318 if (strcmp (key_bindings[i].name, name) == 0)
2319 return (MetaKeyBindingAction) i;
2320
2321 --i;
2322 }
2323
2324 return META_KEYBINDING_ACTION_NONE;
2325}
2326
2327/* This is used by the menu system to decide what key binding
2328 * to display next to an option. We return the first non-disabled
2329 * binding, if any.
2330 */
2331void
2332meta_prefs_get_window_binding (const char *name,
2333 unsigned int *keysym,
2334 MetaVirtualModifier *modifiers)
2335{
2336 int i;
2337
2338 i = G_N_ELEMENTS (key_bindings)(sizeof (key_bindings) / sizeof ((key_bindings)[0])) - 2; /* -2 for dummy entry at end */
2339 while (i >= 0)
2340 {
2341 if (key_bindings[i].per_window &&
2342 strcmp (key_bindings[i].name, name) == 0)
2343 {
2344 GSList *s = key_bindings[i].bindings;
2345
2346 while (s)
2347 {
2348 MetaKeyCombo *c = s->data;
2349
2350 if (c->keysym!=0 || c->modifiers!=0)
2351 {
2352 *keysym = c->keysym;
2353 *modifiers = c->modifiers;
2354 return;
2355 }
2356
2357 s = s->next;
2358 }
2359
2360 /* Not found; return the disabled value */
2361 *keysym = *modifiers = 0;
2362 return;
2363 }
2364
2365 --i;
2366 }
2367
2368 g_assert_not_reached ()do { g_assertion_message_expr ("croma", "core/prefs.c", 2368,
((const char*) (__func__)), ((void*)0)); } while (0)
;
2369}
2370
2371gboolean
2372meta_prefs_get_compositing_manager (void)
2373{
2374 if (use_force_compositor_manager)
2375 return force_compositor_manager;
2376 return compositing_manager;
2377}
2378
2379gboolean
2380meta_prefs_get_compositing_fast_alt_tab (void)
2381{
2382 return compositing_fast_alt_tab;
2383}
2384
2385gboolean
2386meta_prefs_get_center_new_windows (void)
2387{
2388 return center_new_windows;
2389}
2390
2391gboolean
2392meta_prefs_get_allow_tiling ()
2393{
2394 return allow_tiling;
2395}
2396
2397gboolean
2398meta_prefs_get_allow_top_tiling ()
2399{
2400 return allow_top_tiling;
2401}
2402
2403gboolean
2404meta_prefs_get_allow_tile_cycling ()
2405{
2406 return allow_tile_cycling;
2407}
2408
2409guint
2410meta_prefs_get_mouse_button_resize (void)
2411{
2412 return resize_with_right_button ? 3: 2;
2413}
2414
2415guint
2416meta_prefs_get_mouse_button_menu (void)
2417{
2418 return resize_with_right_button ? 2: 3;
2419}
2420
2421gboolean
2422meta_prefs_show_tab_border(void)
2423{
2424 return show_tab_border;
2425}
2426
2427gboolean
2428meta_prefs_get_force_fullscreen (void)
2429{
2430 return force_fullscreen;
2431}
2432
2433MetaPlacementMode
2434meta_prefs_get_placement_mode (void)
2435{
2436 return placement_mode;
2437}
2438
2439void
2440meta_prefs_set_force_compositing_manager (gboolean whether)
2441{
2442 use_force_compositor_manager = TRUE(!(0));
2443 force_compositor_manager = whether;
2444}
2445
2446void
2447meta_prefs_set_compositing_fast_alt_tab (gboolean whether)
2448{
2449 g_settings_set_boolean (settings_general,
2450 KEY_GENERAL_COMPOSITOR_FAST_ALT_TAB"compositing-fast-alt-tab",
2451 whether);
2452}
2453
2454void
2455meta_prefs_set_center_new_windows (gboolean whether)
2456{
2457 g_settings_set_boolean (settings_general,
2458 KEY_GENERAL_CENTER_NEW_WINDOWS"center-new-windows",
2459 whether);
2460}
2461
2462void
2463meta_prefs_set_force_fullscreen (gboolean whether)
2464{
2465 force_fullscreen = whether;
2466}
2467