File: | plugins/xrandr/csd_xrandr-manager.c |
Warning: | line 802, column 34 Although the value stored to 'best_height' is used in the enclosing expression, the value is never actually read from 'best_height' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
2 | * |
3 | * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> |
4 | * Copyright (C) 2007, 2008 Red Hat, Inc |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
19 | * |
20 | */ |
21 | |
22 | #include "config.h" |
23 | |
24 | #include <sys/types.h> |
25 | #include <sys/wait.h> |
26 | #include <sys/stat.h> |
27 | #include <stdlib.h> |
28 | #include <stdio.h> |
29 | #include <unistd.h> |
30 | #include <string.h> |
31 | #include <errno(*__errno_location ()).h> |
32 | |
33 | #include <locale.h> |
34 | |
35 | #include <glib.h> |
36 | #include <glib/gi18n.h> |
37 | #include <cdk/cdk.h> |
38 | #include <cdk/cdkx.h> |
39 | #include <ctk/ctk.h> |
40 | #include <gio/gio.h> |
41 | #include <dbus/dbus-glib.h> |
42 | |
43 | #define CAFE_DESKTOP_USE_UNSTABLE_API |
44 | #include <libcafe-desktop/cafe-rr-config.h> |
45 | #include <libcafe-desktop/cafe-rr.h> |
46 | #include <libcafe-desktop/cafe-rr-labeler.h> |
47 | #include <libcafe-desktop/cafe-desktop-utils.h> |
48 | |
49 | #ifdef HAVE_LIBNOTIFY1 |
50 | #include <libnotify/notify.h> |
51 | #endif |
52 | |
53 | #ifdef HAVE_RDA |
54 | #include <rda/rda.h> |
55 | #endif |
56 | |
57 | #include "cafe-settings-profile.h" |
58 | #include "csd_xrandr-manager.h" |
59 | |
60 | #define CONF_SCHEMA"org.cafe.SettingsDaemon.plugins.xrandr" "org.cafe.SettingsDaemon.plugins.xrandr" |
61 | #define CONF_KEY_SHOW_NOTIFICATION_ICON"show-notification-icon" "show-notification-icon" |
62 | #define CONF_KEY_USE_XORG_MONITOR_SETTINGS"use-xorg-monitor-settings" "use-xorg-monitor-settings" |
63 | #define CONF_KEY_TURN_ON_EXTERNAL_MONITORS_AT_STARTUP"turn-on-external-monitors-at-startup" "turn-on-external-monitors-at-startup" |
64 | #define CONF_KEY_TURN_ON_LAPTOP_MONITOR_AT_STARTUP"turn-on-laptop-monitor-at-startup" "turn-on-laptop-monitor-at-startup" |
65 | #define CONF_KEY_DEFAULT_CONFIGURATION_FILE"default-configuration-file" "default-configuration-file" |
66 | |
67 | #define VIDEO_KEYSYM"XF86Display" "XF86Display" |
68 | #define ROTATE_KEYSYM"XF86RotateWindows" "XF86RotateWindows" |
69 | |
70 | /* Number of seconds that the confirmation dialog will last before it resets the |
71 | * RANDR configuration to its old state. |
72 | */ |
73 | #define CONFIRMATION_DIALOG_SECONDS30 30 |
74 | |
75 | /* name of the icon files (csd_xrandr.svg, etc.) */ |
76 | #define CSD_XRANDR_ICON_NAME"csd_xrandr" "csd_xrandr" |
77 | |
78 | /* executable of the control center's display configuration capplet */ |
79 | #define CSD_XRANDR_DISPLAY_CAPPLET"cafe-display-properties" "cafe-display-properties" |
80 | |
81 | #define CSD_DBUS_PATH"/org/cafe/SettingsDaemon" "/org/cafe/SettingsDaemon" |
82 | #define CSD_DBUS_NAME"org.cafe.SettingsDaemon" "org.cafe.SettingsDaemon" |
83 | #define CSD_XRANDR_DBUS_PATH"/org/cafe/SettingsDaemon" "/XRANDR" CSD_DBUS_PATH"/org/cafe/SettingsDaemon" "/XRANDR" |
84 | #define CSD_XRANDR_DBUS_NAME"org.cafe.SettingsDaemon" ".XRANDR" CSD_DBUS_NAME"org.cafe.SettingsDaemon" ".XRANDR" |
85 | |
86 | struct CsdXrandrManagerPrivate |
87 | { |
88 | DBusGConnection *dbus_connection; |
89 | |
90 | /* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */ |
91 | guint switch_video_mode_keycode; |
92 | |
93 | /* Key code of the XF86RotateWindows key (present on some tablets) */ |
94 | guint rotate_windows_keycode; |
95 | |
96 | CafeRRScreen *rw_screen; |
97 | gboolean running; |
98 | |
99 | CtkStatusIcon *status_icon; |
100 | CtkWidget *popup_menu; |
101 | CafeRRConfig *configuration; |
102 | CafeRRLabeler *labeler; |
103 | GSettings *settings; |
104 | |
105 | /* fn-F7 status */ |
106 | int current_fn_f7_config; /* -1 if no configs */ |
107 | CafeRRConfig **fn_f7_configs; /* NULL terminated, NULL if there are no configs */ |
108 | |
109 | /* Last time at which we got a "screen got reconfigured" event; see on_randr_event() */ |
110 | guint32 last_config_timestamp; |
111 | }; |
112 | |
113 | static const CafeRRRotation possible_rotations[] = { |
114 | CAFE_RR_ROTATION_0, |
115 | CAFE_RR_ROTATION_90, |
116 | CAFE_RR_ROTATION_180, |
117 | CAFE_RR_ROTATION_270 |
118 | /* We don't allow REFLECT_X or REFLECT_Y for now, as cafe-display-properties doesn't allow them, either */ |
119 | }; |
120 | |
121 | static void csd_xrandr_manager_finalize (GObject *object); |
122 | |
123 | static void error_message (CsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text); |
124 | |
125 | static void status_icon_popup_menu (CsdXrandrManager *manager, guint button, guint32 timestamp); |
126 | static void run_display_capplet (CtkWidget *widget); |
127 | static void get_allowed_rotations_for_output (CafeRRConfig *config, |
128 | CafeRRScreen *rr_screen, |
129 | CafeRROutputInfo *output, |
130 | int *out_num_rotations, |
131 | CafeRRRotation *out_rotations); |
132 | |
133 | G_DEFINE_TYPE_WITH_PRIVATE (CsdXrandrManager, csd_xrandr_manager, G_TYPE_OBJECT)static void csd_xrandr_manager_init (CsdXrandrManager *self); static void csd_xrandr_manager_class_init (CsdXrandrManagerClass *klass); static GType csd_xrandr_manager_get_type_once (void ); static gpointer csd_xrandr_manager_parent_class = ((void*) 0); static gint CsdXrandrManager_private_offset; static void csd_xrandr_manager_class_intern_init (gpointer klass) { csd_xrandr_manager_parent_class = g_type_class_peek_parent (klass); if (CsdXrandrManager_private_offset != 0) g_type_class_adjust_private_offset (klass, &CsdXrandrManager_private_offset); csd_xrandr_manager_class_init ((CsdXrandrManagerClass*) klass); } __attribute__ ((__unused__ )) static inline gpointer csd_xrandr_manager_get_instance_private (CsdXrandrManager *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CsdXrandrManager_private_offset)))); } GType csd_xrandr_manager_get_type (void) { static gsize static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id )); }))) { GType g_define_type_id = csd_xrandr_manager_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id) = (g_define_type_id) ) : (void) 0; g_once_init_leave ((&static_g_define_type_id ), (gsize) (g_define_type_id)); })); } return static_g_define_type_id ; } __attribute__ ((__noinline__)) static GType csd_xrandr_manager_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple (((GType) ((20) << (2))), g_intern_static_string ("CsdXrandrManager" ), sizeof (CsdXrandrManagerClass), (GClassInitFunc)(void (*)( void)) csd_xrandr_manager_class_intern_init, sizeof (CsdXrandrManager ), (GInstanceInitFunc)(void (*)(void)) csd_xrandr_manager_init , (GTypeFlags) 0); { {{ CsdXrandrManager_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CsdXrandrManagerPrivate)); };} } return g_define_type_id; } |
134 | |
135 | static gpointer manager_object = NULL((void*)0); |
136 | |
137 | static FILE *log_file; |
138 | |
139 | static void |
140 | log_open (void) |
141 | { |
142 | char *toggle_filename; |
143 | char *log_filename; |
144 | struct stat st; |
145 | |
146 | if (log_file) |
147 | return; |
148 | |
149 | toggle_filename = g_build_filename (g_get_home_dir (), "csd_debug-randr", NULL((void*)0)); |
150 | log_filename = g_build_filename (g_get_home_dir (), "csd_debug-randr.log", NULL((void*)0)); |
151 | |
152 | if (stat (toggle_filename, &st) != 0) |
153 | goto out; |
154 | |
155 | log_file = fopen (log_filename, "a"); |
156 | |
157 | if (log_file && ftell (log_file) == 0) |
158 | fprintf (log_file, "To keep this log from being created, please rm ~/csd_debug-randr\n"); |
159 | |
160 | out: |
161 | g_free (toggle_filename); |
162 | g_free (log_filename); |
163 | } |
164 | |
165 | static void |
166 | log_close (void) |
167 | { |
168 | if (log_file) { |
169 | fclose (log_file); |
170 | log_file = NULL((void*)0); |
171 | } |
172 | } |
173 | |
174 | static void |
175 | log_msg (const char *format, ...) |
176 | { |
177 | if (log_file) { |
178 | va_list args; |
179 | |
180 | va_start (args, format)__builtin_va_start(args, format); |
181 | vfprintf (log_file, format, args); |
182 | va_end (args)__builtin_va_end(args); |
183 | } |
184 | } |
185 | |
186 | static void |
187 | log_output (CafeRROutputInfo *output) |
188 | { |
189 | gchar *name = cafe_rr_output_info_get_name (output); |
190 | gchar *display_name = cafe_rr_output_info_get_display_name (output); |
191 | |
192 | log_msg (" %s: ", name ? name : "unknown"); |
193 | |
194 | if (cafe_rr_output_info_is_connected (output)) { |
195 | if (cafe_rr_output_info_is_active (output)) { |
196 | int x, y, width, height; |
197 | cafe_rr_output_info_get_geometry (output, &x, &y, &width, &height); |
198 | log_msg ("%dx%d@%d +%d+%d", |
199 | width, |
200 | height, |
201 | cafe_rr_output_info_get_refresh_rate (output), |
202 | x, |
203 | y); |
204 | } else |
205 | log_msg ("off"); |
206 | } else |
207 | log_msg ("disconnected"); |
208 | |
209 | if (display_name) |
210 | log_msg (" (%s)", display_name); |
211 | |
212 | if (cafe_rr_output_info_get_primary (output)) |
213 | log_msg (" (primary output)"); |
214 | |
215 | log_msg ("\n"); |
216 | } |
217 | |
218 | static void |
219 | log_configuration (CafeRRConfig *config) |
220 | { |
221 | int i; |
222 | CafeRROutputInfo **outputs = cafe_rr_config_get_outputs (config); |
223 | |
224 | log_msg (" cloned: %s\n", cafe_rr_config_get_clone (config) ? "yes" : "no"); |
225 | |
226 | for (i = 0; outputs[i] != NULL((void*)0); i++) |
227 | log_output (outputs[i]); |
228 | |
229 | if (i == 0) |
230 | log_msg (" no outputs!\n"); |
231 | } |
232 | |
233 | static char |
234 | timestamp_relationship (guint32 a, guint32 b) |
235 | { |
236 | if (a < b) |
237 | return '<'; |
238 | else if (a > b) |
239 | return '>'; |
240 | else |
241 | return '='; |
242 | } |
243 | |
244 | static void |
245 | log_screen (CafeRRScreen *screen) |
246 | { |
247 | CafeRRConfig *config; |
248 | int min_w, min_h, max_w, max_h; |
249 | guint32 change_timestamp, config_timestamp; |
250 | |
251 | if (!log_file) |
252 | return; |
253 | |
254 | config = cafe_rr_config_new_current (screen, NULL((void*)0)); |
255 | |
256 | cafe_rr_screen_get_ranges (screen, &min_w, &max_w, &min_h, &max_h); |
257 | cafe_rr_screen_get_timestamps (screen, &change_timestamp, &config_timestamp); |
258 | |
259 | log_msg (" Screen min(%d, %d), max(%d, %d), change=%u %c config=%u\n", |
260 | min_w, min_h, |
261 | max_w, max_h, |
262 | change_timestamp, |
263 | timestamp_relationship (change_timestamp, config_timestamp), |
264 | config_timestamp); |
265 | |
266 | log_configuration (config); |
267 | g_object_unref (config); |
268 | } |
269 | |
270 | static void |
271 | log_configurations (CafeRRConfig **configs) |
272 | { |
273 | int i; |
274 | |
275 | if (!configs) { |
276 | log_msg (" No configurations\n"); |
277 | return; |
278 | } |
279 | |
280 | for (i = 0; configs[i]; i++) { |
281 | log_msg (" Configuration %d\n", i); |
282 | log_configuration (configs[i]); |
283 | } |
284 | } |
285 | |
286 | static void |
287 | show_timestamps_dialog (CsdXrandrManager *manager, const char *msg) |
288 | { |
289 | #if 1 |
290 | return; |
291 | #else |
292 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
293 | CtkWidget *dialog; |
294 | guint32 change_timestamp, config_timestamp; |
295 | static int serial; |
296 | |
297 | cafe_rr_screen_get_timestamps (priv->rw_screen, &change_timestamp, &config_timestamp); |
298 | |
299 | dialog = ctk_message_dialog_new (NULL((void*)0), |
300 | 0, |
301 | CTK_MESSAGE_INFO, |
302 | CTK_BUTTONS_CLOSE, |
303 | "RANDR timestamps (%d):\n%s\nchange: %u\nconfig: %u", |
304 | serial++, |
305 | msg, |
306 | change_timestamp, |
307 | config_timestamp); |
308 | g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
309 | G_CALLBACK (ctk_widget_destroy), NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
310 | ctk_widget_show (dialog); |
311 | #endif |
312 | } |
313 | |
314 | /* This function centralizes the use of cafe_rr_config_apply_from_filename_with_time(). |
315 | * |
316 | * Optionally filters out CAFE_RR_ERROR_NO_MATCHING_CONFIG from |
317 | * cafe_rr_config_apply_from_filename_with_time(), since that is not usually an error. |
318 | */ |
319 | static gboolean |
320 | apply_configuration_from_filename (CsdXrandrManager *manager, |
321 | const char *filename, |
322 | gboolean no_matching_config_is_an_error, |
323 | guint32 timestamp, |
324 | GError **error) |
325 | { |
326 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
327 | GError *my_error; |
328 | gboolean success; |
329 | char *str; |
330 | |
331 | str = g_strdup_printf ("Applying %s with timestamp %d", filename, timestamp); |
332 | show_timestamps_dialog (manager, str); |
333 | g_free (str); |
334 | |
335 | my_error = NULL((void*)0); |
336 | success = cafe_rr_config_apply_from_filename_with_time (priv->rw_screen, filename, timestamp, &my_error); |
337 | if (success) |
338 | return TRUE(!(0)); |
339 | |
340 | if (g_error_matches (my_error, CAFE_RR_ERROR(cafe_rr_error_quark ()), CAFE_RR_ERROR_NO_MATCHING_CONFIG)) { |
341 | if (no_matching_config_is_an_error) |
342 | goto fail; |
343 | |
344 | /* This is not an error; the user probably changed his monitors |
345 | * and so they don't match any of the stored configurations. |
346 | */ |
347 | g_error_free (my_error); |
348 | return TRUE(!(0)); |
349 | } |
350 | |
351 | fail: |
352 | g_propagate_error (error, my_error); |
353 | return FALSE(0); |
354 | } |
355 | |
356 | /* This function centralizes the use of cafe_rr_config_apply_with_time(). |
357 | * |
358 | * Applies a configuration and displays an error message if an error happens. |
359 | * We just return whether setting the configuration succeeded. |
360 | */ |
361 | static gboolean |
362 | apply_configuration_and_display_error (CsdXrandrManager *manager, CafeRRConfig *config, guint32 timestamp) |
363 | { |
364 | CsdXrandrManagerPrivate *priv = manager->priv; |
365 | GError *error; |
366 | gboolean success; |
367 | |
368 | error = NULL((void*)0); |
369 | success = cafe_rr_config_apply_with_time (config, priv->rw_screen, timestamp, &error); |
370 | if (!success) { |
371 | log_msg ("Could not switch to the following configuration (timestamp %u): %s\n", timestamp, error->message); |
372 | log_configuration (config); |
373 | error_message (manager, _("Could not switch the monitor configuration")gettext ("Could not switch the monitor configuration"), error, NULL((void*)0)); |
374 | g_error_free (error); |
375 | } |
376 | |
377 | return success; |
378 | } |
379 | |
380 | static void |
381 | restore_backup_configuration_without_messages (const char *backup_filename, const char *intended_filename) |
382 | { |
383 | backup_filename = cafe_rr_config_get_backup_filename (); |
384 | rename (backup_filename, intended_filename); |
385 | } |
386 | |
387 | static void |
388 | restore_backup_configuration (CsdXrandrManager *manager, const char *backup_filename, const char *intended_filename, guint32 timestamp) |
389 | { |
390 | int saved_errno; |
391 | |
392 | if (rename (backup_filename, intended_filename) == 0) { |
393 | GError *error; |
394 | |
395 | error = NULL((void*)0); |
396 | if (!apply_configuration_from_filename (manager, intended_filename, FALSE(0), timestamp, &error)) { |
397 | error_message (manager, _("Could not restore the display's configuration")gettext ("Could not restore the display's configuration"), error, NULL((void*)0)); |
398 | |
399 | if (error) |
400 | g_error_free (error); |
401 | } |
402 | |
403 | return; |
404 | } |
405 | |
406 | saved_errno = errno(*__errno_location ()); |
407 | |
408 | /* ENOENT means the original file didn't exist. That is *not* an error; |
409 | * the backup was not created because there wasn't even an original |
410 | * monitors.xml (such as on a first-time login). Note that *here* there |
411 | * is a "didn't work" monitors.xml, so we must delete that one. |
412 | */ |
413 | if (saved_errno == ENOENT2) |
414 | unlink (intended_filename); |
415 | else { |
416 | char *msg; |
417 | |
418 | msg = g_strdup_printf ("Could not rename %s to %s: %s", |
419 | backup_filename, intended_filename, |
420 | g_strerror (saved_errno)); |
421 | error_message (manager, |
422 | _("Could not restore the display's configuration from a backup")gettext ("Could not restore the display's configuration from a backup" ), |
423 | NULL((void*)0), |
424 | msg); |
425 | g_free (msg); |
426 | } |
427 | |
428 | unlink (backup_filename); |
429 | } |
430 | |
431 | typedef struct { |
432 | CsdXrandrManager *manager; |
433 | CtkWidget *dialog; |
434 | |
435 | int countdown; |
436 | int response_id; |
437 | } TimeoutDialog; |
438 | |
439 | static void |
440 | print_countdown_text (TimeoutDialog *timeout) |
441 | { |
442 | ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (timeout->dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((timeout->dialog)), ((ctk_message_dialog_get_type ())))))), |
443 | ngettext ("The display will be reset to its previous configuration in %d second", |
444 | "The display will be reset to its previous configuration in %d seconds", |
445 | timeout->countdown), |
446 | timeout->countdown); |
447 | } |
448 | |
449 | static gboolean |
450 | timeout_cb (gpointer data) |
451 | { |
452 | TimeoutDialog *timeout = data; |
453 | |
454 | timeout->countdown--; |
455 | |
456 | if (timeout->countdown == 0) { |
457 | timeout->response_id = CTK_RESPONSE_CANCEL; |
458 | ctk_main_quit (); |
459 | } else { |
460 | print_countdown_text (timeout); |
461 | } |
462 | |
463 | return TRUE(!(0)); |
464 | } |
465 | |
466 | static void |
467 | timeout_response_cb (CtkDialog *dialog, int response_id, gpointer data) |
468 | { |
469 | TimeoutDialog *timeout = data; |
470 | |
471 | if (response_id == CTK_RESPONSE_DELETE_EVENT) { |
472 | /* The user closed the dialog or pressed ESC, revert */ |
473 | timeout->response_id = CTK_RESPONSE_CANCEL; |
474 | } else |
475 | timeout->response_id = response_id; |
476 | |
477 | ctk_main_quit (); |
478 | } |
479 | |
480 | static gboolean |
481 | user_says_things_are_ok (CsdXrandrManager *manager, CdkWindow *parent_window) |
482 | { |
483 | TimeoutDialog timeout; |
484 | guint timeout_id; |
485 | |
486 | timeout.manager = manager; |
487 | |
488 | timeout.dialog = ctk_message_dialog_new (NULL((void*)0), |
489 | CTK_DIALOG_MODAL, |
490 | CTK_MESSAGE_QUESTION, |
491 | CTK_BUTTONS_NONE, |
492 | _("Does the display look OK?")gettext ("Does the display look OK?")); |
493 | |
494 | timeout.countdown = CONFIRMATION_DIALOG_SECONDS30; |
495 | |
496 | print_countdown_text (&timeout); |
497 | |
498 | ctk_window_set_icon_name (CTK_WINDOW (timeout.dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((timeout.dialog)), ((ctk_window_get_type ())))))), "preferences-desktop-display"); |
499 | ctk_dialog_add_button (CTK_DIALOG (timeout.dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((timeout.dialog)), ((ctk_dialog_get_type ())))))), _("_Restore Previous Configuration")gettext ("_Restore Previous Configuration"), CTK_RESPONSE_CANCEL); |
500 | ctk_dialog_add_button (CTK_DIALOG (timeout.dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((timeout.dialog)), ((ctk_dialog_get_type ())))))), _("_Keep This Configuration")gettext ("_Keep This Configuration"), CTK_RESPONSE_ACCEPT); |
501 | ctk_dialog_set_default_response (CTK_DIALOG (timeout.dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((timeout.dialog)), ((ctk_dialog_get_type ())))))), CTK_RESPONSE_ACCEPT); /* ah, the optimism */ |
502 | |
503 | g_signal_connect (timeout.dialog, "response",g_signal_connect_data ((timeout.dialog), ("response"), (((GCallback ) (timeout_response_cb))), (&timeout), ((void*)0), (GConnectFlags ) 0) |
504 | G_CALLBACK (timeout_response_cb),g_signal_connect_data ((timeout.dialog), ("response"), (((GCallback ) (timeout_response_cb))), (&timeout), ((void*)0), (GConnectFlags ) 0) |
505 | &timeout)g_signal_connect_data ((timeout.dialog), ("response"), (((GCallback ) (timeout_response_cb))), (&timeout), ((void*)0), (GConnectFlags ) 0); |
506 | |
507 | ctk_widget_realize (timeout.dialog); |
508 | |
509 | if (parent_window) |
510 | cdk_window_set_transient_for (ctk_widget_get_window (timeout.dialog), parent_window); |
511 | |
512 | ctk_widget_show_all (timeout.dialog); |
513 | /* We don't use g_timeout_add_seconds() since we actually care that the user sees "real" second ticks in the dialog */ |
514 | timeout_id = g_timeout_add (1000, |
515 | timeout_cb, |
516 | &timeout); |
517 | ctk_main (); |
518 | |
519 | ctk_widget_destroy (timeout.dialog); |
520 | g_source_remove (timeout_id); |
521 | |
522 | if (timeout.response_id == CTK_RESPONSE_ACCEPT) |
523 | return TRUE(!(0)); |
524 | else |
525 | return FALSE(0); |
526 | } |
527 | |
528 | struct confirmation { |
529 | CsdXrandrManager *manager; |
530 | CdkWindow *parent_window; |
531 | guint32 timestamp; |
532 | }; |
533 | |
534 | static gboolean |
535 | confirm_with_user_idle_cb (gpointer data) |
536 | { |
537 | struct confirmation *confirmation = data; |
538 | char *backup_filename; |
539 | char *intended_filename; |
540 | |
541 | backup_filename = cafe_rr_config_get_backup_filename (); |
542 | intended_filename = cafe_rr_config_get_intended_filename (); |
543 | |
544 | if (user_says_things_are_ok (confirmation->manager, confirmation->parent_window)) |
545 | unlink (backup_filename); |
546 | else |
547 | restore_backup_configuration (confirmation->manager, backup_filename, intended_filename, confirmation->timestamp); |
548 | |
549 | g_free (confirmation); |
550 | |
551 | return FALSE(0); |
552 | } |
553 | |
554 | static void |
555 | queue_confirmation_by_user (CsdXrandrManager *manager, CdkWindow *parent_window, guint32 timestamp) |
556 | { |
557 | struct confirmation *confirmation; |
558 | |
559 | confirmation = g_new (struct confirmation, 1)((struct confirmation *) g_malloc_n ((1), sizeof (struct confirmation ))); |
560 | confirmation->manager = manager; |
561 | confirmation->parent_window = parent_window; |
562 | confirmation->timestamp = timestamp; |
563 | |
564 | g_idle_add (confirm_with_user_idle_cb, confirmation); |
565 | } |
566 | |
567 | static gboolean |
568 | try_to_apply_intended_configuration (CsdXrandrManager *manager, CdkWindow *parent_window, guint32 timestamp, GError **error) |
569 | { |
570 | char *backup_filename; |
571 | char *intended_filename; |
572 | gboolean result; |
573 | |
574 | /* Try to apply the intended configuration */ |
575 | |
576 | backup_filename = cafe_rr_config_get_backup_filename (); |
577 | intended_filename = cafe_rr_config_get_intended_filename (); |
578 | |
579 | result = apply_configuration_from_filename (manager, intended_filename, FALSE(0), timestamp, error); |
580 | if (!result) { |
581 | error_message (manager, _("The selected configuration for displays could not be applied")gettext ("The selected configuration for displays could not be applied" ), error ? *error : NULL((void*)0), NULL((void*)0)); |
582 | restore_backup_configuration_without_messages (backup_filename, intended_filename); |
583 | goto out; |
584 | } else { |
585 | /* We need to return as quickly as possible, so instead of |
586 | * confirming with the user right here, we do it in an idle |
587 | * handler. The caller only expects a status for "could you |
588 | * change the RANDR configuration?", not "is the user OK with it |
589 | * as well?". |
590 | */ |
591 | queue_confirmation_by_user (manager, parent_window, timestamp); |
592 | } |
593 | |
594 | out: |
595 | g_free (backup_filename); |
596 | g_free (intended_filename); |
597 | |
598 | return result; |
599 | } |
600 | |
601 | /* DBus method for org.cafe.SettingsDaemon.XRANDR ApplyConfiguration; see csd_xrandr-manager.xml for the interface definition */ |
602 | static gboolean |
603 | csd_xrandr_manager_apply_configuration (CsdXrandrManager *manager, |
604 | GError **error) |
605 | { |
606 | return try_to_apply_intended_configuration (manager, NULL((void*)0), CDK_CURRENT_TIME0L, error); |
607 | } |
608 | |
609 | /* DBus method for org.cafe.SettingsDaemon.XRANDR_2 ApplyConfiguration; see csd_xrandr-manager.xml for the interface definition */ |
610 | static gboolean |
611 | csd_xrandr_manager_2_apply_configuration (CsdXrandrManager *manager, |
612 | gint64 parent_window_id, |
613 | gint64 timestamp, |
614 | GError **error) |
615 | { |
616 | CdkWindow *parent_window; |
617 | gboolean result; |
618 | |
619 | if (parent_window_id != 0) |
620 | parent_window = cdk_x11_window_foreign_new_for_display (cdk_display_get_default (), (Window) parent_window_id); |
621 | else |
622 | parent_window = NULL((void*)0); |
623 | |
624 | result = try_to_apply_intended_configuration (manager, parent_window, (guint32) timestamp, error); |
625 | |
626 | if (parent_window) |
627 | g_object_unref (parent_window); |
628 | |
629 | return result; |
630 | } |
631 | |
632 | /* We include this after the definition of csd_xrandr_manager_apply_configuration() so the prototype will already exist */ |
633 | #include "csd_xrandr-manager-glue.h" |
634 | |
635 | static gboolean |
636 | is_laptop (CafeRRScreen *screen, CafeRROutputInfo *output) |
637 | { |
638 | CafeRROutput *rr_output; |
639 | |
640 | rr_output = cafe_rr_screen_get_output_by_name (screen, cafe_rr_output_info_get_name (output)); |
641 | return cafe_rr_output_is_laptop (rr_output); |
642 | } |
643 | |
644 | static gboolean |
645 | get_clone_size (CafeRRScreen *screen, int *width, int *height) |
646 | { |
647 | CafeRRMode **modes = cafe_rr_screen_list_clone_modes (screen); |
648 | int best_w, best_h; |
649 | int i; |
650 | |
651 | best_w = 0; |
652 | best_h = 0; |
653 | |
654 | for (i = 0; modes[i] != NULL((void*)0); ++i) { |
655 | CafeRRMode *mode = modes[i]; |
656 | int w, h; |
657 | |
658 | w = cafe_rr_mode_get_width (mode); |
659 | h = cafe_rr_mode_get_height (mode); |
660 | |
661 | if (w * h > best_w * best_h) { |
662 | best_w = w; |
663 | best_h = h; |
664 | } |
665 | } |
666 | |
667 | if (best_w > 0 && best_h > 0) { |
668 | if (width) |
669 | *width = best_w; |
670 | if (height) |
671 | *height = best_h; |
672 | |
673 | return TRUE(!(0)); |
674 | } |
675 | |
676 | return FALSE(0); |
677 | } |
678 | |
679 | static void |
680 | print_output (CafeRROutputInfo *info) |
681 | { |
682 | int x, y, width, height; |
683 | |
684 | g_print (" Output: %s attached to %s\n", cafe_rr_output_info_get_display_name (info), cafe_rr_output_info_get_name (info)); |
685 | g_print (" status: %s\n", cafe_rr_output_info_is_active (info) ? "on" : "off"); |
686 | |
687 | cafe_rr_output_info_get_geometry (info, &x, &y, &width, &height); |
688 | g_print (" width: %d\n", width); |
689 | g_print (" height: %d\n", height); |
690 | g_print (" rate: %d\n", cafe_rr_output_info_get_refresh_rate (info)); |
691 | g_print (" position: %d %d\n", x, y); |
692 | } |
693 | |
694 | static void |
695 | print_configuration (CafeRRConfig *config, const char *header) |
696 | { |
697 | int i; |
698 | CafeRROutputInfo **outputs; |
699 | |
700 | g_print ("=== %s Configuration ===\n", header); |
701 | if (!config) { |
702 | g_print (" none\n"); |
703 | return; |
704 | } |
705 | |
706 | outputs = cafe_rr_config_get_outputs (config); |
707 | for (i = 0; outputs[i] != NULL((void*)0); ++i) |
708 | print_output (outputs[i]); |
709 | } |
710 | |
711 | static gboolean |
712 | config_is_all_off (CafeRRConfig *config) |
713 | { |
714 | int j; |
715 | CafeRROutputInfo **outputs; |
716 | |
717 | outputs = cafe_rr_config_get_outputs (config); |
718 | |
719 | for (j = 0; outputs[j] != NULL((void*)0); ++j) { |
720 | if (cafe_rr_output_info_is_active (outputs[j])) { |
721 | return FALSE(0); |
722 | } |
723 | } |
724 | |
725 | return TRUE(!(0)); |
726 | } |
727 | |
728 | static CafeRRConfig * |
729 | make_clone_setup (CafeRRScreen *screen) |
730 | { |
731 | CafeRRConfig *result; |
732 | CafeRROutputInfo **outputs; |
733 | int width, height; |
734 | int i; |
735 | |
736 | if (!get_clone_size (screen, &width, &height)) |
737 | return NULL((void*)0); |
738 | |
739 | result = cafe_rr_config_new_current (screen, NULL((void*)0)); |
740 | outputs = cafe_rr_config_get_outputs (result); |
741 | |
742 | for (i = 0; outputs[i] != NULL((void*)0); ++i) { |
743 | CafeRROutputInfo *info = outputs[i]; |
744 | |
745 | cafe_rr_output_info_set_active (info, FALSE(0)); |
746 | if (cafe_rr_output_info_is_connected (info)) { |
747 | CafeRROutput *output = |
748 | cafe_rr_screen_get_output_by_name (screen, cafe_rr_output_info_get_name (info)); |
749 | CafeRRMode **modes = cafe_rr_output_list_modes (output); |
750 | int j; |
751 | int best_rate = 0; |
752 | |
753 | for (j = 0; modes[j] != NULL((void*)0); ++j) { |
754 | CafeRRMode *mode = modes[j]; |
755 | int w, h; |
756 | |
757 | w = cafe_rr_mode_get_width (mode); |
758 | h = cafe_rr_mode_get_height (mode); |
759 | |
760 | if (w == width && h == height) { |
761 | best_rate = cafe_rr_mode_get_freq (mode); |
762 | } |
763 | } |
764 | |
765 | if (best_rate > 0) { |
766 | cafe_rr_output_info_set_active (info, TRUE(!(0))); |
767 | cafe_rr_output_info_set_rotation (info, CAFE_RR_ROTATION_0); |
768 | cafe_rr_output_info_set_refresh_rate (info, best_rate); |
769 | cafe_rr_output_info_set_geometry (info, 0, 0, width, height); |
770 | } |
771 | } |
772 | } |
773 | |
774 | if (config_is_all_off (result)) { |
775 | g_object_unref (result); |
776 | result = NULL((void*)0); |
777 | } |
778 | |
779 | print_configuration (result, "clone setup"); |
780 | |
781 | return result; |
782 | } |
783 | |
784 | static CafeRRMode * |
785 | find_best_mode (CafeRROutput *output) |
786 | { |
787 | CafeRRMode *preferred; |
788 | CafeRRMode **modes; |
789 | int best_size; |
790 | int best_width, best_height, best_rate; |
791 | int i; |
792 | CafeRRMode *best_mode; |
793 | |
794 | preferred = cafe_rr_output_get_preferred_mode (output); |
795 | if (preferred) |
796 | return preferred; |
797 | |
798 | modes = cafe_rr_output_list_modes (output); |
799 | if (!modes) |
800 | return NULL((void*)0); |
801 | |
802 | best_size = best_width = best_height = best_rate = 0; |
Although the value stored to 'best_height' is used in the enclosing expression, the value is never actually read from 'best_height' | |
803 | best_mode = NULL((void*)0); |
804 | |
805 | for (i = 0; modes[i] != NULL((void*)0); i++) { |
806 | int w, h, r; |
807 | int size; |
808 | |
809 | w = cafe_rr_mode_get_width (modes[i]); |
810 | h = cafe_rr_mode_get_height (modes[i]); |
811 | r = cafe_rr_mode_get_freq (modes[i]); |
812 | |
813 | size = w * h; |
814 | |
815 | if (size > best_size) { |
816 | best_size = size; |
817 | best_width = w; |
818 | best_height = h; |
819 | best_rate = r; |
820 | best_mode = modes[i]; |
821 | } else if (size == best_size) { |
822 | if (r > best_rate) { |
823 | best_rate = r; |
824 | best_mode = modes[i]; |
825 | } |
826 | } |
827 | } |
828 | |
829 | return best_mode; |
830 | } |
831 | |
832 | static gboolean |
833 | turn_on (CafeRRScreen *screen, |
834 | CafeRROutputInfo *info, |
835 | int x, int y) |
836 | { |
837 | CafeRROutput *output = cafe_rr_screen_get_output_by_name (screen, cafe_rr_output_info_get_name (info)); |
838 | CafeRRMode *mode = find_best_mode (output); |
839 | |
840 | if (mode) { |
841 | cafe_rr_output_info_set_active (info, TRUE(!(0))); |
842 | cafe_rr_output_info_set_geometry (info, x, y, cafe_rr_mode_get_width (mode), cafe_rr_mode_get_height (mode)); |
843 | cafe_rr_output_info_set_rotation (info, CAFE_RR_ROTATION_0); |
844 | cafe_rr_output_info_set_refresh_rate (info, cafe_rr_mode_get_freq (mode)); |
845 | |
846 | return TRUE(!(0)); |
847 | } |
848 | |
849 | return FALSE(0); |
850 | } |
851 | |
852 | static CafeRRConfig * |
853 | make_primary_only_setup (CafeRRScreen *screen) |
854 | { |
855 | /*Leave all of the monitors turned on, just change from mirror to xinerama layout*/ |
856 | CafeRRConfig *result = cafe_rr_config_new_current (screen, NULL((void*)0)); |
857 | CafeRROutputInfo **outputs = cafe_rr_config_get_outputs (result); |
858 | int i, x, width,height; |
859 | x = 0; |
860 | |
861 | for (i = 0; outputs[i] != NULL((void*)0); ++i) { |
862 | CafeRROutputInfo *info = outputs[i]; |
863 | width = cafe_rr_output_info_get_preferred_width (info); |
864 | height = cafe_rr_output_info_get_preferred_height (info); |
865 | cafe_rr_output_info_set_geometry (info, x, 0, width, height); |
866 | cafe_rr_output_info_set_active (info, TRUE(!(0))); |
867 | x = x + width; |
868 | } |
869 | |
870 | if (result && config_is_all_off (result)) { |
871 | g_object_unref (G_OBJECT (result)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), (((GType) ((20) << (2))))))))); |
872 | result = NULL((void*)0); |
873 | } |
874 | |
875 | cafe_rr_config_set_clone (result, FALSE(0)); |
876 | print_configuration (result, "Primary only setup"); |
877 | |
878 | return result; |
879 | } |
880 | |
881 | static CafeRRConfig * |
882 | make_laptop_setup (CafeRRScreen *screen) |
883 | { |
884 | /* Turn on the laptop, disable everything else */ |
885 | CafeRRConfig *result = cafe_rr_config_new_current (screen, NULL((void*)0)); |
886 | CafeRROutputInfo **outputs = cafe_rr_config_get_outputs (result); |
887 | int i; |
888 | |
889 | for (i = 0; outputs[i] != NULL((void*)0); ++i) { |
890 | CafeRROutputInfo *info = outputs[i]; |
891 | |
892 | if (is_laptop (screen, info)) { |
893 | if (!turn_on (screen, info, 0, 0)) { |
894 | g_object_unref (G_OBJECT (result)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), (((GType) ((20) << (2))))))))); |
895 | result = NULL((void*)0); |
896 | break; |
897 | } |
898 | } |
899 | else { |
900 | cafe_rr_output_info_set_active (info, FALSE(0)); |
901 | } |
902 | } |
903 | |
904 | if (result && config_is_all_off (result)) { |
905 | g_object_unref (G_OBJECT (result)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), (((GType) ((20) << (2))))))))); |
906 | result = NULL((void*)0); |
907 | } |
908 | |
909 | print_configuration (result, "Laptop setup"); |
910 | |
911 | /* FIXME - Maybe we should return NULL if there is more than |
912 | * one connected "laptop" screen? |
913 | */ |
914 | return result; |
915 | } |
916 | |
917 | static int |
918 | turn_on_and_get_rightmost_offset (CafeRRScreen *screen, CafeRROutputInfo *info, int x) |
919 | { |
920 | if (turn_on (screen, info, x, 0)) { |
921 | int width; |
922 | cafe_rr_output_info_get_geometry (info, NULL((void*)0), NULL((void*)0), &width, NULL((void*)0)); |
923 | x += width; |
924 | } |
925 | |
926 | return x; |
927 | } |
928 | |
929 | static CafeRRConfig * |
930 | make_xinerama_setup (CafeRRScreen *screen) |
931 | { |
932 | /* Turn on everything that has a preferred mode, and |
933 | * position it from left to right |
934 | */ |
935 | CafeRRConfig *result = cafe_rr_config_new_current (screen, NULL((void*)0)); |
936 | CafeRROutputInfo **outputs = cafe_rr_config_get_outputs (result); |
937 | int i; |
938 | int x; |
939 | |
940 | x = 0; |
941 | for (i = 0; outputs[i] != NULL((void*)0); ++i) { |
942 | CafeRROutputInfo *info = outputs[i]; |
943 | |
944 | if (is_laptop (screen, info)) |
945 | x = turn_on_and_get_rightmost_offset (screen, info, x); |
946 | } |
947 | |
948 | for (i = 0; outputs[i] != NULL((void*)0); ++i) { |
949 | CafeRROutputInfo *info = outputs[i]; |
950 | |
951 | if (cafe_rr_output_info_is_connected (info) && !is_laptop (screen, info)) |
952 | x = turn_on_and_get_rightmost_offset (screen, info, x); |
953 | } |
954 | |
955 | if (config_is_all_off (result)) { |
956 | g_object_unref (G_OBJECT (result)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), (((GType) ((20) << (2))))))))); |
957 | result = NULL((void*)0); |
958 | } |
959 | |
960 | print_configuration (result, "xinerama setup"); |
961 | |
962 | return result; |
963 | } |
964 | |
965 | static CafeRRConfig * |
966 | make_other_setup (CafeRRScreen *screen) |
967 | { |
968 | /* Turn off all laptops, and make all external monitors clone |
969 | * from (0, 0) |
970 | */ |
971 | |
972 | CafeRRConfig *result = cafe_rr_config_new_current (screen, NULL((void*)0)); |
973 | CafeRROutputInfo **outputs = cafe_rr_config_get_outputs (result); |
974 | int i; |
975 | |
976 | for (i = 0; outputs[i] != NULL((void*)0); ++i) { |
977 | CafeRROutputInfo *info = outputs[i]; |
978 | |
979 | if (is_laptop (screen, info)) { |
980 | cafe_rr_output_info_set_active (info, FALSE(0)); |
981 | } |
982 | else { |
983 | if (cafe_rr_output_info_is_connected (info)) |
984 | turn_on (screen, info, 0, 0); |
985 | } |
986 | } |
987 | |
988 | if (config_is_all_off (result)) { |
989 | g_object_unref (G_OBJECT (result)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((result)), (((GType) ((20) << (2))))))))); |
990 | result = NULL((void*)0); |
991 | } |
992 | |
993 | print_configuration (result, "other setup"); |
994 | |
995 | return result; |
996 | } |
997 | |
998 | static GPtrArray * |
999 | sanitize (CsdXrandrManager *manager, GPtrArray *array) |
1000 | { |
1001 | int i; |
1002 | GPtrArray *new; |
1003 | |
1004 | g_debug ("before sanitizing"); |
1005 | |
1006 | for (i = 0; i < array->len; ++i) { |
1007 | if (array->pdata[i]) { |
1008 | print_configuration (array->pdata[i], "before"); |
1009 | } |
1010 | } |
1011 | |
1012 | |
1013 | /* Remove configurations that are duplicates of |
1014 | * configurations earlier in the cycle |
1015 | */ |
1016 | for (i = 0; i < array->len; i++) { |
1017 | int j; |
1018 | |
1019 | for (j = i + 1; j < array->len; j++) { |
1020 | CafeRRConfig *this = array->pdata[j]; |
1021 | CafeRRConfig *other = array->pdata[i]; |
1022 | |
1023 | if (this && other && cafe_rr_config_equal (this, other)) { |
1024 | g_debug ("removing duplicate configuration"); |
1025 | g_object_unref (this); |
1026 | array->pdata[j] = NULL((void*)0); |
1027 | break; |
1028 | } |
1029 | } |
1030 | } |
1031 | |
1032 | for (i = 0; i < array->len; ++i) { |
1033 | CafeRRConfig *config = array->pdata[i]; |
1034 | |
1035 | if (config && config_is_all_off (config)) { |
1036 | g_debug ("removing configuration as all outputs are off"); |
1037 | g_object_unref (array->pdata[i]); |
1038 | array->pdata[i] = NULL((void*)0); |
1039 | } |
1040 | } |
1041 | |
1042 | /* Do a final sanitization pass. This will remove configurations that |
1043 | * don't fit in the framebuffer's Virtual size. |
1044 | */ |
1045 | |
1046 | for (i = 0; i < array->len; i++) { |
1047 | CafeRRConfig *config = array->pdata[i]; |
1048 | |
1049 | if (config) { |
1050 | GError *error; |
1051 | |
1052 | error = NULL((void*)0); |
1053 | if (!cafe_rr_config_applicable (config, manager->priv->rw_screen, &error)) { /* NULL-GError */ |
1054 | g_debug ("removing configuration which is not applicable because %s", error->message); |
1055 | g_error_free (error); |
1056 | |
1057 | g_object_unref (config); |
1058 | array->pdata[i] = NULL((void*)0); |
1059 | } |
1060 | } |
1061 | } |
1062 | |
1063 | /* Remove NULL configurations */ |
1064 | new = g_ptr_array_new (); |
1065 | |
1066 | for (i = 0; i < array->len; ++i) { |
1067 | if (array->pdata[i]) { |
1068 | g_ptr_array_add (new, array->pdata[i]); |
1069 | print_configuration (array->pdata[i], "Final"); |
1070 | } |
1071 | } |
1072 | |
1073 | if (new->len > 0) { |
1074 | g_ptr_array_add (new, NULL((void*)0)); |
1075 | } else { |
1076 | g_ptr_array_free (new, TRUE(!(0))); |
1077 | new = NULL((void*)0); |
1078 | } |
1079 | |
1080 | g_ptr_array_free (array, TRUE(!(0))); |
1081 | |
1082 | return new; |
1083 | } |
1084 | |
1085 | static void |
1086 | generate_fn_f7_configs (CsdXrandrManager *mgr) |
1087 | { |
1088 | GPtrArray *array = g_ptr_array_new (); |
1089 | CafeRRScreen *screen = mgr->priv->rw_screen; |
1090 | |
1091 | g_debug ("Generating configurations"); |
1092 | |
1093 | /* Free any existing list of configurations */ |
1094 | if (mgr->priv->fn_f7_configs) { |
1095 | int i; |
1096 | |
1097 | for (i = 0; mgr->priv->fn_f7_configs[i] != NULL((void*)0); ++i) |
1098 | g_object_unref (mgr->priv->fn_f7_configs[i]); |
1099 | g_free (mgr->priv->fn_f7_configs); |
1100 | |
1101 | mgr->priv->fn_f7_configs = NULL((void*)0); |
1102 | mgr->priv->current_fn_f7_config = -1; |
1103 | } |
1104 | |
1105 | g_ptr_array_add (array, cafe_rr_config_new_current (screen, NULL((void*)0))); |
1106 | g_ptr_array_add (array, make_clone_setup (screen)); |
1107 | g_ptr_array_add (array, make_xinerama_setup (screen)); |
1108 | g_ptr_array_add (array, make_laptop_setup (screen)); |
1109 | g_ptr_array_add (array, make_other_setup (screen)); |
1110 | |
1111 | array = sanitize (mgr, array); |
1112 | |
1113 | if (array) { |
1114 | mgr->priv->fn_f7_configs = (CafeRRConfig **)g_ptr_array_free (array, FALSE(0)); |
1115 | mgr->priv->current_fn_f7_config = 0; |
1116 | } |
1117 | } |
1118 | |
1119 | static void |
1120 | error_message (CsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text) |
1121 | { |
1122 | #ifdef HAVE_LIBNOTIFY1 |
1123 | CsdXrandrManagerPrivate *priv = mgr->priv; |
1124 | NotifyNotification *notification; |
1125 | |
1126 | g_assert (error_to_display == NULL || secondary_text == NULL)do { if (error_to_display == ((void*)0) || secondary_text == ( (void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c" , 1126, ((const char*) (__func__)), "error_to_display == NULL || secondary_text == NULL" ); } while (0); |
1127 | |
1128 | if (priv->status_icon) |
1129 | notification = notify_notification_new (primary_text, |
1130 | error_to_display ? error_to_display->message : secondary_text, |
1131 | ctk_status_icon_get_icon_name(priv->status_icon)); |
1132 | else |
1133 | notification = notify_notification_new (primary_text, |
1134 | error_to_display ? error_to_display->message : secondary_text, |
1135 | CSD_XRANDR_ICON_NAME"csd_xrandr"); |
1136 | |
1137 | notify_notification_show (notification, NULL((void*)0)); /* NULL-GError */ |
1138 | #else |
1139 | CtkWidget *dialog; |
1140 | |
1141 | dialog = ctk_message_dialog_new (NULL((void*)0), CTK_DIALOG_MODAL, CTK_MESSAGE_ERROR, CTK_BUTTONS_CLOSE, |
1142 | "%s", primary_text); |
1143 | ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ()) ))))), "%s", |
1144 | error_to_display ? error_to_display->message : secondary_text); |
1145 | |
1146 | ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dialog)), ((ctk_dialog_get_type ()))))))); |
1147 | ctk_widget_destroy (dialog); |
1148 | #endif /* HAVE_LIBNOTIFY */ |
1149 | } |
1150 | |
1151 | static void |
1152 | handle_fn_f7 (CsdXrandrManager *mgr, guint32 timestamp) |
1153 | { |
1154 | CsdXrandrManagerPrivate *priv = mgr->priv; |
1155 | CafeRRScreen *screen = priv->rw_screen; |
1156 | CafeRRConfig *current; |
1157 | GError *error; |
1158 | |
1159 | /* Theory of fn-F7 operation |
1160 | * |
1161 | * We maintain a datastructure "fn_f7_status", that contains |
1162 | * a list of CafeRRConfig's. Each of the CafeRRConfigs has a |
1163 | * mode (or "off") for each connected output. |
1164 | * |
1165 | * When the user hits fn-F7, we cycle to the next CafeRRConfig |
1166 | * in the data structure. If the data structure does not exist, it |
1167 | * is generated. If the configs in the data structure do not match |
1168 | * the current hardware reality, it is regenerated. |
1169 | * |
1170 | */ |
1171 | g_debug ("Handling fn-f7"); |
1172 | |
1173 | log_open (); |
1174 | log_msg ("Handling XF86Display hotkey - timestamp %u\n", timestamp); |
1175 | |
1176 | error = NULL((void*)0); |
1177 | if (!cafe_rr_screen_refresh (screen, &error) && error) { |
1178 | char *str; |
1179 | |
1180 | str = g_strdup_printf (_("Could not refresh the screen information: %s")gettext ("Could not refresh the screen information: %s"), error->message); |
1181 | g_error_free (error); |
1182 | |
1183 | log_msg ("%s\n", str); |
1184 | error_message (mgr, str, NULL((void*)0), _("Trying to switch the monitor configuration anyway.")gettext ("Trying to switch the monitor configuration anyway." )); |
1185 | g_free (str); |
1186 | } |
1187 | |
1188 | if (!priv->fn_f7_configs) { |
1189 | log_msg ("Generating stock configurations:\n"); |
1190 | generate_fn_f7_configs (mgr); |
1191 | log_configurations (priv->fn_f7_configs); |
1192 | } |
1193 | |
1194 | current = cafe_rr_config_new_current (screen, NULL((void*)0)); |
1195 | |
1196 | if (priv->fn_f7_configs && |
1197 | (!cafe_rr_config_match (current, priv->fn_f7_configs[0]) || |
1198 | !cafe_rr_config_equal (current, priv->fn_f7_configs[mgr->priv->current_fn_f7_config]))) { |
1199 | /* Our view of the world is incorrect, so regenerate the |
1200 | * configurations |
1201 | */ |
1202 | generate_fn_f7_configs (mgr); |
1203 | log_msg ("Regenerated stock configurations:\n"); |
1204 | log_configurations (priv->fn_f7_configs); |
1205 | } |
1206 | |
1207 | g_object_unref (current); |
1208 | |
1209 | if (priv->fn_f7_configs) { |
1210 | guint32 server_timestamp; |
1211 | gboolean success; |
1212 | |
1213 | mgr->priv->current_fn_f7_config++; |
1214 | |
1215 | if (priv->fn_f7_configs[mgr->priv->current_fn_f7_config] == NULL((void*)0)) |
1216 | mgr->priv->current_fn_f7_config = 0; |
1217 | |
1218 | g_debug ("cycling to next configuration (%d)", mgr->priv->current_fn_f7_config); |
1219 | |
1220 | print_configuration (priv->fn_f7_configs[mgr->priv->current_fn_f7_config], "new config"); |
1221 | |
1222 | g_debug ("applying"); |
1223 | |
1224 | /* See https://bugzilla.gnome.org/show_bug.cgi?id=610482 |
1225 | * |
1226 | * Sometimes we'll get two rapid XF86Display keypress events, |
1227 | * but their timestamps will be out of order with respect to the |
1228 | * RANDR timestamps. This *may* be due to stupid BIOSes sending |
1229 | * out display-switch keystrokes "to make Windows work". |
1230 | * |
1231 | * The X server will error out if the timestamp provided is |
1232 | * older than a previous change configuration timestamp. We |
1233 | * assume here that we do want this event to go through still, |
1234 | * since kernel timestamps may be skewed wrt the X server. |
1235 | */ |
1236 | cafe_rr_screen_get_timestamps (screen, NULL((void*)0), &server_timestamp); |
1237 | if (timestamp < server_timestamp) |
1238 | timestamp = server_timestamp; |
1239 | |
1240 | success = apply_configuration_and_display_error (mgr, priv->fn_f7_configs[mgr->priv->current_fn_f7_config], timestamp); |
1241 | |
1242 | if (success) { |
1243 | log_msg ("Successfully switched to configuration (timestamp %u):\n", timestamp); |
1244 | log_configuration (priv->fn_f7_configs[mgr->priv->current_fn_f7_config]); |
1245 | } |
1246 | } |
1247 | else { |
1248 | g_debug ("no configurations generated"); |
1249 | } |
1250 | |
1251 | log_close (); |
1252 | |
1253 | g_debug ("done handling fn-f7"); |
1254 | } |
1255 | |
1256 | static CafeRROutputInfo * |
1257 | get_laptop_output_info (CafeRRScreen *screen, CafeRRConfig *config) |
1258 | { |
1259 | int i; |
1260 | CafeRROutputInfo **outputs = cafe_rr_config_get_outputs (config); |
1261 | |
1262 | for (i = 0; outputs[i] != NULL((void*)0); i++) { |
1263 | if (is_laptop (screen, outputs[i])) |
1264 | return outputs[i]; |
1265 | } |
1266 | |
1267 | return NULL((void*)0); |
1268 | |
1269 | } |
1270 | |
1271 | static CafeRRRotation |
1272 | get_next_rotation (CafeRRRotation allowed_rotations, CafeRRRotation current_rotation) |
1273 | { |
1274 | int i; |
1275 | int current_index; |
1276 | |
1277 | /* First, find the index of the current rotation */ |
1278 | |
1279 | current_index = -1; |
1280 | |
1281 | for (i = 0; i < G_N_ELEMENTS (possible_rotations)(sizeof (possible_rotations) / sizeof ((possible_rotations)[0 ])); i++) { |
1282 | CafeRRRotation r; |
1283 | |
1284 | r = possible_rotations[i]; |
1285 | if (r == current_rotation) { |
1286 | current_index = i; |
1287 | break; |
1288 | } |
1289 | } |
1290 | |
1291 | if (current_index == -1) { |
1292 | /* Huh, the current_rotation was not one of the supported rotations. Bail out. */ |
1293 | return current_rotation; |
1294 | } |
1295 | |
1296 | /* Then, find the next rotation that is allowed */ |
1297 | |
1298 | i = (current_index + 1) % G_N_ELEMENTS (possible_rotations)(sizeof (possible_rotations) / sizeof ((possible_rotations)[0 ])); |
1299 | |
1300 | while (1) { |
1301 | CafeRRRotation r; |
1302 | |
1303 | r = possible_rotations[i]; |
1304 | if (r == current_rotation) { |
1305 | /* We wrapped around and no other rotation is suported. Bummer. */ |
1306 | return current_rotation; |
1307 | } else if (r & allowed_rotations) |
1308 | return r; |
1309 | |
1310 | i = (i + 1) % G_N_ELEMENTS (possible_rotations)(sizeof (possible_rotations) / sizeof ((possible_rotations)[0 ])); |
1311 | } |
1312 | } |
1313 | |
1314 | /* We use this when the XF86RotateWindows key is pressed. That key is present |
1315 | * on some tablet PCs; they use it so that the user can rotate the tablet |
1316 | * easily. |
1317 | */ |
1318 | static void |
1319 | handle_rotate_windows (CsdXrandrManager *mgr, guint32 timestamp) |
1320 | { |
1321 | CsdXrandrManagerPrivate *priv = mgr->priv; |
1322 | CafeRRScreen *screen = priv->rw_screen; |
1323 | CafeRRConfig *current; |
1324 | CafeRROutputInfo *rotatable_output_info; |
1325 | int num_allowed_rotations; |
1326 | CafeRRRotation allowed_rotations; |
1327 | CafeRRRotation next_rotation; |
1328 | |
1329 | g_debug ("Handling XF86RotateWindows"); |
1330 | |
1331 | /* Which output? */ |
1332 | |
1333 | current = cafe_rr_config_new_current (screen, NULL((void*)0)); |
1334 | |
1335 | rotatable_output_info = get_laptop_output_info (screen, current); |
1336 | if (rotatable_output_info == NULL((void*)0)) { |
1337 | g_debug ("No laptop outputs found to rotate; XF86RotateWindows key will do nothing"); |
1338 | goto out; |
1339 | } |
1340 | |
1341 | /* Which rotation? */ |
1342 | |
1343 | get_allowed_rotations_for_output (current, priv->rw_screen, rotatable_output_info, &num_allowed_rotations, &allowed_rotations); |
1344 | next_rotation = get_next_rotation (allowed_rotations, cafe_rr_output_info_get_rotation (rotatable_output_info)); |
1345 | |
1346 | if (next_rotation == cafe_rr_output_info_get_rotation (rotatable_output_info)) { |
1347 | g_debug ("No rotations are supported other than the current one; XF86RotateWindows key will do nothing"); |
1348 | goto out; |
1349 | } |
1350 | |
1351 | /* Rotate */ |
1352 | |
1353 | cafe_rr_output_info_set_rotation (rotatable_output_info, next_rotation); |
1354 | |
1355 | apply_configuration_and_display_error (mgr, current, timestamp); |
1356 | |
1357 | out: |
1358 | g_object_unref (current); |
1359 | } |
1360 | |
1361 | static CdkFilterReturn |
1362 | event_filter (CdkXEvent *xevent, |
1363 | CdkEvent *event, |
1364 | gpointer data) |
1365 | { |
1366 | CsdXrandrManager *manager = data; |
1367 | XEvent *xev = (XEvent *) xevent; |
1368 | |
1369 | if (!manager->priv->running) |
1370 | return CDK_FILTER_CONTINUE; |
1371 | |
1372 | /* verify we have a key event */ |
1373 | if (xev->xany.type != KeyPress2 && xev->xany.type != KeyRelease3) |
1374 | return CDK_FILTER_CONTINUE; |
1375 | |
1376 | if (xev->xany.type == KeyPress2) { |
1377 | if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode) |
1378 | handle_fn_f7 (manager, xev->xkey.time); |
1379 | else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode) |
1380 | handle_rotate_windows (manager, xev->xkey.time); |
1381 | |
1382 | return CDK_FILTER_CONTINUE; |
1383 | } |
1384 | |
1385 | return CDK_FILTER_CONTINUE; |
1386 | } |
1387 | |
1388 | static void |
1389 | refresh_tray_icon_menu_if_active (CsdXrandrManager *manager, guint32 timestamp) |
1390 | { |
1391 | CsdXrandrManagerPrivate *priv = manager->priv; |
1392 | |
1393 | if (priv->popup_menu) { |
1394 | ctk_menu_shell_cancel (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) )); /* status_icon_popup_menu_selection_done_cb() will free everything */ |
1395 | status_icon_popup_menu (manager, 0, timestamp); |
1396 | } |
1397 | } |
1398 | |
1399 | static void |
1400 | auto_configure_outputs (CsdXrandrManager *manager, guint32 timestamp) |
1401 | { |
1402 | CsdXrandrManagerPrivate *priv = manager->priv; |
1403 | CafeRRConfig *config; |
1404 | CafeRROutputInfo **outputs; |
1405 | int i; |
1406 | GList *just_turned_on; |
1407 | GList *l; |
1408 | int x; |
1409 | GError *error; |
1410 | gboolean applicable; |
1411 | |
1412 | config = cafe_rr_config_new_current (priv->rw_screen, NULL((void*)0)); |
1413 | |
1414 | /* For outputs that are connected and on (i.e. they have a CRTC assigned |
1415 | * to them, so they are getting a signal), we leave them as they are |
1416 | * with their current modes. |
1417 | * |
1418 | * For other outputs, we will turn on connected-but-off outputs and turn |
1419 | * off disconnected-but-on outputs. |
1420 | * |
1421 | * FIXME: If an output remained connected+on, it would be nice to ensure |
1422 | * that the output's CRTCs still has a reasonable mode (think of |
1423 | * changing one monitor for another with different capabilities). |
1424 | */ |
1425 | |
1426 | just_turned_on = NULL((void*)0); |
1427 | outputs = cafe_rr_config_get_outputs (config); |
1428 | |
1429 | for (i = 0; outputs[i] != NULL((void*)0); i++) { |
1430 | CafeRROutputInfo *output = outputs[i]; |
1431 | |
1432 | if (cafe_rr_output_info_is_connected (output) && !cafe_rr_output_info_is_active (output)) { |
1433 | cafe_rr_output_info_set_active (output, TRUE(!(0))); |
1434 | cafe_rr_output_info_set_rotation (output, CAFE_RR_ROTATION_0); |
1435 | just_turned_on = g_list_prepend (just_turned_on, GINT_TO_POINTER (i)((gpointer) (glong) (i))); |
1436 | } else if (!cafe_rr_output_info_is_connected (output) && cafe_rr_output_info_is_active (output)) |
1437 | cafe_rr_output_info_set_active (output, FALSE(0)); |
1438 | } |
1439 | |
1440 | /* Now, lay out the outputs from left to right. Put first the outputs |
1441 | * which remained on; put last the outputs that were newly turned on. |
1442 | */ |
1443 | |
1444 | x = 0; |
1445 | |
1446 | /* First, outputs that remained on */ |
1447 | |
1448 | for (i = 0; outputs[i] != NULL((void*)0); i++) { |
1449 | CafeRROutputInfo *output = outputs[i]; |
1450 | |
1451 | if (g_list_find (just_turned_on, GINT_TO_POINTER (i)((gpointer) (glong) (i)))) |
1452 | continue; |
1453 | |
1454 | if (cafe_rr_output_info_is_active (output)) { |
1455 | int width, height; |
1456 | g_assert (cafe_rr_output_info_is_connected (output))do { if (cafe_rr_output_info_is_connected (output)) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c", 1456, ((const char*) ( __func__)), "cafe_rr_output_info_is_connected (output)"); } while (0); |
1457 | |
1458 | cafe_rr_output_info_get_geometry (output, NULL((void*)0), NULL((void*)0), &width, &height); |
1459 | cafe_rr_output_info_set_geometry (output, x, 0, width, height); |
1460 | |
1461 | x += width; |
1462 | } |
1463 | } |
1464 | |
1465 | /* Second, outputs that were newly-turned on */ |
1466 | |
1467 | for (l = just_turned_on; l; l = l->next) { |
1468 | CafeRROutputInfo *output; |
1469 | int width; |
1470 | |
1471 | i = GPOINTER_TO_INT (l->data)((gint) (glong) (l->data)); |
1472 | output = outputs[i]; |
1473 | |
1474 | g_assert (cafe_rr_output_info_is_active (output) && cafe_rr_output_info_is_connected (output))do { if (cafe_rr_output_info_is_active (output) && cafe_rr_output_info_is_connected (output)) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c" , 1474, ((const char*) (__func__)), "cafe_rr_output_info_is_active (output) && cafe_rr_output_info_is_connected (output)" ); } while (0); |
1475 | |
1476 | /* since the output was off, use its preferred width/height (it doesn't have a real width/height yet) */ |
1477 | width = cafe_rr_output_info_get_preferred_width (output); |
1478 | cafe_rr_output_info_set_geometry (output, x, 0, width, cafe_rr_output_info_get_preferred_height (output)); |
1479 | |
1480 | x += width; |
1481 | } |
1482 | |
1483 | /* Check if we have a large enough framebuffer size. If not, turn off |
1484 | * outputs from right to left until we reach a usable size. |
1485 | */ |
1486 | |
1487 | just_turned_on = g_list_reverse (just_turned_on); /* now the outputs here are from right to left */ |
1488 | |
1489 | l = just_turned_on; |
1490 | while (1) { |
1491 | CafeRROutputInfo *output; |
1492 | gboolean is_bounds_error; |
1493 | |
1494 | error = NULL((void*)0); |
1495 | applicable = cafe_rr_config_applicable (config, priv->rw_screen, &error); |
1496 | |
1497 | if (applicable) |
1498 | break; |
1499 | |
1500 | is_bounds_error = g_error_matches (error, CAFE_RR_ERROR(cafe_rr_error_quark ()), CAFE_RR_ERROR_BOUNDS_ERROR); |
1501 | g_error_free (error); |
1502 | |
1503 | if (!is_bounds_error) |
1504 | break; |
1505 | |
1506 | if (l) { |
1507 | i = GPOINTER_TO_INT (l->data)((gint) (glong) (l->data)); |
1508 | l = l->next; |
1509 | |
1510 | output = outputs[i]; |
1511 | cafe_rr_output_info_set_active (output, FALSE(0)); |
1512 | } else |
1513 | break; |
1514 | } |
1515 | |
1516 | /* Apply the configuration! */ |
1517 | |
1518 | if (applicable) |
1519 | apply_configuration_and_display_error (manager, config, timestamp); |
1520 | |
1521 | g_list_free (just_turned_on); |
1522 | g_object_unref (config); |
1523 | |
1524 | /* Finally, even though we did a best-effort job in sanitizing the |
1525 | * outputs, we don't know the physical layout of the monitors. We'll |
1526 | * start the display capplet so that the user can tweak things to his |
1527 | * liking. |
1528 | */ |
1529 | |
1530 | #if 0 |
1531 | /* FIXME: This is disabled for now. The capplet is not a single-instance application. |
1532 | * If you do this: |
1533 | * |
1534 | * 1. Start the display capplet |
1535 | * |
1536 | * 2. Plug an extra monitor |
1537 | * |
1538 | * 3. Hit the "Detect displays" button |
1539 | * |
1540 | * Then we will get a RANDR event because X re-probes the outputs. We don't want to |
1541 | * start up a second display capplet right there! |
1542 | */ |
1543 | |
1544 | run_display_capplet (NULL((void*)0)); |
1545 | #endif |
1546 | } |
1547 | |
1548 | static void |
1549 | apply_color_profiles (void) |
1550 | { |
1551 | gboolean ret; |
1552 | GError *error = NULL((void*)0); |
1553 | |
1554 | /* run the cafe-color-manager apply program */ |
1555 | ret = g_spawn_command_line_async (BINDIR"/usr/bin" "/gcm-apply", &error); |
1556 | if (!ret) { |
1557 | /* only print the warning if the binary is installed */ |
1558 | if (error->code != G_SPAWN_ERROR_NOENT) { |
1559 | g_warning ("failed to apply color profiles: %s", error->message); |
1560 | } |
1561 | g_error_free (error); |
1562 | } |
1563 | } |
1564 | |
1565 | static void |
1566 | on_randr_event (CafeRRScreen *screen, gpointer data) |
1567 | { |
1568 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
1569 | CsdXrandrManagerPrivate *priv = manager->priv; |
1570 | guint32 change_timestamp, config_timestamp; |
1571 | |
1572 | if (!priv->running) |
1573 | return; |
1574 | |
1575 | cafe_rr_screen_get_timestamps (screen, &change_timestamp, &config_timestamp); |
1576 | |
1577 | log_open (); |
1578 | log_msg ("Got RANDR event with timestamps change=%u %c config=%u\n", |
1579 | change_timestamp, |
1580 | timestamp_relationship (change_timestamp, config_timestamp), |
1581 | config_timestamp); |
1582 | |
1583 | if (change_timestamp >= config_timestamp) { |
1584 | /* The event is due to an explicit configuration change. |
1585 | * |
1586 | * If the change was performed by us, then we need to do nothing. |
1587 | * |
1588 | * If the change was done by some other X client, we don't need |
1589 | * to do anything, either; the screen is already configured. |
1590 | */ |
1591 | show_timestamps_dialog (manager, "ignoring since change > config"); |
1592 | log_msg (" Ignoring event since change >= config\n"); |
1593 | } else { |
1594 | /* Here, config_timestamp > change_timestamp. This means that |
1595 | * the screen got reconfigured because of hotplug/unplug; the X |
1596 | * server is just notifying us, and we need to configure the |
1597 | * outputs in a sane way. |
1598 | */ |
1599 | |
1600 | char *intended_filename; |
1601 | GError *error; |
1602 | gboolean success; |
1603 | |
1604 | show_timestamps_dialog (manager, "need to deal with reconfiguration, as config > change"); |
1605 | |
1606 | intended_filename = cafe_rr_config_get_intended_filename (); |
1607 | |
1608 | error = NULL((void*)0); |
1609 | success = apply_configuration_from_filename (manager, intended_filename, TRUE(!(0)), config_timestamp, &error); |
1610 | g_free (intended_filename); |
1611 | |
1612 | if (!success) { |
1613 | /* We don't bother checking the error type. |
1614 | * |
1615 | * Both G_FILE_ERROR_NOENT and |
1616 | * CAFE_RR_ERROR_NO_MATCHING_CONFIG would mean, "there |
1617 | * was no configuration to apply, or none that matched |
1618 | * the current outputs", and in that case we need to run |
1619 | * our fallback. |
1620 | * |
1621 | * Any other error means "we couldn't do the smart thing |
1622 | * of using a previously- saved configuration, anyway, |
1623 | * for some other reason. In that case, we also need to |
1624 | * run our fallback to avoid leaving the user with a |
1625 | * bogus configuration. |
1626 | */ |
1627 | |
1628 | if (error) |
1629 | g_error_free (error); |
1630 | |
1631 | if (config_timestamp != priv->last_config_timestamp) { |
1632 | priv->last_config_timestamp = config_timestamp; |
1633 | auto_configure_outputs (manager, config_timestamp); |
1634 | log_msg (" Automatically configured outputs to deal with event\n"); |
1635 | } else |
1636 | log_msg (" Ignored event as old and new config timestamps are the same\n"); |
1637 | } else |
1638 | log_msg ("Applied stored configuration to deal with event\n"); |
1639 | } |
1640 | |
1641 | /* poke cafe-color-manager */ |
1642 | apply_color_profiles (); |
1643 | |
1644 | refresh_tray_icon_menu_if_active (manager, MAX (change_timestamp, config_timestamp)(((change_timestamp) > (config_timestamp)) ? (change_timestamp ) : (config_timestamp))); |
1645 | |
1646 | log_close (); |
1647 | } |
1648 | |
1649 | static void |
1650 | run_display_capplet (CtkWidget *widget) |
1651 | { |
1652 | CdkScreen *screen; |
1653 | GError *error; |
1654 | |
1655 | if (widget) |
1656 | screen = ctk_widget_get_screen (widget); |
1657 | else |
1658 | screen = cdk_screen_get_default (); |
1659 | |
1660 | error = NULL((void*)0); |
1661 | if (!cafe_cdk_spawn_command_line_on_screen (screen, CSD_XRANDR_DISPLAY_CAPPLET"cafe-display-properties", &error)) { |
1662 | CtkWidget *dialog; |
1663 | |
1664 | dialog = ctk_message_dialog_new_with_markup (NULL((void*)0), 0, CTK_MESSAGE_ERROR, CTK_BUTTONS_OK, |
1665 | "<span weight=\"bold\" size=\"larger\">" |
1666 | "Display configuration could not be run" |
1667 | "</span>\n\n" |
1668 | "%s", error->message); |
1669 | ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dialog)), ((ctk_dialog_get_type ()))))))); |
1670 | ctk_widget_destroy (dialog); |
1671 | |
1672 | g_error_free (error); |
1673 | } |
1674 | } |
1675 | |
1676 | static void |
1677 | popup_menu_configure_display_cb (CtkMenuItem *item, gpointer data) |
1678 | { |
1679 | run_display_capplet (CTK_WIDGET (item)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_widget_get_type ()))))))); |
1680 | } |
1681 | |
1682 | static void |
1683 | status_icon_popup_menu_selection_done_cb (CtkMenuShell *menu_shell, gpointer data) |
1684 | { |
1685 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
1686 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
1687 | |
1688 | ctk_widget_destroy (priv->popup_menu); |
1689 | priv->popup_menu = NULL((void*)0); |
1690 | |
1691 | cafe_rr_labeler_hide (priv->labeler); |
1692 | g_object_unref (priv->labeler); |
1693 | priv->labeler = NULL((void*)0); |
1694 | |
1695 | g_object_unref (priv->configuration); |
1696 | priv->configuration = NULL((void*)0); |
1697 | } |
1698 | |
1699 | #define OUTPUT_TITLE_ITEM_BORDER2 2 |
1700 | #define OUTPUT_TITLE_ITEM_PADDING4 4 |
1701 | |
1702 | static void |
1703 | title_item_size_allocate_cb (CtkWidget *widget, CtkAllocation *allocation, gpointer data) |
1704 | { |
1705 | /* When CtkMenu does size_request on its items, it asks them for their "toggle size", |
1706 | * which will be non-zero when there are check/radio items. CtkMenu remembers |
1707 | * the largest of those sizes. During the size_allocate pass, CtkMenu calls |
1708 | * ctk_menu_item_toggle_size_allocate() with that value, to tell the menu item |
1709 | * that it should later paint its child a bit to the right of its edge. |
1710 | * |
1711 | * However, we want the "title" menu items for each RANDR output to span the *whole* |
1712 | * allocation of the menu item, not just the "allocation minus toggle" area. |
1713 | * |
1714 | * So, we let the menu item size_allocate itself as usual, but this |
1715 | * callback gets run afterward. Here we hack a toggle size of 0 into |
1716 | * the menu item, and size_allocate it by hand *again*. We also need to |
1717 | * avoid recursing into this function. |
1718 | */ |
1719 | |
1720 | g_assert (CTK_IS_MENU_ITEM (widget))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((widget)); GType __t = ((ctk_menu_item_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c" , 1720, ((const char*) (__func__)), "CTK_IS_MENU_ITEM (widget)" ); } while (0); |
1721 | |
1722 | ctk_menu_item_toggle_size_allocate (CTK_MENU_ITEM (widget)((((CtkMenuItem*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), ((ctk_menu_item_get_type ())))))), 0); |
1723 | |
1724 | g_signal_handlers_block_by_func (widget, title_item_size_allocate_cb, NULL)g_signal_handlers_block_matched ((widget), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0 ), (title_item_size_allocate_cb), (((void*)0))); |
1725 | |
1726 | /* Sigh. There is no way to turn on CTK_ALLOC_NEEDED outside of CTK+ |
1727 | * itself; also, since calling size_allocate on a widget with the same |
1728 | * allcation is a no-op, we need to allocate with a "different" size |
1729 | * first. |
1730 | */ |
1731 | |
1732 | allocation->width++; |
1733 | ctk_widget_size_allocate (widget, allocation); |
1734 | |
1735 | allocation->width--; |
1736 | ctk_widget_size_allocate (widget, allocation); |
1737 | |
1738 | g_signal_handlers_unblock_by_func (widget, title_item_size_allocate_cb, NULL)g_signal_handlers_unblock_matched ((widget), (GSignalMatchType ) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*) 0), (title_item_size_allocate_cb), (((void*)0))); |
1739 | } |
1740 | |
1741 | static CtkWidget * |
1742 | make_menu_item_for_output_title (CsdXrandrManager *manager, CafeRROutputInfo *output) |
1743 | { |
1744 | CtkWidget *item; |
1745 | CtkStyleContext *context; |
1746 | CtkCssProvider *provider, *provider2; |
1747 | CtkWidget *label; |
1748 | CtkWidget *image; |
1749 | CtkWidget *box; |
1750 | char *str; |
1751 | GString *string; |
1752 | CdkRGBA color; |
1753 | gchar *css, *color_string, *theme_name; |
1754 | CtkSettings *settings; |
1755 | GSettings *icon_settings; |
1756 | |
1757 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
1758 | |
1759 | item = ctk_menu_item_new (); |
1760 | box = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 6); |
1761 | image = ctk_image_new_from_icon_name ("computer", CTK_ICON_SIZE_MENU); |
1762 | context = ctk_widget_get_style_context (item); |
1763 | ctk_style_context_add_class (context, "xrandr-applet"); |
1764 | |
1765 | g_signal_connect (item, "size-allocate",g_signal_connect_data ((item), ("size-allocate"), (((GCallback ) (title_item_size_allocate_cb))), (((void*)0)), ((void*)0), ( GConnectFlags) 0) |
1766 | G_CALLBACK (title_item_size_allocate_cb), NULL)g_signal_connect_data ((item), ("size-allocate"), (((GCallback ) (title_item_size_allocate_cb))), (((void*)0)), ((void*)0), ( GConnectFlags) 0); |
1767 | |
1768 | str = g_markup_printf_escaped ("<b>%s</b>", cafe_rr_output_info_get_display_name (output)); |
1769 | label = ctk_label_new (NULL((void*)0)); |
1770 | ctk_label_set_markup (CTK_LABEL (label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((label)), ((ctk_label_get_type ())))))), str); |
1771 | g_free (str); |
1772 | |
1773 | /* Add padding around the label to fit the box that we'll draw for color-coding */ |
1774 | ctk_label_set_xalign (CTK_LABEL (label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((label)), ((ctk_label_get_type ())))))), 0.0); |
1775 | ctk_label_set_yalign (CTK_LABEL (label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((label)), ((ctk_label_get_type ())))))), 0.5); |
1776 | ctk_widget_set_margin_start (label, OUTPUT_TITLE_ITEM_BORDER2 + OUTPUT_TITLE_ITEM_PADDING4); |
1777 | ctk_widget_set_margin_end (label, OUTPUT_TITLE_ITEM_BORDER2 + OUTPUT_TITLE_ITEM_PADDING4); |
1778 | ctk_widget_set_margin_top (label, OUTPUT_TITLE_ITEM_BORDER2 + OUTPUT_TITLE_ITEM_PADDING4); |
1779 | ctk_widget_set_margin_bottom (label, OUTPUT_TITLE_ITEM_BORDER2 + OUTPUT_TITLE_ITEM_PADDING4); |
1780 | |
1781 | /*Load the icon unless the user has icons in menus turned off*/ |
1782 | icon_settings = g_settings_new ("org.cafe.interface"); |
1783 | if (g_settings_get_boolean (icon_settings, "menus-have-icons")){ |
1784 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), image); |
1785 | } |
1786 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), label); |
1787 | ctk_container_add (CTK_CONTAINER (item)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_container_get_type ())))))), box); |
1788 | |
1789 | cafe_rr_labeler_get_rgba_for_output (priv->labeler, output, &color); |
1790 | |
1791 | color_string = cdk_rgba_to_string (&color); |
1792 | |
1793 | /*This can be overriden by themes, check all label:insensitive entries if it does not show up*/ |
1794 | string = g_string_new(NULL((void*)0)); |
1795 | g_string_append (string, ".cafe-panel-menu-bar menuitem.xrandr-applet:disabled>box>label{\n")(__builtin_constant_p (".cafe-panel-menu-bar menuitem.xrandr-applet:disabled>box>label{\n" ) ? __extension__ ({ const char * const __val = (".cafe-panel-menu-bar menuitem.xrandr-applet:disabled>box>label{\n" ); g_string_append_len_inline (string, __val, (__val != ((void *)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1) ; }) : g_string_append_len_inline (string, ".cafe-panel-menu-bar menuitem.xrandr-applet:disabled>box>label{\n" , (gssize) -1)); |
1796 | /*g_string_append (string, "color: black;"); Does not work-overridden in all themes*/ |
1797 | g_string_append (string, "padding-left: 4px; padding-right: 4px;")(__builtin_constant_p ("padding-left: 4px; padding-right: 4px;" ) ? __extension__ ({ const char * const __val = ("padding-left: 4px; padding-right: 4px;" ); g_string_append_len_inline (string, __val, (__val != ((void *)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1) ; }) : g_string_append_len_inline (string, "padding-left: 4px; padding-right: 4px;" , (gssize) -1)); |
1798 | g_string_append (string, "border-color: gray;")(__builtin_constant_p ("border-color: gray;") ? __extension__ ({ const char * const __val = ("border-color: gray;"); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, "border-color: gray;", (gssize) -1)); |
1799 | g_string_append (string, "border-width: 1px;")(__builtin_constant_p ("border-width: 1px;") ? __extension__ ( { const char * const __val = ("border-width: 1px;"); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, "border-width: 1px;", (gssize) -1)); |
1800 | g_string_append (string, "border-style: inset;")(__builtin_constant_p ("border-style: inset;") ? __extension__ ({ const char * const __val = ("border-style: inset;"); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, "border-style: inset;", (gssize) -1)); |
1801 | g_string_append (string, "background-image: none;")(__builtin_constant_p ("background-image: none;") ? __extension__ ({ const char * const __val = ("background-image: none;"); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, "background-image: none;", (gssize) -1)); |
1802 | /*Bright color for active monitor, dimmed for inactive monitor*/ |
1803 | if (cafe_rr_output_info_is_active (output)){ |
1804 | g_string_append (string, "background-color:")(__builtin_constant_p ("background-color:") ? __extension__ ( { const char * const __val = ("background-color:"); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, "background-color:", (gssize) -1)); |
1805 | g_string_append (string, color_string)(__builtin_constant_p (color_string) ? __extension__ ({ const char * const __val = (color_string); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, color_string, (gssize) -1)); |
1806 | g_string_append (string, ";")(__builtin_constant_p (";") ? __extension__ ({ const char * const __val = (";"); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize ) -1); }) : g_string_append_len_inline (string, ";", (gssize) -1)); |
1807 | g_string_append (string," }")(__builtin_constant_p (" }") ? __extension__ ({ const char * const __val = (" }"); g_string_append_len_inline (string, __val, ( __val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, " }" , (gssize) -1)); |
1808 | } |
1809 | else{ |
1810 | g_string_append (string, "background-color: alpha(")(__builtin_constant_p ("background-color: alpha(") ? __extension__ ({ const char * const __val = ("background-color: alpha("); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, "background-color: alpha(", (gssize) -1)); |
1811 | g_string_append (string, color_string)(__builtin_constant_p (color_string) ? __extension__ ({ const char * const __val = (color_string); g_string_append_len_inline (string, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val ) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, color_string, (gssize) -1)); |
1812 | g_string_append (string, ", 0.4);")(__builtin_constant_p (", 0.4);") ? __extension__ ({ const char * const __val = (", 0.4);"); g_string_append_len_inline (string , __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + ! (__val))) : (gssize) -1); }) : g_string_append_len_inline (string , ", 0.4);", (gssize) -1)); |
1813 | g_string_append (string," }")(__builtin_constant_p (" }") ? __extension__ ({ const char * const __val = (" }"); g_string_append_len_inline (string, __val, ( __val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline (string, " }" , (gssize) -1)); |
1814 | ctk_style_context_add_class (context, "monitor-off"); |
1815 | } |
1816 | |
1817 | css = g_string_free (string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((string ), ((0))) : g_string_free_and_steal (string)) : (g_string_free ) ((string), ((0)))); |
1818 | |
1819 | context = ctk_widget_get_style_context (label); |
1820 | provider = ctk_css_provider_new (); |
1821 | ctk_css_provider_load_from_data (provider,css, -1, NULL((void*)0)); |
1822 | |
1823 | ctk_style_context_add_provider (context, |
1824 | CTK_STYLE_PROVIDER (provider)((((CtkStyleProvider*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((provider)), ((ctk_style_provider_get_type ( ))))))), |
1825 | CTK_STYLE_PROVIDER_PRIORITY_FALLBACK1); |
1826 | |
1827 | g_object_unref (provider); |
1828 | g_free (color_string); |
1829 | g_free (css); |
1830 | |
1831 | /*This is NOT overrridden by themes as FALLBACK won't work here |
1832 | *Disable dim/opacity effects applied to icons in an insensitive menu item |
1833 | */ |
1834 | |
1835 | context = ctk_widget_get_style_context (image); |
1836 | provider = ctk_css_provider_new (); |
1837 | |
1838 | ctk_css_provider_load_from_data (provider, |
1839 | ".cafe-panel-menu-bar menuitem.xrandr-applet:disabled>box>image{\n" |
1840 | "opacity: 1.0; \n" |
1841 | "-ctk-icon-style:regular; \n" /* symbolic icons would get the disabled color*/ |
1842 | "-ctk-icon-effect: none; \n" |
1843 | "}", |
1844 | -1, NULL((void*)0)); |
1845 | ctk_style_context_add_provider (context, |
1846 | CTK_STYLE_PROVIDER (provider)((((CtkStyleProvider*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((provider)), ((ctk_style_provider_get_type ( ))))))), |
1847 | CTK_STYLE_PROVIDER_PRIORITY_APPLICATION600); |
1848 | |
1849 | /*Deal with the GNOME and *bird themes, match display capplet theme */ |
1850 | provider2 = ctk_css_provider_new (); |
1851 | settings = ctk_settings_get_default(); |
1852 | context = ctk_widget_get_style_context (label); |
1853 | g_object_get (settings, "ctk-theme-name", &theme_name, NULL((void*)0)); |
1854 | if (g_strcmp0 (theme_name, "Adwaita") == 0 || |
1855 | g_strcmp0 (theme_name, "Adwaita-dark") == 0 || |
1856 | g_strcmp0 (theme_name, "Raleigh") == 0 || |
1857 | g_strcmp0 (theme_name, "win32") == 0 || |
1858 | g_strcmp0 (theme_name, "HighContrast") == 0 || |
1859 | g_strcmp0 (theme_name, "HighContrastInverse") == 0 || |
1860 | g_strcmp0 (theme_name, "Blackbird") == 0 || |
1861 | g_strcmp0 (theme_name, "Bluebird") == 0 || |
1862 | g_strcmp0 (theme_name, "Greybird") == 0){ |
1863 | ctk_css_provider_load_from_data (provider2, |
1864 | ".cafe-panel-menu-bar menuitem.xrandr-applet:disabled>box>label{\n" |
1865 | "color: black;\n" |
1866 | "}" |
1867 | ".cafe-panel-menu-bar menuitem.xrandr-applet.monitor-off:disabled>box>label{\n" |
1868 | "color: alpha (black, 0.6);\n" |
1869 | "}", |
1870 | -1, NULL((void*)0)); |
1871 | ctk_style_context_add_provider(context, |
1872 | CTK_STYLE_PROVIDER (provider2)((((CtkStyleProvider*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((provider2)), ((ctk_style_provider_get_type ( ))))))), |
1873 | CTK_STYLE_PROVIDER_PRIORITY_APPLICATION600); |
1874 | } |
1875 | /*Keep or take this off all other themes as soon as the theme changes*/ |
1876 | else{ |
1877 | ctk_style_context_remove_provider(context, CTK_STYLE_PROVIDER (provider2)((((CtkStyleProvider*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((provider2)), ((ctk_style_provider_get_type ( )))))))); |
1878 | } |
1879 | |
1880 | g_object_unref (provider); |
1881 | g_object_unref (provider2); |
1882 | |
1883 | ctk_widget_set_sensitive (item, FALSE(0)); /* the title is not selectable */ |
1884 | |
1885 | ctk_widget_show_all (item); |
1886 | |
1887 | return item; |
1888 | } |
1889 | |
1890 | static void |
1891 | get_allowed_rotations_for_output (CafeRRConfig *config, |
1892 | CafeRRScreen *rr_screen, |
1893 | CafeRROutputInfo *output, |
1894 | int *out_num_rotations, |
1895 | CafeRRRotation *out_rotations) |
1896 | { |
1897 | CafeRRRotation current_rotation; |
1898 | int i; |
1899 | |
1900 | *out_num_rotations = 0; |
1901 | *out_rotations = 0; |
1902 | |
1903 | current_rotation = cafe_rr_output_info_get_rotation (output); |
1904 | |
1905 | /* Yay for brute force */ |
1906 | |
1907 | for (i = 0; i < G_N_ELEMENTS (possible_rotations)(sizeof (possible_rotations) / sizeof ((possible_rotations)[0 ])); i++) { |
1908 | CafeRRRotation rotation_to_test; |
1909 | |
1910 | rotation_to_test = possible_rotations[i]; |
1911 | |
1912 | cafe_rr_output_info_set_rotation (output, rotation_to_test); |
1913 | |
1914 | if (cafe_rr_config_applicable (config, rr_screen, NULL((void*)0))) { /* NULL-GError */ |
1915 | (*out_num_rotations)++; |
1916 | (*out_rotations) |= rotation_to_test; |
1917 | } |
1918 | } |
1919 | |
1920 | cafe_rr_output_info_set_rotation (output, current_rotation); |
1921 | |
1922 | if (*out_num_rotations == 0 || *out_rotations == 0) { |
1923 | g_warning ("Huh, output %p says it doesn't support any rotations, and yet it has a current rotation?", output); |
1924 | *out_num_rotations = 1; |
1925 | *out_rotations = cafe_rr_output_info_get_rotation (output); |
1926 | } |
1927 | } |
1928 | |
1929 | static void |
1930 | add_unsupported_rotation_item (CsdXrandrManager *manager) |
1931 | { |
1932 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
1933 | CtkWidget *item; |
1934 | CtkWidget *label; |
1935 | gchar *markup; |
1936 | |
1937 | item = ctk_menu_item_new (); |
1938 | |
1939 | label = ctk_label_new (NULL((void*)0)); |
1940 | markup = g_strdup_printf ("<i>%s</i>", _("Rotation not supported")gettext ("Rotation not supported")); |
1941 | ctk_label_set_markup (CTK_LABEL (label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((label)), ((ctk_label_get_type ())))))), markup); |
1942 | g_free (markup); |
1943 | ctk_container_add (CTK_CONTAINER (item)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_container_get_type ())))))), label); |
1944 | |
1945 | ctk_widget_show_all (item); |
1946 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
1947 | } |
1948 | |
1949 | static void |
1950 | ensure_current_configuration_is_saved (void) |
1951 | { |
1952 | CafeRRScreen *rr_screen; |
1953 | CafeRRConfig *rr_config; |
1954 | |
1955 | /* Normally, cafe_rr_config_save() creates a backup file based on the |
1956 | * old monitors.xml. However, if *that* file didn't exist, there is |
1957 | * nothing from which to create a backup. So, here we'll save the |
1958 | * current/unchanged configuration and then let our caller call |
1959 | * cafe_rr_config_save() again with the new/changed configuration, so |
1960 | * that there *will* be a backup file in the end. |
1961 | */ |
1962 | |
1963 | rr_screen = cafe_rr_screen_new (cdk_screen_get_default (), NULL((void*)0)); /* NULL-GError */ |
1964 | if (!rr_screen) |
1965 | return; |
1966 | |
1967 | rr_config = cafe_rr_config_new_current (rr_screen, NULL((void*)0)); |
1968 | cafe_rr_config_save (rr_config, NULL((void*)0)); /* NULL-GError */ |
1969 | |
1970 | g_object_unref (rr_config); |
1971 | g_object_unref (rr_screen); |
1972 | } |
1973 | |
1974 | static void |
1975 | monitor_activate_cb (CtkCheckMenuItem *item, gpointer data) |
1976 | { |
1977 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
1978 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
1979 | CafeRROutputInfo *output; |
1980 | GError *error; |
1981 | |
1982 | ensure_current_configuration_is_saved (); |
1983 | |
1984 | output = g_object_get_data (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), "output"); |
1985 | |
1986 | /*This is borrowed from the capplet in cafe-control-center |
1987 | *And shares the same limitations concerning monitors |
1988 | *which have been turned off and back on without being reconfigured |
1989 | */ |
1990 | if (ctk_check_menu_item_get_active (item)){ |
1991 | int x, y, width, height; |
1992 | cafe_rr_output_info_get_geometry (output, &x, &y, NULL((void*)0), NULL((void*)0)); |
1993 | width = cafe_rr_output_info_get_preferred_width (output); |
1994 | height = cafe_rr_output_info_get_preferred_height (output); |
1995 | cafe_rr_output_info_set_geometry (output, x, y, width, height); |
1996 | cafe_rr_output_info_set_active (output, TRUE(!(0))); |
1997 | |
1998 | } |
1999 | else{ |
2000 | cafe_rr_output_info_set_active (output, FALSE(0)); |
2001 | } |
2002 | |
2003 | error = NULL((void*)0); |
2004 | if (!cafe_rr_config_save (priv->configuration, &error)) { |
2005 | error_message (manager, _("Could not save monitor configuration")gettext ("Could not save monitor configuration"), error, NULL((void*)0)); |
2006 | if (error) |
2007 | g_error_free (error); |
2008 | |
2009 | return; |
2010 | } |
2011 | |
2012 | try_to_apply_intended_configuration (manager, NULL((void*)0), ctk_get_current_event_time (), NULL((void*)0)); |
2013 | } |
2014 | |
2015 | static void |
2016 | output_rotation_item_activate_cb (CtkCheckMenuItem *item, gpointer data) |
2017 | { |
2018 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
2019 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2020 | CafeRROutputInfo *output; |
2021 | CafeRRRotation rotation; |
2022 | GError *error; |
2023 | |
2024 | /* Not interested in deselected items */ |
2025 | if (!ctk_check_menu_item_get_active (item)) |
2026 | return; |
2027 | |
2028 | ensure_current_configuration_is_saved (); |
2029 | |
2030 | output = g_object_get_data (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), "output"); |
2031 | rotation = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "rotation"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((item)), (((GType) ((20) << (2))))) ))), "rotation"))); |
2032 | |
2033 | cafe_rr_output_info_set_rotation (output, rotation); |
2034 | |
2035 | error = NULL((void*)0); |
2036 | if (!cafe_rr_config_save (priv->configuration, &error)) { |
2037 | error_message (manager, _("Could not save monitor configuration")gettext ("Could not save monitor configuration"), error, NULL((void*)0)); |
2038 | if (error) |
2039 | g_error_free (error); |
2040 | |
2041 | return; |
2042 | } |
2043 | |
2044 | try_to_apply_intended_configuration (manager, NULL((void*)0), ctk_get_current_event_time (), NULL((void*)0)); /* NULL-GError */ |
2045 | } |
2046 | |
2047 | static void |
2048 | mirror_outputs_cb(CtkCheckMenuItem *item, gpointer data) |
2049 | { |
2050 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
2051 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2052 | CafeRRScreen *screen = priv->rw_screen; |
2053 | |
2054 | if (ctk_check_menu_item_get_active(item)){ |
2055 | |
2056 | CafeRRConfig *config; |
2057 | config = make_clone_setup (screen); |
2058 | if (!config || config == NULL((void*)0)){ |
2059 | error_message (manager, _("Mirroring outputs not supported")gettext ("Mirroring outputs not supported"), NULL((void*)0), NULL((void*)0)); |
2060 | } |
2061 | |
2062 | cafe_rr_config_save (config, NULL((void*)0)); |
2063 | try_to_apply_intended_configuration (manager, NULL((void*)0), ctk_get_current_event_time (), NULL((void*)0)); |
2064 | |
2065 | g_object_unref (config); |
2066 | |
2067 | } |
2068 | else{ |
2069 | |
2070 | CafeRRConfig *config; |
2071 | config = make_primary_only_setup (screen); |
2072 | /*If nothing worked, bring up the display capplet so the user can reconfigure*/ |
2073 | if (config == NULL((void*)0)) |
2074 | run_display_capplet(CTK_WIDGET(item)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_widget_get_type ()))))))); |
2075 | cafe_rr_config_save (config, NULL((void*)0)); |
2076 | try_to_apply_intended_configuration (manager, NULL((void*)0), ctk_get_current_event_time (), NULL((void*)0)); |
2077 | |
2078 | g_object_unref (config); |
2079 | |
2080 | } |
2081 | } |
2082 | static void |
2083 | add_items_for_rotations (CsdXrandrManager *manager, CafeRROutputInfo *output, CafeRRRotation allowed_rotations) |
2084 | { |
2085 | typedef struct { |
2086 | CafeRRRotation rotation; |
2087 | const char * name; |
2088 | } RotationInfo; |
2089 | static const RotationInfo rotations[] = { |
2090 | { CAFE_RR_ROTATION_0, N_("Normal")("Normal") }, |
2091 | { CAFE_RR_ROTATION_90, N_("Left")("Left") }, |
2092 | { CAFE_RR_ROTATION_270, N_("Right")("Right") }, |
2093 | { CAFE_RR_ROTATION_180, N_("Upside Down")("Upside Down") }, |
2094 | /* We don't allow REFLECT_X or REFLECT_Y for now, as cafe-display-properties doesn't allow them, either */ |
2095 | }; |
2096 | |
2097 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2098 | int i; |
2099 | GSList *group; |
2100 | CtkWidget *active_item; |
2101 | gulong active_item_activate_id; |
2102 | |
2103 | group = NULL((void*)0); |
2104 | active_item = NULL((void*)0); |
2105 | active_item_activate_id = 0; |
2106 | |
2107 | for (i = 0; i < G_N_ELEMENTS (rotations)(sizeof (rotations) / sizeof ((rotations)[0])); i++) { |
2108 | CafeRRRotation rot; |
2109 | CtkWidget *item; |
2110 | gulong activate_id; |
2111 | |
2112 | rot = rotations[i].rotation; |
2113 | |
2114 | if ((allowed_rotations & rot) == 0) { |
2115 | /* don't display items for rotations which are |
2116 | * unavailable. Their availability is not under the |
2117 | * user's control, anyway. |
2118 | */ |
2119 | continue; |
2120 | } |
2121 | |
2122 | item = ctk_radio_menu_item_new_with_label (group, _(rotations[i].name)gettext (rotations[i].name)); |
2123 | /*HERE*/ |
2124 | if (!(cafe_rr_output_info_is_active (output))){ |
2125 | ctk_widget_set_sensitive (item, FALSE(0)); /*Rotation can't be set from the OFF state*/ |
2126 | } |
2127 | ctk_widget_show_all (item); |
2128 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
2129 | |
2130 | g_object_set_data (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), "output", output); |
2131 | g_object_set_data (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), "rotation", GINT_TO_POINTER (rot)((gpointer) (glong) (rot))); |
2132 | |
2133 | activate_id = g_signal_connect (item, "activate",g_signal_connect_data ((item), ("activate"), (((GCallback) (output_rotation_item_activate_cb ))), (manager), ((void*)0), (GConnectFlags) 0) |
2134 | G_CALLBACK (output_rotation_item_activate_cb), manager)g_signal_connect_data ((item), ("activate"), (((GCallback) (output_rotation_item_activate_cb ))), (manager), ((void*)0), (GConnectFlags) 0); |
2135 | |
2136 | group = ctk_radio_menu_item_get_group (CTK_RADIO_MENU_ITEM (item)((((CtkRadioMenuItem*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((item)), ((ctk_radio_menu_item_get_type ())) ))))); |
2137 | |
2138 | if (rot == cafe_rr_output_info_get_rotation (output)) { |
2139 | active_item = item; |
2140 | active_item_activate_id = activate_id; |
2141 | } |
2142 | } |
2143 | |
2144 | if (active_item) { |
2145 | /* Block the signal temporarily so our callback won't be called; |
2146 | * we are just setting up the UI. |
2147 | */ |
2148 | g_signal_handler_block (active_item, active_item_activate_id); |
2149 | |
2150 | ctk_check_menu_item_set_active (CTK_CHECK_MENU_ITEM (active_item)((((CtkCheckMenuItem*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((active_item)), ((ctk_check_menu_item_get_type ())))))), TRUE(!(0))); |
2151 | |
2152 | g_signal_handler_unblock (active_item, active_item_activate_id); |
2153 | } |
2154 | |
2155 | } |
2156 | |
2157 | static void |
2158 | add_rotation_items_for_output (CsdXrandrManager *manager, CafeRROutputInfo *output) |
2159 | { |
2160 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2161 | int num_rotations; |
2162 | CafeRRRotation rotations; |
2163 | |
2164 | get_allowed_rotations_for_output (priv->configuration, priv->rw_screen, output, &num_rotations, &rotations); |
2165 | |
2166 | if (num_rotations == 1) |
2167 | add_unsupported_rotation_item (manager); |
2168 | else |
2169 | add_items_for_rotations (manager, output, rotations); |
2170 | } |
2171 | |
2172 | static void |
2173 | add_enable_option_for_output (CsdXrandrManager *manager, CafeRROutputInfo *output) |
2174 | { |
2175 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2176 | CtkWidget *item; |
2177 | gulong activate_id; |
2178 | |
2179 | item = ctk_check_menu_item_new(); |
2180 | |
2181 | if (cafe_rr_output_info_is_active (output)){ |
2182 | ctk_menu_item_set_label (CTK_MENU_ITEM(item)((((CtkMenuItem*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_menu_item_get_type ())))))), _("ON")gettext ("ON")); |
2183 | ctk_widget_set_tooltip_text(item, _("Turn this monitor off")gettext ("Turn this monitor off")); |
2184 | } |
2185 | else { |
2186 | ctk_menu_item_set_label (CTK_MENU_ITEM(item)((((CtkMenuItem*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_menu_item_get_type ())))))), _("OFF")gettext ("OFF")); |
2187 | ctk_widget_set_tooltip_text(item, _("Turn this monitor on")gettext ("Turn this monitor on")); |
2188 | } |
2189 | |
2190 | ctk_widget_show_all (item); |
2191 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
2192 | |
2193 | g_object_set_data (G_OBJECT (item)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), (((GType) ((20) << (2)))))))), "output", output); |
2194 | |
2195 | activate_id = g_signal_connect (item, "activate",g_signal_connect_data ((item), ("activate"), (((GCallback) (monitor_activate_cb ))), (manager), ((void*)0), (GConnectFlags) 0) |
2196 | G_CALLBACK (monitor_activate_cb), manager)g_signal_connect_data ((item), ("activate"), (((GCallback) (monitor_activate_cb ))), (manager), ((void*)0), (GConnectFlags) 0); |
2197 | |
2198 | /* Block the signal temporarily so our callback won't be called; |
2199 | * we are just setting up the UI. |
2200 | */ |
2201 | g_signal_handler_block (item, activate_id); |
2202 | |
2203 | if (cafe_rr_output_info_is_active (output)){ |
2204 | ctk_check_menu_item_set_active(CTK_CHECK_MENU_ITEM(item)((((CtkCheckMenuItem*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((item)), ((ctk_check_menu_item_get_type ())) )))), TRUE(!(0))); |
2205 | } |
2206 | else{ |
2207 | ctk_check_menu_item_set_active(CTK_CHECK_MENU_ITEM(item)((((CtkCheckMenuItem*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((item)), ((ctk_check_menu_item_get_type ())) )))), FALSE(0)); |
2208 | } |
2209 | |
2210 | g_signal_handler_unblock (item, activate_id); |
2211 | } |
2212 | |
2213 | static void |
2214 | add_menu_items_for_output (CsdXrandrManager *manager, CafeRROutputInfo *output) |
2215 | { |
2216 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2217 | CtkWidget *item; |
2218 | |
2219 | item = make_menu_item_for_output_title (manager, output); |
2220 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
2221 | |
2222 | add_enable_option_for_output (manager, output); |
2223 | add_rotation_items_for_output (manager, output); |
2224 | } |
2225 | |
2226 | static void |
2227 | add_menu_items_for_outputs (CsdXrandrManager *manager) |
2228 | { |
2229 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2230 | int i; |
2231 | CafeRROutputInfo **outputs; |
2232 | |
2233 | outputs = cafe_rr_config_get_outputs (priv->configuration); |
2234 | for (i = 0; outputs[i] != NULL((void*)0); i++) { |
2235 | if (cafe_rr_output_info_is_connected (outputs[i])) |
2236 | add_menu_items_for_output (manager, outputs[i]); |
2237 | } |
2238 | } |
2239 | |
2240 | static void |
2241 | add_menu_items_for_clone (CsdXrandrManager *manager) |
2242 | { |
2243 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2244 | CtkWidget *item; |
2245 | gulong activate_id; |
2246 | |
2247 | item = ctk_check_menu_item_new_with_label(_("Same output all monitors")gettext ("Same output all monitors")); |
2248 | ctk_widget_set_tooltip_text(item, _("Mirror same output to all monitors and turn them on")gettext ("Mirror same output to all monitors and turn them on" )); |
2249 | ctk_widget_show_all (item); |
2250 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
2251 | activate_id = g_signal_connect (item, "activate",g_signal_connect_data ((item), ("activate"), (((GCallback) (mirror_outputs_cb ))), (manager), ((void*)0), (GConnectFlags) 0) |
2252 | G_CALLBACK (mirror_outputs_cb), manager)g_signal_connect_data ((item), ("activate"), (((GCallback) (mirror_outputs_cb ))), (manager), ((void*)0), (GConnectFlags) 0); |
2253 | /*Block the handler until the GUI is set up no matter what the monitor state*/ |
2254 | g_signal_handler_block (item, activate_id); |
2255 | |
2256 | if (cafe_rr_config_get_clone(priv->configuration)){ |
2257 | ctk_check_menu_item_set_active(CTK_CHECK_MENU_ITEM(item)((((CtkCheckMenuItem*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((item)), ((ctk_check_menu_item_get_type ())) )))), TRUE(!(0))); |
2258 | } |
2259 | else{ |
2260 | ctk_check_menu_item_set_active(CTK_CHECK_MENU_ITEM(item)((((CtkCheckMenuItem*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((item)), ((ctk_check_menu_item_get_type ())) )))), FALSE(0)); |
2261 | } |
2262 | g_signal_handler_unblock (item, activate_id); |
2263 | } |
2264 | |
2265 | static void |
2266 | status_icon_popup_menu (CsdXrandrManager *manager, guint button, guint32 timestamp) |
2267 | { |
2268 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2269 | CtkWidget *item; |
2270 | CtkWidget *image; |
2271 | CtkWidget *label; |
2272 | CtkWidget *box; |
2273 | GSettings *icon_settings; |
2274 | |
2275 | g_assert (priv->configuration == NULL)do { if (priv->configuration == ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c", 2275, ((const char*) ( __func__)), "priv->configuration == NULL"); } while (0); |
2276 | priv->configuration = cafe_rr_config_new_current (priv->rw_screen, NULL((void*)0)); |
2277 | |
2278 | g_assert (priv->labeler == NULL)do { if (priv->labeler == ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c", 2278, ((const char*) ( __func__)), "priv->labeler == NULL"); } while (0); |
2279 | priv->labeler = cafe_rr_labeler_new (priv->configuration); |
2280 | |
2281 | g_assert (priv->popup_menu == NULL)do { if (priv->popup_menu == ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0), "csd_xrandr-manager.c", 2281, ((const char*) ( __func__)), "priv->popup_menu == NULL"); } while (0); |
2282 | priv->popup_menu = ctk_menu_new (); |
2283 | |
2284 | add_menu_items_for_outputs (manager); |
2285 | |
2286 | item = ctk_separator_menu_item_new (); |
2287 | ctk_widget_show (item); |
2288 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
2289 | |
2290 | add_menu_items_for_clone (manager); |
2291 | |
2292 | item = ctk_menu_item_new(); |
2293 | box = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 10); |
2294 | image = ctk_image_new_from_icon_name ("preferences-system", CTK_ICON_SIZE_MENU); |
2295 | label = ctk_label_new_with_mnemonic(_("_Configure Display Settings…")gettext ("_Configure Display Settings…")); |
2296 | /*Load the icon unless the user has icons in menus turned off*/ |
2297 | icon_settings = g_settings_new ("org.cafe.interface"); |
2298 | if (g_settings_get_boolean (icon_settings, "menus-have-icons")){ |
2299 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), image); |
2300 | g_signal_connect (item, "size-allocate",g_signal_connect_data ((item), ("size-allocate"), (((GCallback ) (title_item_size_allocate_cb))), (((void*)0)), ((void*)0), ( GConnectFlags) 0) |
2301 | G_CALLBACK (title_item_size_allocate_cb), NULL)g_signal_connect_data ((item), ("size-allocate"), (((GCallback ) (title_item_size_allocate_cb))), (((void*)0)), ((void*)0), ( GConnectFlags) 0); |
2302 | } |
2303 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), label); |
2304 | ctk_container_add (CTK_CONTAINER (item)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item)), ((ctk_container_get_type ())))))), box); |
2305 | ctk_widget_set_tooltip_text(item, _("Open the display configuration dialog (all settings)")gettext ("Open the display configuration dialog (all settings)" )); |
2306 | g_signal_connect (item, "activate",g_signal_connect_data ((item), ("activate"), (((GCallback) (popup_menu_configure_display_cb ))), (manager), ((void*)0), (GConnectFlags) 0) |
2307 | G_CALLBACK (popup_menu_configure_display_cb), manager)g_signal_connect_data ((item), ("activate"), (((GCallback) (popup_menu_configure_display_cb ))), (manager), ((void*)0), (GConnectFlags) 0); |
2308 | ctk_widget_show_all (item); |
2309 | ctk_menu_shell_append (CTK_MENU_SHELL (priv->popup_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_shell_get_type ()))))) ), item); |
2310 | |
2311 | g_signal_connect (priv->popup_menu, "selection-done",g_signal_connect_data ((priv->popup_menu), ("selection-done" ), (((GCallback) (status_icon_popup_menu_selection_done_cb))) , (manager), ((void*)0), (GConnectFlags) 0) |
2312 | G_CALLBACK (status_icon_popup_menu_selection_done_cb), manager)g_signal_connect_data ((priv->popup_menu), ("selection-done" ), (((GCallback) (status_icon_popup_menu_selection_done_cb))) , (manager), ((void*)0), (GConnectFlags) 0); |
2313 | |
2314 | /*Set up custom theming and forced transparency support*/ |
2315 | CtkWidget *toplevel = ctk_widget_get_toplevel (priv->popup_menu); |
2316 | /*Fix any failures of compiz/other wm's to communicate with ctk for transparency */ |
2317 | CdkScreen *screen = ctk_widget_get_screen(CTK_WIDGET(toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((toplevel)), ((ctk_widget_get_type ()))))))); |
2318 | CdkVisual *visual = cdk_screen_get_rgba_visual(screen); |
2319 | ctk_widget_set_visual(CTK_WIDGET(toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((toplevel)), ((ctk_widget_get_type ())))))), visual); |
2320 | /*Set up the ctk theme class from cafe-panel*/ |
2321 | CtkStyleContext *context; |
2322 | context = ctk_widget_get_style_context (CTK_WIDGET(toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((toplevel)), ((ctk_widget_get_type ()))))))); |
2323 | ctk_style_context_add_class(context,"gnome-panel-menu-bar"); |
2324 | ctk_style_context_add_class(context,"cafe-panel-menu-bar"); |
2325 | |
2326 | ctk_menu_popup (CTK_MENU (priv->popup_menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((priv->popup_menu)), ((ctk_menu_get_type ())))))), NULL((void*)0), NULL((void*)0), |
2327 | ctk_status_icon_position_menu, |
2328 | priv->status_icon, button, timestamp); |
2329 | } |
2330 | |
2331 | static void |
2332 | status_icon_activate_cb (CtkStatusIcon *status_icon, gpointer data) |
2333 | { |
2334 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
2335 | |
2336 | /* Suck; we don't get a proper button/timestamp */ |
2337 | status_icon_popup_menu (manager, 0, ctk_get_current_event_time ()); |
2338 | } |
2339 | |
2340 | static void |
2341 | status_icon_popup_menu_cb (CtkStatusIcon *status_icon, guint button, guint32 timestamp, gpointer data) |
2342 | { |
2343 | CsdXrandrManager *manager = CSD_XRANDR_MANAGER (data)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((data)), ((csd_xrandr_manager_get_type ()))) ))); |
2344 | |
2345 | status_icon_popup_menu (manager, button, timestamp); |
2346 | } |
2347 | |
2348 | static void |
2349 | status_icon_start (CsdXrandrManager *manager) |
2350 | { |
2351 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2352 | |
2353 | /* Ideally, we should detect if we are on a tablet and only display |
2354 | * the icon in that case. |
2355 | */ |
2356 | if (!priv->status_icon) { |
2357 | priv->status_icon = ctk_status_icon_new_from_icon_name (CSD_XRANDR_ICON_NAME"csd_xrandr"); |
2358 | ctk_status_icon_set_tooltip_text (priv->status_icon, _("Configure display settings")gettext ("Configure display settings")); |
2359 | |
2360 | g_signal_connect (priv->status_icon, "activate",g_signal_connect_data ((priv->status_icon), ("activate"), ( ((GCallback) (status_icon_activate_cb))), (manager), ((void*) 0), (GConnectFlags) 0) |
2361 | G_CALLBACK (status_icon_activate_cb), manager)g_signal_connect_data ((priv->status_icon), ("activate"), ( ((GCallback) (status_icon_activate_cb))), (manager), ((void*) 0), (GConnectFlags) 0); |
2362 | g_signal_connect (priv->status_icon, "popup-menu",g_signal_connect_data ((priv->status_icon), ("popup-menu") , (((GCallback) (status_icon_popup_menu_cb))), (manager), ((void *)0), (GConnectFlags) 0) |
2363 | G_CALLBACK (status_icon_popup_menu_cb), manager)g_signal_connect_data ((priv->status_icon), ("popup-menu") , (((GCallback) (status_icon_popup_menu_cb))), (manager), ((void *)0), (GConnectFlags) 0); |
2364 | } |
2365 | } |
2366 | |
2367 | static void |
2368 | status_icon_stop (CsdXrandrManager *manager) |
2369 | { |
2370 | struct CsdXrandrManagerPrivate *priv = manager->priv; |
2371 | |
2372 | if (priv->status_icon) { |
2373 | g_signal_handlers_disconnect_by_func (g_signal_handlers_disconnect_matched ((priv->status_icon), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (((GCallback) (status_icon_activate_cb)) ), (manager)) |
2374 | priv->status_icon, G_CALLBACK (status_icon_activate_cb), manager)g_signal_handlers_disconnect_matched ((priv->status_icon), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (((GCallback) (status_icon_activate_cb)) ), (manager)); |
2375 | g_signal_handlers_disconnect_by_func (g_signal_handlers_disconnect_matched ((priv->status_icon), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (((GCallback) (status_icon_popup_menu_cb ))), (manager)) |
2376 | priv->status_icon, G_CALLBACK (status_icon_popup_menu_cb), manager)g_signal_handlers_disconnect_matched ((priv->status_icon), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA ), 0, 0, ((void*)0), (((GCallback) (status_icon_popup_menu_cb ))), (manager)); |
2377 | |
2378 | /* hide the icon before unreffing it; otherwise we will leak |
2379 | whitespace in the notification area due to a bug in there */ |
2380 | ctk_status_icon_set_visible (priv->status_icon, FALSE(0)); |
2381 | g_object_unref (priv->status_icon); |
2382 | priv->status_icon = NULL((void*)0); |
2383 | } |
2384 | } |
2385 | |
2386 | static void |
2387 | start_or_stop_icon (CsdXrandrManager *manager) |
2388 | { |
2389 | if (g_settings_get_boolean (manager->priv->settings, CONF_KEY_SHOW_NOTIFICATION_ICON"show-notification-icon")) { |
2390 | status_icon_start (manager); |
2391 | } |
2392 | else { |
2393 | status_icon_stop (manager); |
2394 | } |
2395 | } |
2396 | |
2397 | static void |
2398 | on_config_changed (GSettings *settings, |
2399 | gchar *key, |
2400 | CsdXrandrManager *manager) |
2401 | { |
2402 | if (g_strcmp0 (key, CONF_KEY_SHOW_NOTIFICATION_ICON"show-notification-icon") == 0) |
2403 | start_or_stop_icon (manager); |
2404 | } |
2405 | |
2406 | static gboolean |
2407 | apply_intended_configuration (CsdXrandrManager *manager, const char *intended_filename, guint32 timestamp) |
2408 | { |
2409 | GError *my_error; |
2410 | gboolean result; |
2411 | |
2412 | #ifdef HAVE_RDA |
2413 | if (rda_session_is_remote()) { |
2414 | return; |
2415 | } |
2416 | #endif |
2417 | |
2418 | my_error = NULL((void*)0); |
2419 | result = apply_configuration_from_filename (manager, intended_filename, TRUE(!(0)), timestamp, &my_error); |
2420 | if (!result) { |
2421 | if (my_error) { |
2422 | if (!g_error_matches (my_error, G_FILE_ERRORg_file_error_quark (), G_FILE_ERROR_NOENT) && |
2423 | !g_error_matches (my_error, CAFE_RR_ERROR(cafe_rr_error_quark ()), CAFE_RR_ERROR_NO_MATCHING_CONFIG)) |
2424 | error_message (manager, _("Could not apply the stored configuration for monitors")gettext ("Could not apply the stored configuration for monitors" ), my_error, NULL((void*)0)); |
2425 | |
2426 | g_error_free (my_error); |
2427 | } |
2428 | } |
2429 | |
2430 | return result; |
2431 | } |
2432 | |
2433 | static void |
2434 | apply_default_boot_configuration (CsdXrandrManager *mgr, guint32 timestamp) |
2435 | { |
2436 | CsdXrandrManagerPrivate *priv = mgr->priv; |
2437 | CafeRRScreen *screen = priv->rw_screen; |
2438 | CafeRRConfig *config; |
2439 | gboolean turn_on_external, turn_on_laptop; |
2440 | |
2441 | turn_on_external = |
2442 | g_settings_get_boolean (mgr->priv->settings, CONF_KEY_TURN_ON_EXTERNAL_MONITORS_AT_STARTUP"turn-on-external-monitors-at-startup"); |
2443 | turn_on_laptop = |
2444 | g_settings_get_boolean (mgr->priv->settings, CONF_KEY_TURN_ON_LAPTOP_MONITOR_AT_STARTUP"turn-on-laptop-monitor-at-startup"); |
2445 | |
2446 | if (turn_on_external && turn_on_laptop) |
2447 | config = make_clone_setup (screen); |
2448 | else if (!turn_on_external && turn_on_laptop) |
2449 | config = make_laptop_setup (screen); |
2450 | else if (turn_on_external && !turn_on_laptop) |
2451 | config = make_other_setup (screen); |
2452 | else |
2453 | config = make_laptop_setup (screen); |
2454 | |
2455 | if (config) { |
2456 | apply_configuration_and_display_error (mgr, config, timestamp); |
2457 | g_object_unref (config); |
2458 | } |
2459 | } |
2460 | |
2461 | static gboolean |
2462 | apply_stored_configuration_at_startup (CsdXrandrManager *manager, guint32 timestamp) |
2463 | { |
2464 | GError *my_error; |
2465 | gboolean success; |
2466 | char *backup_filename; |
2467 | char *intended_filename; |
2468 | |
2469 | backup_filename = cafe_rr_config_get_backup_filename (); |
2470 | intended_filename = cafe_rr_config_get_intended_filename (); |
2471 | |
2472 | /* 1. See if there was a "saved" configuration. If there is one, it means |
2473 | * that the user had selected to change the display configuration, but the |
2474 | * machine crashed. In that case, we'll apply *that* configuration and save it on top of the |
2475 | * "intended" one. |
2476 | */ |
2477 | |
2478 | my_error = NULL((void*)0); |
2479 | |
2480 | success = apply_configuration_from_filename (manager, backup_filename, FALSE(0), timestamp, &my_error); |
2481 | if (success) { |
2482 | /* The backup configuration existed, and could be applied |
2483 | * successfully, so we must restore it on top of the |
2484 | * failed/intended one. |
2485 | */ |
2486 | restore_backup_configuration (manager, backup_filename, intended_filename, timestamp); |
2487 | goto out; |
2488 | } |
2489 | |
2490 | if (!g_error_matches (my_error, G_FILE_ERRORg_file_error_quark (), G_FILE_ERROR_NOENT)) { |
2491 | /* Epic fail: there (probably) was a backup configuration, but |
2492 | * we could not apply it. The only thing we can do is delete |
2493 | * the backup configuration. Let's hope that the user doesn't |
2494 | * get left with an unusable display... |
2495 | */ |
2496 | |
2497 | unlink (backup_filename); |
2498 | goto out; |
2499 | } |
2500 | |
2501 | /* 2. There was no backup configuration! This means we are |
2502 | * good. Apply the intended configuration instead. |
2503 | */ |
2504 | |
2505 | success = apply_intended_configuration (manager, intended_filename, timestamp); |
2506 | |
2507 | out: |
2508 | if (my_error) |
2509 | g_error_free (my_error); |
2510 | |
2511 | g_free (backup_filename); |
2512 | g_free (intended_filename); |
2513 | |
2514 | return success; |
2515 | } |
2516 | |
2517 | static gboolean |
2518 | apply_default_configuration_from_file (CsdXrandrManager *manager, guint32 timestamp) |
2519 | { |
2520 | CsdXrandrManagerPrivate *priv = manager->priv; |
2521 | char *default_config_filename; |
2522 | gboolean result; |
2523 | |
2524 | default_config_filename = g_settings_get_string (priv->settings, CONF_KEY_DEFAULT_CONFIGURATION_FILE"default-configuration-file"); |
2525 | if (!default_config_filename) |
2526 | return FALSE(0); |
2527 | |
2528 | result = apply_configuration_from_filename (manager, default_config_filename, TRUE(!(0)), timestamp, NULL((void*)0)); |
2529 | |
2530 | g_free (default_config_filename); |
2531 | return result; |
2532 | } |
2533 | |
2534 | gboolean |
2535 | csd_xrandr_manager_start (CsdXrandrManager *manager, |
2536 | GError **error) |
2537 | { |
2538 | CdkDisplay *display; |
2539 | |
2540 | g_debug ("Starting xrandr manager"); |
2541 | cafe_settings_profile_start (NULL); |
2542 | |
2543 | log_open (); |
2544 | log_msg ("------------------------------------------------------------\nSTARTING XRANDR PLUGIN\n"); |
2545 | |
2546 | manager->priv->rw_screen = cafe_rr_screen_new (cdk_screen_get_default (), error); |
2547 | |
2548 | if (manager->priv->rw_screen == NULL((void*)0)) { |
2549 | log_msg ("Could not initialize the RANDR plugin%s%s\n", |
2550 | (error && *error) ? ": " : "", |
2551 | (error && *error) ? (*error)->message : ""); |
2552 | log_close (); |
2553 | return FALSE(0); |
2554 | } |
2555 | |
2556 | g_signal_connect (manager->priv->rw_screen, "changed", G_CALLBACK (on_randr_event), manager)g_signal_connect_data ((manager->priv->rw_screen), ("changed" ), (((GCallback) (on_randr_event))), (manager), ((void*)0), ( GConnectFlags) 0); |
2557 | |
2558 | log_msg ("State of screen at startup:\n"); |
2559 | log_screen (manager->priv->rw_screen); |
2560 | |
2561 | manager->priv->running = TRUE(!(0)); |
2562 | manager->priv->settings = g_settings_new (CONF_SCHEMA"org.cafe.SettingsDaemon.plugins.xrandr"); |
2563 | |
2564 | g_signal_connect (manager->priv->settings,g_signal_connect_data ((manager->priv->settings), ("changed::" "show-notification-icon"), (((GCallback) (on_config_changed) )), (manager), ((void*)0), (GConnectFlags) 0) |
2565 | "changed::" CONF_KEY_SHOW_NOTIFICATION_ICON,g_signal_connect_data ((manager->priv->settings), ("changed::" "show-notification-icon"), (((GCallback) (on_config_changed) )), (manager), ((void*)0), (GConnectFlags) 0) |
2566 | G_CALLBACK (on_config_changed),g_signal_connect_data ((manager->priv->settings), ("changed::" "show-notification-icon"), (((GCallback) (on_config_changed) )), (manager), ((void*)0), (GConnectFlags) 0) |
2567 | manager)g_signal_connect_data ((manager->priv->settings), ("changed::" "show-notification-icon"), (((GCallback) (on_config_changed) )), (manager), ((void*)0), (GConnectFlags) 0); |
2568 | |
2569 | display = cdk_display_get_default (); |
2570 | |
2571 | if (manager->priv->switch_video_mode_keycode) { |
2572 | cdk_x11_display_error_trap_push (display); |
2573 | |
2574 | XGrabKey (cdk_x11_get_default_xdisplay(), |
2575 | manager->priv->switch_video_mode_keycode, AnyModifier(1<<15), |
2576 | cdk_x11_get_default_root_xwindow(), |
2577 | True1, GrabModeAsync1, GrabModeAsync1); |
2578 | |
2579 | cdk_display_flush (display); |
2580 | cdk_x11_display_error_trap_pop_ignored (display); |
2581 | } |
2582 | |
2583 | if (manager->priv->rotate_windows_keycode) { |
2584 | cdk_x11_display_error_trap_push (display); |
2585 | |
2586 | XGrabKey (cdk_x11_get_default_xdisplay(), |
2587 | manager->priv->rotate_windows_keycode, AnyModifier(1<<15), |
2588 | cdk_x11_get_default_root_xwindow(), |
2589 | True1, GrabModeAsync1, GrabModeAsync1); |
2590 | |
2591 | cdk_display_flush (display); |
2592 | cdk_x11_display_error_trap_pop_ignored (display); |
2593 | } |
2594 | |
2595 | show_timestamps_dialog (manager, "Startup"); |
2596 | if (!apply_stored_configuration_at_startup (manager, CDK_CURRENT_TIME0L)) /* we don't have a real timestamp at startup anyway */ |
2597 | if (!apply_default_configuration_from_file (manager, CDK_CURRENT_TIME0L)) |
2598 | if (!g_settings_get_boolean (manager->priv->settings, CONF_KEY_USE_XORG_MONITOR_SETTINGS"use-xorg-monitor-settings")) |
2599 | apply_default_boot_configuration (manager, CDK_CURRENT_TIME0L); |
2600 | |
2601 | log_msg ("State of screen after initial configuration:\n"); |
2602 | log_screen (manager->priv->rw_screen); |
2603 | |
2604 | cdk_window_add_filter (cdk_get_default_root_window(), |
2605 | (CdkFilterFunc)event_filter, |
2606 | manager); |
2607 | |
2608 | start_or_stop_icon (manager); |
2609 | |
2610 | log_close (); |
2611 | |
2612 | cafe_settings_profile_end (NULL); |
2613 | |
2614 | return TRUE(!(0)); |
2615 | } |
2616 | |
2617 | void |
2618 | csd_xrandr_manager_stop (CsdXrandrManager *manager) |
2619 | { |
2620 | CdkDisplay *display; |
2621 | |
2622 | g_debug ("Stopping xrandr manager"); |
2623 | |
2624 | manager->priv->running = FALSE(0); |
2625 | |
2626 | display = cdk_display_get_default (); |
2627 | |
2628 | if (manager->priv->switch_video_mode_keycode) { |
2629 | cdk_x11_display_error_trap_push (display); |
2630 | |
2631 | XUngrabKey (cdk_x11_get_default_xdisplay(), |
2632 | manager->priv->switch_video_mode_keycode, AnyModifier(1<<15), |
2633 | cdk_x11_get_default_root_xwindow()); |
2634 | |
2635 | cdk_x11_display_error_trap_pop_ignored (display); |
2636 | } |
2637 | |
2638 | if (manager->priv->rotate_windows_keycode) { |
2639 | cdk_x11_display_error_trap_push (display); |
2640 | |
2641 | XUngrabKey (cdk_x11_get_default_xdisplay(), |
2642 | manager->priv->rotate_windows_keycode, AnyModifier(1<<15), |
2643 | cdk_x11_get_default_root_xwindow()); |
2644 | |
2645 | cdk_x11_display_error_trap_pop_ignored (display); |
2646 | } |
2647 | |
2648 | cdk_window_remove_filter (cdk_get_default_root_window (), |
2649 | (CdkFilterFunc) event_filter, |
2650 | manager); |
2651 | |
2652 | if (manager->priv->settings != NULL((void*)0)) { |
2653 | g_object_unref (manager->priv->settings); |
2654 | manager->priv->settings = NULL((void*)0); |
2655 | } |
2656 | |
2657 | if (manager->priv->rw_screen != NULL((void*)0)) { |
2658 | g_object_unref (manager->priv->rw_screen); |
2659 | manager->priv->rw_screen = NULL((void*)0); |
2660 | } |
2661 | |
2662 | if (manager->priv->dbus_connection != NULL((void*)0)) { |
2663 | dbus_g_connection_unref (manager->priv->dbus_connection); |
2664 | manager->priv->dbus_connection = NULL((void*)0); |
2665 | } |
2666 | |
2667 | status_icon_stop (manager); |
2668 | |
2669 | log_open (); |
2670 | log_msg ("STOPPING XRANDR PLUGIN\n------------------------------------------------------------\n"); |
2671 | log_close (); |
2672 | } |
2673 | |
2674 | static void |
2675 | csd_xrandr_manager_class_init (CsdXrandrManagerClass *klass) |
2676 | { |
2677 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
2678 | |
2679 | object_class->finalize = csd_xrandr_manager_finalize; |
2680 | |
2681 | dbus_g_object_type_install_info (CSD_TYPE_XRANDR_MANAGER(csd_xrandr_manager_get_type ()), &dbus_glib_csd_xrandr_manager_object_info); |
2682 | } |
2683 | |
2684 | static guint |
2685 | get_keycode_for_keysym_name (const char *name) |
2686 | { |
2687 | Display *dpy; |
2688 | guint keyval; |
2689 | |
2690 | dpy = cdk_x11_get_default_xdisplay (); |
2691 | |
2692 | keyval = cdk_keyval_from_name (name); |
2693 | return XKeysymToKeycode (dpy, keyval); |
2694 | } |
2695 | |
2696 | static void |
2697 | csd_xrandr_manager_init (CsdXrandrManager *manager) |
2698 | { |
2699 | manager->priv = csd_xrandr_manager_get_instance_private (manager); |
2700 | |
2701 | manager->priv->switch_video_mode_keycode = get_keycode_for_keysym_name (VIDEO_KEYSYM"XF86Display"); |
2702 | manager->priv->rotate_windows_keycode = get_keycode_for_keysym_name (ROTATE_KEYSYM"XF86RotateWindows"); |
2703 | |
2704 | manager->priv->current_fn_f7_config = -1; |
2705 | manager->priv->fn_f7_configs = NULL((void*)0); |
2706 | } |
2707 | |
2708 | static void |
2709 | csd_xrandr_manager_finalize (GObject *object) |
2710 | { |
2711 | CsdXrandrManager *xrandr_manager; |
2712 | |
2713 | g_return_if_fail (object != NULL)do { if ((object != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "object != NULL") ; return; } } while (0); |
2714 | g_return_if_fail (CSD_IS_XRANDR_MANAGER (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((object)); GType __t = ((csd_xrandr_manager_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CSD_IS_XRANDR_MANAGER (object)"); return ; } } while (0); |
2715 | |
2716 | xrandr_manager = CSD_XRANDR_MANAGER (object)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((object)), ((csd_xrandr_manager_get_type ()) ))))); |
2717 | |
2718 | g_return_if_fail (xrandr_manager->priv != NULL)do { if ((xrandr_manager->priv != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "xrandr_manager->priv != NULL" ); return; } } while (0); |
2719 | |
2720 | G_OBJECT_CLASS (csd_xrandr_manager_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((csd_xrandr_manager_parent_class)), (((GType) ((20) << (2))))))))->finalize (object); |
2721 | } |
2722 | |
2723 | static gboolean |
2724 | register_manager_dbus (CsdXrandrManager *manager) |
2725 | { |
2726 | GError *error = NULL((void*)0); |
2727 | |
2728 | manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); |
2729 | if (manager->priv->dbus_connection == NULL((void*)0)) { |
2730 | if (error != NULL((void*)0)) { |
2731 | g_warning ("Error getting session bus: %s", error->message); |
2732 | g_error_free (error); |
2733 | } |
2734 | return FALSE(0); |
2735 | } |
2736 | |
2737 | /* Hmm, should we do this in csd_xrandr_manager_start()? */ |
2738 | dbus_g_connection_register_g_object (manager->priv->dbus_connection, CSD_XRANDR_DBUS_PATH"/org/cafe/SettingsDaemon" "/XRANDR", G_OBJECT (manager)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((manager)), (((GType) ((20) << (2))))))))); |
2739 | |
2740 | return TRUE(!(0)); |
2741 | } |
2742 | |
2743 | CsdXrandrManager * |
2744 | csd_xrandr_manager_new (void) |
2745 | { |
2746 | if (manager_object != NULL((void*)0)) { |
2747 | g_object_ref (manager_object)((__typeof__ (manager_object)) (g_object_ref) (manager_object )); |
2748 | } else { |
2749 | manager_object = g_object_new (CSD_TYPE_XRANDR_MANAGER(csd_xrandr_manager_get_type ()), NULL((void*)0)); |
2750 | g_object_add_weak_pointer (manager_object, |
2751 | (gpointer *) &manager_object); |
2752 | |
2753 | if (!register_manager_dbus (manager_object)) { |
2754 | g_object_unref (manager_object); |
2755 | return NULL((void*)0); |
2756 | } |
2757 | } |
2758 | |
2759 | return CSD_XRANDR_MANAGER (manager_object)((((CsdXrandrManager*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((manager_object)), ((csd_xrandr_manager_get_type ())))))); |
2760 | } |