]> Pileus Git - ~andy/gtk/blob - gdk/gdkscreen.c
Bug 570896 - gdkevents-win32.c(2947) : error C4053: one void operand for
[~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 #include "gdk.h"                /* For gdk_rectangle_intersect() */
26 #include "gdkcolor.h"
27 #include "gdkwindow.h"
28 #include "gdkscreen.h"
29 #include "gdkintl.h"
30 #include "gdkalias.h"
31
32 static void gdk_screen_dispose      (GObject        *object);
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->dispose = gdk_screen_dispose;
68   object_class->finalize = gdk_screen_finalize;
69   object_class->set_property = gdk_screen_set_property;
70   object_class->get_property = gdk_screen_get_property;
71   
72   g_object_class_install_property (object_class,
73                                    PROP_FONT_OPTIONS,
74                                    g_param_spec_pointer ("font-options",
75                                                          P_("Font options"),
76                                                          P_("The default font options for the screen"),
77                                                          G_PARAM_READWRITE|G_PARAM_STATIC_NAME|
78                                                         G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
79
80   g_object_class_install_property (object_class,
81                                    PROP_RESOLUTION,
82                                    g_param_spec_double ("resolution",
83                                                         P_("Font resolution"),
84                                                         P_("The resolution for fonts on the screen"),
85                                                         -G_MAXDOUBLE,
86                                                         G_MAXDOUBLE,
87                                                         -1.0,
88                                                         G_PARAM_READWRITE|G_PARAM_STATIC_NAME|
89                                                         G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
90
91   /**
92    * GdkScreen::size-changed:
93    * @screen: the object on which the signal is emitted
94    * 
95    * The ::size-changed signal is emitted when the pixel width or 
96    * height of a screen changes.
97    *
98    * Since: 2.2
99    */
100   signals[SIZE_CHANGED] =
101     g_signal_new (g_intern_static_string ("size-changed"),
102                   G_OBJECT_CLASS_TYPE (klass),
103                   G_SIGNAL_RUN_LAST,
104                   G_STRUCT_OFFSET (GdkScreenClass, size_changed),
105                   NULL, NULL,
106                   g_cclosure_marshal_VOID__VOID,
107                   G_TYPE_NONE,
108                   0);
109
110   /**
111    * GdkScreen::composited-changed:
112    * @screen: the object on which the signal is emitted
113    *
114    * The ::composited-changed signal is emitted when the composited
115    * status of the screen changes
116    *
117    * Since: 2.10
118    */
119   signals[COMPOSITED_CHANGED] =
120     g_signal_new (g_intern_static_string ("composited-changed"),
121                   G_OBJECT_CLASS_TYPE (klass),
122                   G_SIGNAL_RUN_LAST,
123                   G_STRUCT_OFFSET (GdkScreenClass, composited_changed),
124                   NULL, NULL,
125                   g_cclosure_marshal_VOID__VOID,
126                   G_TYPE_NONE,
127                   0);
128         
129   /**
130    * GdkScreen::monitors-changed:
131    * @screen: the object on which the signal is emitted
132    *
133    * The ::monitors-changed signal is emitted when the number, size
134    * or position of the monitors attached to the screen change. 
135    *
136    * Only for X for now. Future implementations for Win32 and
137    * OS X may be a possibility.
138    *
139    * Since: 2.14
140    */
141   signals[MONITORS_CHANGED] =
142     g_signal_new (g_intern_static_string ("monitors-changed"),
143                   G_OBJECT_CLASS_TYPE (klass),
144                   G_SIGNAL_RUN_LAST,
145                   G_STRUCT_OFFSET (GdkScreenClass, monitors_changed),
146                   NULL, NULL,
147                   g_cclosure_marshal_VOID__VOID,
148                   G_TYPE_NONE,
149                   0);
150 }
151
152 static void
153 gdk_screen_init (GdkScreen *screen)
154 {
155   screen->resolution = -1.;
156 }
157
158 static void
159 gdk_screen_dispose (GObject *object)
160 {
161   GdkScreen *screen = GDK_SCREEN (object);
162   gint i;
163
164   for (i = 0; i < 32; ++i)
165     {
166       if (screen->exposure_gcs[i])
167         {
168           g_object_unref (screen->exposure_gcs[i]);
169           screen->exposure_gcs[i] = NULL;
170         }
171
172       if (screen->normal_gcs[i])
173         {
174           g_object_unref (screen->normal_gcs[i]);
175           screen->normal_gcs[i] = NULL;
176         }
177     }
178
179   G_OBJECT_CLASS (gdk_screen_parent_class)->dispose (object);
180 }
181
182 static void
183 gdk_screen_finalize (GObject *object)
184 {
185   GdkScreen *screen = GDK_SCREEN (object);
186
187   if (screen->font_options)
188       cairo_font_options_destroy (screen->font_options);
189
190   G_OBJECT_CLASS (gdk_screen_parent_class)->finalize (object);
191 }
192
193 void 
194 _gdk_screen_close (GdkScreen *screen)
195 {
196   g_return_if_fail (GDK_IS_SCREEN (screen));
197
198   if (!screen->closed)
199     {
200       screen->closed = TRUE;
201       g_object_run_dispose (G_OBJECT (screen));
202     }
203 }
204
205 /* Fallback used when the monitor "at" a point or window
206  * doesn't exist.
207  */
208 static gint
209 get_nearest_monitor (GdkScreen *screen,
210                      gint       x,
211                      gint       y)
212 {
213   gint num_monitors, i;
214   gint nearest_dist = G_MAXINT;
215   gint nearest_monitor = 0;
216   
217   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
218
219   num_monitors = gdk_screen_get_n_monitors (screen);
220   
221   for (i = 0; i < num_monitors; i++)
222     {
223       GdkRectangle monitor;
224       gint dist_x, dist_y;
225       
226       gdk_screen_get_monitor_geometry (screen, i, &monitor);
227
228       if (x < monitor.x)
229         dist_x = monitor.x - x;
230       else if (x >= monitor.x + monitor.width)
231         dist_x = x - (monitor.x + monitor.width) + 1;
232       else
233         dist_x = 0;
234
235       if (y < monitor.y)
236         dist_y = monitor.y - y;
237       else if (y >= monitor.y + monitor.height)
238         dist_y = y - (monitor.y + monitor.height) + 1;
239       else
240         dist_y = 0;
241
242       if (MIN (dist_x, dist_y) < nearest_dist)
243         {
244           nearest_dist = MIN (dist_x, dist_y);
245           nearest_monitor = i;
246         }
247     }
248
249   return nearest_monitor;
250 }
251
252 /**
253  * gdk_screen_get_monitor_at_point:
254  * @screen: a #GdkScreen.
255  * @x: the x coordinate in the virtual screen.
256  * @y: the y coordinate in the virtual screen.
257  *
258  * Returns the monitor number in which the point (@x,@y) is located.
259  *
260  * Returns: the monitor number in which the point (@x,@y) lies, or
261  *   a monitor close to (@x,@y) if the point is not in any monitor.
262  *
263  * Since: 2.2
264  **/
265 gint 
266 gdk_screen_get_monitor_at_point (GdkScreen *screen,
267                                  gint       x,
268                                  gint       y)
269 {
270   gint num_monitors, i;
271   
272   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
273
274   num_monitors = gdk_screen_get_n_monitors (screen);
275   
276   for (i=0;i<num_monitors;i++)
277     {
278       GdkRectangle monitor;
279       
280       gdk_screen_get_monitor_geometry (screen, i, &monitor);
281
282       if (x >= monitor.x &&
283           x < monitor.x + monitor.width &&
284           y >= monitor.y &&
285           y < (monitor.y + monitor.height))
286         return i;
287     }
288
289   return get_nearest_monitor (screen, x, y);
290 }
291
292 /**
293  * gdk_screen_get_monitor_at_window:
294  * @screen: a #GdkScreen.
295  * @window: a #GdkWindow
296  * @returns: the monitor number in which most of @window is located,
297  *           or if @window does not intersect any monitors, a monitor,
298  *           close to @window.
299  *
300  * Returns the number of the monitor in which the largest area of the 
301  * bounding rectangle of @window resides.
302  *
303  * Since: 2.2
304  **/
305 gint 
306 gdk_screen_get_monitor_at_window (GdkScreen      *screen,
307                                   GdkWindow      *window)
308 {
309   gint num_monitors, i, area = 0, screen_num = -1;
310   GdkRectangle win_rect;
311
312   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
313
314   gdk_window_get_geometry (window, &win_rect.x, &win_rect.y, &win_rect.width,
315                            &win_rect.height, NULL);
316   gdk_window_get_origin (window, &win_rect.x, &win_rect.y);
317   num_monitors = gdk_screen_get_n_monitors (screen);
318   
319   for (i=0;i<num_monitors;i++)
320     {
321       GdkRectangle tmp_monitor, intersect;
322       
323       gdk_screen_get_monitor_geometry (screen, i, &tmp_monitor);
324       gdk_rectangle_intersect (&win_rect, &tmp_monitor, &intersect);
325       
326       if (intersect.width * intersect.height > area)
327         { 
328           area = intersect.width * intersect.height;
329           screen_num = i;
330         }
331     }
332   if (screen_num >= 0)
333     return screen_num;
334   else
335     return get_nearest_monitor (screen,
336                                 win_rect.x + win_rect.width / 2,
337                                 win_rect.y + win_rect.height / 2);
338 }
339
340 /**
341  * gdk_screen_width:
342  * 
343  * Returns the width of the default screen in pixels.
344  * 
345  * Return value: the width of the default screen in pixels.
346  **/
347 gint
348 gdk_screen_width (void)
349 {
350   return gdk_screen_get_width (gdk_screen_get_default ());
351 }
352
353 /**
354  * gdk_screen_height:
355  * 
356  * Returns the height of the default screen in pixels.
357  * 
358  * Return value: the height of the default screen in pixels.
359  **/
360 gint
361 gdk_screen_height (void)
362 {
363   return gdk_screen_get_height (gdk_screen_get_default ());
364 }
365
366 /**
367  * gdk_screen_width_mm:
368  * 
369  * Returns the width of the default screen in millimeters.
370  * Note that on many X servers this value will not be correct.
371  * 
372  * Return value: the width of the default screen in millimeters,
373  * though it is not always correct.
374  **/
375 gint
376 gdk_screen_width_mm (void)
377 {
378   return gdk_screen_get_width_mm (gdk_screen_get_default ());
379 }
380
381 /**
382  * gdk_screen_height_mm:
383  * 
384  * Returns the height of the default screen in millimeters.
385  * Note that on many X servers this value will not be correct.
386  * 
387  * Return value: the height of the default screen in millimeters,
388  * though it is not always correct.
389  **/
390 gint
391 gdk_screen_height_mm (void)
392 {
393   return gdk_screen_get_height_mm (gdk_screen_get_default ());
394 }
395
396 /**
397  * gdk_screen_set_font_options:
398  * @screen: a #GdkScreen
399  * @options: a #cairo_font_options_t, or %NULL to unset any
400  *   previously set default font options.
401  *
402  * Sets the default font options for the screen. These
403  * options will be set on any #PangoContext's newly created
404  * with gdk_pango_context_get_for_screen(). Changing the
405  * default set of font options does not affect contexts that
406  * have already been created.
407  *
408  * Since: 2.10
409  **/
410 void
411 gdk_screen_set_font_options (GdkScreen                  *screen,
412                              const cairo_font_options_t *options)
413 {
414   g_return_if_fail (GDK_IS_SCREEN (screen));
415
416   if (screen->font_options != options)
417     {
418       if (screen->font_options)
419         cairo_font_options_destroy (screen->font_options);
420
421       if (options)
422         screen->font_options = cairo_font_options_copy (options);
423       else
424         screen->font_options = NULL;
425
426       g_object_notify (G_OBJECT (screen), "font-options");
427     }
428 }
429
430 /**
431  * gdk_screen_get_font_options:
432  * @screen: a #GdkScreen
433  * 
434  * Gets any options previously set with gdk_screen_set_font_options().
435  * 
436  * Return value: the current font options, or %NULL if no default
437  *  font options have been set.
438  *
439  * Since: 2.10
440  **/
441 const cairo_font_options_t *
442 gdk_screen_get_font_options (GdkScreen *screen)
443 {
444   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
445
446   return screen->font_options;
447 }
448
449 /**
450  * gdk_screen_set_resolution:
451  * @screen: a #GdkScreen
452  * @dpi: the resolution in "dots per inch". (Physical inches aren't actually
453  *   involved; the terminology is conventional.)
454  
455  * Sets the resolution for font handling on the screen. This is a
456  * scale factor between points specified in a #PangoFontDescription
457  * and cairo units. The default value is 96, meaning that a 10 point
458  * font will be 13 units high. (10 * 96. / 72. = 13.3).
459  *
460  * Since: 2.10
461  **/
462 void
463 gdk_screen_set_resolution (GdkScreen *screen,
464                            gdouble    dpi)
465 {
466   g_return_if_fail (GDK_IS_SCREEN (screen));
467
468   if (dpi < 0)
469     dpi = -1.0;
470
471   if (screen->resolution != dpi)
472     {
473       screen->resolution = dpi;
474
475       g_object_notify (G_OBJECT (screen), "resolution");
476     }
477 }
478
479 /**
480  * gdk_screen_get_resolution:
481  * @screen: a #GdkScreen
482  * 
483  * Gets the resolution for font handling on the screen; see
484  * gdk_screen_set_resolution() for full details.
485  * 
486  * Return value: the current resolution, or -1 if no resolution
487  * has been set.
488  *
489  * Since: 2.10
490  **/
491 gdouble
492 gdk_screen_get_resolution (GdkScreen *screen)
493 {
494   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1.0);
495
496   return screen->resolution;
497 }
498
499 static void
500 gdk_screen_get_property (GObject      *object,
501                          guint         prop_id,
502                          GValue       *value,
503                          GParamSpec   *pspec)
504 {
505   GdkScreen *screen = GDK_SCREEN (object);
506
507   switch (prop_id)
508     {
509     case PROP_FONT_OPTIONS:
510       g_value_set_pointer (value, (gpointer) gdk_screen_get_font_options (screen));
511       break;
512     case PROP_RESOLUTION:
513       g_value_set_double (value, gdk_screen_get_resolution (screen));
514       break;
515     default:
516       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
517       break;
518     }
519 }
520
521 static void
522 gdk_screen_set_property (GObject      *object,
523                          guint         prop_id,
524                          const GValue *value,
525                          GParamSpec   *pspec)
526 {
527   GdkScreen *screen = GDK_SCREEN (object);
528
529   switch (prop_id)
530     {
531     case PROP_FONT_OPTIONS:
532       gdk_screen_set_font_options (screen, g_value_get_pointer (value));
533       break;
534     case PROP_RESOLUTION:
535       gdk_screen_set_resolution (screen, g_value_get_double (value));
536       break;
537     default:
538       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
539       break;
540     }
541 }
542
543 #define __GDK_SCREEN_C__
544 #include "gdkaliasdef.c"