]> Pileus Git - ~andy/gtk/blob - gdk/gdkscreen.c
gdk/gdkscreen.c (gdk_screen_get_monitor_at_point) Provide a useful
[~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 "gdk.h"                /* For gdk_rectangle_intersect() */
25 #include "gdkcolor.h"
26 #include "gdkinternals.h"
27 #include "gdkwindow.h"
28 #include "gdkscreen.h"
29
30 static void         gdk_screen_class_init  (GdkScreenClass *klass);
31
32 enum
33 {
34   SIZE_CHANGED,
35   LAST_SIGNAL
36 };
37
38 static guint signals[LAST_SIGNAL] = { 0 };
39
40 GType
41 gdk_screen_get_type (void)
42 {
43   static GType object_type = 0;
44
45   if (!object_type)
46     {
47       static const GTypeInfo object_info =
48         {
49           sizeof (GdkScreenClass),
50           (GBaseInitFunc) NULL,
51           (GBaseFinalizeFunc) NULL,
52           (GClassInitFunc) gdk_screen_class_init,
53           NULL,                 /* class_finalize */
54           NULL,                 /* class_data */
55           sizeof (GdkScreen),
56           0,                    /* n_preallocs */
57           (GInstanceInitFunc) NULL,
58         };
59       
60       object_type = g_type_register_static (G_TYPE_OBJECT,
61                                             "GdkScreen", &object_info, 0);
62     }
63
64   return object_type;
65 }
66
67 static void
68 gdk_screen_class_init (GdkScreenClass *klass)
69 {
70   signals[SIZE_CHANGED] =
71     g_signal_new ("size_changed",
72                   G_OBJECT_CLASS_TYPE (klass),
73                   G_SIGNAL_RUN_LAST,
74                   G_STRUCT_OFFSET (GdkScreenClass, size_changed),
75                   NULL, NULL,
76                   g_cclosure_marshal_VOID__VOID,
77                   G_TYPE_NONE,
78                   0);
79 }
80
81 void 
82 _gdk_screen_close (GdkScreen *screen)
83 {
84   g_return_if_fail (GDK_IS_SCREEN (screen));
85
86   if (!screen->closed)
87     {
88       screen->closed = TRUE;
89       g_object_run_dispose (G_OBJECT (screen));
90     }
91 }
92
93 /* Fallback used when the monitor "at" a point or window
94  * doesn't exist.
95  */
96 static gint
97 get_nearest_monitor (GdkScreen *screen,
98                      gint       x,
99                      gint       y)
100 {
101   gint num_monitors, i;
102   gint nearest_dist = G_MAXINT;
103   gint nearest_monitor = 0;
104   
105   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
106
107   num_monitors = gdk_screen_get_n_monitors (screen);
108   
109   for (i = 0; i < num_monitors; i++)
110     {
111       GdkRectangle monitor;
112       gint dist_x, dist_y;
113       
114       gdk_screen_get_monitor_geometry (screen, i, &monitor);
115
116       if (x < monitor.x)
117         dist_x = monitor.x - x;
118       else if (x >= monitor.x + monitor.width)
119         dist_x = x - (monitor.x + monitor.width) + 1;
120       else
121         dist_x = 0;
122
123       if (y < monitor.y)
124         dist_y = monitor.y - y;
125       else if (y >= monitor.y + monitor.height)
126         dist_y = y - (monitor.y + monitor.height) + 1;
127       else
128         dist_y = 0;
129
130       if (MIN (dist_x, dist_y) < nearest_dist)
131         {
132           nearest_dist = MIN (dist_x, dist_y);
133           nearest_monitor = i;
134         }
135     }
136
137   return nearest_monitor;
138 }
139
140 /**
141  * gdk_screen_get_monitor_at_point:
142  * @screen: a #GdkScreen.
143  * @x: the x coordinate in the virtual screen.
144  * @y: the y coordinate in the virtual screen.
145  *
146  * Returns the monitor number in which the point (@x,@y) is located.
147  *
148  * Returns: the monitor number in which the point (@x,@y) lies, or
149  *   a monitor close to (@x,@y) if the point is not in any monitor.
150  *
151  * Since: 2.2
152  **/
153 gint 
154 gdk_screen_get_monitor_at_point (GdkScreen *screen,
155                                  gint       x,
156                                  gint       y)
157 {
158   gint num_monitors, i;
159   
160   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
161
162   num_monitors = gdk_screen_get_n_monitors (screen);
163   
164   for (i=0;i<num_monitors;i++)
165     {
166       GdkRectangle monitor;
167       
168       gdk_screen_get_monitor_geometry (screen, i, &monitor);
169
170       if (x >= monitor.x &&
171           x < monitor.x + monitor.width &&
172           y >= monitor.y &&
173           y < (monitor.y + monitor.height))
174         return i;
175     }
176
177   return get_nearest_monitor (screen, x, y);
178 }
179
180 /**
181  * gdk_screen_get_monitor_at_window:
182  * @screen: a #GdkScreen.
183  * @window: a #GdkWindow
184  * @returns: the monitor number in which most of @window is located,
185  *           or if @window does not intersect any monitors, a monitor,
186  *           close to @window.
187  *
188  * Returns the number of the monitor in which the largest area of the 
189  * bounding rectangle of @window resides.
190  *
191  * Since: 2.2
192  **/
193 gint 
194 gdk_screen_get_monitor_at_window (GdkScreen      *screen,
195                                   GdkWindow      *window)
196 {
197   gint num_monitors, i, area = 0, screen_num = -1;
198   GdkRectangle win_rect;
199   g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
200   
201   gdk_window_get_geometry (window, &win_rect.x, &win_rect.y, &win_rect.width,
202                            &win_rect.height, NULL);
203   gdk_window_get_origin (window, &win_rect.x, &win_rect.y);
204   num_monitors = gdk_screen_get_n_monitors (screen);
205   
206   for (i=0;i<num_monitors;i++)
207     {
208       GdkRectangle tmp_monitor, intersect;
209       
210       gdk_screen_get_monitor_geometry (screen, i, &tmp_monitor);
211       gdk_rectangle_intersect (&win_rect, &tmp_monitor, &intersect);
212       
213       if (intersect.width * intersect.height > area)
214         { 
215           area = intersect.width * intersect.height;
216           screen_num = i;
217         }
218     }
219   if (screen_num >= 0)
220     return screen_num;
221   else
222     return get_nearest_monitor (screen,
223                                 win_rect.x + win_rect.width / 2,
224                                 win_rect.y + win_rect.height / 2);
225 }
226
227 /**
228  * gdk_screen_width:
229  * 
230  * Returns the width of the default screen in pixels.
231  * 
232  * Return value: the width of the default screen in pixels.
233  **/
234 gint
235 gdk_screen_width (void)
236 {
237   return gdk_screen_get_width (gdk_screen_get_default());
238 }
239
240 /**
241  * gdk_screen_height:
242  * 
243  * Returns the height of the default screen in pixels.
244  * 
245  * Return value: the height of the default screen in pixels.
246  **/
247 gint
248 gdk_screen_height (void)
249 {
250   return gdk_screen_get_height (gdk_screen_get_default());
251 }
252
253 /**
254  * gdk_screen_width_mm:
255  * 
256  * Returns the width of the default screen in millimeters.
257  * Note that on many X servers this value will not be correct.
258  * 
259  * Return value: the width of the default screen in millimeters,
260  * though it is not always correct.
261  **/
262 gint
263 gdk_screen_width_mm (void)
264 {
265   return gdk_screen_get_width_mm (gdk_screen_get_default());
266 }
267
268 /**
269  * gdk_screen_height_mm:
270  * 
271  * Returns the height of the default screen in millimeters.
272  * Note that on many X servers this value will not be correct.
273  * 
274  * Return value: the height of the default screen in millimeters,
275  * though it is not always correct.
276  **/
277 gint
278 gdk_screen_height_mm (void)
279 {
280   return gdk_screen_get_height_mm (gdk_screen_get_default ());
281 }