2010-05-25 22:38:44 +00:00
|
|
|
/* GDK - The GIMP Drawing Kit
|
|
|
|
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-02-27 13:01:10 +00:00
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2010-05-25 22:38:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "gdkeventsource.h"
|
2010-10-15 02:05:51 +00:00
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
#include "gdkinternals.h"
|
2018-03-20 10:46:11 +00:00
|
|
|
#include "gdksurface-x11.h"
|
2010-12-16 03:09:35 +00:00
|
|
|
#include "gdkprivate-x11.h"
|
2018-02-07 05:00:01 +00:00
|
|
|
#include "gdkdisplay-x11.h"
|
2017-08-22 19:08:14 +00:00
|
|
|
#include "xsettings-client.h"
|
2010-07-09 00:34:45 +00:00
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
static gboolean gdk_event_source_prepare (GSource *source,
|
|
|
|
gint *timeout);
|
|
|
|
static gboolean gdk_event_source_check (GSource *source);
|
|
|
|
static gboolean gdk_event_source_dispatch (GSource *source,
|
|
|
|
GSourceFunc callback,
|
|
|
|
gpointer user_data);
|
|
|
|
static void gdk_event_source_finalize (GSource *source);
|
|
|
|
|
2017-09-19 16:14:53 +00:00
|
|
|
static GQuark quark_needs_enter = 0;
|
|
|
|
|
2019-04-30 14:45:51 +00:00
|
|
|
#define HAS_FOCUS(toplevel) \
|
|
|
|
((toplevel)->has_focus || (toplevel)->has_pointer_focus)
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
struct _GdkEventSource
|
|
|
|
{
|
|
|
|
GSource source;
|
|
|
|
|
|
|
|
GdkDisplay *display;
|
|
|
|
GPollFD event_poll_fd;
|
|
|
|
GList *translators;
|
|
|
|
};
|
|
|
|
|
|
|
|
static GSourceFuncs event_funcs = {
|
|
|
|
gdk_event_source_prepare,
|
|
|
|
gdk_event_source_check,
|
|
|
|
gdk_event_source_dispatch,
|
|
|
|
gdk_event_source_finalize
|
|
|
|
};
|
|
|
|
|
2018-03-20 10:40:08 +00:00
|
|
|
static GdkSurface *
|
2018-03-20 14:14:10 +00:00
|
|
|
gdk_event_source_get_filter_surface (GdkEventSource *event_source,
|
|
|
|
const XEvent *xevent,
|
|
|
|
GdkEventTranslator **event_translator)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
2011-05-18 19:24:57 +00:00
|
|
|
GList *list = event_source->translators;
|
2018-03-20 14:14:10 +00:00
|
|
|
GdkSurface *surface;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2011-05-18 19:24:57 +00:00
|
|
|
*event_translator = NULL;
|
|
|
|
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
GdkEventTranslator *translator = list->data;
|
|
|
|
|
|
|
|
list = list->next;
|
2018-03-20 14:14:10 +00:00
|
|
|
surface = _gdk_x11_event_translator_get_surface (translator,
|
2011-05-18 19:24:57 +00:00
|
|
|
event_source->display,
|
|
|
|
xevent);
|
2018-03-20 14:14:10 +00:00
|
|
|
if (surface)
|
2011-05-18 19:24:57 +00:00
|
|
|
{
|
|
|
|
*event_translator = translator;
|
2018-03-20 14:14:10 +00:00
|
|
|
return surface;
|
2011-05-18 19:24:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-20 14:14:10 +00:00
|
|
|
surface = gdk_x11_surface_lookup_for_display (event_source->display,
|
2010-12-15 17:25:38 +00:00
|
|
|
xevent->xany.window);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2018-03-20 14:14:10 +00:00
|
|
|
return surface;
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_focus_change (GdkEventCrossing *event)
|
|
|
|
{
|
|
|
|
GdkToplevelX11 *toplevel;
|
2016-02-12 20:59:29 +00:00
|
|
|
GdkX11Screen *x11_screen;
|
2010-05-25 22:38:44 +00:00
|
|
|
gboolean focus_in, had_focus;
|
|
|
|
|
2018-03-20 14:14:10 +00:00
|
|
|
toplevel = _gdk_x11_surface_get_toplevel (event->any.surface);
|
|
|
|
x11_screen = GDK_X11_SCREEN (GDK_SURFACE_SCREEN (event->any.surface));
|
2017-10-11 13:35:29 +00:00
|
|
|
focus_in = (event->any.type == GDK_ENTER_NOTIFY);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2016-02-12 20:59:29 +00:00
|
|
|
if (x11_screen->wmspec_check_window)
|
|
|
|
return;
|
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
if (!toplevel || event->detail == GDK_NOTIFY_INFERIOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
toplevel->has_pointer = focus_in;
|
|
|
|
|
|
|
|
if (!event->focus || toplevel->has_focus_window)
|
|
|
|
return;
|
|
|
|
|
2019-04-30 14:45:51 +00:00
|
|
|
had_focus = HAS_FOCUS (toplevel);
|
2010-05-25 22:38:44 +00:00
|
|
|
toplevel->has_pointer_focus = focus_in;
|
|
|
|
|
2019-04-30 14:45:51 +00:00
|
|
|
if (HAS_FOCUS (toplevel) != had_focus)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
GdkEvent *focus_event;
|
|
|
|
|
|
|
|
focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
|
2018-03-20 14:14:10 +00:00
|
|
|
focus_event->any.surface = g_object_ref (event->any.surface);
|
2017-10-11 13:35:29 +00:00
|
|
|
focus_event->any.send_event = FALSE;
|
2010-05-25 22:38:44 +00:00
|
|
|
focus_event->focus_change.in = focus_in;
|
|
|
|
gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));
|
|
|
|
|
2018-03-20 14:14:10 +00:00
|
|
|
gdk_display_put_event (gdk_surface_get_display (event->any.surface), focus_event);
|
2017-10-31 12:35:11 +00:00
|
|
|
g_object_unref (focus_event);
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:14:53 +00:00
|
|
|
static GdkEvent *
|
|
|
|
create_synth_crossing_event (GdkEventType evtype,
|
|
|
|
GdkCrossingMode mode,
|
|
|
|
const GdkEvent *real_event)
|
|
|
|
{
|
|
|
|
GdkEvent *event;
|
|
|
|
gdouble x, y;
|
|
|
|
GdkModifierType state;
|
|
|
|
|
|
|
|
g_assert (evtype == GDK_ENTER_NOTIFY || evtype == GDK_LEAVE_NOTIFY);
|
|
|
|
|
|
|
|
event = gdk_event_new (evtype);
|
2017-10-11 13:35:29 +00:00
|
|
|
event->any.send_event = TRUE;
|
2018-03-20 14:14:10 +00:00
|
|
|
event->any.surface = g_object_ref (real_event->any.surface);
|
2017-09-19 16:14:53 +00:00
|
|
|
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
|
|
|
|
event->crossing.mode = mode;
|
|
|
|
event->crossing.time = gdk_event_get_time (real_event);
|
|
|
|
gdk_event_set_device (event, gdk_event_get_device (real_event));
|
|
|
|
gdk_event_set_source_device (event, gdk_event_get_device (real_event));
|
|
|
|
|
|
|
|
if (gdk_event_get_state (real_event, &state))
|
|
|
|
event->crossing.state = state;
|
|
|
|
|
|
|
|
if (gdk_event_get_coords (real_event, &x, &y))
|
|
|
|
gdk_event_set_coords (event, x, y);
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_touch_synthetic_crossing (GdkEvent *event)
|
|
|
|
{
|
|
|
|
GdkEventType evtype = gdk_event_get_event_type (event);
|
|
|
|
GdkDevice *device = gdk_event_get_device (event);
|
|
|
|
GdkEvent *crossing = NULL;
|
|
|
|
GdkSeat *seat = gdk_device_get_seat (device);
|
|
|
|
gboolean needs_enter, set_needs_enter = FALSE;
|
|
|
|
|
|
|
|
if (quark_needs_enter == 0)
|
|
|
|
quark_needs_enter = g_quark_from_static_string ("gdk-x11-needs-enter-after-touch-end");
|
|
|
|
|
|
|
|
needs_enter =
|
|
|
|
GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (seat), quark_needs_enter));
|
|
|
|
|
|
|
|
if (evtype == GDK_MOTION_NOTIFY && needs_enter)
|
|
|
|
{
|
|
|
|
set_needs_enter = FALSE;
|
|
|
|
crossing = create_synth_crossing_event (GDK_ENTER_NOTIFY,
|
|
|
|
GDK_CROSSING_DEVICE_SWITCH,
|
|
|
|
event);
|
|
|
|
}
|
|
|
|
else if (evtype == GDK_TOUCH_BEGIN && needs_enter &&
|
|
|
|
gdk_event_get_pointer_emulated (event))
|
|
|
|
{
|
|
|
|
set_needs_enter = FALSE;
|
|
|
|
crossing = create_synth_crossing_event (GDK_ENTER_NOTIFY,
|
|
|
|
GDK_CROSSING_TOUCH_BEGIN,
|
|
|
|
event);
|
|
|
|
}
|
|
|
|
else if (evtype == GDK_TOUCH_END &&
|
|
|
|
gdk_event_get_pointer_emulated (event))
|
|
|
|
{
|
|
|
|
set_needs_enter = TRUE;
|
|
|
|
crossing = create_synth_crossing_event (GDK_LEAVE_NOTIFY,
|
|
|
|
GDK_CROSSING_TOUCH_END,
|
|
|
|
event);
|
|
|
|
}
|
|
|
|
else if (evtype == GDK_ENTER_NOTIFY ||
|
|
|
|
evtype == GDK_LEAVE_NOTIFY)
|
|
|
|
{
|
|
|
|
/* We are receiving or shall receive a real crossing event,
|
|
|
|
* turn this off.
|
|
|
|
*/
|
|
|
|
set_needs_enter = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (needs_enter != set_needs_enter)
|
|
|
|
{
|
|
|
|
if (!set_needs_enter)
|
|
|
|
g_object_steal_qdata (G_OBJECT (seat), quark_needs_enter);
|
|
|
|
else
|
|
|
|
g_object_set_qdata (G_OBJECT (seat), quark_needs_enter,
|
|
|
|
GUINT_TO_POINTER (TRUE));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (crossing)
|
|
|
|
{
|
2017-12-12 23:35:16 +00:00
|
|
|
gdk_display_put_event (gdk_device_get_display (device), crossing);
|
2017-10-31 12:35:11 +00:00
|
|
|
g_object_unref (crossing);
|
2017-09-19 16:14:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-13 00:53:17 +00:00
|
|
|
static GdkEvent *
|
2017-12-12 23:43:30 +00:00
|
|
|
gdk_event_source_translate_event (GdkX11Display *x11_display,
|
|
|
|
const XEvent *xevent)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
2017-12-12 23:43:30 +00:00
|
|
|
GdkEventSource *event_source = (GdkEventSource *) x11_display->event_source;
|
2018-05-22 13:48:50 +00:00
|
|
|
GdkEvent *event;
|
2011-05-18 17:37:34 +00:00
|
|
|
GdkFilterReturn result = GDK_FILTER_CONTINUE;
|
2017-12-12 23:43:30 +00:00
|
|
|
GdkDisplay *display = GDK_DISPLAY (x11_display);
|
2011-05-18 19:24:57 +00:00
|
|
|
GdkEventTranslator *event_translator;
|
2018-03-20 14:14:10 +00:00
|
|
|
GdkSurface *filter_surface;
|
2011-05-18 17:37:34 +00:00
|
|
|
Display *dpy;
|
2017-08-22 19:08:14 +00:00
|
|
|
GdkX11Screen *x11_screen;
|
2017-11-09 23:40:16 +00:00
|
|
|
gpointer cache;
|
2017-08-22 19:08:14 +00:00
|
|
|
|
2017-12-12 23:43:30 +00:00
|
|
|
x11_screen = GDK_X11_DISPLAY (display)->screen;
|
|
|
|
dpy = GDK_DISPLAY_XDISPLAY (display);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2018-05-22 13:48:50 +00:00
|
|
|
event = gdk_event_new (GDK_NOTHING);
|
2018-03-20 14:14:10 +00:00
|
|
|
filter_surface = gdk_event_source_get_filter_surface (event_source, xevent,
|
2011-05-18 19:24:57 +00:00
|
|
|
&event_translator);
|
2018-03-20 14:14:10 +00:00
|
|
|
if (filter_surface)
|
|
|
|
event->any.surface = g_object_ref (filter_surface);
|
2011-02-01 04:55:10 +00:00
|
|
|
|
2017-08-22 19:08:14 +00:00
|
|
|
/* apply XSettings filters */
|
|
|
|
if (xevent->xany.window == XRootWindow (dpy, 0))
|
|
|
|
result = gdk_xsettings_root_window_filter (xevent, event, x11_screen);
|
|
|
|
|
|
|
|
if (result == GDK_FILTER_CONTINUE &&
|
|
|
|
xevent->xany.window == x11_screen->xsettings_manager_window)
|
|
|
|
result = gdk_xsettings_manager_window_filter (xevent, event, x11_screen);
|
|
|
|
|
2018-03-20 10:40:08 +00:00
|
|
|
cache = gdk_surface_cache_get (display);
|
2017-11-09 23:40:16 +00:00
|
|
|
if (cache)
|
|
|
|
{
|
|
|
|
if (result == GDK_FILTER_CONTINUE)
|
2018-03-20 10:40:08 +00:00
|
|
|
result = gdk_surface_cache_shape_filter (xevent, event, cache);
|
2017-11-09 23:40:16 +00:00
|
|
|
|
|
|
|
if (result == GDK_FILTER_CONTINUE &&
|
|
|
|
xevent->xany.window == XRootWindow (dpy, 0))
|
2018-03-20 10:40:08 +00:00
|
|
|
result = gdk_surface_cache_filter (xevent, event, cache);
|
2017-11-09 23:40:16 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 09:32:22 +00:00
|
|
|
if (result == GDK_FILTER_CONTINUE)
|
2018-02-07 05:00:01 +00:00
|
|
|
result = _gdk_wm_protocols_filter (xevent, event, NULL);
|
2018-02-07 03:10:43 +00:00
|
|
|
|
2018-06-14 00:47:56 +00:00
|
|
|
if (result == GDK_FILTER_CONTINUE &&
|
|
|
|
gdk_x11_drop_filter (event->any.surface, xevent))
|
|
|
|
result = GDK_FILTER_REMOVE;
|
2011-05-18 17:37:34 +00:00
|
|
|
|
|
|
|
if (result != GDK_FILTER_CONTINUE)
|
|
|
|
{
|
2010-05-25 22:38:44 +00:00
|
|
|
if (result == GDK_FILTER_REMOVE)
|
|
|
|
{
|
2017-10-31 12:35:11 +00:00
|
|
|
g_object_unref (event);
|
2010-05-25 22:38:44 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2011-05-18 17:37:34 +00:00
|
|
|
else /* GDK_FILTER_TRANSLATE */
|
2010-05-25 22:38:44 +00:00
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
2017-10-31 12:35:11 +00:00
|
|
|
g_object_unref (event);
|
2010-05-25 22:38:44 +00:00
|
|
|
event = NULL;
|
|
|
|
|
2011-05-18 19:24:57 +00:00
|
|
|
if (event_translator)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
2011-05-18 19:24:57 +00:00
|
|
|
/* Event translator was gotten before in get_filter_window() */
|
|
|
|
event = _gdk_x11_event_translator_translate (event_translator,
|
2017-12-12 23:43:30 +00:00
|
|
|
display,
|
2010-12-15 19:49:23 +00:00
|
|
|
xevent);
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
2011-05-18 19:24:57 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
GList *list = event_source->translators;
|
|
|
|
|
|
|
|
while (list && !event)
|
|
|
|
{
|
|
|
|
GdkEventTranslator *translator = list->data;
|
|
|
|
|
|
|
|
list = list->next;
|
|
|
|
event = _gdk_x11_event_translator_translate (translator,
|
2017-12-12 23:43:30 +00:00
|
|
|
display,
|
2011-05-18 19:24:57 +00:00
|
|
|
xevent);
|
|
|
|
}
|
|
|
|
}
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2019-03-07 04:38:52 +00:00
|
|
|
if (event &&
|
|
|
|
event->any.type == GDK_NOTHING)
|
|
|
|
{
|
|
|
|
g_clear_object (&event);
|
|
|
|
}
|
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
if (event &&
|
2017-10-11 13:55:19 +00:00
|
|
|
(event->any.type == GDK_ENTER_NOTIFY ||
|
|
|
|
event->any.type == GDK_LEAVE_NOTIFY) &&
|
2018-03-20 14:14:10 +00:00
|
|
|
event->any.surface != NULL)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
/* Handle focusing (in the case where no window manager is running */
|
|
|
|
handle_focus_change (&event->crossing);
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:14:53 +00:00
|
|
|
if (event &&
|
2017-10-11 13:55:19 +00:00
|
|
|
(event->any.type == GDK_TOUCH_BEGIN ||
|
|
|
|
event->any.type == GDK_TOUCH_END ||
|
|
|
|
event->any.type == GDK_MOTION_NOTIFY ||
|
|
|
|
event->any.type == GDK_ENTER_NOTIFY ||
|
|
|
|
event->any.type == GDK_LEAVE_NOTIFY))
|
2017-09-19 16:14:53 +00:00
|
|
|
{
|
|
|
|
handle_touch_synthetic_crossing (event);
|
|
|
|
}
|
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
2017-12-13 00:53:17 +00:00
|
|
|
gboolean
|
|
|
|
gdk_event_source_xevent (GdkX11Display *x11_display,
|
|
|
|
const XEvent *xevent)
|
|
|
|
{
|
|
|
|
GdkDisplay *display = GDK_DISPLAY (x11_display);
|
|
|
|
GdkEvent *event;
|
|
|
|
GList *node;
|
|
|
|
|
|
|
|
event = gdk_event_source_translate_event (x11_display, xevent);
|
|
|
|
if (event == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
node = _gdk_event_queue_append (display, event);
|
|
|
|
_gdk_windowing_got_event (display, node, event, xevent->xany.serial);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-05-25 22:38:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_check_xpending (GdkDisplay *display)
|
|
|
|
{
|
|
|
|
return XPending (GDK_DISPLAY_XDISPLAY (display));
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_event_source_prepare (GSource *source,
|
|
|
|
gint *timeout)
|
|
|
|
{
|
|
|
|
GdkDisplay *display = ((GdkEventSource*) source)->display;
|
|
|
|
gboolean retval;
|
|
|
|
|
|
|
|
*timeout = -1;
|
2012-10-07 15:47:49 +00:00
|
|
|
|
|
|
|
if (display->event_pause_count > 0)
|
2013-11-11 23:04:34 +00:00
|
|
|
retval = _gdk_event_queue_find_first (display) != NULL;
|
2012-10-07 15:47:49 +00:00
|
|
|
else
|
|
|
|
retval = (_gdk_event_queue_find_first (display) != NULL ||
|
|
|
|
gdk_check_xpending (display));
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_event_source_check (GSource *source)
|
|
|
|
{
|
|
|
|
GdkEventSource *event_source = (GdkEventSource*) source;
|
|
|
|
gboolean retval;
|
|
|
|
|
2012-10-07 15:47:49 +00:00
|
|
|
if (event_source->display->event_pause_count > 0)
|
2013-11-11 23:04:34 +00:00
|
|
|
retval = _gdk_event_queue_find_first (event_source->display) != NULL;
|
2012-10-07 15:47:49 +00:00
|
|
|
else if (event_source->event_poll_fd.revents & G_IO_IN)
|
2010-05-25 22:38:44 +00:00
|
|
|
retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
|
2010-12-15 17:25:38 +00:00
|
|
|
gdk_check_xpending (event_source->display));
|
2010-05-25 22:38:44 +00:00
|
|
|
else
|
|
|
|
retval = FALSE;
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-12-11 01:46:42 +00:00
|
|
|
_gdk_x11_display_queue_events (GdkDisplay *display)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
|
2017-12-13 00:53:17 +00:00
|
|
|
XEvent xevent;
|
|
|
|
gboolean unused;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
while (!_gdk_event_queue_find_first (display) && XPending (xdisplay))
|
|
|
|
{
|
|
|
|
XNextEvent (xdisplay, &xevent);
|
|
|
|
|
|
|
|
switch (xevent.type)
|
2010-12-11 01:46:42 +00:00
|
|
|
{
|
|
|
|
case KeyPress:
|
|
|
|
case KeyRelease:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (XFilterEvent (&xevent, None))
|
|
|
|
continue;
|
|
|
|
}
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2017-12-12 23:43:30 +00:00
|
|
|
#ifdef HAVE_XGENERICEVENTS
|
|
|
|
/* Get cookie data here so it's available
|
|
|
|
* to every event translator and event filter.
|
|
|
|
*/
|
|
|
|
if (xevent.type == GenericEvent)
|
|
|
|
XGetEventData (xdisplay, &xevent.xcookie);
|
|
|
|
#endif
|
|
|
|
|
2017-12-13 00:53:17 +00:00
|
|
|
g_signal_emit_by_name (display, "xevent", &xevent, &unused);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2017-12-12 23:43:30 +00:00
|
|
|
#ifdef HAVE_XGENERICEVENTS
|
|
|
|
if (xevent.type == GenericEvent)
|
|
|
|
XFreeEventData (xdisplay, &xevent.xcookie);
|
|
|
|
#endif
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_event_source_dispatch (GSource *source,
|
|
|
|
GSourceFunc callback,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GdkDisplay *display = ((GdkEventSource*) source)->display;
|
|
|
|
GdkEvent *event;
|
|
|
|
|
|
|
|
event = gdk_display_get_event (display);
|
|
|
|
|
|
|
|
if (event)
|
|
|
|
{
|
2010-12-02 09:59:37 +00:00
|
|
|
_gdk_event_emit (event);
|
2010-05-25 22:38:44 +00:00
|
|
|
|
2017-10-31 12:35:11 +00:00
|
|
|
g_object_unref (event);
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_event_source_finalize (GSource *source)
|
|
|
|
{
|
2010-09-19 02:57:36 +00:00
|
|
|
GdkEventSource *event_source = (GdkEventSource *)source;
|
|
|
|
|
|
|
|
g_list_free (event_source->translators);
|
|
|
|
event_source->translators = NULL;
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GSource *
|
2010-12-15 17:25:38 +00:00
|
|
|
gdk_x11_event_source_new (GdkDisplay *display)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
GSource *source;
|
|
|
|
GdkEventSource *event_source;
|
2010-12-20 16:14:04 +00:00
|
|
|
GdkX11Display *display_x11;
|
2010-05-25 22:38:44 +00:00
|
|
|
int connection_number;
|
2010-06-03 20:24:38 +00:00
|
|
|
char *name;
|
2010-05-25 22:38:44 +00:00
|
|
|
|
|
|
|
source = g_source_new (&event_funcs, sizeof (GdkEventSource));
|
2010-06-03 20:24:38 +00:00
|
|
|
name = g_strdup_printf ("GDK X11 Event source (%s)",
|
2010-12-15 17:25:38 +00:00
|
|
|
gdk_display_get_name (display));
|
2010-06-03 20:24:38 +00:00
|
|
|
g_source_set_name (source, name);
|
|
|
|
g_free (name);
|
2010-05-25 22:38:44 +00:00
|
|
|
event_source = (GdkEventSource *) source;
|
|
|
|
event_source->display = display;
|
|
|
|
|
2010-12-20 18:20:10 +00:00
|
|
|
display_x11 = GDK_X11_DISPLAY (display);
|
2010-05-25 22:38:44 +00:00
|
|
|
connection_number = ConnectionNumber (display_x11->xdisplay);
|
|
|
|
|
|
|
|
event_source->event_poll_fd.fd = connection_number;
|
|
|
|
event_source->event_poll_fd.events = G_IO_IN;
|
|
|
|
g_source_add_poll (source, &event_source->event_poll_fd);
|
|
|
|
|
|
|
|
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
|
|
|
|
g_source_set_can_recurse (source, TRUE);
|
|
|
|
g_source_attach (source, NULL);
|
|
|
|
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-12-15 17:25:38 +00:00
|
|
|
gdk_x11_event_source_add_translator (GdkEventSource *source,
|
|
|
|
GdkEventTranslator *translator)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
g_return_if_fail (GDK_IS_EVENT_TRANSLATOR (translator));
|
|
|
|
|
|
|
|
source->translators = g_list_append (source->translators, translator);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-12-15 17:25:38 +00:00
|
|
|
gdk_x11_event_source_select_events (GdkEventSource *source,
|
|
|
|
Window window,
|
|
|
|
GdkEventMask event_mask,
|
|
|
|
unsigned int extra_x_mask)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
unsigned int xmask = extra_x_mask;
|
|
|
|
GList *list;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
list = source->translators;
|
|
|
|
|
|
|
|
while (list)
|
|
|
|
{
|
|
|
|
GdkEventTranslator *translator = list->data;
|
|
|
|
GdkEventMask translator_mask, mask;
|
|
|
|
|
2010-12-15 19:49:23 +00:00
|
|
|
translator_mask = _gdk_x11_event_translator_get_handled_events (translator);
|
2010-05-25 22:38:44 +00:00
|
|
|
mask = event_mask & translator_mask;
|
|
|
|
|
|
|
|
if (mask != 0)
|
|
|
|
{
|
2018-03-20 11:05:26 +00:00
|
|
|
_gdk_x11_event_translator_select_surface_events (translator, window, mask);
|
2010-05-25 22:38:44 +00:00
|
|
|
event_mask &= ~mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = list->next;
|
|
|
|
}
|
|
|
|
|
2010-12-15 22:32:29 +00:00
|
|
|
for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
|
2010-05-25 22:38:44 +00:00
|
|
|
{
|
|
|
|
if (event_mask & (1 << (i + 1)))
|
2010-12-15 22:32:29 +00:00
|
|
|
xmask |= _gdk_x11_event_mask_table[i];
|
2010-05-25 22:38:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XSelectInput (GDK_DISPLAY_XDISPLAY (source->display), window, xmask);
|
|
|
|
}
|