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