2010-12-18 20:38:49 +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-12-18 20:38:49 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2011-02-09 19:48:29 +00:00
|
|
|
#include "gdkprivate-wayland.h"
|
2010-12-18 20:38:49 +00:00
|
|
|
|
2021-09-24 19:49:38 +00:00
|
|
|
#include "gdkeventsprivate.h"
|
|
|
|
|
2017-05-24 14:42:01 +00:00
|
|
|
#include <unistd.h>
|
2013-07-09 17:08:21 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
typedef struct _GdkWaylandEventSource GdkWaylandEventSource;
|
|
|
|
typedef struct _GdkWaylandPollSource GdkWaylandPollSource;
|
|
|
|
|
|
|
|
struct _GdkWaylandEventSource
|
|
|
|
{
|
|
|
|
GSource source;
|
|
|
|
GdkWaylandDisplay *display;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _GdkWaylandPollSource
|
|
|
|
{
|
2010-12-18 20:38:49 +00:00
|
|
|
GSource source;
|
|
|
|
GPollFD pfd;
|
2024-10-24 03:02:55 +00:00
|
|
|
GdkWaylandDisplay *display;
|
|
|
|
guint reading : 1;
|
|
|
|
guint can_dispatch : 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* If we should try wl_display_dispatch_pending() before
|
|
|
|
* polling the Wayland fd
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
gdk_wayland_display_can_dispatch (GdkWaylandDisplay *display_wayland)
|
|
|
|
{
|
|
|
|
GdkWaylandPollSource *poll_source = (GdkWaylandPollSource *) display_wayland->poll_source;
|
|
|
|
|
|
|
|
return poll_source->can_dispatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we still have events to process and don't need to poll */
|
|
|
|
static gboolean
|
|
|
|
gdk_wayland_display_has_events_pending (GdkWaylandDisplay *display_wayland)
|
|
|
|
{
|
|
|
|
return gdk_wayland_display_can_dispatch (display_wayland) ||
|
|
|
|
_gdk_event_queue_find_first (GDK_DISPLAY (display_wayland)) != NULL;
|
|
|
|
}
|
2010-12-18 20:38:49 +00:00
|
|
|
|
|
|
|
static gboolean
|
2024-10-24 01:03:58 +00:00
|
|
|
gdk_wayland_event_source_prepare (GSource *base,
|
|
|
|
int *timeout)
|
2010-12-18 20:38:49 +00:00
|
|
|
{
|
|
|
|
GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
|
|
|
|
|
|
|
|
*timeout = -1;
|
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
return gdk_wayland_display_has_events_pending (source->display);
|
|
|
|
}
|
2013-02-20 13:53:59 +00:00
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_wayland_event_source_check (GSource *base)
|
|
|
|
{
|
|
|
|
GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
|
2010-12-18 20:38:49 +00:00
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
return gdk_wayland_display_has_events_pending (source->display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_wayland_event_source_dispatch (GSource *base,
|
|
|
|
GSourceFunc callback,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
|
|
|
|
GdkEvent *event;
|
|
|
|
|
|
|
|
event = gdk_display_get_event (GDK_DISPLAY (source->display));
|
|
|
|
|
|
|
|
if (event)
|
|
|
|
{
|
|
|
|
_gdk_event_emit (event);
|
|
|
|
|
|
|
|
gdk_event_unref (event);
|
|
|
|
}
|
|
|
|
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gdk_wayland_event_source_finalize (GSource *base)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static GSourceFuncs gdk_wayland_event_source_funcs = {
|
|
|
|
gdk_wayland_event_source_prepare,
|
|
|
|
gdk_wayland_event_source_check,
|
|
|
|
gdk_wayland_event_source_dispatch,
|
|
|
|
gdk_wayland_event_source_finalize
|
|
|
|
};
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gdk_wayland_poll_source_prepare (GSource *base,
|
|
|
|
int *timeout)
|
|
|
|
{
|
|
|
|
GdkWaylandPollSource *source = (GdkWaylandPollSource *) base;
|
|
|
|
GdkWaylandDisplay *display = (GdkWaylandDisplay *) source->display;
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
*timeout = -1;
|
|
|
|
|
|
|
|
if (gdk_wayland_display_has_events_pending (source->display))
|
|
|
|
return FALSE;
|
2010-12-18 20:38:49 +00:00
|
|
|
|
2024-10-24 03:08:07 +00:00
|
|
|
/* wl_display_prepare_read() needs to be balanced with either
|
|
|
|
* wl_display_read_events() or wl_display_cancel_read()
|
2024-10-24 01:03:58 +00:00
|
|
|
* (in gdk_wayland_event_source_check() */
|
2024-10-24 03:08:07 +00:00
|
|
|
if (source->reading)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-03-18 06:17:23 +00:00
|
|
|
/* if prepare_read() returns non-zero, there are events to be dispatched */
|
|
|
|
if (wl_display_prepare_read (display->wl_display) != 0)
|
2024-10-24 03:02:55 +00:00
|
|
|
{
|
|
|
|
source->can_dispatch = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2020-01-07 16:13:22 +00:00
|
|
|
|
|
|
|
/* We need to check whether there are pending events on the surface queues as well,
|
|
|
|
* but we also need to make sure to only have one active "read" in the end,
|
|
|
|
* or none if we immediately return TRUE, as multiple reads expect reads from
|
|
|
|
* as many threads.
|
|
|
|
*/
|
|
|
|
for (l = display->event_queues; l; l = l->next)
|
|
|
|
{
|
|
|
|
struct wl_event_queue *queue = l->data;
|
|
|
|
|
|
|
|
if (wl_display_prepare_read_queue (display->wl_display, queue) != 0)
|
2024-10-24 03:08:07 +00:00
|
|
|
{
|
2024-10-24 03:02:55 +00:00
|
|
|
source->can_dispatch = TRUE;
|
|
|
|
/* cancel the read from before the for loop */
|
2024-10-24 03:08:07 +00:00
|
|
|
wl_display_cancel_read (display->wl_display);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2020-01-07 16:13:22 +00:00
|
|
|
wl_display_cancel_read (display->wl_display);
|
|
|
|
}
|
|
|
|
|
2024-10-24 03:08:07 +00:00
|
|
|
source->reading = TRUE;
|
|
|
|
|
2013-07-09 17:08:21 +00:00
|
|
|
if (wl_display_flush (display->wl_display) < 0)
|
2017-05-24 14:08:07 +00:00
|
|
|
{
|
|
|
|
g_message ("Error flushing display: %s", g_strerror (errno));
|
|
|
|
_exit (1);
|
|
|
|
}
|
2013-08-04 13:36:01 +00:00
|
|
|
|
2010-12-18 20:38:49 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-10-24 03:02:55 +00:00
|
|
|
gdk_wayland_poll_source_check (GSource *base)
|
2010-12-18 20:38:49 +00:00
|
|
|
{
|
2024-10-24 03:02:55 +00:00
|
|
|
GdkWaylandPollSource *source = (GdkWaylandPollSource *) base;
|
2016-03-18 06:17:23 +00:00
|
|
|
GdkWaylandDisplay *display_wayland = (GdkWaylandDisplay *) source->display;
|
2010-12-18 20:38:49 +00:00
|
|
|
|
2016-03-18 06:17:23 +00:00
|
|
|
/* read the events from the wayland fd into their respective queues if we have data */
|
2024-10-24 03:08:07 +00:00
|
|
|
if (source->reading)
|
2016-03-18 06:17:23 +00:00
|
|
|
{
|
2024-10-24 03:02:55 +00:00
|
|
|
if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))
|
|
|
|
{
|
|
|
|
g_message ("Lost connection to Wayland compositor.");
|
|
|
|
_exit (1);
|
|
|
|
}
|
2024-10-24 03:08:07 +00:00
|
|
|
if (source->pfd.revents & G_IO_IN)
|
2016-03-18 06:17:23 +00:00
|
|
|
{
|
2024-10-24 03:08:07 +00:00
|
|
|
if (wl_display_read_events (display_wayland->wl_display) < 0)
|
|
|
|
{
|
|
|
|
g_message ("Error reading events from display: %s", g_strerror (errno));
|
|
|
|
_exit (1);
|
|
|
|
}
|
2024-10-24 03:02:55 +00:00
|
|
|
source->pfd.revents = 0;
|
|
|
|
source->can_dispatch = TRUE;
|
2016-03-18 06:17:23 +00:00
|
|
|
}
|
2024-10-24 03:08:07 +00:00
|
|
|
else
|
|
|
|
wl_display_cancel_read (display_wayland->wl_display);
|
|
|
|
source->reading = FALSE;
|
2016-03-18 06:17:23 +00:00
|
|
|
}
|
2013-02-20 13:53:59 +00:00
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
return FALSE;
|
2010-12-18 20:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-10-24 03:02:55 +00:00
|
|
|
gdk_wayland_poll_source_dispatch (GSource *base,
|
|
|
|
GSourceFunc callback,
|
|
|
|
gpointer data)
|
2010-12-18 20:38:49 +00:00
|
|
|
{
|
2024-10-24 03:02:55 +00:00
|
|
|
return G_SOURCE_CONTINUE;
|
2010-12-18 20:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-10-24 03:02:55 +00:00
|
|
|
gdk_wayland_poll_source_finalize (GSource *base)
|
2010-12-18 20:38:49 +00:00
|
|
|
{
|
2024-10-24 03:02:55 +00:00
|
|
|
GdkWaylandPollSource *source = (GdkWaylandPollSource *) base;
|
2024-10-24 03:08:07 +00:00
|
|
|
|
|
|
|
if (source->reading)
|
2024-10-24 03:02:55 +00:00
|
|
|
wl_display_cancel_read (source->display->wl_display);
|
2024-10-24 03:08:07 +00:00
|
|
|
source->reading = FALSE;
|
2010-12-18 20:38:49 +00:00
|
|
|
}
|
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
static GSourceFuncs gdk_wayland_poll_source_funcs = {
|
|
|
|
gdk_wayland_poll_source_prepare,
|
|
|
|
gdk_wayland_poll_source_check,
|
|
|
|
gdk_wayland_poll_source_dispatch,
|
|
|
|
gdk_wayland_poll_source_finalize
|
2010-12-18 20:38:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2015-02-28 03:28:28 +00:00
|
|
|
_gdk_wayland_display_deliver_event (GdkDisplay *display,
|
|
|
|
GdkEvent *event)
|
2010-12-18 20:38:49 +00:00
|
|
|
{
|
|
|
|
GList *node;
|
|
|
|
|
|
|
|
node = _gdk_event_queue_append (display, event);
|
2012-01-06 16:48:13 +00:00
|
|
|
_gdk_windowing_got_event (display, node, event,
|
|
|
|
_gdk_display_get_next_serial (display));
|
2010-12-18 20:38:49 +00:00
|
|
|
}
|
|
|
|
|
2024-10-24 01:18:49 +00:00
|
|
|
void
|
2024-10-24 03:02:55 +00:00
|
|
|
gdk_wayland_display_install_gsources (GdkWaylandDisplay *display_wayland)
|
2010-12-18 20:38:49 +00:00
|
|
|
{
|
2024-10-24 01:18:49 +00:00
|
|
|
GdkDisplay *display = GDK_DISPLAY (display_wayland);
|
2010-12-18 20:38:49 +00:00
|
|
|
GSource *source;
|
2024-10-24 01:03:58 +00:00
|
|
|
GdkWaylandEventSource *event_source;
|
2024-10-24 03:02:55 +00:00
|
|
|
GdkWaylandPollSource *poll_source;
|
2010-12-18 20:38:49 +00:00
|
|
|
char *name;
|
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
/* SOURCE 1 */
|
2024-10-24 01:03:58 +00:00
|
|
|
source = g_source_new (&gdk_wayland_event_source_funcs,
|
2010-12-18 20:38:49 +00:00
|
|
|
sizeof (GdkWaylandEventSource));
|
2024-10-24 01:18:49 +00:00
|
|
|
display_wayland->event_source = source;
|
|
|
|
event_source = (GdkWaylandEventSource *) source;
|
2016-05-01 14:52:31 +00:00
|
|
|
name = g_strdup_printf ("GDK Wayland Event source (%s)",
|
|
|
|
gdk_display_get_name (display));
|
2010-12-18 20:38:49 +00:00
|
|
|
g_source_set_name (source, name);
|
|
|
|
g_free (name);
|
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
event_source->display = display_wayland;
|
2010-12-18 20:38:49 +00:00
|
|
|
|
|
|
|
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
|
|
|
|
g_source_set_can_recurse (source, TRUE);
|
|
|
|
g_source_attach (source, NULL);
|
2024-10-24 03:02:55 +00:00
|
|
|
|
|
|
|
/* SOURCE 2 */
|
|
|
|
source = g_source_new (&gdk_wayland_poll_source_funcs,
|
|
|
|
sizeof (GdkWaylandPollSource));
|
|
|
|
display_wayland->poll_source = source;
|
|
|
|
poll_source = (GdkWaylandPollSource *) source;
|
|
|
|
name = g_strdup_printf ("GDK Wayland Poll source (%s)",
|
|
|
|
gdk_display_get_name (display));
|
|
|
|
g_source_set_name (source, name);
|
|
|
|
g_free (name);
|
|
|
|
|
|
|
|
poll_source->display = display_wayland;
|
|
|
|
poll_source->pfd.fd = wl_display_get_fd (display_wayland->wl_display);
|
|
|
|
poll_source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
|
|
|
|
g_source_add_poll (source, &poll_source->pfd);
|
|
|
|
|
|
|
|
/* We must guarantee to ALWAYS be called and called FIRST after
|
|
|
|
* every poll - or rather: after every prepare().
|
|
|
|
* Any other source might call Wayland functions and in turn
|
|
|
|
* block while waiting for us.
|
|
|
|
* And GSource has no after_pool() vfunc, check() is not guaranteed
|
|
|
|
* to be called.
|
|
|
|
*/
|
|
|
|
g_source_set_priority (source, G_MININT);
|
|
|
|
g_source_attach (source, NULL);
|
2024-10-24 01:18:49 +00:00
|
|
|
}
|
2010-12-18 20:38:49 +00:00
|
|
|
|
2024-10-24 01:18:49 +00:00
|
|
|
void
|
2024-10-24 03:02:55 +00:00
|
|
|
gdk_wayland_display_uninstall_gsources (GdkWaylandDisplay *display_wayland)
|
2024-10-24 01:18:49 +00:00
|
|
|
{
|
|
|
|
if (display_wayland->event_source)
|
|
|
|
{
|
|
|
|
g_source_destroy (display_wayland->event_source);
|
|
|
|
g_source_unref (display_wayland->event_source);
|
|
|
|
display_wayland->event_source = NULL;
|
|
|
|
}
|
2024-10-24 03:02:55 +00:00
|
|
|
if (display_wayland->poll_source)
|
|
|
|
{
|
|
|
|
g_source_destroy (display_wayland->poll_source);
|
|
|
|
g_source_unref (display_wayland->poll_source);
|
|
|
|
display_wayland->poll_source = NULL;
|
|
|
|
}
|
2010-12-18 20:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_gdk_wayland_display_queue_events (GdkDisplay *display)
|
|
|
|
{
|
2024-10-24 03:02:55 +00:00
|
|
|
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
|
|
|
GdkWaylandPollSource *poll_source;
|
2020-01-07 16:13:22 +00:00
|
|
|
GList *l;
|
2010-12-18 20:38:49 +00:00
|
|
|
|
2016-03-18 06:17:23 +00:00
|
|
|
if (wl_display_dispatch_pending (display_wayland->wl_display) < 0)
|
2013-07-09 17:08:21 +00:00
|
|
|
{
|
2017-05-24 14:42:01 +00:00
|
|
|
g_message ("Error %d (%s) dispatching to Wayland display.",
|
2016-03-18 06:17:23 +00:00
|
|
|
errno, g_strerror (errno));
|
2017-05-24 14:42:01 +00:00
|
|
|
_exit (1);
|
2013-07-09 17:08:21 +00:00
|
|
|
}
|
2013-03-30 18:17:07 +00:00
|
|
|
|
2020-01-07 16:13:22 +00:00
|
|
|
for (l = display_wayland->event_queues; l; l = l->next)
|
|
|
|
{
|
|
|
|
struct wl_event_queue *queue = l->data;
|
|
|
|
|
|
|
|
if (wl_display_dispatch_queue_pending (display_wayland->wl_display, queue) < 0)
|
|
|
|
{
|
|
|
|
g_message ("Error %d (%s) dispatching to Wayland display.",
|
|
|
|
errno, g_strerror (errno));
|
|
|
|
_exit (1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-24 03:02:55 +00:00
|
|
|
poll_source = (GdkWaylandPollSource *) display_wayland->poll_source;
|
|
|
|
poll_source->can_dispatch = FALSE;
|
2010-12-18 20:38:49 +00:00
|
|
|
}
|