* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
+#include <string.h> /* For memset() */
+
#include "gdk.h"
#include "gdkinternals.h"
gpointer _gdk_event_data = NULL;
GDestroyNotify _gdk_event_notify = NULL;
-#define TRIPLE_CLICK_TIME(display) (2*display->double_click_time)
-#define DOUBLE_CLICK_DIST 5
-#define TRIPLE_CLICK_DIST 5
-
/*********************************************
* Functions for maintaining the event queue *
*********************************************/
}
static GMemChunk *event_chunk = NULL;
+static GHashTable *event_hash = NULL;
+/**
+ * gdk_event_new:
+ * @type: a #GdkEventType
+ *
+ * Creates a new event of the given type. All fields are set to 0.
+ *
+ * Return value: a newly-allocated #GdkEvent. The returned #GdkEvent
+ * should be freed with gdk_event_free().
+ *
+ * Since: 2.2
+ **/
GdkEvent*
-_gdk_event_new (void)
+gdk_event_new (GdkEventType type)
{
- GdkEventPrivate *new_event;
+ GdkEventPrivate *new_private;
+ GdkEvent *new_event;
if (event_chunk == NULL)
- event_chunk = g_mem_chunk_new ("events",
- sizeof (GdkEventPrivate),
- 4096,
- G_ALLOC_AND_FREE);
+ {
+ event_chunk = g_mem_chunk_new ("events",
+ sizeof (GdkEventPrivate),
+ 4096,
+ G_ALLOC_AND_FREE);
+ event_hash = g_hash_table_new (g_direct_hash, NULL);
+ }
+
+ new_private = g_chunk_new (GdkEventPrivate, event_chunk);
+ memset (new_private, 0, sizeof (GdkEventPrivate));
- new_event = g_chunk_new (GdkEventPrivate, event_chunk);
- new_event->flags = 0;
+ new_private->flags = 0;
+ new_private->screen = NULL;
+
+ g_hash_table_insert (event_hash, new_private, GUINT_TO_POINTER (1));
+
+ new_event = (GdkEvent *) new_private;
+
+ new_event->any.type = type;
+
+ /*
+ * 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.
+ */
+ switch (type)
+ {
+ 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_2BUTTON_PRESS:
+ case GDK_3BUTTON_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;
+ 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.;
+ 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;
+ default:
+ break;
+ }
- return (GdkEvent*) new_event;
+ return new_event;
}
+static gboolean
+gdk_event_is_allocated (GdkEvent *event)
+{
+ if (event_hash)
+ return g_hash_table_lookup (event_hash, event) != NULL;
+
+ return FALSE;
+}
+
/**
* gdk_event_copy:
* @event: a #GdkEvent
GdkEvent*
gdk_event_copy (GdkEvent *event)
{
+ GdkEventPrivate *new_private;
GdkEvent *new_event;
g_return_val_if_fail (event != NULL, NULL);
- new_event = _gdk_event_new ();
-
+ new_event = gdk_event_new (GDK_NOTHING);
+ new_private = (GdkEventPrivate *)new_event;
+
*new_event = *event;
if (new_event->any.window)
g_object_ref (new_event->any.window);
+
+ if (gdk_event_is_allocated (event))
+ {
+ GdkEventPrivate *private = (GdkEventPrivate *)event;
+
+ new_private->screen = private->screen;
+ }
switch (event->any.type)
{
case GDK_SETTING:
new_event->setting.name = g_strdup (new_event->setting.name);
break;
+
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ if (event->button.axes)
+ new_event->button.axes = g_memdup (event->button.axes,
+ sizeof (gdouble) * event->button.device->num_axes);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ if (event->motion.axes)
+ new_event->motion.axes = g_memdup (event->motion.axes,
+ sizeof (gdouble) * event->motion.device->num_axes);
+
+ break;
default:
break;
default:
break;
}
-
+
+ g_hash_table_remove (event_hash, event);
g_mem_chunk_free (event_chunk, event);
}
return gdk_device_get_axis (device, axes, axis_use, value);
}
+/**
+ * gdk_event_set_screen:
+ * @event: a #GdkEvent
+ * @screen: a #GdkScreen
+ *
+ * Sets the screen for @event to @screen. The event must
+ * have been allocated by GTK+, for instance, by
+ * gdk_event_copy().
+ *
+ * Since: 2.2
+ **/
+void
+gdk_event_set_screen (GdkEvent *event,
+ GdkScreen *screen)
+{
+ GdkEventPrivate *private;
+
+ g_return_if_fail (gdk_event_is_allocated (event));
+
+ private = (GdkEventPrivate *)event;
+
+ private->screen = screen;
+}
+
+/**
+ * gdk_event_get_screen:
+ * @event: a #GdkEvent
+ *
+ * Returns the screen for the event. The screen is
+ * typically the screen for <literal>event->any.window</literal>, but
+ * for events such as mouse events, it is the screen
+ * where the the pointer was when the event occurs -
+ * that is, the screen which has the root window
+ * to which <literal>event->motion.x_root</literal> and
+ * <literal>event->motion.y_root</literal> are relative.
+ *
+ * Return value: the screen for the event
+ *
+ * Since: 2.2
+ **/
+GdkScreen *
+gdk_event_get_screen (GdkEvent *event)
+{
+ if (gdk_event_is_allocated (event))
+ {
+ GdkEventPrivate *private = (GdkEventPrivate *)event;
+
+ if (private->screen)
+ return private->screen;
+ }
+
+ if (event->any.window)
+ return gdk_drawable_get_screen (event->any.window);
+
+ return NULL;
+}
+
/**
* gdk_set_show_events:
* @show_events: %TRUE to output event debugging information.
_gdk_event_button_generate (GdkDisplay *display,
GdkEvent *event)
{
- if ((event->button.time < (display->button_click_time[1] + TRIPLE_CLICK_TIME (display))) &&
+ if ((event->button.time < (display->button_click_time[1] + 2*display->double_click_time)) &&
(event->button.window == display->button_window[1]) &&
- (event->button.button == display->button_number[1]))
- {
+ (event->button.button == display->button_number[1]) &&
+ (ABS (event->button.x - display->button_x[1]) <= display->double_click_distance) &&
+ (ABS (event->button.y - display->button_y[1]) <= display->double_click_distance))
+{
gdk_synthesize_click (display, event, 3);
-
+
display->button_click_time[1] = 0;
display->button_click_time[0] = 0;
display->button_window[1] = NULL;
display->button_window[0] = 0;
display->button_number[1] = -1;
display->button_number[0] = -1;
+ display->button_x[0] = display->button_x[1] = 0;
+ display->button_y[0] = display->button_y[1] = 0;
}
else if ((event->button.time < (display->button_click_time[0] + display->double_click_time)) &&
(event->button.window == display->button_window[0]) &&
- (event->button.button == display->button_number[0]))
+ (event->button.button == display->button_number[0]) &&
+ (ABS (event->button.x - display->button_x[0]) <= display->double_click_distance) &&
+ (ABS (event->button.y - display->button_y[0]) <= display->double_click_distance))
{
gdk_synthesize_click (display, event, 2);
display->button_window[0] = event->button.window;
display->button_number[1] = display->button_number[0];
display->button_number[0] = event->button.button;
+ display->button_x[1] = display->button_x[0];
+ display->button_x[0] = event->button.x;
+ display->button_y[1] = display->button_y[0];
+ display->button_y[0] = event->button.y;
}
else
{
display->button_window[0] = event->button.window;
display->button_number[1] = -1;
display->button_number[0] = event->button.button;
+ display->button_x[1] = 0;
+ display->button_x[0] = event->button.x;
+ display->button_y[1] = 0;
+ display->button_y[0] = event->button.y;
}
}
old = ((GdkWindowObject*) temp_event.window_state.window)->state;
- temp_event.window_state.changed_mask = (unset_flags | set_flags) ^ old;
temp_event.window_state.new_window_state = old;
temp_event.window_state.new_window_state |= set_flags;
temp_event.window_state.new_window_state &= ~unset_flags;
+ temp_event.window_state.changed_mask = temp_event.window_state.new_window_state ^ old;
if (temp_event.window_state.new_window_state == old)
return; /* No actual work to do, nothing changed. */
*
* Sets the double click time (two clicks within this time interval
* count as a double click and result in a #GDK_2BUTTON_PRESS event).
- * Applications should NOT set this, it is a global user-configured setting.
+ * Applications should <emphasis>not</emphasis> set this, it is a global
+ * user-configured setting.
+ *
+ * Since: 2.2
**/
void
gdk_display_set_double_click_time (GdkDisplay *display,
* @msec: double click time in milliseconds (thousandths of a second)
*
* Set the double click time for the default display. See
- * gdk_display_set_double_click_time(). Applications should NOT
- * set this, it is a global user-configured setting.
+ * gdk_display_set_double_click_time().
+ * See also gdk_display_set_double_click_distance().
+ * Applications should <emphasis>not</emphasis> set this, it is a
+ * global user-configured setting.
**/
void
gdk_set_double_click_time (guint msec)
gdk_display_set_double_click_time (gdk_display_get_default (), msec);
}
+/**
+ * gdk_display_set_double_click_distance:
+ * @display: a #GdkDisplay
+ * @distance: distance in pixels
+ *
+ * Sets the double click distance (two clicks within this distance
+ * count as a double click and result in a #GDK_2BUTTON_PRESS event).
+ * See also gdk_display_set_double_click_time().
+ * Applications should <emphasis>not</emphasis> set this, it is a global
+ * user-configured setting.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_display_set_double_click_distance (GdkDisplay *display,
+ guint distance)
+{
+ display->double_click_distance = distance;
+}
+
GType
gdk_event_get_type (void)
{