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