2021-06-06 01:26:18 +00:00
|
|
|
/**
|
|
|
|
* Looking Glass
|
2023-10-20 04:36:34 +00:00
|
|
|
* Copyright © 2017-2023 The Looking Glass Authors
|
2021-06-06 01:26:18 +00:00
|
|
|
* https://looking-glass.io
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
|
|
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
2021-01-15 09:30:03 +00:00
|
|
|
|
2021-01-27 04:06:02 +00:00
|
|
|
#define _GNU_SOURCE
|
2021-02-20 06:23:48 +00:00
|
|
|
#include "wayland.h"
|
|
|
|
|
2021-01-16 09:31:58 +00:00
|
|
|
#include <signal.h>
|
2021-02-25 05:01:54 +00:00
|
|
|
#include <string.h>
|
2021-01-15 09:30:03 +00:00
|
|
|
#include <wayland-client.h>
|
2023-11-09 05:30:27 +00:00
|
|
|
#include <sys/socket.h>
|
2021-01-15 09:30:03 +00:00
|
|
|
|
|
|
|
#include "common/debug.h"
|
2021-02-16 01:54:02 +00:00
|
|
|
#include "common/option.h"
|
2021-01-15 09:30:03 +00:00
|
|
|
|
2023-11-09 05:30:27 +00:00
|
|
|
#include "dynamic/wayland_desktops.h"
|
|
|
|
|
2021-02-16 01:54:02 +00:00
|
|
|
static struct Option waylandOptions[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
.module = "wayland",
|
|
|
|
.name = "warpSupport",
|
|
|
|
.description = "Enable cursor warping",
|
|
|
|
.type = OPTION_TYPE_BOOL,
|
|
|
|
.value.x_bool = true,
|
|
|
|
},
|
2021-08-01 02:57:03 +00:00
|
|
|
{
|
|
|
|
.module = "wayland",
|
|
|
|
.name = "fractionScale",
|
|
|
|
.description = "Enable fractional scale",
|
|
|
|
.type = OPTION_TYPE_BOOL,
|
|
|
|
.value.x_bool = true,
|
|
|
|
},
|
2021-02-16 01:54:02 +00:00
|
|
|
{0}
|
|
|
|
};
|
|
|
|
|
2021-01-26 23:59:10 +00:00
|
|
|
static bool waylandEarlyInit(void)
|
|
|
|
{
|
2021-01-16 09:31:58 +00:00
|
|
|
// Request to receive EPIPE instead of SIGPIPE when one end of a pipe
|
|
|
|
// disconnects while a write is pending. This is useful to the Wayland
|
|
|
|
// clipboard backend, where an arbitrary application is on the other end of
|
|
|
|
// that pipe.
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-16 01:54:02 +00:00
|
|
|
static void waylandSetup(void)
|
|
|
|
{
|
|
|
|
option_register(waylandOptions);
|
|
|
|
}
|
|
|
|
|
2021-01-26 10:46:30 +00:00
|
|
|
static bool waylandProbe(void)
|
|
|
|
{
|
|
|
|
return getenv("WAYLAND_DISPLAY") != NULL;
|
|
|
|
}
|
|
|
|
|
2023-11-09 05:30:27 +00:00
|
|
|
static bool getCompositor(char * dst, size_t size)
|
|
|
|
{
|
|
|
|
int fd = wl_display_get_fd(wlWm.display);
|
|
|
|
struct ucred ucred;
|
|
|
|
socklen_t len = sizeof(struct ucred);
|
|
|
|
|
|
|
|
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("Failed to get the pid of the socket");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char path[64];
|
|
|
|
snprintf(path, sizeof(path), "/proc/%d/comm", ucred.pid);
|
|
|
|
FILE *fp = fopen(path, "r");
|
|
|
|
if (!fp)
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("Failed to open %s", path);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fgets(dst, size, fp))
|
|
|
|
{
|
|
|
|
DEBUG_ERROR("Failed to read %s", path);
|
|
|
|
fclose(fp);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
dst[strlen(dst) - 1] = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-01-26 10:46:30 +00:00
|
|
|
static bool waylandInit(const LG_DSInitParams params)
|
2021-01-15 09:30:03 +00:00
|
|
|
{
|
2021-02-20 06:23:48 +00:00
|
|
|
memset(&wlWm, 0, sizeof(wlWm));
|
2023-11-09 05:30:27 +00:00
|
|
|
wlWm.desktop = WL_Desktops[0];
|
2023-02-28 12:38:44 +00:00
|
|
|
|
|
|
|
wlWm.display = wl_display_connect(NULL);
|
|
|
|
if (!wlWm.display)
|
|
|
|
return false;
|
|
|
|
|
2023-11-09 05:30:27 +00:00
|
|
|
// select the desktop interface based on the compositor process name
|
|
|
|
char compositor[1024];
|
|
|
|
if (getCompositor(compositor, sizeof(compositor)))
|
|
|
|
{
|
2023-11-09 05:37:34 +00:00
|
|
|
DEBUG_INFO("Compositor: %s", compositor);
|
2023-11-09 05:30:27 +00:00
|
|
|
for(int i = 0; i < WL_DESKTOP_COUNT; ++i)
|
|
|
|
if (strcmp(WL_Desktops[i]->compositor, compositor) == 0)
|
|
|
|
{
|
|
|
|
wlWm.desktop = WL_Desktops[0];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-11-09 05:37:34 +00:00
|
|
|
else
|
|
|
|
DEBUG_WARN("Compositor: UNKNOWN");
|
|
|
|
DEBUG_INFO("Selected : %s", wlWm.desktop->name);
|
2023-11-09 05:30:27 +00:00
|
|
|
|
2021-02-22 07:19:03 +00:00
|
|
|
wl_list_init(&wlWm.surfaceOutputs);
|
2021-02-16 01:54:02 +00:00
|
|
|
|
2021-08-01 02:57:03 +00:00
|
|
|
wlWm.warpSupport = option_get_bool("wayland", "warpSupport");
|
|
|
|
wlWm.useFractionalScale = option_get_bool("wayland", "fractionScale");
|
2021-02-11 06:52:41 +00:00
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
if (!waylandPollInit())
|
2021-02-11 06:52:41 +00:00
|
|
|
return false;
|
2021-01-15 09:30:03 +00:00
|
|
|
|
2021-02-21 03:48:48 +00:00
|
|
|
if (!waylandOutputInit())
|
|
|
|
return false;
|
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
if (!waylandRegistryInit())
|
2021-01-16 18:01:30 +00:00
|
|
|
return false;
|
2021-01-26 23:59:10 +00:00
|
|
|
|
2022-02-06 21:07:29 +00:00
|
|
|
if (!waylandActivationInit())
|
|
|
|
return false;
|
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
if (!waylandIdleInit())
|
|
|
|
return false;
|
2021-01-26 23:59:10 +00:00
|
|
|
|
2021-05-14 02:51:45 +00:00
|
|
|
if (!waylandPresentationInit())
|
|
|
|
return false;
|
|
|
|
|
2021-12-07 01:35:36 +00:00
|
|
|
if (!waylandCursorInit())
|
|
|
|
return false;
|
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
if (!waylandInputInit())
|
|
|
|
return false;
|
2021-01-27 04:44:57 +00:00
|
|
|
|
2023-11-09 05:30:27 +00:00
|
|
|
wlWm.desktop->setSize(params.w, params.h);
|
|
|
|
if (!waylandWindowInit(params.title, params.fullscreen, params.maximize,
|
|
|
|
params.borderless, params.resizable))
|
2021-02-20 06:23:48 +00:00
|
|
|
return false;
|
2021-01-26 23:59:10 +00:00
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
if (!waylandEGLInit(params.w, params.h))
|
|
|
|
return false;
|
2021-01-27 04:53:02 +00:00
|
|
|
|
2021-01-27 20:13:35 +00:00
|
|
|
#ifdef ENABLE_OPENGL
|
2021-02-20 06:23:48 +00:00
|
|
|
if (params.opengl && !waylandOpenGLInit())
|
|
|
|
return false;
|
2021-01-27 20:13:35 +00:00
|
|
|
#endif
|
2021-01-27 20:03:55 +00:00
|
|
|
|
2021-01-16 18:01:30 +00:00
|
|
|
return true;
|
2021-01-15 09:30:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void waylandStartup(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-01-26 23:59:10 +00:00
|
|
|
static void waylandShutdown(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
static void waylandFree(void)
|
2021-01-27 20:13:35 +00:00
|
|
|
{
|
2021-02-20 06:23:48 +00:00
|
|
|
waylandIdleFree();
|
|
|
|
waylandWindowFree();
|
2021-09-11 01:17:51 +00:00
|
|
|
waylandPresentationFree();
|
2021-02-20 06:23:48 +00:00
|
|
|
waylandInputFree();
|
2021-02-21 03:48:48 +00:00
|
|
|
waylandOutputFree();
|
2021-02-20 06:23:48 +00:00
|
|
|
waylandRegistryFree();
|
2021-04-06 00:06:49 +00:00
|
|
|
waylandCursorFree();
|
2021-02-20 06:23:48 +00:00
|
|
|
wl_display_disconnect(wlWm.display);
|
2021-01-27 20:13:35 +00:00
|
|
|
}
|
|
|
|
|
2021-02-20 06:23:48 +00:00
|
|
|
static bool waylandGetProp(LG_DSProperty prop, void * ret)
|
2021-01-16 10:19:20 +00:00
|
|
|
{
|
|
|
|
if (prop == LG_DS_WARP_SUPPORT)
|
|
|
|
{
|
2021-02-20 06:23:48 +00:00
|
|
|
*(enum LG_DSWarpSupport*)ret = wlWm.warpSupport ? LG_DS_WARP_SURFACE : LG_DS_WARP_NONE;
|
2021-01-16 10:19:20 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-11-09 05:30:27 +00:00
|
|
|
void waylandNeedsResize(void)
|
|
|
|
{
|
|
|
|
wlWm.needsResize = true;
|
|
|
|
app_invalidateWindow(true);
|
|
|
|
waylandStopWaitFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void waylandSetFullscreen(bool fs)
|
|
|
|
{
|
|
|
|
wlWm.desktop->setFullscreen(fs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool waylandGetFullscreen(void)
|
|
|
|
{
|
|
|
|
return wlWm.desktop->getFullscreen();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void waylandMinimize(void)
|
|
|
|
{
|
|
|
|
wlWm.desktop->minimize();
|
|
|
|
}
|
|
|
|
|
2021-01-15 09:30:03 +00:00
|
|
|
struct LG_DisplayServerOps LGDS_Wayland =
|
|
|
|
{
|
2022-07-10 04:00:58 +00:00
|
|
|
.name = "Wayland",
|
2021-05-03 20:35:36 +00:00
|
|
|
.setup = waylandSetup,
|
|
|
|
.probe = waylandProbe,
|
|
|
|
.earlyInit = waylandEarlyInit,
|
|
|
|
.init = waylandInit,
|
|
|
|
.startup = waylandStartup,
|
|
|
|
.shutdown = waylandShutdown,
|
|
|
|
.free = waylandFree,
|
|
|
|
.getProp = waylandGetProp,
|
2021-01-26 23:59:10 +00:00
|
|
|
|
|
|
|
#ifdef ENABLE_EGL
|
2021-05-03 20:35:36 +00:00
|
|
|
.getEGLDisplay = waylandGetEGLDisplay,
|
|
|
|
.getEGLNativeWindow = waylandGetEGLNativeWindow,
|
|
|
|
.eglSwapBuffers = waylandEGLSwapBuffers,
|
2021-01-26 23:59:10 +00:00
|
|
|
#endif
|
|
|
|
|
2021-01-27 20:13:35 +00:00
|
|
|
#ifdef ENABLE_OPENGL
|
2021-05-03 20:35:36 +00:00
|
|
|
.glCreateContext = waylandGLCreateContext,
|
|
|
|
.glDeleteContext = waylandGLDeleteContext,
|
|
|
|
.glMakeCurrent = waylandGLMakeCurrent,
|
|
|
|
.glSetSwapInterval = waylandGLSetSwapInterval,
|
|
|
|
.glSwapBuffers = waylandGLSwapBuffers,
|
2021-01-27 20:13:35 +00:00
|
|
|
#endif
|
2021-08-01 07:06:03 +00:00
|
|
|
.waitFrame = waylandWaitFrame,
|
2021-08-01 08:06:35 +00:00
|
|
|
.skipFrame = waylandSkipFrame,
|
2021-08-01 09:46:07 +00:00
|
|
|
.stopWaitFrame = waylandStopWaitFrame,
|
2021-05-03 20:35:36 +00:00
|
|
|
.guestPointerUpdated = waylandGuestPointerUpdated,
|
2021-07-29 20:31:07 +00:00
|
|
|
.setPointer = waylandSetPointer,
|
2021-05-03 20:35:36 +00:00
|
|
|
.grabPointer = waylandGrabPointer,
|
|
|
|
.ungrabPointer = waylandUngrabPointer,
|
2021-05-04 00:16:51 +00:00
|
|
|
.capturePointer = waylandCapturePointer,
|
|
|
|
.uncapturePointer = waylandUncapturePointer,
|
2021-05-03 20:35:36 +00:00
|
|
|
.grabKeyboard = waylandGrabKeyboard,
|
|
|
|
.ungrabKeyboard = waylandUngrabKeyboard,
|
|
|
|
.warpPointer = waylandWarpPointer,
|
|
|
|
.realignPointer = waylandRealignPointer,
|
|
|
|
.isValidPointerPos = waylandIsValidPointerPos,
|
2022-02-06 21:20:59 +00:00
|
|
|
.requestActivation = waylandActivationRequestActivation,
|
2021-05-03 20:35:36 +00:00
|
|
|
.inhibitIdle = waylandInhibitIdle,
|
|
|
|
.uninhibitIdle = waylandUninhibitIdle,
|
|
|
|
.wait = waylandWait,
|
|
|
|
.setWindowSize = waylandSetWindowSize,
|
|
|
|
.setFullscreen = waylandSetFullscreen,
|
|
|
|
.getFullscreen = waylandGetFullscreen,
|
2021-05-06 12:25:38 +00:00
|
|
|
.minimize = waylandMinimize,
|
2021-01-15 09:30:03 +00:00
|
|
|
|
|
|
|
.cbInit = waylandCBInit,
|
|
|
|
.cbNotice = waylandCBNotice,
|
|
|
|
.cbRelease = waylandCBRelease,
|
|
|
|
.cbRequest = waylandCBRequest
|
|
|
|
};
|