Blame gdk/gdkdisplay.c

Packit 98cdb6
/* GDK - The GIMP Drawing Kit
Packit 98cdb6
 * gdkdisplay.c
Packit 98cdb6
 * 
Packit 98cdb6
 * Copyright 2001 Sun Microsystems Inc. 
Packit 98cdb6
 *
Packit 98cdb6
 * Erwann Chenede <erwann.chenede@sun.com>
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Library General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 98cdb6
 * Library General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Library General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
#include <math.h>
Packit 98cdb6
#include <glib.h>
Packit 98cdb6
#include "gdk.h"		/* gdk_event_send_client_message() */
Packit 98cdb6
#include "gdkdisplay.h"
Packit 98cdb6
#include "gdkwindowimpl.h"
Packit 98cdb6
#include "gdkinternals.h"
Packit 98cdb6
#include "gdkmarshalers.h"
Packit 98cdb6
#include "gdkscreen.h"
Packit 98cdb6
#include "gdkalias.h"
Packit 98cdb6
Packit 98cdb6
enum {
Packit 98cdb6
  CLOSED,
Packit 98cdb6
  LAST_SIGNAL
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static void gdk_display_dispose    (GObject         *object);
Packit 98cdb6
static void gdk_display_finalize   (GObject         *object);
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
static void       singlehead_get_pointer (GdkDisplay       *display,
Packit 98cdb6
					  GdkScreen       **screen,
Packit 98cdb6
					  gint             *x,
Packit 98cdb6
					  gint             *y,
Packit 98cdb6
					  GdkModifierType  *mask);
Packit 98cdb6
static GdkWindow* singlehead_window_get_pointer (GdkDisplay       *display,
Packit 98cdb6
						 GdkWindow        *window,
Packit 98cdb6
						 gint             *x,
Packit 98cdb6
						 gint             *y,
Packit 98cdb6
						 GdkModifierType  *mask);
Packit 98cdb6
static GdkWindow* singlehead_window_at_pointer  (GdkDisplay       *display,
Packit 98cdb6
						 gint             *win_x,
Packit 98cdb6
						 gint             *win_y);
Packit 98cdb6
Packit 98cdb6
static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window,
Packit 98cdb6
							 gint            *x,
Packit 98cdb6
							 gint            *y,
Packit 98cdb6
							 GdkModifierType *mask);
Packit 98cdb6
static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
Packit 98cdb6
							 gint            *win_x,
Packit 98cdb6
							 gint            *win_y);
Packit 98cdb6
static GdkWindow *gdk_window_real_window_get_pointer     (GdkDisplay       *display,
Packit 98cdb6
                                                          GdkWindow        *window,
Packit 98cdb6
                                                          gint             *x,
Packit 98cdb6
                                                          gint             *y,
Packit 98cdb6
                                                          GdkModifierType  *mask);
Packit 98cdb6
static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay       *display,
Packit 98cdb6
                                                          gint             *win_x,
Packit 98cdb6
                                                          gint             *win_y);
