[client] wayland: dispatch events through libdecor when using it

Currently, we dispatch the events on the wayland display server ourselves.
This is fine when using the cairo backend of libdecor, as it does the same
thign we do, but other backends may require other things to be dispatched.

This commit lets libdecor dispatch events instead through libdecor_get_fd
and libdecor_dispatch, which should hopefully makes things less sketchy.
This commit is contained in:
Quantum 2021-07-21 18:48:10 -04:00 committed by Geoffrey McRae
parent ed18ead1ff
commit bb60107a3b
3 changed files with 34 additions and 2 deletions

View File

@ -18,7 +18,7 @@ if (ENABLE_LIBDECOR)
list(APPEND DISPLAYSERVER_Wayland_PKGCONFIG_LIBRARIES ${DISPLAYSERVER_Wayland_LIBDECOR_LIBRARIES})
list(APPEND DISPLAYSERVER_Wayland_PKGCONFIG_INCLUDE_DIRS ${DISPLAYSERVER_Wayland_LIBDECOR_INCLUDE_DIRS})
list(APPEND displayserver_Wayland_SHELL_SRC shell_libdecor.c)
add_definitions(-D ENABLE_LIBDECOR)
add_compile_definitions(ENABLE_LIBDECOR)
else()
list(APPEND displayserver_Wayland_SHELL_SRC shell_xdg.c)
endif()

View File

@ -30,8 +30,13 @@
#include "common/debug.h"
#include "common/locking.h"
#ifdef ENABLE_LIBDECOR
#include <libdecor.h>
#endif
#define EPOLL_EVENTS 10 // Maximum number of fds we can process at once in waylandWait
#ifndef ENABLE_LIBDECOR
static void waylandDisplayCallback(uint32_t events, void * opaque)
{
if (events & EPOLLERR)
@ -40,6 +45,7 @@ static void waylandDisplayCallback(uint32_t events, void * opaque)
wl_display_read_events(wlWm.display);
wl_display_dispatch_pending(wlWm.display);
}
#endif
bool waylandPollInit(void)
{
@ -55,21 +61,27 @@ bool waylandPollInit(void)
LG_LOCK_INIT(wlWm.pollLock);
LG_LOCK_INIT(wlWm.pollFreeLock);
#ifndef ENABLE_LIBDECOR
wlWm.displayFd = wl_display_get_fd(wlWm.display);
if (!waylandPollRegister(wlWm.displayFd, waylandDisplayCallback, NULL, EPOLLIN))
{
DEBUG_ERROR("Failed register display to epoll: %s", strerror(errno));
return false;
}
#endif
return true;
}
void waylandWait(unsigned int time)
{
#ifdef ENABLE_LIBDECOR
libdecor_dispatch(wlWm.libdecor, 0);
#else
while (wl_display_prepare_read(wlWm.display))
wl_display_dispatch_pending(wlWm.display);
wl_display_flush(wlWm.display);
#endif
struct epoll_event events[EPOLL_EVENTS];
int count;
@ -77,21 +89,29 @@ void waylandWait(unsigned int time)
{
if (errno != EINTR)
DEBUG_INFO("epoll failed: %s", strerror(errno));
#ifndef ENABLE_LIBDECOR
wl_display_cancel_read(wlWm.display);
#endif
return;
}
#ifndef ENABLE_LIBDECOR
bool sawDisplay = false;
#endif
for (int i = 0; i < count; ++i) {
struct WaylandPoll * poll = events[i].data.ptr;
if (!poll->removed)
poll->callback(events[i].events, poll->opaque);
#ifndef ENABLE_LIBDECOR
if (poll->fd == wlWm.displayFd)
sawDisplay = true;
#endif
}
#ifndef ENABLE_LIBDECOR
if (!sawDisplay)
wl_display_cancel_read(wlWm.display);
#endif
INTERLOCKED_SECTION(wlWm.pollFreeLock,
{

View File

@ -20,8 +20,10 @@
#include "wayland.h"
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <sys/epoll.h>
#include <libdecor.h>
#include <wayland-client.h>
@ -94,6 +96,11 @@ static struct libdecor_frame_interface libdecorFrameListener = {
};
#pragma GCC diagnostic pop
static void libdecorCallback(uint32_t events, void * opaque)
{
libdecor_dispatch(wlWm.libdecor, 0);
}
bool waylandShellInit(const char * title, bool fullscreen, bool maximize, bool borderless)
{
wlWm.libdecor = libdecor_new(wlWm.display, &libdecorListener);
@ -104,8 +111,13 @@ bool waylandShellInit(const char * title, bool fullscreen, bool maximize, bool b
libdecor_frame_map(wlWm.libdecorFrame);
while (!wlWm.configured)
wl_display_roundtrip(wlWm.display);
libdecor_dispatch(wlWm.libdecor, 0);
if (!waylandPollRegister(libdecor_get_fd(wlWm.libdecor), libdecorCallback, NULL, EPOLLIN))
{
DEBUG_ERROR("Failed register display to epoll: %s", strerror(errno));
return false;
}
return true;
}