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