]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
Applied patch from maemo-gtk that addresses many issues wrt display
[~andy/gtk] / gdk / gdkdisplay.c
1 /* GDK - The GIMP Drawing Kit
2  * gdkdisplay.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 <glib.h>
26 #include "gdk.h"                /* gdk_event_send_client_message() */
27 #include "gdkdisplay.h"
28 #include "gdkinternals.h"
29 #include "gdkmarshalers.h"
30 #include "gdkscreen.h"
31 #include "gdkalias.h"
32
33 enum {
34   CLOSED,
35   LAST_SIGNAL
36 };
37
38 static void gdk_display_class_init (GdkDisplayClass *class);
39 static void gdk_display_init       (GdkDisplay      *display);
40 static void gdk_display_dispose    (GObject         *object);
41 static void gdk_display_finalize   (GObject         *object);
42
43
44 static void       singlehead_get_pointer (GdkDisplay       *display,
45                                           GdkScreen       **screen,
46                                           gint             *x,
47                                           gint             *y,
48                                           GdkModifierType  *mask);
49 static GdkWindow* singlehead_window_get_pointer (GdkDisplay       *display,
50                                                  GdkWindow        *window,
51                                                  gint             *x,
52                                                  gint             *y,
53                                                  GdkModifierType  *mask);
54 static GdkWindow* singlehead_window_at_pointer  (GdkDisplay       *display,
55                                                  gint             *win_x,
56                                                  gint             *win_y);
57
58 static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window,
59                                                          gint            *x,
60                                                          gint            *y,
61                                                          GdkModifierType *mask);
62 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
63                                                          gint            *win_x,
64                                                          gint            *win_y);
65
66 static guint signals[LAST_SIGNAL] = { 0 };
67
68 static GObjectClass *parent_class;
69 static char *gdk_sm_client_id;
70
71 static const GdkDisplayPointerHooks default_pointer_hooks = {
72   _gdk_windowing_get_pointer,
73   _gdk_windowing_window_get_pointer,
74   _gdk_windowing_window_at_pointer
75 };
76
77 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
78   singlehead_get_pointer,
79   singlehead_window_get_pointer,
80   singlehead_window_at_pointer
81 };
82
83 static const GdkPointerHooks singlehead_default_pointer_hooks = {
84   singlehead_default_window_get_pointer,
85   singlehead_default_window_at_pointer
86 };
87
88 static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
89
90 GType
91 gdk_display_get_type (void)
92 {
93
94   static GType object_type = 0;
95
96   if (!object_type)
97     {
98       static const GTypeInfo object_info = {
99         sizeof (GdkDisplayClass),
100         (GBaseInitFunc) NULL,
101         (GBaseFinalizeFunc) NULL,
102         (GClassInitFunc) gdk_display_class_init,
103         NULL,                   /* class_finalize */
104         NULL,                   /* class_data */
105         sizeof (GdkDisplay),
106         0,                      /* n_preallocs */
107         (GInstanceInitFunc) gdk_display_init
108       };
109       object_type = g_type_register_static (G_TYPE_OBJECT,
110                                             g_intern_static_string ("GdkDisplay"), &object_info, 0);
111     }
112
113   return object_type;
114 }
115
116 static void
117 gdk_display_class_init (GdkDisplayClass *class)
118 {
119   GObjectClass *object_class = G_OBJECT_CLASS (class);
120   
121   parent_class = g_type_class_peek_parent (class);
122
123   object_class->finalize = gdk_display_finalize;
124   object_class->dispose = gdk_display_dispose;
125
126   /**
127    * GdkDisplay::closed:
128    * @display: the object on which the signal is emitted
129    * @is_error: %TRUE if the display was closed due to an error
130    *
131    * The ::closed signal is emitted when the connection to the windowing
132    * system for @display is closed.
133    *
134    * Since: 2.2
135    */   
136   signals[CLOSED] =
137     g_signal_new (g_intern_static_string ("closed"),
138                   G_OBJECT_CLASS_TYPE (object_class),
139                   G_SIGNAL_RUN_LAST,
140                   G_STRUCT_OFFSET (GdkDisplayClass, closed),
141                   NULL, NULL,
142                   gdk_marshal_VOID__BOOLEAN,
143                   G_TYPE_NONE,
144                   1,
145                   G_TYPE_BOOLEAN);
146 }
147
148 static void
149 gdk_display_init (GdkDisplay *display)
150 {
151   _gdk_displays = g_slist_prepend (_gdk_displays, display);
152
153   display->button_click_time[0] = display->button_click_time[1] = 0;
154   display->button_window[0] = display->button_window[1] = NULL;
155   display->button_number[0] = display->button_number[1] = -1;
156   display->button_x[0] = display->button_x[1] = 0;
157   display->button_y[0] = display->button_y[1] = 0;
158
159   display->double_click_time = 250;
160   display->double_click_distance = 5;
161
162   display->pointer_hooks = &default_pointer_hooks;
163 }
164
165 static void
166 gdk_display_dispose (GObject *object)
167 {
168   GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
169
170   g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
171   g_list_free (display->queued_events);
172   display->queued_events = NULL;
173   display->queued_tail = NULL;
174
175   _gdk_displays = g_slist_remove (_gdk_displays, object);
176
177   if (gdk_display_get_default() == display)
178     {
179       if (_gdk_displays)
180         gdk_display_manager_set_default_display (gdk_display_manager_get(),
181                                                  _gdk_displays->data);
182       else
183         gdk_display_manager_set_default_display (gdk_display_manager_get(),
184                                                  NULL);
185     }
186
187   G_OBJECT_CLASS (parent_class)->dispose (object);
188 }
189
190 static void
191 gdk_display_finalize (GObject *object)
192 {
193   G_OBJECT_CLASS (parent_class)->finalize (object);
194 }
195
196 /**
197  * gdk_display_close:
198  * @display: a #GdkDisplay
199  *
200  * Closes the connection to the windowing system for the given display,
201  * and cleans up associated resources.
202  *
203  * Since: 2.2
204  */
205 void
206 gdk_display_close (GdkDisplay *display)
207 {
208   g_return_if_fail (GDK_IS_DISPLAY (display));
209
210   if (!display->closed)
211     {
212       display->closed = TRUE;
213       
214       g_signal_emit (display, signals[CLOSED], 0, FALSE);
215       g_object_run_dispose (G_OBJECT (display));
216       
217       g_object_unref (display);
218     }
219 }
220
221 /**
222  * gdk_display_get_event:
223  * @display: a #GdkDisplay
224  * 
225  * Gets the next #GdkEvent to be processed for @display, fetching events from the
226  * windowing system if necessary.
227  * 
228  * Return value: the next #GdkEvent to be processed, or %NULL if no events
229  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
230  *
231  * Since: 2.2
232  **/
233 GdkEvent*
234 gdk_display_get_event (GdkDisplay *display)
235 {
236   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
237   
238   _gdk_events_queue (display);
239   return _gdk_event_unqueue (display);
240 }
241
242 /**
243  * gdk_display_peek_event:
244  * @display: a #GdkDisplay 
245  * 
246  * Gets a copy of the first #GdkEvent in the @display's event queue, without
247  * removing the event from the queue.  (Note that this function will
248  * not get more events from the windowing system.  It only checks the events
249  * that have already been moved to the GDK event queue.)
250  * 
251  * Return value: a copy of the first #GdkEvent on the event queue, or %NULL 
252  * if no events are in the queue. The returned #GdkEvent should be freed with
253  * gdk_event_free().
254  *
255  * Since: 2.2
256  **/
257 GdkEvent*
258 gdk_display_peek_event (GdkDisplay *display)
259 {
260   GList *tmp_list;
261
262   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
263
264   tmp_list = _gdk_event_queue_find_first (display);
265   
266   if (tmp_list)
267     return gdk_event_copy (tmp_list->data);
268   else
269     return NULL;
270 }
271
272 /**
273  * gdk_display_put_event:
274  * @display: a #GdkDisplay
275  * @event: a #GdkEvent.
276  *
277  * Appends a copy of the given event onto the front of the event
278  * queue for @display.
279  *
280  * Since: 2.2
281  **/
282 void
283 gdk_display_put_event (GdkDisplay *display,
284                        GdkEvent   *event)
285 {
286   g_return_if_fail (GDK_IS_DISPLAY (display));
287   g_return_if_fail (event != NULL);
288
289   _gdk_event_queue_append (display, gdk_event_copy (event));
290 }
291
292 /**
293  * gdk_pointer_ungrab:
294  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no 
295  *  timestamp is available.
296  *
297  * Ungrabs the pointer, if it is grabbed by this application.
298  **/
299 void
300 gdk_pointer_ungrab (guint32 time)
301 {
302   gdk_display_pointer_ungrab (gdk_display_get_default (), time);
303 }
304
305 /**
306  * gdk_pointer_is_grabbed:
307  * 
308  * Returns %TRUE if the pointer is currently grabbed by this application.
309  *
310  * Note that this does not take the inmplicit pointer grab on button
311  * presses into account.
312
313  * Return value: %TRUE if the pointer is currently grabbed by this application.* 
314  **/
315 gboolean
316 gdk_pointer_is_grabbed (void)
317 {
318   return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
319 }
320
321 /**
322  * gdk_keyboard_ungrab:
323  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
324  *        timestamp is available.
325  * 
326  * Ungrabs the keyboard, if it is grabbed by this application.
327  **/
328 void
329 gdk_keyboard_ungrab (guint32 time)
330 {
331   gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
332 }
333
334 /**
335  * gdk_beep:
336  * 
337  * Emits a short beep.
338  **/
339 void
340 gdk_beep (void)
341 {
342   gdk_display_beep (gdk_display_get_default ());
343 }
344
345 /**
346  * gdk_event_send_client_message:
347  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
348  * @winid:  the window to send the X ClientMessage event to.
349  * 
350  * Sends an X ClientMessage event to a given window (which must be
351  * on the default #GdkDisplay.)
352  * This could be used for communicating between different applications,
353  * though the amount of data is limited to 20 bytes.
354  * 
355  * Return value: non-zero on success.
356  **/
357 gboolean
358 gdk_event_send_client_message (GdkEvent        *event,
359                                GdkNativeWindow  winid)
360 {
361   g_return_val_if_fail (event != NULL, FALSE);
362
363   return gdk_event_send_client_message_for_display (gdk_display_get_default (),
364                                                     event, winid);
365 }
366
367 /**
368  * gdk_event_send_clientmessage_toall:
369  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
370  *
371  * Sends an X ClientMessage event to all toplevel windows on the default
372  * #GdkScreen.
373  *
374  * Toplevel windows are determined by checking for the WM_STATE property, as
375  * described in the Inter-Client Communication Conventions Manual (ICCCM).
376  * If no windows are found with the WM_STATE property set, the message is sent
377  * to all children of the root window.
378  **/
379 void
380 gdk_event_send_clientmessage_toall (GdkEvent *event)
381 {
382   g_return_if_fail (event != NULL);
383
384   gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
385 }
386
387 /**
388  * gdk_device_get_core_pointer:
389  * 
390  * Returns the core pointer device for the default display.
391  * 
392  * Return value: the core pointer device; this is owned by the
393  *   display and should not be freed.
394  **/
395 GdkDevice *
396 gdk_device_get_core_pointer (void)
397 {
398   return gdk_display_get_core_pointer (gdk_display_get_default ());
399 }
400
401 /**
402  * gdk_display_get_core_pointer:
403  * @display: a #GdkDisplay
404  * 
405  * Returns the core pointer device for the given display
406  * 
407  * Return value: the core pointer device; this is owned by the
408  *   display and should not be freed.
409  *
410  * Since: 2.2
411  **/
412 GdkDevice *
413 gdk_display_get_core_pointer (GdkDisplay *display)
414 {
415   return display->core_pointer;
416 }
417
418 /**
419  * gdk_set_sm_client_id:
420  * @sm_client_id: the client id assigned by the session manager when the
421  *    connection was opened, or %NULL to remove the property.
422  * 
423  * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
424  * the window manager can save the application's state using the X11R6 ICCCM
425  * session management protocol.
426  *
427  * See the X Session Management Library documentation for more information on
428  * session management and the Inter-Client Communication Conventions Manual
429  * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property. 
430  * (Both documents are part of the X Window System distribution.)
431  **/
432 void
433 gdk_set_sm_client_id (const gchar* sm_client_id)
434 {
435   GSList *displays, *tmp_list;
436   
437   g_free (gdk_sm_client_id);
438   gdk_sm_client_id = g_strdup (sm_client_id);
439
440   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
441   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
442     _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
443
444   g_slist_free (displays);
445 }
446
447 /**
448  * _gdk_get_sm_client_id:
449  * 
450  * Gets the client ID set with gdk_set_sm_client_id(), if any.
451  * 
452  * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
453  *               has never been called.
454  **/
455 const char *
456 _gdk_get_sm_client_id (void)
457 {
458   return gdk_sm_client_id;
459 }
460
461 /**
462  * gdk_display_get_pointer:
463  * @display: a #GdkDisplay
464  * @screen: location to store the screen that the
465  *          cursor is on, or %NULL.
466  * @x: location to store root window X coordinate of pointer, or %NULL.
467  * @y: location to store root window Y coordinate of pointer, or %NULL.
468  * @mask: location to store current modifier mask, or %NULL
469  * 
470  * Gets the current location of the pointer and the current modifier
471  * mask for a given display.
472  *
473  * Since: 2.2
474  **/
475 void
476 gdk_display_get_pointer (GdkDisplay      *display,
477                          GdkScreen      **screen,
478                          gint            *x,
479                          gint            *y,
480                          GdkModifierType *mask)
481 {
482   GdkScreen *tmp_screen;
483   gint tmp_x, tmp_y;
484   GdkModifierType tmp_mask;
485   
486   g_return_if_fail (GDK_IS_DISPLAY (display));
487
488   display->pointer_hooks->get_pointer (display, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
489
490   if (screen)
491     *screen = tmp_screen;
492   if (x)
493     *x = tmp_x;
494   if (y)
495     *y = tmp_y;
496   if (mask)
497     *mask = tmp_mask;
498 }
499
500 /**
501  * gdk_display_get_window_at_pointer:
502  * @display: a #GdkDisplay
503  * @win_x: return location for origin of the window under the pointer
504  * @win_y: return location for origin of the window under the pointer
505  * 
506  * Obtains the window underneath the mouse pointer, returning the location
507  * of that window in @win_x, @win_y for @screen. Returns %NULL if the window 
508  * under the mouse pointer is not known to GDK (for example, belongs to
509  * another application).
510  * 
511  * Returns: the window under the mouse pointer, or %NULL
512  *
513  * Since: 2.2
514  **/
515 GdkWindow *
516 gdk_display_get_window_at_pointer (GdkDisplay *display,
517                                    gint       *win_x,
518                                    gint       *win_y)
519 {
520   gint tmp_x, tmp_y;
521   GdkWindow *window;
522
523   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
524
525   window = display->pointer_hooks->window_at_pointer (display, &tmp_x, &tmp_y);
526
527   if (win_x)
528     *win_x = tmp_x;
529   if (win_y)
530     *win_y = tmp_y;
531
532   return window;
533 }
534
535 /**
536  * gdk_display_set_pointer_hooks:
537  * @display: a #GdkDisplay
538  * @new_hooks: a table of pointers to functions for getting
539  *   quantities related to the current pointer position,
540  *   or %NULL to restore the default table.
541  * 
542  * This function allows for hooking into the operation
543  * of getting the current location of the pointer on a particular
544  * display. This is only useful for such low-level tools as an
545  * event recorder. Applications should never have any
546  * reason to use this facility.
547  *
548  * Return value: the previous pointer hook table
549  *
550  * Since: 2.2
551  **/
552 GdkDisplayPointerHooks *
553 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
554                                const GdkDisplayPointerHooks *new_hooks)
555 {
556   const GdkDisplayPointerHooks *result;
557
558   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
559   result = display->pointer_hooks;
560
561   if (new_hooks)
562     display->pointer_hooks = new_hooks;
563   else
564     display->pointer_hooks = &default_pointer_hooks;
565
566   return (GdkDisplayPointerHooks *)result;
567 }
568
569 static void
570 singlehead_get_pointer (GdkDisplay       *display,
571                         GdkScreen       **screen,
572                         gint             *x,
573                         gint             *y,
574                         GdkModifierType  *mask)
575 {
576   GdkScreen *default_screen = gdk_display_get_default_screen (display);
577   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
578
579   *screen = default_screen;
580
581   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
582 }
583
584 static GdkWindow*
585 singlehead_window_get_pointer (GdkDisplay       *display,
586                                GdkWindow        *window,
587                                gint             *x,
588                                gint             *y,
589                                GdkModifierType  *mask)
590 {
591   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
592 }
593
594 static GdkWindow*
595 singlehead_window_at_pointer   (GdkDisplay *display,
596                                 gint       *win_x,
597                                 gint       *win_y)
598 {
599   GdkScreen *default_screen = gdk_display_get_default_screen (display);
600
601   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
602                                                               win_x, win_y);
603 }
604
605 static GdkWindow*
606 singlehead_default_window_get_pointer (GdkWindow       *window,
607                                        gint            *x,
608                                        gint            *y,
609                                        GdkModifierType *mask)
610 {
611   return _gdk_windowing_window_get_pointer (gdk_drawable_get_display (window),
612                                             window, x, y, mask);
613 }
614
615 static GdkWindow*
616 singlehead_default_window_at_pointer  (GdkScreen       *screen,
617                                        gint            *win_x,
618                                        gint            *win_y)
619 {
620   return _gdk_windowing_window_at_pointer (gdk_screen_get_display (screen),
621                                            win_x, win_y);
622 }
623
624 /**
625  * gdk_set_pointer_hooks:
626  * @new_hooks: a table of pointers to functions for getting
627  *   quantities related to the current pointer position,
628  *   or %NULL to restore the default table.
629  * 
630  * This function allows for hooking into the operation
631  * of getting the current location of the pointer. This
632  * is only useful for such low-level tools as an
633  * event recorder. Applications should never have any
634  * reason to use this facility.
635  *
636  * This function is not multihead safe. For multihead operation,
637  * see gdk_display_set_pointer_hooks().
638  * 
639  * Return value: the previous pointer hook table
640  **/
641 GdkPointerHooks *
642 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
643 {
644   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
645
646   if (new_hooks)
647     singlehead_current_pointer_hooks = new_hooks;
648   else
649     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
650
651   gdk_display_set_pointer_hooks (gdk_display_get_default (),
652                                  &singlehead_pointer_hooks);
653   
654   return (GdkPointerHooks *)result;
655 }
656
657 #define __GDK_DISPLAY_C__
658 #include "gdkaliasdef.c"