gdkevents.c 59.5 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GDK - The GIMP Drawing Kit
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6 7 8 9 10 11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 17
 */

18
/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21 22 23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

25
#include "config.h"
26

27
#include "gdkintl.h"
28
#include "gdkeventsprivate.h"
29
#include "gdkinternals.h"
30
#include "gdkdisplayprivate.h"
31
#include "gdkdndprivate.h"
32
#include "gdkdropprivate.h"
33
#include "gdk-private.h"
34

35 36
#include <string.h>
#include <math.h>
37

38 39 40 41 42

/**
 * SECTION:events
 * @Short_description: Functions for handling events from the window system
 * @Title: Events
43
 * @See_also: [Event Structures][gdk3-Event-Structures]
44 45 46 47 48
 *
 * This section describes functions dealing with events from the window
 * system.
 *
 * In GTK+ applications the events are handled automatically in
49 50
 * gtk_main_do_event() and passed on to the appropriate widgets,
 * so these functions are rarely needed.
51 52
 */

Matthias Clasen's avatar
Matthias Clasen committed
53 54 55 56 57 58 59 60 61 62 63 64 65
/**
 * GdkEvent:
 *
 * The GdkEvent struct contains only private fields and
 * should not be accessed directly.
 */

/**
 * GdkEventSequence:
 *
 * GdkEventSequence is an opaque type representing a sequence
 * of related touch events.
 */
66

67
typedef struct _GdkIOClosure GdkIOClosure;
68

69 70
struct _GdkIOClosure
{
71
  GDestroyNotify notify;
72 73 74 75 76 77
  gpointer data;
};

/* Private variable declarations
 */

78 79 80 81
static GdkEventFunc   _gdk_event_func = NULL;    /* Callback for events */
static gpointer       _gdk_event_data = NULL;
static GDestroyNotify _gdk_event_notify = NULL;

82 83
static GQuark quark_event_user_data = 0;

84
static void gdk_event_constructed (GObject *object);
85 86 87 88
static void gdk_event_finalize (GObject *object);

G_DEFINE_TYPE (GdkEvent, gdk_event, G_TYPE_OBJECT)

89 90 91 92 93 94 95 96
enum {
  PROP_0,
  PROP_EVENT_TYPE,
  N_PROPS
};

static GParamSpec *event_props[N_PROPS] = { NULL, };

97 98 99 100 101 102 103 104
#define EVENT_PAYLOAD(ev) (&(ev)->any.type)
#define EVENT_PAYLOAD_SIZE (sizeof (GdkEvent) - sizeof (GObject))