Packit 98cdb6
Packit 98cdb6
static guint signals[LAST_SIGNAL] = { 0 };
Packit 98cdb6
Packit 98cdb6
static char *gdk_sm_client_id;
Packit 98cdb6
Packit 98cdb6
static const GdkDisplayPointerHooks default_pointer_hooks = {
Packit 98cdb6
  _gdk_windowing_get_pointer,
Packit 98cdb6
  gdk_window_real_window_get_pointer,
Packit 98cdb6
  gdk_display_real_get_window_at_pointer
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
Packit 98cdb6
  singlehead_get_pointer,
Packit 98cdb6
  singlehead_window_get_pointer,
Packit 98cdb6
  singlehead_window_at_pointer
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static const GdkPointerHooks singlehead_default_pointer_hooks = {
Packit 98cdb6
  singlehead_default_window_get_pointer,
Packit 98cdb6
  singlehead_default_window_at_pointer
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
Packit 98cdb6
Packit 98cdb6
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_display_class_init (GdkDisplayClass *class)
Packit 98cdb6
{
Packit 98cdb6
  GObjectClass *object_class = G_OBJECT_CLASS (class);
Packit 98cdb6
  
Packit 98cdb6
  object_class->finalize = gdk_display_finalize;
Packit 98cdb6
  object_class->dispose = gdk_display_dispose;
Packit 98cdb6
Packit 98cdb6
  /**
Packit 98cdb6
   * GdkDisplay::closed:
Packit 98cdb6
   * @display: the object on which the signal is emitted
Packit 98cdb6
   * @is_error: %TRUE if the display was closed due to an error
Packit 98cdb6
   *
Packit 98cdb6
   * The ::closed signal is emitted when the connection to the windowing
Packit 98cdb6
   * system for @display is closed.
Packit 98cdb6
   *
Packit 98cdb6
   * Since: 2.2
Packit 98cdb6
   */   
Packit 98cdb6
  signals[CLOSED] =
Packit 98cdb6
    g_signal_new (g_intern_static_string ("closed"),
Packit 98cdb6
		  G_OBJECT_CLASS_TYPE (object_class),
Packit 98cdb6
		  G_SIGNAL_RUN_LAST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GdkDisplayClass, closed),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  _gdk_marshal_VOID__BOOLEAN,
Packit 98cdb6
		  G_TYPE_NONE,
Packit 98cdb6
		  1,
Packit 98cdb6
		  G_TYPE_BOOLEAN);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_display_init (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  _gdk_displays = g_slist_prepend (_gdk_displays, display);
Packit 98cdb6
Packit 98cdb6
  display->button_click_time[0] = display->button_click_time[1] = 0;
Packit 98cdb6
  display->button_window[0] = display->button_window[1] = NULL;
Packit 98cdb6
  display->button_number[0] = display->button_number[1] = -1;
Packit 98cdb6
  display->button_x[0] = display->button_x[1] = 0;
Packit 98cdb6
  display->button_y[0] = display->button_y[1] = 0;
Packit 98cdb6
Packit 98cdb6
  display->double_click_time = 250;
Packit 98cdb6
  display->double_click_distance = 5;
Packit 98cdb6
Packit 98cdb6
  display->pointer_hooks = &default_pointer_hooks;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_display_dispose (GObject *object)
Packit 98cdb6
{
Packit 98cdb6
  GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
Packit 98cdb6
Packit 98cdb6
  g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
Packit 98cdb6
  g_list_free (display->queued_events);
Packit 98cdb6
  display->queued_events = NULL;
Packit 98cdb6
  display->queued_tail = NULL;
Packit 98cdb6
Packit 98cdb6
  _gdk_displays = g_slist_remove (_gdk_displays, object);
Packit 98cdb6
Packit 98cdb6
  if (gdk_display_get_default() == display)
Packit 98cdb6
    {
Packit 98cdb6
      if (_gdk_displays)
Packit 98cdb6
        gdk_display_manager_set_default_display (gdk_display_manager_get(),
Packit 98cdb6
                                                 _gdk_displays->data);
Packit 98cdb6
      else
Packit 98cdb6
        gdk_display_manager_set_default_display (gdk_display_manager_get(),
Packit 98cdb6
                                                 NULL);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_display_finalize (GObject *object)
Packit 98cdb6
{
Packit 98cdb6
  G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_close:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 *
Packit 98cdb6
 * Closes the connection to the windowing system for the given display,
Packit 98cdb6
 * and cleans up associated resources.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 */
Packit 98cdb6
void
Packit 98cdb6
gdk_display_close (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GDK_IS_DISPLAY (display));
Packit 98cdb6
Packit 98cdb6
  if (!display->closed)
Packit 98cdb6
    {
Packit 98cdb6
      display->closed = TRUE;
Packit 98cdb6
      
Packit 98cdb6
      g_signal_emit (display, signals[CLOSED], 0, FALSE);
Packit 98cdb6
      g_object_run_dispose (G_OBJECT (display));
Packit 98cdb6
      
Packit 98cdb6
      g_object_unref (display);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_is_closed:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 *
Packit 98cdb6
 * Finds out if the display has been closed.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns: %TRUE if the display is closed.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.22
Packit 98cdb6
 */
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_display_is_closed  (GdkDisplay  *display)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
Packit 98cdb6
Packit 98cdb6
  return display->closed;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_get_event:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 * 
Packit 98cdb6
 * Gets the next #GdkEvent to be processed for @display, fetching events from the
Packit 98cdb6
 * windowing system if necessary.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: the next #GdkEvent to be processed, or %NULL if no events
Packit 98cdb6
 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
GdkEvent*
Packit 98cdb6
gdk_display_get_event (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
Packit 98cdb6
  
Packit 98cdb6
  _gdk_events_queue (display);
Packit 98cdb6
  return _gdk_event_unqueue (display);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_peek_event:
Packit 98cdb6
 * @display: a #GdkDisplay 
Packit 98cdb6
 * 
Packit 98cdb6
 * Gets a copy of the first #GdkEvent in the @display's event queue, without
Packit 98cdb6
 * removing the event from the queue.  (Note that this function will
Packit 98cdb6
 * not get more events from the windowing system.  It only checks the events
Packit 98cdb6
 * that have already been moved to the GDK event queue.)
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL 
Packit 98cdb6
 * if no events are in the queue. The returned #GdkEvent should be freed with
Packit 98cdb6
 * gdk_event_free().
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
GdkEvent*
Packit 98cdb6
gdk_display_peek_event (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  GList *tmp_list;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
Packit 98cdb6
Packit 98cdb6
  tmp_list = _gdk_event_queue_find_first (display);
Packit 98cdb6
  
Packit 98cdb6
  if (tmp_list)
Packit 98cdb6
    return gdk_event_copy (tmp_list->data);
Packit 98cdb6
  else
Packit 98cdb6
    return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_put_event:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 * @event: a #GdkEvent.
Packit 98cdb6
 *
Packit 98cdb6
 * Appends a copy of the given event onto the front of the event
Packit 98cdb6
 * queue for @display.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_display_put_event (GdkDisplay     *display,
Packit 98cdb6
		       const GdkEvent *event)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GDK_IS_DISPLAY (display));
Packit 98cdb6
  g_return_if_fail (event != NULL);
Packit 98cdb6
Packit 98cdb6
  _gdk_event_queue_append (display, gdk_event_copy (event));
Packit 98cdb6
  /* If the main loop is blocking in a different thread, wake it up */
Packit 98cdb6
  g_main_context_wakeup (NULL); 
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_pointer_ungrab:
Packit 98cdb6
 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no 
Packit 98cdb6
 *  timestamp is available.
Packit 98cdb6
 *
Packit 98cdb6
 * Ungrabs the pointer on the default display, if it is grabbed by this 
Packit 98cdb6
 * application.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_pointer_ungrab (guint32 time)
Packit 98cdb6
{
Packit 98cdb6
  gdk_display_pointer_ungrab (gdk_display_get_default (), time);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_pointer_is_grabbed:
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns %TRUE if the pointer on the default display is currently 
Packit 98cdb6
 * grabbed by this application.
Packit 98cdb6
 *
Packit 98cdb6
 * Note that this does not take the inmplicit pointer grab on button
Packit 98cdb6
 * presses into account.
Packit 98cdb6
Packit 98cdb6
 * Return value: %TRUE if the pointer is currently grabbed by this application.* 
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_pointer_is_grabbed (void)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_keyboard_ungrab:
Packit 98cdb6
 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
Packit 98cdb6
 *        timestamp is available.
Packit 98cdb6
 * 
Packit 98cdb6
 * Ungrabs the keyboard on the default display, if it is grabbed by this 
Packit 98cdb6
 * application.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_keyboard_ungrab (guint32 time)
Packit 98cdb6
{
Packit 98cdb6
  gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_beep:
Packit 98cdb6
 * 
Packit 98cdb6
 * Emits a short beep on the default display.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_beep (void)
Packit 98cdb6
{
Packit 98cdb6
  gdk_display_beep (gdk_display_get_default ());
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_event_send_client_message:
Packit 98cdb6
 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
Packit 98cdb6
 * @winid:  the window to send the X ClientMessage event to.
Packit 98cdb6
 * 
Packit 98cdb6
 * Sends an X ClientMessage event to a given window (which must be
Packit 98cdb6
 * on the default #GdkDisplay.)
Packit 98cdb6
 * This could be used for communicating between different applications,
Packit 98cdb6
 * though the amount of data is limited to 20 bytes.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: non-zero on success.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_event_send_client_message (GdkEvent        *event,
Packit 98cdb6
			       GdkNativeWindow  winid)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (event != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  return gdk_event_send_client_message_for_display (gdk_display_get_default (),
Packit 98cdb6
						    event, winid);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_event_send_clientmessage_toall:
Packit 98cdb6
 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
Packit 98cdb6
 *
Packit 98cdb6
 * Sends an X ClientMessage event to all toplevel windows on the default
Packit 98cdb6
 * #GdkScreen.
Packit 98cdb6
 *
Packit 98cdb6
 * Toplevel windows are determined by checking for the WM_STATE property, as
Packit 98cdb6
 * described in the Inter-Client Communication Conventions Manual (ICCCM).
Packit 98cdb6
 * If no windows are found with the WM_STATE property set, the message is sent
Packit 98cdb6
 * to all children of the root window.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_event_send_clientmessage_toall (GdkEvent *event)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (event != NULL);
Packit 98cdb6
Packit 98cdb6
  gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_device_get_core_pointer:
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns the core pointer device for the default display.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: the core pointer device; this is owned by the
Packit 98cdb6
 *   display and should not be freed.
Packit 98cdb6
 **/
Packit 98cdb6
GdkDevice *
Packit 98cdb6
gdk_device_get_core_pointer (void)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_display_get_core_pointer (gdk_display_get_default ());
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_get_core_pointer:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns the core pointer device for the given display
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: the core pointer device; this is owned by the
Packit 98cdb6
 *   display and should not be freed.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
GdkDevice *
Packit 98cdb6
gdk_display_get_core_pointer (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  return display->core_pointer;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_set_sm_client_id:
Packit 98cdb6
 * @sm_client_id: the client id assigned by the session manager when the
Packit 98cdb6
 *    connection was opened, or %NULL to remove the property.
Packit 98cdb6
 * 
Packit 98cdb6
 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
Packit 98cdb6
 * the window manager can save the application's state using the X11R6 ICCCM
Packit 98cdb6
 * session management protocol.
Packit 98cdb6
 *
Packit 98cdb6
 * See the X Session Management Library documentation for more information on
Packit 98cdb6
 * session management and the Inter-Client Communication Conventions Manual
Packit 98cdb6
 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property. 
Packit 98cdb6
 * (Both documents are part of the X Window System distribution.)
Packit 98cdb6
 *
Packit 98cdb6
 * Deprecated:2.24: Use gdk_x11_set_sm_client_id() instead
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_set_sm_client_id (const gchar* sm_client_id)
Packit 98cdb6
{
Packit 98cdb6
  GSList *displays, *tmp_list;
Packit 98cdb6
  
Packit 98cdb6
  g_free (gdk_sm_client_id);
Packit 98cdb6
  gdk_sm_client_id = g_strdup (sm_client_id);
Packit 98cdb6
Packit 98cdb6
  displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
Packit 98cdb6
  for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
Packit 98cdb6
    _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
Packit 98cdb6
Packit 98cdb6
  g_slist_free (displays);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gdk_get_sm_client_id:
Packit 98cdb6
 * 
Packit 98cdb6
 * Gets the client ID set with gdk_set_sm_client_id(), if any.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
Packit 98cdb6
 *               has never been called.
Packit 98cdb6
 **/
Packit 98cdb6
const char *
Packit 98cdb6
_gdk_get_sm_client_id (void)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_sm_client_id;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
_gdk_display_enable_motion_hints (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  gulong serial;
Packit 98cdb6
  
Packit 98cdb6
  if (display->pointer_info.motion_hint_serial != 0)
Packit 98cdb6
    {
Packit 98cdb6
      serial = _gdk_windowing_window_get_next_serial (display);
Packit 98cdb6
      /* We might not actually generate the next request, so
Packit 98cdb6
	 make sure this triggers always, this may cause it to
Packit 98cdb6
	 trigger slightly too early, but this is just a hint
Packit 98cdb6
	 anyway. */
Packit 98cdb6
      if (serial > 0)
Packit 98cdb6
	serial--;
Packit 98cdb6
      if (serial < display->pointer_info.motion_hint_serial)
Packit 98cdb6
	display->pointer_info.motion_hint_serial = serial;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_get_pointer:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 * @screen: (out) (allow-none): location to store the screen that the
Packit 98cdb6
 *          cursor is on, or %NULL.
Packit 98cdb6
 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
Packit 98cdb6
 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
Packit 98cdb6
 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
Packit 98cdb6
 *
Packit 98cdb6
 * Gets the current location of the pointer and the current modifier
Packit 98cdb6
 * mask for a given display.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gdk_display_get_pointer (GdkDisplay      *display,
Packit 98cdb6
			 GdkScreen      **screen,
Packit 98cdb6
			 gint            *x,
Packit 98cdb6
			 gint            *y,
Packit 98cdb6
			 GdkModifierType *mask)
Packit 98cdb6
{
Packit 98cdb6
  GdkScreen *tmp_screen;
Packit 98cdb6
  gint tmp_x, tmp_y;
Packit 98cdb6
  GdkModifierType tmp_mask;
Packit 98cdb6
  
Packit 98cdb6
  g_return_if_fail (GDK_IS_DISPLAY (display));
Packit 98cdb6
Packit 98cdb6
  display->pointer_hooks->get_pointer (display, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
Packit 98cdb6
Packit 98cdb6
  if (screen)
Packit 98cdb6
    *screen = tmp_screen;
Packit 98cdb6
  if (x)
Packit 98cdb6
    *x = tmp_x;
Packit 98cdb6
  if (y)
Packit 98cdb6
    *y = tmp_y;
Packit 98cdb6
  if (mask)
Packit 98cdb6
    *mask = tmp_mask;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow *
Packit 98cdb6
gdk_display_real_get_window_at_pointer (GdkDisplay *display,
Packit 98cdb6
                                        gint       *win_x,
Packit 98cdb6
                                        gint       *win_y)
Packit 98cdb6
{
Packit 98cdb6
  GdkWindow *window;
Packit 98cdb6
  gint x, y;
Packit 98cdb6
Packit 98cdb6
  window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  /* This might need corrections, as the native window returned
Packit 98cdb6
     may contain client side children */
Packit 98cdb6
  if (window)
Packit 98cdb6
    {
Packit 98cdb6
      double xx, yy;
Packit 98cdb6
Packit 98cdb6
      window = _gdk_window_find_descendant_at (window,
Packit 98cdb6
					       x, y,
Packit 98cdb6
					       &xx, &yy;;
Packit 98cdb6
      x = floor (xx + 0.5);
Packit 98cdb6
      y = floor (yy + 0.5);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  *win_x = x;
Packit 98cdb6
  *win_y = y;
Packit 98cdb6
Packit 98cdb6
  return window;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow *
Packit 98cdb6
gdk_window_real_window_get_pointer (GdkDisplay       *display,
Packit 98cdb6
                                    GdkWindow        *window,
Packit 98cdb6
                                    gint             *x,
Packit 98cdb6
                                    gint             *y,
Packit 98cdb6
                                    GdkModifierType  *mask)
Packit 98cdb6
{
Packit 98cdb6
  GdkWindowObject *private;
Packit 98cdb6
  gint tmpx, tmpy;
Packit 98cdb6
  GdkModifierType tmp_mask;
Packit 98cdb6
  gboolean normal_child;
Packit 98cdb6
Packit 98cdb6
  private = (GdkWindowObject *) window;
Packit 98cdb6
Packit 98cdb6
  normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_pointer (window,
Packit 98cdb6
									 &tmpx, &tmpy,
Packit 98cdb6
									 &tmp_mask);
Packit 98cdb6
  /* We got the coords on the impl, convert to the window */
Packit 98cdb6
  tmpx -= private->abs_x;
Packit 98cdb6
  tmpy -= private->abs_y;
Packit 98cdb6
Packit 98cdb6
  if (x)
Packit 98cdb6
    *x = tmpx;
Packit 98cdb6
  if (y)
Packit 98cdb6
    *y = tmpy;
Packit 98cdb6
  if (mask)
Packit 98cdb6
    *mask = tmp_mask;
Packit 98cdb6
Packit 98cdb6
  if (normal_child)
Packit 98cdb6
    return _gdk_window_find_child_at (window, tmpx, tmpy);
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_get_window_at_pointer:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
Packit 98cdb6
 *    to the window origin, or %NULL
Packit 98cdb6
 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
Packit 98cdb6
 &    to the window origin, or %NULL
Packit 98cdb6
 *
Packit 98cdb6
 * Obtains the window underneath the mouse pointer, returning the location
Packit 98cdb6
 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
Packit 98cdb6
 * if the window under the mouse pointer is not known to GDK (for example, 
Packit 98cdb6
 * belongs to another application).
Packit 98cdb6
 *
Packit 98cdb6
 * Returns: (transfer none): the window under the mouse pointer, or %NULL
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
GdkWindow *
Packit 98cdb6
gdk_display_get_window_at_pointer (GdkDisplay *display,
Packit 98cdb6
				   gint       *win_x,
Packit 98cdb6
				   gint       *win_y)
Packit 98cdb6
{
Packit 98cdb6
  gint tmp_x, tmp_y;
Packit 98cdb6
  GdkWindow *window;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
Packit 98cdb6
Packit 98cdb6
  window = display->pointer_hooks->window_at_pointer (display, &tmp_x, &tmp_y);
Packit 98cdb6
Packit 98cdb6
  if (win_x)
Packit 98cdb6
    *win_x = tmp_x;
Packit 98cdb6
  if (win_y)
Packit 98cdb6
    *win_y = tmp_y;
Packit 98cdb6
Packit 98cdb6
  return window;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_set_pointer_hooks:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 * @new_hooks: a table of pointers to functions for getting
Packit 98cdb6
 *   quantities related to the current pointer position,
Packit 98cdb6
 *   or %NULL to restore the default table.
Packit 98cdb6
 * 
Packit 98cdb6
 * This function allows for hooking into the operation
Packit 98cdb6
 * of getting the current location of the pointer on a particular
Packit 98cdb6
 * display. This is only useful for such low-level tools as an
Packit 98cdb6
 * event recorder. Applications should never have any
Packit 98cdb6
 * reason to use this facility.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: the previous pointer hook table
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 *
Packit 98cdb6
 * Deprecated: 2.24: This function will go away in GTK 3 for lack of use cases.
Packit 98cdb6
 **/
Packit 98cdb6
GdkDisplayPointerHooks *
Packit 98cdb6
gdk_display_set_pointer_hooks (GdkDisplay                   *display,
Packit 98cdb6
			       const GdkDisplayPointerHooks *new_hooks)
Packit 98cdb6
{
Packit 98cdb6
  const GdkDisplayPointerHooks *result;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
Packit 98cdb6
  result = display->pointer_hooks;
Packit 98cdb6
Packit 98cdb6
  if (new_hooks)
Packit 98cdb6
    display->pointer_hooks = new_hooks;
Packit 98cdb6
  else
Packit 98cdb6
    display->pointer_hooks = &default_pointer_hooks;
Packit 98cdb6
Packit 98cdb6
  return (GdkDisplayPointerHooks *)result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
singlehead_get_pointer (GdkDisplay       *display,
Packit 98cdb6
			GdkScreen       **screen,
Packit 98cdb6
			gint             *x,
Packit 98cdb6
			gint             *y,
Packit 98cdb6
			GdkModifierType  *mask)
Packit 98cdb6
{
Packit 98cdb6
  GdkScreen *default_screen = gdk_display_get_default_screen (display);
Packit 98cdb6
  GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
Packit 98cdb6
Packit 98cdb6
  *screen = default_screen;
Packit 98cdb6
Packit 98cdb6
  singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow*
Packit 98cdb6
singlehead_window_get_pointer (GdkDisplay       *display,
Packit 98cdb6
			       GdkWindow        *window,
Packit 98cdb6
			       gint             *x,
Packit 98cdb6
			       gint             *y,
Packit 98cdb6
			       GdkModifierType  *mask)
Packit 98cdb6
{
Packit 98cdb6
  return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow*
Packit 98cdb6
singlehead_window_at_pointer   (GdkDisplay *display,
Packit 98cdb6
				gint       *win_x,
Packit 98cdb6
				gint       *win_y)
Packit 98cdb6
{
Packit 98cdb6
  GdkScreen *default_screen = gdk_display_get_default_screen (display);
Packit 98cdb6
Packit 98cdb6
  return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
Packit 98cdb6
							      win_x, win_y);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow*
Packit 98cdb6
singlehead_default_window_get_pointer (GdkWindow       *window,
Packit 98cdb6
				       gint            *x,
Packit 98cdb6
				       gint            *y,
Packit 98cdb6
				       GdkModifierType *mask)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
Packit 98cdb6
                                             window, x, y, mask);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow*
Packit 98cdb6
singlehead_default_window_at_pointer  (GdkScreen       *screen,
Packit 98cdb6
				       gint            *win_x,
Packit 98cdb6
				       gint            *win_y)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
Packit 98cdb6
                                                 win_x, win_y);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_set_pointer_hooks:
Packit 98cdb6
 * @new_hooks: a table of pointers to functions for getting
Packit 98cdb6
 *   quantities related to the current pointer position,
Packit 98cdb6
 *   or %NULL to restore the default table.
Packit 98cdb6
 * 
Packit 98cdb6
 * This function allows for hooking into the operation
Packit 98cdb6
 * of getting the current location of the pointer. This
Packit 98cdb6
 * is only useful for such low-level tools as an
Packit 98cdb6
 * event recorder. Applications should never have any
Packit 98cdb6
 * reason to use this facility.
Packit 98cdb6
 *
Packit 98cdb6
 * This function is not multihead safe. For multihead operation,
Packit 98cdb6
 * see gdk_display_set_pointer_hooks().
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: the previous pointer hook table
Packit 98cdb6
 *
Packit 98cdb6
 * Deprecated: 2.24: This function will go away in GTK 3 for lack of use cases.
Packit 98cdb6
 **/
Packit 98cdb6
GdkPointerHooks *
Packit 98cdb6
gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
Packit 98cdb6
{
Packit 98cdb6
  const GdkPointerHooks *result = singlehead_current_pointer_hooks;
Packit 98cdb6
Packit 98cdb6
  if (new_hooks)
Packit 98cdb6
    singlehead_current_pointer_hooks = new_hooks;
Packit 98cdb6
  else
Packit 98cdb6
    singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
Packit 98cdb6
Packit 98cdb6
  gdk_display_set_pointer_hooks (gdk_display_get_default (),
Packit 98cdb6
				 &singlehead_pointer_hooks);
Packit 98cdb6
  
Packit 98cdb6
  return (GdkPointerHooks *)result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
generate_grab_broken_event (GdkWindow *window,
Packit 98cdb6
			    gboolean   keyboard,
Packit 98cdb6
			    gboolean   implicit,
Packit 98cdb6
			    GdkWindow *grab_window)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (window != NULL);
Packit 98cdb6
Packit 98cdb6
  if (!GDK_WINDOW_DESTROYED (window))
Packit 98cdb6
    {
Packit 98cdb6
      GdkEvent event;
Packit 98cdb6
      event.type = GDK_GRAB_BROKEN;
Packit 98cdb6
      event.grab_broken.window = window;
Packit 98cdb6
      event.grab_broken.send_event = 0;
Packit 98cdb6
      event.grab_broken.keyboard = keyboard;
Packit 98cdb6
      event.grab_broken.implicit = implicit;
Packit 98cdb6
      event.grab_broken.grab_window = grab_window;
Packit 98cdb6
      gdk_event_put (&event);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
GdkPointerGrabInfo *
Packit 98cdb6
_gdk_display_get_last_pointer_grab (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  GList *l;
Packit 98cdb6
Packit 98cdb6
  l = g_list_last (display->pointer_grabs);
Packit 98cdb6
Packit 98cdb6
  if (l == NULL)
Packit 98cdb6
    return NULL;
Packit 98cdb6
  else
Packit 98cdb6
    return (GdkPointerGrabInfo *)l->data;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
GdkPointerGrabInfo *
Packit 98cdb6
_gdk_display_add_pointer_grab (GdkDisplay *display,
Packit 98cdb6
			       GdkWindow *window,
Packit 98cdb6
			       GdkWindow *native_window,
Packit 98cdb6
			       gboolean owner_events,
Packit 98cdb6
			       GdkEventMask event_mask,
Packit 98cdb6
			       unsigned long serial_start,
Packit 98cdb6
			       guint32 time,
Packit 98cdb6
			       gboolean implicit)
Packit 98cdb6
{
Packit 98cdb6
  GdkPointerGrabInfo *info, *other_info;
Packit 98cdb6
  GList *l;
Packit 98cdb6
Packit 98cdb6
  info = g_new0 (GdkPointerGrabInfo, 1);
Packit 98cdb6
Packit 98cdb6
  info->window = g_object_ref (window);
Packit 98cdb6
  info->native_window = g_object_ref (native_window);
Packit 98cdb6
  info->serial_start = serial_start;
Packit 98cdb6
  info->serial_end = G_MAXULONG;
Packit 98cdb6
  info->owner_events = owner_events;
Packit 98cdb6
  info->event_mask = event_mask;
Packit 98cdb6
  info->time = time;
Packit 98cdb6
  info->implicit = implicit;
Packit 98cdb6
Packit 98cdb6
  /* Find the first grab that has a larger start time (if any) and insert
Packit 98cdb6
   * before that. I.E we insert after already existing grabs with same
Packit 98cdb6
   * start time */
Packit 98cdb6
  for (l = display->pointer_grabs; l != NULL; l = l->next)
Packit 98cdb6
    {
Packit 98cdb6
      other_info = l->data;
Packit 98cdb6
      
Packit 98cdb6
      if (info->serial_start < other_info->serial_start)
Packit 98cdb6
	break;
Packit 98cdb6
    }
Packit 98cdb6
  display->pointer_grabs =
Packit 98cdb6
    g_list_insert_before (display->pointer_grabs, l, info);
Packit 98cdb6
Packit 98cdb6
  /* Make sure the new grab end before next grab */
Packit 98cdb6
  if (l)
Packit 98cdb6
    {
Packit 98cdb6
      other_info = l->data;
Packit 98cdb6
      info->serial_end = other_info->serial_start;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  /* Find any previous grab and update its end time */
Packit 98cdb6
  l = g_list_find  (display->pointer_grabs, info);
Packit 98cdb6
  l = l->prev;
Packit 98cdb6
  if (l)
Packit 98cdb6
    {
Packit 98cdb6
      other_info = l->data;
Packit 98cdb6
      other_info->serial_end = serial_start;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return info;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
free_pointer_grab (GdkPointerGrabInfo *info)
Packit 98cdb6
{
Packit 98cdb6
  g_object_unref (info->window);
Packit 98cdb6
  g_object_unref (info->native_window);
Packit 98cdb6
  g_free (info);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* _gdk_synthesize_crossing_events only works inside one toplevel.
Packit 98cdb6
   This function splits things into two calls if needed, converting the
Packit 98cdb6
   coordinates to the right toplevel */
Packit 98cdb6
static void
Packit 98cdb6
synthesize_crossing_events (GdkDisplay *display,
Packit 98cdb6
			    GdkWindow *src_window,
Packit 98cdb6
			    GdkWindow *dest_window,
Packit 98cdb6
			    GdkCrossingMode crossing_mode,
Packit 98cdb6
			    guint32 time,
Packit 98cdb6
			    gulong serial)
Packit 98cdb6
{
Packit 98cdb6
  GdkWindow *src_toplevel, *dest_toplevel;
Packit 98cdb6
  GdkModifierType state;
Packit 98cdb6
  int x, y;
Packit 98cdb6
Packit 98cdb6
  /* We use the native crossing events if all native */
Packit 98cdb6
  if (_gdk_native_windows)
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  if (src_window)
Packit 98cdb6
    src_toplevel = gdk_window_get_toplevel (src_window);
Packit 98cdb6
  else
Packit 98cdb6
    src_toplevel = NULL;
Packit 98cdb6
  if (dest_window)
Packit 98cdb6
    dest_toplevel = gdk_window_get_toplevel (dest_window);
Packit 98cdb6
  else
Packit 98cdb6
    dest_toplevel = NULL;
Packit 98cdb6
Packit 98cdb6
  if (src_toplevel == NULL && dest_toplevel == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  if (src_toplevel == NULL ||
Packit 98cdb6
      src_toplevel == dest_toplevel)
Packit 98cdb6
    {
Packit 98cdb6
      /* Same toplevels */
Packit 98cdb6
      gdk_window_get_pointer (dest_toplevel,
Packit 98cdb6
			      &x, &y, &state);
Packit 98cdb6
      _gdk_synthesize_crossing_events (display,
Packit 98cdb6
				       src_window,
Packit 98cdb6
				       dest_window,
Packit 98cdb6
				       crossing_mode,
Packit 98cdb6
				       x, y, state,
Packit 98cdb6
				       time,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       serial, FALSE);
Packit 98cdb6
    }
Packit 98cdb6
  else if (dest_toplevel == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gdk_window_get_pointer (src_toplevel,
Packit 98cdb6
			      &x, &y, &state);
Packit 98cdb6
      _gdk_synthesize_crossing_events (display,
Packit 98cdb6
				       src_window,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       crossing_mode,
Packit 98cdb6
				       x, y, state,
Packit 98cdb6
				       time,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       serial, FALSE);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      /* Different toplevels */
Packit 98cdb6
      gdk_window_get_pointer (src_toplevel,
Packit 98cdb6
			      &x, &y, &state);
Packit 98cdb6
      _gdk_synthesize_crossing_events (display,
Packit 98cdb6
				       src_window,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       crossing_mode,
Packit 98cdb6
				       x, y, state,
Packit 98cdb6
				       time,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       serial, FALSE);
Packit 98cdb6
      gdk_window_get_pointer (dest_toplevel,
Packit 98cdb6
			      &x, &y, &state);
Packit 98cdb6
      _gdk_synthesize_crossing_events (display,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       dest_window,
Packit 98cdb6
				       crossing_mode,
Packit 98cdb6
				       x, y, state,
Packit 98cdb6
				       time,
Packit 98cdb6
				       NULL,
Packit 98cdb6
				       serial, FALSE);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GdkWindow *
Packit 98cdb6
get_current_toplevel (GdkDisplay *display,
Packit 98cdb6
		      int *x_out, int *y_out,
Packit 98cdb6
		      GdkModifierType *state_out)
Packit 98cdb6
{
Packit 98cdb6
  GdkWindow *pointer_window;
Packit 98cdb6
  int x, y;
Packit 98cdb6
  GdkModifierType state;
Packit 98cdb6
Packit 98cdb6
  pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state, TRUE);
Packit 98cdb6
  if (pointer_window != NULL &&
Packit 98cdb6
      (GDK_WINDOW_DESTROYED (pointer_window) ||
Packit 98cdb6
       GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
Packit 98cdb6
       GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
Packit 98cdb6
    pointer_window = NULL;
Packit 98cdb6
Packit 98cdb6
  *x_out = x;
Packit 98cdb6
  *y_out = y;
Packit 98cdb6
  *state_out = state;
Packit 98cdb6
  return pointer_window;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
switch_to_pointer_grab (GdkDisplay *display,
Packit 98cdb6
			GdkPointerGrabInfo *grab,
Packit 98cdb6
			GdkPointerGrabInfo *last_grab,
Packit 98cdb6
			guint32 time,
Packit 98cdb6
			gulong serial)
Packit 98cdb6
{
Packit 98cdb6
  GdkWindow *src_window, *pointer_window, *new_toplevel;
Packit 98cdb6
  GList *old_grabs;
Packit 98cdb6
  GdkModifierType state;
Packit 98cdb6
  int x, y;
Packit 98cdb6
Packit 98cdb6
  /* Temporarily unset pointer to make sure we send the crossing events below */
Packit 98cdb6
  old_grabs = display->pointer_grabs;
Packit 98cdb6
  display->pointer_grabs = NULL;
Packit 98cdb6
  
Packit 98cdb6
  if (grab)
Packit 98cdb6
    {
Packit 98cdb6
      /* New grab is in effect */
Packit 98cdb6
      
Packit 98cdb6
      /* We need to generate crossing events for the grab.
Packit 98cdb6
       * However, there are never any crossing events for implicit grabs
Packit 98cdb6
       * TODO: ... Actually, this could happen if the pointer window
Packit 98cdb6
       *           doesn't have button mask so a parent gets the event... 
Packit 98cdb6
       */
Packit 98cdb6
      if (!grab->implicit)
Packit 98cdb6
	{
Packit 98cdb6
	  /* We send GRAB crossing events from the window under the pointer to the
Packit 98cdb6
	     grab window. Except if there is an old grab then we start from that */
Packit 98cdb6
	  if (last_grab)
Packit 98cdb6
	    src_window = last_grab->window;
Packit 98cdb6
	  else
Packit 98cdb6
	    src_window = display->pointer_info.window_under_pointer;
Packit 98cdb6
	  
Packit 98cdb6
	  if (src_window != grab->window)
Packit 98cdb6
	    {
Packit 98cdb6
	      synthesize_crossing_events (display,
Packit 98cdb6
					  src_window, grab->window,
Packit 98cdb6
					  GDK_CROSSING_GRAB, time, serial);
Packit 98cdb6
	    }
Packit 98cdb6
Packit 98cdb6
	  /* !owner_event Grabbing a window that we're not inside, current status is
Packit 98cdb6
	     now NULL (i.e. outside grabbed window) */
Packit 98cdb6
	  if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
Packit 98cdb6
	    _gdk_display_set_window_under_pointer (display, NULL);
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      grab->activated = TRUE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (last_grab)
Packit 98cdb6
    {
Packit 98cdb6
      new_toplevel = NULL;
Packit 98cdb6
Packit 98cdb6
      if (grab == NULL /* ungrab */ ||
Packit 98cdb6
	  (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
Packit 98cdb6
	{
Packit 98cdb6
	  /* We force check what window we're in, and update the toplevel_under_pointer info,
Packit 98cdb6
	   * as that won't get told of this change with toplevel enter events.
Packit 98cdb6
	   */
Packit 98cdb6
	  if (display->pointer_info.toplevel_under_pointer)
Packit 98cdb6
	    g_object_unref (display->pointer_info.toplevel_under_pointer);
Packit 98cdb6
	  display->pointer_info.toplevel_under_pointer = NULL;
Packit 98cdb6
Packit 98cdb6
	  new_toplevel = get_current_toplevel (display, &x, &y, &state);
Packit 98cdb6
	  if (new_toplevel)
Packit 98cdb6
	    {
Packit 98cdb6
	      /* w is now toplevel and x,y in toplevel coords */
Packit 98cdb6
	      display->pointer_info.toplevel_under_pointer = g_object_ref (new_toplevel);
Packit 98cdb6
	      display->pointer_info.toplevel_x = x;
Packit 98cdb6
	      display->pointer_info.toplevel_y = y;
Packit 98cdb6
	      display->pointer_info.state = state;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      if (grab == NULL) /* Ungrabbed, send events */
Packit 98cdb6
	{
Packit 98cdb6
	  pointer_window = NULL;
Packit 98cdb6
	  if (new_toplevel)
Packit 98cdb6
	    {
Packit 98cdb6
	      /* Find (possibly virtual) child window */
Packit 98cdb6
	      pointer_window =
Packit 98cdb6
		_gdk_window_find_descendant_at (new_toplevel,
Packit 98cdb6
						x, y,
Packit 98cdb6
						NULL, NULL);
Packit 98cdb6
	    }
Packit 98cdb6
	  
Packit 98cdb6
	  if (pointer_window != last_grab->window)
Packit 98cdb6
	    synthesize_crossing_events (display,
Packit 98cdb6
					last_grab->window, pointer_window,
Packit 98cdb6
					GDK_CROSSING_UNGRAB, time, serial);
Packit 98cdb6
	  
Packit 98cdb6
	  /* We're now ungrabbed, update the window_under_pointer */
Packit 98cdb6
	  _gdk_display_set_window_under_pointer (display, pointer_window);
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  display->pointer_grabs = old_grabs;
Packit 98cdb6
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
_gdk_display_pointer_grab_update (GdkDisplay *display,
Packit 98cdb6
				  gulong current_serial)
Packit 98cdb6
{
Packit 98cdb6
  GdkPointerGrabInfo *current_grab, *next_grab;
Packit 98cdb6
  guint32 time;
Packit 98cdb6
  
Packit 98cdb6
  time = display->last_event_time;
Packit 98cdb6
Packit 98cdb6
  while (display->pointer_grabs != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      current_grab = display->pointer_grabs->data;
Packit 98cdb6
Packit 98cdb6
      if (current_grab->serial_start > current_serial)
Packit 98cdb6
	return; /* Hasn't started yet */
Packit 98cdb6
      
Packit 98cdb6
      if (current_grab->serial_end > current_serial)
Packit 98cdb6
	{
Packit 98cdb6
	  /* This one hasn't ended yet.
Packit 98cdb6
	     its the currently active one or scheduled to be active */
Packit 98cdb6
Packit 98cdb6
	  if (!current_grab->activated)
Packit 98cdb6
	    switch_to_pointer_grab (display, current_grab, NULL, time, current_serial);
Packit 98cdb6
	  
Packit 98cdb6
	  break;
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
      next_grab = NULL;
Packit 98cdb6
      if (display->pointer_grabs->next)
Packit 98cdb6
	{
Packit 98cdb6
	  /* This is the next active grab */
Packit 98cdb6
	  next_grab = display->pointer_grabs->next->data;
Packit 98cdb6
	  
Packit 98cdb6
	  if (next_grab->serial_start > current_serial)
Packit 98cdb6
	    next_grab = NULL; /* Actually its not yet active */
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      if ((next_grab == NULL && current_grab->implicit_ungrab) ||
Packit 98cdb6
	  (next_grab != NULL && current_grab->window != next_grab->window))
Packit 98cdb6
	generate_grab_broken_event (GDK_WINDOW (current_grab->window),
Packit 98cdb6
				    FALSE, current_grab->implicit,
Packit 98cdb6
				    next_grab? next_grab->window : NULL);
Packit 98cdb6
Packit 98cdb6
      /* Remove old grab */
Packit 98cdb6
      display->pointer_grabs =
Packit 98cdb6
	g_list_delete_link (display->pointer_grabs,
Packit 98cdb6
			    display->pointer_grabs);
Packit 98cdb6
      
Packit 98cdb6
      switch_to_pointer_grab (display,
Packit 98cdb6
			      next_grab, current_grab,
Packit 98cdb6
			      time, current_serial);
Packit 98cdb6
      
Packit 98cdb6
      free_pointer_grab (current_grab);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GList *
Packit 98cdb6
find_pointer_grab (GdkDisplay *display,
Packit 98cdb6
		   gulong serial)
Packit 98cdb6
{
Packit 98cdb6
  GdkPointerGrabInfo *grab;
Packit 98cdb6
  GList *l;
Packit 98cdb6
Packit 98cdb6
  for (l = display->pointer_grabs; l != NULL; l = l->next)
Packit 98cdb6
    {
Packit 98cdb6
      grab = l->data;
Packit 98cdb6
Packit 98cdb6
      if (serial >= grab->serial_start && serial < grab->serial_end)
Packit 98cdb6
	return l;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
GdkPointerGrabInfo *
Packit 98cdb6
_gdk_display_has_pointer_grab (GdkDisplay *display,
Packit 98cdb6
			       gulong serial)
Packit 98cdb6
{
Packit 98cdb6
  GList *l;
Packit 98cdb6
Packit 98cdb6
  l = find_pointer_grab (display, serial);
Packit 98cdb6
  if (l)
Packit 98cdb6
    return l->data;
Packit 98cdb6
  
Packit 98cdb6
  return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* Returns true if last grab was ended
Packit 98cdb6
 * If if_child is non-NULL, end the grab only if the grabbed
Packit 98cdb6
 * window is the same as if_child or a descendant of it */
Packit 98cdb6
gboolean
Packit 98cdb6
_gdk_display_end_pointer_grab (GdkDisplay *display,
Packit 98cdb6
			       gulong serial,
Packit 98cdb6
			       GdkWindow *if_child,
Packit 98cdb6
			       gboolean implicit)
Packit 98cdb6
{
Packit 98cdb6
  GdkPointerGrabInfo *grab;
Packit 98cdb6
  GList *l;
Packit 98cdb6
Packit 98cdb6
  l = find_pointer_grab (display, serial);
Packit 98cdb6
  
Packit 98cdb6
  if (l == NULL)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  grab = l->data;
Packit 98cdb6
  if (grab &&
Packit 98cdb6
      (if_child == NULL ||
Packit 98cdb6
       _gdk_window_event_parent_of (if_child, grab->window)))
Packit 98cdb6
    {
Packit 98cdb6
      grab->serial_end = serial;
Packit 98cdb6
      grab->implicit_ungrab = implicit;
Packit 98cdb6
      return l->next == NULL;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
_gdk_display_set_has_keyboard_grab (GdkDisplay *display,
Packit 98cdb6
				    GdkWindow *window,
Packit 98cdb6
				    GdkWindow *native_window,
Packit 98cdb6
				    gboolean owner_events,
Packit 98cdb6
				    unsigned long serial,
Packit 98cdb6
				    guint32 time)
Packit 98cdb6
{
Packit 98cdb6
  if (display->keyboard_grab.window != NULL &&
Packit 98cdb6
      display->keyboard_grab.window != window)
Packit 98cdb6
    generate_grab_broken_event (display->keyboard_grab.window,
Packit 98cdb6
				TRUE, FALSE, window);
Packit 98cdb6
  
Packit 98cdb6
  display->keyboard_grab.window = window;
Packit 98cdb6
  display->keyboard_grab.native_window = native_window;
Packit 98cdb6
  display->keyboard_grab.owner_events = owner_events;
Packit 98cdb6
  display->keyboard_grab.serial = serial;
Packit 98cdb6
  display->keyboard_grab.time = time;      
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
_gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
Packit 98cdb6
				      gboolean implicit)
Packit 98cdb6
{
Packit 98cdb6
  if (implicit)
Packit 98cdb6
    generate_grab_broken_event (display->keyboard_grab.window,
Packit 98cdb6
				TRUE, FALSE, NULL);
Packit 98cdb6
  display->keyboard_grab.window = NULL;  
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_keyboard_grab_info_libgtk_only:
Packit 98cdb6
 * @display: the display for which to get the grab information
Packit 98cdb6
 * @grab_window: location to store current grab window
Packit 98cdb6
 * @owner_events: location to store boolean indicating whether
Packit 98cdb6
 *   the @owner_events flag to gdk_keyboard_grab() was %TRUE.
Packit 98cdb6
 * 
Packit 98cdb6
 * Determines information about the current keyboard grab.
Packit 98cdb6
 * This is not public API and must not be used by applications.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE if this application currently has the
Packit 98cdb6
 *  keyboard grabbed.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
Packit 98cdb6
				    GdkWindow **grab_window,
Packit 98cdb6
				    gboolean   *owner_events)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
Packit 98cdb6
Packit 98cdb6
  if (display->keyboard_grab.window)
Packit 98cdb6
    {
Packit 98cdb6
      if (grab_window)
Packit 98cdb6
        *grab_window = display->keyboard_grab.window;
Packit 98cdb6
      if (owner_events)
Packit 98cdb6
        *owner_events = display->keyboard_grab.owner_events;
Packit 98cdb6
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_pointer_grab_info_libgtk_only:
Packit 98cdb6
 * @display: the #GdkDisplay for which to get the grab information
Packit 98cdb6
 * @grab_window: location to store current grab window
Packit 98cdb6
 * @owner_events: location to store boolean indicating whether
Packit 98cdb6
 *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
Packit 98cdb6
 * 
Packit 98cdb6
 * Determines information about the current pointer grab.
Packit 98cdb6
 * This is not public API and must not be used by applications.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE if this application currently has the
Packit 98cdb6
 *  pointer grabbed.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
Packit 98cdb6
				   GdkWindow **grab_window,
Packit 98cdb6
				   gboolean   *owner_events)
Packit 98cdb6
{
Packit 98cdb6
  GdkPointerGrabInfo *info;
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
Packit 98cdb6
Packit 98cdb6
  /* What we're interested in is the steady state (ie last grab),
Packit 98cdb6
     because we're interested e.g. if we grabbed so that we
Packit 98cdb6
     can ungrab, even if our grab is not active just yet. */
Packit 98cdb6
  info = _gdk_display_get_last_pointer_grab (display);
Packit 98cdb6
  
Packit 98cdb6
  if (info)
Packit 98cdb6
    {
Packit 98cdb6
      if (grab_window)
Packit 98cdb6
        *grab_window = info->window;
Packit 98cdb6
      if (owner_events)
Packit 98cdb6
        *owner_events = info->owner_events;
Packit 98cdb6
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gdk_display_pointer_is_grabbed:
Packit 98cdb6
 * @display: a #GdkDisplay
Packit 98cdb6
 *
Packit 98cdb6
 * Test if the pointer is grabbed.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns: %TRUE if an active X pointer grab is in effect
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 */
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_display_pointer_is_grabbed (GdkDisplay *display)
Packit 98cdb6
{
Packit 98cdb6
  GdkPointerGrabInfo *info;
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
Packit 98cdb6
Packit 98cdb6
  /* What we're interested in is the steady state (ie last grab),
Packit 98cdb6
     because we're interested e.g. if we grabbed so that we
Packit 98cdb6
     can ungrab, even if our grab is not active just yet. */
Packit 98cdb6
  info = _gdk_display_get_last_pointer_grab (display);
Packit 98cdb6
  
Packit 98cdb6
  return (info && !info->implicit);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#define __GDK_DISPLAY_C__
Packit 98cdb6
#include "gdkaliasdef.c"