1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1 |
/* Monitor Settings. A preference panel for configuring monitors
|
2 |
*
|
|
3 |
* Copyright (C) 2007, 2008 Red Hat, Inc.
|
|
4 |
*
|
|
5 |
* This program is free software; you can redistribute it and/or modify
|
|
6 |
* it under the terms of the GNU General Public License as published by
|
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
8 |
* (at your option) any later version.
|
|
9 |
*
|
|
10 |
* This program is distributed in the hope that it will be useful,
|
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
* GNU General Public License for more details.
|
|
68
by Michael Vogt
* move packaging into bzr |
14 |
*
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
15 |
* You should have received a copy of the GNU General Public License
|
16 |
* along with this program; if not, write to the Free Software
|
|
17 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18 |
*
|
|
19 |
* Author: Soren Sandmann <sandmann@redhat.com>
|
|
20 |
*/
|
|
21 |
||
22 |
#include <config.h> |
|
23 |
#include <gtk/gtk.h> |
|
24 |
#include <string.h> |
|
25 |
#include <stdlib.h> |
|
26 |
#include "scrollarea.h" |
|
27 |
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
|
28 |
#include <libgnomeui/gnome-rr.h> |
|
29 |
#include <libgnomeui/gnome-rr-config.h> |
|
68
by Michael Vogt
* move packaging into bzr |
30 |
#include <libgnomeui/gnome-rr-labeler.h> |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
31 |
#include <gdk/gdkx.h> |
32 |
#include <X11/Xlib.h> |
|
33 |
#include <glib/gi18n.h> |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
34 |
#include <gconf/gconf-client.h> |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
35 |
#include <dbus/dbus-glib.h> |
36 |
#include <dbus/dbus-glib-bindings.h> |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
37 |
|
38 |
typedef struct App App; |
|
39 |
typedef struct GrabInfo GrabInfo; |
|
40 |
||
41 |
struct App |
|
42 |
{
|
|
43 |
GnomeRRScreen *screen; |
|
44 |
GnomeRRConfig *current_configuration; |
|
68
by Michael Vogt
* move packaging into bzr |
45 |
GnomeRRLabeler *labeler; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
46 |
GnomeOutputInfo *current_output; |
68
by Michael Vogt
* move packaging into bzr |
47 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
48 |
GtkWidget *dialog; |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
49 |
GtkWidget *current_monitor_event_box; |
50 |
GtkWidget *current_monitor_label; |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
51 |
GtkWidget *monitor_on_radio; |
52 |
GtkWidget *monitor_off_radio; |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
53 |
GtkListStore *resolution_store; |
54 |
GtkWidget *resolution_combo; |
|
55 |
GtkWidget *refresh_combo; |
|
56 |
GtkWidget *rotation_combo; |
|
57 |
GtkWidget *panel_checkbox; |
|
58 |
GtkWidget *clone_checkbox; |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
59 |
GtkWidget *show_icon_checkbox; |
68
by Michael Vogt
* move packaging into bzr |
60 |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
61 |
/* We store the event timestamp when the Apply button is clicked */
|
62 |
GtkWidget *apply_button; |
|
63 |
guint32 apply_button_clicked_timestamp; |
|
64 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
65 |
GtkWidget *area; |
66 |
gboolean ignore_gui_changes; |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
67 |
GConfClient *client; |
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
68 |
|
69 |
/* These are used while we are waiting for the ApplyConfiguration method to be executed over D-bus */
|
|
70 |
DBusGConnection *connection; |
|
71 |
DBusGProxy *proxy; |
|
72 |
DBusGProxyCall *proxy_call; |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
73 |
|
74 |
enum { |
|
75 |
APPLYING_VERSION_1, |
|
76 |
APPLYING_VERSION_2
|
|
77 |
} apply_configuration_state; |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
78 |
};
|
79 |
||
80 |
static void rebuild_gui (App *app); |
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
81 |
static void on_clone_changed (GtkWidget *box, gpointer data); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
82 |
static void on_rate_changed (GtkComboBox *box, gpointer data); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
83 |
static gboolean output_overlaps (GnomeOutputInfo *output, GnomeRRConfig *config); |
84 |
static void select_current_output_from_dialog_position (App *app); |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
85 |
static void monitor_on_off_toggled_cb (GtkToggleButton *toggle, gpointer data); |
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
86 |
static void get_geometry (GnomeOutputInfo *output, int *w, int *h); |
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
87 |
static void apply_configuration_returned_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, void *data); |
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
88 |
static gboolean get_clone_size (GnomeRRScreen *screen, int *width, int *height); |
89 |
static gboolean output_info_supports_mode (App *app, GnomeOutputInfo *info, int width, int height); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
90 |
|
91 |
static void |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
92 |
error_message (App *app, const char *primary_text, const char *secondary_text) |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
93 |
{
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
94 |
GtkWidget *dialog; |
68
by Michael Vogt
* move packaging into bzr |
95 |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
96 |
dialog = gtk_message_dialog_new ((app && app->dialog) ? GTK_WINDOW (app->dialog) : NULL, |
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
97 |
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
98 |
GTK_MESSAGE_ERROR, |
99 |
GTK_BUTTONS_CLOSE, |
|
100 |
"%s", primary_text); |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
101 |
|
102 |
if (secondary_text) |
|
103 |
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", secondary_text); |
|
68
by Michael Vogt
* move packaging into bzr |
104 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
105 |
gtk_dialog_run (GTK_DIALOG (dialog)); |
106 |
gtk_widget_destroy (dialog); |
|
107 |
}
|
|
108 |
||
109 |
static gboolean |
|
110 |
do_free (gpointer data) |
|
111 |
{
|
|
112 |
g_free (data); |
|
113 |
return FALSE; |
|
114 |
}
|
|
115 |
||
116 |
static gchar * |
|
117 |
idle_free (gchar *s) |
|
118 |
{
|
|
119 |
g_idle_add (do_free, s); |
|
120 |
||
121 |
return s; |
|
122 |
}
|
|
123 |
||
124 |
static void |
|
125 |
on_screen_changed (GnomeRRScreen *scr, |
|
126 |
gpointer data) |
|
127 |
{
|
|
128 |
GnomeRRConfig *current; |
|
129 |
App *app = data; |
|
130 |
||
131 |
current = gnome_rr_config_new_current (app->screen); |
|
132 |
||
133 |
if (app->current_configuration) |
|
134 |
gnome_rr_config_free (app->current_configuration); |
|
68
by Michael Vogt
* move packaging into bzr |
135 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
136 |
app->current_configuration = current; |
1.1.27
by Didier Roche
Import upstream version 2.26.0 |
137 |
app->current_output = NULL; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
138 |
|
68
by Michael Vogt
* move packaging into bzr |
139 |
if (app->labeler) { |
140 |
gnome_rr_labeler_hide (app->labeler); |
|
141 |
g_object_unref (app->labeler); |
|
142 |
}
|
|
143 |
||
144 |
app->labeler = gnome_rr_labeler_new (app->current_configuration); |
|
145 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
146 |
select_current_output_from_dialog_position (app); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
147 |
}
|
148 |
||
149 |
static void |
|
150 |
on_viewport_changed (FooScrollArea *scroll_area, |
|
151 |
GdkRectangle *old_viewport, |
|
152 |
GdkRectangle *new_viewport) |
|
153 |
{
|
|
154 |
foo_scroll_area_set_size (scroll_area, |
|
155 |
new_viewport->width, |
|
156 |
new_viewport->height); |
|
157 |
||
158 |
foo_scroll_area_invalidate (scroll_area); |
|
159 |
}
|
|
160 |
||
161 |
static void |
|
162 |
layout_set_font (PangoLayout *layout, const char *font) |
|
163 |
{
|
|
164 |
PangoFontDescription *desc = |
|
165 |
pango_font_description_from_string (font); |
|
166 |
||
167 |
if (desc) |
|
168 |
{
|
|
169 |
pango_layout_set_font_description (layout, desc); |
|
170 |
||
171 |
pango_font_description_free (desc); |
|
172 |
}
|
|
173 |
}
|
|
174 |
||
175 |
static void |
|
176 |
clear_combo (GtkWidget *widget) |
|
177 |
{
|
|
178 |
GtkComboBox *box = GTK_COMBO_BOX (widget); |
|
179 |
GtkTreeModel *model = gtk_combo_box_get_model (box); |
|
180 |
GtkListStore *store = GTK_LIST_STORE (model); |
|
181 |
||
182 |
gtk_list_store_clear (store); |
|
183 |
}
|
|
184 |
||
185 |
typedef struct |
|
186 |
{
|
|
187 |
const char *text; |
|
188 |
gboolean found; |
|
189 |
GtkTreeIter iter; |
|
190 |
} ForeachInfo; |
|
191 |
||
192 |
static gboolean |
|
193 |
foreach (GtkTreeModel *model, |
|
194 |
GtkTreePath *path, |
|
195 |
GtkTreeIter *iter, |
|
196 |
gpointer data) |
|
197 |
{
|
|
198 |
ForeachInfo *info = data; |
|
199 |
char *text = NULL; |
|
200 |
||
201 |
gtk_tree_model_get (model, iter, 0, &text, -1); |
|
202 |
||
203 |
g_assert (text != NULL); |
|
68
by Michael Vogt
* move packaging into bzr |
204 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
205 |
if (strcmp (info->text, text) == 0) |
206 |
{
|
|
207 |
info->found = TRUE; |
|
208 |
info->iter = *iter; |
|
209 |
return TRUE; |
|
210 |
}
|
|
211 |
||
212 |
return FALSE; |
|
213 |
}
|
|
214 |
||
215 |
static void |
|
216 |
add_key (GtkWidget *widget, |
|
217 |
const char *text, |
|
218 |
int width, int height, int rate, |
|
219 |
GnomeRRRotation rotation) |
|
220 |
{
|
|
221 |
ForeachInfo info; |
|
222 |
GtkComboBox *box = GTK_COMBO_BOX (widget); |
|
223 |
GtkTreeModel *model = gtk_combo_box_get_model (box); |
|
224 |
GtkListStore *store = GTK_LIST_STORE (model); |
|
225 |
gboolean retval; |
|
226 |
||
227 |
info.text = text; |
|
228 |
info.found = FALSE; |
|
68
by Michael Vogt
* move packaging into bzr |
229 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
230 |
gtk_tree_model_foreach (model, foreach, &info); |
231 |
||
232 |
if (!info.found) |
|
233 |
{
|
|
234 |
GtkTreeIter iter; |
|
1.1.23
by Michael Vogt
Import upstream version 2.25.2 |
235 |
gtk_list_store_insert_with_values (store, &iter, -1, |
236 |
0, text, |
|
237 |
1, width, |
|
238 |
2, height, |
|
239 |
3, rate, |
|
240 |
4, width * height, |
|
241 |
5, rotation, |
|
242 |
-1); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
243 |
|
244 |
retval = TRUE; |
|
245 |
}
|
|
246 |
else
|
|
247 |
{
|
|
248 |
retval = FALSE; |
|
249 |
}
|
|
250 |
}
|
|
251 |
||
252 |
static gboolean |
|
253 |
combo_select (GtkWidget *widget, const char *text) |
|
254 |
{
|
|
255 |
GtkComboBox *box = GTK_COMBO_BOX (widget); |
|
256 |
GtkTreeModel *model = gtk_combo_box_get_model (box); |
|
257 |
ForeachInfo info; |
|
258 |
||
259 |
info.text = text; |
|
260 |
info.found = FALSE; |
|
68
by Michael Vogt
* move packaging into bzr |
261 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
262 |
gtk_tree_model_foreach (model, foreach, &info); |
263 |
||
264 |
if (!info.found) |
|
265 |
return FALSE; |
|
266 |
||
267 |
gtk_combo_box_set_active_iter (box, &info.iter); |
|
268 |
return TRUE; |
|
269 |
}
|
|
270 |
||
271 |
static GnomeRRMode ** |
|
272 |
get_current_modes (App *app) |
|
273 |
{
|
|
274 |
GnomeRROutput *output; |
|
275 |
||
276 |
if (app->current_configuration->clone) |
|
277 |
{
|
|
1.1.23
by Michael Vogt
Import upstream version 2.25.2 |
278 |
return gnome_rr_screen_list_clone_modes (app->screen); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
279 |
}
|
280 |
else
|
|
281 |
{
|
|
282 |
if (!app->current_output) |
|
283 |
return NULL; |
|
68
by Michael Vogt
* move packaging into bzr |
284 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
285 |
output = gnome_rr_screen_get_output_by_name ( |
286 |
app->screen, app->current_output->name); |
|
68
by Michael Vogt
* move packaging into bzr |
287 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
288 |
if (!output) |
289 |
return NULL; |
|
68
by Michael Vogt
* move packaging into bzr |
290 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
291 |
return gnome_rr_output_list_modes (output); |
292 |
}
|
|
293 |
}
|
|
294 |
||
295 |
static void |
|
296 |
rebuild_rotation_combo (App *app) |
|
297 |
{
|
|
298 |
typedef struct |
|
299 |
{
|
|
300 |
GnomeRRRotation rotation; |
|
301 |
const char * name; |
|
302 |
} RotationInfo; |
|
303 |
static const RotationInfo rotations[] = { |
|
304 |
{ GNOME_RR_ROTATION_0, N_("Normal") }, |
|
305 |
{ GNOME_RR_ROTATION_90, N_("Left") }, |
|
306 |
{ GNOME_RR_ROTATION_270, N_("Right") }, |
|
307 |
{ GNOME_RR_ROTATION_180, N_("Upside Down") }, |
|
308 |
};
|
|
309 |
const char *selection; |
|
310 |
GnomeRRRotation current; |
|
311 |
int i; |
|
68
by Michael Vogt
* move packaging into bzr |
312 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
313 |
clear_combo (app->rotation_combo); |
314 |
||
315 |
gtk_widget_set_sensitive ( |
|
316 |
app->rotation_combo, app->current_output && app->current_output->on); |
|
68
by Michael Vogt
* move packaging into bzr |
317 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
318 |
if (!app->current_output) |
319 |
return; |
|
68
by Michael Vogt
* move packaging into bzr |
320 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
321 |
current = app->current_output->rotation; |
322 |
||
323 |
selection = NULL; |
|
324 |
for (i = 0; i < G_N_ELEMENTS (rotations); ++i) |
|
325 |
{
|
|
326 |
const RotationInfo *info = &(rotations[i]); |
|
68
by Michael Vogt
* move packaging into bzr |
327 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
328 |
app->current_output->rotation = info->rotation; |
329 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
330 |
/* NULL-GError --- FIXME: we should say why this rotation is not available! */
|
331 |
if (gnome_rr_config_applicable (app->current_configuration, app->screen, NULL)) |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
332 |
{
|
1.1.27
by Didier Roche
Import upstream version 2.26.0 |
333 |
add_key (app->rotation_combo, _(info->name), 0, 0, 0, info->rotation); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
334 |
|
335 |
if (info->rotation == current) |
|
1.1.27
by Didier Roche
Import upstream version 2.26.0 |
336 |
selection = _(info->name); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
337 |
}
|
338 |
}
|
|
339 |
||
340 |
app->current_output->rotation = current; |
|
68
by Michael Vogt
* move packaging into bzr |
341 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
342 |
if (!(selection && combo_select (app->rotation_combo, selection))) |
1.1.27
by Didier Roche
Import upstream version 2.26.0 |
343 |
combo_select (app->rotation_combo, _("Normal")); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
344 |
}
|
345 |
||
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
346 |
static char * |
347 |
make_rate_string (int hz) |
|
348 |
{
|
|
349 |
return g_strdup_printf (_("%d Hz"), hz); |
|
350 |
}
|
|
351 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
352 |
static void |
353 |
rebuild_rate_combo (App *app) |
|
354 |
{
|
|
355 |
GHashTable *rates; |
|
356 |
GnomeRRMode **modes; |
|
357 |
int best; |
|
358 |
int i; |
|
359 |
||
360 |
clear_combo (app->refresh_combo); |
|
361 |
||
362 |
gtk_widget_set_sensitive ( |
|
363 |
app->refresh_combo, app->current_output && app->current_output->on); |
|
364 |
||
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
365 |
if (!app->current_output |
366 |
|| !(modes = get_current_modes (app))) |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
367 |
return; |
68
by Michael Vogt
* move packaging into bzr |
368 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
369 |
rates = g_hash_table_new_full ( |
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
370 |
g_str_hash, g_str_equal, (GFreeFunc) g_free, NULL); |
68
by Michael Vogt
* move packaging into bzr |
371 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
372 |
best = -1; |
373 |
for (i = 0; modes[i] != NULL; ++i) |
|
374 |
{
|
|
375 |
GnomeRRMode *mode = modes[i]; |
|
376 |
int width, height, rate; |
|
377 |
||
378 |
width = gnome_rr_mode_get_width (mode); |
|
379 |
height = gnome_rr_mode_get_height (mode); |
|
380 |
rate = gnome_rr_mode_get_freq (mode); |
|
381 |
||
382 |
if (width == app->current_output->width && |
|
383 |
height == app->current_output->height) |
|
384 |
{
|
|
385 |
add_key (app->refresh_combo, |
|
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
386 |
idle_free (make_rate_string (rate)), |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
387 |
0, 0, rate, -1); |
388 |
||
389 |
if (rate > best) |
|
390 |
best = rate; |
|
391 |
}
|
|
392 |
}
|
|
393 |
||
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
394 |
if (!combo_select (app->refresh_combo, idle_free (make_rate_string (app->current_output->rate)))) |
395 |
combo_select (app->refresh_combo, idle_free (make_rate_string (best))); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
396 |
}
|
397 |
||
398 |
static int |
|
399 |
count_active_outputs (App *app) |
|
400 |
{
|
|
401 |
int i, count = 0; |
|
68
by Michael Vogt
* move packaging into bzr |
402 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
403 |
for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) |
404 |
{
|
|
405 |
GnomeOutputInfo *output = app->current_configuration->outputs[i]; |
|
406 |
if (output->on) |
|
407 |
count++; |
|
408 |
}
|
|
68
by Michael Vogt
* move packaging into bzr |
409 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
410 |
return count; |
411 |
}
|
|
412 |
||
1.1.23
by Michael Vogt
Import upstream version 2.25.2 |
413 |
#if 0
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
414 |
static int
|
415 |
count_all_outputs (GnomeRRConfig *config)
|
|
416 |
{
|
|
417 |
int i;
|
|
418 |
||
419 |
for (i = 0; config->outputs[i] != NULL; i++)
|
|
420 |
;
|
|
421 |
||
422 |
return i;
|
|
423 |
}
|
|
1.1.23
by Michael Vogt
Import upstream version 2.25.2 |
424 |
#endif
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
425 |
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
426 |
/* Computes whether "Mirror Screens" (clone mode) is supported based on these criteria:
|
427 |
*
|
|
428 |
* 1. There is an available size for cloning.
|
|
429 |
*
|
|
430 |
* 2. There are 2 or more connected outputs that support that size.
|
|
431 |
*/
|
|
432 |
static gboolean |
|
433 |
mirror_screens_is_supported (App *app) |
|
434 |
{
|
|
435 |
int clone_width, clone_height; |
|
436 |
gboolean have_clone_size; |
|
437 |
gboolean mirror_is_supported; |
|
438 |
||
439 |
mirror_is_supported = FALSE; |
|
440 |
||
441 |
have_clone_size = get_clone_size (app->screen, &clone_width, &clone_height); |
|
442 |
||
443 |
if (have_clone_size) { |
|
444 |
int i; |
|
445 |
int num_outputs_with_clone_size; |
|
446 |
||
447 |
num_outputs_with_clone_size = 0; |
|
448 |
||
449 |
for (i = 0; app->current_configuration->outputs[i] != NULL; i++) |
|
450 |
{
|
|
451 |
GnomeOutputInfo *output = app->current_configuration->outputs[i]; |
|
452 |
||
453 |
/* We count the connected outputs that support the clone size. It
|
|
454 |
* doesn't matter if those outputs aren't actually On currently; we
|
|
455 |
* will turn them on in on_clone_changed().
|
|
456 |
*/
|
|
457 |
if (output->connected && output_info_supports_mode (app, output, clone_width, clone_height)) |
|
458 |
num_outputs_with_clone_size++; |
|
459 |
}
|
|
460 |
||
461 |
if (num_outputs_with_clone_size >= 2) |
|
462 |
mirror_is_supported = TRUE; |
|
463 |
}
|
|
464 |
||
465 |
return mirror_is_supported; |
|
466 |
}
|
|
467 |
||
468 |
static void |
|
469 |
rebuild_mirror_screens (App *app) |
|
470 |
{
|
|
471 |
gboolean mirror_is_active; |
|
472 |
gboolean mirror_is_supported; |
|
473 |
||
474 |
g_signal_handlers_block_by_func (app->clone_checkbox, G_CALLBACK (on_clone_changed), app); |
|
475 |
||
476 |
mirror_is_active = app->current_configuration && app->current_configuration->clone; |
|
477 |
||
478 |
/* If mirror_is_active, then it *must* be possible to turn mirroring off */
|
|
479 |
mirror_is_supported = mirror_is_active || mirror_screens_is_supported (app); |
|
480 |
||
481 |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (app->clone_checkbox), mirror_is_active); |
|
482 |
gtk_widget_set_sensitive (app->clone_checkbox, mirror_is_supported); |
|
483 |
||
484 |
g_signal_handlers_unblock_by_func (app->clone_checkbox, G_CALLBACK (on_clone_changed), app); |
|
485 |
}
|
|
486 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
487 |
static void |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
488 |
rebuild_current_monitor_label (App *app) |
489 |
{
|
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
490 |
char *str, *tmp; |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
491 |
GdkColor color; |
492 |
gboolean use_color; |
|
493 |
||
494 |
if (app->current_output) |
|
495 |
{
|
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
496 |
if (app->current_configuration->clone) |
497 |
tmp = g_strdup (_("Mirror Screens")); |
|
498 |
else
|
|
499 |
tmp = g_strdup_printf (_("Monitor: %s"), app->current_output->display_name); |
|
500 |
||
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
501 |
str = g_strdup_printf ("<b>%s</b>", tmp); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
502 |
gnome_rr_labeler_get_color_for_output (app->labeler, app->current_output, &color); |
503 |
use_color = TRUE; |
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
504 |
g_free (tmp); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
505 |
}
|
506 |
else
|
|
507 |
{
|
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
508 |
str = g_strdup_printf ("<b>%s</b>", _("Monitor")); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
509 |
use_color = FALSE; |
510 |
}
|
|
511 |
||
512 |
gtk_label_set_markup (GTK_LABEL (app->current_monitor_label), str); |
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
513 |
g_free (str); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
514 |
|
515 |
if (use_color) |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
516 |
{
|
517 |
GdkColor black = { 0, 0, 0, 0 }; |
|
518 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
519 |
gtk_widget_modify_bg (app->current_monitor_event_box, app->current_monitor_event_box->state, &color); |
520 |
||
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
521 |
/* Make the label explicitly black. We don't want it to follow the
|
522 |
* theme's colors, since the label is always shown against a light
|
|
523 |
* pastel background. See bgo#556050
|
|
524 |
*/
|
|
525 |
gtk_widget_modify_fg (app->current_monitor_label, GTK_WIDGET_STATE (app->current_monitor_label), &black); |
|
526 |
}
|
|
527 |
else
|
|
528 |
{
|
|
529 |
/* Remove any modifications we did on the label's color */
|
|
530 |
GtkRcStyle *reset_rc_style; |
|
531 |
||
532 |
reset_rc_style = gtk_rc_style_new (); |
|
533 |
gtk_widget_modify_style (app->current_monitor_label, reset_rc_style); /* takes ownership of, and destroys, the rc style */ |
|
534 |
}
|
|
535 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
536 |
gtk_event_box_set_visible_window (GTK_EVENT_BOX (app->current_monitor_event_box), use_color); |
537 |
}
|
|
538 |
||
539 |
static void |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
540 |
rebuild_on_off_radios (App *app) |
541 |
{
|
|
542 |
gboolean sensitive; |
|
543 |
gboolean on_active; |
|
544 |
gboolean off_active; |
|
545 |
||
546 |
g_signal_handlers_block_by_func (app->monitor_on_radio, G_CALLBACK (monitor_on_off_toggled_cb), app); |
|
547 |
g_signal_handlers_block_by_func (app->monitor_off_radio, G_CALLBACK (monitor_on_off_toggled_cb), app); |
|
548 |
||
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
549 |
sensitive = FALSE; |
550 |
on_active = FALSE; |
|
551 |
off_active = FALSE; |
|
552 |
||
553 |
if (!app->current_configuration->clone && app->current_output) |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
554 |
{
|
555 |
if (count_active_outputs (app) > 1 || !app->current_output->on) |
|
556 |
sensitive = TRUE; |
|
557 |
else
|
|
558 |
sensitive = FALSE; |
|
559 |
||
560 |
on_active = app->current_output->on; |
|
561 |
off_active = !on_active; |
|
562 |
}
|
|
563 |
||
564 |
gtk_widget_set_sensitive (app->monitor_on_radio, sensitive); |
|
565 |
gtk_widget_set_sensitive (app->monitor_off_radio, sensitive); |
|
566 |
||
567 |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (app->monitor_on_radio), on_active); |
|
568 |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (app->monitor_off_radio), off_active); |
|
569 |
||
570 |
g_signal_handlers_unblock_by_func (app->monitor_on_radio, G_CALLBACK (monitor_on_off_toggled_cb), app); |
|
571 |
g_signal_handlers_unblock_by_func (app->monitor_off_radio, G_CALLBACK (monitor_on_off_toggled_cb), app); |
|
572 |
}
|
|
573 |
||
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
574 |
static char * |
575 |
make_resolution_string (int width, int height) |
|
576 |
{
|
|
577 |
return g_strdup_printf (_("%d x %d"), width, height); |
|
578 |
}
|
|
579 |
||
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
580 |
static void |
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
581 |
find_best_mode (GnomeRRMode **modes, int *out_width, int *out_height) |
582 |
{
|
|
583 |
int i; |
|
584 |
||
585 |
*out_width = 0; |
|
586 |
*out_height = 0; |
|
587 |
||
588 |
for (i = 0; modes[i] != NULL; i++) |
|
589 |
{
|
|
590 |
int w, h; |
|
591 |
||
592 |
w = gnome_rr_mode_get_width (modes[i]); |
|
593 |
h = gnome_rr_mode_get_height (modes[i]); |
|
594 |
||
595 |
if (w * h > *out_width * *out_height) |
|
596 |
{
|
|
597 |
*out_width = w; |
|
598 |
*out_height = h; |
|
599 |
}
|
|
600 |
}
|
|
601 |
}
|
|
602 |
||
603 |
static void |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
604 |
rebuild_resolution_combo (App *app) |
605 |
{
|
|
606 |
int i; |
|
607 |
GnomeRRMode **modes; |
|
608 |
const char *current; |
|
609 |
||
610 |
clear_combo (app->resolution_combo); |
|
68
by Michael Vogt
* move packaging into bzr |
611 |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
612 |
if (!(modes = get_current_modes (app)) |
613 |
|| !app->current_output |
|
614 |
|| !app->current_output->on) |
|
615 |
{
|
|
616 |
gtk_widget_set_sensitive (app->resolution_combo, FALSE); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
617 |
return; |
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
618 |
}
|
619 |
||
620 |
g_assert (app->current_output != NULL); |
|
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
621 |
g_assert (app->current_output->width != 0 && app->current_output->height != 0); |
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
622 |
|
623 |
gtk_widget_set_sensitive (app->resolution_combo, TRUE); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
624 |
|
625 |
for (i = 0; modes[i] != NULL; ++i) |
|
626 |
{
|
|
627 |
int width, height; |
|
628 |
||
629 |
width = gnome_rr_mode_get_width (modes[i]); |
|
630 |
height = gnome_rr_mode_get_height (modes[i]); |
|
68
by Michael Vogt
* move packaging into bzr |
631 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
632 |
add_key (app->resolution_combo, |
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
633 |
idle_free (make_resolution_string (width, height)), |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
634 |
width, height, 0, -1); |
635 |
}
|
|
636 |
||
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
637 |
current = idle_free (make_resolution_string (app->current_output->width, app->current_output->height)); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
638 |
|
639 |
if (!combo_select (app->resolution_combo, current)) |
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
640 |
{
|
641 |
int best_w, best_h; |
|
642 |
||
643 |
find_best_mode (modes, &best_w, &best_h); |
|
644 |
combo_select (app->resolution_combo, idle_free (make_resolution_string (best_w, best_h))); |
|
645 |
}
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
646 |
}
|
647 |
||
648 |
static void |
|
649 |
rebuild_gui (App *app) |
|
650 |
{
|
|
651 |
gboolean sensitive; |
|
652 |
||
653 |
/* We would break spectacularly if we recursed, so
|
|
654 |
* just assert if that happens
|
|
655 |
*/
|
|
656 |
g_assert (app->ignore_gui_changes == FALSE); |
|
68
by Michael Vogt
* move packaging into bzr |
657 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
658 |
app->ignore_gui_changes = TRUE; |
659 |
||
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
660 |
sensitive = app->current_output ? TRUE : FALSE; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
661 |
|
662 |
#if 0
|
|
68
by Michael Vogt
* move packaging into bzr |
663 |
g_debug ("rebuild gui, is on: %d", app->current_output->on);
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
664 |
#endif
|
68
by Michael Vogt
* move packaging into bzr |
665 |
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
666 |
rebuild_mirror_screens (app); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
667 |
rebuild_current_monitor_label (app); |
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
668 |
rebuild_on_off_radios (app); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
669 |
rebuild_resolution_combo (app); |
670 |
rebuild_rate_combo (app); |
|
671 |
rebuild_rotation_combo (app); |
|
672 |
||
673 |
#if 0
|
|
68
by Michael Vogt
* move packaging into bzr |
674 |
g_debug ("sensitive: %d, on: %d", sensitive, app->current_output->on);
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
675 |
#endif
|
676 |
gtk_widget_set_sensitive (app->panel_checkbox, sensitive); |
|
677 |
||
678 |
app->ignore_gui_changes = FALSE; |
|
679 |
}
|
|
680 |
||
681 |
static gboolean |
|
682 |
get_mode (GtkWidget *widget, int *width, int *height, int *freq, GnomeRRRotation *rot) |
|
683 |
{
|
|
684 |
GtkTreeIter iter; |
|
685 |
GtkTreeModel *model; |
|
686 |
GtkComboBox *box = GTK_COMBO_BOX (widget); |
|
687 |
int dummy; |
|
688 |
||
689 |
if (!gtk_combo_box_get_active_iter (box, &iter)) |
|
690 |
return FALSE; |
|
691 |
||
692 |
if (!width) |
|
693 |
width = &dummy; |
|
694 |
||
695 |
if (!height) |
|
696 |
height = &dummy; |
|
697 |
||
698 |
if (!freq) |
|
699 |
freq = &dummy; |
|
700 |
||
701 |
if (!rot) |
|
702 |
rot = (GnomeRRRotation *)&dummy; |
|
68
by Michael Vogt
* move packaging into bzr |
703 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
704 |
model = gtk_combo_box_get_model (box); |
705 |
gtk_tree_model_get (model, &iter, |
|
706 |
1, width, |
|
707 |
2, height, |
|
708 |
3, freq, |
|
709 |
5, rot, |
|
710 |
-1); |
|
711 |
||
712 |
return TRUE; |
|
713 |
||
714 |
}
|
|
715 |
||
716 |
static void |
|
717 |
on_rotation_changed (GtkComboBox *box, gpointer data) |
|
718 |
{
|
|
719 |
App *app = data; |
|
720 |
GnomeRRRotation rotation; |
|
721 |
||
722 |
if (!app->current_output) |
|
723 |
return; |
|
724 |
||
725 |
if (get_mode (app->rotation_combo, NULL, NULL, NULL, &rotation)) |
|
726 |
app->current_output->rotation = rotation; |
|
727 |
||
728 |
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); |
|
729 |
}
|
|
730 |
||
731 |
static void |
|
732 |
on_rate_changed (GtkComboBox *box, gpointer data) |
|
733 |
{
|
|
734 |
App *app = data; |
|
735 |
int rate; |
|
736 |
||
737 |
if (!app->current_output) |
|
738 |
return; |
|
739 |
||
740 |
if (get_mode (app->refresh_combo, NULL, NULL, &rate, NULL)) |
|
741 |
app->current_output->rate = rate; |
|
742 |
||
743 |
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); |
|
744 |
}
|
|
745 |
||
746 |
static void |
|
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
747 |
select_resolution_for_current_output (App *app) |
748 |
{
|
|
749 |
GnomeRRMode **modes; |
|
750 |
int width, height; |
|
751 |
||
752 |
if (app->current_output->pref_width != 0 && app->current_output->pref_height != 0) |
|
753 |
{
|
|
754 |
app->current_output->width = app->current_output->pref_width; |
|
755 |
app->current_output->height = app->current_output->pref_height; |
|
756 |
return; |
|
757 |
}
|
|
758 |
||
759 |
modes = get_current_modes (app); |
|
760 |
if (!modes) |
|
761 |
return; |
|
762 |
||
763 |
find_best_mode (modes, &width, &height); |
|
764 |
||
765 |
app->current_output->width = width; |
|
766 |
app->current_output->height = height; |
|
767 |
}
|
|
768 |
||
769 |
static void |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
770 |
monitor_on_off_toggled_cb (GtkToggleButton *toggle, gpointer data) |
771 |
{
|
|
772 |
App *app = data; |
|
773 |
gboolean is_on; |
|
774 |
||
775 |
if (!app->current_output) |
|
776 |
return; |
|
777 |
||
778 |
if (!gtk_toggle_button_get_active (toggle)) |
|
779 |
return; |
|
780 |
||
781 |
if (GTK_WIDGET (toggle) == app->monitor_on_radio) |
|
782 |
is_on = TRUE; |
|
783 |
else if (GTK_WIDGET (toggle) == app->monitor_off_radio) |
|
784 |
is_on = FALSE; |
|
785 |
else
|
|
786 |
{
|
|
787 |
g_assert_not_reached (); |
|
788 |
return; |
|
789 |
}
|
|
790 |
||
791 |
app->current_output->on = is_on; |
|
792 |
||
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
793 |
if (is_on) |
794 |
select_resolution_for_current_output (app); /* The refresh rate will be picked in rebuild_rate_combo() */ |
|
795 |
||
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
796 |
rebuild_gui (app); |
797 |
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); |
|
798 |
}
|
|
799 |
||
800 |
static void |
|
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
801 |
realign_outputs_after_resolution_change (App *app, GnomeOutputInfo *output_that_changed, int old_width, int old_height) |
802 |
{
|
|
803 |
/* We find the outputs that were below or to the right of the output that
|
|
804 |
* changed, and realign them; we also do that for outputs that shared the
|
|
805 |
* right/bottom edges with the output that changed. The outputs that are
|
|
806 |
* above or to the left of that output don't need to change.
|
|
807 |
*/
|
|
808 |
||
809 |
int i; |
|
810 |
int old_right_edge, old_bottom_edge; |
|
811 |
int dx, dy; |
|
812 |
||
813 |
g_assert (app->current_configuration != NULL); |
|
814 |
||
1.1.30
by Chris Coulson
Import upstream version 2.27.5 |
815 |
if (output_that_changed->width == old_width && output_that_changed->height == old_height) |
816 |
return; |
|
817 |
||
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
818 |
old_right_edge = output_that_changed->x + old_width; |
819 |
old_bottom_edge = output_that_changed->y + old_height; |
|
820 |
||
821 |
dx = output_that_changed->width - old_width; |
|
822 |
dy = output_that_changed->height - old_height; |
|
823 |
||
824 |
for (i = 0; app->current_configuration->outputs[i] != NULL; i++) { |
|
825 |
GnomeOutputInfo *output; |
|
826 |
int output_width, output_height; |
|
827 |
||
828 |
output = app->current_configuration->outputs[i]; |
|
829 |
||
830 |
if (output == output_that_changed || !output->connected) |
|
831 |
continue; |
|
832 |
||
833 |
get_geometry (output, &output_width, &output_height); |
|
834 |
||
835 |
if (output->x >= old_right_edge) |
|
836 |
output->x += dx; |
|
837 |
else if (output->x + output_width == old_right_edge) |
|
838 |
output->x = output_that_changed->x + output_that_changed->width - output_width; |
|
839 |
||
840 |
if (output->y >= old_bottom_edge) |
|
841 |
output->y += dy; |
|
842 |
else if (output->y + output_height == old_bottom_edge) |
|
843 |
output->y = output_that_changed->y + output_that_changed->height - output_height; |
|
844 |
}
|
|
845 |
}
|
|
846 |
||
847 |
static void |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
848 |
on_resolution_changed (GtkComboBox *box, gpointer data) |
849 |
{
|
|
850 |
App *app = data; |
|
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
851 |
int old_width, old_height; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
852 |
int width; |
853 |
int height; |
|
854 |
||
855 |
if (!app->current_output) |
|
856 |
return; |
|
857 |
||
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
858 |
old_width = app->current_output->width; |
859 |
old_height = app->current_output->height; |
|
860 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
861 |
if (get_mode (app->resolution_combo, &width, &height, NULL, NULL)) |
862 |
{
|
|
863 |
app->current_output->width = width; |
|
864 |
app->current_output->height = height; |
|
865 |
||
866 |
if (width == 0 || height == 0) |
|
867 |
app->current_output->on = FALSE; |
|
868 |
else
|
|
869 |
app->current_output->on = TRUE; |
|
870 |
}
|
|
68
by Michael Vogt
* move packaging into bzr |
871 |
|
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
872 |
realign_outputs_after_resolution_change (app, app->current_output, old_width, old_height); |
68
by Michael Vogt
* move packaging into bzr |
873 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
874 |
rebuild_rate_combo (app); |
875 |
rebuild_rotation_combo (app); |
|
68
by Michael Vogt
* move packaging into bzr |
876 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
877 |
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); |
878 |
}
|
|
879 |
||
880 |
static void |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
881 |
lay_out_outputs_horizontally (App *app) |
882 |
{
|
|
883 |
int i; |
|
884 |
int x; |
|
885 |
||
886 |
/* Lay out all the monitors horizontally when "mirror screens" is turned
|
|
887 |
* off, to avoid having all of them overlapped initially. We put the
|
|
888 |
* outputs turned off on the right-hand side.
|
|
889 |
*/
|
|
890 |
||
891 |
x = 0; |
|
892 |
||
893 |
/* First pass, all "on" outputs */
|
|
894 |
||
895 |
for (i = 0; app->current_configuration->outputs[i]; ++i) |
|
896 |
{
|
|
897 |
GnomeOutputInfo *output; |
|
898 |
||
899 |
output = app->current_configuration->outputs[i]; |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
900 |
if (output->connected && output->on) { |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
901 |
output->x = x; |
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
902 |
output->y = 0; |
903 |
x += output->width; |
|
904 |
}
|
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
905 |
}
|
906 |
||
907 |
/* Second pass, all the black screens */
|
|
908 |
||
909 |
for (i = 0; app->current_configuration->outputs[i]; ++i) |
|
910 |
{
|
|
911 |
GnomeOutputInfo *output; |
|
912 |
||
913 |
output = app->current_configuration->outputs[i]; |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
914 |
if (!(output->connected && output->on)) { |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
915 |
output->x = x; |
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
916 |
output->y = 0; |
917 |
x += output->width; |
|
918 |
}
|
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
919 |
}
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
920 |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
921 |
}
|
922 |
||
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
923 |
/* FIXME: this function is copied from gnome-settings-daemon/plugins/xrandr/gsd-xrandr-manager.c.
|
924 |
* Do we need to put this function in gnome-desktop for public use?
|
|
925 |
*/
|
|
926 |
static gboolean |
|
927 |
get_clone_size (GnomeRRScreen *screen, int *width, int *height) |
|
928 |
{
|
|
929 |
GnomeRRMode **modes = gnome_rr_screen_list_clone_modes (screen); |
|
930 |
int best_w, best_h; |
|
931 |
int i; |
|
932 |
||
933 |
best_w = 0; |
|
934 |
best_h = 0; |
|
935 |
||
936 |
for (i = 0; modes[i] != NULL; ++i) { |
|
937 |
GnomeRRMode *mode = modes[i]; |
|
938 |
int w, h; |
|
939 |
||
940 |
w = gnome_rr_mode_get_width (mode); |
|
941 |
h = gnome_rr_mode_get_height (mode); |
|
942 |
||
943 |
if (w * h > best_w * best_h) { |
|
944 |
best_w = w; |
|
945 |
best_h = h; |
|
946 |
}
|
|
947 |
}
|
|
948 |
||
949 |
if (best_w > 0 && best_h > 0) { |
|
950 |
if (width) |
|
951 |
*width = best_w; |
|
952 |
if (height) |
|
953 |
*height = best_h; |
|
954 |
||
955 |
return TRUE; |
|
956 |
}
|
|
957 |
||
958 |
return FALSE; |
|
959 |
}
|
|
960 |
||
961 |
static gboolean |
|
962 |
output_info_supports_mode (App *app, GnomeOutputInfo *info, int width, int height) |
|
963 |
{
|
|
964 |
GnomeRROutput *output; |
|
965 |
GnomeRRMode **modes; |
|
966 |
int i; |
|
967 |
||
968 |
if (!info->connected) |
|
969 |
return FALSE; |
|
970 |
||
971 |
output = gnome_rr_screen_get_output_by_name (app->screen, info->name); |
|
972 |
if (!output) |
|
973 |
return FALSE; |
|
974 |
||
975 |
modes = gnome_rr_output_list_modes (output); |
|
976 |
||
977 |
for (i = 0; modes[i]; i++) { |
|
978 |
if (gnome_rr_mode_get_width (modes[i]) == width |
|
979 |
&& gnome_rr_mode_get_height (modes[i]) == height) |
|
980 |
return TRUE; |
|
981 |
}
|
|
982 |
||
983 |
return FALSE; |
|
984 |
}
|
|
985 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
986 |
static void |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
987 |
on_clone_changed (GtkWidget *box, gpointer data) |
988 |
{
|
|
989 |
App *app = data; |
|
990 |
||
991 |
app->current_configuration->clone = |
|
992 |
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (app->clone_checkbox)); |
|
993 |
||
994 |
if (app->current_configuration->clone) |
|
995 |
{
|
|
996 |
int i; |
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
997 |
int width, height; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
998 |
|
999 |
for (i = 0; app->current_configuration->outputs[i]; ++i) |
|
1000 |
{
|
|
1001 |
if (app->current_configuration->outputs[i]->connected) |
|
1002 |
{
|
|
1003 |
app->current_output = app->current_configuration->outputs[i]; |
|
1004 |
break; |
|
1005 |
}
|
|
1006 |
}
|
|
1.1.34
by Chris Coulson
Import upstream version 2.29.4 |
1007 |
|
1008 |
/* Turn on all the connected screens that support the best clone mode.
|
|
1009 |
* The user may hit "Mirror Screens", but he shouldn't have to turn on
|
|
1010 |
* all the required outputs as well.
|
|
1011 |
*/
|
|
1012 |
||
1013 |
get_clone_size (app->screen, &width, &height); |
|
1014 |
||
1015 |
for (i = 0; app->current_configuration->outputs[i]; i++) { |
|
1016 |
if (output_info_supports_mode (app, app->current_configuration->outputs[i], width, height)) { |
|
1017 |
app->current_configuration->outputs[i]->on = TRUE; |
|
1018 |
app->current_configuration->outputs[i]->width = width; |
|
1019 |
app->current_configuration->outputs[i]->height = height; |
|
1020 |
}
|
|
1021 |
}
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1022 |
}
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
1023 |
else
|
1024 |
{
|
|
1025 |
if (output_overlaps (app->current_output, app->current_configuration)) |
|
1026 |
lay_out_outputs_horizontally (app); |
|
1027 |
}
|
|
68
by Michael Vogt
* move packaging into bzr |
1028 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1029 |
rebuild_gui (app); |
1030 |
}
|
|
1031 |
||
1032 |
static void |
|
1033 |
get_geometry (GnomeOutputInfo *output, int *w, int *h) |
|
1034 |
{
|
|
1035 |
if (output->on) |
|
1036 |
{
|
|
1037 |
*h = output->height; |
|
1038 |
*w = output->width; |
|
1039 |
}
|
|
1040 |
else
|
|
1041 |
{
|
|
1042 |
*h = output->pref_height; |
|
1043 |
*w = output->pref_width; |
|
1044 |
}
|
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
1045 |
if ((output->rotation & GNOME_RR_ROTATION_90) || (output->rotation & GNOME_RR_ROTATION_270)) |
1046 |
{
|
|
1047 |
int tmp; |
|
1048 |
tmp = *h; |
|
1049 |
*h = *w; |
|
1050 |
*w = tmp; |
|
1051 |
}
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1052 |
}
|
1053 |
||
1054 |
#define SPACE 15
|
|
1055 |
#define MARGIN 15
|
|
1056 |
||
1057 |
static GList * |
|
1058 |
list_connected_outputs (App *app, int *total_w, int *total_h) |
|
1059 |
{
|
|
1060 |
int i, dummy; |
|
1061 |
GList *result = NULL; |
|
1062 |
||
1063 |
if (!total_w) |
|
1064 |
total_w = &dummy; |
|
1065 |
if (!total_h) |
|
1066 |
total_h = &dummy; |
|
1067 |
||
1068 |
*total_w = 0; |
|
1069 |
*total_h = 0; |
|
1070 |
for (i = 0; app->current_configuration->outputs[i] != NULL; ++i) |
|
1071 |
{
|
|
1072 |
GnomeOutputInfo *output = app->current_configuration->outputs[i]; |
|
1073 |
||
1074 |
if (output->connected) |
|
1075 |
{
|
|
1076 |
int w, h; |
|
68
by Michael Vogt
* move packaging into bzr |
1077 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1078 |
result = g_list_prepend (result, output); |
1079 |
||
1080 |
get_geometry (output, &w, &h); |
|
1081 |
||
1082 |
*total_w += w; |
|
1083 |
*total_h += h; |
|
1084 |
}
|
|
1085 |
}
|
|
1086 |
||
1087 |
return g_list_reverse (result); |
|
1088 |
}
|
|
1089 |
||
1090 |
static int |
|
1091 |
get_n_connected (App *app) |
|
1092 |
{
|
|
1093 |
GList *connected_outputs = list_connected_outputs (app, NULL, NULL); |
|
1094 |
int n = g_list_length (connected_outputs); |
|
1095 |
||
1096 |
g_list_free (connected_outputs); |
|
1097 |
||
1098 |
return n; |
|
1099 |
}
|
|
1100 |
||
1101 |
static double |
|
1102 |
compute_scale (App *app) |
|
1103 |
{
|
|
1104 |
int available_w, available_h; |
|
1105 |
int total_w, total_h; |
|
1106 |
int n_monitors; |
|
1107 |
GdkRectangle viewport; |
|
1108 |
GList *connected_outputs; |
|
68
by Michael Vogt
* move packaging into bzr |
1109 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1110 |
foo_scroll_area_get_viewport (FOO_SCROLL_AREA (app->area), &viewport); |
1111 |
||
1112 |
connected_outputs = list_connected_outputs (app, &total_w, &total_h); |
|
68
by Michael Vogt
* move packaging into bzr |
1113 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1114 |
n_monitors = g_list_length (connected_outputs); |
1115 |
||
1116 |
g_list_free (connected_outputs); |
|
1117 |
||
1118 |
available_w = viewport.width - 2 * MARGIN - (n_monitors - 1) * SPACE; |
|
1119 |
available_h = viewport.height - 2 * MARGIN - (n_monitors - 1) * SPACE; |
|
1120 |
||
1121 |
return MIN ((double)available_w / total_w, (double)available_h / total_h); |
|
1122 |
}
|
|
1123 |
||
1124 |
typedef struct Edge |
|
1125 |
{
|
|
1126 |
GnomeOutputInfo *output; |
|
1127 |
int x1, y1; |
|
1128 |
int x2, y2; |
|
1129 |
} Edge; |
|
1130 |
||
1131 |
typedef struct Snap |
|
1132 |
{
|
|
1133 |
Edge *snapper; /* Edge that should be snapped */ |
|
1134 |
Edge *snappee; |
|
68
by Michael Vogt
* move packaging into bzr |
1135 |
int dy, dx; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1136 |
} Snap; |
1137 |
||
1138 |
static void |
|
1139 |
add_edge (GnomeOutputInfo *output, int x1, int y1, int x2, int y2, GArray *edges) |
|
1140 |
{
|
|
1141 |
Edge e; |
|
68
by Michael Vogt
* move packaging into bzr |
1142 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1143 |
e.x1 = x1; |
1144 |
e.x2 = x2; |
|
1145 |
e.y1 = y1; |
|
1146 |
e.y2 = y2; |
|
1147 |
e.output = output; |
|
1148 |
||
1149 |
g_array_append_val (edges, e); |
|
1150 |
}
|
|
1151 |
||
1152 |
static void |
|
1153 |
list_edges_for_output (GnomeOutputInfo *output, GArray *edges) |
|
1154 |
{
|
|
1155 |
int x, y, w, h; |
|
68
by Michael Vogt
* move packaging into bzr |
1156 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1157 |
x = output->x; |
1158 |
y = output->y; |
|
1159 |
get_geometry (output, &w, &h); |
|
68
by Michael Vogt
* move packaging into bzr |
1160 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1161 |
/* Top, Bottom, Left, Right */
|
1162 |
add_edge (output, x, y, x + w, y, edges); |
|
1163 |
add_edge (output, x, y + h, x + w, y + h, edges); |
|
1164 |
add_edge (output, x, y, x, y + h, edges); |
|
1165 |
add_edge (output, x + w, y, x + w, y + h, edges); |
|
1166 |
}
|
|
1167 |
||
1168 |
static void |
|
1169 |
list_edges (GnomeRRConfig *config, GArray *edges) |
|
1170 |
{
|
|
1171 |
int i; |
|
1172 |
||
1173 |
for (i = 0; config->outputs[i]; ++i) |
|
1174 |
{
|
|
1175 |
GnomeOutputInfo *output = config->outputs[i]; |
|
1176 |
||
1177 |
if (output->connected) |
|
1178 |
list_edges_for_output (output, edges); |
|
1179 |
}
|
|
1180 |
}
|
|
1181 |
||
1182 |
static gboolean |
|
1183 |
overlap (int s1, int e1, int s2, int e2) |
|
1184 |
{
|
|
1185 |
return (!(e1 < s2 || s1 >= e2)); |
|
1186 |
}
|
|
1187 |
||
1188 |
static gboolean |
|
1189 |
horizontal_overlap (Edge *snapper, Edge *snappee) |
|
1190 |
{
|
|
1191 |
if (snapper->y1 != snapper->y2 || snappee->y1 != snappee->y2) |
|
1192 |
return FALSE; |
|
1193 |
||
1194 |
return overlap (snapper->x1, snapper->x2, snappee->x1, snappee->x2); |
|
1195 |
}
|
|
1196 |
||
1197 |
static gboolean |
|
1198 |
vertical_overlap (Edge *snapper, Edge *snappee) |
|
1199 |
{
|
|
1200 |
if (snapper->x1 != snapper->x2 || snappee->x1 != snappee->x2) |
|
1201 |
return FALSE; |
|
68
by Michael Vogt
* move packaging into bzr |
1202 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1203 |
return overlap (snapper->y1, snapper->y2, snappee->y1, snappee->y2); |
1204 |
}
|
|
1205 |
||
1206 |
static void |
|
1207 |
add_snap (GArray *snaps, Snap snap) |
|
1208 |
{
|
|
1209 |
if (ABS (snap.dx) <= 200 || ABS (snap.dy) <= 200) |
|
1210 |
g_array_append_val (snaps, snap); |
|
1211 |
}
|
|
1212 |
||
1213 |
static void |
|
1214 |
add_edge_snaps (Edge *snapper, Edge *snappee, GArray *snaps) |
|
1215 |
{
|
|
1216 |
Snap snap; |
|
1217 |
||
1218 |
snap.snapper = snapper; |
|
1219 |
snap.snappee = snappee; |
|
68
by Michael Vogt
* move packaging into bzr |
1220 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1221 |
if (horizontal_overlap (snapper, snappee)) |
1222 |
{
|
|
1223 |
snap.dx = 0; |
|
1224 |
snap.dy = snappee->y1 - snapper->y1; |
|
1225 |
||
1226 |
add_snap (snaps, snap); |
|
1227 |
}
|
|
1228 |
else if (vertical_overlap (snapper, snappee)) |
|
1229 |
{
|
|
1230 |
snap.dy = 0; |
|
1231 |
snap.dx = snappee->x1 - snapper->x1; |
|
1232 |
||
1233 |
add_snap (snaps, snap); |
|
1234 |
}
|
|
1235 |
||
1236 |
/* Corner snaps */
|
|
1237 |
/* 1->1 */
|
|
1238 |
snap.dx = snappee->x1 - snapper->x1; |
|
1239 |
snap.dy = snappee->y1 - snapper->y1; |
|
68
by Michael Vogt
* move packaging into bzr |
1240 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1241 |
add_snap (snaps, snap); |
68
by Michael Vogt
* move packaging into bzr |
1242 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1243 |
/* 1->2 */
|
1244 |
snap.dx = snappee->x2 - snapper->x1; |
|
1245 |
snap.dy = snappee->y2 - snapper->y1; |
|
1246 |
||
1247 |
add_snap (snaps, snap); |
|
1248 |
||
1249 |
/* 2->2 */
|
|
1250 |
snap.dx = snappee->x2 - snapper->x2; |
|
1251 |
snap.dy = snappee->y2 - snapper->y2; |
|
1252 |
||
1253 |
add_snap (snaps, snap); |
|
1254 |
||
1255 |
/* 2->1 */
|
|
1256 |
snap.dx = snappee->x1 - snapper->x2; |
|
1257 |
snap.dy = snappee->y1 - snapper->y2; |
|
1258 |
||
1259 |
add_snap (snaps, snap); |
|
1260 |
}
|
|
1261 |
||
1262 |
static void |
|
1263 |
list_snaps (GnomeOutputInfo *output, GArray *edges, GArray *snaps) |
|
1264 |
{
|
|
1265 |
int i; |
|
1266 |
||
1267 |
for (i = 0; i < edges->len; ++i) |
|
1268 |
{
|
|
1269 |
Edge *output_edge = &(g_array_index (edges, Edge, i)); |
|
1270 |
||
1271 |
if (output_edge->output == output) |
|
1272 |
{
|
|
1273 |
int j; |
|
68
by Michael Vogt
* move packaging into bzr |
1274 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1275 |
for (j = 0; j < edges->len; ++j) |
68
by Michael Vogt
* move packaging into bzr |
1276 |
{
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1277 |
Edge *edge = &(g_array_index (edges, Edge, j)); |
1278 |
||
1279 |
if (edge->output != output) |
|
1280 |
add_edge_snaps (output_edge, edge, snaps); |
|
1281 |
}
|
|
1282 |
}
|
|
1283 |
}
|
|
1284 |
}
|
|
1285 |
||
1286 |
#if 0
|
|
1287 |
static void
|
|
1288 |
print_edge (Edge *edge)
|
|
1289 |
{
|
|
68
by Michael Vogt
* move packaging into bzr |
1290 |
g_debug ("(%d %d %d %d)", edge->x1, edge->y1, edge->x2, edge->y2);
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1291 |
}
|
1292 |
#endif
|
|
1293 |
||
1294 |
static gboolean |
|
1295 |
corner_on_edge (int x, int y, Edge *e) |
|
1296 |
{
|
|
1297 |
if (x == e->x1 && x == e->x2 && y >= e->y1 && y <= e->y2) |
|
1298 |
return TRUE; |
|
68
by Michael Vogt
* move packaging into bzr |
1299 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1300 |
if (y == e->y1 && y == e->y2 && x >= e->x1 && x <= e->x2) |
1301 |
return TRUE; |
|
1302 |
||
1303 |
return FALSE; |
|
1304 |
}
|
|
1305 |
||
1306 |
static gboolean |
|
1307 |
edges_align (Edge *e1, Edge *e2) |
|
1308 |
{
|
|
1309 |
if (corner_on_edge (e1->x1, e1->y1, e2)) |
|
1310 |
return TRUE; |
|
1311 |
||
1312 |
if (corner_on_edge (e2->x1, e2->y1, e1)) |
|
1313 |
return TRUE; |
|
1314 |
||
1315 |
return FALSE; |
|
1316 |
}
|
|
1317 |
||
1318 |
static gboolean |
|
1319 |
output_is_aligned (GnomeOutputInfo *output, GArray *edges) |
|
1320 |
{
|
|
1321 |
gboolean result = FALSE; |
|
1322 |
int i; |
|
1323 |
||
1324 |
for (i = 0; i < edges->len; ++i) |
|
1325 |
{
|
|
1326 |
Edge *output_edge = &(g_array_index (edges, Edge, i)); |
|
1327 |
||
1328 |
if (output_edge->output == output) |
|
1329 |
{
|
|
1330 |
int j; |
|
1331 |
||
1332 |
for (j = 0; j < edges->len; ++j) |
|
1333 |
{
|
|
1334 |
Edge *edge = &(g_array_index (edges, Edge, j)); |
|
1335 |
||
1336 |
/* We are aligned if an output edge matches
|
|
1337 |
* an edge of another output
|
|
1338 |
*/
|
|
1339 |
if (edge->output != output_edge->output) |
|
1340 |
{
|
|
1341 |
if (edges_align (output_edge, edge)) |
|
1342 |
{
|
|
1343 |
result = TRUE; |
|
1344 |
goto done; |
|
1345 |
}
|
|
1346 |
}
|
|
1347 |
}
|
|
1348 |
}
|
|
1349 |
}
|
|
1350 |
done: |
|
1351 |
||
1352 |
return result; |
|
1353 |
}
|
|
1354 |
||
1355 |
static void |
|
1356 |
get_output_rect (GnomeOutputInfo *output, GdkRectangle *rect) |
|
1357 |
{
|
|
1358 |
int w, h; |
|
1359 |
||
1360 |
get_geometry (output, &w, &h); |
|
1361 |
||
1362 |
rect->width = w; |
|
1363 |
rect->height = h; |
|
1364 |
rect->x = output->x; |
|
1365 |
rect->y = output->y; |
|
1366 |
}
|
|
1367 |
||
1368 |
static gboolean |
|
1369 |
output_overlaps (GnomeOutputInfo *output, GnomeRRConfig *config) |
|
1370 |
{
|
|
1371 |
int i; |
|
1372 |
GdkRectangle output_rect; |
|
1373 |
||
1374 |
get_output_rect (output, &output_rect); |
|
1375 |
||
1376 |
for (i = 0; config->outputs[i]; ++i) |
|
1377 |
{
|
|
1378 |
GnomeOutputInfo *other = config->outputs[i]; |
|
1379 |
||
1380 |
if (other != output && other->connected) |
|
1381 |
{
|
|
1382 |
GdkRectangle other_rect; |
|
68
by Michael Vogt
* move packaging into bzr |
1383 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1384 |
get_output_rect (other, &other_rect); |
1385 |
if (gdk_rectangle_intersect (&output_rect, &other_rect, NULL)) |
|
1386 |
return TRUE; |
|
1387 |
}
|
|
1388 |
}
|
|
1389 |
||
1390 |
return FALSE; |
|
1391 |
}
|
|
1392 |
||
1393 |
static gboolean |
|
1394 |
gnome_rr_config_is_aligned (GnomeRRConfig *config, GArray *edges) |
|
1395 |
{
|
|
1396 |
int i; |
|
1397 |
gboolean result = TRUE; |
|
1398 |
||
1399 |
for (i = 0; config->outputs[i]; ++i) |
|
1400 |
{
|
|
1401 |
GnomeOutputInfo *output = config->outputs[i]; |
|
1402 |
||
1403 |
if (output->connected) |
|
1404 |
{
|
|
1405 |
if (!output_is_aligned (output, edges)) |
|
1406 |
return FALSE; |
|
1407 |
||
1408 |
if (output_overlaps (output, config)) |
|
1409 |
return FALSE; |
|
1410 |
}
|
|
1411 |
}
|
|
1412 |
||
1413 |
return result; |
|
1414 |
}
|
|
1415 |
||
1416 |
struct GrabInfo |
|
1417 |
{
|
|
1418 |
int grab_x; |
|
1419 |
int grab_y; |
|
1420 |
int output_x; |
|
1421 |
int output_y; |
|
1422 |
};
|
|
1423 |
||
1424 |
static gboolean |
|
1425 |
is_corner_snap (const Snap *s) |
|
1426 |
{
|
|
1427 |
return s->dx != 0 && s->dy != 0; |
|
1428 |
}
|
|
1429 |
||
1430 |
static int |
|
1431 |
compare_snaps (gconstpointer v1, gconstpointer v2) |
|
1432 |
{
|
|
1433 |
const Snap *s1 = v1; |
|
1434 |
const Snap *s2 = v2; |
|
1435 |
int sv1 = MAX (ABS (s1->dx), ABS (s1->dy)); |
|
1436 |
int sv2 = MAX (ABS (s2->dx), ABS (s2->dy)); |
|
1437 |
int d; |
|
1438 |
||
1439 |
d = sv1 - sv2; |
|
1440 |
||
1441 |
/* This snapping algorithm is good enough for rock'n'roll, but
|
|
1442 |
* this is probably a better:
|
|
1443 |
*
|
|
1444 |
* First do a horizontal/vertical snap, then
|
|
1445 |
* with the new coordinates from that snap,
|
|
1446 |
* do a corner snap.
|
|
1447 |
*
|
|
1448 |
* Right now, it's confusing that corner snapping
|
|
1449 |
* depends on the distance in an axis that you can't actually see.
|
|
1450 |
*
|
|
1451 |
*/
|
|
1452 |
if (d == 0) |
|
1453 |
{
|
|
1454 |
if (is_corner_snap (s1) && !is_corner_snap (s2)) |
|
1455 |
return -1; |
|
1456 |
else if (is_corner_snap (s2) && !is_corner_snap (s1)) |
|
1457 |
return 1; |
|
1458 |
else
|
|
1459 |
return 0; |
|
1460 |
}
|
|
1461 |
else
|
|
1462 |
{
|
|
1463 |
return d; |
|
1464 |
}
|
|
1465 |
}
|
|
1466 |
||
1.1.37
by Chris Coulson
Import upstream version 2.29.91 |
1467 |
/* Sets a mouse cursor for a widget's window. As a hack, you can pass
|
1468 |
* GDK_BLANK_CURSOR to mean "set the cursor to NULL" (i.e. reset the widget's
|
|
1469 |
* window's cursor to its default).
|
|
1470 |
*/
|
|
1471 |
static void |
|
1472 |
set_cursor (GtkWidget *widget, GdkCursorType type) |
|
1473 |
{
|
|
1474 |
GdkCursor *cursor; |
|
1475 |
GdkWindow *window; |
|
1476 |
||
1477 |
if (type == GDK_BLANK_CURSOR) |
|
1478 |
cursor = NULL; |
|
1479 |
else
|
|
1480 |
cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), type); |
|
1481 |
||
1482 |
window = gtk_widget_get_window (widget); |
|
1483 |
||
1484 |
if (window) |
|
1485 |
gdk_window_set_cursor (window, cursor); |
|
1486 |
||
1487 |
if (cursor) |
|
1488 |
gdk_cursor_unref (cursor); |
|
1489 |
}
|
|
1490 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1491 |
static void |
1.1.39
by Didier Roche
Import upstream version 2.30.0 |
1492 |
set_monitors_tooltip (App *app, gboolean is_dragging) |
1493 |
{
|
|
1494 |
const char *text; |
|
1495 |
||
1496 |
if (is_dragging) |
|
1497 |
text = NULL; |
|
1498 |
else
|
|
1499 |
text = _("Select a monitor to change its properties; drag it to rearrange its placement."); |
|
1500 |
||
1501 |
gtk_widget_set_tooltip_text (app->area, text); |
|
1502 |
}
|
|
1503 |
||
1504 |
static void |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1505 |
on_output_event (FooScrollArea *area, |
1506 |
FooScrollAreaEvent *event, |
|
1507 |
gpointer data) |
|
1508 |
{
|
|
1509 |
GnomeOutputInfo *output = data; |
|
1510 |
App *app = g_object_get_data (G_OBJECT (area), "app"); |
|
1511 |
||
1.1.37
by Chris Coulson
Import upstream version 2.29.91 |
1512 |
/* If the mouse is inside the outputs, set the cursor to "you can move me". See
|
1513 |
* on_canvas_event() for where we reset the cursor to the default if it
|
|
1514 |
* exits the outputs' area.
|
|
1515 |
*/
|
|
1516 |
if (!app->current_configuration->clone && get_n_connected (app) > 1) |
|
1517 |
set_cursor (GTK_WIDGET (area), GDK_FLEUR); |
|
1518 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1519 |
if (event->type == FOO_BUTTON_PRESS) |
1520 |
{
|
|
1521 |
GrabInfo *info; |
|
68
by Michael Vogt
* move packaging into bzr |
1522 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1523 |
app->current_output = output; |
1524 |
||
1525 |
rebuild_gui (app); |
|
1.1.39
by Didier Roche
Import upstream version 2.30.0 |
1526 |
set_monitors_tooltip (app, TRUE); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1527 |
|
1528 |
if (!app->current_configuration->clone && get_n_connected (app) > 1) |
|
1529 |
{
|
|
1530 |
foo_scroll_area_begin_grab (area, on_output_event, data); |
|
68
by Michael Vogt
* move packaging into bzr |
1531 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1532 |
info = g_new0 (GrabInfo, 1); |
1533 |
info->grab_x = event->x; |
|
1534 |
info->grab_y = event->y; |
|
1535 |
info->output_x = output->x; |
|
1536 |
info->output_y = output->y; |
|
68
by Michael Vogt
* move packaging into bzr |
1537 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1538 |
output->user_data = info; |
1539 |
}
|
|
68
by Michael Vogt
* move packaging into bzr |
1540 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1541 |
foo_scroll_area_invalidate (area); |
1542 |
}
|
|
1543 |
else
|
|
1544 |
{
|
|
1545 |
if (foo_scroll_area_is_grabbed (area)) |
|
1546 |
{
|
|
1547 |
GrabInfo *info = output->user_data; |
|
1548 |
double scale = compute_scale (app); |
|
1549 |
int old_x, old_y; |
|
1550 |
int new_x, new_y; |
|
1551 |
int i; |
|
1552 |
GArray *edges, *snaps, *new_edges; |
|
1553 |
||
1554 |
old_x = output->x; |
|
1555 |
old_y = output->y; |
|
1556 |
new_x = info->output_x + (event->x - info->grab_x) / scale; |
|
1557 |
new_y = info->output_y + (event->y - info->grab_y) / scale; |
|
68
by Michael Vogt
* move packaging into bzr |
1558 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1559 |
output->x = new_x; |
1560 |
output->y = new_y; |
|
1561 |
||
1562 |
edges = g_array_new (TRUE, TRUE, sizeof (Edge)); |
|
1563 |
snaps = g_array_new (TRUE, TRUE, sizeof (Snap)); |
|
1564 |
new_edges = g_array_new (TRUE, TRUE, sizeof (Edge)); |
|
68
by Michael Vogt
* move packaging into bzr |
1565 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1566 |
list_edges (app->current_configuration, edges); |
1567 |
list_snaps (output, edges, snaps); |
|
1568 |
||
1569 |
g_array_sort (snaps, compare_snaps); |
|
1570 |
||
1571 |
output->x = info->output_x; |
|
1572 |
output->y = info->output_y; |
|
68
by Michael Vogt
* move packaging into bzr |
1573 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1574 |
for (i = 0; i < snaps->len; ++i) |
1575 |
{
|
|
1576 |
Snap *snap = &(g_array_index (snaps, Snap, i)); |
|
1577 |
GArray *new_edges = g_array_new (TRUE, TRUE, sizeof (Edge)); |
|
1578 |
||
1579 |
output->x = new_x + snap->dx; |
|
1580 |
output->y = new_y + snap->dy; |
|
1581 |
||
1582 |
g_array_set_size (new_edges, 0); |
|
1583 |
list_edges (app->current_configuration, new_edges); |
|
68
by Michael Vogt
* move packaging into bzr |
1584 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1585 |
if (gnome_rr_config_is_aligned (app->current_configuration, new_edges)) |
1586 |
{
|
|
1587 |
g_array_free (new_edges, TRUE); |
|
1588 |
break; |
|
1589 |
}
|
|
1590 |
else
|
|
1591 |
{
|
|
1592 |
output->x = info->output_x; |
|
1593 |
output->y = info->output_y; |
|
1594 |
}
|
|
1595 |
}
|
|
1596 |
||
1597 |
g_array_free (new_edges, TRUE); |
|
1598 |
g_array_free (snaps, TRUE); |
|
1599 |
g_array_free (edges, TRUE); |
|
68
by Michael Vogt
* move packaging into bzr |
1600 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1601 |
if (event->type == FOO_BUTTON_RELEASE) |
1602 |
{
|
|
1603 |
foo_scroll_area_end_grab (area); |
|
1.1.39
by Didier Roche
Import upstream version 2.30.0 |
1604 |
set_monitors_tooltip (app, FALSE); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1605 |
|
1606 |
g_free (output->user_data); |
|
1607 |
output->user_data = NULL; |
|
1608 |
||
1609 |
#if 0
|
|
68
by Michael Vogt
* move packaging into bzr |
1610 |
g_debug ("new position: %d %d %d %d", output->x, output->y, output->width, output->height);
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1611 |
#endif
|
1612 |
}
|
|
1613 |
||
1614 |
foo_scroll_area_invalidate (area); |
|
1615 |
}
|
|
1616 |
}
|
|
1617 |
}
|
|
1618 |
||
1619 |
static void |
|
1620 |
on_canvas_event (FooScrollArea *area, |
|
1621 |
FooScrollAreaEvent *event, |
|
1622 |
gpointer data) |
|
1623 |
{
|
|
1.1.37
by Chris Coulson
Import upstream version 2.29.91 |
1624 |
/* If the mouse exits the outputs, reset the cursor to the default. See
|
1625 |
* on_output_event() for where we set the cursor to the movement cursor if
|
|
1626 |
* it is over one of the outputs.
|
|
1627 |
*/
|
|
1628 |
set_cursor (GTK_WIDGET (area), GDK_BLANK_CURSOR); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1629 |
}
|
1630 |
||
1631 |
static PangoLayout * |
|
1632 |
get_display_name (App *app, |
|
1633 |
GnomeOutputInfo *output) |
|
1634 |
{
|
|
1635 |
const char *text; |
|
68
by Michael Vogt
* move packaging into bzr |
1636 |
|
1.1.21
by Michael Vogt
Import upstream version 2.24.0 |
1637 |
if (app->current_configuration->clone) { |
1638 |
/* Translators: this is the feature where what you see on your laptop's
|
|
1639 |
* screen is the same as your external monitor. Here, "Mirror" is being
|
|
1640 |
* used as an adjective, not as a verb. For example, the Spanish
|
|
1641 |
* translation could be "Pantallas en Espejo", *not* "Espejar Pantallas".
|
|
1642 |
*/
|
|
1643 |
text = _("Mirror Screens"); |
|
1644 |
} else |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1645 |
text = output->display_name; |
1646 |
||
1647 |
return gtk_widget_create_pango_layout ( |
|
1648 |
GTK_WIDGET (app->area), text); |
|
1649 |
}
|
|
1650 |
||
1651 |
static void |
|
1652 |
paint_background (FooScrollArea *area, |
|
1653 |
cairo_t *cr) |
|
1654 |
{
|
|
1655 |
GdkRectangle viewport; |
|
1.1.21
by Michael Vogt
Import upstream version 2.24.0 |
1656 |
GtkWidget *widget; |
1657 |
||
1658 |
widget = GTK_WIDGET (area); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1659 |
|
1660 |
foo_scroll_area_get_viewport (area, &viewport); |
|
68
by Michael Vogt
* move packaging into bzr |
1661 |
|
1.1.21
by Michael Vogt
Import upstream version 2.24.0 |
1662 |
cairo_set_source_rgb (cr, |
1663 |
widget->style->base[GTK_STATE_SELECTED].red / 65535.0, |
|
1664 |
widget->style->base[GTK_STATE_SELECTED].green / 65535.0, |
|
1665 |
widget->style->base[GTK_STATE_SELECTED].blue / 65535.0); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1666 |
|
1667 |
cairo_rectangle (cr, |
|
1668 |
viewport.x, viewport.y, |
|
1669 |
viewport.width, viewport.height); |
|
1670 |
||
1671 |
cairo_fill_preserve (cr); |
|
1672 |
||
1673 |
foo_scroll_area_add_input_from_fill (area, cr, on_canvas_event, NULL); |
|
1674 |
||
1.1.21
by Michael Vogt
Import upstream version 2.24.0 |
1675 |
cairo_set_source_rgb (cr, |
1676 |
widget->style->dark[GTK_STATE_SELECTED].red / 65535.0, |
|
1677 |
widget->style->dark[GTK_STATE_SELECTED].green / 65535.0, |
|
1678 |
widget->style->dark[GTK_STATE_SELECTED].blue / 65535.0); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1679 |
|
1680 |
cairo_stroke (cr); |
|
1681 |
}
|
|
1682 |
||
1683 |
static void |
|
1684 |
paint_output (App *app, cairo_t *cr, int i) |
|
1685 |
{
|
|
1686 |
int w, h; |
|
1687 |
double scale = compute_scale (app); |
|
1688 |
double x, y; |
|
1689 |
int total_w, total_h; |
|
68
by Michael Vogt
* move packaging into bzr |
1690 |
GList *connected_outputs = list_connected_outputs (app, &total_w, &total_h); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1691 |
GnomeOutputInfo *output = g_list_nth (connected_outputs, i)->data; |
1692 |
PangoLayout *layout = get_display_name (app, output); |
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
1693 |
PangoRectangle ink_extent, log_extent; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1694 |
GdkRectangle viewport; |
68
by Michael Vogt
* move packaging into bzr |
1695 |
GdkColor output_color; |
1696 |
double r, g, b; |
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
1697 |
double available_w; |
1698 |
double factor; |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1699 |
|
1700 |
cairo_save (cr); |
|
68
by Michael Vogt
* move packaging into bzr |
1701 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1702 |
foo_scroll_area_get_viewport (FOO_SCROLL_AREA (app->area), &viewport); |
68
by Michael Vogt
* move packaging into bzr |
1703 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1704 |
get_geometry (output, &w, &h); |
68
by Michael Vogt
* move packaging into bzr |
1705 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1706 |
#if 0
|
68
by Michael Vogt
* move packaging into bzr |
1707 |
g_debug ("%s (%p) geometry %d %d %d", output->name, output,
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1708 |
w, h, output->rate);
|
1709 |
#endif
|
|
1710 |
||
1711 |
viewport.height -= 2 * MARGIN; |
|
1712 |
viewport.width -= 2 * MARGIN; |
|
68
by Michael Vogt
* move packaging into bzr |
1713 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1714 |
x = output->x * scale + MARGIN + (viewport.width - total_w * scale) / 2.0; |
1715 |
y = output->y * scale + MARGIN + (viewport.height - total_h * scale) / 2.0; |
|
1716 |
||
1717 |
#if 0
|
|
68
by Michael Vogt
* move packaging into bzr |
1718 |
g_debug ("scaled: %f %f", x, y);
|
1719 |
||
1720 |
g_debug ("scale: %f", scale);
|
|
1721 |
||
1722 |
g_debug ("%f %f %f %f", x, y, w * scale + 0.5, h * scale + 0.5);
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1723 |
#endif
|
1724 |
||
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
1725 |
cairo_save (cr); |
1726 |
||
1727 |
cairo_translate (cr, |
|
1728 |
x + (w * scale + 0.5) / 2, |
|
1729 |
y + (h * scale + 0.5) / 2); |
|
68
by Michael Vogt
* move packaging into bzr |
1730 |
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
1731 |
/* rotation is already applied in get_geometry */
|
68
by Michael Vogt
* move packaging into bzr |
1732 |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
1733 |
if (output->rotation & GNOME_RR_REFLECT_X) |
1734 |
cairo_scale (cr, -1, 1); |
|
68
by Michael Vogt
* move packaging into bzr |
1735 |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
1736 |
if (output->rotation & GNOME_RR_REFLECT_Y) |
1737 |
cairo_scale (cr, 1, -1); |
|
68
by Michael Vogt
* move packaging into bzr |
1738 |
|
1739 |
cairo_translate (cr, |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
1740 |
- x - (w * scale + 0.5) / 2, |
1741 |
- y - (h * scale + 0.5) / 2); |
|
68
by Michael Vogt
* move packaging into bzr |
1742 |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
1743 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1744 |
cairo_rectangle (cr, x, y, w * scale + 0.5, h * scale + 0.5); |
1745 |
cairo_clip_preserve (cr); |
|
68
by Michael Vogt
* move packaging into bzr |
1746 |
|
1747 |
gnome_rr_labeler_get_color_for_output (app->labeler, output, &output_color); |
|
1748 |
r = output_color.red / 65535.0; |
|
1749 |
g = output_color.green / 65535.0; |
|
1750 |
b = output_color.blue / 65535.0; |
|
1751 |
||
1752 |
if (!output->on) |
|
1753 |
{
|
|
1754 |
/* If the output is turned off, just darken the selected color */
|
|
1755 |
r *= 0.2; |
|
1756 |
g *= 0.2; |
|
1757 |
b *= 0.2; |
|
1758 |
}
|
|
1759 |
||
1760 |
cairo_set_source_rgba (cr, r, g, b, 1.0); |
|
1761 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1762 |
foo_scroll_area_add_input_from_fill (FOO_SCROLL_AREA (app->area), |
1763 |
cr, on_output_event, output); |
|
1764 |
cairo_fill (cr); |
|
68
by Michael Vogt
* move packaging into bzr |
1765 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1766 |
if (output == app->current_output) |
1767 |
{
|
|
1768 |
cairo_rectangle (cr, x + 2, y + 2, w * scale + 0.5 - 4, h * scale + 0.5 - 4); |
|
68
by Michael Vogt
* move packaging into bzr |
1769 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1770 |
cairo_set_line_width (cr, 4); |
1771 |
cairo_set_source_rgba (cr, 0.33, 0.43, 0.57, 1.0); |
|
1772 |
cairo_stroke (cr); |
|
1773 |
}
|
|
68
by Michael Vogt
* move packaging into bzr |
1774 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1775 |
cairo_rectangle (cr, x + 0.5, y + 0.5, w * scale + 0.5 - 1, h * scale + 0.5 - 1); |
68
by Michael Vogt
* move packaging into bzr |
1776 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1777 |
cairo_set_line_width (cr, 1); |
1778 |
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); |
|
1779 |
||
1780 |
cairo_stroke (cr); |
|
1781 |
cairo_set_line_width (cr, 2); |
|
1782 |
||
1783 |
layout_set_font (layout, "Sans Bold 12"); |
|
1.1.31
by Chris Coulson
Import upstream version 2.27.91 |
1784 |
pango_layout_get_pixel_extents (layout, &ink_extent, &log_extent); |
1785 |
||
1786 |
available_w = w * scale + 0.5 - 6; /* Same as the inner rectangle's width, minus 1 pixel of padding on each side */ |
|
1787 |
if (available_w < ink_extent.width) |
|
1788 |
factor = available_w / ink_extent.width; |
|
1789 |
else
|
|
1790 |
factor = 1.0; |
|
1791 |
||
1792 |
cairo_move_to (cr, |
|
1793 |
x + ((w * scale + 0.5) - factor * log_extent.width) / 2, |
|
1794 |
y + ((h * scale + 0.5) - factor * log_extent.height) / 2); |
|
1795 |
||
1796 |
cairo_scale (cr, factor, factor); |
|
68
by Michael Vogt
* move packaging into bzr |
1797 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1798 |
if (output->on) |
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
1799 |
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1800 |
else
|
1801 |
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); |
|
68
by Michael Vogt
* move packaging into bzr |
1802 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1803 |
pango_cairo_show_layout (cr, layout); |
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
1804 |
|
1805 |
cairo_restore (cr); |
|
68
by Michael Vogt
* move packaging into bzr |
1806 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1807 |
g_object_unref (layout); |
1808 |
}
|
|
1809 |
||
1810 |
static void |
|
1811 |
on_area_paint (FooScrollArea *area, |
|
1812 |
cairo_t *cr, |
|
1813 |
GdkRectangle *extent, |
|
1814 |
GdkRegion *region, |
|
1815 |
gpointer data) |
|
1816 |
{
|
|
1817 |
App *app = data; |
|
1818 |
double scale; |
|
1819 |
GList *connected_outputs = NULL; |
|
1820 |
GList *list; |
|
1821 |
||
1822 |
paint_background (area, cr); |
|
68
by Michael Vogt
* move packaging into bzr |
1823 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1824 |
if (!app->current_configuration) |
1825 |
return; |
|
68
by Michael Vogt
* move packaging into bzr |
1826 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1827 |
scale = compute_scale (app); |
1828 |
connected_outputs = list_connected_outputs (app, NULL, NULL); |
|
68
by Michael Vogt
* move packaging into bzr |
1829 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1830 |
#if 0
|
68
by Michael Vogt
* move packaging into bzr |
1831 |
g_debug ("scale: %f", scale);
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1832 |
#endif
|
68
by Michael Vogt
* move packaging into bzr |
1833 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1834 |
for (list = connected_outputs; list != NULL; list = list->next) |
1835 |
{
|
|
1836 |
paint_output (app, cr, g_list_position (connected_outputs, list)); |
|
1837 |
||
1838 |
if (app->current_configuration->clone) |
|
1839 |
break; |
|
1840 |
}
|
|
1841 |
}
|
|
1842 |
||
1843 |
static void |
|
1844 |
make_text_combo (GtkWidget *widget, int sort_column) |
|
1845 |
{
|
|
1846 |
GtkComboBox *box = GTK_COMBO_BOX (widget); |
|
1847 |
GtkListStore *store = gtk_list_store_new ( |
|
1848 |
6, |
|
1849 |
G_TYPE_STRING, /* Text */ |
|
68
by Michael Vogt
* move packaging into bzr |
1850 |
G_TYPE_INT, /* Width */ |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1851 |
G_TYPE_INT, /* Height */ |
1852 |
G_TYPE_INT, /* Frequency */ |
|
1853 |
G_TYPE_INT, /* Width * Height */ |
|
1854 |
G_TYPE_INT); /* Rotation */ |
|
68
by Michael Vogt
* move packaging into bzr |
1855 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1856 |
GtkCellRenderer *cell; |
1857 |
||
1858 |
gtk_cell_layout_clear (GTK_CELL_LAYOUT (widget)); |
|
68
by Michael Vogt
* move packaging into bzr |
1859 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1860 |
gtk_combo_box_set_model (box, GTK_TREE_MODEL (store)); |
1861 |
||
1862 |
cell = gtk_cell_renderer_text_new (); |
|
1863 |
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, TRUE); |
|
1864 |
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (box), cell, |
|
1865 |
"text", 0, |
|
1866 |
NULL); |
|
1867 |
||
1868 |
if (sort_column != -1) |
|
1869 |
{
|
|
1870 |
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), |
|
1871 |
sort_column, |
|
1872 |
GTK_SORT_DESCENDING); |
|
1873 |
}
|
|
1874 |
}
|
|
1875 |
||
1876 |
static void |
|
1877 |
compute_virtual_size_for_configuration (GnomeRRConfig *config, int *ret_width, int *ret_height) |
|
1878 |
{
|
|
1879 |
int i; |
|
1880 |
int width, height; |
|
1881 |
||
1882 |
width = height = 0; |
|
1883 |
||
1884 |
for (i = 0; config->outputs[i] != NULL; i++) |
|
1885 |
{
|
|
1886 |
GnomeOutputInfo *output; |
|
1887 |
||
1888 |
output = config->outputs[i]; |
|
1889 |
||
1890 |
if (output->on) |
|
1891 |
{
|
|
1892 |
width = MAX (width, output->x + output->width); |
|
1893 |
height = MAX (height, output->y + output->height); |
|
1894 |
}
|
|
1895 |
}
|
|
1896 |
||
1897 |
*ret_width = width; |
|
1898 |
*ret_height = height; |
|
1899 |
}
|
|
1900 |
||
1901 |
static void |
|
1902 |
check_required_virtual_size (App *app) |
|
1903 |
{
|
|
1904 |
int req_width, req_height; |
|
1905 |
int min_width, max_width; |
|
1906 |
int min_height, max_height; |
|
1907 |
||
1908 |
compute_virtual_size_for_configuration (app->current_configuration, &req_width, &req_height); |
|
1909 |
||
1910 |
gnome_rr_screen_get_ranges (app->screen, &min_width, &max_width, &min_height, &max_height); |
|
1911 |
||
1912 |
#if 0
|
|
68
by Michael Vogt
* move packaging into bzr |
1913 |
g_debug ("X Server supports:");
|
1914 |
g_debug ("min_width = %d, max_width = %d", min_width, max_width);
|
|
1915 |
g_debug ("min_height = %d, max_height = %d", min_height, max_height);
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1916 |
|
68
by Michael Vogt
* move packaging into bzr |
1917 |
g_debug ("Requesting size of %dx%d", req_width, req_height);
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1918 |
#endif
|
1919 |
||
1920 |
if (!(min_width <= req_width && req_width <= max_width |
|
1921 |
&& min_height <= req_height && req_height <= max_height)) |
|
1922 |
{
|
|
1923 |
/* FIXME: present a useful dialog, maybe even before the user tries to Apply */
|
|
1924 |
#if 0
|
|
68
by Michael Vogt
* move packaging into bzr |
1925 |
g_debug ("Your X server needs a larger Virtual size!");
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
1926 |
#endif
|
1927 |
}
|
|
1928 |
}
|
|
1929 |
||
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
1930 |
static void |
1931 |
begin_version2_apply_configuration (App *app, GdkWindow *parent_window, guint32 timestamp) |
|
1932 |
{
|
|
1933 |
XID parent_window_xid; |
|
1934 |
||
1935 |
parent_window_xid = GDK_WINDOW_XID (parent_window); |
|
1936 |
||
1937 |
app->proxy = dbus_g_proxy_new_for_name (app->connection, |
|
1938 |
"org.gnome.SettingsDaemon", |
|
1939 |
"/org/gnome/SettingsDaemon/XRANDR", |
|
1940 |
"org.gnome.SettingsDaemon.XRANDR_2"); |
|
1941 |
g_assert (app->proxy != NULL); /* that call does not fail unless we pass bogus names */ |
|
1942 |
||
1943 |
app->apply_configuration_state = APPLYING_VERSION_2; |
|
1944 |
app->proxy_call = dbus_g_proxy_begin_call (app->proxy, "ApplyConfiguration", |
|
1945 |
apply_configuration_returned_cb, app, |
|
1946 |
NULL, |
|
1947 |
G_TYPE_INT64, (gint64) parent_window_xid, |
|
1948 |
G_TYPE_INT64, (gint64) timestamp, |
|
1949 |
G_TYPE_INVALID, |
|
1950 |
G_TYPE_INVALID); |
|
1951 |
/* FIXME: we don't check for app->proxy_call == NULL, which could happen if
|
|
1952 |
* the connection was disconnected. This is left as an exercise for the
|
|
1953 |
* reader.
|
|
1954 |
*/
|
|
1955 |
}
|
|
1956 |
||
1957 |
static void |
|
1958 |
begin_version1_apply_configuration (App *app) |
|
1959 |
{
|
|
1960 |
app->proxy = dbus_g_proxy_new_for_name (app->connection, |
|
1961 |
"org.gnome.SettingsDaemon", |
|
1962 |
"/org/gnome/SettingsDaemon/XRANDR", |
|
1963 |
"org.gnome.SettingsDaemon.XRANDR"); |
|
1964 |
g_assert (app->proxy != NULL); /* that call does not fail unless we pass bogus names */ |
|
1965 |
||
1966 |
app->apply_configuration_state = APPLYING_VERSION_1; |
|
1967 |
app->proxy_call = dbus_g_proxy_begin_call (app->proxy, "ApplyConfiguration", |
|
1968 |
apply_configuration_returned_cb, app, |
|
1969 |
NULL, |
|
1970 |
G_TYPE_INVALID, |
|
1971 |
G_TYPE_INVALID); |
|
1972 |
/* FIXME: we don't check for app->proxy_call == NULL, which could happen if
|
|
1973 |
* the connection was disconnected. This is left as an exercise for the
|
|
1974 |
* reader.
|
|
1975 |
*/
|
|
1976 |
}
|
|
1977 |
||
1978 |
static void |
|
1979 |
ensure_current_configuration_is_saved (void) |
|
1980 |
{
|
|
1981 |
GnomeRRScreen *rr_screen; |
|
1982 |
GnomeRRConfig *rr_config; |
|
1983 |
||
1984 |
/* Normally, gnome_rr_config_save() creates a backup file based on the
|
|
1985 |
* old monitors.xml. However, if *that* file didn't exist, there is
|
|
1986 |
* nothing from which to create a backup. So, here we'll save the
|
|
1987 |
* current/unchanged configuration and then let our caller call
|
|
1988 |
* gnome_rr_config_save() again with the new/changed configuration, so
|
|
1989 |
* that there *will* be a backup file in the end.
|
|
1990 |
*/
|
|
1991 |
||
1992 |
rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), NULL, NULL, NULL); /* NULL-GError */ |
|
1993 |
if (!rr_screen) |
|
1994 |
return; |
|
1995 |
||
1996 |
rr_config = gnome_rr_config_new_current (rr_screen); |
|
1997 |
gnome_rr_config_save (rr_config, NULL); /* NULL-GError */ |
|
1998 |
||
1999 |
gnome_rr_config_free (rr_config); |
|
2000 |
gnome_rr_screen_destroy (rr_screen); |
|
2001 |
}
|
|
2002 |
||
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
2003 |
/* Callback for dbus_g_proxy_begin_call() */
|
2004 |
static void |
|
2005 |
apply_configuration_returned_cb (DBusGProxy *proxy, |
|
2006 |
DBusGProxyCall *call_id, |
|
2007 |
void *data) |
|
2008 |
{
|
|
2009 |
App *app = data; |
|
2010 |
gboolean success; |
|
2011 |
GError *error; |
|
2012 |
||
2013 |
g_assert (call_id == app->proxy_call); |
|
2014 |
||
2015 |
error = NULL; |
|
2016 |
success = dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); |
|
2017 |
||
2018 |
if (!success) { |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
2019 |
if (app->apply_configuration_state == APPLYING_VERSION_2 |
2020 |
&& g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD)) { |
|
2021 |
g_error_free (error); |
|
2022 |
||
2023 |
g_object_unref (app->proxy); |
|
2024 |
app->proxy = NULL; |
|
2025 |
||
2026 |
begin_version1_apply_configuration (app); |
|
2027 |
return; |
|
2028 |
} else { |
|
2029 |
/* We don't pop up an error message; gnome-settings-daemon already does that
|
|
2030 |
* in case the selected RANDR configuration could not be applied.
|
|
2031 |
*/
|
|
2032 |
g_error_free (error); |
|
2033 |
}
|
|
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
2034 |
}
|
2035 |
||
2036 |
g_object_unref (app->proxy); |
|
2037 |
app->proxy = NULL; |
|
2038 |
||
2039 |
dbus_g_connection_unref (app->connection); |
|
2040 |
app->connection = NULL; |
|
2041 |
app->proxy_call = NULL; |
|
2042 |
||
2043 |
gtk_widget_set_sensitive (app->dialog, TRUE); |
|
2044 |
}
|
|
2045 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2046 |
static void |
2047 |
apply (App *app) |
|
2048 |
{
|
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2049 |
GError *error = NULL; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2050 |
|
2051 |
gnome_rr_config_sanitize (app->current_configuration); |
|
2052 |
||
2053 |
check_required_virtual_size (app); |
|
2054 |
||
2055 |
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area)); |
|
68
by Michael Vogt
* move packaging into bzr |
2056 |
|
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
2057 |
ensure_current_configuration_is_saved (); |
2058 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2059 |
if (!gnome_rr_config_save (app->current_configuration, &error)) |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2060 |
{
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2061 |
error_message (app, _("Could not save the monitor configuration"), error->message); |
2062 |
g_error_free (error); |
|
2063 |
return; |
|
2064 |
}
|
|
2065 |
||
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
2066 |
g_assert (app->connection == NULL); |
2067 |
g_assert (app->proxy == NULL); |
|
2068 |
g_assert (app->proxy_call == NULL); |
|
2069 |
||
2070 |
app->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); |
|
2071 |
if (app->connection == NULL) { |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2072 |
error_message (app, _("Could not get session bus while applying display configuration"), error->message); |
2073 |
g_error_free (error); |
|
2074 |
return; |
|
2075 |
}
|
|
2076 |
||
1.1.26
by Sebastien Bacher
Import upstream version 2.25.92 |
2077 |
gtk_widget_set_sensitive (app->dialog, FALSE); |
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
2078 |
|
2079 |
begin_version2_apply_configuration (app, gtk_widget_get_window (app->dialog), app->apply_button_clicked_timestamp); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2080 |
}
|
2081 |
||
1.1.23
by Michael Vogt
Import upstream version 2.25.2 |
2082 |
#if 0
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2083 |
/* Returns whether the graphics driver doesn't advertise RANDR 1.2 features, and just 1.0 */
|
2084 |
static gboolean
|
|
2085 |
driver_is_randr_10 (GnomeRRConfig *config)
|
|
2086 |
{
|
|
2087 |
/* In the Xorg code, see xserver/randr/rrinfo.c:RRScanOldConfig(). It gets
|
|
2088 |
* called when the graphics driver doesn't support RANDR 1.2 yet, just 1.0.
|
|
2089 |
* In that case, the X server's base code (which supports RANDR 1.2) will
|
|
2090 |
* simulate having a single output called "default". For drivers that *do*
|
|
2091 |
* support RANDR 1.2, the separate outputs will be named differently, we
|
|
2092 |
* hope.
|
|
2093 |
*
|
|
2094 |
* This heuristic is courtesy of Dirk Mueller <dmueller@suse.de>
|
|
2095 |
*
|
|
2096 |
* FIXME: however, we don't even check for XRRQueryVersion() returning 1.2, neither
|
|
2097 |
* here nor in gnome-desktop/libgnomedesktop*.c. Do we need to check for that,
|
|
2098 |
* or is gnome_rr_screen_new()'s return value sufficient?
|
|
2099 |
*/
|
|
2100 |
||
2101 |
return (count_all_outputs (config) == 1 && strcmp (config->outputs[0]->name, "default") == 0);
|
|
2102 |
}
|
|
1.1.23
by Michael Vogt
Import upstream version 2.25.2 |
2103 |
#endif
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2104 |
|
2105 |
static void |
|
2106 |
on_detect_displays (GtkWidget *widget, gpointer data) |
|
2107 |
{
|
|
2108 |
App *app = data; |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2109 |
GError *error; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2110 |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2111 |
error = NULL; |
2112 |
if (!gnome_rr_screen_refresh (app->screen, &error)) { |
|
2113 |
if (error) { |
|
2114 |
error_message (app, _("Could not detect displays"), error->message); |
|
2115 |
g_error_free (error); |
|
2116 |
}
|
|
2117 |
}
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2118 |
}
|
2119 |
||
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2120 |
#define SHOW_ICON_KEY "/apps/gnome_settings_daemon/xrandr/show_notification_icon"
|
2121 |
||
2122 |
||
2123 |
static void |
|
2124 |
on_show_icon_toggled (GtkWidget *widget, gpointer data) |
|
2125 |
{
|
|
2126 |
GtkToggleButton *tb = GTK_TOGGLE_BUTTON (widget); |
|
2127 |
App *app = data; |
|
68
by Michael Vogt
* move packaging into bzr |
2128 |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2129 |
gconf_client_set_bool (app->client, SHOW_ICON_KEY, |
2130 |
gtk_toggle_button_get_active (tb), NULL); |
|
2131 |
}
|
|
2132 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2133 |
static GnomeOutputInfo * |
2134 |
get_nearest_output (GnomeRRConfig *configuration, int x, int y) |
|
2135 |
{
|
|
2136 |
int i; |
|
2137 |
int nearest_index; |
|
2138 |
int nearest_dist; |
|
2139 |
||
2140 |
nearest_index = -1; |
|
2141 |
nearest_dist = G_MAXINT; |
|
2142 |
||
2143 |
for (i = 0; configuration->outputs[i] != NULL; i++) |
|
2144 |
{
|
|
2145 |
GnomeOutputInfo *output; |
|
2146 |
int dist_x, dist_y; |
|
2147 |
||
2148 |
output = configuration->outputs[i]; |
|
2149 |
||
2150 |
if (!(output->connected && output->on)) |
|
2151 |
continue; |
|
2152 |
||
2153 |
if (x < output->x) |
|
2154 |
dist_x = output->x - x; |
|
2155 |
else if (x >= output->x + output->width) |
|
2156 |
dist_x = x - (output->x + output->width) + 1; |
|
2157 |
else
|
|
2158 |
dist_x = 0; |
|
2159 |
||
2160 |
if (y < output->y) |
|
2161 |
dist_y = output->y - y; |
|
2162 |
else if (y >= output->y + output->height) |
|
2163 |
dist_y = y - (output->y + output->height) + 1; |
|
2164 |
else
|
|
2165 |
dist_y = 0; |
|
2166 |
||
2167 |
if (MIN (dist_x, dist_y) < nearest_dist) |
|
2168 |
{
|
|
2169 |
nearest_dist = MIN (dist_x, dist_y); |
|
2170 |
nearest_index = i; |
|
2171 |
}
|
|
2172 |
}
|
|
2173 |
||
2174 |
if (nearest_index != -1) |
|
2175 |
return configuration->outputs[nearest_index]; |
|
2176 |
else
|
|
2177 |
return NULL; |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
2178 |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2179 |
}
|
2180 |
||
2181 |
/* Gets the output that contains the largest intersection with the window.
|
|
2182 |
* Logic stolen from gdk_screen_get_monitor_at_window().
|
|
2183 |
*/
|
|
2184 |
static GnomeOutputInfo * |
|
2185 |
get_output_for_window (GnomeRRConfig *configuration, GdkWindow *window) |
|
2186 |
{
|
|
2187 |
GdkRectangle win_rect; |
|
2188 |
int i; |
|
2189 |
int largest_area; |
|
2190 |
int largest_index; |
|
2191 |
||
2192 |
gdk_window_get_geometry (window, &win_rect.x, &win_rect.y, &win_rect.width, &win_rect.height, NULL); |
|
2193 |
gdk_window_get_origin (window, &win_rect.x, &win_rect.y); |
|
2194 |
||
2195 |
largest_area = 0; |
|
2196 |
largest_index = -1; |
|
2197 |
||
2198 |
for (i = 0; configuration->outputs[i] != NULL; i++) |
|
2199 |
{
|
|
2200 |
GnomeOutputInfo *output; |
|
2201 |
GdkRectangle output_rect, intersection; |
|
2202 |
||
2203 |
output = configuration->outputs[i]; |
|
2204 |
||
2205 |
output_rect.x = output->x; |
|
2206 |
output_rect.y = output->y; |
|
2207 |
output_rect.width = output->width; |
|
2208 |
output_rect.height = output->height; |
|
2209 |
||
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
2210 |
if (output->connected && gdk_rectangle_intersect (&win_rect, &output_rect, &intersection)) |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2211 |
{
|
2212 |
int area; |
|
2213 |
||
2214 |
area = intersection.width * intersection.height; |
|
2215 |
if (area > largest_area) |
|
2216 |
{
|
|
2217 |
largest_area = area; |
|
2218 |
largest_index = i; |
|
2219 |
}
|
|
2220 |
}
|
|
2221 |
}
|
|
2222 |
||
2223 |
if (largest_index != -1) |
|
2224 |
return configuration->outputs[largest_index]; |
|
2225 |
else
|
|
2226 |
return get_nearest_output (configuration, |
|
2227 |
win_rect.x + win_rect.width / 2, |
|
2228 |
win_rect.y + win_rect.height / 2); |
|
2229 |
}
|
|
2230 |
||
2231 |
/* We select the current output, i.e. select the one being edited, based on
|
|
2232 |
* which output is showing the configuration dialog.
|
|
2233 |
*/
|
|
2234 |
static void |
|
2235 |
select_current_output_from_dialog_position (App *app) |
|
2236 |
{
|
|
2237 |
if (GTK_WIDGET_REALIZED (app->dialog)) |
|
1.1.27
by Didier Roche
Import upstream version 2.26.0 |
2238 |
app->current_output = get_output_for_window (app->current_configuration, app->dialog->window); |
2239 |
else
|
|
2240 |
app->current_output = NULL; |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2241 |
|
2242 |
rebuild_gui (app); |
|
2243 |
}
|
|
2244 |
||
2245 |
/* This is a GtkWidget::map-event handler. We wait for the display-properties
|
|
2246 |
* dialog to be mapped, and then we select the output which corresponds to the
|
|
2247 |
* monitor on which the dialog is being shown.
|
|
2248 |
*/
|
|
2249 |
static gboolean |
|
2250 |
dialog_map_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer data) |
|
2251 |
{
|
|
2252 |
App *app = data; |
|
2253 |
||
2254 |
select_current_output_from_dialog_position (app); |
|
2255 |
return FALSE; |
|
2256 |
}
|
|
2257 |
||
2258 |
static void |
|
2259 |
hide_help_button (App *app) |
|
2260 |
{
|
|
2261 |
GtkWidget *action_area; |
|
2262 |
GList *children; |
|
2263 |
GList *l; |
|
2264 |
||
2265 |
action_area = gtk_dialog_get_action_area (GTK_DIALOG (app->dialog)); |
|
2266 |
children = gtk_container_get_children (GTK_CONTAINER (action_area)); |
|
2267 |
||
2268 |
for (l = children; l; l = l->next) |
|
2269 |
{
|
|
2270 |
GtkWidget *child; |
|
2271 |
int response; |
|
2272 |
||
2273 |
child = GTK_WIDGET (l->data); |
|
2274 |
||
2275 |
response = gtk_dialog_get_response_for_widget (GTK_DIALOG (app->dialog), child); |
|
2276 |
if (response == GTK_RESPONSE_HELP) |
|
2277 |
{
|
|
2278 |
gtk_widget_hide (child); |
|
2279 |
return; |
|
2280 |
}
|
|
2281 |
}
|
|
2282 |
}
|
|
2283 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2284 |
static void |
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
2285 |
apply_button_clicked_cb (GtkButton *button, gpointer data) |
2286 |
{
|
|
2287 |
App *app = data; |
|
2288 |
||
2289 |
/* We simply store the timestamp at which the Apply button was clicked.
|
|
2290 |
* We'll just wait for the dialog to return from gtk_dialog_run(), and
|
|
2291 |
* *then* use the timestamp when applying the RANDR configuration.
|
|
2292 |
*/
|
|
2293 |
||
2294 |
app->apply_button_clicked_timestamp = gtk_get_current_event_time (); |
|
2295 |
}
|
|
2296 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2297 |
static GtkWidget* |
2298 |
_gtk_builder_get_widget (GtkBuilder *builder, const gchar *name) |
|
2299 |
{
|
|
2300 |
return GTK_WIDGET (gtk_builder_get_object (builder, name)); |
|
2301 |
}
|
|
2302 |
||
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
2303 |
static void |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2304 |
run_application (App *app) |
2305 |
{
|
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2306 |
#ifndef UIDIR
|
2307 |
#define UIDIR "."
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2308 |
#endif
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2309 |
#define UI_FILE UIDIR "/display-capplet.ui"
|
2310 |
GtkBuilder *builder; |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2311 |
GtkWidget *align; |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2312 |
GError *error; |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2313 |
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2314 |
error = NULL; |
2315 |
builder = gtk_builder_new (); |
|
2316 |
||
2317 |
if (gtk_builder_add_from_file (builder, UI_FILE, &error) == 0) |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2318 |
{
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2319 |
g_warning ("Could not parse UI definition: %s", error->message); |
2320 |
g_error_free (error); |
|
2321 |
g_object_unref (builder); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2322 |
return; |
2323 |
}
|
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2324 |
|
68
by Michael Vogt
* move packaging into bzr |
2325 |
app->screen = gnome_rr_screen_new (gdk_screen_get_default (), |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2326 |
on_screen_changed, app, &error); |
68
by Michael Vogt
* move packaging into bzr |
2327 |
if (!app->screen) |
2328 |
{
|
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2329 |
error_message (NULL, _("Could not get screen information"), error->message); |
2330 |
g_error_free (error); |
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2331 |
g_object_unref (builder); |
68
by Michael Vogt
* move packaging into bzr |
2332 |
return; |
2333 |
}
|
|
2334 |
||
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2335 |
app->client = gconf_client_get_default (); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2336 |
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2337 |
app->dialog = _gtk_builder_get_widget (builder, "dialog"); |
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2338 |
g_signal_connect_after (app->dialog, "map-event", |
2339 |
G_CALLBACK (dialog_map_event_cb), app); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2340 |
|
2341 |
gtk_window_set_default_icon_name ("gnome-display-properties"); |
|
2342 |
gtk_window_set_icon_name (GTK_WINDOW (app->dialog), |
|
2343 |
"gnome-display-properties"); |
|
2344 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2345 |
app->current_monitor_event_box = _gtk_builder_get_widget (builder, |
2346 |
"current_monitor_event_box"); |
|
2347 |
app->current_monitor_label = _gtk_builder_get_widget (builder, |
|
2348 |
"current_monitor_label"); |
|
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2349 |
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2350 |
app->monitor_on_radio = _gtk_builder_get_widget (builder, |
2351 |
"monitor_on_radio"); |
|
2352 |
app->monitor_off_radio = _gtk_builder_get_widget (builder, |
|
2353 |
"monitor_off_radio"); |
|
1.1.25
by Sebastien Bacher
Import upstream version 2.25.90 |
2354 |
g_signal_connect (app->monitor_on_radio, "toggled", |
2355 |
G_CALLBACK (monitor_on_off_toggled_cb), app); |
|
2356 |
g_signal_connect (app->monitor_off_radio, "toggled", |
|
2357 |
G_CALLBACK (monitor_on_off_toggled_cb), app); |
|
2358 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2359 |
app->resolution_combo = _gtk_builder_get_widget (builder, |
2360 |
"resolution_combo"); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2361 |
g_signal_connect (app->resolution_combo, "changed", |
2362 |
G_CALLBACK (on_resolution_changed), app); |
|
2363 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2364 |
app->refresh_combo = _gtk_builder_get_widget (builder, "refresh_combo"); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2365 |
g_signal_connect (app->refresh_combo, "changed", |
2366 |
G_CALLBACK (on_rate_changed), app); |
|
2367 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2368 |
app->rotation_combo = _gtk_builder_get_widget (builder, "rotation_combo"); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2369 |
g_signal_connect (app->rotation_combo, "changed", |
2370 |
G_CALLBACK (on_rotation_changed), app); |
|
2371 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2372 |
app->clone_checkbox = _gtk_builder_get_widget (builder, "clone_checkbox"); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2373 |
g_signal_connect (app->clone_checkbox, "toggled", |
2374 |
G_CALLBACK (on_clone_changed), app); |
|
2375 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2376 |
g_signal_connect (_gtk_builder_get_widget (builder, "detect_displays_button"), |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2377 |
"clicked", G_CALLBACK (on_detect_displays), app); |
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2378 |
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2379 |
app->show_icon_checkbox = _gtk_builder_get_widget (builder, |
2380 |
"show_notification_icon"); |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2381 |
|
2382 |
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (app->show_icon_checkbox), |
|
2383 |
gconf_client_get_bool (app->client, SHOW_ICON_KEY, NULL)); |
|
68
by Michael Vogt
* move packaging into bzr |
2384 |
|
1.1.19
by Sebastien Bacher
Import upstream version 2.23.6 |
2385 |
g_signal_connect (app->show_icon_checkbox, "toggled", G_CALLBACK (on_show_icon_toggled), app); |
68
by Michael Vogt
* move packaging into bzr |
2386 |
|
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2387 |
app->panel_checkbox = _gtk_builder_get_widget (builder, "panel_checkbox"); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2388 |
|
2389 |
make_text_combo (app->resolution_combo, 4); |
|
2390 |
make_text_combo (app->refresh_combo, 3); |
|
2391 |
make_text_combo (app->rotation_combo, -1); |
|
68
by Michael Vogt
* move packaging into bzr |
2392 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2393 |
g_assert (app->panel_checkbox); |
68
by Michael Vogt
* move packaging into bzr |
2394 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2395 |
/* Scroll Area */
|
2396 |
app->area = (GtkWidget *)foo_scroll_area_new (); |
|
2397 |
||
2398 |
g_object_set_data (G_OBJECT (app->area), "app", app); |
|
68
by Michael Vogt
* move packaging into bzr |
2399 |
|
1.1.39
by Didier Roche
Import upstream version 2.30.0 |
2400 |
set_monitors_tooltip (app, FALSE); |
1.1.37
by Chris Coulson
Import upstream version 2.29.91 |
2401 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2402 |
/* FIXME: this should be computed dynamically */
|
2403 |
foo_scroll_area_set_min_size (FOO_SCROLL_AREA (app->area), -1, 200); |
|
2404 |
gtk_widget_show (app->area); |
|
2405 |
g_signal_connect (app->area, "paint", |
|
2406 |
G_CALLBACK (on_area_paint), app); |
|
2407 |
g_signal_connect (app->area, "viewport_changed", |
|
2408 |
G_CALLBACK (on_viewport_changed), app); |
|
2409 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2410 |
align = _gtk_builder_get_widget (builder, "align"); |
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2411 |
|
2412 |
gtk_container_add (GTK_CONTAINER (align), app->area); |
|
2413 |
||
1.1.24
by Didier Roche
Import upstream version 2.25.3 |
2414 |
/* Until we have help to show, we'll just hide the Help button */
|
2415 |
hide_help_button (app); |
|
2416 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2417 |
app->apply_button = _gtk_builder_get_widget (builder, "apply_button"); |
1.1.28
by Chris Coulson
Import upstream version 2.27.3 |
2418 |
g_signal_connect (app->apply_button, "clicked", |
2419 |
G_CALLBACK (apply_button_clicked_cb), app); |
|
2420 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2421 |
on_screen_changed (app->screen, app); |
2422 |
||
1.1.29
by Chris Coulson
Import upstream version 2.27.4.1 |
2423 |
g_object_unref (builder); |
68
by Michael Vogt
* move packaging into bzr |
2424 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2425 |
restart: |
2426 |
switch (gtk_dialog_run (GTK_DIALOG (app->dialog))) |
|
2427 |
{
|
|
2428 |
default: |
|
2429 |
/* Fall Through */
|
|
2430 |
case GTK_RESPONSE_DELETE_EVENT: |
|
2431 |
case GTK_RESPONSE_CLOSE: |
|
68
by Michael Vogt
* move packaging into bzr |
2432 |
#if 0
|
2433 |
g_debug ("Close");
|
|
2434 |
#endif
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2435 |
break; |
2436 |
||
2437 |
case GTK_RESPONSE_HELP: |
|
68
by Michael Vogt
* move packaging into bzr |
2438 |
#if 0
|
2439 |
g_debug ("Help");
|
|
2440 |
#endif
|
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2441 |
goto restart; |
2442 |
break; |
|
2443 |
||
2444 |
case GTK_RESPONSE_APPLY: |
|
2445 |
apply (app); |
|
2446 |
goto restart; |
|
2447 |
break; |
|
2448 |
}
|
|
2449 |
||
2450 |
gtk_widget_destroy (app->dialog); |
|
68
by Michael Vogt
* move packaging into bzr |
2451 |
gnome_rr_screen_destroy (app->screen); |
2452 |
g_object_unref (app->client); |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2453 |
}
|
2454 |
||
2455 |
int
|
|
2456 |
main (int argc, char **argv) |
|
2457 |
{
|
|
2458 |
App *app; |
|
68
by Michael Vogt
* move packaging into bzr |
2459 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2460 |
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); |
2461 |
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
|
2462 |
textdomain (GETTEXT_PACKAGE); |
|
68
by Michael Vogt
* move packaging into bzr |
2463 |
|
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2464 |
gtk_init (&argc, &argv); |
2465 |
||
2466 |
app = g_new0 (App, 1); |
|
2467 |
||
2468 |
run_application (app); |
|
68
by Michael Vogt
* move packaging into bzr |
2469 |
|
2470 |
g_free (app); |
|
2471 |
||
1.1.18
by Sebastien Bacher
Import upstream version 2.23.5 |
2472 |
return 0; |
2473 |
}
|