static void
gdk_event_init (GdkEvent *event)
{
}

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
static void
gdk_event_real_get_property (GObject    *object,
                             guint       prop_id,
                             GValue     *value,
                             GParamSpec *pspec)
{
  GdkEvent *event = GDK_EVENT (object);

  switch (prop_id)
    {
    case PROP_EVENT_TYPE:
      g_value_set_enum (value, event->any.type);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gdk_event_real_set_property (GObject      *object,
                             guint         prop_id,
                             const GValue *value,
                             GParamSpec   *pspec)
{
  GdkEvent *event = GDK_EVENT (object);

  switch (prop_id)
    {
    case PROP_EVENT_TYPE:
      event->any.type = g_value_get_enum (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

143 144 145 146 147
static void
gdk_event_class_init (GdkEventClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

148 149
  object_class->get_property = gdk_event_real_get_property;
  object_class->set_property = gdk_event_real_set_property;
150
  object_class->constructed = gdk_event_constructed;
151 152
  object_class->finalize = gdk_event_finalize;

153 154 155 156 157 158 159 160 161
  event_props[PROP_EVENT_TYPE] =
    g_param_spec_enum ("event-type",
                       P_("Event type"),
                       P_("Event type"),
                       GDK_TYPE_EVENT_TYPE, GDK_NOTHING,
                       G_PARAM_READWRITE |
                       G_PARAM_CONSTRUCT_ONLY);
  g_object_class_install_properties (object_class, N_PROPS, event_props);

162 163 164
  quark_event_user_data = g_quark_from_static_string ("gdk-event-user-data");
}

165 166 167
void
_gdk_event_emit (GdkEvent *event)
{
168 169 170
  if (gdk_drag_context_handle_source_event (event))
    return;

171 172 173
  if (_gdk_event_func)
    (*_gdk_event_func) (event, _gdk_event_data);
}
174

175 176 177 178
/*********************************************
 * Functions for maintaining the event queue *
 *********************************************/

179
/**
180
 * _gdk_event_queue_find_first:
181 182 183 184 185
 * @display: a #GdkDisplay
 * 
 * Find the first event on the queue that is not still
 * being filled in.
 * 
186 187
 * Returns: (nullable): Pointer to the list node for that event, or
 *   %NULL.
188
 **/
189
GList*
190
_gdk_event_queue_find_first (GdkDisplay *display)
191
{
192 193 194
  GList *tmp_list;
  GList *pending_motion = NULL;

195
  gboolean paused = display->event_pause_count > 0;
196

197
  tmp_list = display->queued_events;
198 199
  while (tmp_list)
    {
200
      GdkEvent *event = tmp_list->data;
201

202 203
      if ((event->any.flags & GDK_EVENT_PENDING) == 0 &&
	  (!paused || (event->any.flags & GDK_EVENT_FLUSHED) != 0))
204 205 206 207
        {
          if (pending_motion)
            return pending_motion;

208
          if (event->any.type == GDK_MOTION_NOTIFY && (event->any.flags & GDK_EVENT_FLUSHED) == 0)
209 210 211 212
            pending_motion = tmp_list;
          else
            return tmp_list;
        }
213

214
      tmp_list = tmp_list->next;
215 216 217 218 219
    }

  return NULL;
}

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
/**
 * _gdk_event_queue_append:
 * @display: a #GdkDisplay
 * @event: Event to append.
 * 
 * Appends an event onto the tail of the event queue.
 *
 * Returns: the newly appended list node.
 **/
GList *
_gdk_event_queue_append (GdkDisplay *display,
			 GdkEvent   *event)
{
  display->queued_tail = g_list_append (display->queued_tail, event);
  
  if (!display->queued_events)
    display->queued_events = display->queued_tail;
  else
    display->queued_tail = display->queued_tail->next;

  return display->queued_tail;
}
242

243 244 245 246 247 248
/**
 * _gdk_event_queue_insert_after:
 * @display: a #GdkDisplay
 * @sibling: Append after this event.
 * @event: Event to append.
 *
249
 * Appends an event after the specified event, or if it isn’t in
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
 * the queue, onto the tail of the event queue.
 *
 * Returns: the newly appended list node.
 */
GList*
_gdk_event_queue_insert_after (GdkDisplay *display,
                               GdkEvent   *sibling,
                               GdkEvent   *event)
{
  GList *prev = g_list_find (display->queued_events, sibling);
  if (prev && prev->next)
    {
      display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
      return prev->next;
    }
  else
    return _gdk_event_queue_append (display, event);
}

/**
Matthias Clasen's avatar
Matthias Clasen committed
270
 * _gdk_event_queue_insert_before:
271
 * @display: a #GdkDisplay
Matthias Clasen's avatar
Matthias Clasen committed
272 273
 * @sibling: Append before this event
 * @event: Event to prepend
274
 *
275
 * Prepends an event before the specified event, or if it isn’t in
Matthias Clasen's avatar
Matthias Clasen committed
276
 * the queue, onto the head of the event queue.
277
 *
Matthias Clasen's avatar
Matthias Clasen committed
278
 * Returns: the newly prepended list node.
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
 */
GList*
_gdk_event_queue_insert_before (GdkDisplay *display,
				GdkEvent   *sibling,
				GdkEvent   *event)
{
  GList *next = g_list_find (display->queued_events, sibling);
  if (next)
    {
      display->queued_events = g_list_insert_before (display->queued_events, next, event);
      return next->prev;
    }
  else
    return _gdk_event_queue_append (display, event);
}


296 297 298 299 300 301 302
/**
 * _gdk_event_queue_remove_link:
 * @display: a #GdkDisplay
 * @node: node to remove
 * 
 * Removes a specified list node from the event queue.
 **/
303
void
304 305
_gdk_event_queue_remove_link (GdkDisplay *display,
			      GList      *node)
306 307 308 309
{
  if (node->prev)
    node->prev->next = node->next;
  else
310
    display->queued_events = node->next;
311 312 313 314
  
  if (node->next)
    node->next->prev = node->prev;
  else
315
    display->queued_tail = node->prev;
316 317
}

318 319 320 321 322 323 324
/**
 * _gdk_event_unqueue:
 * @display: a #GdkDisplay
 * 
 * Removes and returns the first event from the event
 * queue that is not still being filled in.
 * 
325
 * Returns: (nullable): the event, or %NULL. Ownership is transferred
326 327 328 329
 * to the caller.
 **/
GdkEvent*
_gdk_event_unqueue (GdkDisplay *display)
330
{
331 332 333 334 335 336 337 338 339 340 341 342 343
  GdkEvent *event = NULL;
  GList *tmp_list;

  tmp_list = _gdk_event_queue_find_first (display);

  if (tmp_list)
    {
      event = tmp_list->data;
      _gdk_event_queue_remove_link (display, tmp_list);
      g_list_free_1 (tmp_list);
    }

  return event;
344 345
}

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
static void
gdk_event_push_history (GdkEvent       *event,
                        const GdkEvent *history_event)
{
  GdkTimeCoord *hist;
  GdkDevice *device;
  gint i, n_axes;

  g_assert (event->any.type == GDK_MOTION_NOTIFY);
  g_assert (history_event->any.type == GDK_MOTION_NOTIFY);

  hist = g_new0 (GdkTimeCoord, 1);

  device = gdk_event_get_device (history_event);
  n_axes = gdk_device_get_n_axes (device);

  for (i = 0; i <= MIN (n_axes, GDK_MAX_TIMECOORD_AXES); i++)
    gdk_event_get_axis (history_event, i, &hist->axes[i]);

  event->motion.history = g_list_prepend (event->motion.history, hist);
}

368 369 370 371 372
void
_gdk_event_queue_handle_motion_compression (GdkDisplay *display)
{
  GList *tmp_list;
  GList *pending_motions = NULL;
373
  GdkSurface *pending_motion_surface = NULL;
374
  GdkDevice *pending_motion_device = NULL;
375
  GdkEvent *last_motion = NULL;
376 377

  /* If the last N events in the event queue are motion notify
378
   * events for the same surface, drop all but the last */
379 380 381 382 383

  tmp_list = display->queued_tail;

  while (tmp_list)
    {
384
      GdkEvent *event = tmp_list->data;
385

386
      if (event->any.flags & GDK_EVENT_PENDING)
387 388
        break;

389
      if (event->any.type != GDK_MOTION_NOTIFY)
390 391
        break;

392 393
      if (pending_motion_surface != NULL &&
          pending_motion_surface != event->any.surface)
394 395
        break;

396
      if (pending_motion_device != NULL &&
397
          pending_motion_device != event->any.device)
398 399
        break;

400 401 402
      if (!last_motion)
        last_motion = event;

403
      pending_motion_surface = event->any.surface;
404
      pending_motion_device = event->any.device;
405 406 407 408 409 410 411 412
      pending_motions = tmp_list;

      tmp_list = tmp_list->prev;
    }

  while (pending_motions && pending_motions->next != NULL)
    {
      GList *next = pending_motions->next;
413 414 415 416 417 418 419

      if (last_motion &&
          (last_motion->motion.state &
           (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
            GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
        gdk_event_push_history (last_motion, pending_motions->data);

420
      g_object_unref (pending_motions->data);
421 422 423 424 425 426 427 428 429
      display->queued_events = g_list_delete_link (display->queued_events,
                                                   pending_motions);
      pending_motions = next;
    }

  if (pending_motions &&
      pending_motions == display->queued_events &&
      pending_motions == display->queued_tail)
    {
430 431
      GdkFrameClock *clock = gdk_surface_get_frame_clock (pending_motion_surface);
      if (clock) /* might be NULL if surface was destroyed */
432
	gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
433 434 435
    }
}

436 437 438 439 440 441 442
void
_gdk_event_queue_flush (GdkDisplay *display)
{
  GList *tmp_list;

  for (tmp_list = display->queued_events; tmp_list; tmp_list = tmp_list->next)
    {
443 444
      GdkEvent *event = tmp_list->data;
      event->any.flags |= GDK_EVENT_FLUSHED;
445 446 447
    }
}

448
/**
449
 * gdk_event_handler_set:
450 451 452 453
 * @func: the function to call to handle events from GDK.
 * @data: user data to pass to the function. 
 * @notify: the function to call when the handler function is removed, i.e. when
 *          gdk_event_handler_set() is called with another event handler.
454
 * 
455 456 457 458 459 460 461
 * Sets the function to call to handle all events from GDK.
 *
 * Note that GTK+ uses this to install its own event handler, so it is
 * usually not useful for GTK+ applications. (Although an application
 * can call this function then call gtk_main_do_event() to pass
 * events to GTK+.)
 **/
462 463 464 465 466
void 
gdk_event_handler_set (GdkEventFunc   func,
		       gpointer       data,
		       GDestroyNotify notify)
{
467 468
  if (_gdk_event_notify)
    (*_gdk_event_notify) (_gdk_event_data);
469

470 471 472
  _gdk_event_func = func;
  _gdk_event_data = data;
  _gdk_event_notify = notify;
473 474
}

Matthias Clasen's avatar
Matthias Clasen committed
475 476 477 478 479 480
/**
 * gdk_event_new:
 * @type: a #GdkEventType 
 * 
 * Creates a new event of the given type. All fields are set to 0.
 * 
Matthias Clasen's avatar
Matthias Clasen committed
481 482
 * Returns: a newly-allocated #GdkEvent. Free with g_object_unref()
 */
483
GdkEvent*
484
gdk_event_new (GdkEventType type)
485
{
486 487 488 489
  return g_object_new (GDK_TYPE_EVENT,
                       "event-type", type,
                       NULL);
}
490

491 492 493 494
static void
gdk_event_constructed (GObject *object)
{
  GdkEvent *new_event = GDK_EVENT (object);
495

496 497 498 499 500 501
  /*
   * Bytewise 0 initialization is reasonable for most of the 
   * current event types. Explicitely initialize double fields
   * since I trust bytewise 0 == 0. less than for integers
   * or pointers.
   */
502
  switch ((guint) new_event->any.type)
503 504 505 506 507 508 509 510 511 512 513 514 515 516
    {
    case GDK_MOTION_NOTIFY:
      new_event->motion.x = 0.;
      new_event->motion.y = 0.;
      new_event->motion.x_root = 0.;
      new_event->motion.y_root = 0.;
      break;
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      new_event->button.x = 0.;
      new_event->button.y = 0.;
      new_event->button.x_root = 0.;
      new_event->button.y_root = 0.;
      break;
517 518 519 520 521 522 523 524 525
    case GDK_TOUCH_BEGIN:
    case GDK_TOUCH_UPDATE:
    case GDK_TOUCH_END:
    case GDK_TOUCH_CANCEL:
      new_event->touch.x = 0.;
      new_event->touch.y = 0.;
      new_event->touch.x_root = 0.;
      new_event->touch.y_root = 0.;
      break;
526 527 528 529 530
    case GDK_SCROLL:
      new_event->scroll.x = 0.;
      new_event->scroll.y = 0.;
      new_event->scroll.x_root = 0.;
      new_event->scroll.y_root = 0.;
531 532
      new_event->scroll.delta_x = 0.;
      new_event->scroll.delta_y = 0.;
533
      new_event->scroll.is_stop = FALSE;
534 535 536 537 538 539 540 541
      break;
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      new_event->crossing.x = 0.;
      new_event->crossing.y = 0.;
      new_event->crossing.x_root = 0.;
      new_event->crossing.y_root = 0.;
      break;
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
    case GDK_TOUCHPAD_SWIPE:
      new_event->touchpad_swipe.x = 0;
      new_event->touchpad_swipe.y = 0;
      new_event->touchpad_swipe.dx = 0;
      new_event->touchpad_swipe.dy = 0;
      new_event->touchpad_swipe.x_root = 0;
      new_event->touchpad_swipe.y_root = 0;
      break;
    case GDK_TOUCHPAD_PINCH:
      new_event->touchpad_pinch.x = 0;
      new_event->touchpad_pinch.y = 0;
      new_event->touchpad_pinch.dx = 0;
      new_event->touchpad_pinch.dy = 0;
      new_event->touchpad_pinch.angle_delta = 0;
      new_event->touchpad_pinch.scale = 0;
      new_event->touchpad_pinch.x_root = 0;
      new_event->touchpad_pinch.y_root = 0;
      break;
560 561 562
    default:
      break;
    }
563 564

  G_OBJECT_CLASS (gdk_event_parent_class)->constructed (object);
565 566
}

567
void
568 569
gdk_event_set_pointer_emulated (GdkEvent *event,
                                gboolean  emulated)
570
{
571 572 573 574
  if (emulated)
    event->any.flags |= GDK_EVENT_POINTER_EMULATED;
  else
    event->any.flags &= ~(GDK_EVENT_POINTER_EMULATED);
575 576
}

Matthias Clasen's avatar
Matthias Clasen committed
577 578
/**
 * gdk_event_get_pointer_emulated:
Matthias Clasen's avatar
Matthias Clasen committed
579
 * @event: a #GdkEvent
Matthias Clasen's avatar
Matthias Clasen committed
580 581 582 583 584 585
 *
 * Returns whether this event is an 'emulated' pointer event (typically
 * from a touch event), as opposed to a real one.
 *
 * Returns: %TRUE if this event is emulated
 */
586
gboolean
587
gdk_event_get_pointer_emulated (GdkEvent *event)
588
{
589
  return (event->any.flags & GDK_EVENT_POINTER_EMULATED) != 0;
590 591
}

592 593 594 595 596 597
static GdkTimeCoord *
copy_time_coord (const GdkTimeCoord *coord)
{
  return g_memdup (coord, sizeof (GdkTimeCoord));
}

598 599 600
/**
 * gdk_event_copy:
 * @event: a #GdkEvent
Matthias Clasen's avatar
Matthias Clasen committed
601
 *
602
 * Copies a #GdkEvent, copying or incrementing the reference count of the
603
 * resources associated with it (e.g. #GdkSurface’s and strings).
Matthias Clasen's avatar
Matthias Clasen committed
604 605
 *
 * Returns: (transfer full): a copy of @event. Free with g_object_unref()
606
 */
607
GdkEvent*
608
gdk_event_copy (const GdkEvent *event)
609 610
{
  GdkEvent *new_event;
611

612
  g_return_val_if_fail (event != NULL, NULL);
613

614
  new_event = gdk_event_new (event->any.type);
615

616 617 618 619
  memcpy (EVENT_PAYLOAD (new_event),
          EVENT_PAYLOAD (event),
          EVENT_PAYLOAD_SIZE);

620 621
  if (new_event->any.surface)
    g_object_ref (new_event->any.surface);
622 623 624 625
  if (new_event->any.device)
    g_object_ref (new_event->any.device);
  if (new_event->any.source_device)
    g_object_ref (new_event->any.source_device);
626

627
  gdk_event_set_user_data (new_event, gdk_event_get_user_data (event));
628

629
  switch ((guint) event->any.type)
630 631 632 633 634
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      new_event->key.string = g_strdup (event->key.string);
      break;
635

636 637
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
638 639
      if (event->crossing.child_surface != NULL)
        g_object_ref (event->crossing.child_surface);
640
      break;
641

642 643 644 645
    case GDK_DRAG_ENTER:
    case GDK_DRAG_LEAVE:
    case GDK_DRAG_MOTION:
    case GDK_DROP_START:
646
      g_object_ref (event->dnd.drop);
647
      break;
648

649 650
    case GDK_EXPOSE:
      if (event->expose.region)
651
        new_event->expose.region = cairo_region_copy (event->expose.region);
652
      break;
653

Larry Ewing's avatar
Larry Ewing committed
654 655
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
656 657
      if (event->button.axes)
        new_event->button.axes = g_memdup (event->button.axes,
658
                                           sizeof (gdouble) * gdk_device_get_n_axes (event->any.device));
659 660
      if (event->button.tool)
        g_object_ref (new_event->button.tool);
Larry Ewing's avatar
Larry Ewing committed
661 662
      break;

663 664 665 666 667 668
    case GDK_TOUCH_BEGIN:
    case GDK_TOUCH_UPDATE:
    case GDK_TOUCH_END:
    case GDK_TOUCH_CANCEL:
      if (event->touch.axes)
        new_event->touch.axes = g_memdup (event->touch.axes,
669
                                           sizeof (gdouble) * gdk_device_get_n_axes (event->any.device));
670 671
      break;

Larry Ewing's avatar
Larry Ewing committed
672
    case GDK_MOTION_NOTIFY:
673 674
      if (event->motion.axes)
        new_event->motion.axes = g_memdup (event->motion.axes,
675
                                           sizeof (gdouble) * gdk_device_get_n_axes (event->any.device));
676 677
      if (event->motion.tool)
        g_object_ref (new_event->motion.tool);
678 679 680 681 682 683

      if (event->motion.history)
        {
          new_event->motion.history = g_list_copy_deep (event->motion.history,
                                                        (GCopyFunc) copy_time_coord, NULL);
        }
Larry Ewing's avatar
Larry Ewing committed
684
      break;
685

686
    default:
687 688
      break;
    }
689

690
  _gdk_display_event_data_copy (gdk_event_get_display (event), event, new_event);
691

692 693 694
  return new_event;
}

695
static void
696 697 698 699
gdk_event_finalize (GObject *object)
{
  GdkEvent *event = GDK_EVENT (object);
  GdkDisplay *display;
700

701
  switch ((guint) event->any.type)
702 703 704 705 706
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      g_free (event->key.string);
      break;
707

708 709
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
710
      g_clear_object (&event->crossing.child_surface);
711
      break;
712

713 714 715 716
    case GDK_DRAG_ENTER:
    case GDK_DRAG_LEAVE:
    case GDK_DRAG_MOTION:
    case GDK_DROP_START:
717
      g_clear_object (&event->dnd.drop);
718
      break;
719 720 721

    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
722
      g_clear_object (&event->button.tool);
723
      g_free (event->button.axes);
724
      break;
725 726 727 728 729 730 731 732

    case GDK_TOUCH_BEGIN:
    case GDK_TOUCH_UPDATE:
    case GDK_TOUCH_END:
    case GDK_TOUCH_CANCEL:
      g_free (event->touch.axes);
      break;

733 734
    case GDK_EXPOSE:
      if (event->expose.region)
Benjamin Otte's avatar
Benjamin Otte committed
735
	cairo_region_destroy (event->expose.region);
736 737
      break;
      
738
    case GDK_MOTION_NOTIFY:
739
      g_clear_object (&event->motion.tool);
740
      g_free (event->motion.axes);
741
      g_list_free_full (event->motion.history, g_free);
742
      break;
743

744 745 746
    default:
      break;
    }
747

748
  display = gdk_event_get_display (event);
749 750
  if (display)
    _gdk_display_event_data_free (display, event);
751

752 753
  if (event->any.surface)
    g_object_unref (event->any.surface);
754

755 756 757
  g_clear_object (&event->any.device);
  g_clear_object (&event->any.source_device);

758
  G_OBJECT_CLASS (gdk_event_parent_class)->finalize (object);
759 760
}

761
/**
762
 * gdk_event_get_surface:
763 764
 * @event: a #GdkEvent
 *
765
 * Extracts the #GdkSurface associated with an event.
766
 *
767
 * Returns: (transfer none): The #GdkSurface associated with the event
768
 */
769
GdkSurface *
770
gdk_event_get_surface (const GdkEvent *event)
771 772 773
{
  g_return_val_if_fail (event != NULL, NULL);

774
  return event->any.surface;
775 776
}

777
/**
778
 * gdk_event_get_time:
779 780 781 782 783
 * @event: a #GdkEvent
 * 
 * Returns the time stamp from @event, if there is one; otherwise
 * returns #GDK_CURRENT_TIME. If @event is %NULL, returns #GDK_CURRENT_TIME.
 * 
784
 * Returns: time stamp field from @event
785
 **/
786
guint32
787
gdk_event_get_time (const GdkEvent *event)
788 789
{
  if (event)
790
    switch (event->any.type)
791 792 793 794 795 796
      {
      case GDK_MOTION_NOTIFY:
	return event->motion.time;
      case GDK_BUTTON_PRESS:
      case GDK_BUTTON_RELEASE:
	return event->button.time;
797 798 799 800 801
      case GDK_TOUCH_BEGIN:
      case GDK_TOUCH_UPDATE:
      case GDK_TOUCH_END:
      case GDK_TOUCH_CANCEL:
        return event->touch.time;
802 803 804 805
      case GDK_TOUCHPAD_SWIPE:
        return event->touchpad_swipe.time;
      case GDK_TOUCHPAD_PINCH:
        return event->touchpad_pinch.time;
806 807
      case GDK_SCROLL:
        return event->scroll.time;
808 809 810 811 812 813 814 815 816 817 818 819 820 821
      case GDK_KEY_PRESS:
      case GDK_KEY_RELEASE:
	return event->key.time;
      case GDK_ENTER_NOTIFY:
      case GDK_LEAVE_NOTIFY:
	return event->crossing.time;
      case GDK_PROXIMITY_IN:
      case GDK_PROXIMITY_OUT:
	return event->proximity.time;
      case GDK_DRAG_ENTER:
      case GDK_DRAG_LEAVE:
      case GDK_DRAG_MOTION:
      case GDK_DROP_START:
	return event->dnd.time;
822 823 824 825 826 827 828 829
      case GDK_PAD_BUTTON_PRESS:
      case GDK_PAD_BUTTON_RELEASE:
        return event->pad_button.time;
      case GDK_PAD_RING:
      case GDK_PAD_STRIP:
        return event->pad_axis.time;
      case GDK_PAD_GROUP_MODE:
        return event->pad_group_mode.time;
830 831 832 833 834 835 836 837
      case GDK_CONFIGURE:
      case GDK_FOCUS_CHANGE:
      case GDK_NOTHING:
      case GDK_DELETE:
      case GDK_DESTROY:
      case GDK_EXPOSE:
      case GDK_MAP:
      case GDK_UNMAP:
838
      case GDK_GRAB_BROKEN:
839
      case GDK_EVENT_LAST:
840
      default:
841 842
        /* return current time */
        break;
843 844 845 846 847
      }
  
  return GDK_CURRENT_TIME;
}

848 849
/**
 * gdk_event_get_state:
850
 * @event: (allow-none): a #GdkEvent or %NULL
851
 * @state: (out): return location for state
Matthias Clasen's avatar
Matthias Clasen committed
852 853 854 855 856
 *
 * If the event contains a “state” field, puts that field in @state.
 *
 * Otherwise stores an empty state (0).
 * @event may be %NULL, in which case it’s treated
857
 * as if the event had no state field.
Matthias Clasen's avatar
Matthias Clasen committed
858 859
 *
 * Returns: %TRUE if there was a state field in the event
860 861
 **/
gboolean
Matthias Clasen's avatar
Matthias Clasen committed
862 863
gdk_event_get_state (const GdkEvent  *event,
                     GdkModifierType *state)
864
{
865 866
  g_return_val_if_fail (state != NULL, FALSE);
  
867
  if (event)
868
    switch (event->any.type)
869 870
      {
      case GDK_MOTION_NOTIFY:
871 872
	*state = event->motion.state;
        return TRUE;
873 874
      case GDK_BUTTON_PRESS:
      case GDK_BUTTON_RELEASE:
875 876 877 878 879 880 881
        *state = event->button.state;
        return TRUE;
      case GDK_TOUCH_BEGIN:
      case GDK_TOUCH_UPDATE:
      case GDK_TOUCH_END:
      case GDK_TOUCH_CANCEL:
        *state = event->touch.state;
882
        return TRUE;
883 884 885 886 887 888
      case GDK_TOUCHPAD_SWIPE:
        *state = event->touchpad_swipe.state;
        return TRUE;
      case GDK_TOUCHPAD_PINCH:
        *state = event->touchpad_pinch.state;
        return TRUE;
889
      case GDK_SCROLL:
890 891
	*state =  event->scroll.state;
        return TRUE;
892 893
      case GDK_KEY_PRESS:
      case GDK_KEY_RELEASE:
894 895
	*state =  event->key.state;
        return TRUE;
896 897
      case GDK_ENTER_NOTIFY:
      case GDK_LEAVE_NOTIFY:
898 899
	*state =  event->crossing.state;
        return TRUE;
900 901 902 903 904 905 906 907 908 909 910 911 912 913
      case GDK_CONFIGURE:
      case GDK_FOCUS_CHANGE:
      case GDK_PROXIMITY_IN:
      case GDK_PROXIMITY_OUT:
      case GDK_DRAG_ENTER:
      case GDK_DRAG_LEAVE:
      case GDK_DRAG_MOTION:
      case GDK_DROP_START:
      case GDK_NOTHING:
      case GDK_DELETE:
      case GDK_DESTROY:
      case GDK_EXPOSE:
      case GDK_MAP:
      case GDK_UNMAP:
914
      case GDK_GRAB_BROKEN:
915 916 917 918 919
      case GDK_PAD_BUTTON_PRESS:
      case GDK_PAD_BUTTON_RELEASE:
      case GDK_PAD_RING:
      case GDK_PAD_STRIP:
      case GDK_PAD_GROUP_MODE:
920
      case GDK_EVENT_LAST:
921
      default:
922 923 924 925
        /* no state field */
        break;
      }

926 927
  *state = 0;
  return FALSE;
928 929
}

930 931 932
/**
 * gdk_event_get_coords:
 * @event: a #GdkEvent
933 934
 * @x_win: (out) (optional): location to put event surface x coordinate
 * @y_win: (out) (optional): location to put event surface y coordinate
Matthias Clasen's avatar
Matthias Clasen committed
935
 *
936
 * Extract the event surface relative x/y coordinates from an event.
Matthias Clasen's avatar
Matthias Clasen committed
937
 *
938
 * Returns: %TRUE if the event delivered event surface coordinates
939 940
 **/
gboolean
941 942 943
gdk_event_get_coords (const GdkEvent *event,
		      gdouble        *x_win,
		      gdouble        *y_win)
944 945 946
{
  gdouble x = 0, y = 0;
  gboolean fetched = TRUE;
Matthias Clasen's avatar
Matthias Clasen committed
947

948 949
  g_return_val_if_fail (event != NULL, FALSE);

950
  switch ((guint) event->any.type)
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
    {
    case GDK_CONFIGURE:
      x = event->configure.x;
      y = event->configure.y;
      break;
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      x = event->crossing.x;
      y = event->crossing.y;
      break;
    case GDK_SCROLL:
      x = event->scroll.x;
      y = event->scroll.y;
      break;
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      x = event->button.x;
      y = event->button.y;
      break;
970 971 972 973 974 975 976
    case GDK_TOUCH_BEGIN:
    case GDK_TOUCH_UPDATE:
    case GDK_TOUCH_END:
    case GDK_TOUCH_CANCEL:
      x = event->touch.x;
      y = event->touch.y;
      break;
977 978 979 980
    case GDK_MOTION_NOTIFY:
      x = event->motion.x;
      y = event->motion.y;
      break;
981 982 983 984 985 986 987 988
    case GDK_TOUCHPAD_SWIPE:
      x = event->touchpad_swipe.x;
      y = event->touchpad_swipe.y;
      break;
    case GDK_TOUCHPAD_PINCH:
      x = event->touchpad_pinch.x;
      y = event->touchpad_pinch.y;
      break;
989 990 991 992 993 994 995 996
    default:
      fetched = FALSE;
      break;
    }

  if (x_win)
    *x_win = x;
  if (y_win)
997
    *y_win = y;
998 999 1000 1001 1002 1003 1004

  return fetched;
}

/**
 * gdk_event_get_root_coords:
 * @event: a #GdkEvent
1005 1006
 * @x_root: (out) (optional): location to put root window x coordinate
 * @y_root: (out) (optional): location to put root window y coordinate
Matthias Clasen's avatar
Matthias Clasen committed
1007
 *
1008
 * Extract the root window relative x/y coordinates from an event.
Matthias Clasen's avatar
Matthias Clasen committed
1009
 *
1010
 * Returns: %TRUE if the event delivered root window coordinates
1011 1012
 **/
gboolean
1013 1014 1015
gdk_event_get_root_coords (const GdkEvent *event,
			   gdouble        *x_root,
			   gdouble        *y_root)
1016 1017 1018 1019 1020 1021
{
  gdouble x = 0, y = 0;
  gboolean fetched = TRUE;
  
  g_return_val_if_fail (event != NULL, FALSE);

1022
  switch ((guint) event->any.type)
1023 1024 1025 1026 1027
    {
    case GDK_MOTION_NOTIFY:
      x = event->motion.x_root;
      y = event->motion.y_root;
      break;
1028 1029 1030 1031
    case GDK_SCROLL:
      x = event->scroll.x_root;
      y = event->scroll.y_root;
      break;
1032 1033 1034 1035 1036
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      x = event->button.x_root;
      y = event->button.y_root;
      break;
1037 1038 1039 1040 1041 1042 1043
    case GDK_TOUCH_BEGIN:
    case GDK_TOUCH_UPDATE:
    case GDK_TOUCH_END:
    case GDK_TOUCH_CANCEL:
      x = event->touch.x_root;
      y = event->touch.y_root;
      break;
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      x = event->crossing.x_root;
      y = event->crossing.y_root;
      break;
    case GDK_DRAG_ENTER:
    case GDK_DRAG_LEAVE:
    case GDK_DRAG_MOTION:
    case GDK_DROP_START:
      x = event->dnd.x_root;
      y = event->dnd.y_root;
      break;
1056 1057 1058 1059 1060 1061 1062 1063
    case GDK_TOUCHPAD_SWIPE:
      x = event->touchpad_swipe.x_root;
      y = event->touchpad_swipe.y_root;
      break;
    case GDK_TOUCHPAD_PINCH:
      x = event->touchpad_pinch.x_root;
      y = event->touchpad_pinch.y_root;
      break;
1064 1065 1066 1067 1068 1069 1070 1071
    default:
      fetched = FALSE;
      break;
    }

  if (x_root)
    *x_root = x;
  if (y_root)
1072
    *y_root = y;
1073 1074 1075 1076

  return fetched;
}

1077 1078 1079 1080 1081 1082 1083
void
gdk_event_set_coords (GdkEvent *event,
                      gdouble   x,
                      gdouble   y)
{
  g_return_if_fail (event != NULL);

1084
  switch ((guint) event->any.type)
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
    {
    case GDK_CONFIGURE:
      event->configure.x = x;
      event->configure.y = y;
      break;
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      event->crossing.x = x;
      event->crossing.y = y;
      break;
    case GDK_SCROLL:
      event->scroll.x = x;
      event->scroll.y = y;
      break;
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      event->button.x = x;
      event->button.y = y;
      break;
    case GDK_TOUCH_BEGIN:
    case GDK_TOUCH_UPDATE:
    case GDK_TOUCH_END:
    case GDK_TOUCH_CANCEL:
      event->touch.x = x;
      event->touch.y = y;
      break;
    case GDK_MOTION_NOTIFY:
      event->motion.x = x;
      event->motion.y = y;
      break;
    case GDK_TOUCHPAD_SWIPE:
      event->touchpad_swipe.x = x;
      event->touchpad_swipe.y = y;
      break;
    case GDK_TOUCHPAD_PINCH:
      event->touchpad_pinch.x = x;
      event->touchpad_pinch.y = y;
      break;
    default:
      break;
    }
}

1128 1129 1130 1131 1132 1133 1134
/**
 * gdk_event_get_button:
 * @event: a #GdkEvent
 * @button: (out): location to store mouse button number
 *
 * Extract the button number from an event.
 *
1135
 * Returns: %TRUE if the event delivered a button number
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
 **/
gboolean
gdk_event_get_button (const GdkEvent *event,
                      guint *button)
{
  gboolean fetched = TRUE;
  guint number = 0;

  g_return_val_if_fail (event != NULL, FALSE);
  
1146
  switch ((guint) event->any.type)
1147 1148 1149 1150 1151
    {
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      number = event->button.button;
      break;
1152 1153 1154 1155
    case GDK_PAD_BUTTON_PRESS:
    case GDK_PAD_BUTTON_RELEASE:
      number = event->pad_button.button;
      break;
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
    default:
      fetched = FALSE;
      break;
    }

  if (button)
    *button = number;

  return fetched;
}

/**
 * gdk_event_get_click_count:
 * @event: a #GdkEvent
 * @click_count: (out): location to store click count
 *
 * Extracts the click count from an event.
 *
1174
 * Returns: %TRUE if the event delivered a click count
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
 */
gboolean
gdk_event_get_click_count (const GdkEvent *event,
                           guint *click_count)
{
  gboolean fetched = TRUE;
  guint number = 0;

  g_return_val_if_fail (event != NULL, FALSE);

1185
  switch ((guint) event->any.type)
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
    {
    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      number = 1;
      break;
    default:
      fetched = FALSE;
      break;
    }

  if (click_count)
    *click_count = number;

  return fetched;
}

/**
 * gdk_event_get_keyval:
 * @event: a #GdkEvent
 * @keyval: (out): location to store the keyval
 *
 * Extracts the keyval from an event.
 *
1209
 * Returns: %TRUE if the event delivered a key symbol
1210 1211 1212 1213 1214 1215 1216 1217
 */
gboolean
gdk_event_get_keyval (const GdkEvent *event,
                      guint *keyval)
{
  gboolean fetched = TRUE;
  guint number = 0;

1218
  switch ((guint) event->any.type)
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      number = event->key.keyval;
      break;
    default:
      fetched = FALSE;
      break;
    }

  if (keyval)
    *keyval = number;

  return fetched;
}

Matthias Clasen's avatar
Matthias Clasen committed
1235 1236 1237 1238
void
gdk_event_set_keyval (GdkEvent *event,
                      guint     keyval)
{
1239 1240
  if (event->any.type == GDK_KEY_PRESS ||
      event->any.type == GDK_KEY_RELEASE)
Matthias Clasen's avatar
Matthias Clasen committed
1241 1242 1243
    event->key.keyval = keyval;
}

1244 1245 1246 1247 1248 1249 1250
/**
 * gdk_event_get_keycode:
 * @event: a #GdkEvent
 * @keycode: (out): location to store the keycode
 *
 * Extracts the hardware keycode from an event.
 *
Matthias Clasen's avatar
Matthias Clasen committed
1251 1252
 * Also see gdk_event_get_scancode().
 *
1253
 * Returns: %TRUE if the event delivered a hardware keycode
1254 1255 1256 1257 1258 1259 1260 1261
 */
gboolean
gdk_event_get_keycode (const GdkEvent *event,
                       guint16 *keycode)
{
  gboolean fetched = TRUE;
  guint16 number = 0;

1262
  switch ((guint) event->any.type)
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      number = event->key.hardware_keycode;
      break;
    default:
      fetched = FALSE;
      break;
    }

  if (keycode)
    *keycode = number;

  return fetched;
}

1279 1280 1281
/**
 * gdk_event_get_key_group:
 * @event: a #GdkEvent
Matthias Clasen's avatar
Matthias Clasen committed
1282 1283 1284 1285
 * @group: (out): return location for the key group
 *
 * Extracts the key group from an event.
 *
1286 1287
 * Returns: %TRUE on success, otherwise %FALSE
 **/
1288 1289 1290 1291 1292 1293
gboolean
gdk_event_get_key_group (const GdkEvent *event,
                         guint          *group)
{
  gboolean fetched = TRUE;

1294
  switch ((guint) event->any.type)
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      *group = event->key.group;
      break;
    default:
      *group = 0;
      fetched = FALSE;
      break;
    }

  return fetched;
}

1309 1310 1311
/**
 * gdk_event_get_string:
 * @event: a #GdkEvent
Matthias Clasen's avatar
Matthias Clasen committed
1312 1313 1314 1315 1316
 * @string: (out) (transfer none): return location for the string
 *
 * Extracts a string from an event. The string is an
 * approximation of the keyval in a key event.
 *
1317 1318
 * Returns: %TRUE on success, otherwise %FALSE
 **/
1319 1320 1321 1322 1323 1324
gboolean
gdk_event_get_string (const GdkEvent  *event,
                      const char     **string)
{
  gboolean fetched = TRUE;

1325
  switch ((guint) event->any.type)
1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      *string = event->key.string;
      break;
    default:
      *string = NULL;
      fetched = FALSE;
      break;
    }

  return fetched;
}

1340 1341 1342
/**
 * gdk_event_get_key_is_modifier:
 * @event: a #GdkEvent
Matthias Clasen's avatar
Matthias Clasen committed
1343 1344 1345 1346 1347
 * @is_modifier: (out): return location for the value
 *
 * Extracts whether the event is a key event for
 * a modifier key.
 *
1348 1349
 * Returns: %TRUE on success, otherwise %FALSE
 **/
1350 1351 1352 1353 1354 1355
gboolean
gdk_event_get_key_is_modifier (const GdkEvent *event,
                               gboolean       *is_modifier)
{
  gboolean fetched = TRUE;

1356
  switch ((guint) event->any.type)
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      *is_modifier = event->key.is_modifier;
      break;
    default:
      *is_modifier = FALSE;
      fetched = FALSE;
      break;
    }

  return fetched;
}

1371 1372 1373 1374 1375 1376 1377
/**
 * gdk_event_get_scroll_direction:
 * @event: a #GdkEvent
 * @direction: (out): location to store the scroll direction
 *
 * Extracts the scroll direction from an event.
 *
1378
 * Returns: %TRUE if the event delivered a scroll direction
1379 1380 1381 1382 1383 1384 1385 1386
 */
gboolean
gdk_event_get_scroll_direction (const GdkEvent *event,
                                GdkScrollDirection *direction)
{
  gboolean fetched = TRUE;
  GdkScrollDirection dir = 0;

1387
  switch ((guint) event->any.type)
1388 1389
    {
    case GDK_SCROLL: