From f3a422fdd7950bf6089f35d43f2c2ae32fff6858 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 27 Dec 2025 23:34:44 +0100 Subject: [PATCH] Initial multi-x11/wayland backend setup Signed-off-by: falkTX --- Makefile.base.mk | 12 +- dgl/src/pugl-upstream | 2 +- dgl/src/pugl.cpp | 905 ++++++++++++++++++++++++++++++++++++++---- tests/Makefile | 2 +- 4 files changed, 834 insertions(+), 87 deletions(-) diff --git a/Makefile.base.mk b/Makefile.base.mk index f09cea9b..fa23558e 100644 --- a/Makefile.base.mk +++ b/Makefile.base.mk @@ -556,8 +556,16 @@ else ifeq ($(WINDOWS),true) OPENGL_FLAGS = OPENGL_LIBS = -lopengl32 else -OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl x11) -OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl x11) +OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl) +OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl) +ifeq ($(HAVE_X11),true) +OPENGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) +OPENGL_LIBS += $(shell $(PKG_CONFIG) --libs x11) +endif +ifeq ($(HAVE_WAYLAND_EGL),true) +OPENGL_FLAGS += $(shell $(PKG_CONFIG) --cflags egl wayland-egl) +OPENGL_LIBS += $(shell $(PKG_CONFIG) --libs egl wayland-egl) +endif endif HAVE_CAIRO_OR_OPENGL = true diff --git a/dgl/src/pugl-upstream b/dgl/src/pugl-upstream index 43c0944a..ed30e030 160000 --- a/dgl/src/pugl-upstream +++ b/dgl/src/pugl-upstream @@ -1 +1 @@ -Subproject commit 43c0944a2e28c6921bc827ac46f7215e5e59fe26 +Subproject commit ed30e030d78a6d647bf4c1ff19b1b50c627417f0 diff --git a/dgl/src/pugl.cpp b/dgl/src/pugl.cpp index 75fe8f05..0e67ff13 100644 --- a/dgl/src/pugl.cpp +++ b/dgl/src/pugl.cpp @@ -15,6 +15,8 @@ */ #include "pugl.hpp" +#include "Base.hpp" +#include "pugl/pugl.h" // -------------------------------------------------------------------------------------------------------------------- // include base headers @@ -76,37 +78,59 @@ # include # include # endif -#elif defined(HAVE_X11) +#elif defined(DGL_USING_X11_OR_WAYLAND) # include # include # include +# include # include // # include -# include -# include -# include -# include -# include -# include -# ifdef HAVE_XCURSOR -# include -// # include -# endif -# ifdef HAVE_XRANDR -# include -# endif -# ifdef HAVE_XSYNC -# include -# include -# endif -# ifdef DGL_CAIRO -# include -# endif -# ifdef DGL_OPENGL -# include +# ifdef HAVE_X11 +# include +# include +# include +# include +# include +# include +# ifdef HAVE_XCURSOR +# include +// # include +# endif +# ifdef HAVE_XRANDR +# include +# endif +# ifdef HAVE_XSYNC +# include +# include +# endif +# ifdef DGL_CAIRO +# include +# endif +# ifdef DGL_OPENGL +# include +# endif +# ifdef DGL_VULKAN +# include +# endif # endif -# ifdef DGL_VULKAN -# include +# ifdef HAVE_WAYLAND +// # include +// # include +// # include +// # include +// # include +// # include +// # include +// # include "pugl-upstream/src/xdg-decoration.h" +// # include "pugl-upstream/src/xdg-shell.h" +// # ifdef DGL_OPENGL +// # include +// # include +// # include +// # endif +// # ifdef DGL_VULKAN +// # include +// # endif # endif #endif @@ -193,29 +217,102 @@ START_NAMESPACE_DGL # ifdef DGL_VULKAN # include "pugl-upstream/src/win_vulkan.c" # endif -#elif defined(HAVE_X11) -# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wsign-conversion" -# endif -# include "pugl-upstream/src/x11.c" -# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -# pragma GCC diagnostic pop -# endif -# include "pugl-upstream/src/x11_stub.c" -# ifdef DGL_CAIRO -# include "pugl-upstream/src/x11_cairo.c" -# endif -# ifdef DGL_OPENGL -# include "pugl-upstream/src/x11_gl.c" +#elif defined(DGL_USING_X11_OR_WAYLAND) +// # include "pugl-upstream/src/types.h" +# include "pugl-upstream/src/common.c" +# include "pugl-upstream/src/internal.c" +# ifdef HAVE_X11 +# undef PUGL_PUGL_H +# undef PUGL_CAIRO_H +# undef PUGL_GL_H +# undef PUGL_STUB_H +# undef PUGL_VULKAN_H +# undef PUGL_INTERNAL_H +# undef PUGL_PLATFORM_H +# undef PUGL_SRC_STUB_H +# undef PUGL_SRC_TYPES_H +static const char kUsingX11Check[] = "x11"; +namespace x11 { +struct PuglBackendImpl; +struct PuglInternalsImpl; +struct PuglViewImpl; +struct PuglWorldImpl; +struct PuglWorldInternalsImpl; +# include "pugl-upstream/src/common.c" +# include "pugl-upstream/src/internal.c" +# include "pugl-upstream/src/x11.c" +# include "pugl-upstream/src/x11_stub.c" +# ifdef DGL_CAIRO +# include "pugl-upstream/src/x11_cairo.c" +# endif +# ifdef DGL_OPENGL +# include "pugl-upstream/src/x11_gl.c" +# endif +# ifdef DGL_VULKAN +# include "pugl-upstream/src/x11_vulkan.c" +# endif +} # endif -# ifdef DGL_VULKAN -# include "pugl-upstream/src/x11_vulkan.c" +# ifdef HAVE_WAYLAND +# undef PUGL_PUGL_H +# undef PUGL_CAIRO_H +# undef PUGL_GL_H +# undef PUGL_STUB_H +# undef PUGL_VULKAN_H +# undef PUGL_INTERNAL_H +# undef PUGL_PLATFORM_H +# undef PUGL_SRC_STUB_H +# undef PUGL_SRC_TYPES_H +END_NAMESPACE_DGL +extern "C" { +# include "pugl-upstream/src/xdg-decoration.c" +# include "pugl-upstream/src/xdg-shell.c" +} +START_NAMESPACE_DGL +static const char kUsingWaylandCheck[] = "wl"; +namespace wl { +struct PuglBackendImpl; +struct PuglInternalsImpl; +struct PuglViewImpl; +struct PuglWorldImpl; +struct PuglWorldInternalsImpl; +# define wl_callback ::wl_callback +# define wl_seat ::wl_seat +# define wl_surface ::wl_surface +# define xdg_decoration_manager ::zxdg_decoration_manager_v1 +# include "pugl-upstream/src/common.c" +# include "pugl-upstream/src/internal.c" +# include "pugl-upstream/src/wayland.c" +# include "pugl-upstream/src/wayland_stub.c" +# ifdef DGL_CAIRO +# include "pugl-upstream/src/wayland_cairo.c" +# endif +# ifdef DGL_OPENGL +# include "pugl-upstream/src/wayland_gl.c" +# endif +# ifdef DGL_VULKAN +# include "pugl-upstream/src/wayland_vulkan.c" +# endif +} # endif #endif -#include "pugl-upstream/src/common.c" -#include "pugl-upstream/src/internal.c" +#ifdef DGL_USING_X11_OR_WAYLAND +template +static constexpr inline Tp* cast(T* t) noexcept +{ + return static_cast(static_cast(t)); +} + +template +static constexpr inline const Tp* cast(const T* t) noexcept +{ + return static_cast(static_cast(t)); +} +#else +# include "pugl-upstream/src/common.c" +# include "pugl-upstream/src/internal.c" +#endif // -------------------------------------------------------------------------------------------------------------------- // DGL specific, expose backend enter @@ -238,6 +335,46 @@ bool puglBackendLeave(PuglView* const view) void puglSetMatchingBackendForCurrentBuild(PuglView* const view) { + #ifdef DGL_USING_X11_OR_WAYLAND + do { + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + x11::PuglView* const x11view = cast(view); + #ifdef DGL_CAIRO + x11::puglSetBackend(x11view, x11::puglCairoBackend()); + #endif + #ifdef DGL_OPENGL + x11::puglSetBackend(x11view, x11::puglGlBackend()); + #endif + #ifdef DGL_VULKAN + x11::puglSetBackend(x11view, x11::puglVulkanBackend()); + #endif + // maybe unused + (void)x11view; + break; + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + wl::PuglView* const wlview = cast(view); + #ifdef DGL_CAIRO + wl::puglSetBackend(wlview, wl::puglCairoBackend()); + #endif + #ifdef DGL_OPENGL + wl::puglSetBackend(wlview, wl::puglGlBackend()); + #endif + #ifdef DGL_VULKAN + wl::puglSetBackend(wlview, wl::puglVulkanBackend()); + #endif + // maybe unused + (void)wlview; + break; + } + #endif + } while (false); + #else #ifdef DGL_CAIRO puglSetBackend(view, puglCairoBackend()); #endif @@ -247,6 +384,7 @@ void puglSetMatchingBackendForCurrentBuild(PuglView* const view) #ifdef DGL_VULKAN puglSetBackend(view, puglVulkanBackend()); #endif + #endif if (view->backend != nullptr) { @@ -270,7 +408,24 @@ void puglSetMatchingBackendForCurrentBuild(PuglView* const view) } else { + #ifdef DGL_USING_X11_OR_WAYLAND + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + x11::puglSetBackend(cast(view), x11::puglStubBackend()); + return; + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + wl::puglSetBackend(cast(view), wl::puglStubBackend()); + return; + } + #endif + #else puglSetBackend(view, puglStubBackend()); + #endif } } @@ -290,8 +445,23 @@ void puglRaiseWindow(PuglView* const view) #elif defined(DISTRHO_OS_WINDOWS) SetForegroundWindow(view->impl->hwnd); SetActiveWindow(view->impl->hwnd); - #elif defined(HAVE_X11) - XRaiseWindow(view->world->impl->display, view->impl->win); + #elif defined(DGL_USING_X11_OR_WAYLAND) + do { + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + x11::PuglView* const x11view = cast(view); + XRaiseWindow(x11view->world->impl->display, x11view->impl->win); + break; + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + break; + } + #endif + } while (false); #endif } @@ -325,14 +495,29 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co }, className, width, height); #elif defined(DISTRHO_OS_WINDOWS) // nothing - #elif defined(HAVE_X11) - if (view->impl->win) - { - if (const PuglStatus status = puglUpdateSizeHints(view)) - return status; - - XFlush(view->world->impl->display); - } + #elif defined(DGL_USING_X11_OR_WAYLAND) + do { + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + x11::PuglView* const x11view = cast(view); + if (x11view->impl->win) + { + if (const x11::PuglStatus status = x11::puglUpdateSizeHints(x11view)) + return static_cast(status); + + XFlush(x11view->world->impl->display); + break; + } + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + break; + } + #endif + } while (false); #endif return PUGL_SUCCESS; @@ -363,8 +548,22 @@ void puglSetResizable(PuglView* const view, const bool resizable) : GetWindowLong(hwnd, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX); SetWindowLong(hwnd, GWL_STYLE, winFlags); } - #elif defined(HAVE_X11) - puglUpdateSizeHints(view); + #elif defined(DGL_USING_X11_OR_WAYLAND) + do { + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + x11::puglUpdateSizeHints(cast(view)); + break; + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + break; + } + #endif + } while (false); #endif } @@ -404,19 +603,34 @@ PuglStatus puglSetSizeAndDefault(PuglView* const view, const uint width, const u // make sure to return context back to ourselves puglBackendEnter(view); } - #elif defined(HAVE_X11) - // matches upstream pugl, adds flush at the end - if (view->impl->win) - { - if (const PuglStatus status = puglUpdateSizeHints(view)) - return status; - - if (const PuglStatus status = puglSetWindowSize(view, width, height)) - return status; - - // flush size changes - XFlush(view->world->impl->display); - } + #elif defined(DGL_USING_X11_OR_WAYLAND) + do { + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + // matches upstream pugl, adds flush at the end + x11::PuglView* const x11view = cast(view); + if (x11view->impl->win) + { + if (const x11::PuglStatus status = x11::puglUpdateSizeHints(x11view)) + return static_cast(status); + + if (const x11::PuglStatus status = x11::puglSetWindowSize(x11view, width, height)) + return static_cast(status); + + // flush size changes + XFlush(x11view->world->impl->display); + } + break; + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + break; + } + #endif + } while (false); #endif return PUGL_SUCCESS; @@ -573,14 +787,497 @@ void puglWin32ShowCentered(PuglView* const view) #elif defined(DGL_USING_X11_OR_WAYLAND) +// -------------------------------------------------------------------------------------------------------------------- +// X11 vs Wayland redirect + +// static constexpr inline PuglStatus status(x11::PuglStatus st) noexcept { return static_cast(st); } +// static constexpr inline PuglStatus status(wl::PuglStatus st) noexcept { return static_cast(st); } + +PuglStatus puglAcceptOffer(PuglView* const view, const PuglDataOfferEvent* const offer, const uint32_t typeIndex) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast( + x11::puglAcceptOffer(cast(view), cast(offer), typeIndex)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast( + wl::puglAcceptOffer(cast(view), cast(offer), typeIndex)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglApplySizeHint(PuglView* view, PuglSizeHint hint) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglApplySizeHint(cast(view), + static_cast(hint))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglApplySizeHint(cast(view), + static_cast(hint))); + #endif + return PUGL_BAD_BACKEND; +} + +void puglFreeViewInternals(PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return x11::puglFreeViewInternals(cast(view)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return wl::puglFreeViewInternals(cast(view)); + #endif +} + +void puglFreeWorldInternals(PuglWorld* const world) +{ + #ifdef HAVE_X11 + if (world->handle == kUsingX11Check) + return x11::puglFreeWorldInternals(cast(world)); + #endif + #ifdef HAVE_WAYLAND + if (world->handle == kUsingWaylandCheck) + return wl::puglFreeWorldInternals(cast(world)); + #endif +} + +PuglPoint puglGetAncestorCenter(const PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + { + const x11::PuglPoint pp = x11::puglGetAncestorCenter(cast(view)); + return CPP_AGGREGATE_INIT(PuglPoint){ pp.x, pp.y }; + } + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + { + const wl::PuglPoint pp = wl::puglGetAncestorCenter(cast(view)); + return CPP_AGGREGATE_INIT(PuglPoint){ pp.x, pp.y }; + } + #endif + return CPP_AGGREGATE_INIT(PuglPoint) { 0, 0 }; +} + +const void* puglGetClipboard(PuglView* const view, const uint32_t typeIndex, size_t* const len) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return x11::puglGetClipboard(cast(view), typeIndex, len); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return wl::puglGetClipboard(cast(view), typeIndex, len); + #endif + return nullptr; +} + +const char* puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return x11::puglGetClipboardType(cast(view), typeIndex); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return wl::puglGetClipboardType(cast(view), typeIndex); + #endif + return nullptr; +} + +PuglNativeView puglGetNativeView(PuglView* view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return x11::puglGetNativeView(cast(view)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return wl::puglGetNativeView(cast(view)); + #endif + return 0; +} + +uint32_t puglGetNumClipboardTypes(const PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return x11::puglGetNumClipboardTypes(cast(view)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return wl::puglGetNumClipboardTypes(cast(view)); + #endif + return 0; +} + +double puglGetScaleFactor(const PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return x11::puglGetScaleFactor(cast(view)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return wl::puglGetScaleFactor(cast(view)); + #endif + return 1.0; +} + +double puglGetTime(const PuglWorld* const world) +{ + #ifdef HAVE_X11 + if (world->handle == kUsingX11Check) + return x11::puglGetTime(cast(world)); + #endif + #ifdef HAVE_WAYLAND + if (world->handle == kUsingWaylandCheck) + return wl::puglGetTime(cast(world)); + #endif + return 0.0; +} + +PuglStatus puglGrabFocus(PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglGrabFocus(cast(view))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglGrabFocus(cast(view))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglHide(PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglHide(cast(view))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglHide(cast(view))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglInternals* puglInitViewInternals(PuglWorld* const world) +{ + #ifdef HAVE_X11 + if (world->handle == kUsingX11Check) + return cast(x11::puglInitViewInternals(cast(world))); + #endif + #ifdef HAVE_WAYLAND + if (world->handle == kUsingWaylandCheck) + return cast(wl::puglInitViewInternals(cast(world))); + #endif + return nullptr; +} + +PuglWorldInternals* puglInitWorldInternals(PuglWorld* const world, const PuglWorldType type, const PuglWorldFlags flags) +{ + bool usingX11 = false; + bool usingWayland = false; + #ifdef HAVE_WAYLAND + bool supportsDecorations = true; + #endif + + // initial choice by env var + if (const char* const backend = std::getenv("DPF_BACKEND")) + { + if (std::strcmp(backend, "x11") == 0) + usingX11 = true; + else if (std::strcmp(backend, "wayland") == 0) + usingWayland = true; + else + d_stderr("Unknown DPF_BACKEND value, must be 'x11' or 'wayland'"); + } + + // overridden if required for operation + if (flags & PUGL_WORLD_BACKEND_X11) + { + usingX11 = true; + usingWayland = false; + } + if (flags & PUGL_WORLD_BACKEND_WAYLAND) + { + usingX11 = false; + usingWayland = true; + #ifdef HAVE_WAYLAND + puglWaylandStatus(&supportsDecorations); + #endif + } + + // pick backend automatically if none selected + if (! (usingX11 || usingWayland)) + { + #ifdef HAVE_WAYLAND + usingWayland = puglWaylandStatus(&supportsDecorations); + if (! usingWayland) + #endif + { + #ifdef HAVE_X11 + usingX11 = true; + #ifdef HAVE_WAYLAND + supportsDecorations = true; + #endif + #endif + } + + if (! (usingX11 || usingWayland)) + { + d_stderr("Could not find a usable windowing backend"); + return nullptr; + } + } + + if (usingX11) + { + #ifdef HAVE_X11 + d_stdout("Using X11"); + x11::PuglWorld* const x11world = cast(world); + x11::puglSetWorldHandle(x11world, const_cast(kUsingX11Check)); + return cast(x11::puglInitWorldInternals(x11world, + static_cast(type), + static_cast(flags))); + #else + return nullptr; + #endif + } + + if (usingWayland) + { + #ifdef HAVE_WAYLAND + d_stdout("Using Wayland, compositor supports decorations: %s", supportsDecorations ? "true" : "false"); + wl::PuglWorld* const wlworld = cast(world); + wl::puglSetWorldHandle(wlworld, const_cast(kUsingWaylandCheck)); + return cast(wl::puglInitWorldInternals(wlworld, + static_cast(type), + static_cast(flags))); + #else + return nullptr; + #endif + } + + return nullptr; +} + + +PuglStatus puglObscureRegion(PuglView* const view, + const int x, + const int y, + const unsigned width, + const unsigned height) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglObscureRegion(cast(view), x, y, width, height)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglObscureRegion(cast(view), x, y, width, height)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglObscureView(PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglObscureView(cast(view))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglObscureView(cast(view))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglPaste(PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglPaste(cast(view))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglPaste(cast(view))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglRealize(PuglView* const view) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglRealize(cast(view))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglRealize(cast(view))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglSetClipboard(PuglView* const view, const char* const type, const void* const data, const size_t len) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglSetClipboard(cast(view), type, data, len)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglSetClipboard(cast(view), type, data, len)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglSetCursor(PuglView* view, PuglCursor cursor) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglSetCursor(cast(view), + static_cast(cursor))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglSetCursor(cast(view), + static_cast(cursor))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglSetTransientParent(PuglView* const view, const PuglNativeView parent) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglSetTransientParent(cast(view), parent)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglSetTransientParent(cast(view), parent)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglSetWindowPosition(PuglView* view, int x, int y) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglSetWindowPosition(cast(view), x, y)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglSetWindowPosition(cast(view), x, y)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglSetWindowSize(PuglView* view, unsigned width, unsigned height) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglSetWindowSize(cast(view), width, height)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglSetWindowSize(cast(view), width, height)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglShow(PuglView* const view, const PuglShowCommand command) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglShow(cast(view), + static_cast(command))); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglShow(cast(view), + static_cast(command))); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglStartTimer(cast(view), id, timeout)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglStartTimer(cast(view), id, timeout)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglStopTimer(PuglView* const view, const uintptr_t id) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglStopTimer(cast(view), id)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglStopTimer(cast(view), id)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglUpdate(PuglWorld* const world, const double timeout) +{ + #ifdef HAVE_X11 + if (world->handle == kUsingX11Check) + return static_cast(x11::puglUpdate(cast(world), timeout)); + #endif + #ifdef HAVE_WAYLAND + if (world->handle == kUsingWaylandCheck) + return static_cast(wl::puglUpdate(cast(world), timeout)); + #endif + return PUGL_BAD_BACKEND; +} + +PuglStatus puglViewStringChanged(PuglView* const view, const PuglStringHint key, const char* const value) +{ + #ifdef HAVE_X11 + if (view->world->handle == kUsingX11Check) + return static_cast(x11::puglViewStringChanged(cast(view), + static_cast(key), + value)); + #endif + #ifdef HAVE_WAYLAND + if (view->world->handle == kUsingWaylandCheck) + return static_cast(wl::puglViewStringChanged(cast(view), + static_cast(key), + value)); + #endif + return PUGL_BAD_BACKEND; +} + // -------------------------------------------------------------------------------------------------------------------- // X11 or Wayland specific, check if using wayland bool puglUsingWayland(PuglWorld* const world) { - // TODO - (void)world; +#ifdef HAVE_WAYLAND + return world->handle == kUsingWaylandCheck; +#else return false; + // unused + (void)world; +#endif } #ifdef HAVE_X11 @@ -590,21 +1287,26 @@ bool puglUsingWayland(PuglWorld* const world) PuglStatus puglX11UpdateWithoutExposures(PuglWorld* const world) { + if (world->handle != kUsingX11Check) + return PUGL_BACKEND_FAILED; + + x11::PuglWorld* const x11world = cast(world); + const PuglWorldState startState = world->state; world->state = PUGL_WORLD_UPDATING; - PuglStatus st = PUGL_SUCCESS; + x11::PuglStatus st = x11::PUGL_SUCCESS; - const double startTime = puglGetTime(world); + const double startTime = x11::puglGetTime(x11world); const double endTime = startTime + 0.03; - for (double t = startTime; !st && t < endTime; t = puglGetTime(world)) + for (double t = startTime; !st && t < endTime; t = x11::puglGetTime(x11world)) { - if (!(st = pollX11Socket(world, endTime - t))) - st = dispatchX11Events(world); + if (!(st = x11::pollX11Socket(x11world, endTime - t))) + st = x11::dispatchX11Events(x11world); } world->state = startState; - return st; + return static_cast(st); } // -------------------------------------------------------------------------------------------------------------------- @@ -612,8 +1314,12 @@ PuglStatus puglX11UpdateWithoutExposures(PuglWorld* const world) void puglX11SetWindowType(const PuglView* const view, const bool isStandalone) { - const PuglInternals* const impl = view->impl; - Display* const display = view->world->impl->display; + if (view->world->handle != kUsingX11Check) + return; + + const x11::PuglView* const x11view = cast(view); + const x11::PuglInternals* const impl = x11view->impl; + Display* const display = x11view->world->impl->display; #if defined(DGL_X11_WINDOW_ICON_NAME) && defined(DGL_X11_WINDOW_ICON_SIZE) if (isStandalone) @@ -657,11 +1363,44 @@ void puglX11SetWindowType(const PuglView* const view, const bool isStandalone) // -------------------------------------------------------------------------------------------------------------------- // Wayland specific, check if running wayland and if compositor supports decorations -bool puglWaylandStatus(bool* supportsDecorations) +static void wayland_compositor_test(void* const data, + struct wl_registry* const wl_registry, + const uint32_t name, + const char* const interface, + const uint32_t version) { - // TODO - (void)supportsDecorations; - return false; + if (std::strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) + *static_cast(data) = wl_registry != NULL && name != 0 && version != 0; +} + +bool puglWaylandStatus(bool* const supportsDecorations) +{ + static constexpr const struct wl_registry_listener wl_registry_listener = { + wayland_compositor_test, + nullptr, + }; + + bool supportsWayland = false; + *supportsDecorations = false; + + if (struct wl_display* const wl_display = wl_display_connect(nullptr)) + { + if (struct wl_registry* const wl_registry = wl_display_get_registry(wl_display)) + { + if (wl_registry_add_listener(wl_registry, &wl_registry_listener, supportsDecorations) == 0) + { + if (wl_display_roundtrip(wl_display) > 0) + // TODO also query required features + supportsWayland = true; + } + + wl_registry_destroy(wl_registry); + } + + wl_display_disconnect(wl_display); + } + + return supportsWayland; } #endif // HAVE_WAYLAND diff --git a/tests/Makefile b/tests/Makefile index 2be6d2ef..350341c3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -11,7 +11,7 @@ include ../Makefile.base.mk # --------------------------------------------------------------------------------------------------------------------- BUILD_C_FLAGS += $(DGL_FLAGS) -I.. -BUILD_CXX_FLAGS += $(DGL_FLAGS) -I.. -I../dgl/src/pugl-upstream/include -DDONT_SET_USING_DGL_NAMESPACE +BUILD_CXX_FLAGS += $(DGL_FLAGS) -I.. -I../dgl -I../dgl/src/pugl-upstream/include -DDONT_SET_USING_DGL_NAMESPACE LINK_FLAGS += -lpthread # TODO fix within pugl