1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
1 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
2 |
*
|
|
3 |
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
4 |
* Copyright (C) 2007, 2008 Red Hat, Inc
|
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
5 |
*
|
6 |
* This program is free software; you can redistribute it and/or modify
|
|
7 |
* it under the terms of the GNU General Public License as published by
|
|
8 |
* the Free Software Foundation; either version 2 of the License, or
|
|
9 |
* (at your option) any later version.
|
|
10 |
*
|
|
11 |
* This program is distributed in the hope that it will be useful,
|
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
* GNU General Public License for more details.
|
|
15 |
*
|
|
16 |
* You should have received a copy of the GNU General Public License
|
|
17 |
* along with this program; if not, write to the Free Software
|
|
18 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
19 |
*
|
|
20 |
*/
|
|
21 |
||
22 |
#include "config.h" |
|
23 |
||
24 |
#include <sys/types.h> |
|
25 |
#include <sys/wait.h> |
|
26 |
#include <stdlib.h> |
|
27 |
#include <stdio.h> |
|
28 |
#include <unistd.h> |
|
29 |
#include <string.h> |
|
30 |
#include <errno.h> |
|
31 |
||
32 |
#include <locale.h> |
|
33 |
||
34 |
#include <glib.h> |
|
35 |
#include <glib/gi18n.h> |
|
36 |
#include <gdk/gdk.h> |
|
37 |
#include <gdk/gdkx.h> |
|
38 |
#include <gtk/gtk.h> |
|
0.1.1
by Sebastian Dröge
Import upstream version 2.22.2.1 |
39 |
#include <gconf/gconf-client.h> |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
40 |
#include <dbus/dbus-glib.h> |
0.1.1
by Sebastian Dröge
Import upstream version 2.22.2.1 |
41 |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
42 |
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
43 |
||
44 |
#include <libgnomeui/gnome-rr-config.h> |
|
45 |
#include <libgnomeui/gnome-rr.h> |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
46 |
#include <libgnomeui/gnome-rr-labeler.h> |
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
47 |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
48 |
#ifdef HAVE_LIBNOTIFY
|
49 |
#include <libnotify/notify.h> |
|
50 |
#endif
|
|
51 |
||
1.1.6
by Sebastien Bacher
Import upstream version 2.22.1 |
52 |
#include "gnome-settings-profile.h" |
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
53 |
#include "gsd-xrandr-manager.h" |
54 |
||
1.1.7
by Sebastien Bacher
Import upstream version 2.23.1.1 |
55 |
#ifndef HOST_NAME_MAX
|
56 |
#define HOST_NAME_MAX 255
|
|
57 |
#endif
|
|
58 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
59 |
#define GSD_XRANDR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManagerPrivate))
|
60 |
||
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
61 |
#define CONF_DIR "/apps/gnome_settings_daemon/xrandr"
|
62 |
#define CONF_KEY "show_notification_icon"
|
|
63 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
64 |
#define VIDEO_KEYSYM "XF86Display"
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
65 |
#define ROTATE_KEYSYM "XF86RotateWindows"
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
66 |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
67 |
/* Number of seconds that the confirmation dialog will last before it resets the
|
68 |
* RANDR configuration to its old state.
|
|
69 |
*/
|
|
70 |
#define CONFIRMATION_DIALOG_SECONDS 30
|
|
71 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
72 |
/* name of the icon files (gsd-xrandr.svg, etc.) */
|
73 |
#define GSD_XRANDR_ICON_NAME "gsd-xrandr"
|
|
74 |
||
75 |
/* executable of the control center's display configuration capplet */
|
|
76 |
#define GSD_XRANDR_DISPLAY_CAPPLET "gnome-display-properties"
|
|
77 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
78 |
#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
|
79 |
#define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
|
|
80 |
#define GSD_XRANDR_DBUS_PATH GSD_DBUS_PATH "/XRANDR"
|
|
81 |
#define GSD_XRANDR_DBUS_NAME GSD_DBUS_NAME ".XRANDR"
|
|
82 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
83 |
struct GsdXrandrManagerPrivate |
84 |
{
|
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
85 |
DBusGConnection *dbus_connection; |
86 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
87 |
/* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */
|
88 |
guint switch_video_mode_keycode; |
|
89 |
||
90 |
/* Key code of the XF86RotateWindows key (present on some tablets) */
|
|
91 |
guint rotate_windows_keycode; |
|
92 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
93 |
GnomeRRScreen *rw_screen; |
94 |
gboolean running; |
|
95 |
||
96 |
GtkStatusIcon *status_icon; |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
97 |
GtkWidget *popup_menu; |
98 |
GnomeRRConfig *configuration; |
|
99 |
GnomeRRLabeler *labeler; |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
100 |
GConfClient *client; |
101 |
int notify_id; |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
102 |
|
103 |
/* fn-F7 status */
|
|
104 |
int current_fn_f7_config; /* -1 if no configs */ |
|
105 |
GnomeRRConfig **fn_f7_configs; /* NULL terminated, NULL if there are no configs */ |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
106 |
|
107 |
/* Last time at which we got a "screen got reconfigured" event; see on_randr_event() */
|
|
108 |
guint32 last_config_timestamp; |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
109 |
};
|
110 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
111 |
static const GnomeRRRotation possible_rotations[] = { |
112 |
GNOME_RR_ROTATION_0, |
|
113 |
GNOME_RR_ROTATION_90, |
|
114 |
GNOME_RR_ROTATION_180, |
|
115 |
GNOME_RR_ROTATION_270
|
|
116 |
/* We don't allow REFLECT_X or REFLECT_Y for now, as gnome-display-properties doesn't allow them, either */
|
|
117 |
};
|
|
118 |
||
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
119 |
static void gsd_xrandr_manager_class_init (GsdXrandrManagerClass *klass); |
120 |
static void gsd_xrandr_manager_init (GsdXrandrManager *xrandr_manager); |
|
121 |
static void gsd_xrandr_manager_finalize (GObject *object); |
|
122 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
123 |
static void error_message (GsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text); |
124 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
125 |
static void status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timestamp); |
126 |
static void run_display_capplet (GtkWidget *widget); |
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
127 |
static void get_allowed_rotations_for_output (GnomeRRConfig *config, |
128 |
GnomeRRScreen *rr_screen, |
|
129 |
GnomeOutputInfo *output, |
|
130 |
int *out_num_rotations, |
|
131 |
GnomeRRRotation *out_rotations); |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
132 |
|
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
133 |
G_DEFINE_TYPE (GsdXrandrManager, gsd_xrandr_manager, G_TYPE_OBJECT) |
134 |
||
135 |
static gpointer manager_object = NULL; |
|
136 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
137 |
static void |
138 |
show_timestamps_dialog (GsdXrandrManager *manager, const char *msg) |
|
139 |
{
|
|
140 |
#if 1
|
|
141 |
return; |
|
142 |
#else
|
|
143 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
144 |
GtkWidget *dialog; |
|
145 |
guint32 change_timestamp, config_timestamp; |
|
146 |
static int serial; |
|
147 |
||
148 |
gnome_rr_screen_get_timestamps (priv->rw_screen, &change_timestamp, &config_timestamp); |
|
149 |
||
150 |
dialog = gtk_message_dialog_new (NULL, |
|
151 |
0, |
|
152 |
GTK_MESSAGE_INFO, |
|
153 |
GTK_BUTTONS_CLOSE, |
|
154 |
"RANDR timestamps (%d):\n%s\nchange: %u\nconfig: %u", |
|
155 |
serial++, |
|
156 |
msg, |
|
157 |
change_timestamp, |
|
158 |
config_timestamp); |
|
159 |
g_signal_connect (dialog, "response", |
|
160 |
G_CALLBACK (gtk_widget_destroy), NULL); |
|
161 |
gtk_widget_show (dialog); |
|
162 |
#endif
|
|
163 |
}
|
|
164 |
||
1.1.32
by Chris Coulson
Import upstream version 2.29.90 |
165 |
/* This function centralizes the use of gnome_rr_config_apply_from_filename_with_time().
|
166 |
*
|
|
167 |
* Optionally filters out GNOME_RR_ERROR_NO_MATCHING_CONFIG from
|
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
168 |
* gnome_rr_config_apply_from_filename_with_time(), since that is not usually an error.
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
169 |
*/
|
170 |
static gboolean |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
171 |
apply_configuration_from_filename (GsdXrandrManager *manager, |
172 |
const char *filename, |
|
173 |
gboolean no_matching_config_is_an_error, |
|
174 |
guint32 timestamp, |
|
175 |
GError **error) |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
176 |
{
|
177 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
178 |
GError *my_error; |
|
179 |
gboolean success; |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
180 |
char *str; |
181 |
||
182 |
str = g_strdup_printf ("Applying %s with timestamp %d", filename, timestamp); |
|
183 |
show_timestamps_dialog (manager, str); |
|
184 |
g_free (str); |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
185 |
|
186 |
my_error = NULL; |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
187 |
success = gnome_rr_config_apply_from_filename_with_time (priv->rw_screen, filename, timestamp, &my_error); |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
188 |
if (success) |
189 |
return TRUE; |
|
190 |
||
191 |
if (g_error_matches (my_error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG)) { |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
192 |
if (no_matching_config_is_an_error) |
193 |
goto fail; |
|
194 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
195 |
/* This is not an error; the user probably changed his monitors
|
196 |
* and so they don't match any of the stored configurations.
|
|
197 |
*/
|
|
198 |
g_error_free (my_error); |
|
199 |
return TRUE; |
|
200 |
}
|
|
201 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
202 |
fail: |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
203 |
g_propagate_error (error, my_error); |
204 |
return FALSE; |
|
205 |
}
|
|
206 |
||
1.1.32
by Chris Coulson
Import upstream version 2.29.90 |
207 |
/* This function centralizes the use of gnome_rr_config_apply_with_time().
|
208 |
*
|
|
209 |
* Applies a configuration and displays an error message if an error happens.
|
|
210 |
* We just return whether setting the configuration succeeded.
|
|
211 |
*/
|
|
212 |
static gboolean |
|
213 |
apply_configuration_and_display_error (GsdXrandrManager *manager, GnomeRRConfig *config, guint32 timestamp) |
|
214 |
{
|
|
215 |
GsdXrandrManagerPrivate *priv = manager->priv; |
|
216 |
GError *error; |
|
217 |
gboolean success; |
|
218 |
||
219 |
error = NULL; |
|
220 |
success = gnome_rr_config_apply_with_time (config, priv->rw_screen, timestamp, &error); |
|
221 |
if (!success) { |
|
222 |
error_message (manager, _("Could not switch the monitor configuration"), error, NULL); |
|
223 |
g_error_free (error); |
|
224 |
}
|
|
225 |
||
226 |
return success; |
|
227 |
}
|
|
228 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
229 |
static void |
230 |
restore_backup_configuration_without_messages (const char *backup_filename, const char *intended_filename) |
|
231 |
{
|
|
232 |
backup_filename = gnome_rr_config_get_backup_filename (); |
|
233 |
rename (backup_filename, intended_filename); |
|
234 |
}
|
|
235 |
||
236 |
static void |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
237 |
restore_backup_configuration (GsdXrandrManager *manager, const char *backup_filename, const char *intended_filename, guint32 timestamp) |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
238 |
{
|
239 |
int saved_errno; |
|
240 |
||
241 |
if (rename (backup_filename, intended_filename) == 0) { |
|
242 |
GError *error; |
|
243 |
||
244 |
error = NULL; |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
245 |
if (!apply_configuration_from_filename (manager, intended_filename, FALSE, timestamp, &error)) { |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
246 |
error_message (manager, _("Could not restore the display's configuration"), error, NULL); |
247 |
||
248 |
if (error) |
|
249 |
g_error_free (error); |
|
250 |
}
|
|
251 |
||
252 |
return; |
|
253 |
}
|
|
254 |
||
255 |
saved_errno = errno; |
|
256 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
257 |
/* ENOENT means the original file didn't exist. That is *not* an error;
|
258 |
* the backup was not created because there wasn't even an original
|
|
259 |
* monitors.xml (such as on a first-time login). Note that *here* there
|
|
260 |
* is a "didn't work" monitors.xml, so we must delete that one.
|
|
261 |
*/
|
|
262 |
if (saved_errno == ENOENT) |
|
263 |
unlink (intended_filename); |
|
264 |
else { |
|
265 |
char *msg; |
|
266 |
||
267 |
msg = g_strdup_printf ("Could not rename %s to %s: %s", |
|
268 |
backup_filename, intended_filename, |
|
269 |
g_strerror (saved_errno)); |
|
270 |
error_message (manager, |
|
271 |
_("Could not restore the display's configuration from a backup"), |
|
272 |
NULL, |
|
273 |
msg); |
|
274 |
g_free (msg); |
|
275 |
}
|
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
276 |
|
277 |
unlink (backup_filename); |
|
278 |
}
|
|
279 |
||
280 |
typedef struct { |
|
281 |
GsdXrandrManager *manager; |
|
282 |
GtkWidget *dialog; |
|
283 |
||
284 |
int countdown; |
|
285 |
int response_id; |
|
286 |
} TimeoutDialog; |
|
287 |
||
288 |
static void |
|
289 |
print_countdown_text (TimeoutDialog *timeout) |
|
290 |
{
|
|
291 |
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (timeout->dialog), |
|
1.1.21
by Sebastien Bacher
Import upstream version 2.27.1 |
292 |
ngettext ("The display will be reset to its previous configuration in %d second", |
293 |
"The display will be reset to its previous configuration in %d seconds", |
|
294 |
timeout->countdown), |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
295 |
timeout->countdown); |
296 |
}
|
|
297 |
||
298 |
static gboolean |
|
299 |
timeout_cb (gpointer data) |
|
300 |
{
|
|
301 |
TimeoutDialog *timeout = data; |
|
302 |
||
303 |
timeout->countdown--; |
|
304 |
||
305 |
if (timeout->countdown == 0) { |
|
306 |
timeout->response_id = GTK_RESPONSE_CANCEL; |
|
307 |
gtk_main_quit (); |
|
308 |
} else { |
|
309 |
print_countdown_text (timeout); |
|
310 |
}
|
|
311 |
||
312 |
return TRUE; |
|
313 |
}
|
|
314 |
||
315 |
static void |
|
316 |
timeout_response_cb (GtkDialog *dialog, int response_id, gpointer data) |
|
317 |
{
|
|
318 |
TimeoutDialog *timeout = data; |
|
319 |
||
320 |
if (response_id == GTK_RESPONSE_DELETE_EVENT) { |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.25.92 |
321 |
/* The user closed the dialog or pressed ESC, revert */
|
322 |
timeout->response_id = GTK_RESPONSE_CANCEL; |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
323 |
} else |
324 |
timeout->response_id = response_id; |
|
325 |
||
326 |
gtk_main_quit (); |
|
327 |
}
|
|
328 |
||
329 |
static gboolean |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
330 |
user_says_things_are_ok (GsdXrandrManager *manager, GdkWindow *parent_window) |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
331 |
{
|
332 |
TimeoutDialog timeout; |
|
333 |
guint timeout_id; |
|
334 |
||
335 |
timeout.manager = manager; |
|
336 |
||
337 |
timeout.dialog = gtk_message_dialog_new (NULL, |
|
338 |
GTK_DIALOG_MODAL, |
|
339 |
GTK_MESSAGE_QUESTION, |
|
340 |
GTK_BUTTONS_NONE, |
|
341 |
_("Does the display look OK?")); |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
342 |
|
343 |
timeout.countdown = CONFIRMATION_DIALOG_SECONDS; |
|
344 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
345 |
print_countdown_text (&timeout); |
346 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.25.92 |
347 |
gtk_dialog_add_button (GTK_DIALOG (timeout.dialog), _("_Restore Previous Configuration"), GTK_RESPONSE_CANCEL); |
348 |
gtk_dialog_add_button (GTK_DIALOG (timeout.dialog), _("_Keep This Configuration"), GTK_RESPONSE_ACCEPT); |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
349 |
gtk_dialog_set_default_response (GTK_DIALOG (timeout.dialog), GTK_RESPONSE_ACCEPT); /* ah, the optimism */ |
350 |
||
351 |
g_signal_connect (timeout.dialog, "response", |
|
352 |
G_CALLBACK (timeout_response_cb), |
|
353 |
&timeout); |
|
354 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
355 |
gtk_widget_realize (timeout.dialog); |
356 |
||
357 |
if (parent_window) |
|
358 |
gdk_window_set_transient_for (gtk_widget_get_window (timeout.dialog), parent_window); |
|
359 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
360 |
gtk_widget_show_all (timeout.dialog); |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
361 |
/* We don't use g_timeout_add_seconds() since we actually care that the user sees "real" second ticks in the dialog */
|
362 |
timeout_id = g_timeout_add (1000, |
|
363 |
timeout_cb, |
|
364 |
&timeout); |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
365 |
gtk_main (); |
366 |
||
367 |
gtk_widget_destroy (timeout.dialog); |
|
368 |
g_source_remove (timeout_id); |
|
369 |
||
370 |
if (timeout.response_id == GTK_RESPONSE_ACCEPT) |
|
371 |
return TRUE; |
|
372 |
else
|
|
373 |
return FALSE; |
|
374 |
}
|
|
375 |
||
1.1.23
by Chris Coulson
Import upstream version 2.27.4 |
376 |
struct confirmation { |
377 |
GsdXrandrManager *manager; |
|
378 |
GdkWindow *parent_window; |
|
379 |
guint32 timestamp; |
|
380 |
};
|
|
381 |
||
382 |
static gboolean |
|
383 |
confirm_with_user_idle_cb (gpointer data) |
|
384 |
{
|
|
385 |
struct confirmation *confirmation = data; |
|
386 |
char *backup_filename; |
|
387 |
char *intended_filename; |
|
388 |
||
389 |
backup_filename = gnome_rr_config_get_backup_filename (); |
|
390 |
intended_filename = gnome_rr_config_get_intended_filename (); |
|
391 |
||
392 |
if (user_says_things_are_ok (confirmation->manager, confirmation->parent_window)) |
|
393 |
unlink (backup_filename); |
|
394 |
else
|
|
395 |
restore_backup_configuration (confirmation->manager, backup_filename, intended_filename, confirmation->timestamp); |
|
396 |
||
397 |
g_free (confirmation); |
|
398 |
||
399 |
return FALSE; |
|
400 |
}
|
|
401 |
||
402 |
static void |
|
403 |
queue_confirmation_by_user (GsdXrandrManager *manager, GdkWindow *parent_window, guint32 timestamp) |
|
404 |
{
|
|
405 |
struct confirmation *confirmation; |
|
406 |
||
407 |
confirmation = g_new (struct confirmation, 1); |
|
408 |
confirmation->manager = manager; |
|
409 |
confirmation->parent_window = parent_window; |
|
410 |
confirmation->timestamp = timestamp; |
|
411 |
||
412 |
g_idle_add (confirm_with_user_idle_cb, confirmation); |
|
413 |
}
|
|
414 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
415 |
static gboolean |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
416 |
try_to_apply_intended_configuration (GsdXrandrManager *manager, GdkWindow *parent_window, guint32 timestamp, GError **error) |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
417 |
{
|
418 |
char *backup_filename; |
|
419 |
char *intended_filename; |
|
420 |
gboolean result; |
|
421 |
||
422 |
/* Try to apply the intended configuration */
|
|
423 |
||
424 |
backup_filename = gnome_rr_config_get_backup_filename (); |
|
425 |
intended_filename = gnome_rr_config_get_intended_filename (); |
|
426 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
427 |
result = apply_configuration_from_filename (manager, intended_filename, FALSE, timestamp, error); |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
428 |
if (!result) { |
429 |
error_message (manager, _("The selected configuration for displays could not be applied"), error ? *error : NULL, NULL); |
|
430 |
restore_backup_configuration_without_messages (backup_filename, intended_filename); |
|
431 |
goto out; |
|
1.1.23
by Chris Coulson
Import upstream version 2.27.4 |
432 |
} else { |
433 |
/* We need to return as quickly as possible, so instead of
|
|
434 |
* confirming with the user right here, we do it in an idle
|
|
435 |
* handler. The caller only expects a status for "could you
|
|
436 |
* change the RANDR configuration?", not "is the user OK with it
|
|
437 |
* as well?".
|
|
438 |
*/
|
|
439 |
queue_confirmation_by_user (manager, parent_window, timestamp); |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
440 |
}
|
441 |
||
442 |
out: |
|
443 |
g_free (backup_filename); |
|
444 |
g_free (intended_filename); |
|
445 |
||
446 |
return result; |
|
447 |
}
|
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
448 |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
449 |
/* DBus method for org.gnome.SettingsDaemon.XRANDR ApplyConfiguration; see gsd-xrandr-manager.xml for the interface definition */
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
450 |
static gboolean |
451 |
gsd_xrandr_manager_apply_configuration (GsdXrandrManager *manager, |
|
452 |
GError **error) |
|
453 |
{
|
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
454 |
return try_to_apply_intended_configuration (manager, NULL, GDK_CURRENT_TIME, error); |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
455 |
}
|
456 |
||
457 |
/* DBus method for org.gnome.SettingsDaemon.XRANDR_2 ApplyConfiguration; see gsd-xrandr-manager.xml for the interface definition */
|
|
458 |
static gboolean |
|
459 |
gsd_xrandr_manager_2_apply_configuration (GsdXrandrManager *manager, |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
460 |
gint64 parent_window_id, |
461 |
gint64 timestamp, |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
462 |
GError **error) |
463 |
{
|
|
464 |
GdkWindow *parent_window; |
|
465 |
gboolean result; |
|
466 |
||
467 |
if (parent_window_id != 0) |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
468 |
parent_window = gdk_window_foreign_new_for_display (gdk_display_get_default (), (GdkNativeWindow) parent_window_id); |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
469 |
else
|
470 |
parent_window = NULL; |
|
471 |
||
472 |
result = try_to_apply_intended_configuration (manager, parent_window, (guint32) timestamp, error); |
|
473 |
||
474 |
if (parent_window) |
|
475 |
g_object_unref (parent_window); |
|
476 |
||
477 |
return result; |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
478 |
}
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
479 |
|
480 |
/* We include this after the definition of gsd_xrandr_manager_apply_configuration() so the prototype will already exist */
|
|
481 |
#include "gsd-xrandr-manager-glue.h" |
|
482 |
||
483 |
static gboolean |
|
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
484 |
is_laptop (GnomeRRScreen *screen, GnomeOutputInfo *output) |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
485 |
{
|
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
486 |
GnomeRROutput *rr_output; |
487 |
||
488 |
rr_output = gnome_rr_screen_get_output_by_name (screen, output->name); |
|
489 |
return gnome_rr_output_is_laptop (rr_output); |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
490 |
}
|
491 |
||
492 |
static gboolean |
|
493 |
get_clone_size (GnomeRRScreen *screen, int *width, int *height) |
|
494 |
{
|
|
495 |
GnomeRRMode **modes = gnome_rr_screen_list_clone_modes (screen); |
|
496 |
int best_w, best_h; |
|
497 |
int i; |
|
498 |
||
499 |
best_w = 0; |
|
500 |
best_h = 0; |
|
501 |
||
502 |
for (i = 0; modes[i] != NULL; ++i) { |
|
503 |
GnomeRRMode *mode = modes[i]; |
|
504 |
int w, h; |
|
505 |
||
506 |
w = gnome_rr_mode_get_width (mode); |
|
507 |
h = gnome_rr_mode_get_height (mode); |
|
508 |
||
509 |
if (w * h > best_w * best_h) { |
|
510 |
best_w = w; |
|
511 |
best_h = h; |
|
512 |
}
|
|
513 |
}
|
|
514 |
||
515 |
if (best_w > 0 && best_h > 0) { |
|
516 |
if (width) |
|
517 |
*width = best_w; |
|
518 |
if (height) |
|
519 |
*height = best_h; |
|
520 |
||
521 |
return TRUE; |
|
522 |
}
|
|
523 |
||
524 |
return FALSE; |
|
525 |
}
|
|
526 |
||
527 |
static void |
|
528 |
print_output (GnomeOutputInfo *info) |
|
529 |
{
|
|
530 |
g_print (" Output: %s attached to %s\n", info->display_name, info->name); |
|
531 |
g_print (" status: %s\n", info->on ? "on" : "off"); |
|
532 |
g_print (" width: %d\n", info->width); |
|
533 |
g_print (" height: %d\n", info->height); |
|
534 |
g_print (" rate: %d\n", info->rate); |
|
535 |
g_print (" position: %d %d\n", info->x, info->y); |
|
536 |
}
|
|
537 |
||
538 |
static void |
|
539 |
print_configuration (GnomeRRConfig *config, const char *header) |
|
540 |
{
|
|
541 |
int i; |
|
542 |
||
543 |
g_print ("=== %s Configuration ===\n", header); |
|
544 |
if (!config) { |
|
545 |
g_print (" none\n"); |
|
546 |
return; |
|
547 |
}
|
|
548 |
||
549 |
for (i = 0; config->outputs[i] != NULL; ++i) |
|
550 |
print_output (config->outputs[i]); |
|
551 |
}
|
|
552 |
||
553 |
static GnomeRRConfig * |
|
554 |
make_clone_setup (GnomeRRScreen *screen) |
|
555 |
{
|
|
556 |
GnomeRRConfig *result; |
|
557 |
int width, height; |
|
558 |
int i; |
|
559 |
||
560 |
if (!get_clone_size (screen, &width, &height)) |
|
561 |
return NULL; |
|
562 |
||
563 |
result = gnome_rr_config_new_current (screen); |
|
564 |
||
565 |
for (i = 0; result->outputs[i] != NULL; ++i) { |
|
566 |
GnomeOutputInfo *info = result->outputs[i]; |
|
567 |
||
568 |
info->on = FALSE; |
|
569 |
if (info->connected) { |
|
570 |
GnomeRROutput *output = |
|
571 |
gnome_rr_screen_get_output_by_name (screen, info->name); |
|
572 |
GnomeRRMode **modes = gnome_rr_output_list_modes (output); |
|
573 |
int j; |
|
574 |
int best_rate = 0; |
|
575 |
||
576 |
for (j = 0; modes[j] != NULL; ++j) { |
|
577 |
GnomeRRMode *mode = modes[j]; |
|
578 |
int w, h; |
|
579 |
||
580 |
w = gnome_rr_mode_get_width (mode); |
|
581 |
h = gnome_rr_mode_get_height (mode); |
|
582 |
||
583 |
if (w == width && h == height) { |
|
584 |
int r = gnome_rr_mode_get_freq (mode); |
|
585 |
if (r > best_rate) |
|
586 |
best_rate = r; |
|
587 |
}
|
|
588 |
}
|
|
589 |
||
590 |
if (best_rate > 0) { |
|
591 |
info->on = TRUE; |
|
592 |
info->width = width; |
|
593 |
info->height = height; |
|
594 |
info->rate = best_rate; |
|
595 |
info->rotation = GNOME_RR_ROTATION_0; |
|
596 |
info->x = 0; |
|
597 |
info->y = 0; |
|
598 |
}
|
|
599 |
}
|
|
600 |
}
|
|
601 |
||
602 |
print_configuration (result, "clone setup"); |
|
603 |
||
604 |
return result; |
|
605 |
}
|
|
606 |
||
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
607 |
static GnomeRRMode * |
608 |
find_best_mode (GnomeRROutput *output) |
|
609 |
{
|
|
610 |
GnomeRRMode *preferred; |
|
611 |
GnomeRRMode **modes; |
|
612 |
int best_size; |
|
613 |
int best_width, best_height, best_rate; |
|
614 |
int i; |
|
615 |
GnomeRRMode *best_mode; |
|
616 |
||
617 |
preferred = gnome_rr_output_get_preferred_mode (output); |
|
618 |
if (preferred) |
|
619 |
return preferred; |
|
620 |
||
621 |
modes = gnome_rr_output_list_modes (output); |
|
622 |
if (!modes) |
|
623 |
return NULL; |
|
624 |
||
625 |
best_size = best_width = best_height = best_rate = 0; |
|
626 |
best_mode = NULL; |
|
627 |
||
628 |
for (i = 0; modes[i] != NULL; i++) { |
|
629 |
int w, h, r; |
|
630 |
int size; |
|
631 |
||
632 |
w = gnome_rr_mode_get_width (modes[i]); |
|
633 |
h = gnome_rr_mode_get_height (modes[i]); |
|
634 |
r = gnome_rr_mode_get_freq (modes[i]); |
|
635 |
||
636 |
size = w * h; |
|
637 |
||
638 |
if (size > best_size) { |
|
639 |
best_size = size; |
|
640 |
best_width = w; |
|
641 |
best_height = h; |
|
642 |
best_rate = r; |
|
643 |
best_mode = modes[i]; |
|
644 |
} else if (size == best_size) { |
|
645 |
if (r > best_rate) { |
|
646 |
best_rate = r; |
|
647 |
best_mode = modes[i]; |
|
648 |
}
|
|
649 |
}
|
|
650 |
}
|
|
651 |
||
652 |
return best_mode; |
|
653 |
}
|
|
654 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
655 |
static gboolean |
656 |
turn_on (GnomeRRScreen *screen, |
|
657 |
GnomeOutputInfo *info, |
|
658 |
int x, int y) |
|
659 |
{
|
|
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
660 |
GnomeRROutput *output = gnome_rr_screen_get_output_by_name (screen, info->name); |
661 |
GnomeRRMode *mode = find_best_mode (output); |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
662 |
|
663 |
if (mode) { |
|
664 |
info->on = TRUE; |
|
665 |
info->x = x; |
|
666 |
info->y = y; |
|
667 |
info->width = gnome_rr_mode_get_width (mode); |
|
668 |
info->height = gnome_rr_mode_get_height (mode); |
|
669 |
info->rotation = GNOME_RR_ROTATION_0; |
|
670 |
info->rate = gnome_rr_mode_get_freq (mode); |
|
671 |
||
672 |
return TRUE; |
|
673 |
}
|
|
674 |
||
675 |
return FALSE; |
|
676 |
}
|
|
677 |
||
678 |
static GnomeRRConfig * |
|
679 |
make_laptop_setup (GnomeRRScreen *screen) |
|
680 |
{
|
|
681 |
/* Turn on the laptop, disable everything else */
|
|
682 |
GnomeRRConfig *result = gnome_rr_config_new_current (screen); |
|
683 |
int i; |
|
684 |
||
685 |
for (i = 0; result->outputs[i] != NULL; ++i) { |
|
686 |
GnomeOutputInfo *info = result->outputs[i]; |
|
687 |
||
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
688 |
if (is_laptop (screen, info)) { |
1.1.33
by Chris Coulson
Import upstream version 2.29.91.1 |
689 |
if (!turn_on (screen, info, 0, 0)) { |
690 |
gnome_rr_config_free (result); |
|
691 |
result = NULL; |
|
692 |
break; |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
693 |
}
|
694 |
}
|
|
695 |
else { |
|
696 |
info->on = FALSE; |
|
697 |
}
|
|
698 |
}
|
|
699 |
||
700 |
print_configuration (result, "Laptop setup"); |
|
701 |
||
702 |
/* FIXME - Maybe we should return NULL if there is more than
|
|
703 |
* one connected "laptop" screen?
|
|
704 |
*/
|
|
705 |
return result; |
|
706 |
||
707 |
}
|
|
708 |
||
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
709 |
static int |
710 |
turn_on_and_get_rightmost_offset (GnomeRRScreen *screen, GnomeOutputInfo *info, int x) |
|
711 |
{
|
|
1.1.33
by Chris Coulson
Import upstream version 2.29.91.1 |
712 |
if (turn_on (screen, info, x, 0)) |
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
713 |
x += info->width; |
714 |
||
715 |
return x; |
|
716 |
}
|
|
717 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
718 |
static GnomeRRConfig * |
719 |
make_xinerama_setup (GnomeRRScreen *screen) |
|
720 |
{
|
|
721 |
/* Turn on everything that has a preferred mode, and
|
|
722 |
* position it from left to right
|
|
723 |
*/
|
|
724 |
GnomeRRConfig *result = gnome_rr_config_new_current (screen); |
|
725 |
int i; |
|
726 |
int x; |
|
727 |
||
728 |
x = 0; |
|
729 |
for (i = 0; result->outputs[i] != NULL; ++i) { |
|
730 |
GnomeOutputInfo *info = result->outputs[i]; |
|
731 |
||
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
732 |
if (is_laptop (screen, info)) |
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
733 |
x = turn_on_and_get_rightmost_offset (screen, info, x); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
734 |
}
|
735 |
||
736 |
for (i = 0; result->outputs[i] != NULL; ++i) { |
|
737 |
GnomeOutputInfo *info = result->outputs[i]; |
|
738 |
||
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
739 |
if (info->connected && !is_laptop (screen, info)) |
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
740 |
x = turn_on_and_get_rightmost_offset (screen, info, x); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
741 |
}
|
742 |
||
743 |
print_configuration (result, "xinerama setup"); |
|
744 |
||
745 |
return result; |
|
746 |
}
|
|
747 |
||
748 |
static GnomeRRConfig * |
|
749 |
make_other_setup (GnomeRRScreen *screen) |
|
750 |
{
|
|
751 |
/* Turn off all laptops, and make all external monitors clone
|
|
752 |
* from (0, 0)
|
|
753 |
*/
|
|
754 |
||
755 |
GnomeRRConfig *result = gnome_rr_config_new_current (screen); |
|
756 |
int i; |
|
757 |
||
758 |
for (i = 0; result->outputs[i] != NULL; ++i) { |
|
759 |
GnomeOutputInfo *info = result->outputs[i]; |
|
760 |
||
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
761 |
if (is_laptop (screen, info)) { |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
762 |
info->on = FALSE; |
763 |
}
|
|
764 |
else { |
|
1.1.33
by Chris Coulson
Import upstream version 2.29.91.1 |
765 |
if (info->connected) |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
766 |
turn_on (screen, info, 0, 0); |
767 |
}
|
|
768 |
}
|
|
769 |
||
770 |
print_configuration (result, "other setup"); |
|
771 |
||
772 |
return result; |
|
773 |
}
|
|
774 |
||
775 |
static GPtrArray * |
|
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
776 |
sanitize (GsdXrandrManager *manager, GPtrArray *array) |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
777 |
{
|
778 |
int i; |
|
779 |
GPtrArray *new; |
|
780 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
781 |
g_debug ("before sanitizing"); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
782 |
|
783 |
for (i = 0; i < array->len; ++i) { |
|
784 |
if (array->pdata[i]) { |
|
785 |
print_configuration (array->pdata[i], "before"); |
|
786 |
}
|
|
787 |
}
|
|
788 |
||
789 |
||
790 |
/* Remove configurations that are duplicates of
|
|
791 |
* configurations earlier in the cycle
|
|
792 |
*/
|
|
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
793 |
for (i = 0; i < array->len; i++) { |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
794 |
int j; |
795 |
||
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
796 |
for (j = i + 1; j < array->len; j++) { |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
797 |
GnomeRRConfig *this = array->pdata[j]; |
798 |
GnomeRRConfig *other = array->pdata[i]; |
|
799 |
||
800 |
if (this && other && gnome_rr_config_equal (this, other)) { |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
801 |
g_debug ("removing duplicate configuration"); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
802 |
gnome_rr_config_free (this); |
803 |
array->pdata[j] = NULL; |
|
804 |
break; |
|
805 |
}
|
|
806 |
}
|
|
807 |
}
|
|
808 |
||
809 |
for (i = 0; i < array->len; ++i) { |
|
810 |
GnomeRRConfig *config = array->pdata[i]; |
|
811 |
||
812 |
if (config) { |
|
813 |
gboolean all_off = TRUE; |
|
814 |
int j; |
|
815 |
||
816 |
for (j = 0; config->outputs[j] != NULL; ++j) { |
|
817 |
if (config->outputs[j]->on) |
|
818 |
all_off = FALSE; |
|
819 |
}
|
|
820 |
||
821 |
if (all_off) { |
|
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
822 |
g_debug ("removing configuration as all outputs are off"); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
823 |
gnome_rr_config_free (array->pdata[i]); |
824 |
array->pdata[i] = NULL; |
|
825 |
}
|
|
826 |
}
|
|
827 |
}
|
|
828 |
||
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
829 |
/* Do a final sanitization pass. This will remove configurations that
|
830 |
* don't fit in the framebuffer's Virtual size.
|
|
831 |
*/
|
|
832 |
||
833 |
for (i = 0; i < array->len; i++) { |
|
834 |
GnomeRRConfig *config = array->pdata[i]; |
|
835 |
||
836 |
if (config) { |
|
837 |
GError *error; |
|
838 |
||
839 |
error = NULL; |
|
840 |
if (!gnome_rr_config_applicable (config, manager->priv->rw_screen, &error)) { /* NULL-GError */ |
|
841 |
g_debug ("removing configuration which is not applicable because %s", error->message); |
|
842 |
g_error_free (error); |
|
843 |
||
844 |
gnome_rr_config_free (config); |
|
845 |
array->pdata[i] = NULL; |
|
846 |
}
|
|
847 |
}
|
|
848 |
}
|
|
849 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
850 |
/* Remove NULL configurations */
|
851 |
new = g_ptr_array_new (); |
|
852 |
||
853 |
for (i = 0; i < array->len; ++i) { |
|
854 |
if (array->pdata[i]) { |
|
855 |
g_ptr_array_add (new, array->pdata[i]); |
|
856 |
print_configuration (array->pdata[i], "Final"); |
|
857 |
}
|
|
858 |
}
|
|
859 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
860 |
if (new->len > 0) { |
861 |
g_ptr_array_add (new, NULL); |
|
862 |
} else { |
|
863 |
g_ptr_array_free (new, TRUE); |
|
864 |
new = NULL; |
|
865 |
}
|
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
866 |
|
867 |
g_ptr_array_free (array, TRUE); |
|
868 |
||
869 |
return new; |
|
870 |
}
|
|
871 |
||
872 |
static void |
|
873 |
generate_fn_f7_configs (GsdXrandrManager *mgr) |
|
874 |
{
|
|
875 |
GPtrArray *array = g_ptr_array_new (); |
|
876 |
GnomeRRScreen *screen = mgr->priv->rw_screen; |
|
877 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
878 |
g_debug ("Generating configurations"); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
879 |
|
880 |
/* Free any existing list of configurations */
|
|
881 |
if (mgr->priv->fn_f7_configs) { |
|
882 |
int i; |
|
883 |
||
884 |
for (i = 0; mgr->priv->fn_f7_configs[i] != NULL; ++i) |
|
885 |
gnome_rr_config_free (mgr->priv->fn_f7_configs[i]); |
|
886 |
g_free (mgr->priv->fn_f7_configs); |
|
887 |
||
888 |
mgr->priv->fn_f7_configs = NULL; |
|
889 |
mgr->priv->current_fn_f7_config = -1; |
|
890 |
}
|
|
891 |
||
892 |
g_ptr_array_add (array, gnome_rr_config_new_current (screen)); |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
893 |
g_ptr_array_add (array, make_clone_setup (screen)); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
894 |
g_ptr_array_add (array, make_xinerama_setup (screen)); |
895 |
g_ptr_array_add (array, make_laptop_setup (screen)); |
|
896 |
g_ptr_array_add (array, make_other_setup (screen)); |
|
897 |
g_ptr_array_add (array, gnome_rr_config_new_stored (screen, NULL)); /* NULL-GError - if this can't read the stored config, no big deal */ |
|
898 |
||
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
899 |
array = sanitize (mgr, array); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
900 |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
901 |
if (array) { |
902 |
mgr->priv->fn_f7_configs = (GnomeRRConfig **)g_ptr_array_free (array, FALSE); |
|
903 |
mgr->priv->current_fn_f7_config = 0; |
|
904 |
}
|
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
905 |
}
|
906 |
||
907 |
static void |
|
908 |
error_message (GsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text) |
|
909 |
{
|
|
910 |
#ifdef HAVE_LIBNOTIFY
|
|
911 |
GsdXrandrManagerPrivate *priv = mgr->priv; |
|
912 |
NotifyNotification *notification; |
|
913 |
||
914 |
g_assert (error_to_display == NULL || secondary_text == NULL); |
|
915 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
916 |
if (priv->status_icon) |
917 |
notification = notify_notification_new_with_status_icon (primary_text, |
|
918 |
error_to_display ? error_to_display->message : secondary_text, |
|
919 |
GSD_XRANDR_ICON_NAME, |
|
920 |
priv->status_icon); |
|
921 |
else
|
|
922 |
notification = notify_notification_new (primary_text, |
|
923 |
error_to_display ? error_to_display->message : secondary_text, |
|
924 |
GSD_XRANDR_ICON_NAME, |
|
925 |
NULL); |
|
926 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
927 |
notify_notification_show (notification, NULL); /* NULL-GError */ |
928 |
#else
|
|
929 |
GtkWidget *dialog; |
|
930 |
||
931 |
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, |
|
932 |
"%s", primary_text); |
|
933 |
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", |
|
934 |
error_to_display ? error_to_display->message : secondary_text); |
|
935 |
||
936 |
gtk_dialog_run (GTK_DIALOG (dialog)); |
|
937 |
gtk_widget_destroy (dialog); |
|
938 |
#endif /* HAVE_LIBNOTIFY */ |
|
939 |
}
|
|
940 |
||
941 |
static void |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
942 |
handle_fn_f7 (GsdXrandrManager *mgr, guint32 timestamp) |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
943 |
{
|
944 |
GsdXrandrManagerPrivate *priv = mgr->priv; |
|
945 |
GnomeRRScreen *screen = priv->rw_screen; |
|
946 |
GnomeRRConfig *current; |
|
947 |
GError *error; |
|
948 |
||
949 |
/* Theory of fn-F7 operation
|
|
950 |
*
|
|
951 |
* We maintain a datastructure "fn_f7_status", that contains
|
|
952 |
* a list of GnomeRRConfig's. Each of the GnomeRRConfigs has a
|
|
953 |
* mode (or "off") for each connected output.
|
|
954 |
*
|
|
955 |
* When the user hits fn-F7, we cycle to the next GnomeRRConfig
|
|
956 |
* in the data structure. If the data structure does not exist, it
|
|
957 |
* is generated. If the configs in the data structure do not match
|
|
958 |
* the current hardware reality, it is regenerated.
|
|
959 |
*
|
|
960 |
*/
|
|
961 |
g_debug ("Handling fn-f7"); |
|
962 |
||
963 |
error = NULL; |
|
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
964 |
if (!gnome_rr_screen_refresh (screen, &error) && error) { |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
965 |
char *str; |
966 |
||
967 |
str = g_strdup_printf (_("Could not refresh the screen information: %s"), error->message); |
|
968 |
g_error_free (error); |
|
969 |
||
970 |
error_message (mgr, str, NULL, _("Trying to switch the monitor configuration anyway.")); |
|
971 |
g_free (str); |
|
972 |
}
|
|
973 |
||
974 |
if (!priv->fn_f7_configs) |
|
975 |
generate_fn_f7_configs (mgr); |
|
976 |
||
977 |
current = gnome_rr_config_new_current (screen); |
|
978 |
||
979 |
if (priv->fn_f7_configs && |
|
980 |
(!gnome_rr_config_match (current, priv->fn_f7_configs[0]) || |
|
981 |
!gnome_rr_config_equal (current, priv->fn_f7_configs[mgr->priv->current_fn_f7_config]))) { |
|
982 |
/* Our view of the world is incorrect, so regenerate the
|
|
983 |
* configurations
|
|
984 |
*/
|
|
985 |
generate_fn_f7_configs (mgr); |
|
986 |
}
|
|
987 |
||
988 |
gnome_rr_config_free (current); |
|
989 |
||
990 |
if (priv->fn_f7_configs) { |
|
991 |
mgr->priv->current_fn_f7_config++; |
|
992 |
||
993 |
if (priv->fn_f7_configs[mgr->priv->current_fn_f7_config] == NULL) |
|
994 |
mgr->priv->current_fn_f7_config = 0; |
|
995 |
||
996 |
g_debug ("cycling to next configuration (%d)", mgr->priv->current_fn_f7_config); |
|
997 |
||
998 |
print_configuration (priv->fn_f7_configs[mgr->priv->current_fn_f7_config], "new config"); |
|
999 |
||
1000 |
g_debug ("applying"); |
|
1001 |
||
1.1.32
by Chris Coulson
Import upstream version 2.29.90 |
1002 |
apply_configuration_and_display_error (mgr, priv->fn_f7_configs[mgr->priv->current_fn_f7_config], timestamp); |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
1003 |
}
|
1004 |
else { |
|
1005 |
g_debug ("no configurations generated"); |
|
1006 |
}
|
|
1007 |
g_debug ("done handling fn-f7"); |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1008 |
}
|
1009 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1010 |
static GnomeOutputInfo * |
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
1011 |
get_laptop_output_info (GnomeRRScreen *screen, GnomeRRConfig *config) |
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1012 |
{
|
1013 |
int i; |
|
1014 |
||
1015 |
for (i = 0; config->outputs[i] != NULL; i++) { |
|
1016 |
GnomeOutputInfo *info; |
|
1017 |
||
1018 |
info = config->outputs[i]; |
|
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
1019 |
if (is_laptop (screen, info)) |
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1020 |
return info; |
1021 |
}
|
|
1022 |
||
1023 |
return NULL; |
|
1024 |
||
1025 |
}
|
|
1026 |
||
1027 |
static GnomeRRRotation |
|
1028 |
get_next_rotation (GnomeRRRotation allowed_rotations, GnomeRRRotation current_rotation) |
|
1029 |
{
|
|
1030 |
int i; |
|
1031 |
int current_index; |
|
1032 |
||
1033 |
/* First, find the index of the current rotation */
|
|
1034 |
||
1035 |
current_index = -1; |
|
1036 |
||
1037 |
for (i = 0; i < G_N_ELEMENTS (possible_rotations); i++) { |
|
1038 |
GnomeRRRotation r; |
|
1039 |
||
1040 |
r = possible_rotations[i]; |
|
1041 |
if (r == current_rotation) { |
|
1042 |
current_index = i; |
|
1043 |
break; |
|
1044 |
}
|
|
1045 |
}
|
|
1046 |
||
1047 |
if (current_index == -1) { |
|
1048 |
/* Huh, the current_rotation was not one of the supported rotations. Bail out. */
|
|
1049 |
return current_rotation; |
|
1050 |
}
|
|
1051 |
||
1052 |
/* Then, find the next rotation that is allowed */
|
|
1053 |
||
1054 |
i = (current_index + 1) % G_N_ELEMENTS (possible_rotations); |
|
1055 |
||
1056 |
while (1) { |
|
1057 |
GnomeRRRotation r; |
|
1058 |
||
1059 |
r = possible_rotations[i]; |
|
1060 |
if (r == current_rotation) { |
|
1061 |
/* We wrapped around and no other rotation is suported. Bummer. */
|
|
1062 |
return current_rotation; |
|
1063 |
} else if (r & allowed_rotations) |
|
1064 |
return r; |
|
1065 |
||
1066 |
i = (i + 1) % G_N_ELEMENTS (possible_rotations); |
|
1067 |
}
|
|
1068 |
}
|
|
1069 |
||
1070 |
/* We use this when the XF86RotateWindows key is pressed. That key is present
|
|
1071 |
* on some tablet PCs; they use it so that the user can rotate the tablet
|
|
1072 |
* easily.
|
|
1073 |
*/
|
|
1074 |
static void |
|
1075 |
handle_rotate_windows (GsdXrandrManager *mgr, guint32 timestamp) |
|
1076 |
{
|
|
1077 |
GsdXrandrManagerPrivate *priv = mgr->priv; |
|
1078 |
GnomeRRScreen *screen = priv->rw_screen; |
|
1079 |
GnomeRRConfig *current; |
|
1080 |
GnomeOutputInfo *rotatable_output_info; |
|
1081 |
int num_allowed_rotations; |
|
1082 |
GnomeRRRotation allowed_rotations; |
|
1083 |
GnomeRRRotation next_rotation; |
|
1084 |
||
1085 |
g_debug ("Handling XF86RotateWindows"); |
|
1086 |
||
1087 |
/* Which output? */
|
|
1088 |
||
1089 |
current = gnome_rr_config_new_current (screen); |
|
1090 |
||
1.1.34
by Sebastien Bacher
Import upstream version 2.29.92 |
1091 |
rotatable_output_info = get_laptop_output_info (screen, current); |
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1092 |
if (rotatable_output_info == NULL) { |
1093 |
g_debug ("No laptop outputs found to rotate; XF86RotateWindows key will do nothing"); |
|
1094 |
goto out; |
|
1095 |
}
|
|
1096 |
||
1097 |
/* Which rotation? */
|
|
1098 |
||
1099 |
get_allowed_rotations_for_output (current, priv->rw_screen, rotatable_output_info, &num_allowed_rotations, &allowed_rotations); |
|
1100 |
next_rotation = get_next_rotation (allowed_rotations, rotatable_output_info->rotation); |
|
1101 |
||
1102 |
if (next_rotation == rotatable_output_info->rotation) { |
|
1103 |
g_debug ("No rotations are supported other than the current one; XF86RotateWindows key will do nothing"); |
|
1104 |
goto out; |
|
1105 |
}
|
|
1106 |
||
1107 |
/* Rotate */
|
|
1108 |
||
1109 |
rotatable_output_info->rotation = next_rotation; |
|
1110 |
||
1.1.32
by Chris Coulson
Import upstream version 2.29.90 |
1111 |
apply_configuration_and_display_error (mgr, current, timestamp); |
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1112 |
|
1113 |
out: |
|
1114 |
gnome_rr_config_free (current); |
|
1115 |
}
|
|
1116 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1117 |
static GdkFilterReturn |
1118 |
event_filter (GdkXEvent *xevent, |
|
1119 |
GdkEvent *event, |
|
1120 |
gpointer data) |
|
1121 |
{
|
|
1122 |
GsdXrandrManager *manager = data; |
|
1123 |
XEvent *xev = (XEvent *) xevent; |
|
1124 |
||
1125 |
if (!manager->priv->running) |
|
1126 |
return GDK_FILTER_CONTINUE; |
|
1127 |
||
1128 |
/* verify we have a key event */
|
|
1129 |
if (xev->xany.type != KeyPress && xev->xany.type != KeyRelease) |
|
1130 |
return GDK_FILTER_CONTINUE; |
|
1131 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1132 |
if (xev->xany.type == KeyPress) { |
1133 |
if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode) |
|
1134 |
handle_fn_f7 (manager, xev->xkey.time); |
|
1135 |
else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode) |
|
1136 |
handle_rotate_windows (manager, xev->xkey.time); |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1137 |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1138 |
return GDK_FILTER_CONTINUE; |
1139 |
}
|
|
1140 |
||
1141 |
return GDK_FILTER_CONTINUE; |
|
1142 |
}
|
|
1143 |
||
1144 |
static void |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1145 |
refresh_tray_icon_menu_if_active (GsdXrandrManager *manager, guint32 timestamp) |
1146 |
{
|
|
1147 |
GsdXrandrManagerPrivate *priv = manager->priv; |
|
1148 |
||
1149 |
if (priv->popup_menu) { |
|
1150 |
gtk_menu_shell_cancel (GTK_MENU_SHELL (priv->popup_menu)); /* status_icon_popup_menu_selection_done_cb() will free everything */ |
|
1151 |
status_icon_popup_menu (manager, 0, timestamp); |
|
1152 |
}
|
|
1153 |
}
|
|
1154 |
||
1155 |
static void |
|
1156 |
auto_configure_outputs (GsdXrandrManager *manager, guint32 timestamp) |
|
1157 |
{
|
|
1158 |
GsdXrandrManagerPrivate *priv = manager->priv; |
|
1159 |
GnomeRRConfig *config; |
|
1160 |
int i; |
|
1161 |
GList *just_turned_on; |
|
1162 |
GList *l; |
|
1163 |
int x; |
|
1164 |
GError *error; |
|
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
1165 |
gboolean applicable; |
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1166 |
|
1167 |
config = gnome_rr_config_new_current (priv->rw_screen); |
|
1168 |
||
1169 |
/* For outputs that are connected and on (i.e. they have a CRTC assigned
|
|
1170 |
* to them, so they are getting a signal), we leave them as they are
|
|
1171 |
* with their current modes.
|
|
1172 |
*
|
|
1173 |
* For other outputs, we will turn on connected-but-off outputs and turn
|
|
1174 |
* off disconnected-but-on outputs.
|
|
1175 |
*
|
|
1176 |
* FIXME: If an output remained connected+on, it would be nice to ensure
|
|
1177 |
* that the output's CRTCs still has a reasonable mode (think of
|
|
1178 |
* changing one monitor for another with different capabilities).
|
|
1179 |
*/
|
|
1180 |
||
1181 |
just_turned_on = NULL; |
|
1182 |
||
1183 |
for (i = 0; config->outputs[i] != NULL; i++) { |
|
1184 |
GnomeOutputInfo *output = config->outputs[i]; |
|
1185 |
||
1186 |
if (output->connected && !output->on) { |
|
1187 |
output->on = TRUE; |
|
1188 |
output->rotation = GNOME_RR_ROTATION_0; |
|
1189 |
just_turned_on = g_list_prepend (just_turned_on, GINT_TO_POINTER (i)); |
|
1190 |
} else if (!output->connected && output->on) |
|
1191 |
output->on = FALSE; |
|
1192 |
}
|
|
1193 |
||
1194 |
/* Now, lay out the outputs from left to right. Put first the outputs
|
|
1195 |
* which remained on; put last the outputs that were newly turned on.
|
|
1196 |
*/
|
|
1197 |
||
1198 |
x = 0; |
|
1199 |
||
1200 |
/* First, outputs that remained on */
|
|
1201 |
||
1202 |
for (i = 0; config->outputs[i] != NULL; i++) { |
|
1203 |
GnomeOutputInfo *output = config->outputs[i]; |
|
1204 |
||
1205 |
if (g_list_find (just_turned_on, GINT_TO_POINTER (i))) |
|
1206 |
continue; |
|
1207 |
||
1208 |
if (output->on) { |
|
1209 |
g_assert (output->connected); |
|
1210 |
||
1211 |
output->x = x; |
|
1212 |
output->y = 0; |
|
1213 |
||
1214 |
x += output->width; |
|
1215 |
}
|
|
1216 |
}
|
|
1217 |
||
1218 |
/* Second, outputs that were newly-turned on */
|
|
1219 |
||
1220 |
for (l = just_turned_on; l; l = l->next) { |
|
1221 |
GnomeOutputInfo *output; |
|
1222 |
||
1223 |
i = GPOINTER_TO_INT (l->data); |
|
1224 |
output = config->outputs[i]; |
|
1225 |
||
1226 |
g_assert (output->on && output->connected); |
|
1227 |
||
1228 |
output->x = x; |
|
1229 |
output->y = 0; |
|
1230 |
||
1231 |
/* since the output was off, use its preferred width/height (it doesn't have a real width/height yet) */
|
|
1232 |
output->width = output->pref_width; |
|
1233 |
output->height = output->pref_height; |
|
1234 |
||
1235 |
x += output->width; |
|
1236 |
}
|
|
1237 |
||
1.1.24
by Chris Coulson
Import upstream version 2.27.5 |
1238 |
/* Check if we have a large enough framebuffer size. If not, turn off
|
1239 |
* outputs from right to left until we reach a usable size.
|
|
1240 |
*/
|
|
1241 |
||
1242 |
just_turned_on = g_list_reverse (just_turned_on); /* now the outputs here are from right to left */ |
|
1243 |
||
1244 |
l = just_turned_on; |
|
1245 |
while (1) { |
|
1246 |
GnomeOutputInfo *output; |
|
1247 |
gboolean is_bounds_error; |
|
1248 |
||
1249 |
error = NULL; |
|
1250 |
applicable = gnome_rr_config_applicable (config, priv->rw_screen, &error); |
|
1251 |
||
1252 |
if (applicable) |
|
1253 |
break; |
|
1254 |
||
1255 |
is_bounds_error = g_error_matches (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR); |
|
1256 |
g_error_free (error); |
|
1257 |
||
1258 |
if (!is_bounds_error) |
|
1259 |
break; |
|
1260 |
||
1261 |
if (l) { |
|
1262 |
i = GPOINTER_TO_INT (l->data); |
|
1263 |
l = l->next; |
|
1264 |
||
1265 |
output = config->outputs[i]; |
|
1266 |
output->on = FALSE; |
|
1267 |
} else |
|
1268 |
break; |
|
1269 |
}
|
|
1270 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1271 |
/* Apply the configuration! */
|
1272 |
||
1.1.32
by Chris Coulson
Import upstream version 2.29.90 |
1273 |
if (applicable) |
1274 |
apply_configuration_and_display_error (manager, config, timestamp); |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1275 |
|
1276 |
g_list_free (just_turned_on); |
|
1277 |
gnome_rr_config_free (config); |
|
1278 |
||
1279 |
/* Finally, even though we did a best-effort job in sanitizing the
|
|
1280 |
* outputs, we don't know the physical layout of the monitors. We'll
|
|
1281 |
* start the display capplet so that the user can tweak things to his
|
|
1282 |
* liking.
|
|
1283 |
*/
|
|
1284 |
||
1285 |
#if 0
|
|
1286 |
/* FIXME: This is disabled for now. The capplet is not a single-instance application.
|
|
1287 |
* If you do this:
|
|
1288 |
*
|
|
1289 |
* 1. Start the display capplet
|
|
1290 |
*
|
|
1291 |
* 2. Plug an extra monitor
|
|
1292 |
*
|
|
1293 |
* 3. Hit the "Detect displays" button
|
|
1294 |
*
|
|
1295 |
* Then we will get a RANDR event because X re-probes the outputs. We don't want to
|
|
1296 |
* start up a second display capplet right there!
|
|
1297 |
*/
|
|
1298 |
||
1299 |
run_display_capplet (NULL);
|
|
1300 |
#endif
|
|
1301 |
}
|
|
1302 |
||
1303 |
static void |
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1304 |
apply_color_profiles (void) |
1305 |
{
|
|
1306 |
gboolean ret; |
|
1307 |
GError *error = NULL; |
|
1308 |
||
1309 |
/* run the gnome-color-manager apply program */
|
|
1310 |
ret = g_spawn_command_line_async (BINDIR "/gcm-apply", &error); |
|
1311 |
if (!ret) { |
|
1312 |
/* only print the warning if the binary is installed */
|
|
1313 |
if (error->code != G_SPAWN_ERROR_NOENT) { |
|
1314 |
g_warning ("failed to apply color profiles: %s", error->message); |
|
1315 |
}
|
|
1316 |
g_error_free (error); |
|
1317 |
}
|
|
1318 |
}
|
|
1319 |
||
1320 |
static void |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1321 |
on_randr_event (GnomeRRScreen *screen, gpointer data) |
1322 |
{
|
|
1323 |
GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data); |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1324 |
GsdXrandrManagerPrivate *priv = manager->priv; |
1325 |
guint32 change_timestamp, config_timestamp; |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1326 |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1327 |
if (!priv->running) |
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1328 |
return; |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1329 |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1330 |
gnome_rr_screen_get_timestamps (screen, &change_timestamp, &config_timestamp); |
1331 |
||
1332 |
if (change_timestamp >= config_timestamp) { |
|
1333 |
/* The event is due to an explicit configuration change.
|
|
1334 |
*
|
|
1335 |
* If the change was performed by us, then we need to do nothing.
|
|
1336 |
*
|
|
1337 |
* If the change was done by some other X client, we don't need
|
|
1338 |
* to do anything, either; the screen is already configured.
|
|
1339 |
*/
|
|
1340 |
show_timestamps_dialog (manager, "ignoring since change > config"); |
|
1341 |
} else { |
|
1342 |
/* Here, config_timestamp > change_timestamp. This means that
|
|
1343 |
* the screen got reconfigured because of hotplug/unplug; the X
|
|
1344 |
* server is just notifying us, and we need to configure the
|
|
1345 |
* outputs in a sane way.
|
|
1346 |
*/
|
|
1347 |
||
1348 |
||
1349 |
#if 1
|
|
1350 |
if (config_timestamp != priv->last_config_timestamp) { |
|
1351 |
priv->last_config_timestamp = config_timestamp; |
|
1352 |
auto_configure_outputs (manager, config_timestamp); |
|
1353 |
}
|
|
1354 |
#else
|
|
1355 |
/* WHY THIS CODE IS DISABLED:
|
|
1356 |
*
|
|
1357 |
* The strategy of "on hotplug or unsuspend, restore a
|
|
1358 |
* known-good configuration, and fall back to autoconfiguration"
|
|
1359 |
* works fine as long as you don't happen to be running
|
|
1360 |
* gnome-display-properties and click its "Detect displays"
|
|
1361 |
* button.
|
|
1362 |
*
|
|
1363 |
* If you do that, the RANDR calls from g-d-p will cause the X
|
|
1364 |
* server to re-probe the RANDR outputs. The server will send
|
|
1365 |
* us an event, we'll restore the configuration to something
|
|
1366 |
* else... and you'll be weirded out, because "just detecting
|
|
1367 |
* your monitors" should not change the current configuration,
|
|
1368 |
* right?
|
|
1369 |
*
|
|
1370 |
* We may need some kind of D-bus API so that g-d-p can inhibit
|
|
1371 |
* this RANDR plugin's reconfiguration-fu when the "Detect
|
|
1372 |
* displays" button is being used.
|
|
1373 |
*/
|
|
1374 |
||
1375 |
char *intended_filename; |
|
1376 |
GError *error; |
|
1377 |
gboolean success; |
|
1378 |
||
1379 |
show_timestamps_dialog (manager, "need to deal with reconfiguration, as config >= change"); |
|
1380 |
||
1381 |
intended_filename = gnome_rr_config_get_intended_filename (); |
|
1382 |
||
1383 |
error = NULL; |
|
1384 |
success = apply_configuration_from_filename (manager, intended_filename, TRUE, config_timestamp, &error); |
|
1385 |
g_free (intended_filename); |
|
1386 |
||
1387 |
if (!success) { |
|
1388 |
/* We don't bother checking the error type.
|
|
1389 |
*
|
|
1390 |
* Both G_FILE_ERROR_NOENT and
|
|
1391 |
* GNOME_RR_ERROR_NO_MATCHING_CONFIG would mean, "there
|
|
1392 |
* was no configuration to apply, or none that matched
|
|
1393 |
* the current outputs", and in that case we need to run
|
|
1394 |
* our fallback.
|
|
1395 |
*
|
|
1396 |
* Any other error means "we couldn't do the smart thing
|
|
1397 |
* of using a previously- saved configuration, anyway,
|
|
1398 |
* for some other reason. In that case, we also need to
|
|
1399 |
* run our fallback to avoid leaving the user with a
|
|
1400 |
* bogus configuration.
|
|
1401 |
*/
|
|
1402 |
||
1403 |
if (error) |
|
1404 |
g_error_free (error); |
|
1405 |
||
1406 |
auto_configure_outputs (manager, config_timestamp); |
|
1407 |
}
|
|
1408 |
#endif
|
|
1409 |
}
|
|
1410 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1411 |
/* poke gnome-color-manager */
|
1412 |
apply_color_profiles (); |
|
1413 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1414 |
refresh_tray_icon_menu_if_active (manager, MAX (change_timestamp, config_timestamp)); |
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1415 |
}
|
1416 |
||
1417 |
static void |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1418 |
run_display_capplet (GtkWidget *widget) |
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1419 |
{
|
1420 |
GdkScreen *screen; |
|
1421 |
GError *error; |
|
1422 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1423 |
if (widget) |
1424 |
screen = gtk_widget_get_screen (widget); |
|
1425 |
else
|
|
1426 |
screen = gdk_screen_get_default (); |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1427 |
|
1428 |
error = NULL; |
|
1429 |
if (!gdk_spawn_command_line_on_screen (screen, GSD_XRANDR_DISPLAY_CAPPLET, &error)) { |
|
1430 |
GtkWidget *dialog; |
|
1431 |
||
1432 |
dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, |
|
1433 |
"<span weight=\"bold\" size=\"larger\">" |
|
1434 |
"Display configuration could not be run"
|
|
1435 |
"</span>\n\n" |
|
1436 |
"%s", error->message); |
|
1437 |
gtk_dialog_run (GTK_DIALOG (dialog)); |
|
1438 |
gtk_widget_destroy (dialog); |
|
1439 |
||
1440 |
g_error_free (error); |
|
1441 |
}
|
|
1442 |
}
|
|
1443 |
||
1444 |
static void |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1445 |
popup_menu_configure_display_cb (GtkMenuItem *item, gpointer data) |
1446 |
{
|
|
1447 |
run_display_capplet (GTK_WIDGET (item)); |
|
1448 |
}
|
|
1449 |
||
1450 |
static void |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1451 |
status_icon_popup_menu_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) |
1452 |
{
|
|
1453 |
GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data); |
|
1454 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1455 |
||
1456 |
gtk_widget_destroy (priv->popup_menu); |
|
1457 |
priv->popup_menu = NULL; |
|
1458 |
||
1459 |
gnome_rr_labeler_hide (priv->labeler); |
|
1460 |
g_object_unref (priv->labeler); |
|
1461 |
priv->labeler = NULL; |
|
1462 |
||
1463 |
gnome_rr_config_free (priv->configuration); |
|
1464 |
priv->configuration = NULL; |
|
1465 |
}
|
|
1466 |
||
1467 |
#define OUTPUT_TITLE_ITEM_BORDER 2
|
|
1468 |
#define OUTPUT_TITLE_ITEM_PADDING 4
|
|
1469 |
||
1470 |
/* This is an expose-event hander for the title label for each GnomeRROutput.
|
|
1471 |
* We want each title to have a colored background, so we paint that background, then
|
|
1472 |
* return FALSE to let GtkLabel expose itself (i.e. paint the label's text), and then
|
|
1473 |
* we have a signal_connect_after handler as well. See the comments below
|
|
1474 |
* to see why that "after" handler is needed.
|
|
1475 |
*/
|
|
1476 |
static gboolean |
|
1477 |
output_title_label_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) |
|
1478 |
{
|
|
1479 |
GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data); |
|
1480 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1481 |
GnomeOutputInfo *output; |
|
1482 |
GdkColor color; |
|
1483 |
cairo_t *cr; |
|
1484 |
||
1485 |
g_assert (GTK_IS_LABEL (widget)); |
|
1486 |
||
1487 |
output = g_object_get_data (G_OBJECT (widget), "output"); |
|
1488 |
g_assert (output != NULL); |
|
1489 |
||
1490 |
g_assert (priv->labeler != NULL); |
|
1491 |
||
1492 |
/* Draw a black rectangular border, filled with the color that corresponds to this output */
|
|
1493 |
||
1494 |
gnome_rr_labeler_get_color_for_output (priv->labeler, output, &color); |
|
1495 |
||
1496 |
cr = gdk_cairo_create (widget->window); |
|
1497 |
||
1498 |
cairo_set_source_rgb (cr, 0, 0, 0); |
|
1499 |
cairo_set_line_width (cr, OUTPUT_TITLE_ITEM_BORDER); |
|
1500 |
cairo_rectangle (cr, |
|
1501 |
widget->allocation.x + OUTPUT_TITLE_ITEM_BORDER / 2.0, |
|
1502 |
widget->allocation.y + OUTPUT_TITLE_ITEM_BORDER / 2.0, |
|
1503 |
widget->allocation.width - OUTPUT_TITLE_ITEM_BORDER, |
|
1504 |
widget->allocation.height - OUTPUT_TITLE_ITEM_BORDER); |
|
1505 |
cairo_stroke (cr); |
|
1506 |
||
1507 |
gdk_cairo_set_source_color (cr, &color); |
|
1508 |
cairo_rectangle (cr, |
|
1509 |
widget->allocation.x + OUTPUT_TITLE_ITEM_BORDER, |
|
1510 |
widget->allocation.y + OUTPUT_TITLE_ITEM_BORDER, |
|
1511 |
widget->allocation.width - 2 * OUTPUT_TITLE_ITEM_BORDER, |
|
1512 |
widget->allocation.height - 2 * OUTPUT_TITLE_ITEM_BORDER); |
|
1513 |
||
1514 |
cairo_fill (cr); |
|
1515 |
||
1516 |
/* We want the label to always show up as if it were sensitive
|
|
1517 |
* ("style->fg[GTK_STATE_NORMAL]"), even though the label is insensitive
|
|
1518 |
* due to being inside an insensitive menu item. So, here we have a
|
|
1519 |
* HACK in which we frob the label's state directly. GtkLabel's expose
|
|
1520 |
* handler will be run after this function, so it will think that the
|
|
1521 |
* label is in GTK_STATE_NORMAL. We reset the label's state back to
|
|
1522 |
* insensitive in output_title_label_after_expose_event_cb().
|
|
1523 |
*
|
|
1524 |
* Yay for fucking with GTK+'s internals.
|
|
1525 |
*/
|
|
1526 |
||
1527 |
widget->state = GTK_STATE_NORMAL; |
|
1528 |
||
1.1.15
by Sebastien Bacher
Import upstream version 2.25.2 |
1529 |
return FALSE; |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1530 |
}
|
1531 |
||
1532 |
/* See the comment in output_title_event_box_expose_event_cb() about this funny label widget */
|
|
1533 |
static gboolean |
|
1534 |
output_title_label_after_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer data) |
|
1535 |
{
|
|
1536 |
g_assert (GTK_IS_LABEL (widget)); |
|
1537 |
widget->state = GTK_STATE_INSENSITIVE; |
|
1538 |
||
1539 |
return FALSE; |
|
1540 |
}
|
|
1541 |
||
1542 |
static void |
|
1543 |
title_item_size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer data) |
|
1544 |
{
|
|
1545 |
/* When GtkMenu does size_request on its items, it asks them for their "toggle size",
|
|
1546 |
* which will be non-zero when there are check/radio items. GtkMenu remembers
|
|
1547 |
* the largest of those sizes. During the size_allocate pass, GtkMenu calls
|
|
1548 |
* gtk_menu_item_toggle_size_allocate() with that value, to tell the menu item
|
|
1549 |
* that it should later paint its child a bit to the right of its edge.
|
|
1550 |
*
|
|
1551 |
* However, we want the "title" menu items for each RANDR output to span the *whole*
|
|
1552 |
* allocation of the menu item, not just the "allocation minus toggle" area.
|
|
1553 |
*
|
|
1554 |
* So, we let the menu item size_allocate itself as usual, but this
|
|
1555 |
* callback gets run afterward. Here we hack a toggle size of 0 into
|
|
1556 |
* the menu item, and size_allocate it by hand *again*. We also need to
|
|
1557 |
* avoid recursing into this function.
|
|
1558 |
*/
|
|
1559 |
||
1560 |
g_assert (GTK_IS_MENU_ITEM (widget)); |
|
1561 |
||
1562 |
gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (widget), 0); |
|
1563 |
||
1564 |
g_signal_handlers_block_by_func (widget, title_item_size_allocate_cb, NULL); |
|
1565 |
||
1566 |
/* Sigh. There is no way to turn on GTK_ALLOC_NEEDED outside of GTK+
|
|
1567 |
* itself; also, since calling size_allocate on a widget with the same
|
|
1568 |
* allcation is a no-op, we need to allocate with a "different" size
|
|
1569 |
* first.
|
|
1570 |
*/
|
|
1571 |
||
1572 |
allocation->width++; |
|
1573 |
gtk_widget_size_allocate (widget, allocation); |
|
1574 |
||
1575 |
allocation->width--; |
|
1576 |
gtk_widget_size_allocate (widget, allocation); |
|
1577 |
||
1578 |
g_signal_handlers_unblock_by_func (widget, title_item_size_allocate_cb, NULL); |
|
1579 |
}
|
|
1580 |
||
1581 |
static GtkWidget * |
|
1582 |
make_menu_item_for_output_title (GsdXrandrManager *manager, GnomeOutputInfo *output) |
|
1583 |
{
|
|
1584 |
GtkWidget *item; |
|
1585 |
GtkWidget *label; |
|
1586 |
char *str; |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1587 |
GdkColor black = { 0, 0, 0, 0 }; |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1588 |
|
1589 |
item = gtk_menu_item_new (); |
|
1590 |
||
1591 |
g_signal_connect (item, "size-allocate", |
|
1592 |
G_CALLBACK (title_item_size_allocate_cb), NULL); |
|
1593 |
||
1594 |
str = g_markup_printf_escaped ("<b>%s</b>", output->display_name); |
|
1595 |
label = gtk_label_new (NULL); |
|
1596 |
gtk_label_set_markup (GTK_LABEL (label), str); |
|
1597 |
g_free (str); |
|
1598 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1599 |
/* Make the label explicitly black. We don't want it to follow the
|
1600 |
* theme's colors, since the label is always shown against a light
|
|
1601 |
* pastel background. See bgo#556050
|
|
1602 |
*/
|
|
1603 |
gtk_widget_modify_fg (label, GTK_WIDGET_STATE (label), &black); |
|
1604 |
||
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1605 |
/* Add padding around the label to fit the box that we'll draw for color-coding */
|
1606 |
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
|
1607 |
gtk_misc_set_padding (GTK_MISC (label), |
|
1608 |
OUTPUT_TITLE_ITEM_BORDER + OUTPUT_TITLE_ITEM_PADDING, |
|
1609 |
OUTPUT_TITLE_ITEM_BORDER + OUTPUT_TITLE_ITEM_PADDING); |
|
1610 |
||
1611 |
gtk_container_add (GTK_CONTAINER (item), label); |
|
1612 |
||
1613 |
/* We want to paint a colored box as the background of the label, so we connect
|
|
1614 |
* to its expose-event signal. See the comment in *** to see why need to connect
|
|
1615 |
* to the label both 'before' and 'after'.
|
|
1616 |
*/
|
|
1617 |
g_signal_connect (label, "expose-event", |
|
1618 |
G_CALLBACK (output_title_label_expose_event_cb), manager); |
|
1619 |
g_signal_connect_after (label, "expose-event", |
|
1620 |
G_CALLBACK (output_title_label_after_expose_event_cb), manager); |
|
1621 |
||
1622 |
g_object_set_data (G_OBJECT (label), "output", output); |
|
1623 |
||
1624 |
gtk_widget_set_sensitive (item, FALSE); /* the title is not selectable */ |
|
1625 |
gtk_widget_show_all (item); |
|
1626 |
||
1627 |
return item; |
|
1628 |
}
|
|
1629 |
||
1630 |
static void |
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1631 |
get_allowed_rotations_for_output (GnomeRRConfig *config, |
1632 |
GnomeRRScreen *rr_screen, |
|
1633 |
GnomeOutputInfo *output, |
|
1634 |
int *out_num_rotations, |
|
1635 |
GnomeRRRotation *out_rotations) |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1636 |
{
|
1637 |
GnomeRRRotation current_rotation; |
|
1638 |
int i; |
|
1639 |
||
1640 |
*out_num_rotations = 0; |
|
1641 |
*out_rotations = 0; |
|
1642 |
||
1643 |
current_rotation = output->rotation; |
|
1644 |
||
1645 |
/* Yay for brute force */
|
|
1646 |
||
1647 |
for (i = 0; i < G_N_ELEMENTS (possible_rotations); i++) { |
|
1648 |
GnomeRRRotation rotation_to_test; |
|
1649 |
||
1650 |
rotation_to_test = possible_rotations[i]; |
|
1651 |
||
1652 |
output->rotation = rotation_to_test; |
|
1653 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1654 |
if (gnome_rr_config_applicable (config, rr_screen, NULL)) { /* NULL-GError */ |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1655 |
(*out_num_rotations)++; |
1656 |
(*out_rotations) |= rotation_to_test; |
|
1657 |
}
|
|
1658 |
}
|
|
1659 |
||
1660 |
output->rotation = current_rotation; |
|
1661 |
||
1662 |
if (*out_num_rotations == 0 || *out_rotations == 0) { |
|
1663 |
g_warning ("Huh, output %p says it doesn't support any rotations, and yet it has a current rotation?", output); |
|
1664 |
*out_num_rotations = 1; |
|
1665 |
*out_rotations = output->rotation; |
|
1666 |
}
|
|
1667 |
}
|
|
1668 |
||
1669 |
static void |
|
1670 |
add_unsupported_rotation_item (GsdXrandrManager *manager) |
|
1671 |
{
|
|
1672 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1673 |
GtkWidget *item; |
|
1674 |
GtkWidget *label; |
|
1675 |
||
1676 |
item = gtk_menu_item_new (); |
|
1677 |
||
1678 |
label = gtk_label_new (NULL); |
|
1679 |
gtk_label_set_markup (GTK_LABEL (label), _("<i>Rotation not supported</i>")); |
|
1680 |
gtk_container_add (GTK_CONTAINER (item), label); |
|
1681 |
||
1682 |
gtk_widget_show_all (item); |
|
1683 |
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item); |
|
1684 |
}
|
|
1685 |
||
1686 |
static void |
|
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
1687 |
ensure_current_configuration_is_saved (void) |
1688 |
{
|
|
1689 |
GnomeRRScreen *rr_screen; |
|
1690 |
GnomeRRConfig *rr_config; |
|
1691 |
||
1692 |
/* Normally, gnome_rr_config_save() creates a backup file based on the
|
|
1693 |
* old monitors.xml. However, if *that* file didn't exist, there is
|
|
1694 |
* nothing from which to create a backup. So, here we'll save the
|
|
1695 |
* current/unchanged configuration and then let our caller call
|
|
1696 |
* gnome_rr_config_save() again with the new/changed configuration, so
|
|
1697 |
* that there *will* be a backup file in the end.
|
|
1698 |
*/
|
|
1699 |
||
1700 |
rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), NULL, NULL, NULL); /* NULL-GError */ |
|
1701 |
if (!rr_screen) |
|
1702 |
return; |
|
1703 |
||
1704 |
rr_config = gnome_rr_config_new_current (rr_screen); |
|
1705 |
gnome_rr_config_save (rr_config, NULL); /* NULL-GError */ |
|
1706 |
||
1707 |
gnome_rr_config_free (rr_config); |
|
1708 |
gnome_rr_screen_destroy (rr_screen); |
|
1709 |
}
|
|
1710 |
||
1711 |
static void |
|
1.1.15
by Sebastien Bacher
Import upstream version 2.25.2 |
1712 |
output_rotation_item_activate_cb (GtkCheckMenuItem *item, gpointer data) |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1713 |
{
|
1714 |
GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data); |
|
1715 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1716 |
GnomeOutputInfo *output; |
|
1717 |
GnomeRRRotation rotation; |
|
1718 |
GError *error; |
|
1719 |
||
1.1.15
by Sebastien Bacher
Import upstream version 2.25.2 |
1720 |
/* Not interested in deselected items */
|
1721 |
if (!gtk_check_menu_item_get_active (item)) |
|
1722 |
return; |
|
1723 |
||
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
1724 |
ensure_current_configuration_is_saved (); |
1725 |
||
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1726 |
output = g_object_get_data (G_OBJECT (item), "output"); |
1727 |
rotation = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "rotation")); |
|
1728 |
||
1729 |
output->rotation = rotation; |
|
1730 |
||
1731 |
error = NULL; |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
1732 |
if (!gnome_rr_config_save (priv->configuration, &error)) { |
1733 |
error_message (manager, _("Could not save monitor configuration"), error, NULL); |
|
1734 |
if (error) |
|
1735 |
g_error_free (error); |
|
1736 |
||
1737 |
return; |
|
0.2.1
by Josselin Mouette
Import upstream version 2.24.1 |
1738 |
}
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
1739 |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1740 |
try_to_apply_intended_configuration (manager, NULL, gtk_get_current_event_time (), NULL); /* NULL-GError */ |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1741 |
}
|
1742 |
||
1743 |
static void |
|
1744 |
add_items_for_rotations (GsdXrandrManager *manager, GnomeOutputInfo *output, GnomeRRRotation allowed_rotations) |
|
1745 |
{
|
|
1746 |
typedef struct { |
|
1747 |
GnomeRRRotation rotation; |
|
1748 |
const char * name; |
|
1749 |
} RotationInfo; |
|
1750 |
static const RotationInfo rotations[] = { |
|
1751 |
{ GNOME_RR_ROTATION_0, N_("Normal") }, |
|
1752 |
{ GNOME_RR_ROTATION_90, N_("Left") }, |
|
1753 |
{ GNOME_RR_ROTATION_270, N_("Right") }, |
|
1754 |
{ GNOME_RR_ROTATION_180, N_("Upside Down") }, |
|
1755 |
/* We don't allow REFLECT_X or REFLECT_Y for now, as gnome-display-properties doesn't allow them, either */
|
|
1756 |
};
|
|
1757 |
||
1758 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1759 |
int i; |
|
1760 |
GSList *group; |
|
1761 |
GtkWidget *active_item; |
|
1762 |
gulong active_item_activate_id; |
|
1763 |
||
1764 |
group = NULL; |
|
1765 |
active_item = NULL; |
|
1766 |
active_item_activate_id = 0; |
|
1767 |
||
1768 |
for (i = 0; i < G_N_ELEMENTS (rotations); i++) { |
|
1769 |
GnomeRRRotation rot; |
|
1770 |
GtkWidget *item; |
|
1771 |
gulong activate_id; |
|
1772 |
||
1773 |
rot = rotations[i].rotation; |
|
1774 |
||
1775 |
if ((allowed_rotations & rot) == 0) { |
|
1776 |
/* don't display items for rotations which are
|
|
1777 |
* unavailable. Their availability is not under the
|
|
1778 |
* user's control, anyway.
|
|
1779 |
*/
|
|
1780 |
continue; |
|
1781 |
}
|
|
1782 |
||
1783 |
item = gtk_radio_menu_item_new_with_label (group, _(rotations[i].name)); |
|
1784 |
gtk_widget_show_all (item); |
|
1785 |
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item); |
|
1786 |
||
1787 |
g_object_set_data (G_OBJECT (item), "output", output); |
|
1788 |
g_object_set_data (G_OBJECT (item), "rotation", GINT_TO_POINTER (rot)); |
|
1789 |
||
1790 |
activate_id = g_signal_connect (item, "activate", |
|
1791 |
G_CALLBACK (output_rotation_item_activate_cb), manager); |
|
1792 |
||
1793 |
group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item)); |
|
1794 |
||
1795 |
if (rot == output->rotation) { |
|
1796 |
active_item = item; |
|
1797 |
active_item_activate_id = activate_id; |
|
1798 |
}
|
|
1799 |
}
|
|
1800 |
||
1801 |
if (active_item) { |
|
1802 |
/* Block the signal temporarily so our callback won't be called;
|
|
1803 |
* we are just setting up the UI.
|
|
1804 |
*/
|
|
1805 |
g_signal_handler_block (active_item, active_item_activate_id); |
|
1806 |
||
1807 |
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (active_item), TRUE); |
|
1808 |
||
1809 |
g_signal_handler_unblock (active_item, active_item_activate_id); |
|
1810 |
}
|
|
1811 |
||
1812 |
}
|
|
1813 |
||
1814 |
static void |
|
1815 |
add_rotation_items_for_output (GsdXrandrManager *manager, GnomeOutputInfo *output) |
|
1816 |
{
|
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1817 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1818 |
int num_rotations; |
1819 |
GnomeRRRotation rotations; |
|
1820 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1821 |
get_allowed_rotations_for_output (priv->configuration, priv->rw_screen, output, &num_rotations, &rotations); |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1822 |
|
1823 |
if (num_rotations == 1) |
|
1824 |
add_unsupported_rotation_item (manager); |
|
1825 |
else
|
|
1826 |
add_items_for_rotations (manager, output, rotations); |
|
1827 |
}
|
|
1828 |
||
1829 |
static void |
|
1830 |
add_menu_items_for_output (GsdXrandrManager *manager, GnomeOutputInfo *output) |
|
1831 |
{
|
|
1832 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1833 |
GtkWidget *item; |
|
1834 |
||
1835 |
item = make_menu_item_for_output_title (manager, output); |
|
1836 |
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item); |
|
1837 |
||
1838 |
add_rotation_items_for_output (manager, output); |
|
1839 |
}
|
|
1840 |
||
1841 |
static void |
|
1842 |
add_menu_items_for_outputs (GsdXrandrManager *manager) |
|
1843 |
{
|
|
1844 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1845 |
int i; |
|
1846 |
||
1847 |
for (i = 0; priv->configuration->outputs[i] != NULL; i++) { |
|
1848 |
if (priv->configuration->outputs[i]->connected) |
|
1849 |
add_menu_items_for_output (manager, priv->configuration->outputs[i]); |
|
1850 |
}
|
|
1851 |
}
|
|
1852 |
||
1853 |
static void |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1854 |
status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timestamp) |
1855 |
{
|
|
1856 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1857 |
GtkWidget *item; |
|
1858 |
||
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1859 |
g_assert (priv->configuration == NULL); |
1860 |
priv->configuration = gnome_rr_config_new_current (priv->rw_screen); |
|
1861 |
||
1862 |
g_assert (priv->labeler == NULL); |
|
1863 |
priv->labeler = gnome_rr_labeler_new (priv->configuration); |
|
1864 |
||
1865 |
g_assert (priv->popup_menu == NULL); |
|
1866 |
priv->popup_menu = gtk_menu_new (); |
|
1867 |
||
1868 |
add_menu_items_for_outputs (manager); |
|
1869 |
||
1870 |
item = gtk_separator_menu_item_new (); |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1871 |
gtk_widget_show (item); |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1872 |
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item); |
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1873 |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
1874 |
item = gtk_menu_item_new_with_mnemonic (_("_Configure Display Settings ...")); |
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1875 |
g_signal_connect (item, "activate", |
1876 |
G_CALLBACK (popup_menu_configure_display_cb), manager); |
|
1877 |
gtk_widget_show (item); |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1878 |
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item); |
1879 |
||
1880 |
g_signal_connect (priv->popup_menu, "selection-done", |
|
1881 |
G_CALLBACK (status_icon_popup_menu_selection_done_cb), manager); |
|
1882 |
||
1883 |
gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL, |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1884 |
gtk_status_icon_position_menu, |
1885 |
priv->status_icon, button, timestamp); |
|
1886 |
}
|
|
1887 |
||
1888 |
static void |
|
1889 |
status_icon_activate_cb (GtkStatusIcon *status_icon, gpointer data) |
|
1890 |
{
|
|
1891 |
GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data); |
|
1892 |
||
1893 |
/* Suck; we don't get a proper button/timestamp */
|
|
1894 |
status_icon_popup_menu (manager, 0, gtk_get_current_event_time ()); |
|
1895 |
}
|
|
1896 |
||
1897 |
static void |
|
1898 |
status_icon_popup_menu_cb (GtkStatusIcon *status_icon, guint button, guint32 timestamp, gpointer data) |
|
1899 |
{
|
|
1900 |
GsdXrandrManager *manager = GSD_XRANDR_MANAGER (data); |
|
1901 |
||
1902 |
status_icon_popup_menu (manager, button, timestamp); |
|
1903 |
}
|
|
1904 |
||
1905 |
static void |
|
1906 |
status_icon_start (GsdXrandrManager *manager) |
|
1907 |
{
|
|
1908 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1909 |
||
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1910 |
/* Ideally, we should detect if we are on a tablet and only display
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1911 |
* the icon in that case.
|
1912 |
*/
|
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
1913 |
if (!priv->status_icon) { |
1914 |
priv->status_icon = gtk_status_icon_new_from_icon_name (GSD_XRANDR_ICON_NAME); |
|
1.1.21
by Sebastien Bacher
Import upstream version 2.27.1 |
1915 |
gtk_status_icon_set_tooltip_text (priv->status_icon, _("Configure display settings")); |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1916 |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
1917 |
g_signal_connect (priv->status_icon, "activate", |
1918 |
G_CALLBACK (status_icon_activate_cb), manager); |
|
1919 |
g_signal_connect (priv->status_icon, "popup-menu", |
|
1920 |
G_CALLBACK (status_icon_popup_menu_cb), manager); |
|
1921 |
}
|
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
1922 |
}
|
1923 |
||
1924 |
static void |
|
1925 |
status_icon_stop (GsdXrandrManager *manager) |
|
1926 |
{
|
|
1927 |
struct GsdXrandrManagerPrivate *priv = manager->priv; |
|
1928 |
||
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
1929 |
if (priv->status_icon) { |
1930 |
g_signal_handlers_disconnect_by_func ( |
|
1931 |
priv->status_icon, G_CALLBACK (status_icon_activate_cb), manager); |
|
1932 |
g_signal_handlers_disconnect_by_func ( |
|
1933 |
priv->status_icon, G_CALLBACK (status_icon_popup_menu_cb), manager); |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
1934 |
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
1935 |
/* hide the icon before unreffing it; otherwise we will leak
|
1936 |
whitespace in the notification area due to a bug in there */
|
|
1937 |
gtk_status_icon_set_visible (priv->status_icon, FALSE); |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
1938 |
g_object_unref (priv->status_icon); |
1939 |
priv->status_icon = NULL; |
|
1940 |
}
|
|
1941 |
}
|
|
1942 |
||
1943 |
static void |
|
1944 |
start_or_stop_icon (GsdXrandrManager *manager) |
|
1945 |
{
|
|
1946 |
if (gconf_client_get_bool (manager->priv->client, CONF_DIR "/" CONF_KEY, NULL)) { |
|
1947 |
status_icon_start (manager); |
|
1948 |
}
|
|
1949 |
else { |
|
1950 |
status_icon_stop (manager); |
|
1951 |
}
|
|
1952 |
}
|
|
1953 |
||
1954 |
static void |
|
1955 |
on_config_changed (GConfClient *client, |
|
1956 |
guint cnxn_id, |
|
1957 |
GConfEntry *entry, |
|
1958 |
GsdXrandrManager *manager) |
|
1959 |
{
|
|
1960 |
start_or_stop_icon (manager); |
|
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
1961 |
}
|
1962 |
||
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
1963 |
static void |
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1964 |
apply_intended_configuration (GsdXrandrManager *manager, const char *intended_filename, guint32 timestamp) |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
1965 |
{
|
1966 |
GError *my_error; |
|
1967 |
||
1968 |
my_error = NULL; |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1969 |
if (!apply_configuration_from_filename (manager, intended_filename, FALSE, timestamp, &my_error)) { |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
1970 |
if (my_error) { |
1.1.20
by Sebastien Bacher
Import upstream version 2.26.1 |
1971 |
if (!g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
1972 |
error_message (manager, _("Could not apply the stored configuration for monitors"), my_error, NULL); |
1973 |
||
1974 |
g_error_free (my_error); |
|
1975 |
}
|
|
1976 |
}
|
|
1977 |
}
|
|
1978 |
||
1979 |
static void |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1980 |
apply_stored_configuration_at_startup (GsdXrandrManager *manager, guint32 timestamp) |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
1981 |
{
|
1982 |
GError *my_error; |
|
1983 |
gboolean success; |
|
1984 |
char *backup_filename; |
|
1985 |
char *intended_filename; |
|
1986 |
||
1987 |
backup_filename = gnome_rr_config_get_backup_filename (); |
|
1988 |
intended_filename = gnome_rr_config_get_intended_filename (); |
|
1989 |
||
1990 |
/* 1. See if there was a "saved" configuration. If there is one, it means
|
|
1991 |
* that the user had selected to change the display configuration, but the
|
|
1992 |
* machine crashed. In that case, we'll apply *that* configuration and save it on top of the
|
|
1993 |
* "intended" one.
|
|
1994 |
*/
|
|
1995 |
||
1996 |
my_error = NULL; |
|
1997 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
1998 |
success = apply_configuration_from_filename (manager, backup_filename, FALSE, timestamp, &my_error); |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
1999 |
if (success) { |
2000 |
/* The backup configuration existed, and could be applied
|
|
2001 |
* successfully, so we must restore it on top of the
|
|
2002 |
* failed/intended one.
|
|
2003 |
*/
|
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
2004 |
restore_backup_configuration (manager, backup_filename, intended_filename, timestamp); |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
2005 |
goto out; |
2006 |
}
|
|
2007 |
||
2008 |
if (!g_error_matches (my_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { |
|
2009 |
/* Epic fail: there (probably) was a backup configuration, but
|
|
2010 |
* we could not apply it. The only thing we can do is delete
|
|
2011 |
* the backup configuration. Let's hope that the user doesn't
|
|
2012 |
* get left with an unusable display...
|
|
2013 |
*/
|
|
2014 |
||
2015 |
unlink (backup_filename); |
|
2016 |
goto out; |
|
2017 |
}
|
|
2018 |
||
2019 |
/* 2. There was no backup configuration! This means we are
|
|
2020 |
* good. Apply the intended configuration instead.
|
|
2021 |
*/
|
|
2022 |
||
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
2023 |
apply_intended_configuration (manager, intended_filename, timestamp); |
1.1.17
by Sebastien Bacher
Import upstream version 2.25.90 |
2024 |
|
2025 |
out: |
|
2026 |
||
2027 |
if (my_error) |
|
2028 |
g_error_free (my_error); |
|
2029 |
||
2030 |
g_free (backup_filename); |
|
2031 |
g_free (intended_filename); |
|
2032 |
}
|
|
2033 |
||
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2034 |
gboolean
|
2035 |
gsd_xrandr_manager_start (GsdXrandrManager *manager, |
|
2036 |
GError **error) |
|
2037 |
{
|
|
2038 |
g_debug ("Starting xrandr manager"); |
|
1.1.15
by Sebastien Bacher
Import upstream version 2.25.2 |
2039 |
gnome_settings_profile_start (NULL); |
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2040 |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2041 |
manager->priv->rw_screen = gnome_rr_screen_new ( |
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2042 |
gdk_screen_get_default (), on_randr_event, manager, error); |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2043 |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2044 |
if (manager->priv->rw_screen == NULL) |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2045 |
return FALSE; |
2046 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2047 |
manager->priv->running = TRUE; |
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
2048 |
manager->priv->client = gconf_client_get_default (); |
2049 |
||
2050 |
g_assert (manager->priv->notify_id == 0); |
|
2051 |
||
2052 |
gconf_client_add_dir (manager->priv->client, CONF_DIR, |
|
1.1.15
by Sebastien Bacher
Import upstream version 2.25.2 |
2053 |
GCONF_CLIENT_PRELOAD_ONELEVEL, |
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
2054 |
NULL); |
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2055 |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
2056 |
manager->priv->notify_id = |
2057 |
gconf_client_notify_add ( |
|
2058 |
manager->priv->client, CONF_DIR, |
|
2059 |
(GConfClientNotifyFunc)on_config_changed, |
|
2060 |
manager, NULL, NULL); |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2061 |
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
2062 |
if (manager->priv->switch_video_mode_keycode) { |
2063 |
gdk_error_trap_push (); |
|
2064 |
||
2065 |
XGrabKey (gdk_x11_get_default_xdisplay(), |
|
2066 |
manager->priv->switch_video_mode_keycode, AnyModifier, |
|
2067 |
gdk_x11_get_default_root_xwindow(), |
|
2068 |
True, GrabModeAsync, GrabModeAsync); |
|
2069 |
||
2070 |
gdk_flush (); |
|
2071 |
gdk_error_trap_pop (); |
|
2072 |
}
|
|
2073 |
||
2074 |
if (manager->priv->rotate_windows_keycode) { |
|
2075 |
gdk_error_trap_push (); |
|
2076 |
||
2077 |
XGrabKey (gdk_x11_get_default_xdisplay(), |
|
2078 |
manager->priv->rotate_windows_keycode, AnyModifier, |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2079 |
gdk_x11_get_default_root_xwindow(), |
2080 |
True, GrabModeAsync, GrabModeAsync); |
|
2081 |
||
2082 |
gdk_flush (); |
|
2083 |
gdk_error_trap_pop (); |
|
2084 |
}
|
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2085 |
|
1.1.22
by Sebastien Bacher
Import upstream version 2.27.3 |
2086 |
show_timestamps_dialog (manager, "Startup"); |
2087 |
apply_stored_configuration_at_startup (manager, GDK_CURRENT_TIME); /* we don't have a real timestamp at startup anyway */ |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2088 |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2089 |
gdk_window_add_filter (gdk_get_default_root_window(), |
2090 |
(GdkFilterFunc)event_filter, |
|
2091 |
manager); |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2092 |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
2093 |
start_or_stop_icon (manager); |
0.1.1
by Sebastian Dröge
Import upstream version 2.22.2.1 |
2094 |
|
1.1.15
by Sebastien Bacher
Import upstream version 2.25.2 |
2095 |
gnome_settings_profile_end (NULL); |
2096 |
||
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2097 |
return TRUE; |
2098 |
}
|
|
2099 |
||
2100 |
void
|
|
2101 |
gsd_xrandr_manager_stop (GsdXrandrManager *manager) |
|
2102 |
{
|
|
2103 |
g_debug ("Stopping xrandr manager"); |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2104 |
|
2105 |
manager->priv->running = FALSE; |
|
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
2106 |
|
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
2107 |
if (manager->priv->switch_video_mode_keycode) { |
2108 |
gdk_error_trap_push (); |
|
2109 |
||
2110 |
XUngrabKey (gdk_x11_get_default_xdisplay(), |
|
2111 |
manager->priv->switch_video_mode_keycode, AnyModifier, |
|
2112 |
gdk_x11_get_default_root_xwindow()); |
|
2113 |
||
2114 |
gdk_error_trap_pop (); |
|
2115 |
}
|
|
2116 |
||
2117 |
if (manager->priv->rotate_windows_keycode) { |
|
2118 |
gdk_error_trap_push (); |
|
2119 |
||
2120 |
XUngrabKey (gdk_x11_get_default_xdisplay(), |
|
2121 |
manager->priv->rotate_windows_keycode, AnyModifier, |
|
2122 |
gdk_x11_get_default_root_xwindow()); |
|
2123 |
||
2124 |
gdk_error_trap_pop (); |
|
2125 |
}
|
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2126 |
|
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2127 |
gdk_window_remove_filter (gdk_get_default_root_window (), |
2128 |
(GdkFilterFunc) event_filter, |
|
2129 |
manager); |
|
2130 |
||
1.1.10
by Sebastien Bacher
Import upstream version 2.23.6 |
2131 |
if (manager->priv->notify_id != 0) { |
2132 |
gconf_client_remove_dir (manager->priv->client, |
|
2133 |
CONF_DIR, NULL); |
|
2134 |
gconf_client_notify_remove (manager->priv->client, |
|
2135 |
manager->priv->notify_id); |
|
2136 |
manager->priv->notify_id = 0; |
|
2137 |
}
|
|
2138 |
||
2139 |
if (manager->priv->client != NULL) { |
|
2140 |
g_object_unref (manager->priv->client); |
|
2141 |
manager->priv->client = NULL; |
|
2142 |
}
|
|
2143 |
||
1.1.11
by Sebastien Bacher
Import upstream version 2.23.90 |
2144 |
if (manager->priv->rw_screen != NULL) { |
2145 |
gnome_rr_screen_destroy (manager->priv->rw_screen); |
|
2146 |
manager->priv->rw_screen = NULL; |
|
2147 |
}
|
|
2148 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2149 |
if (manager->priv->dbus_connection != NULL) { |
2150 |
dbus_g_connection_unref (manager->priv->dbus_connection); |
|
2151 |
manager->priv->dbus_connection = NULL; |
|
2152 |
}
|
|
2153 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2154 |
status_icon_stop (manager); |
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2155 |
}
|
2156 |
||
2157 |
static void |
|
2158 |
gsd_xrandr_manager_set_property (GObject *object, |
|
2159 |
guint prop_id, |
|
2160 |
const GValue *value, |
|
2161 |
GParamSpec *pspec) |
|
2162 |
{
|
|
2163 |
GsdXrandrManager *self; |
|
2164 |
||
2165 |
self = GSD_XRANDR_MANAGER (object); |
|
2166 |
||
2167 |
switch (prop_id) { |
|
2168 |
default: |
|
2169 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
2170 |
break; |
|
2171 |
}
|
|
2172 |
}
|
|
2173 |
||
2174 |
static void |
|
2175 |
gsd_xrandr_manager_get_property (GObject *object, |
|
2176 |
guint prop_id, |
|
2177 |
GValue *value, |
|
2178 |
GParamSpec *pspec) |
|
2179 |
{
|
|
2180 |
GsdXrandrManager *self; |
|
2181 |
||
2182 |
self = GSD_XRANDR_MANAGER (object); |
|
2183 |
||
2184 |
switch (prop_id) { |
|
2185 |
default: |
|
2186 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
2187 |
break; |
|
2188 |
}
|
|
2189 |
}
|
|
2190 |
||
2191 |
static GObject * |
|
2192 |
gsd_xrandr_manager_constructor (GType type, |
|
2193 |
guint n_construct_properties, |
|
2194 |
GObjectConstructParam *construct_properties) |
|
2195 |
{
|
|
2196 |
GsdXrandrManager *xrandr_manager; |
|
2197 |
GsdXrandrManagerClass *klass; |
|
2198 |
||
2199 |
klass = GSD_XRANDR_MANAGER_CLASS (g_type_class_peek (GSD_TYPE_XRANDR_MANAGER)); |
|
2200 |
||
2201 |
xrandr_manager = GSD_XRANDR_MANAGER (G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->constructor (type, |
|
2202 |
n_construct_properties, |
|
2203 |
construct_properties)); |
|
2204 |
||
2205 |
return G_OBJECT (xrandr_manager); |
|
2206 |
}
|
|
2207 |
||
2208 |
static void |
|
2209 |
gsd_xrandr_manager_dispose (GObject *object) |
|
2210 |
{
|
|
2211 |
GsdXrandrManager *xrandr_manager; |
|
2212 |
||
2213 |
xrandr_manager = GSD_XRANDR_MANAGER (object); |
|
2214 |
||
2215 |
G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->dispose (object); |
|
2216 |
}
|
|
2217 |
||
2218 |
static void |
|
2219 |
gsd_xrandr_manager_class_init (GsdXrandrManagerClass *klass) |
|
2220 |
{
|
|
1.1.7
by Sebastien Bacher
Import upstream version 2.23.1.1 |
2221 |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2222 |
|
2223 |
object_class->get_property = gsd_xrandr_manager_get_property; |
|
2224 |
object_class->set_property = gsd_xrandr_manager_set_property; |
|
2225 |
object_class->constructor = gsd_xrandr_manager_constructor; |
|
2226 |
object_class->dispose = gsd_xrandr_manager_dispose; |
|
2227 |
object_class->finalize = gsd_xrandr_manager_finalize; |
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2228 |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2229 |
dbus_g_object_type_install_info (GSD_TYPE_XRANDR_MANAGER, &dbus_glib_gsd_xrandr_manager_object_info); |
2230 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2231 |
g_type_class_add_private (klass, sizeof (GsdXrandrManagerPrivate)); |
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2232 |
}
|
2233 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
2234 |
static guint |
2235 |
get_keycode_for_keysym_name (const char *name) |
|
2236 |
{
|
|
2237 |
Display *dpy; |
|
2238 |
guint keyval; |
|
2239 |
||
2240 |
dpy = gdk_x11_get_default_xdisplay (); |
|
2241 |
||
2242 |
keyval = gdk_keyval_from_name (name); |
|
2243 |
return XKeysymToKeycode (dpy, keyval); |
|
2244 |
}
|
|
2245 |
||
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2246 |
static void |
2247 |
gsd_xrandr_manager_init (GsdXrandrManager *manager) |
|
2248 |
{
|
|
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2249 |
manager->priv = GSD_XRANDR_MANAGER_GET_PRIVATE (manager); |
2250 |
||
1.1.30
by Chris Coulson
Import upstream version 2.29.5 |
2251 |
manager->priv->switch_video_mode_keycode = get_keycode_for_keysym_name (VIDEO_KEYSYM); |
2252 |
manager->priv->rotate_windows_keycode = get_keycode_for_keysym_name (ROTATE_KEYSYM); |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2253 |
|
2254 |
manager->priv->current_fn_f7_config = -1; |
|
2255 |
manager->priv->fn_f7_configs = NULL; |
|
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2256 |
}
|
2257 |
||
2258 |
static void |
|
2259 |
gsd_xrandr_manager_finalize (GObject *object) |
|
2260 |
{
|
|
2261 |
GsdXrandrManager *xrandr_manager; |
|
2262 |
||
2263 |
g_return_if_fail (object != NULL); |
|
2264 |
g_return_if_fail (GSD_IS_XRANDR_MANAGER (object)); |
|
2265 |
||
2266 |
xrandr_manager = GSD_XRANDR_MANAGER (object); |
|
2267 |
||
1.1.9
by Sebastien Bacher
Import upstream version 2.23.5 |
2268 |
g_return_if_fail (xrandr_manager->priv != NULL); |
2269 |
||
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2270 |
G_OBJECT_CLASS (gsd_xrandr_manager_parent_class)->finalize (object); |
2271 |
}
|
|
2272 |
||
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2273 |
static gboolean |
2274 |
register_manager_dbus (GsdXrandrManager *manager) |
|
2275 |
{
|
|
2276 |
GError *error = NULL; |
|
2277 |
||
2278 |
manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); |
|
2279 |
if (manager->priv->dbus_connection == NULL) { |
|
2280 |
if (error != NULL) { |
|
2281 |
g_warning ("Error getting session bus: %s", error->message); |
|
2282 |
g_error_free (error); |
|
2283 |
}
|
|
2284 |
return FALSE; |
|
2285 |
}
|
|
2286 |
||
2287 |
/* Hmm, should we do this in gsd_xrandr_manager_start()? */
|
|
2288 |
dbus_g_connection_register_g_object (manager->priv->dbus_connection, GSD_XRANDR_DBUS_PATH, G_OBJECT (manager)); |
|
2289 |
||
2290 |
return TRUE; |
|
2291 |
}
|
|
2292 |
||
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2293 |
GsdXrandrManager * |
2294 |
gsd_xrandr_manager_new (void) |
|
2295 |
{
|
|
2296 |
if (manager_object != NULL) { |
|
2297 |
g_object_ref (manager_object); |
|
2298 |
} else { |
|
2299 |
manager_object = g_object_new (GSD_TYPE_XRANDR_MANAGER, NULL); |
|
2300 |
g_object_add_weak_pointer (manager_object, |
|
2301 |
(gpointer *) &manager_object); |
|
1.1.16
by Sebastien Bacher
Import upstream version 2.25.3 |
2302 |
|
2303 |
if (!register_manager_dbus (manager_object)) { |
|
2304 |
g_object_unref (manager_object); |
|
2305 |
return NULL; |
|
2306 |
}
|
|
1
by Sebastien Bacher
Import upstream version 2.21.5.2 |
2307 |
}
|
2308 |
||
2309 |
return GSD_XRANDR_MANAGER (manager_object); |
|
2310 |
}
|