]> Pileus Git - ~andy/gtk/blob - gdk/gdkscreen.c
Inclusion cleanups in sources
[~andy/gtk] / gdk / gdkscreen.c
1 /*
2  * gdkscreen.c
3  * 
4  * Copyright 2001 Sun Microsystems Inc. 
5  *
6  * Erwann Chenede <erwann.chenede@sun.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25
26 #include "gdkscreen.h"
27
28 #include "gdkrectangle.h"
29 #include "gdkwindow.h"
30 #include "gdkintl.h"
31
32
33 static void gdk_screen_finalize     (GObject        *object);
34 static void gdk_screen_set_property (GObject        *object,
35                                      guint           prop_id,
36                                      const GValue   *value,
37                                      GParamSpec     *pspec);
38 static void gdk_screen_get_property (GObject        *object,
39                                      guint           prop_id,
40                                      GValue         *value,
41                                      GParamSpec     *pspec);
42
43 enum
44 {
45   PROP_0,
46   PROP_FONT_OPTIONS,
47   PROP_RESOLUTION
48 };
49
50 enum
51 {
52   SIZE_CHANGED,
53   COMPOSITED_CHANGED,
54   MONITORS_CHANGED,
55   LAST_SIGNAL
56 };
57
58 static guint signals[LAST_SIGNAL] = { 0 };
59
60 G_DEFINE_TYPE (GdkScreen, gdk_screen, G_TYPE_OBJECT)
61
62 static void
63 gdk_screen_class_init (GdkScreenClass *klass)
64 {
65   GObjectClass *object_class = G_OBJECT_CLASS (klass);
66
67   object_class->finalize = gdk_screen_finalize;
68   object_class->set_property = gdk_screen_set_property;
69   object_class->get_property = gdk_screen_get_property;
70   
71   g_object_class_install_property (object_class,
72                                    PROP_FONT_OPTIONS,
73                                    g_param_spec_pointer ("font-options",
74                                                          P_("Font options"),
75                                                          P_("The default font options for the screen"),
76                                                          G_PARAM_READWRITE|G_PARAM_STATIC_NAME|
77                                                         G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
78
79   g_object_class_install_property (object_class,
80                                    PROP_RESOLUTION,
81                                    g_param_spec_double ("resolution",
82                                                         P_("Font resolution"),
83                                                         P_("The resolution for fonts on the screen"),
84                                                         -G_MAXDOUBLE,
85                                                         G_MAXDOUBLE,
86                                                         -1.0,
87                                                         G_PARAM_READWRITE|G_PARAM_STATIC_NAME|
88                                                         G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
89
90   /**
91    * GdkScreen::size-changed:
92    * @screen: the object on which the signal is emitted
93    * 
94    * The ::size-changed signal is emitted when the pixel width or 
95    * height of a screen changes.
96    *
97    * Since: 2.2
98    */
99   signals[SIZE_CHANGED] =
100     g_signal_new (g_intern_static_string ("size-changed"),
101                   G_OBJECT_CLASS_TYPE (klass),
102                   G_SIGNAL_RUN_LAST,
103                   G_STRUCT_OFFSET (GdkScreenClass, size_changed),
104                   NULL, NULL,
105                   g_cclosure_marshal_VOID__VOID,
106                   G_TYPE_NONE,
107                   0);
108
109   /**
110    * GdkScreen::composited-changed:
111    * @screen: the object on which the signal is emitted
112    *
113    * The ::composited-changed signal is emitted when the composited
114    * status of the screen changes
115    *
116    * Since: 2.10
117    */
118   signals[COMPOSITED_CHANGED] =
119     g_signal_new (g_intern_static_string ("composited-changed"),
120                   G_OBJECT_CLASS_TYPE (klass),
121                   G_SIGNAL_RUN_LAST,
122                   G_STRUCT_OFFSET (GdkScreenClass, composited_changed),
123                   NULL, NULL,
124                   g_cclosure_marshal_VOID__VOID,
125                   G_TYPE_NONE,
126                   0);
127         
128   /**
129    * GdkScreen::monitors-changed:
130    * @screen: the object on which the signal is emitted
131    *
132    * The ::monitors-changed signal is emitted when the number, size
133    * or position of the monitors attached to the screen change. 
134    *
135    * Only for X11 and OS X for now. A future implementation for Win32
136    * may be a possibility.
137    *
138    * Since: 2.14
139    */
140   signals[MONITORS_CHANGED] =
141     g_signal_new (g_intern_static_string ("monitors-changed"),
142                   G_OBJECT_CLASS_TYPE (klass),
143                   G_SIGNAL_RUN_LAST,
144                   G_STRUCT_OFFSET (GdkScreenClass, monitors_changed),
145                   NULL, NULL,
146                   g_cclosure_marshal_VOID__VOID,
147                   G_TYPE_NONE,
148                   0);
149 }
150
151 static void
152 gdk_screen_init (GdkScreen *screen)
153 {
154   screen->resolution = -1.;
155 }
156
157 static void
158 gdk_screen_finalize (GObject *object)
159 {
160   GdkScreen *screen = GDK_SCREEN (object);
161
162   if (screen->font_options)
163       cairo_font_options_destroy (screen->font_options);
164
165   G_OBJECT_CLASS (gdk_screen_parent_class)->finalize (object);
166 }
167
168 void 
169 _gdk_screen_close (GdkScreen *screen)
170 {
171   g_return_if_fail (GDK_IS_SCREEN (screen));
172
173   if (!screen->closed)
174     {
175       screen->closed = TRUE;
176       g_object_run_dispose (G_OBJECT (screen));
177     }
178 }
179
180 /* Fallback used when the monitor "at" a point or window
181  * doesn't exist.
182  */
183 static gint
184 get_nearest_monitor (GdkScreen *screen,
185                      gint       x,
186                      gint       y)
187 {
188   gint num_monitors, i;
189   gint nearest_dist = G_MAXINT;
190   gint nearest_monitor = 0;
191
192   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
193
194   num_monitors = gdk_screen_get_n_monitors (screen);
195   
196   for (i = 0; i < num_monitors; i++)
197     {
198       GdkRectangle monitor;
199       gint dist_x, dist_y, dist;
200       
201       gdk_screen_get_monitor_geometry (screen, i, &monitor);
202
203       if (x < monitor.x)
204         dist_x = monitor.x - x;
205       else if (x >= monitor.x + monitor.width)
206         dist_x = x - (monitor.x + monitor.width) + 1;
207       else
208         dist_x = 0;
209
210       if (y < monitor.y)
211         dist_y = monitor.y - y;
212       else if (y >= monitor.y + monitor.height)
213         dist_y = y - (monitor.y + monitor.height) + 1;
214       else
215         dist_y = 0;
216
217       dist = dist_x + dist_y;
218       if (dist < nearest_dist)
219         {
220           nearest_dist = dist;
221           nearest_monitor = i;
222         }
223     }
224
225   return nearest_monitor;
226 }
227
228 /**
229  * gdk_screen_get_monitor_at_point:
230  * @screen: a #GdkScreen.
231  * @x: the x coordinate in the virtual screen.
232  * @y: the y coordinate in the virtual screen.
233  *
234  * Returns the monitor number in which the point (@x,@y) is located.
235  *
236  * Returns: the monitor number in which the point (@x,@y) lies, or
237  *   a monitor close to (@x,@y) if the point is not in any monitor.
238  *
239  * Since: 2.2
240  **/
241 gint 
242 gdk_screen_get_monitor_at_point (GdkScreen *screen,
243                                  gint       x,
244                                  gint       y)
245 {
246   gint num_monitors, i;
247   
248   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
249
250   num_monitors = gdk_screen_get_n_monitors (screen);
251   
252   for (i=0;i<num_monitors;i++)
253     {
254       GdkRectangle monitor;
255       
256       gdk_screen_get_monitor_geometry (screen, i, &monitor);
257
258       if (x >= monitor.x &&
259           x < monitor.x + monitor.width &&
260           y >= monitor.y &&
261           y < (monitor.y + monitor.height))
262         return i;
263     }
264
265   return get_nearest_monitor (screen, x, y);
266 }
267
268 /**
269  * gdk_screen_get_monitor_at_window:
270  * @screen: a #GdkScreen.
271  * @window: a #GdkWindow
272  * @returns: the monitor number in which most of @window is located,
273  *           or if @window does not intersect any monitors, a monitor,
274  *           close to @window.
275  *
276  * Returns the number of the monitor in which the largest area of the 
277  * bounding rectangle of @window resides.
278  *
279  * Since: 2.2
280  **/
281 gint 
282 gdk_screen_get_monitor_at_window (GdkScreen      *screen,
283                                   GdkWindow      *window)
284 {
285   gint num_monitors, i, area = 0, screen_num = -1;
286   GdkRectangle win_rect;
287
288   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
289
290   gdk_window_get_geometry (window, &win_rect.x, &win_rect.y, &win_rect.width,
291                            &win_rect.height, NULL);
292   gdk_window_get_origin (window, &win_rect.x, &win_rect.y);
293   num_monitors = gdk_screen_get_n_monitors (screen);
294   
295   for (i=0;i<num_monitors;i++)
296     {
297       GdkRectangle tmp_monitor, intersect;
298       
299       gdk_screen_get_monitor_geometry (screen, i, &tmp_monitor);
300       gdk_rectangle_intersect (&win_rect, &tmp_monitor, &intersect);
301       
302       if (intersect.width * intersect.height > area)
303         { 
304           area = intersect.width * intersect.height;
305           screen_num = i;
306         }
307     }
308   if (screen_num >= 0)
309     return screen_num;
310   else
311     return get_nearest_monitor (screen,
312                                 win_rect.x + win_rect.width / 2,
313                                 win_rect.y + win_rect.height / 2);
314 }
315
316 /**
317  * gdk_screen_width:
318  * 
319  * Returns the width of the default screen in pixels.
320  * 
321  * Return value: the width of the default screen in pixels.
322  **/
323 gint
324 gdk_screen_width (void)
325 {
326   return gdk_screen_get_width (gdk_screen_get_default ());
327 }
328
329 /**
330  * gdk_screen_height:
331  * 
332  * Returns the height of the default screen in pixels.
333  * 
334  * Return value: the height of the default screen in pixels.
335  **/
336 gint
337 gdk_screen_height (void)
338 {
339   return gdk_screen_get_height (gdk_screen_get_default ());
340 }
341
342 /**
343  * gdk_screen_width_mm:
344  * 
345  * Returns the width of the default screen in millimeters.
346  * Note that on many X servers this value will not be correct.
347  * 
348  * Return value: the width of the default screen in millimeters,
349  * though it is not always correct.
350  **/
351 gint
352 gdk_screen_width_mm (void)
353 {
354   return gdk_screen_get_width_mm (gdk_screen_get_default ());
355 }
356
357 /**
358  * gdk_screen_height_mm:
359  * 
360  * Returns the height of the default screen in millimeters.
361  * Note that on many X servers this value will not be correct.
362  * 
363  * Return value: the height of the default screen in millimeters,
364  * though it is not always correct.
365  **/
366 gint
367 gdk_screen_height_mm (void)
368 {
369   return gdk_screen_get_height_mm (gdk_screen_get_default ());
370 }
371
372 /**
373  * gdk_screen_set_font_options:
374  * @screen: a #GdkScreen
375  * @options: (allow-none): a #cairo_font_options_t, or %NULL to unset any
376  *   previously set default font options.
377  *
378  * Sets the default font options for the screen. These
379  * options will be set on any #PangoContext's newly created
380  * with gdk_pango_context_get_for_screen(). Changing the
381  * default set of font options does not affect contexts that
382  * have already been created.
383  *
384  * Since: 2.10
385  **/
386 void
387 gdk_screen_set_font_options (GdkScreen                  *screen,
388                              const cairo_font_options_t *options)
389 {
390   g_return_if_fail (GDK_IS_SCREEN (screen));
391
392   if (screen->font_options != options)
393     {
394       if (screen->font_options)
395         cairo_font_options_destroy (screen->font_options);
396
397       if (options)
398         screen->font_options = cairo_font_options_copy (options);
399       else
400         screen->font_options = NULL;
401
402       g_object_notify (G_OBJECT (screen), "font-options");
403     }
404 }
405
406 /**
407  * gdk_screen_get_font_options:
408  * @screen: a #GdkScreen
409  * 
410  * Gets any options previously set with gdk_screen_set_font_options().
411  * 
412  * Return value: the current font options, or %NULL if no default
413  *  font options have been set.
414  *
415  * Since: 2.10
416  **/
417 const cairo_font_options_t *
418 gdk_screen_get_font_options (GdkScreen *screen)
419 {
420   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
421
422   return screen->font_options;
423 }
424
425 /**
426  * gdk_screen_set_resolution:
427  * @screen: a #GdkScreen
428  * @dpi: the resolution in "dots per inch". (Physical inches aren't actually
429  *   involved; the terminology is conventional.)
430  
431  * Sets the resolution for font handling on the screen. This is a
432  * scale factor between points specified in a #PangoFontDescription
433  * and cairo units. The default value is 96, meaning that a 10 point
434  * font will be 13 units high. (10 * 96. / 72. = 13.3).
435  *
436  * Since: 2.10
437  **/
438 void
439 gdk_screen_set_resolution (GdkScreen *screen,
440                            gdouble    dpi)
441 {
442   g_return_if_fail (GDK_IS_SCREEN (screen));
443
444   if (dpi < 0)
445     dpi = -1.0;
446
447   if (screen->resolution != dpi)
448     {
449       screen->resolution = dpi;
450
451       g_object_notify (G_OBJECT (screen), "resolution");
452     }
453 }
454
455 /**
456  * gdk_screen_get_resolution:
457  * @screen: a #GdkScreen
458  * 
459  * Gets the resolution for font handling on the screen; see
460  * gdk_screen_set_resolution() for full details.
461  * 
462  * Return value: the current resolution, or -1 if no resolution
463  * has been set.
464  *
465  * Since: 2.10
466  **/
467 gdouble
468 gdk_screen_get_resolution (GdkScreen *screen)
469 {
470   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1.0);
471
472   return screen->resolution;
473 }
474
475 static void
476 gdk_screen_get_property (GObject      *object,
477                          guint         prop_id,
478                          GValue       *value,
479                          GParamSpec   *pspec)
480 {
481   GdkScreen *screen = GDK_SCREEN (object);
482
483   switch (prop_id)
484     {
485     case PROP_FONT_OPTIONS:
486       g_value_set_pointer (value, (gpointer) gdk_screen_get_font_options (screen));
487       break;
488     case PROP_RESOLUTION:
489       g_value_set_double (value, gdk_screen_get_resolution (screen));
490       break;
491     default:
492       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
493       break;
494     }
495 }
496
497 static void
498 gdk_screen_set_property (GObject      *object,
499                          guint         prop_id,
500                          const GValue *value,
501                          GParamSpec   *pspec)
502 {
503   GdkScreen *screen = GDK_SCREEN (object);
504
505   switch (prop_id)
506     {
507     case PROP_FONT_OPTIONS:
508       gdk_screen_set_font_options (screen, g_value_get_pointer (value));
509       break;
510     case PROP_RESOLUTION:
511       gdk_screen_set_resolution (screen, g_value_get_double (value));
512       break;
513     default:
514       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
515       break;
516     }
517 }