mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-13 15:27:21 +00:00
[common/client] platform: abstract runtime services
This commit is contained in:
@@ -21,11 +21,14 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "wayland.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <wayland-client.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/option.h"
|
||||
@@ -106,12 +109,53 @@ static bool getCompositor(char * dst, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool eventSourceWake(void * opaque)
|
||||
{
|
||||
const int fd = *(const int *)opaque;
|
||||
int result;
|
||||
do
|
||||
result = eventfd_write(fd, 1);
|
||||
while (result < 0 && errno == EINTR);
|
||||
if (result == 0 || errno == EAGAIN)
|
||||
return true;
|
||||
|
||||
DEBUG_WARN("Failed to signal the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
static void eventSourceCallback(uint32_t events, void * opaque)
|
||||
{
|
||||
(void)events;
|
||||
(void)opaque;
|
||||
|
||||
const LG_DSEventSource * source = (const LG_DSEventSource *)opaque;
|
||||
source->callback(source->opaque);
|
||||
eventfd_t value;
|
||||
for (;;)
|
||||
{
|
||||
if (eventfd_read(wlWm.eventSourceFd, &value) == 0 || errno == EINTR)
|
||||
continue;
|
||||
if (errno != EAGAIN)
|
||||
DEBUG_WARN("Failed to drain the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
wlWm.eventSource.dispatch(wlWm.eventSource.opaque);
|
||||
}
|
||||
|
||||
static void eventSourceFree(void)
|
||||
{
|
||||
if (wlWm.eventSourceSubscribed)
|
||||
{
|
||||
wlWm.eventSource.unsubscribe(wlWm.eventSource.opaque);
|
||||
wlWm.eventSourceSubscribed = false;
|
||||
}
|
||||
|
||||
if (wlWm.eventSourceFd >= 0)
|
||||
{
|
||||
waylandPollUnregister(wlWm.eventSourceFd);
|
||||
close(wlWm.eventSourceFd);
|
||||
wlWm.eventSourceFd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool waylandInit(const LG_DSInitParams params)
|
||||
@@ -130,6 +174,7 @@ static bool waylandInit(const LG_DSInitParams params)
|
||||
atomic_init(&wlWm.hdrScRGBWhiteLevel, 80);
|
||||
atomic_init(&wlWm.pendingResize, 0);
|
||||
wlWm.resizeEventFd = -1;
|
||||
wlWm.eventSourceFd = -1;
|
||||
wlWm.eventSource = params.eventSource;
|
||||
|
||||
wlWm.display = wl_display_connect(NULL);
|
||||
@@ -162,42 +207,90 @@ static bool waylandInit(const LG_DSInitParams params)
|
||||
if (!waylandPollInit())
|
||||
return false;
|
||||
|
||||
if (wlWm.eventSource.fd >= 0 && wlWm.eventSource.callback &&
|
||||
!waylandPollRegister(wlWm.eventSource.fd, eventSourceCallback,
|
||||
&wlWm.eventSource, EPOLLIN))
|
||||
if (lgEventSourceValid(&wlWm.eventSource))
|
||||
{
|
||||
DEBUG_ERROR("Failed to register the external event source");
|
||||
return false;
|
||||
wlWm.eventSourceFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
if (wlWm.eventSourceFd < 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandPollRegister(wlWm.eventSourceFd, eventSourceCallback,
|
||||
NULL, EPOLLIN))
|
||||
{
|
||||
DEBUG_ERROR("Failed to register the display event wake fd");
|
||||
close(wlWm.eventSourceFd);
|
||||
wlWm.eventSourceFd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wlWm.eventSource.subscribe(wlWm.eventSource.opaque,
|
||||
eventSourceWake, &wlWm.eventSourceFd))
|
||||
{
|
||||
DEBUG_ERROR("Failed to subscribe to the display event source");
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
wlWm.eventSourceSubscribed = true;
|
||||
}
|
||||
|
||||
if (!waylandOutputInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandRegistryInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandColorMgmtInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandActivationInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandIdleInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandPresentationInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandCursorInit())
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!waylandInputInit(params.allowNoInput))
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
wlWm.desktop->setSize(params.w, params.h);
|
||||
if (!waylandWindowInit(params.title, params.appId, params.fullscreen, params.maximize,
|
||||
params.borderless, params.resizable))
|
||||
{
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
wlWm.desktop->getSize(&width, &height);
|
||||
@@ -206,6 +299,7 @@ static bool waylandInit(const LG_DSInitParams params)
|
||||
waylandScaleMulInt(wlWm.scale, height)))
|
||||
{
|
||||
waylandWindowFree();
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -218,6 +312,7 @@ static bool waylandInit(const LG_DSInitParams params)
|
||||
if (params.opengl && !waylandOpenGLInit())
|
||||
{
|
||||
waylandWindowFree();
|
||||
eventSourceFree();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -235,6 +330,7 @@ static void waylandShutdown(void)
|
||||
|
||||
static void waylandFree(void)
|
||||
{
|
||||
eventSourceFree();
|
||||
waylandCBFree();
|
||||
waylandIdleFree();
|
||||
waylandPresentationFree();
|
||||
|
||||
@@ -283,6 +283,8 @@ struct WaylandDSState
|
||||
unsigned int pollWaiters;
|
||||
int epollFd;
|
||||
int displayFd;
|
||||
int eventSourceFd;
|
||||
bool eventSourceSubscribed;
|
||||
LG_DSEventSource eventSource;
|
||||
};
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ enum WindowsMessage
|
||||
WM_LG_ACTIVATE,
|
||||
WM_LG_INHIBIT_IDLE,
|
||||
WM_LG_SET_HANDLER,
|
||||
WM_LG_EVENT_SOURCE,
|
||||
};
|
||||
|
||||
struct WindowsPointMessage
|
||||
@@ -104,6 +105,8 @@ struct WindowsDSState
|
||||
|
||||
WindowsInput input;
|
||||
|
||||
LG_DSEventSource eventSource;
|
||||
bool eventSourceSubscribed;
|
||||
WindowsMessageHandler messageHandler;
|
||||
void * messageOpaque;
|
||||
|
||||
@@ -820,12 +823,33 @@ static void setCursorShape(LG_DSPointer pointer)
|
||||
SetCursor(windows.cursors[pointer]);
|
||||
}
|
||||
|
||||
static bool eventSourceWake(void * opaque)
|
||||
{
|
||||
const HWND window = (HWND)opaque;
|
||||
if (PostMessageW(window, WM_LG_EVENT_SOURCE, 0, 0))
|
||||
return true;
|
||||
|
||||
DEBUG_WINERROR("Failed to signal the display event source",
|
||||
GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
static void eventSourceFree(void)
|
||||
{
|
||||
if (!windows.eventSourceSubscribed)
|
||||
return;
|
||||
|
||||
windows.eventSource.unsubscribe(windows.eventSource.opaque);
|
||||
windows.eventSourceSubscribed = false;
|
||||
}
|
||||
|
||||
static LRESULT handleCustomMessage(UINT message, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_LG_SHUTDOWN:
|
||||
eventSourceFree();
|
||||
setKeyboardGrab(false);
|
||||
setPointerGrab(false, false);
|
||||
if (windows.idleInhibited)
|
||||
@@ -894,6 +918,10 @@ static LRESULT handleCustomMessage(UINT message, WPARAM wParam,
|
||||
windows.messageOpaque = handler->opaque;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_LG_EVENT_SOURCE:
|
||||
windows.eventSource.dispatch(windows.eventSource.opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -902,7 +930,7 @@ static LRESULT handleCustomMessage(UINT message, WPARAM wParam,
|
||||
static LRESULT CALLBACK windowProc(HWND window, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message >= WM_LG_SHUTDOWN && message <= WM_LG_SET_HANDLER)
|
||||
if (message >= WM_LG_SHUTDOWN && message <= WM_LG_EVENT_SOURCE)
|
||||
return handleCustomMessage(message, wParam, lParam);
|
||||
|
||||
if (windows.dispatchReady && windows.messageHandler)
|
||||
@@ -1309,6 +1337,19 @@ static int eventThread(void * opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lgEventSourceValid(&windows.eventSource) &&
|
||||
!windows.eventSource.subscribe(windows.eventSource.opaque,
|
||||
eventSourceWake, windows.window))
|
||||
{
|
||||
DEBUG_ERROR("Failed to subscribe to the display event source");
|
||||
DestroyWindow(windows.window);
|
||||
windows.window = NULL;
|
||||
UnregisterClassW(LG_WINDOW_CLASS, windows.instance);
|
||||
lgSignalEvent(windows.initEvent);
|
||||
return 0;
|
||||
}
|
||||
windows.eventSourceSubscribed = lgEventSourceValid(&windows.eventSource);
|
||||
|
||||
windows.dispatchReady = true;
|
||||
windows.initOK = true;
|
||||
updateWindowGeometry();
|
||||
@@ -1325,6 +1366,7 @@ static int eventThread(void * opaque)
|
||||
DispatchMessageW(&message);
|
||||
}
|
||||
|
||||
eventSourceFree();
|
||||
windows.dispatchReady = false;
|
||||
windows.window = NULL;
|
||||
removeKeyboardHook();
|
||||
@@ -1446,6 +1488,7 @@ static bool windowsInit(const LG_DSInitParams params)
|
||||
windowsInputInit(&windows.input, &inputSink, NULL);
|
||||
|
||||
windows.instance = GetModuleHandleW(NULL);
|
||||
windows.eventSource = params.eventSource;
|
||||
windows.title = lgUtf8ToWide(params.title);
|
||||
windows.x = params.x;
|
||||
windows.y = params.y;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/extensions/XInput2.h>
|
||||
@@ -1063,12 +1064,27 @@ static bool x11GetProp(LG_DSProperty prop, void *ret)
|
||||
}
|
||||
}
|
||||
|
||||
static bool x11EventSourceWake(void * opaque)
|
||||
{
|
||||
const int fd = *(const int *)opaque;
|
||||
int result;
|
||||
do
|
||||
result = eventfd_write(fd, 1);
|
||||
while (result < 0 && errno == EINTR);
|
||||
if (result == 0 || errno == EAGAIN)
|
||||
return true;
|
||||
|
||||
DEBUG_WARN("Failed to signal the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
static int x11EventThread(void * unused)
|
||||
{
|
||||
enum
|
||||
{
|
||||
EPOLL_SOURCE_X11,
|
||||
EPOLL_SOURCE_EXTERNAL,
|
||||
EPOLL_SOURCE_EVENT,
|
||||
};
|
||||
|
||||
int epollfd = epoll_create1(0);
|
||||
@@ -1091,16 +1107,36 @@ static int x11EventThread(void * unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eventFd = -1;
|
||||
bool eventSubscribed = false;
|
||||
bool pollEventSource = false;
|
||||
if (x11.eventSource.fd >= 0 && x11.eventSource.callback)
|
||||
if (lgEventSourceValid(&x11.eventSource))
|
||||
{
|
||||
ev.data.u32 = EPOLL_SOURCE_EXTERNAL;
|
||||
if (epoll_ctl(epollfd, EPOLL_CTL_ADD,
|
||||
x11.eventSource.fd, &ev) == -1)
|
||||
eventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
if (eventFd < 0)
|
||||
{
|
||||
DEBUG_WARN("Failed to register the external event source; polling");
|
||||
DEBUG_WARN("Failed to create the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
pollEventSource = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ev.data.u32 = EPOLL_SOURCE_EVENT;
|
||||
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, eventFd, &ev) == -1)
|
||||
{
|
||||
DEBUG_WARN("Failed to register the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
pollEventSource = true;
|
||||
}
|
||||
else if (!x11.eventSource.subscribe(x11.eventSource.opaque,
|
||||
x11EventSourceWake, &eventFd))
|
||||
{
|
||||
DEBUG_WARN("Failed to subscribe to the display event source");
|
||||
pollEventSource = true;
|
||||
}
|
||||
else
|
||||
eventSubscribed = true;
|
||||
}
|
||||
}
|
||||
|
||||
while(app_isRunning())
|
||||
@@ -1121,17 +1157,28 @@ static int x11EventThread(void * unused)
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
close(epollfd);
|
||||
DEBUG_ERROR("epoll_wait failure");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nfds; ++i)
|
||||
if (events[i].data.u32 == EPOLL_SOURCE_EXTERNAL)
|
||||
x11.eventSource.callback(x11.eventSource.opaque);
|
||||
if (events[i].data.u32 == EPOLL_SOURCE_EVENT)
|
||||
{
|
||||
eventfd_t value;
|
||||
for (;;)
|
||||
{
|
||||
if (eventfd_read(eventFd, &value) == 0 || errno == EINTR)
|
||||
continue;
|
||||
if (errno != EAGAIN)
|
||||
DEBUG_WARN("Failed to drain the display event wake fd: %s",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
x11.eventSource.dispatch(x11.eventSource.opaque);
|
||||
}
|
||||
|
||||
if (pollEventSource)
|
||||
x11.eventSource.callback(x11.eventSource.opaque);
|
||||
x11.eventSource.dispatch(x11.eventSource.opaque);
|
||||
|
||||
if (!XPending(x11.display))
|
||||
{
|
||||
@@ -1310,6 +1357,10 @@ static int x11EventThread(void * unused)
|
||||
}
|
||||
}
|
||||
|
||||
if (eventSubscribed)
|
||||
x11.eventSource.unsubscribe(x11.eventSource.opaque);
|
||||
if (eventFd >= 0)
|
||||
close(eventFd);
|
||||
close(epollfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user