From 85debc121e10366a503b88f26875398565d9466a Mon Sep 17 00:00:00 2001 From: Silo Date: Fri, 28 Mar 2025 14:19:27 +0300 Subject: [PATCH 01/13] Adds native support wayland linux --- examples/host/linux/skia_app.cpp | 310 +++++++++++++++---------------- 1 file changed, 150 insertions(+), 160 deletions(-) diff --git a/examples/host/linux/skia_app.cpp b/examples/host/linux/skia_app.cpp index d70f530..5548e5e 100644 --- a/examples/host/linux/skia_app.cpp +++ b/examples/host/linux/skia_app.cpp @@ -4,163 +4,37 @@ Distributed under the MIT License [ https://opensource.org/licenses/MIT ] =============================================================================*/ #include "../../app.hpp" -#include +//#include #include -#include +//#include #include "GrDirectContext.h" #include "gl/GrGLInterface.h" #include "gl/GrGLAssembleInterface.h" -#include "SkImage.h" +//#include "SkImage.h" #include "SkColorSpace.h" #include "SkCanvas.h" #include "SkSurface.h" #include +#include "wayland/contextegl.h" +#include "wayland/xdgshell.h" + using namespace cycfi::artist; float elapsed_ = 0; // rendering elapsed time -namespace +void render(SkCanvas* gpu_canvas, float scale) { - struct view_state - { - extent _size = {}; - float _scale = 1.0; - bool _animate = false; - color _bkd = colors::white; - guint _timer_id = 0; - - sk_sp _xface; - sk_sp _ctx; - sk_sp _surface; - }; - - void close_window(GtkWidget*, gpointer user_data) - { - view_state& state = *reinterpret_cast(user_data); - if (state._timer_id) - g_source_remove(state._timer_id); - } - - void realize(GtkGLArea* area, gpointer user_data) - { - auto error = [](char const* msg) { throw std::runtime_error(msg); }; - - gtk_gl_area_make_current(area); - if (gtk_gl_area_get_error(area) != nullptr) - error("Error. gtk_gl_area_get_error failed"); - - view_state& state = *reinterpret_cast(user_data); - glClearColor(state._bkd.red, state._bkd.green, state._bkd.blue, state._bkd.alpha); - glClear(GL_COLOR_BUFFER_BIT); - if (state._xface = GrGLMakeNativeInterface(); state._xface == nullptr) - { - //backup plan. see https://gist.github.com/ad8e/dd150b775ae6aa4d5cf1a092e4713add?permalink_comment_id=4680136#gistcomment-4680136 - state._xface = GrGLMakeAssembledInterface( - nullptr, (GrGLGetProc) * - [](void*, const char* p) -> void* - { - return (void*)glXGetProcAddress((const GLubyte*)p); - } - ); - if (state._xface == nullptr) - error("Error. GLMakeNativeInterface failed"); - } - if (state._ctx = GrDirectContext::MakeGL(state._xface); state._ctx == nullptr) - error("Error. GrDirectContext::MakeGL failed"); - } - - gboolean render(GtkGLArea* area, GdkGLContext* context, gpointer user_data) - { - view_state& state = *reinterpret_cast(user_data); - auto error = [](char const* msg) { throw std::runtime_error(msg); }; - - auto draw_f = - [&]() - { - if (!state._surface) - { - GrGLint buffer; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer); - GrGLFramebufferInfo info; - info.fFBOID = (GrGLuint) buffer; - SkColorType colorType = kRGBA_8888_SkColorType; - - info.fFormat = GL_RGBA8; - GrBackendRenderTarget target( - state._size.x*state._scale - , state._size.y*state._scale - , 0, 8, info - ); - - state._surface = - SkSurface::MakeFromBackendRenderTarget( - state._ctx.get(), target, - kBottomLeft_GrSurfaceOrigin, colorType, nullptr, nullptr - ); - - if (!state._surface) - error("Error: SkSurface::MakeRenderTarget returned null"); - } - - SkCanvas* gpu_canvas = state._surface->getCanvas(); - gpu_canvas->save(); - gpu_canvas->scale(state._scale, state._scale); - auto cnv = canvas{gpu_canvas}; - - draw(cnv); - - gpu_canvas->restore(); - state._surface->flush(); - }; - - auto start = std::chrono::steady_clock::now(); - draw_f(); - auto stop = std::chrono::steady_clock::now(); - elapsed_ = std::chrono::duration{stop - start}.count(); - - return true; - } + auto start = std::chrono::steady_clock::now(); - gboolean animate(gpointer user_data) - { - GtkWidget* da = GTK_WIDGET(user_data); - gtk_widget_queue_draw(da); - return true; - } + gpu_canvas->save(); + gpu_canvas->scale(scale, scale); + auto cnv = canvas{gpu_canvas}; + draw(cnv); + gpu_canvas->restore(); - static auto proc = &glXGetProcAddress; - - void activate(GtkApplication* app, gpointer user_data) - { - auto error = [](char const* msg) { throw std::runtime_error(msg); }; - if (!proc) - error("Error: glXGetProcAddress is null"); - - view_state& state = *reinterpret_cast(user_data); - auto* window = gtk_application_window_new(app); - gtk_window_set_title(GTK_WINDOW(window), "Drawing Area"); - - g_signal_connect(window, "destroy", G_CALLBACK(close_window), user_data); - - GtkWidget* widget = nullptr; - // create a GtkGLArea instance - GtkWidget* gl_area = gtk_gl_area_new(); - widget = gl_area; - gtk_container_add(GTK_CONTAINER(window), gl_area); - - g_signal_connect(gl_area, "render", G_CALLBACK(render), user_data); - g_signal_connect(gl_area, "realize", G_CALLBACK(realize), user_data); - - gtk_window_resize(GTK_WINDOW(window), state._size.x, state._size.y); - gtk_widget_show_all(window); - - auto w = gtk_widget_get_window(GTK_WIDGET(window)); - state._scale = gdk_window_get_scale_factor(w); - - if (widget && state._animate) - state._timer_id = g_timeout_add(1000 / 60, animate, widget); - } + auto stop = std::chrono::steady_clock::now(); + elapsed_ = std::chrono::duration{stop - start}.count(); } namespace cycfi::artist @@ -179,6 +53,114 @@ namespace cycfi::artist } } +namespace WL { + +class PaintContextSkia; + +class SurfaceSkia: public ContextEGL::BufferEGL +{ +public: + SurfaceSkia(PaintContextSkia &ctx, NativeSurface &wl, uint32_t width, uint32_t height): + ContextEGL::BufferEGL(ctx, wl, width, height) + { + if (ContextEGL::BufferEGL::valid()){ + + GrGLFramebufferInfo framebufferInfo; + framebufferInfo.fFBOID = 0; // assume default framebuffer + framebufferInfo.fFormat = GL_RGBA8; + + SkColorType colorType = kRGBA_8888_SkColorType; + GrBackendRenderTarget target(width, + height, + 1, // sample count + 8, // stencil bits + framebufferInfo); + + skia = SkSurface::MakeFromBackendRenderTarget(ctx._ctx.get(), + target, + kBottomLeft_GrSurfaceOrigin, + colorType, + nullptr, + nullptr); + if (!skia) ctx.destroy(*this); + } + } + + sk_sp skia; +}; + +class PaintContextSkia : public ContextEGL +{ +public: + using Buffer = SurfaceSkia; + + void flush(Buffer &buf) const + { + buf.skia->flush(); + ContextEGL::flush(buf); + } + void destroy(Buffer &buf) + { + buf.skia.reset(); + ContextEGL::destroy(buf); + } + + PaintContextSkia(bool transparent = false): + ContextEGL(transparent) + { + auto _xface = GrGLMakeNativeInterface(); + if (_xface == nullptr) { + //backup plan. see https://gist.github.com/ad8e/dd150b775ae6aa4d5cf1a092e4713add?permalink_comment_id=4680136#gistcomment-4680136 + _xface = GrGLMakeAssembledInterface( + nullptr, (GrGLGetProc) * [](void *, const char *p) -> void * { + return (void *) eglGetProcAddress(p); + }); + } + + _ctx = GrDirectContext::MakeGL(_xface); + if (!_ctx) + throw std::runtime_error("failed to make Skia context"); + } + +private: + sk_sp _ctx; + friend class SurfaceSkia; +}; + +class Window: public Toplevel, + public SeatListener +{ +public: + Window(int width, int height): + Toplevel(width, height)//, + //m_opaque(ctx.opaque()) + { + listenerInput(*this); + } + + std::function onClosed; + std::function onDraw; + std::function onReshape; + +private: + //bool m_opaque; + + void draw(float scale) override + {if (onDraw) onDraw(m_buffer->skia->getCanvas(), scale);} + void closed() override + {if (onClosed) onClosed();} + bool configure(uint32_t width, uint32_t height, uint32_t state) override + { + if (onReshape && state & WL::XDGState::resizing) { + onReshape(width, height); + return true; + } + return false; + } +}; + +} + int run_app( int argc , char const* argv[] @@ -187,28 +169,36 @@ int run_app( , bool animate ) { - view_state state; - state._size = window_size; - state._animate = animate; - state._bkd = background_color; + try { - auto* app = gtk_application_new("org.gtk-skia.example", G_APPLICATION_FLAGS_NONE); - int status = 0; + auto& dpy = WL::Display::init(); - try - { - g_signal_connect(app, "activate", G_CALLBACK(activate), &state); - int status = g_application_run(G_APPLICATION(app), argc, const_cast(argv)); - } - catch (std::runtime_error const& e) - { - // GPU rendering not available - g_printerr(e.what()); - int status = 1; - } - g_object_unref(app); + WL::Window window(window_size.x, window_size.y); + + window.onClosed = [&dpy](){dpy.stop();}; + window.setTitle("Example application"); + window.onDraw = [&window, animate](SkCanvas *surf, float scale ) { + render(surf, scale); + + if (animate) + window.refresh(); + }; + window.onReshape = [&background_color](int, int) { + glClearColor(background_color.red + 0.1, + background_color.green, + background_color.blue, + background_color.alpha); + glClear(GL_COLOR_BUFFER_BIT); + }; + + dpy.start_event(); + + } catch (const char* err) { + std::cerr<<"Error: "< Date: Fri, 28 Mar 2025 14:24:13 +0300 Subject: [PATCH 02/13] Adds native support wayland linux --- examples/CMakeLists.txt | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1fc8b41..436a582 100755 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -78,17 +78,40 @@ function(add_example name) ) elseif (UNIX) - + set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake") + find_package(WaylandScanner REQUIRED) + + set(WORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/host/linux/wayland") + + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/stable/xdg-shell/xdg-shell.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/staging/cursor-shape/cursor-shape-v1.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/unstable/tablet/tablet-unstable-v2.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/stable/viewporter/viewporter.xml") + add_executable( ${name} ${name}.cpp + host/linux/wayland/core.cpp + host/linux/wayland/display.cpp + host/linux/wayland/xdgshell.cpp + host/linux/wayland/contextegl.cpp + ${SRC_GEN} host/linux/skia_app.cpp print_elapsed.cpp ) target_link_libraries( ${name} - PkgConfig::gtk3 + #PkgConfig::gtk3 + PkgConfig::depend OpenGL::GL ) From 4954e284aeb99cef29dd98b97a3492625a0c13b4 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 28 Mar 2025 19:08:19 +0300 Subject: [PATCH 03/13] Adds native wayland window support to Linux --- CMakeLists.txt.user | 260 ++ examples/CMakeLists.txt | 5 +- examples/cmake/FindWaylandScanner.cmake | 60 + examples/host/linux/skia_app.cpp | 78 +- examples/host/linux/wayland/contextegl.cpp | 158 ++ examples/host/linux/wayland/contextegl.h | 58 + examples/host/linux/wayland/core.cpp | 439 ++++ examples/host/linux/wayland/core.h | 283 ++ .../wayland/cursor-shape-v1-client-protocol.h | 426 +++ .../linux/wayland/cursor-shape-v1-protocol.c | 75 + examples/host/linux/wayland/display.cpp | 171 ++ examples/host/linux/wayland/display.h | 244 ++ .../fractional-scale-v1-client-protocol.h | 264 ++ .../wayland/fractional-scale-v1-protocol.c | 74 + .../tablet-unstable-v2-client-protocol.h | 2252 ++++++++++++++++ .../wayland/tablet-unstable-v2-protocol.c | 234 ++ .../wayland/viewporter-client-protocol.h | 394 +++ .../host/linux/wayland/viewporter-protocol.c | 75 + ...g-decoration-unstable-v1-client-protocol.h | 384 +++ .../xdg-decoration-unstable-v1-protocol.c | 76 + .../linux/wayland/xdg-shell-client-protocol.h | 2325 +++++++++++++++++ .../host/linux/wayland/xdg-shell-protocol.c | 184 ++ examples/host/linux/wayland/xdgshell.cpp | 78 + examples/host/linux/wayland/xdgshell.h | 143 + 24 files changed, 8696 insertions(+), 44 deletions(-) create mode 100644 CMakeLists.txt.user create mode 100644 examples/cmake/FindWaylandScanner.cmake create mode 100644 examples/host/linux/wayland/contextegl.cpp create mode 100644 examples/host/linux/wayland/contextegl.h create mode 100644 examples/host/linux/wayland/core.cpp create mode 100644 examples/host/linux/wayland/core.h create mode 100644 examples/host/linux/wayland/cursor-shape-v1-client-protocol.h create mode 100644 examples/host/linux/wayland/cursor-shape-v1-protocol.c create mode 100644 examples/host/linux/wayland/display.cpp create mode 100644 examples/host/linux/wayland/display.h create mode 100644 examples/host/linux/wayland/fractional-scale-v1-client-protocol.h create mode 100644 examples/host/linux/wayland/fractional-scale-v1-protocol.c create mode 100644 examples/host/linux/wayland/tablet-unstable-v2-client-protocol.h create mode 100644 examples/host/linux/wayland/tablet-unstable-v2-protocol.c create mode 100644 examples/host/linux/wayland/viewporter-client-protocol.h create mode 100644 examples/host/linux/wayland/viewporter-protocol.c create mode 100644 examples/host/linux/wayland/xdg-decoration-unstable-v1-client-protocol.h create mode 100644 examples/host/linux/wayland/xdg-decoration-unstable-v1-protocol.c create mode 100644 examples/host/linux/wayland/xdg-shell-client-protocol.h create mode 100644 examples/host/linux/wayland/xdg-shell-protocol.c create mode 100644 examples/host/linux/wayland/xdgshell.cpp create mode 100644 examples/host/linux/wayland/xdgshell.h diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user new file mode 100644 index 0000000..6624bc5 --- /dev/null +++ b/CMakeLists.txt.user @@ -0,0 +1,260 @@ + + + + + + EnvironmentId + {23b32c7f-0899-49e8-97cb-f699c52a0902} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 0 + 80 + true + true + 1 + 0 + false + true + false + 2 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 4 + true + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {627454d1-a178-4e9b-896d-df645d6cef58} + 0 + 0 + 0 + + Debug + 2 + false + + -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + 0 + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug + + + + + all + + false + + true + Собрать + CMakeProjectManager.MakeStep + + 1 + Сборка + Сборка + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + Собрать + CMakeProjectManager.MakeStep + + 1 + Очистка + Очистка + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Отладка + CMakeProjectManager.CMakeBuildConfiguration + + + Release + 2 + false + + -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Release + + + + + all + + false + + true + CMakeProjectManager.MakeStep + + 1 + Сборка + Сборка + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + CMakeProjectManager.MakeStep + + 1 + Очистка + Очистка + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Выпуск + CMakeProjectManager.CMakeBuildConfiguration + + 2 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 436a582..9d7ae25 100755 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,7 +8,10 @@ project(examples) if (UNIX AND NOT APPLE) find_package(OpenGL REQUIRED COMPONENTS OpenGL) find_package(PkgConfig REQUIRED) - pkg_check_modules(gtk3 REQUIRED IMPORTED_TARGET gtk+-3.0) + #pkg_check_modules(gtk3 REQUIRED IMPORTED_TARGET gtk+-3.0) + pkg_check_modules(depend REQUIRED IMPORTED_TARGET + wayland-client wayland-cursor wayland-egl xkbcommon egl + ) endif() file( diff --git a/examples/cmake/FindWaylandScanner.cmake b/examples/cmake/FindWaylandScanner.cmake new file mode 100644 index 0000000..62af156 --- /dev/null +++ b/examples/cmake/FindWaylandScanner.cmake @@ -0,0 +1,60 @@ +# Finds the Wayland client libraries +# Also supports components "protocols" and "scanner" + +find_package(PkgConfig QUIET) + +pkg_check_modules(PKG_Wayland QUIET wayland-protocols wayland-scanner) + +set(WaylandScanner_VERSION ${PKG_Wayland_VERSION}) +set(WaylandScanner_DEFINITIONS ${PKG_Wayland_CFLAGS}) +mark_as_advanced(WaylandScanner_DEFINITIONS) + +pkg_get_variable(Wayland_PROTOCOLS_DATADIR wayland-protocols pkgdatadir) +mark_as_advanced(Wayland_PROTOCOLS_DATADIR) + +if (NOT Wayland_PROTOCOLS_DATADIR) + message(FATAL "The wayland-protocols data directory has not been found on your system.") +endif() + +pkg_get_variable(WaylandScanner_EXECUTABLE_DIR wayland-scanner bindir) +find_program(WaylandScanner_EXECUTABLE NAMES wayland-scanner HINTS ${WaylandScanner_EXECUTABLE_DIR}) +mark_as_advanced(WaylandScanner_EXECUTABLE WaylandScanner_EXECUTABLE_DIR) + +set(WaylandScanner_DATADIR ${Wayland_PROTOCOLS_DATADIR}) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(WaylandScanner + FOUND_VAR WaylandScanner_FOUND + VERSION_VAR WaylandScanner_VERSION + REQUIRED_VARS WaylandScanner_EXECUTABLE ) #Wayland_LIBRARIES) + +if (NOT TARGET Wayland::Scanner AND WaylandScanner_FOUND) + add_executable(Wayland::Scanner IMPORTED) + set_target_properties(Wayland::Scanner PROPERTIES + IMPORTED_LOCATION "${WaylandScanner_EXECUTABLE}") +endif() + +function(wayland_add_protocol_client _sources _workdir _protocol) + if (NOT TARGET Wayland::Scanner) + message(FATAL "The wayland-scanner executable has not been found on your system.") + endif() + + get_filename_component(_basename ${_protocol} NAME_WLE) + + set(_source_file "${_protocol}") + set(_client_header "${_workdir}/${_basename}-client-protocol.h") + set(_private_code "${_workdir}/${_basename}-protocol.c") + + add_custom_command(OUTPUT ${_client_header} + COMMAND Wayland::Scanner client-header ${_source_file} ${_client_header} + DEPENDS ${_source_file} VERBATIM) + + add_custom_command(OUTPUT ${_private_code} + COMMAND Wayland::Scanner private-code ${_source_file} ${_private_code} + DEPENDS ${_source_file} ${_client_header} VERBATIM) + + list(APPEND ${_sources} ${_client_header} ${_private_code}) + set(${_sources} ${${_sources}} PARENT_SCOPE) + +endfunction() diff --git a/examples/host/linux/skia_app.cpp b/examples/host/linux/skia_app.cpp index 5548e5e..8ff8daa 100644 --- a/examples/host/linux/skia_app.cpp +++ b/examples/host/linux/skia_app.cpp @@ -53,46 +53,41 @@ namespace cycfi::artist } } -namespace WL { - -class PaintContextSkia; - -class SurfaceSkia: public ContextEGL::BufferEGL +class PaintContextSkia : public WL::ContextEGL { public: - SurfaceSkia(PaintContextSkia &ctx, NativeSurface &wl, uint32_t width, uint32_t height): - ContextEGL::BufferEGL(ctx, wl, width, height) - { - if (ContextEGL::BufferEGL::valid()){ - - GrGLFramebufferInfo framebufferInfo; - framebufferInfo.fFBOID = 0; // assume default framebuffer - framebufferInfo.fFormat = GL_RGBA8; - - SkColorType colorType = kRGBA_8888_SkColorType; - GrBackendRenderTarget target(width, - height, - 1, // sample count - 8, // stencil bits - framebufferInfo); - - skia = SkSurface::MakeFromBackendRenderTarget(ctx._ctx.get(), - target, - kBottomLeft_GrSurfaceOrigin, - colorType, - nullptr, - nullptr); - if (!skia) ctx.destroy(*this); - } - } - sk_sp skia; -}; - -class PaintContextSkia : public ContextEGL -{ -public: - using Buffer = SurfaceSkia; + class Buffer: public BufferEGL + { + public: + Buffer(PaintContextSkia &ctx, WL::NativeSurface &wl, uint32_t width, uint32_t height): + BufferEGL(ctx, wl, width, height) + { + if (BufferEGL::valid()){ + + GrGLFramebufferInfo framebufferInfo; + framebufferInfo.fFBOID = 0; // assume default framebuffer + framebufferInfo.fFormat = GL_RGBA8; + + SkColorType colorType = kRGBA_8888_SkColorType; + GrBackendRenderTarget target(width, + height, + 1, // sample count + 8, // stencil bits + framebufferInfo); + + skia = SkSurface::MakeFromBackendRenderTarget(ctx._ctx.get(), + target, + kBottomLeft_GrSurfaceOrigin, + colorType, + nullptr, + nullptr); + if (!skia) ctx.destroy(*this); + } + } + + sk_sp skia; + }; void flush(Buffer &buf) const { @@ -124,11 +119,10 @@ class PaintContextSkia : public ContextEGL private: sk_sp _ctx; - friend class SurfaceSkia; }; -class Window: public Toplevel, - public SeatListener +class Window: public WL::Toplevel, + public WL::SeatListener { public: Window(int width, int height): @@ -159,8 +153,6 @@ class Window: public Toplevel, } }; -} - int run_app( int argc , char const* argv[] @@ -173,7 +165,7 @@ int run_app( auto& dpy = WL::Display::init(); - WL::Window window(window_size.x, window_size.y); + Window window(window_size.x, window_size.y); window.onClosed = [&dpy](){dpy.stop();}; window.setTitle("Example application"); diff --git a/examples/host/linux/wayland/contextegl.cpp b/examples/host/linux/wayland/contextegl.cpp new file mode 100644 index 0000000..94d9f52 --- /dev/null +++ b/examples/host/linux/wayland/contextegl.cpp @@ -0,0 +1,158 @@ +#include "contextegl.h" +#include "display.h" + +#include + +using namespace WL; + +ContextEGL::ContextEGL(bool transparent): + m_egl_display(eglGetDisplay(Display::instance().native())) +{ + EGLint majorVersion; + EGLint minorVersion; + + if (m_egl_display == EGL_NO_DISPLAY || + eglInitialize(m_egl_display, &majorVersion, &minorVersion) != EGL_TRUE) { + + throw std::runtime_error("Can't connect to egl display"); + } + + if (eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) + throw std::runtime_error("Can't bind EGL_OPENGL_ES_API"); + + std::cerr<<"EGL: "< +#include +#include + +//#include + +namespace WL { + +class NativeSurface; +class Display; + +class ContextEGL +{ +public: + class BufferEGL + { + public: + BufferEGL(ContextEGL &ctx, NativeSurface &wl, uint32_t width, uint32_t height); + + void resize(uint32_t width, uint32_t height) + {wl_egl_window_resize(m_egl_window, width, height, 0, 0);} + + bool valid() const {return m_egl_surface != nullptr;} + + protected: + wl_egl_window *m_egl_window{nullptr}; + EGLSurface m_egl_surface{nullptr}; + + friend class ContextEGL; + }; + + using Buffer = BufferEGL; + + void makeCurrent(Buffer &buf); + void flush(Buffer &buf) const; + void destroy(Buffer &buf); + + ContextEGL(bool transparent = true); + ~ContextEGL(); + + operator bool() const { return m_egl_display != nullptr; } + + bool opaque() const; + +private: + EGLDisplay m_egl_display; + EGLContext m_egl_context; + EGLConfig m_egl_config ; + + // static inline ContextEGL *s_instance = nullptr; +}; + +} + +#endif // CONTEXTEGL_H diff --git a/examples/host/linux/wayland/core.cpp b/examples/host/linux/wayland/core.cpp new file mode 100644 index 0000000..a7e3445 --- /dev/null +++ b/examples/host/linux/wayland/core.cpp @@ -0,0 +1,439 @@ +#include "core.h" + +#include +#include +#include +//#include +#include +#include + +#include + +namespace WL { + +////////---- Surface Impl ----/////////////////////////////////////// + +NativeSurface::NativeSurface(wl_compositor *compositor, + const FractionalScaleManager *manager): + Base(wl_compositor_create_surface(compositor), "Can't create surface"), + m_fscale(manager ? wp_fractional_scale_manager_v1_get_fractional_scale(manager->c_ptr(), c_ptr()) + : nullptr) +{ + if (m_fscale) { + static const wp_fractional_scale_v1_listener lsr{ + .preferred_scale = [](void *data, wp_fractional_scale_v1 *, uint32_t scale) { + auto self = static_cast(data); + auto val = (float)scale / 120; + + self->m_scale = val; + if (self->onScale) self->onScale(val); + } + }; + + wp_fractional_scale_v1_add_listener(m_fscale.c_ptr(), &lsr, this); + } +} + +void NativeSurface::setAreaOpaque(wl_compositor *compositor, int32_t w, int32_t h) const +{ + auto region = wl_compositor_create_region(compositor); + if (!region) + return; + + wl_region_add(region, 0, 0, w, h); + wl_surface_set_opaque_region(c_ptr(), region); + wl_region_destroy(region); +} + + +////////---- Seat Impl ----////////////////////////////////////////// + +struct Keyboard::KeyMapper +{ + xkb_context *kcontext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + xkb_keymap *keymap = nullptr; + xkb_state *kstate = nullptr; + uint32_t keycode = 0; + uint32_t keysymbol = 0; + + ~KeyMapper() + { + if (kstate) + xkb_state_unref(kstate); + if (keymap) + xkb_keymap_unref(keymap); + if (kcontext) + xkb_context_unref(kcontext); + } + + bool map(int32_t fd, uint32_t size) noexcept; + bool keySymbol(uint32_t key) noexcept; +}; + +bool Keyboard::KeyMapper::map(int32_t fd, uint32_t size) noexcept +{ + if(!kcontext){ + std::cerr<<"Error: create xkb context"<= XKB_KEY_Shift_L && sym <= XKB_KEY_Hyper_R) || + (sym >= XKB_KEY_ISO_Lock && sym <= XKB_KEY_ISO_Last_Group_Lock) || + sym == XKB_KEY_Mode_switch || + sym == XKB_KEY_Num_Lock) + return false; + + keycode = raw_key; + keysymbol = sym; + return true; +} + +Keyboard::~Keyboard() +{ + delete m_mapper; +} + +unsigned Keyboard::modifiers(ModSet group) const +{ + if (m_mapper) + switch (group) { + case ModSet::effective: + return xkb_state_serialize_mods( + m_mapper->kstate, XKB_STATE_MODS_EFFECTIVE); + case ModSet::consumed: + return xkb_state_key_get_consumed_mods2( + m_mapper->kstate, m_mapper->keycode, XKB_CONSUMED_MODE_XKB); + case ModSet::locked: + return xkb_state_serialize_mods( + m_mapper->kstate, XKB_STATE_MODS_LOCKED); + default: + break; + } + + return 0; +} + +const char* Keyboard::utf8() const +{ + return ""; +} + +uint32_t Keyboard::symbol() const +{ + return m_mapper->keysymbol; +} + +void Seat::emitKeypress() const +{ + assert(m_focused_surf); + assert(m_focused_surf->onKey); + + m_focused_surf->onKey(m_keyboard); +} + +const wl_keyboard_listener Seat::keyboard_listener = { + .keymap = [](void *data, wl_keyboard*, + uint32_t format, int32_t fd, + uint32_t size){ + + auto& kb = static_cast(data)->m_keyboard; + + if (format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 && !kb.m_mapper) + kb.m_mapper = new(std::nothrow) Keyboard::KeyMapper; + //else + //To Do WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP + + if(kb.m_mapper){ + if (!kb.m_mapper->map(fd, size)) { + delete kb.m_mapper; + kb.m_mapper = nullptr; + //To Do log file + } + } + else + std::cerr<<"KEYMAP_FORMAT not supported, format code: "<(data); + + seat->m_focused_surf = static_cast( + wl_surface_get_user_data(surface)); + + if (seat->m_focused_surf && seat->m_focused_surf->onFocused) + seat->m_focused_surf->onFocused(true); + }, + .leave = [](void *data, wl_keyboard *wl_kd, uint32_t, + wl_surface*){ + + auto seat = static_cast(data); + + if (seat->m_focused_surf->onFocused) + seat->m_focused_surf->onFocused(false); + + seat->m_focused_surf = nullptr; + + struct itimerspec timer = {0}; + timerfd_settime(seat->key_repeat_fd, 0, &timer, NULL); + }, + .key = [](void *data, wl_keyboard *wl_kd, uint32_t /*serial*/, + uint32_t time, + uint32_t key, + uint32_t state){ + + auto seat = static_cast(data); + auto mapper = seat->m_keyboard.m_mapper; + + if (seat->m_focused_surf && + mapper && + seat->m_focused_surf->onKey){ + + bool pressed = (state == WL_KEYBOARD_KEY_STATE_PRESSED); + + itimerspec timer = {0}; + + if (seat->rate != 0 && + xkb_keymap_key_repeats(mapper->keymap, key+8) && + pressed) { + + timer = { + .it_interval = {.tv_sec = 0, .tv_nsec = seat->rate}, + .it_value = {.tv_sec = 0, .tv_nsec = seat->delay}, + }; + + if (timer.it_value.tv_nsec >= 1000000000) { + timer.it_value.tv_sec += timer.it_value.tv_nsec / 1000000000; + timer.it_value.tv_nsec %= 1000000000; + } + if (timer.it_interval.tv_nsec >= 1000000000) { + timer.it_interval.tv_sec += timer.it_interval.tv_nsec / 1000000000; + timer.it_interval.tv_nsec %= 1000000000; + } + } + + //std::cout<<"repeat_info "<key_repeat_fd, 0, &timer, NULL); + + if (pressed && mapper->keySymbol(key)) + seat->emitKeypress(); + } + }, + .modifiers = [](void *data, wl_keyboard *, uint32_t /*serial*/, + uint32_t mods_depressed, //which key + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group){ + + auto mapper = static_cast(data)->m_keyboard.m_mapper; + + if (mapper) + xkb_state_update_mask(mapper->kstate, + mods_depressed, mods_latched, mods_locked, + 0, 0, group); + + //std::cout<<"modifiers "<(data); + //std::cout<<"repeat_info "<delay = delay * 1000000; + seat->rate = 1000000000 / rate; + } + } +}; + +const wl_pointer_listener Seat::pointer_listener = { + .enter = [](void *data, wl_pointer *pointer, + uint32_t serial, wl_surface *surface, + wl_fixed_t sx, wl_fixed_t sy) + { + // Happens in the case we just destroyed the surface. + if (!surface) return; + + auto seat = static_cast(data); + auto surf = static_cast( + wl_surface_get_user_data(surface)); + + assert(seat && seat->m_pointer.c_ptr() == pointer); + + if (surf){ + seat->m_hovered_surf = surf; + + if (surf->onPoint) + surf->onPoint(SeatListener::enter, 0, seat->m_pointer.set(sx, sy)); + } + }, + .leave = [](void *data, wl_pointer *pointer, + uint32_t serial, wl_surface *surface) + { + auto seat = static_cast(data); + + assert(seat && seat->m_pointer.c_ptr() == pointer); + + if (seat->m_hovered_surf) { + + if (seat->m_hovered_surf->onPoint) + seat->m_hovered_surf->onPoint(SeatListener::leave, 0, seat->m_pointer); + + seat->m_hovered_surf = nullptr; + } + }, + .motion = [](void *data, wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) + { + auto seat = static_cast(data); + + assert(seat && seat->m_pointer.c_ptr() == pointer); + + if (seat->m_hovered_surf && seat->m_hovered_surf->onPoint) + seat->m_hovered_surf->onPoint(SeatListener::motion, time, seat->m_pointer.set(sx, sy)); + }, + .button = [](void *data, wl_pointer *pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) + { + auto seat = static_cast(data); + + assert(seat && seat->m_pointer.c_ptr() == pointer); + + if (seat->m_hovered_surf && seat->m_hovered_surf->onClick) { + + /* count click */ + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + if (state == WL_POINTER_BUTTON_STATE_PRESSED){ + + if (seat->m_last_released_button == button && + now.tv_sec == seat->m_stamp && + time - seat->m_last_time <= 300) + seat->m_count_click++; + else + seat->m_count_click = 1; + + auto& key = seat->m_keyboard; + + seat->m_hovered_surf->onClick((Pointer::BTN)button, true, + seat->m_count_click, + key ? key.modifiers(Keyboard::ModSet::effective) : 0, + seat->m_pointer ); + } + else { + seat->m_last_released_button = button; + seat->m_last_time = time; + seat->m_stamp = now.tv_sec; + seat->m_hovered_surf->onClick((Pointer::BTN)button, false, 0, 0, seat->m_pointer); + } + } + }, + .axis = [](void *data, wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) + { + auto seat = static_cast(data); + + assert(seat && seat->m_pointer.c_ptr() == pointer); + + if (seat->m_hovered_surf && seat->m_hovered_surf->onScroll) + seat->m_hovered_surf->onScroll(time, axis, wl_fixed_to_double(value)); + } +}; + +Seat::~Seat() +{ + if (key_repeat_fd >= 0) + close(key_repeat_fd); +} + +void Seat::bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept +{ + registry(reg, name, 4); + + static const wl_seat_listener seat_listener = { + .capabilities = [](void *data, wl_seat *wl_seat, uint32_t flags){ + + auto seat = static_cast(data); + //std::cout<<"capabilities "<m_pointer.reset(pointer); + if (wl_pointer_add_listener(pointer, &pointer_listener, seat) < 0) + std::cerr<<"Error: не удалось добавить pointer listener"<m_pointer.reset(nullptr); + + if (flags & WL_SEAT_CAPABILITY_KEYBOARD){ + auto kb = wl_seat_get_keyboard(wl_seat); + seat->m_keyboard.reset(kb); + if (wl_keyboard_add_listener(kb, &keyboard_listener, seat) < 0) + std::cerr<<"Error: не удалось добавить keyboard listener"<m_keyboard.reset(nullptr); + + //self->touch.init(app, wl_seat, capabilities); + }, + .name = [](void*, wl_seat*, const char *name){ + std::cout<<"Seat name: "<c_ptr(), surface.c_ptr()) : nullptr) +{} + +} + diff --git a/examples/host/linux/wayland/core.h b/examples/host/linux/wayland/core.h new file mode 100644 index 0000000..3b23759 --- /dev/null +++ b/examples/host/linux/wayland/core.h @@ -0,0 +1,283 @@ +#pragma once + +#include +//#include + +#include +#include +#include +#include + +#include "fractional-scale-v1-client-protocol.h" +#include "viewporter-client-protocol.h" + +namespace WL +{ + +template +class ProxyBase +{ +public: + ~ProxyBase() + { + if (m_ptr) + wl_proxy_marshal_flags(m_ptr, DCode, NULL, + version(), WL_MARSHAL_FLAG_DESTROY); + } + + inline operator bool() const noexcept + {return m_ptr != nullptr;} + + inline uint32_t version() const noexcept + {return wl_proxy_get_version((wl_proxy*)m_ptr);} + +protected: + ProxyBase():m_ptr(nullptr){} + + template + ProxyBase(T* ptr):m_ptr((wl_proxy*)ptr){} + + ProxyBase(ProxyBase const&) = delete; + ProxyBase& operator=(ProxyBase const&) = delete; + + ProxyBase(ProxyBase&& other): + m_ptr(other.m_ptr) + { + other.m_ptr = nullptr; + } + + wl_proxy* m_ptr; +}; + +class ProtocolBase +{ +public: + virtual void bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept = 0; +}; + +template +class Protocol: public ProtocolBase, public ProxyBase +{ +public: + constexpr static const wl_interface* iface(){return I;} + + Protocol() = default; + + Protocol(Protocol&& other) = default; + Protocol& operator=(Protocol&&) = delete; + + void bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept override + { registry(reg, name, version);} + + inline T* c_ptr() const noexcept + { return (T*) this->m_ptr; } + +protected: + void registry(wl_registry *reg, uint32_t name, uint32_t version) noexcept + { this->m_ptr = static_cast(wl_registry_bind(reg, name, I, version)); } +}; + +template +class Proxy: public ProxyBase +{ +public: + Proxy() = default; + explicit Proxy(T* p):ProxyBase(p){} + + Proxy(T* p, const char* msg): ProxyBase(p) + { if (!p) throw std::runtime_error(msg); } + + Proxy(Proxy&& other) = default; + Proxy& operator=(Proxy&& other) + { + ~Proxy(); + this->m_ptr = other.m_ptr; + other.m_ptr = nullptr; + + return *this; + } + + inline void reset(T* ptr) noexcept + { + ~Proxy(); + this->m_ptr = (wl_proxy*)ptr; + } + + inline T* c_ptr() const noexcept + {return (T*) this->m_ptr;} + +protected: + using Base = Proxy; +}; + +class Keyboard: public Proxy +{ +public: + ~Keyboard(); + + enum ModSet {locked, effective, consumed}; + + unsigned modifiers(ModSet group) const; + const char *utf8() const; + uint32_t symbol() const; + +private: + struct KeyMapper; + KeyMapper* m_mapper{nullptr}; + + friend class Seat; +}; + +class Pointer: public Proxy +{ +public: + std::pair toInt() const + { + return {wl_fixed_to_int(m_x), + wl_fixed_to_int(m_y)}; + } + + std::pair toDouble() const + { + return {wl_fixed_to_double(m_x), + wl_fixed_to_double(m_y)}; + } + + bool inBound(int sx, int sy, int sw, int sh) const + { + auto [x, y] = toInt(); + return sx > x && sw < x && sy > y && sh < y; + } + + //from input-event-codes.h + //зависит от платформы, хотя на Linux и FreeBSD одинаковые + enum BTN { + LEFT = 0x110, + RIGHT = 0x111, + MIDDLE = 0x112, + SIDE = 0x113, + EXTRA = 0x114, + FORWARD = 0x115, + BACK = 0x116, + ASK = 0x117 + }; + +private: + wl_fixed_t m_x{0}, m_y{0}; + + const Pointer& set(wl_fixed_t x, wl_fixed_t y) + {m_x = x; m_y = y; return *this;} + + friend class Seat; +}; + +class SeatListener +{ +public: + std::function onFocused; + std::function onKey; + + //virtual void keyUnfocused() = 0; + //virtual void key(Keyboard const&) = 0; + + enum PointerState { enter, leave, motion }; + + std::function onPoint; + std::function onClick; + std::function onScroll; + + // virtual void enter(uint32_t /*serial*/, Pointer const&) = 0; + // virtual void leave() = 0; + // virtual void motion(uint32_t /*time*/, Pointer const&) = 0; + // virtual void click(Pointer::BTN /*button*/ , + // bool /*pressed*/, + // int /*count*/, + // unsigned /*key_mod*/, + // Pointer const&) = 0; + // virtual void scroll(int time, int axis, double value) = 0; + +// protected: +// virtual void keyFocused(bool) = 0; +}; + +class Seat final: public Protocol +{ +public: + ~Seat(); + void bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept override; + +private: + // Поддерживает только XKB на Linux и FreeBSD платформах + // возможно в дальнейшем этот класс нужно будет сделать более гибким + + Keyboard m_keyboard; + SeatListener *m_focused_surf = nullptr; + static const wl_keyboard_listener keyboard_listener; + int key_repeat_fd{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)}; + uint32_t delay {0}; + uint32_t rate {0}; + void emitKeypress() const; + + friend class Display; + + Pointer m_pointer; + SeatListener *m_hovered_surf = nullptr; + static const wl_pointer_listener pointer_listener; + //для вычисления нескольких нажатий одной и той же кнопки мыши + uint32_t m_last_time = 0; + std::time_t m_stamp; + uint32_t m_last_released_button = 0; + int m_count_click = 0; +}; + +using FractionalScaleManager = Protocol; + +class NativeSurface: public Proxy +{ +public: + explicit NativeSurface(wl_compositor *compositor, + const FractionalScaleManager *manager); + + inline void listenerInput(SeatListener &input) + { wl_surface_set_user_data(c_ptr(), &input); } + + inline void commit() + { wl_surface_commit(c_ptr()); } + + std::function onScale; + +protected: + void setAreaOpaque(wl_compositor *compositor, int32_t w, int32_t h) const; + + float m_scale{1}; + +private: + Proxy m_fscale; +}; + +using Viewporter = Protocol; + +class Viewport final: public Proxy +{ +public: + Viewport(const WL::Viewporter *vpr, NativeSurface const &surface); + Viewport() = default; + + void setDestination(int32_t width, int32_t height) + {wp_viewport_set_destination(c_ptr(), width, height);} +}; + +} + + diff --git a/examples/host/linux/wayland/cursor-shape-v1-client-protocol.h b/examples/host/linux/wayland/cursor-shape-v1-client-protocol.h new file mode 100644 index 0000000..72ed2ba --- /dev/null +++ b/examples/host/linux/wayland/cursor-shape-v1-client-protocol.h @@ -0,0 +1,426 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef CURSOR_SHAPE_V1_CLIENT_PROTOCOL_H +#define CURSOR_SHAPE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_cursor_shape_v1 The cursor_shape_v1 protocol + * @section page_ifaces_cursor_shape_v1 Interfaces + * - @subpage page_iface_wp_cursor_shape_manager_v1 - cursor shape manager + * - @subpage page_iface_wp_cursor_shape_device_v1 - cursor shape for a device + * @section page_copyright_cursor_shape_v1 Copyright + *
+ *
+ * Copyright 2018 The Chromium Authors
+ * Copyright 2023 Simon Ser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_pointer; +struct wp_cursor_shape_device_v1; +struct wp_cursor_shape_manager_v1; +struct zwp_tablet_tool_v2; + +#ifndef WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE +#define WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE +/** + * @page page_iface_wp_cursor_shape_manager_v1 wp_cursor_shape_manager_v1 + * @section page_iface_wp_cursor_shape_manager_v1_desc Description + * + * This global offers an alternative, optional way to set cursor images. This + * new way uses enumerated cursors instead of a wl_surface like + * wl_pointer.set_cursor does. + * + * Warning! The protocol described in this file is currently in the testing + * phase. Backward compatible changes may be added together with the + * corresponding interface version bump. Backward incompatible changes can + * only be done by creating a new major version of the extension. + * @section page_iface_wp_cursor_shape_manager_v1_api API + * See @ref iface_wp_cursor_shape_manager_v1. + */ +/** + * @defgroup iface_wp_cursor_shape_manager_v1 The wp_cursor_shape_manager_v1 interface + * + * This global offers an alternative, optional way to set cursor images. This + * new way uses enumerated cursors instead of a wl_surface like + * wl_pointer.set_cursor does. + * + * Warning! The protocol described in this file is currently in the testing + * phase. Backward compatible changes may be added together with the + * corresponding interface version bump. Backward incompatible changes can + * only be done by creating a new major version of the extension. + */ +extern const struct wl_interface wp_cursor_shape_manager_v1_interface; +#endif +#ifndef WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE +#define WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE +/** + * @page page_iface_wp_cursor_shape_device_v1 wp_cursor_shape_device_v1 + * @section page_iface_wp_cursor_shape_device_v1_desc Description + * + * This interface allows clients to set the cursor shape. + * @section page_iface_wp_cursor_shape_device_v1_api API + * See @ref iface_wp_cursor_shape_device_v1. + */ +/** + * @defgroup iface_wp_cursor_shape_device_v1 The wp_cursor_shape_device_v1 interface + * + * This interface allows clients to set the cursor shape. + */ +extern const struct wl_interface wp_cursor_shape_device_v1_interface; +#endif + +#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY 0 +#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER 1 +#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2 2 + + +/** + * @ingroup iface_wp_cursor_shape_manager_v1 + */ +#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_cursor_shape_manager_v1 + */ +#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER_SINCE_VERSION 1 +/** + * @ingroup iface_wp_cursor_shape_manager_v1 + */ +#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2_SINCE_VERSION 1 + +/** @ingroup iface_wp_cursor_shape_manager_v1 */ +static inline void +wp_cursor_shape_manager_v1_set_user_data(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_cursor_shape_manager_v1, user_data); +} + +/** @ingroup iface_wp_cursor_shape_manager_v1 */ +static inline void * +wp_cursor_shape_manager_v1_get_user_data(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_cursor_shape_manager_v1); +} + +static inline uint32_t +wp_cursor_shape_manager_v1_get_version(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1); +} + +/** + * @ingroup iface_wp_cursor_shape_manager_v1 + * + * Destroy the cursor shape manager. + */ +static inline void +wp_cursor_shape_manager_v1_destroy(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1, + WP_CURSOR_SHAPE_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_wp_cursor_shape_manager_v1 + * + * Obtain a wp_cursor_shape_device_v1 for a wl_pointer object. + * + * When the pointer capability is removed from the wl_seat, the + * wp_cursor_shape_device_v1 object becomes inert. + */ +static inline struct wp_cursor_shape_device_v1 * +wp_cursor_shape_manager_v1_get_pointer(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, struct wl_pointer *pointer) +{ + struct wl_proxy *cursor_shape_device; + + cursor_shape_device = wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1, + WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER, &wp_cursor_shape_device_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), 0, NULL, pointer); + + return (struct wp_cursor_shape_device_v1 *) cursor_shape_device; +} + +/** + * @ingroup iface_wp_cursor_shape_manager_v1 + * + * Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object. + * + * When the zwp_tablet_tool_v2 is removed, the wp_cursor_shape_device_v1 + * object becomes inert. + */ +static inline struct wp_cursor_shape_device_v1 * +wp_cursor_shape_manager_v1_get_tablet_tool_v2(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, struct zwp_tablet_tool_v2 *tablet_tool) +{ + struct wl_proxy *cursor_shape_device; + + cursor_shape_device = wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1, + WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2, &wp_cursor_shape_device_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), 0, NULL, tablet_tool); + + return (struct wp_cursor_shape_device_v1 *) cursor_shape_device; +} + +#ifndef WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM +#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM +/** + * @ingroup iface_wp_cursor_shape_device_v1 + * cursor shapes + * + * This enum describes cursor shapes. + * + * The names are taken from the CSS W3C specification: + * https://w3c.github.io/csswg-drafts/css-ui/#cursor + */ +enum wp_cursor_shape_device_v1_shape { + /** + * default cursor + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT = 1, + /** + * a context menu is available for the object under the cursor + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU = 2, + /** + * help is available for the object under the cursor + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP = 3, + /** + * pointer that indicates a link or another interactive element + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER = 4, + /** + * progress indicator + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS = 5, + /** + * program is busy, user should wait + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT = 6, + /** + * a cell or set of cells may be selected + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CELL = 7, + /** + * simple crosshair + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR = 8, + /** + * text may be selected + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT = 9, + /** + * vertical text may be selected + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT = 10, + /** + * drag-and-drop: alias of/shortcut to something is to be created + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS = 11, + /** + * drag-and-drop: something is to be copied + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY = 12, + /** + * drag-and-drop: something is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE = 13, + /** + * drag-and-drop: the dragged item cannot be dropped at the current cursor location + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP = 14, + /** + * drag-and-drop: the requested action will not be carried out + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED = 15, + /** + * drag-and-drop: something can be grabbed + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB = 16, + /** + * drag-and-drop: something is being grabbed + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING = 17, + /** + * resizing: the east border is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE = 18, + /** + * resizing: the north border is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE = 19, + /** + * resizing: the north-east corner is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE = 20, + /** + * resizing: the north-west corner is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE = 21, + /** + * resizing: the south border is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE = 22, + /** + * resizing: the south-east corner is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE = 23, + /** + * resizing: the south-west corner is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE = 24, + /** + * resizing: the west border is to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE = 25, + /** + * resizing: the east and west borders are to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE = 26, + /** + * resizing: the north and south borders are to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE = 27, + /** + * resizing: the north-east and south-west corners are to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE = 28, + /** + * resizing: the north-west and south-east corners are to be moved + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE = 29, + /** + * resizing: that the item/column can be resized horizontally + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE = 30, + /** + * resizing: that the item/row can be resized vertically + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE = 31, + /** + * something can be scrolled in any direction + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL = 32, + /** + * something can be zoomed in + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN = 33, + /** + * something can be zoomed out + */ + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT = 34, +}; +#endif /* WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM */ + +#ifndef WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM +#define WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM +enum wp_cursor_shape_device_v1_error { + /** + * the specified shape value is invalid + */ + WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE = 1, +}; +#endif /* WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM */ + +#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY 0 +#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE 1 + + +/** + * @ingroup iface_wp_cursor_shape_device_v1 + */ +#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_cursor_shape_device_v1 + */ +#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE_SINCE_VERSION 1 + +/** @ingroup iface_wp_cursor_shape_device_v1 */ +static inline void +wp_cursor_shape_device_v1_set_user_data(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_cursor_shape_device_v1, user_data); +} + +/** @ingroup iface_wp_cursor_shape_device_v1 */ +static inline void * +wp_cursor_shape_device_v1_get_user_data(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_cursor_shape_device_v1); +} + +static inline uint32_t +wp_cursor_shape_device_v1_get_version(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1); +} + +/** + * @ingroup iface_wp_cursor_shape_device_v1 + * + * Destroy the cursor shape device. + * + * The device cursor shape remains unchanged. + */ +static inline void +wp_cursor_shape_device_v1_destroy(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_device_v1, + WP_CURSOR_SHAPE_DEVICE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_wp_cursor_shape_device_v1 + * + * Sets the device cursor to the specified shape. The compositor will + * change the cursor image based on the specified shape. + * + * The cursor actually changes only if the input device focus is one of + * the requesting client's surfaces. If any, the previous cursor image + * (surface or shape) is replaced. + * + * The "shape" argument must be a valid enum entry, otherwise the + * invalid_shape protocol error is raised. + * + * This is similar to the wl_pointer.set_cursor and + * zwp_tablet_tool_v2.set_cursor requests, but this request accepts a + * shape instead of contents in the form of a surface. Clients can mix + * set_cursor and set_shape requests. + * + * The serial parameter must match the latest wl_pointer.enter or + * zwp_tablet_tool_v2.proximity_in serial number sent to the client. + * Otherwise the request will be ignored. + */ +static inline void +wp_cursor_shape_device_v1_set_shape(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1, uint32_t serial, uint32_t shape) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_device_v1, + WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1), 0, serial, shape); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/host/linux/wayland/cursor-shape-v1-protocol.c b/examples/host/linux/wayland/cursor-shape-v1-protocol.c new file mode 100644 index 0000000..3c2c1a0 --- /dev/null +++ b/examples/host/linux/wayland/cursor-shape-v1-protocol.c @@ -0,0 +1,75 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright 2018 The Chromium Authors + * Copyright 2023 Simon Ser + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_pointer_interface; +extern const struct wl_interface wp_cursor_shape_device_v1_interface; +extern const struct wl_interface zwp_tablet_tool_v2_interface; + +static const struct wl_interface *cursor_shape_v1_types[] = { + NULL, + NULL, + &wp_cursor_shape_device_v1_interface, + &wl_pointer_interface, + &wp_cursor_shape_device_v1_interface, + &zwp_tablet_tool_v2_interface, +}; + +static const struct wl_message wp_cursor_shape_manager_v1_requests[] = { + { "destroy", "", cursor_shape_v1_types + 0 }, + { "get_pointer", "no", cursor_shape_v1_types + 2 }, + { "get_tablet_tool_v2", "no", cursor_shape_v1_types + 4 }, +}; + +WL_PRIVATE const struct wl_interface wp_cursor_shape_manager_v1_interface = { + "wp_cursor_shape_manager_v1", 1, + 3, wp_cursor_shape_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message wp_cursor_shape_device_v1_requests[] = { + { "destroy", "", cursor_shape_v1_types + 0 }, + { "set_shape", "uu", cursor_shape_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface wp_cursor_shape_device_v1_interface = { + "wp_cursor_shape_device_v1", 1, + 2, wp_cursor_shape_device_v1_requests, + 0, NULL, +}; + diff --git a/examples/host/linux/wayland/display.cpp b/examples/host/linux/wayland/display.cpp new file mode 100644 index 0000000..3848898 --- /dev/null +++ b/examples/host/linux/wayland/display.cpp @@ -0,0 +1,171 @@ +#include "display.h" + +#include + +using namespace WL; + +std::unique_ptr Display::s_instance; + +Display::Display(const char *dpy_name, std::unique_ptr &&protocols) + : m_display(wl_display_connect(dpy_name)) + , m_compositor(nullptr) + , m_surfaces(nullptr) + , isRuning(false) +{ + if (!m_display) + throw std::runtime_error("display with name 'dpy_name' does not exist"); + + static const wl_registry_listener lsr = { + .global = [](void *data, + wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version) + { + auto dpy = static_cast(data); + // std::cerr<<"available interface "<m_compositor = + (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, version); + else + if (auto item = dpy->m_protocols->find(interface)) + item->bind(registry, name, version); + + }, + .global_remove = [](void*, wl_registry*, uint32_t){ + //To do global remove + } + }; + + auto registry = wl_display_get_registry(m_display); + + if (!registry || wl_registry_add_listener(registry, &lsr, this) < 0){ + wl_display_disconnect(m_display); + throw std::runtime_error("add registry listener failed"); + } + + m_protocols = std::move(protocols); + + wl_display_roundtrip(m_display); + wl_registry_destroy(registry); + + if (!m_compositor) { + m_protocols.reset(nullptr); + wl_display_disconnect(m_display); + throw std::runtime_error("wayland compositor not found"); + } + + m_fds[EventT::wayland].fd = wl_display_get_fd(m_display); + m_fds[EventT::wayland].events = POLLIN; + m_fds[EventT::system].fd = -1; +} + +Display::~Display() +{ + if (m_compositor) + wl_proxy_destroy((wl_proxy*) m_compositor); + + m_protocols.reset(nullptr); + wl_display_disconnect(m_display); +} + +void Display::start_event() +{ + if (isRuning) return; + + isRuning = true; + + auto seat = protocol(); + + if (seat){ + m_fds[EventT::system].fd = seat->key_repeat_fd; + m_fds[EventT::system].events = POLLIN; + m_fds[EventT::system].revents = 0; + } + + while (isRuning) { + + while (wl_display_prepare_read(m_display) != 0) { + if (wl_display_dispatch_pending(m_display) < 0) + throw std::runtime_error("failed to dispatch pending Wayland events"); + } + + int ret; + + while ((ret = wl_display_flush(m_display)) < 0) { + if (errno == EINTR) { + continue; + } + + if (errno == EAGAIN) { + struct pollfd fds[1]; + fds[0].fd = m_fds[EventT::wayland].fd; + fds[0].events = POLLOUT; + + do { + ret = poll(fds, 1, -1); + } while (ret < 0 && errno == EINTR); + } + } + + if (ret < 0) { + wl_display_cancel_read(m_display); + throw std::runtime_error("failed to display flush"); + } + + do { + ret = poll(m_fds, EventT::count, -1); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + if (m_fds[0].revents & POLLHUP) + throw std::runtime_error("disconnected from wayland"); + + wl_display_cancel_read(m_display); + throw std::runtime_error("failed to poll():"); + } + + if ((m_fds[0].revents & POLLIN)) { + + if (wl_display_read_events(m_display) < 0) + throw std::runtime_error("failed to read Wayland events"); + } + else + wl_display_cancel_read(m_display); + + if (wl_display_dispatch_pending(m_display) < 0) + throw std::runtime_error("failed to dispatch pending Wayland events"); + + if (m_fds[1].revents & POLLIN) { + uint64_t repeats; + if (read(m_fds[1].fd, &repeats, sizeof(repeats)) == 8) { + for (uint64_t i = 0; i < repeats; i++) + seat->emitKeypress(); + } + } + + auto node = m_surfaces; + while (node){ + if (node->draw_f){ + auto cb = std::move(node->draw_f); + cb(); + } + + node = node->next; + } + } +} + +void Display::add(Node &node) +{ + if(!m_surfaces){ + m_surfaces = &node; + m_surfaces->prev = m_surfaces; + } + else { + auto last = m_surfaces->prev; + m_surfaces->prev = &node; + node.prev = last; + last->next = &node; + } +} diff --git a/examples/host/linux/wayland/display.h b/examples/host/linux/wayland/display.h new file mode 100644 index 0000000..ac2e551 --- /dev/null +++ b/examples/host/linux/wayland/display.h @@ -0,0 +1,244 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include + +#include +#include +// #include + +#include +#include +#include +#include + +#include "core.h" + +namespace WL { + +class ProtocolContainer +{ +public: + virtual ~ProtocolContainer() = default; + virtual ProtocolBase* find(const char*) noexcept = 0; + virtual ProtocolBase* find(const wl_interface*) noexcept = 0; +}; + +template +class ProtocolTuple final: public ProtocolContainer +{ + std::tuple m_gb; + + template + void tuple_find(F &&f) noexcept + { + std::apply([&f](auto &...e) { + (std::forward(f)(e, e.iface()) || ...); + }, m_gb); + } + +public: + ProtocolBase* find(const char* str) noexcept override + { + ProtocolBase* result = nullptr; + tuple_find([str, &result](ProtocolBase& gb, + const wl_interface* ifc){ + if (strcmp(str, ifc->name) == 0){ + result = &gb; return true; + } + return false; + }); + + return result; + } + + ProtocolBase* find(const wl_interface* iface) noexcept override + { + ProtocolBase* result = nullptr; + tuple_find([iface, &result](ProtocolBase& gb, + const wl_interface* ifc){ + if (iface == ifc){ + result = &gb; return true; + } + return false; + }); + + return result; + } + + virtual ~ProtocolTuple() + { + std::cerr<<"~GlobalTuple"< + static Display& init(const char *name = nullptr) + { + assert(!s_instance); + + s_instance = std::make_unique(name, + std::make_unique>()); + return *s_instance.get(); + } + + inline static Display& instance() noexcept + { + assert(s_instance); + return *s_instance.get(); + } + + Display(Display const&) = delete; + Display& operator=(Display const&) = delete; + Display(Display&& other) = default; + Display& operator=(Display&&) = delete; + + ~Display(); + + void start_event(); + void stop(){isRuning = false;} + + wl_display* native() const {return m_display;} + //wl_compositor* compositor() const {return m_compositor;} + + template + const G* protocol() const + { + if (auto search = m_protocols->find(G::iface())) + return static_cast(search); + + return nullptr; + } + + template + const G& ensureProtocol() const + { + if (auto search = m_protocols->find(G::iface())) + return *static_cast(search); + + std::string err("protocol not find: "); + throw std::runtime_error(err + G::iface()->name); + } + + Display(const char *name, std::unique_ptr &&protocols); + +private: + wl_display* m_display; + wl_compositor* m_compositor; + + std::unique_ptr m_protocols; + + enum EventT + {wayland, system, count}; + + pollfd m_fds[EventT::count]; + + using DrawFunc = std::function; + struct Node + { + DrawFunc draw_f; + Node *next{nullptr}; + Node *prev{nullptr}; + }; + + //std::vector m_surfaces; + Node *m_surfaces; + void add(Node &node); + + bool isRuning; + static std::unique_ptr s_instance; + + template + friend class Surface; +}; + +template +class Surface : public NativeSurface +{ + using Buffer = std::unique_ptr; + + static inline CTX *s_ctx = nullptr; + static inline void *s_buf = nullptr; + + Display::Node m_node; + +public: + Surface(): + NativeSurface(Display::instance().m_compositor, + Display::instance().protocol()) + {} + + ~Surface() + { + s_ctx->destroy(*m_buffer.get()); + + //если окно последнее уничтожаем контекст + if (m_node.prev == &m_node){ + Display::instance().m_surfaces = nullptr; + delete s_ctx; + s_ctx = nullptr; + } + else { + m_node.prev->next = m_node.next; + } + } + + void refresh() + { + if (mapped()) + m_node.draw_f = [this](){ + if (s_buf != m_buffer.get()){ + s_ctx->makeCurrent(*m_buffer.get()); + s_buf = m_buffer.get(); + } + draw(m_scale); + s_ctx->flush(*m_buffer.get()); + }; + } + +protected: + Buffer m_buffer; + + CTX& context() const + { + //Context динамически создается для предсказуемого удаления т.к. он static + if (!s_ctx) s_ctx = new CTX; + return *s_ctx; + } + + bool mapped() const {return m_node.prev != nullptr;} + + bool makeBuffer(unsigned &width, unsigned &height) + { + auto scale_width = width * m_scale; + auto scale_height = height * m_scale; + auto buf = std::make_unique( + context(), *this, scale_width, scale_height); + + if (buf->valid()){ + Display::instance().add(m_node); + width = scale_width; + height = scale_height; + s_ctx->makeCurrent(*buf.get()); + s_buf = buf.get(); + m_buffer = std::move(buf); + return true; + } + + return false; + } + + void setAreaOpaque(int32_t w, int32_t h) const + {NativeSurface::setAreaOpaque(Display::instance().m_compositor, w, h);} + + virtual void draw(float) = 0; +}; + +} + +#endif // DISPLAY_H diff --git a/examples/host/linux/wayland/fractional-scale-v1-client-protocol.h b/examples/host/linux/wayland/fractional-scale-v1-client-protocol.h new file mode 100644 index 0000000..8df7558 --- /dev/null +++ b/examples/host/linux/wayland/fractional-scale-v1-client-protocol.h @@ -0,0 +1,264 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H +#define FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_fractional_scale_v1 The fractional_scale_v1 protocol + * Protocol for requesting fractional surface scales + * + * @section page_desc_fractional_scale_v1 Description + * + * This protocol allows a compositor to suggest for surfaces to render at + * fractional scales. + * + * A client can submit scaled content by utilizing wp_viewport. This is done by + * creating a wp_viewport object for the surface and setting the destination + * rectangle to the surface size before the scale factor is applied. + * + * The buffer size is calculated by multiplying the surface size by the + * intended scale. + * + * The wl_surface buffer scale should remain set to 1. + * + * If a surface has a surface-local size of 100 px by 50 px and wishes to + * submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should + * be used and the wp_viewport destination rectangle should be 100 px by 50 px. + * + * For toplevel surfaces, the size is rounded halfway away from zero. The + * rounding algorithm for subsurface position and size is not defined. + * + * @section page_ifaces_fractional_scale_v1 Interfaces + * - @subpage page_iface_wp_fractional_scale_manager_v1 - fractional surface scale information + * - @subpage page_iface_wp_fractional_scale_v1 - fractional scale interface to a wl_surface + * @section page_copyright_fractional_scale_v1 Copyright + *
+ *
+ * Copyright © 2022 Kenny Levinsen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_surface; +struct wp_fractional_scale_manager_v1; +struct wp_fractional_scale_v1; + +#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE +#define WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE +/** + * @page page_iface_wp_fractional_scale_manager_v1 wp_fractional_scale_manager_v1 + * @section page_iface_wp_fractional_scale_manager_v1_desc Description + * + * A global interface for requesting surfaces to use fractional scales. + * @section page_iface_wp_fractional_scale_manager_v1_api API + * See @ref iface_wp_fractional_scale_manager_v1. + */ +/** + * @defgroup iface_wp_fractional_scale_manager_v1 The wp_fractional_scale_manager_v1 interface + * + * A global interface for requesting surfaces to use fractional scales. + */ +extern const struct wl_interface wp_fractional_scale_manager_v1_interface; +#endif +#ifndef WP_FRACTIONAL_SCALE_V1_INTERFACE +#define WP_FRACTIONAL_SCALE_V1_INTERFACE +/** + * @page page_iface_wp_fractional_scale_v1 wp_fractional_scale_v1 + * @section page_iface_wp_fractional_scale_v1_desc Description + * + * An additional interface to a wl_surface object which allows the compositor + * to inform the client of the preferred scale. + * @section page_iface_wp_fractional_scale_v1_api API + * See @ref iface_wp_fractional_scale_v1. + */ +/** + * @defgroup iface_wp_fractional_scale_v1 The wp_fractional_scale_v1 interface + * + * An additional interface to a wl_surface object which allows the compositor + * to inform the client of the preferred scale. + */ +extern const struct wl_interface wp_fractional_scale_v1_interface; +#endif + +#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM +#define WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM +enum wp_fractional_scale_manager_v1_error { + /** + * the surface already has a fractional_scale object associated + */ + WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS = 0, +}; +#endif /* WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM */ + +#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY 0 +#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE 1 + + +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + */ +#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + */ +#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE_SINCE_VERSION 1 + +/** @ingroup iface_wp_fractional_scale_manager_v1 */ +static inline void +wp_fractional_scale_manager_v1_set_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1, user_data); +} + +/** @ingroup iface_wp_fractional_scale_manager_v1 */ +static inline void * +wp_fractional_scale_manager_v1_get_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1); +} + +static inline uint32_t +wp_fractional_scale_manager_v1_get_version(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1); +} + +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + * + * Informs the server that the client will not be using this protocol + * object anymore. This does not affect any other objects, + * wp_fractional_scale_v1 objects included. + */ +static inline void +wp_fractional_scale_manager_v1_destroy(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_manager_v1, + WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + * + * Create an add-on object for the the wl_surface to let the compositor + * request fractional scales. If the given wl_surface already has a + * wp_fractional_scale_v1 object associated, the fractional_scale_exists + * protocol error is raised. + */ +static inline struct wp_fractional_scale_v1 * +wp_fractional_scale_manager_v1_get_fractional_scale(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_manager_v1, + WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE, &wp_fractional_scale_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1), 0, NULL, surface); + + return (struct wp_fractional_scale_v1 *) id; +} + +/** + * @ingroup iface_wp_fractional_scale_v1 + * @struct wp_fractional_scale_v1_listener + */ +struct wp_fractional_scale_v1_listener { + /** + * notify of new preferred scale + * + * Notification of a new preferred scale for this surface that + * the compositor suggests that the client should use. + * + * The sent scale is the numerator of a fraction with a denominator + * of 120. + * @param scale the new preferred scale + */ + void (*preferred_scale)(void *data, + struct wp_fractional_scale_v1 *wp_fractional_scale_v1, + uint32_t scale); +}; + +/** + * @ingroup iface_wp_fractional_scale_v1 + */ +static inline int +wp_fractional_scale_v1_add_listener(struct wp_fractional_scale_v1 *wp_fractional_scale_v1, + const struct wp_fractional_scale_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) wp_fractional_scale_v1, + (void (**)(void)) listener, data); +} + +#define WP_FRACTIONAL_SCALE_V1_DESTROY 0 + +/** + * @ingroup iface_wp_fractional_scale_v1 + */ +#define WP_FRACTIONAL_SCALE_V1_PREFERRED_SCALE_SINCE_VERSION 1 + +/** + * @ingroup iface_wp_fractional_scale_v1 + */ +#define WP_FRACTIONAL_SCALE_V1_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_wp_fractional_scale_v1 */ +static inline void +wp_fractional_scale_v1_set_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_v1, user_data); +} + +/** @ingroup iface_wp_fractional_scale_v1 */ +static inline void * +wp_fractional_scale_v1_get_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_v1); +} + +static inline uint32_t +wp_fractional_scale_v1_get_version(struct wp_fractional_scale_v1 *wp_fractional_scale_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1); +} + +/** + * @ingroup iface_wp_fractional_scale_v1 + * + * Destroy the fractional scale object. When this object is destroyed, + * preferred_scale events will no longer be sent. + */ +static inline void +wp_fractional_scale_v1_destroy(struct wp_fractional_scale_v1 *wp_fractional_scale_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_v1, + WP_FRACTIONAL_SCALE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1), WL_MARSHAL_FLAG_DESTROY); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/host/linux/wayland/fractional-scale-v1-protocol.c b/examples/host/linux/wayland/fractional-scale-v1-protocol.c new file mode 100644 index 0000000..f847c1e --- /dev/null +++ b/examples/host/linux/wayland/fractional-scale-v1-protocol.c @@ -0,0 +1,74 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright © 2022 Kenny Levinsen + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wp_fractional_scale_v1_interface; + +static const struct wl_interface *fractional_scale_v1_types[] = { + NULL, + &wp_fractional_scale_v1_interface, + &wl_surface_interface, +}; + +static const struct wl_message wp_fractional_scale_manager_v1_requests[] = { + { "destroy", "", fractional_scale_v1_types + 0 }, + { "get_fractional_scale", "no", fractional_scale_v1_types + 1 }, +}; + +WL_PRIVATE const struct wl_interface wp_fractional_scale_manager_v1_interface = { + "wp_fractional_scale_manager_v1", 1, + 2, wp_fractional_scale_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message wp_fractional_scale_v1_requests[] = { + { "destroy", "", fractional_scale_v1_types + 0 }, +}; + +static const struct wl_message wp_fractional_scale_v1_events[] = { + { "preferred_scale", "u", fractional_scale_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface wp_fractional_scale_v1_interface = { + "wp_fractional_scale_v1", 1, + 1, wp_fractional_scale_v1_requests, + 1, wp_fractional_scale_v1_events, +}; + diff --git a/examples/host/linux/wayland/tablet-unstable-v2-client-protocol.h b/examples/host/linux/wayland/tablet-unstable-v2-client-protocol.h new file mode 100644 index 0000000..38629f2 --- /dev/null +++ b/examples/host/linux/wayland/tablet-unstable-v2-client-protocol.h @@ -0,0 +1,2252 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef TABLET_UNSTABLE_V2_CLIENT_PROTOCOL_H +#define TABLET_UNSTABLE_V2_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_tablet_unstable_v2 The tablet_unstable_v2 protocol + * Wayland protocol for graphics tablets + * + * @section page_desc_tablet_unstable_v2 Description + * + * This description provides a high-level overview of the interplay between + * the interfaces defined this protocol. For details, see the protocol + * specification. + * + * More than one tablet may exist, and device-specifics matter. Tablets are + * not represented by a single virtual device like wl_pointer. A client + * binds to the tablet manager object which is just a proxy object. From + * that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat) + * and that returns the actual interface that has all the tablets. With + * this indirection, we can avoid merging wp_tablet into the actual Wayland + * protocol, a long-term benefit. + * + * The wp_tablet_seat sends a "tablet added" event for each tablet + * connected. That event is followed by descriptive events about the + * hardware; currently that includes events for name, vid/pid and + * a wp_tablet.path event that describes a local path. This path can be + * used to uniquely identify a tablet or get more information through + * libwacom. Emulated or nested tablets can skip any of those, e.g. a + * virtual tablet may not have a vid/pid. The sequence of descriptive + * events is terminated by a wp_tablet.done event to signal that a client + * may now finalize any initialization for that tablet. + * + * Events from tablets require a tool in proximity. Tools are also managed + * by the tablet seat; a "tool added" event is sent whenever a tool is new + * to the compositor. That event is followed by a number of descriptive + * events about the hardware; currently that includes capabilities, + * hardware id and serial number, and tool type. Similar to the tablet + * interface, a wp_tablet_tool.done event is sent to terminate that initial + * sequence. + * + * Any event from a tool happens on the wp_tablet_tool interface. When the + * tool gets into proximity of the tablet, a proximity_in event is sent on + * the wp_tablet_tool interface, listing the tablet and the surface. That + * event is followed by a motion event with the coordinates. After that, + * it's the usual motion, axis, button, etc. events. The protocol's + * serialisation means events are grouped by wp_tablet_tool.frame events. + * + * Two special events (that don't exist in X) are down and up. They signal + * "tip touching the surface". For tablets without real proximity + * detection, the sequence is: proximity_in, motion, down, frame. + * + * When the tool leaves proximity, a proximity_out event is sent. If any + * button is still down, a button release event is sent before this + * proximity event. These button events are sent in the same frame as the + * proximity event to signal to the client that the buttons were held when + * the tool left proximity. + * + * If the tool moves out of the surface but stays in proximity (i.e. + * between windows), compositor-specific grab policies apply. This usually + * means that the proximity-out is delayed until all buttons are released. + * + * Moving a tool physically from one tablet to the other has no real effect + * on the protocol, since we already have the tool object from the "tool + * added" event. All the information is already there and the proximity + * events on both tablets are all a client needs to reconstruct what + * happened. + * + * Some extra axes are normalized, i.e. the client knows the range as + * specified in the protocol (e.g. [0, 65535]), the granularity however is + * unknown. The current normalized axes are pressure, distance, and slider. + * + * Other extra axes are in physical units as specified in the protocol. + * The current extra axes with physical units are tilt, rotation and + * wheel rotation. + * + * Since tablets work independently of the pointer controlled by the mouse, + * the focus handling is independent too and controlled by proximity. + * The wp_tablet_tool.set_cursor request sets a tool-specific cursor. + * This cursor surface may be the same as the mouse cursor, and it may be + * the same across tools but it is possible to be more fine-grained. For + * example, a client may set different cursors for the pen and eraser. + * + * Tools are generally independent of tablets and it is + * compositor-specific policy when a tool can be removed. Common approaches + * will likely include some form of removing a tool when all tablets the + * tool was used on are removed. + * + * Disclaimer: This protocol extension has been marked stable. This copy is + * no longer used and only retained for backwards compatibility. The + * canonical version can be found in the stable/ directory. + * + * @section page_ifaces_tablet_unstable_v2 Interfaces + * - @subpage page_iface_zwp_tablet_manager_v2 - controller object for graphic tablet devices + * - @subpage page_iface_zwp_tablet_seat_v2 - controller object for graphic tablet devices of a seat + * - @subpage page_iface_zwp_tablet_tool_v2 - a physical tablet tool + * - @subpage page_iface_zwp_tablet_v2 - graphics tablet device + * - @subpage page_iface_zwp_tablet_pad_ring_v2 - pad ring + * - @subpage page_iface_zwp_tablet_pad_strip_v2 - pad strip + * - @subpage page_iface_zwp_tablet_pad_group_v2 - a set of buttons, rings and strips + * - @subpage page_iface_zwp_tablet_pad_v2 - a set of buttons, rings and strips + * @section page_copyright_tablet_unstable_v2 Copyright + *
+ *
+ * Copyright 2014 © Stephen "Lyude" Chandler Paul
+ * Copyright 2015-2016 © Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * 
+ */ +struct wl_seat; +struct wl_surface; +struct zwp_tablet_manager_v2; +struct zwp_tablet_pad_group_v2; +struct zwp_tablet_pad_ring_v2; +struct zwp_tablet_pad_strip_v2; +struct zwp_tablet_pad_v2; +struct zwp_tablet_seat_v2; +struct zwp_tablet_tool_v2; +struct zwp_tablet_v2; + +#ifndef ZWP_TABLET_MANAGER_V2_INTERFACE +#define ZWP_TABLET_MANAGER_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_manager_v2 zwp_tablet_manager_v2 + * @section page_iface_zwp_tablet_manager_v2_desc Description + * + * An object that provides access to the graphics tablets available on this + * system. All tablets are associated with a seat, to get access to the + * actual tablets, use wp_tablet_manager.get_tablet_seat. + * @section page_iface_zwp_tablet_manager_v2_api API + * See @ref iface_zwp_tablet_manager_v2. + */ +/** + * @defgroup iface_zwp_tablet_manager_v2 The zwp_tablet_manager_v2 interface + * + * An object that provides access to the graphics tablets available on this + * system. All tablets are associated with a seat, to get access to the + * actual tablets, use wp_tablet_manager.get_tablet_seat. + */ +extern const struct wl_interface zwp_tablet_manager_v2_interface; +#endif +#ifndef ZWP_TABLET_SEAT_V2_INTERFACE +#define ZWP_TABLET_SEAT_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_seat_v2 zwp_tablet_seat_v2 + * @section page_iface_zwp_tablet_seat_v2_desc Description + * + * An object that provides access to the graphics tablets available on this + * seat. After binding to this interface, the compositor sends a set of + * wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events. + * @section page_iface_zwp_tablet_seat_v2_api API + * See @ref iface_zwp_tablet_seat_v2. + */ +/** + * @defgroup iface_zwp_tablet_seat_v2 The zwp_tablet_seat_v2 interface + * + * An object that provides access to the graphics tablets available on this + * seat. After binding to this interface, the compositor sends a set of + * wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events. + */ +extern const struct wl_interface zwp_tablet_seat_v2_interface; +#endif +#ifndef ZWP_TABLET_TOOL_V2_INTERFACE +#define ZWP_TABLET_TOOL_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_tool_v2 zwp_tablet_tool_v2 + * @section page_iface_zwp_tablet_tool_v2_desc Description + * + * An object that represents a physical tool that has been, or is + * currently in use with a tablet in this seat. Each wp_tablet_tool + * object stays valid until the client destroys it; the compositor + * reuses the wp_tablet_tool object to indicate that the object's + * respective physical tool has come into proximity of a tablet again. + * + * A wp_tablet_tool object's relation to a physical tool depends on the + * tablet's ability to report serial numbers. If the tablet supports + * this capability, then the object represents a specific physical tool + * and can be identified even when used on multiple tablets. + * + * A tablet tool has a number of static characteristics, e.g. tool type, + * hardware_serial and capabilities. These capabilities are sent in an + * event sequence after the wp_tablet_seat.tool_added event before any + * actual events from this tool. This initial event sequence is + * terminated by a wp_tablet_tool.done event. + * + * Tablet tool events are grouped by wp_tablet_tool.frame events. + * Any events received before a wp_tablet_tool.frame event should be + * considered part of the same hardware state change. + * @section page_iface_zwp_tablet_tool_v2_api API + * See @ref iface_zwp_tablet_tool_v2. + */ +/** + * @defgroup iface_zwp_tablet_tool_v2 The zwp_tablet_tool_v2 interface + * + * An object that represents a physical tool that has been, or is + * currently in use with a tablet in this seat. Each wp_tablet_tool + * object stays valid until the client destroys it; the compositor + * reuses the wp_tablet_tool object to indicate that the object's + * respective physical tool has come into proximity of a tablet again. + * + * A wp_tablet_tool object's relation to a physical tool depends on the + * tablet's ability to report serial numbers. If the tablet supports + * this capability, then the object represents a specific physical tool + * and can be identified even when used on multiple tablets. + * + * A tablet tool has a number of static characteristics, e.g. tool type, + * hardware_serial and capabilities. These capabilities are sent in an + * event sequence after the wp_tablet_seat.tool_added event before any + * actual events from this tool. This initial event sequence is + * terminated by a wp_tablet_tool.done event. + * + * Tablet tool events are grouped by wp_tablet_tool.frame events. + * Any events received before a wp_tablet_tool.frame event should be + * considered part of the same hardware state change. + */ +extern const struct wl_interface zwp_tablet_tool_v2_interface; +#endif +#ifndef ZWP_TABLET_V2_INTERFACE +#define ZWP_TABLET_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_v2 zwp_tablet_v2 + * @section page_iface_zwp_tablet_v2_desc Description + * + * The wp_tablet interface represents one graphics tablet device. The + * tablet interface itself does not generate events; all events are + * generated by wp_tablet_tool objects when in proximity above a tablet. + * + * A tablet has a number of static characteristics, e.g. device name and + * pid/vid. These capabilities are sent in an event sequence after the + * wp_tablet_seat.tablet_added event. This initial event sequence is + * terminated by a wp_tablet.done event. + * @section page_iface_zwp_tablet_v2_api API + * See @ref iface_zwp_tablet_v2. + */ +/** + * @defgroup iface_zwp_tablet_v2 The zwp_tablet_v2 interface + * + * The wp_tablet interface represents one graphics tablet device. The + * tablet interface itself does not generate events; all events are + * generated by wp_tablet_tool objects when in proximity above a tablet. + * + * A tablet has a number of static characteristics, e.g. device name and + * pid/vid. These capabilities are sent in an event sequence after the + * wp_tablet_seat.tablet_added event. This initial event sequence is + * terminated by a wp_tablet.done event. + */ +extern const struct wl_interface zwp_tablet_v2_interface; +#endif +#ifndef ZWP_TABLET_PAD_RING_V2_INTERFACE +#define ZWP_TABLET_PAD_RING_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_pad_ring_v2 zwp_tablet_pad_ring_v2 + * @section page_iface_zwp_tablet_pad_ring_v2_desc Description + * + * A circular interaction area, such as the touch ring on the Wacom Intuos + * Pro series tablets. + * + * Events on a ring are logically grouped by the wl_tablet_pad_ring.frame + * event. + * @section page_iface_zwp_tablet_pad_ring_v2_api API + * See @ref iface_zwp_tablet_pad_ring_v2. + */ +/** + * @defgroup iface_zwp_tablet_pad_ring_v2 The zwp_tablet_pad_ring_v2 interface + * + * A circular interaction area, such as the touch ring on the Wacom Intuos + * Pro series tablets. + * + * Events on a ring are logically grouped by the wl_tablet_pad_ring.frame + * event. + */ +extern const struct wl_interface zwp_tablet_pad_ring_v2_interface; +#endif +#ifndef ZWP_TABLET_PAD_STRIP_V2_INTERFACE +#define ZWP_TABLET_PAD_STRIP_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_pad_strip_v2 zwp_tablet_pad_strip_v2 + * @section page_iface_zwp_tablet_pad_strip_v2_desc Description + * + * A linear interaction area, such as the strips found in Wacom Cintiq + * models. + * + * Events on a strip are logically grouped by the wl_tablet_pad_strip.frame + * event. + * @section page_iface_zwp_tablet_pad_strip_v2_api API + * See @ref iface_zwp_tablet_pad_strip_v2. + */ +/** + * @defgroup iface_zwp_tablet_pad_strip_v2 The zwp_tablet_pad_strip_v2 interface + * + * A linear interaction area, such as the strips found in Wacom Cintiq + * models. + * + * Events on a strip are logically grouped by the wl_tablet_pad_strip.frame + * event. + */ +extern const struct wl_interface zwp_tablet_pad_strip_v2_interface; +#endif +#ifndef ZWP_TABLET_PAD_GROUP_V2_INTERFACE +#define ZWP_TABLET_PAD_GROUP_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_pad_group_v2 zwp_tablet_pad_group_v2 + * @section page_iface_zwp_tablet_pad_group_v2_desc Description + * + * A pad group describes a distinct (sub)set of buttons, rings and strips + * present in the tablet. The criteria of this grouping is usually positional, + * eg. if a tablet has buttons on the left and right side, 2 groups will be + * presented. The physical arrangement of groups is undisclosed and may + * change on the fly. + * + * Pad groups will announce their features during pad initialization. Between + * the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the + * pad group will announce the buttons, rings and strips contained in it, + * plus the number of supported modes. + * + * Modes are a mechanism to allow multiple groups of actions for every element + * in the pad group. The number of groups and available modes in each is + * persistent across device plugs. The current mode is user-switchable, it + * will be announced through the wp_tablet_pad_group.mode_switch event both + * whenever it is switched, and after wp_tablet_pad.enter. + * + * The current mode logically applies to all elements in the pad group, + * although it is at clients' discretion whether to actually perform different + * actions, and/or issue the respective .set_feedback requests to notify the + * compositor. See the wp_tablet_pad_group.mode_switch event for more details. + * @section page_iface_zwp_tablet_pad_group_v2_api API + * See @ref iface_zwp_tablet_pad_group_v2. + */ +/** + * @defgroup iface_zwp_tablet_pad_group_v2 The zwp_tablet_pad_group_v2 interface + * + * A pad group describes a distinct (sub)set of buttons, rings and strips + * present in the tablet. The criteria of this grouping is usually positional, + * eg. if a tablet has buttons on the left and right side, 2 groups will be + * presented. The physical arrangement of groups is undisclosed and may + * change on the fly. + * + * Pad groups will announce their features during pad initialization. Between + * the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the + * pad group will announce the buttons, rings and strips contained in it, + * plus the number of supported modes. + * + * Modes are a mechanism to allow multiple groups of actions for every element + * in the pad group. The number of groups and available modes in each is + * persistent across device plugs. The current mode is user-switchable, it + * will be announced through the wp_tablet_pad_group.mode_switch event both + * whenever it is switched, and after wp_tablet_pad.enter. + * + * The current mode logically applies to all elements in the pad group, + * although it is at clients' discretion whether to actually perform different + * actions, and/or issue the respective .set_feedback requests to notify the + * compositor. See the wp_tablet_pad_group.mode_switch event for more details. + */ +extern const struct wl_interface zwp_tablet_pad_group_v2_interface; +#endif +#ifndef ZWP_TABLET_PAD_V2_INTERFACE +#define ZWP_TABLET_PAD_V2_INTERFACE +/** + * @page page_iface_zwp_tablet_pad_v2 zwp_tablet_pad_v2 + * @section page_iface_zwp_tablet_pad_v2_desc Description + * + * A pad device is a set of buttons, rings and strips + * usually physically present on the tablet device itself. Some + * exceptions exist where the pad device is physically detached, e.g. the + * Wacom ExpressKey Remote. + * + * Pad devices have no axes that control the cursor and are generally + * auxiliary devices to the tool devices used on the tablet surface. + * + * A pad device has a number of static characteristics, e.g. the number + * of rings. These capabilities are sent in an event sequence after the + * wp_tablet_seat.pad_added event before any actual events from this pad. + * This initial event sequence is terminated by a wp_tablet_pad.done + * event. + * + * All pad features (buttons, rings and strips) are logically divided into + * groups and all pads have at least one group. The available groups are + * notified through the wp_tablet_pad.group event; the compositor will + * emit one event per group before emitting wp_tablet_pad.done. + * + * Groups may have multiple modes. Modes allow clients to map multiple + * actions to a single pad feature. Only one mode can be active per group, + * although different groups may have different active modes. + * @section page_iface_zwp_tablet_pad_v2_api API + * See @ref iface_zwp_tablet_pad_v2. + */ +/** + * @defgroup iface_zwp_tablet_pad_v2 The zwp_tablet_pad_v2 interface + * + * A pad device is a set of buttons, rings and strips + * usually physically present on the tablet device itself. Some + * exceptions exist where the pad device is physically detached, e.g. the + * Wacom ExpressKey Remote. + * + * Pad devices have no axes that control the cursor and are generally + * auxiliary devices to the tool devices used on the tablet surface. + * + * A pad device has a number of static characteristics, e.g. the number + * of rings. These capabilities are sent in an event sequence after the + * wp_tablet_seat.pad_added event before any actual events from this pad. + * This initial event sequence is terminated by a wp_tablet_pad.done + * event. + * + * All pad features (buttons, rings and strips) are logically divided into + * groups and all pads have at least one group. The available groups are + * notified through the wp_tablet_pad.group event; the compositor will + * emit one event per group before emitting wp_tablet_pad.done. + * + * Groups may have multiple modes. Modes allow clients to map multiple + * actions to a single pad feature. Only one mode can be active per group, + * although different groups may have different active modes. + */ +extern const struct wl_interface zwp_tablet_pad_v2_interface; +#endif + +#define ZWP_TABLET_MANAGER_V2_GET_TABLET_SEAT 0 +#define ZWP_TABLET_MANAGER_V2_DESTROY 1 + + +/** + * @ingroup iface_zwp_tablet_manager_v2 + */ +#define ZWP_TABLET_MANAGER_V2_GET_TABLET_SEAT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_manager_v2 + */ +#define ZWP_TABLET_MANAGER_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_manager_v2 */ +static inline void +zwp_tablet_manager_v2_set_user_data(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_manager_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_manager_v2 */ +static inline void * +zwp_tablet_manager_v2_get_user_data(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_manager_v2); +} + +static inline uint32_t +zwp_tablet_manager_v2_get_version(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_manager_v2); +} + +/** + * @ingroup iface_zwp_tablet_manager_v2 + * + * Get the wp_tablet_seat object for the given seat. This object + * provides access to all graphics tablets in this seat. + */ +static inline struct zwp_tablet_seat_v2 * +zwp_tablet_manager_v2_get_tablet_seat(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2, struct wl_seat *seat) +{ + struct wl_proxy *tablet_seat; + + tablet_seat = wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_manager_v2, + ZWP_TABLET_MANAGER_V2_GET_TABLET_SEAT, &zwp_tablet_seat_v2_interface, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_manager_v2), 0, NULL, seat); + + return (struct zwp_tablet_seat_v2 *) tablet_seat; +} + +/** + * @ingroup iface_zwp_tablet_manager_v2 + * + * Destroy the wp_tablet_manager object. Objects created from this + * object are unaffected and should be destroyed separately. + */ +static inline void +zwp_tablet_manager_v2_destroy(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_manager_v2, + ZWP_TABLET_MANAGER_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_manager_v2), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_zwp_tablet_seat_v2 + * @struct zwp_tablet_seat_v2_listener + */ +struct zwp_tablet_seat_v2_listener { + /** + * new device notification + * + * This event is sent whenever a new tablet becomes available on + * this seat. This event only provides the object id of the tablet, + * any static information about the tablet (device name, vid/pid, + * etc.) is sent through the wp_tablet interface. + * @param id the newly added graphics tablet + */ + void (*tablet_added)(void *data, + struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, + struct zwp_tablet_v2 *id); + /** + * a new tool has been used with a tablet + * + * This event is sent whenever a tool that has not previously + * been used with a tablet comes into use. This event only provides + * the object id of the tool; any static information about the tool + * (capabilities, type, etc.) is sent through the wp_tablet_tool + * interface. + * @param id the newly added tablet tool + */ + void (*tool_added)(void *data, + struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, + struct zwp_tablet_tool_v2 *id); + /** + * new pad notification + * + * This event is sent whenever a new pad is known to the system. + * Typically, pads are physically attached to tablets and a + * pad_added event is sent immediately after the + * wp_tablet_seat.tablet_added. However, some standalone pad + * devices logically attach to tablets at runtime, and the client + * must wait for wp_tablet_pad.enter to know the tablet a pad is + * attached to. + * + * This event only provides the object id of the pad. All further + * features (buttons, strips, rings) are sent through the + * wp_tablet_pad interface. + * @param id the newly added pad + */ + void (*pad_added)(void *data, + struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, + struct zwp_tablet_pad_v2 *id); +}; + +/** + * @ingroup iface_zwp_tablet_seat_v2 + */ +static inline int +zwp_tablet_seat_v2_add_listener(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, + const struct zwp_tablet_seat_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_seat_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_SEAT_V2_DESTROY 0 + +/** + * @ingroup iface_zwp_tablet_seat_v2 + */ +#define ZWP_TABLET_SEAT_V2_TABLET_ADDED_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_seat_v2 + */ +#define ZWP_TABLET_SEAT_V2_TOOL_ADDED_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_seat_v2 + */ +#define ZWP_TABLET_SEAT_V2_PAD_ADDED_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_seat_v2 + */ +#define ZWP_TABLET_SEAT_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_seat_v2 */ +static inline void +zwp_tablet_seat_v2_set_user_data(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_seat_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_seat_v2 */ +static inline void * +zwp_tablet_seat_v2_get_user_data(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_seat_v2); +} + +static inline uint32_t +zwp_tablet_seat_v2_get_version(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_seat_v2); +} + +/** + * @ingroup iface_zwp_tablet_seat_v2 + * + * Destroy the wp_tablet_seat object. Objects created from this + * object are unaffected and should be destroyed separately. + */ +static inline void +zwp_tablet_seat_v2_destroy(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_seat_v2, + ZWP_TABLET_SEAT_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_seat_v2), WL_MARSHAL_FLAG_DESTROY); +} + +#ifndef ZWP_TABLET_TOOL_V2_TYPE_ENUM +#define ZWP_TABLET_TOOL_V2_TYPE_ENUM +/** + * @ingroup iface_zwp_tablet_tool_v2 + * a physical tool type + * + * Describes the physical type of a tool. The physical type of a tool + * generally defines its base usage. + * + * The mouse tool represents a mouse-shaped tool that is not a relative + * device but bound to the tablet's surface, providing absolute + * coordinates. + * + * The lens tool is a mouse-shaped tool with an attached lens to + * provide precision focus. + */ +enum zwp_tablet_tool_v2_type { + /** + * Pen + */ + ZWP_TABLET_TOOL_V2_TYPE_PEN = 0x140, + /** + * Eraser + */ + ZWP_TABLET_TOOL_V2_TYPE_ERASER = 0x141, + /** + * Brush + */ + ZWP_TABLET_TOOL_V2_TYPE_BRUSH = 0x142, + /** + * Pencil + */ + ZWP_TABLET_TOOL_V2_TYPE_PENCIL = 0x143, + /** + * Airbrush + */ + ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH = 0x144, + /** + * Finger + */ + ZWP_TABLET_TOOL_V2_TYPE_FINGER = 0x145, + /** + * Mouse + */ + ZWP_TABLET_TOOL_V2_TYPE_MOUSE = 0x146, + /** + * Lens + */ + ZWP_TABLET_TOOL_V2_TYPE_LENS = 0x147, +}; +#endif /* ZWP_TABLET_TOOL_V2_TYPE_ENUM */ + +#ifndef ZWP_TABLET_TOOL_V2_CAPABILITY_ENUM +#define ZWP_TABLET_TOOL_V2_CAPABILITY_ENUM +/** + * @ingroup iface_zwp_tablet_tool_v2 + * capability flags for a tool + * + * Describes extra capabilities on a tablet. + * + * Any tool must provide x and y values, extra axes are + * device-specific. + */ +enum zwp_tablet_tool_v2_capability { + /** + * Tilt axes + */ + ZWP_TABLET_TOOL_V2_CAPABILITY_TILT = 1, + /** + * Pressure axis + */ + ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE = 2, + /** + * Distance axis + */ + ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE = 3, + /** + * Z-rotation axis + */ + ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION = 4, + /** + * Slider axis + */ + ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER = 5, + /** + * Wheel axis + */ + ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL = 6, +}; +#endif /* ZWP_TABLET_TOOL_V2_CAPABILITY_ENUM */ + +#ifndef ZWP_TABLET_TOOL_V2_BUTTON_STATE_ENUM +#define ZWP_TABLET_TOOL_V2_BUTTON_STATE_ENUM +/** + * @ingroup iface_zwp_tablet_tool_v2 + * physical button state + * + * Describes the physical state of a button that produced the button event. + */ +enum zwp_tablet_tool_v2_button_state { + /** + * button is not pressed + */ + ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED = 0, + /** + * button is pressed + */ + ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED = 1, +}; +#endif /* ZWP_TABLET_TOOL_V2_BUTTON_STATE_ENUM */ + +#ifndef ZWP_TABLET_TOOL_V2_ERROR_ENUM +#define ZWP_TABLET_TOOL_V2_ERROR_ENUM +enum zwp_tablet_tool_v2_error { + /** + * given wl_surface has another role + */ + ZWP_TABLET_TOOL_V2_ERROR_ROLE = 0, +}; +#endif /* ZWP_TABLET_TOOL_V2_ERROR_ENUM */ + +/** + * @ingroup iface_zwp_tablet_tool_v2 + * @struct zwp_tablet_tool_v2_listener + */ +struct zwp_tablet_tool_v2_listener { + /** + * tool type + * + * The tool type is the high-level type of the tool and usually + * decides the interaction expected from this tool. + * + * This event is sent in the initial burst of events before the + * wp_tablet_tool.done event. + * @param tool_type the physical tool type + */ + void (*type)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t tool_type); + /** + * unique hardware serial number of the tool + * + * If the physical tool can be identified by a unique 64-bit + * serial number, this event notifies the client of this serial + * number. + * + * If multiple tablets are available in the same seat and the tool + * is uniquely identifiable by the serial number, that tool may + * move between tablets. + * + * Otherwise, if the tool has no serial number and this event is + * missing, the tool is tied to the tablet it first comes into + * proximity with. Even if the physical tool is used on multiple + * tablets, separate wp_tablet_tool objects will be created, one + * per tablet. + * + * This event is sent in the initial burst of events before the + * wp_tablet_tool.done event. + * @param hardware_serial_hi the unique serial number of the tool, most significant bits + * @param hardware_serial_lo the unique serial number of the tool, least significant bits + */ + void (*hardware_serial)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t hardware_serial_hi, + uint32_t hardware_serial_lo); + /** + * hardware id notification in Wacom's format + * + * This event notifies the client of a hardware id available on + * this tool. + * + * The hardware id is a device-specific 64-bit id that provides + * extra information about the tool in use, beyond the wl_tool.type + * enumeration. The format of the id is specific to tablets made by + * Wacom Inc. For example, the hardware id of a Wacom Grip Pen (a + * stylus) is 0x802. + * + * This event is sent in the initial burst of events before the + * wp_tablet_tool.done event. + * @param hardware_id_hi the hardware id, most significant bits + * @param hardware_id_lo the hardware id, least significant bits + */ + void (*hardware_id_wacom)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t hardware_id_hi, + uint32_t hardware_id_lo); + /** + * tool capability notification + * + * This event notifies the client of any capabilities of this + * tool, beyond the main set of x/y axes and tip up/down detection. + * + * One event is sent for each extra capability available on this + * tool. + * + * This event is sent in the initial burst of events before the + * wp_tablet_tool.done event. + * @param capability the capability + */ + void (*capability)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t capability); + /** + * tool description events sequence complete + * + * This event signals the end of the initial burst of descriptive + * events. A client may consider the static description of the tool + * to be complete and finalize initialization of the tool. + */ + void (*done)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); + /** + * tool removed + * + * This event is sent when the tool is removed from the system + * and will send no further events. Should the physical tool come + * back into proximity later, a new wp_tablet_tool object will be + * created. + * + * It is compositor-dependent when a tool is removed. A compositor + * may remove a tool on proximity out, tablet removal or any other + * reason. A compositor may also keep a tool alive until shutdown. + * + * If the tool is currently in proximity, a proximity_out event + * will be sent before the removed event. See + * wp_tablet_tool.proximity_out for the handling of any buttons + * logically down. + * + * When this event is received, the client must + * wp_tablet_tool.destroy the object. + */ + void (*removed)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); + /** + * proximity in event + * + * Notification that this tool is focused on a certain surface. + * + * This event can be received when the tool has moved from one + * surface to another, or when the tool has come back into + * proximity above the surface. + * + * If any button is logically down when the tool comes into + * proximity, the respective button event is sent after the + * proximity_in event but within the same frame as the proximity_in + * event. + * @param tablet The tablet the tool is in proximity of + * @param surface The current surface the tablet tool is over + */ + void (*proximity_in)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t serial, + struct zwp_tablet_v2 *tablet, + struct wl_surface *surface); + /** + * proximity out event + * + * Notification that this tool has either left proximity, or is + * no longer focused on a certain surface. + * + * When the tablet tool leaves proximity of the tablet, button + * release events are sent for each button that was held down at + * the time of leaving proximity. These events are sent before the + * proximity_out event but within the same wp_tablet.frame. + * + * If the tool stays within proximity of the tablet, but the focus + * changes from one surface to another, a button release event may + * not be sent until the button is actually released or the tool + * leaves the proximity of the tablet. + */ + void (*proximity_out)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); + /** + * tablet tool is making contact + * + * Sent whenever the tablet tool comes in contact with the + * surface of the tablet. + * + * If the tool is already in contact with the tablet when entering + * the input region, the client owning said region will receive a + * wp_tablet.proximity_in event, followed by a wp_tablet.down event + * and a wp_tablet.frame event. + * + * Note that this event describes logical contact, not physical + * contact. On some devices, a compositor may not consider a tool + * in logical contact until a minimum physical pressure threshold + * is exceeded. + */ + void (*down)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t serial); + /** + * tablet tool is no longer making contact + * + * Sent whenever the tablet tool stops making contact with the + * surface of the tablet, or when the tablet tool moves out of the + * input region and the compositor grab (if any) is dismissed. + * + * If the tablet tool moves out of the input region while in + * contact with the surface of the tablet and the compositor does + * not have an ongoing grab on the surface, the client owning said + * region will receive a wp_tablet.up event, followed by a + * wp_tablet.proximity_out event and a wp_tablet.frame event. If + * the compositor has an ongoing grab on this device, this event + * sequence is sent whenever the grab is dismissed in the future. + * + * Note that this event describes logical contact, not physical + * contact. On some devices, a compositor may not consider a tool + * out of logical contact until physical pressure falls below a + * specific threshold. + */ + void (*up)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2); + /** + * motion event + * + * Sent whenever a tablet tool moves. + * @param x surface-local x coordinate + * @param y surface-local y coordinate + */ + void (*motion)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + wl_fixed_t x, + wl_fixed_t y); + /** + * pressure change event + * + * Sent whenever the pressure axis on a tool changes. The value + * of this event is normalized to a value between 0 and 65535. + * + * Note that pressure may be nonzero even when a tool is not in + * logical contact. See the down and up events for more details. + * @param pressure The current pressure value + */ + void (*pressure)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t pressure); + /** + * distance change event + * + * Sent whenever the distance axis on a tool changes. The value + * of this event is normalized to a value between 0 and 65535. + * + * Note that distance may be nonzero even when a tool is not in + * logical contact. See the down and up events for more details. + * @param distance The current distance value + */ + void (*distance)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t distance); + /** + * tilt change event + * + * Sent whenever one or both of the tilt axes on a tool change. + * Each tilt value is in degrees, relative to the z-axis of the + * tablet. The angle is positive when the top of a tool tilts along + * the positive x or y axis. + * @param tilt_x The current value of the X tilt axis + * @param tilt_y The current value of the Y tilt axis + */ + void (*tilt)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + wl_fixed_t tilt_x, + wl_fixed_t tilt_y); + /** + * z-rotation change event + * + * Sent whenever the z-rotation axis on the tool changes. The + * rotation value is in degrees clockwise from the tool's logical + * neutral position. + * @param degrees The current rotation of the Z axis + */ + void (*rotation)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + wl_fixed_t degrees); + /** + * Slider position change event + * + * Sent whenever the slider position on the tool changes. The + * value is normalized between -65535 and 65535, with 0 as the + * logical neutral position of the slider. + * + * The slider is available on e.g. the Wacom Airbrush tool. + * @param position The current position of slider + */ + void (*slider)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + int32_t position); + /** + * Wheel delta event + * + * Sent whenever the wheel on the tool emits an event. This event + * contains two values for the same axis change. The degrees value + * is in the same orientation as the wl_pointer.vertical_scroll + * axis. The clicks value is in discrete logical clicks of the + * mouse wheel. This value may be zero if the movement of the wheel + * was less than one logical click. + * + * Clients should choose either value and avoid mixing degrees and + * clicks. The compositor may accumulate values smaller than a + * logical click and emulate click events when a certain threshold + * is met. Thus, wl_tablet_tool.wheel events with non-zero clicks + * values may have different degrees values. + * @param degrees The wheel delta in degrees + * @param clicks The wheel delta in discrete clicks + */ + void (*wheel)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + wl_fixed_t degrees, + int32_t clicks); + /** + * button event + * + * Sent whenever a button on the tool is pressed or released. + * + * If a button is held down when the tool moves in or out of + * proximity, button events are generated by the compositor. See + * wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for + * details. + * @param button The button whose state has changed + * @param state Whether the button was pressed or released + */ + void (*button)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t serial, + uint32_t button, + uint32_t state); + /** + * frame event + * + * Marks the end of a series of axis and/or button updates from + * the tablet. The Wayland protocol requires axis updates to be + * sent sequentially, however all events within a frame should be + * considered one hardware event. + * @param time The time of the event with millisecond granularity + */ + void (*frame)(void *data, + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + uint32_t time); +}; + +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +static inline int +zwp_tablet_tool_v2_add_listener(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, + const struct zwp_tablet_tool_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_tool_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_TOOL_V2_SET_CURSOR 0 +#define ZWP_TABLET_TOOL_V2_DESTROY 1 + +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_TYPE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_HARDWARE_SERIAL_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_HARDWARE_ID_WACOM_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_CAPABILITY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_DONE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_REMOVED_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_PROXIMITY_IN_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_PROXIMITY_OUT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_DOWN_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_UP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_MOTION_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_PRESSURE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_DISTANCE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_TILT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_ROTATION_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_SLIDER_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_WHEEL_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_BUTTON_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_SET_CURSOR_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_tool_v2 + */ +#define ZWP_TABLET_TOOL_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_tool_v2 */ +static inline void +zwp_tablet_tool_v2_set_user_data(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_tool_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_tool_v2 */ +static inline void * +zwp_tablet_tool_v2_get_user_data(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_tool_v2); +} + +static inline uint32_t +zwp_tablet_tool_v2_get_version(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_tool_v2); +} + +/** + * @ingroup iface_zwp_tablet_tool_v2 + * + * Sets the surface of the cursor used for this tool on the given + * tablet. This request only takes effect if the tool is in proximity + * of one of the requesting client's surfaces or the surface parameter + * is the current pointer surface. If there was a previous surface set + * with this request it is replaced. If surface is NULL, the cursor + * image is hidden. + * + * The parameters hotspot_x and hotspot_y define the position of the + * pointer surface relative to the pointer location. Its top-left corner + * is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the + * coordinates of the pointer location, in surface-local coordinates. + * + * On surface.attach requests to the pointer surface, hotspot_x and + * hotspot_y are decremented by the x and y parameters passed to the + * request. Attach must be confirmed by wl_surface.commit as usual. + * + * The hotspot can also be updated by passing the currently set pointer + * surface to this request with new values for hotspot_x and hotspot_y. + * + * The current and pending input regions of the wl_surface are cleared, + * and wl_surface.set_input_region is ignored until the wl_surface is no + * longer used as the cursor. When the use as a cursor ends, the current + * and pending input regions become undefined, and the wl_surface is + * unmapped. + * + * This request gives the surface the role of a wp_tablet_tool cursor. A + * surface may only ever be used as the cursor surface for one + * wp_tablet_tool. If the surface already has another role or has + * previously been used as cursor surface for a different tool, a + * protocol error is raised. + */ +static inline void +zwp_tablet_tool_v2_set_cursor(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_tool_v2, + ZWP_TABLET_TOOL_V2_SET_CURSOR, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_tool_v2), 0, serial, surface, hotspot_x, hotspot_y); +} + +/** + * @ingroup iface_zwp_tablet_tool_v2 + * + * This destroys the client's resource for this tool object. + */ +static inline void +zwp_tablet_tool_v2_destroy(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_tool_v2, + ZWP_TABLET_TOOL_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_tool_v2), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_zwp_tablet_v2 + * @struct zwp_tablet_v2_listener + */ +struct zwp_tablet_v2_listener { + /** + * tablet device name + * + * A descriptive name for the tablet device. + * + * If the device has no descriptive name, this event is not sent. + * + * This event is sent in the initial burst of events before the + * wp_tablet.done event. + * @param name the device name + */ + void (*name)(void *data, + struct zwp_tablet_v2 *zwp_tablet_v2, + const char *name); + /** + * tablet device USB vendor/product id + * + * The USB vendor and product IDs for the tablet device. + * + * If the device has no USB vendor/product ID, this event is not + * sent. This can happen for virtual devices or non-USB devices, + * for instance. + * + * This event is sent in the initial burst of events before the + * wp_tablet.done event. + * @param vid USB vendor id + * @param pid USB product id + */ + void (*id)(void *data, + struct zwp_tablet_v2 *zwp_tablet_v2, + uint32_t vid, + uint32_t pid); + /** + * path to the device + * + * A system-specific device path that indicates which device is + * behind this wp_tablet. This information may be used to gather + * additional information about the device, e.g. through libwacom. + * + * A device may have more than one device path. If so, multiple + * wp_tablet.path events are sent. A device may be emulated and not + * have a device path, and in that case this event will not be + * sent. + * + * The format of the path is unspecified, it may be a device node, + * a sysfs path, or some other identifier. It is up to the client + * to identify the string provided. + * + * This event is sent in the initial burst of events before the + * wp_tablet.done event. + * @param path path to local device + */ + void (*path)(void *data, + struct zwp_tablet_v2 *zwp_tablet_v2, + const char *path); + /** + * tablet description events sequence complete + * + * This event is sent immediately to signal the end of the + * initial burst of descriptive events. A client may consider the + * static description of the tablet to be complete and finalize + * initialization of the tablet. + */ + void (*done)(void *data, + struct zwp_tablet_v2 *zwp_tablet_v2); + /** + * tablet removed event + * + * Sent when the tablet has been removed from the system. When a + * tablet is removed, some tools may be removed. + * + * When this event is received, the client must wp_tablet.destroy + * the object. + */ + void (*removed)(void *data, + struct zwp_tablet_v2 *zwp_tablet_v2); +}; + +/** + * @ingroup iface_zwp_tablet_v2 + */ +static inline int +zwp_tablet_v2_add_listener(struct zwp_tablet_v2 *zwp_tablet_v2, + const struct zwp_tablet_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_V2_DESTROY 0 + +/** + * @ingroup iface_zwp_tablet_v2 + */ +#define ZWP_TABLET_V2_NAME_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_v2 + */ +#define ZWP_TABLET_V2_ID_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_v2 + */ +#define ZWP_TABLET_V2_PATH_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_v2 + */ +#define ZWP_TABLET_V2_DONE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_v2 + */ +#define ZWP_TABLET_V2_REMOVED_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_v2 + */ +#define ZWP_TABLET_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_v2 */ +static inline void +zwp_tablet_v2_set_user_data(struct zwp_tablet_v2 *zwp_tablet_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_v2 */ +static inline void * +zwp_tablet_v2_get_user_data(struct zwp_tablet_v2 *zwp_tablet_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_v2); +} + +static inline uint32_t +zwp_tablet_v2_get_version(struct zwp_tablet_v2 *zwp_tablet_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_v2); +} + +/** + * @ingroup iface_zwp_tablet_v2 + * + * This destroys the client's resource for this tablet object. + */ +static inline void +zwp_tablet_v2_destroy(struct zwp_tablet_v2 *zwp_tablet_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_v2, + ZWP_TABLET_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_v2), WL_MARSHAL_FLAG_DESTROY); +} + +#ifndef ZWP_TABLET_PAD_RING_V2_SOURCE_ENUM +#define ZWP_TABLET_PAD_RING_V2_SOURCE_ENUM +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + * ring axis source + * + * Describes the source types for ring events. This indicates to the + * client how a ring event was physically generated; a client may + * adjust the user interface accordingly. For example, events + * from a "finger" source may trigger kinetic scrolling. + */ +enum zwp_tablet_pad_ring_v2_source { + /** + * finger + */ + ZWP_TABLET_PAD_RING_V2_SOURCE_FINGER = 1, +}; +#endif /* ZWP_TABLET_PAD_RING_V2_SOURCE_ENUM */ + +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + * @struct zwp_tablet_pad_ring_v2_listener + */ +struct zwp_tablet_pad_ring_v2_listener { + /** + * ring event source + * + * Source information for ring events. + * + * This event does not occur on its own. It is sent before a + * wp_tablet_pad_ring.frame event and carries the source + * information for all events within that frame. + * + * The source specifies how this event was generated. If the source + * is wp_tablet_pad_ring.source.finger, a wp_tablet_pad_ring.stop + * event will be sent when the user lifts the finger off the + * device. + * + * This event is optional. If the source is unknown for an + * interaction, no event is sent. + * @param source the event source + */ + void (*source)(void *data, + struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, + uint32_t source); + /** + * angle changed + * + * Sent whenever the angle on a ring changes. + * + * The angle is provided in degrees clockwise from the logical + * north of the ring in the pad's current rotation. + * @param degrees the current angle in degrees + */ + void (*angle)(void *data, + struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, + wl_fixed_t degrees); + /** + * interaction stopped + * + * Stop notification for ring events. + * + * For some wp_tablet_pad_ring.source types, a + * wp_tablet_pad_ring.stop event is sent to notify a client that + * the interaction with the ring has terminated. This enables the + * client to implement kinetic scrolling. See the + * wp_tablet_pad_ring.source documentation for information on when + * this event may be generated. + * + * Any wp_tablet_pad_ring.angle events with the same source after + * this event should be considered as the start of a new + * interaction. + */ + void (*stop)(void *data, + struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2); + /** + * end of a ring event sequence + * + * Indicates the end of a set of ring events that logically + * belong together. A client is expected to accumulate the data in + * all events within the frame before proceeding. + * + * All wp_tablet_pad_ring events before a wp_tablet_pad_ring.frame + * event belong logically together. For example, on termination of + * a finger interaction on a ring the compositor will send a + * wp_tablet_pad_ring.source event, a wp_tablet_pad_ring.stop event + * and a wp_tablet_pad_ring.frame event. + * + * A wp_tablet_pad_ring.frame event is sent for every logical event + * group, even if the group only contains a single + * wp_tablet_pad_ring event. Specifically, a client may get a + * sequence: angle, frame, angle, frame, etc. + * @param time timestamp with millisecond granularity + */ + void (*frame)(void *data, + struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, + uint32_t time); +}; + +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +static inline int +zwp_tablet_pad_ring_v2_add_listener(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, + const struct zwp_tablet_pad_ring_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_ring_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_PAD_RING_V2_SET_FEEDBACK 0 +#define ZWP_TABLET_PAD_RING_V2_DESTROY 1 + +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +#define ZWP_TABLET_PAD_RING_V2_SOURCE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +#define ZWP_TABLET_PAD_RING_V2_ANGLE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +#define ZWP_TABLET_PAD_RING_V2_STOP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +#define ZWP_TABLET_PAD_RING_V2_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +#define ZWP_TABLET_PAD_RING_V2_SET_FEEDBACK_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + */ +#define ZWP_TABLET_PAD_RING_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_pad_ring_v2 */ +static inline void +zwp_tablet_pad_ring_v2_set_user_data(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_ring_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_pad_ring_v2 */ +static inline void * +zwp_tablet_pad_ring_v2_get_user_data(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_ring_v2); +} + +static inline uint32_t +zwp_tablet_pad_ring_v2_get_version(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_ring_v2); +} + +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + * + * Request that the compositor use the provided feedback string + * associated with this ring. This request should be issued immediately + * after a wp_tablet_pad_group.mode_switch event from the corresponding + * group is received, or whenever the ring is mapped to a different + * action. See wp_tablet_pad_group.mode_switch for more details. + * + * Clients are encouraged to provide context-aware descriptions for + * the actions associated with the ring; compositors may use this + * information to offer visual feedback about the button layout + * (eg. on-screen displays). + * + * The provided string 'description' is a UTF-8 encoded string to be + * associated with this ring, and is considered user-visible; general + * internationalization rules apply. + * + * The serial argument will be that of the last + * wp_tablet_pad_group.mode_switch event received for the group of this + * ring. Requests providing other serials than the most recent one will be + * ignored. + */ +static inline void +zwp_tablet_pad_ring_v2_set_feedback(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, const char *description, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_ring_v2, + ZWP_TABLET_PAD_RING_V2_SET_FEEDBACK, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_ring_v2), 0, description, serial); +} + +/** + * @ingroup iface_zwp_tablet_pad_ring_v2 + * + * This destroys the client's resource for this ring object. + */ +static inline void +zwp_tablet_pad_ring_v2_destroy(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_ring_v2, + ZWP_TABLET_PAD_RING_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_ring_v2), WL_MARSHAL_FLAG_DESTROY); +} + +#ifndef ZWP_TABLET_PAD_STRIP_V2_SOURCE_ENUM +#define ZWP_TABLET_PAD_STRIP_V2_SOURCE_ENUM +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + * strip axis source + * + * Describes the source types for strip events. This indicates to the + * client how a strip event was physically generated; a client may + * adjust the user interface accordingly. For example, events + * from a "finger" source may trigger kinetic scrolling. + */ +enum zwp_tablet_pad_strip_v2_source { + /** + * finger + */ + ZWP_TABLET_PAD_STRIP_V2_SOURCE_FINGER = 1, +}; +#endif /* ZWP_TABLET_PAD_STRIP_V2_SOURCE_ENUM */ + +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + * @struct zwp_tablet_pad_strip_v2_listener + */ +struct zwp_tablet_pad_strip_v2_listener { + /** + * strip event source + * + * Source information for strip events. + * + * This event does not occur on its own. It is sent before a + * wp_tablet_pad_strip.frame event and carries the source + * information for all events within that frame. + * + * The source specifies how this event was generated. If the source + * is wp_tablet_pad_strip.source.finger, a wp_tablet_pad_strip.stop + * event will be sent when the user lifts their finger off the + * device. + * + * This event is optional. If the source is unknown for an + * interaction, no event is sent. + * @param source the event source + */ + void (*source)(void *data, + struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, + uint32_t source); + /** + * position changed + * + * Sent whenever the position on a strip changes. + * + * The position is normalized to a range of [0, 65535], the 0-value + * represents the top-most and/or left-most position of the strip + * in the pad's current rotation. + * @param position the current position + */ + void (*position)(void *data, + struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, + uint32_t position); + /** + * interaction stopped + * + * Stop notification for strip events. + * + * For some wp_tablet_pad_strip.source types, a + * wp_tablet_pad_strip.stop event is sent to notify a client that + * the interaction with the strip has terminated. This enables the + * client to implement kinetic scrolling. See the + * wp_tablet_pad_strip.source documentation for information on when + * this event may be generated. + * + * Any wp_tablet_pad_strip.position events with the same source + * after this event should be considered as the start of a new + * interaction. + */ + void (*stop)(void *data, + struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2); + /** + * end of a strip event sequence + * + * Indicates the end of a set of events that represent one + * logical hardware strip event. A client is expected to accumulate + * the data in all events within the frame before proceeding. + * + * All wp_tablet_pad_strip events before a + * wp_tablet_pad_strip.frame event belong logically together. For + * example, on termination of a finger interaction on a strip the + * compositor will send a wp_tablet_pad_strip.source event, a + * wp_tablet_pad_strip.stop event and a wp_tablet_pad_strip.frame + * event. + * + * A wp_tablet_pad_strip.frame event is sent for every logical + * event group, even if the group only contains a single + * wp_tablet_pad_strip event. Specifically, a client may get a + * sequence: position, frame, position, frame, etc. + * @param time timestamp with millisecond granularity + */ + void (*frame)(void *data, + struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, + uint32_t time); +}; + +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +static inline int +zwp_tablet_pad_strip_v2_add_listener(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, + const struct zwp_tablet_pad_strip_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_strip_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_PAD_STRIP_V2_SET_FEEDBACK 0 +#define ZWP_TABLET_PAD_STRIP_V2_DESTROY 1 + +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +#define ZWP_TABLET_PAD_STRIP_V2_SOURCE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +#define ZWP_TABLET_PAD_STRIP_V2_POSITION_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +#define ZWP_TABLET_PAD_STRIP_V2_STOP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +#define ZWP_TABLET_PAD_STRIP_V2_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +#define ZWP_TABLET_PAD_STRIP_V2_SET_FEEDBACK_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + */ +#define ZWP_TABLET_PAD_STRIP_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_pad_strip_v2 */ +static inline void +zwp_tablet_pad_strip_v2_set_user_data(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_strip_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_pad_strip_v2 */ +static inline void * +zwp_tablet_pad_strip_v2_get_user_data(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_strip_v2); +} + +static inline uint32_t +zwp_tablet_pad_strip_v2_get_version(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_strip_v2); +} + +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + * + * Requests the compositor to use the provided feedback string + * associated with this strip. This request should be issued immediately + * after a wp_tablet_pad_group.mode_switch event from the corresponding + * group is received, or whenever the strip is mapped to a different + * action. See wp_tablet_pad_group.mode_switch for more details. + * + * Clients are encouraged to provide context-aware descriptions for + * the actions associated with the strip, and compositors may use this + * information to offer visual feedback about the button layout + * (eg. on-screen displays). + * + * The provided string 'description' is a UTF-8 encoded string to be + * associated with this ring, and is considered user-visible; general + * internationalization rules apply. + * + * The serial argument will be that of the last + * wp_tablet_pad_group.mode_switch event received for the group of this + * strip. Requests providing other serials than the most recent one will be + * ignored. + */ +static inline void +zwp_tablet_pad_strip_v2_set_feedback(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, const char *description, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_strip_v2, + ZWP_TABLET_PAD_STRIP_V2_SET_FEEDBACK, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_strip_v2), 0, description, serial); +} + +/** + * @ingroup iface_zwp_tablet_pad_strip_v2 + * + * This destroys the client's resource for this strip object. + */ +static inline void +zwp_tablet_pad_strip_v2_destroy(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_strip_v2, + ZWP_TABLET_PAD_STRIP_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_strip_v2), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + * @struct zwp_tablet_pad_group_v2_listener + */ +struct zwp_tablet_pad_group_v2_listener { + /** + * buttons announced + * + * Sent on wp_tablet_pad_group initialization to announce the + * available buttons in the group. Button indices start at 0, a + * button may only be in one group at a time. + * + * This event is first sent in the initial burst of events before + * the wp_tablet_pad_group.done event. + * + * Some buttons are reserved by the compositor. These buttons may + * not be assigned to any wp_tablet_pad_group. Compositors may + * broadcast this event in the case of changes to the mapping of + * these reserved buttons. If the compositor happens to reserve all + * buttons in a group, this event will be sent with an empty array. + * @param buttons buttons in this group + */ + void (*buttons)(void *data, + struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, + struct wl_array *buttons); + /** + * ring announced + * + * Sent on wp_tablet_pad_group initialization to announce + * available rings. One event is sent for each ring available on + * this pad group. + * + * This event is sent in the initial burst of events before the + * wp_tablet_pad_group.done event. + */ + void (*ring)(void *data, + struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, + struct zwp_tablet_pad_ring_v2 *ring); + /** + * strip announced + * + * Sent on wp_tablet_pad initialization to announce available + * strips. One event is sent for each strip available on this pad + * group. + * + * This event is sent in the initial burst of events before the + * wp_tablet_pad_group.done event. + */ + void (*strip)(void *data, + struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, + struct zwp_tablet_pad_strip_v2 *strip); + /** + * mode-switch ability announced + * + * Sent on wp_tablet_pad_group initialization to announce that + * the pad group may switch between modes. A client may use a mode + * to store a specific configuration for buttons, rings and strips + * and use the wl_tablet_pad_group.mode_switch event to toggle + * between these configurations. Mode indices start at 0. + * + * Switching modes is compositor-dependent. See the + * wp_tablet_pad_group.mode_switch event for more details. + * + * This event is sent in the initial burst of events before the + * wp_tablet_pad_group.done event. This event is only sent when + * more than more than one mode is available. + * @param modes the number of modes + */ + void (*modes)(void *data, + struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, + uint32_t modes); + /** + * tablet group description events sequence complete + * + * This event is sent immediately to signal the end of the + * initial burst of descriptive events. A client may consider the + * static description of the tablet to be complete and finalize + * initialization of the tablet group. + */ + void (*done)(void *data, + struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2); + /** + * mode switch event + * + * Notification that the mode was switched. + * + * A mode applies to all buttons, rings and strips in a group + * simultaneously, but a client is not required to assign different + * actions for each mode. For example, a client may have + * mode-specific button mappings but map the ring to vertical + * scrolling in all modes. Mode indices start at 0. + * + * Switching modes is compositor-dependent. The compositor may + * provide visual cues to the client about the mode, e.g. by + * toggling LEDs on the tablet device. Mode-switching may be + * software-controlled or controlled by one or more physical + * buttons. For example, on a Wacom Intuos Pro, the button inside + * the ring may be assigned to switch between modes. + * + * The compositor will also send this event after + * wp_tablet_pad.enter on each group in order to notify of the + * current mode. Groups that only feature one mode will use mode=0 + * when emitting this event. + * + * If a button action in the new mode differs from the action in + * the previous mode, the client should immediately issue a + * wp_tablet_pad.set_feedback request for each changed button. + * + * If a ring or strip action in the new mode differs from the + * action in the previous mode, the client should immediately issue + * a wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback + * request for each changed ring or strip. + * @param time the time of the event with millisecond granularity + * @param mode the new mode of the pad + */ + void (*mode_switch)(void *data, + struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, + uint32_t time, + uint32_t serial, + uint32_t mode); +}; + +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +static inline int +zwp_tablet_pad_group_v2_add_listener(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, + const struct zwp_tablet_pad_group_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_group_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_PAD_GROUP_V2_DESTROY 0 + +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_BUTTONS_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_RING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_STRIP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_MODES_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_DONE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_MODE_SWITCH_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + */ +#define ZWP_TABLET_PAD_GROUP_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_pad_group_v2 */ +static inline void +zwp_tablet_pad_group_v2_set_user_data(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_group_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_pad_group_v2 */ +static inline void * +zwp_tablet_pad_group_v2_get_user_data(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_group_v2); +} + +static inline uint32_t +zwp_tablet_pad_group_v2_get_version(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_group_v2); +} + +/** + * @ingroup iface_zwp_tablet_pad_group_v2 + * + * Destroy the wp_tablet_pad_group object. Objects created from this object + * are unaffected and should be destroyed separately. + */ +static inline void +zwp_tablet_pad_group_v2_destroy(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_group_v2, + ZWP_TABLET_PAD_GROUP_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_group_v2), WL_MARSHAL_FLAG_DESTROY); +} + +#ifndef ZWP_TABLET_PAD_V2_BUTTON_STATE_ENUM +#define ZWP_TABLET_PAD_V2_BUTTON_STATE_ENUM +/** + * @ingroup iface_zwp_tablet_pad_v2 + * physical button state + * + * Describes the physical state of a button that caused the button + * event. + */ +enum zwp_tablet_pad_v2_button_state { + /** + * the button is not pressed + */ + ZWP_TABLET_PAD_V2_BUTTON_STATE_RELEASED = 0, + /** + * the button is pressed + */ + ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED = 1, +}; +#endif /* ZWP_TABLET_PAD_V2_BUTTON_STATE_ENUM */ + +/** + * @ingroup iface_zwp_tablet_pad_v2 + * @struct zwp_tablet_pad_v2_listener + */ +struct zwp_tablet_pad_v2_listener { + /** + * group announced + * + * Sent on wp_tablet_pad initialization to announce available + * groups. One event is sent for each pad group available. + * + * This event is sent in the initial burst of events before the + * wp_tablet_pad.done event. At least one group will be announced. + */ + void (*group)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + struct zwp_tablet_pad_group_v2 *pad_group); + /** + * path to the device + * + * A system-specific device path that indicates which device is + * behind this wp_tablet_pad. This information may be used to + * gather additional information about the device, e.g. through + * libwacom. + * + * The format of the path is unspecified, it may be a device node, + * a sysfs path, or some other identifier. It is up to the client + * to identify the string provided. + * + * This event is sent in the initial burst of events before the + * wp_tablet_pad.done event. + * @param path path to local device + */ + void (*path)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + const char *path); + /** + * buttons announced + * + * Sent on wp_tablet_pad initialization to announce the available + * buttons. + * + * This event is sent in the initial burst of events before the + * wp_tablet_pad.done event. This event is only sent when at least + * one button is available. + * @param buttons the number of buttons + */ + void (*buttons)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + uint32_t buttons); + /** + * pad description event sequence complete + * + * This event signals the end of the initial burst of descriptive + * events. A client may consider the static description of the pad + * to be complete and finalize initialization of the pad. + */ + void (*done)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2); + /** + * physical button state + * + * Sent whenever the physical state of a button changes. + * @param time the time of the event with millisecond granularity + * @param button the index of the button that changed state + */ + void (*button)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + uint32_t time, + uint32_t button, + uint32_t state); + /** + * enter event + * + * Notification that this pad is focused on the specified + * surface. + * @param serial serial number of the enter event + * @param tablet the tablet the pad is attached to + * @param surface surface the pad is focused on + */ + void (*enter)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + uint32_t serial, + struct zwp_tablet_v2 *tablet, + struct wl_surface *surface); + /** + * leave event + * + * Notification that this pad is no longer focused on the + * specified surface. + * @param serial serial number of the leave event + * @param surface surface the pad is no longer focused on + */ + void (*leave)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + uint32_t serial, + struct wl_surface *surface); + /** + * pad removed event + * + * Sent when the pad has been removed from the system. When a + * tablet is removed its pad(s) will be removed too. + * + * When this event is received, the client must destroy all rings, + * strips and groups that were offered by this pad, and issue + * wp_tablet_pad.destroy the pad itself. + */ + void (*removed)(void *data, + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2); +}; + +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +static inline int +zwp_tablet_pad_v2_add_listener(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, + const struct zwp_tablet_pad_v2_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_v2, + (void (**)(void)) listener, data); +} + +#define ZWP_TABLET_PAD_V2_SET_FEEDBACK 0 +#define ZWP_TABLET_PAD_V2_DESTROY 1 + +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_GROUP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_PATH_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_BUTTONS_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_DONE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_BUTTON_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_ENTER_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_LEAVE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_REMOVED_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_SET_FEEDBACK_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_tablet_pad_v2 + */ +#define ZWP_TABLET_PAD_V2_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_tablet_pad_v2 */ +static inline void +zwp_tablet_pad_v2_set_user_data(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_v2, user_data); +} + +/** @ingroup iface_zwp_tablet_pad_v2 */ +static inline void * +zwp_tablet_pad_v2_get_user_data(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_v2); +} + +static inline uint32_t +zwp_tablet_pad_v2_get_version(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_v2); +} + +/** + * @ingroup iface_zwp_tablet_pad_v2 + * + * Requests the compositor to use the provided feedback string + * associated with this button. This request should be issued immediately + * after a wp_tablet_pad_group.mode_switch event from the corresponding + * group is received, or whenever a button is mapped to a different + * action. See wp_tablet_pad_group.mode_switch for more details. + * + * Clients are encouraged to provide context-aware descriptions for + * the actions associated with each button, and compositors may use + * this information to offer visual feedback on the button layout + * (e.g. on-screen displays). + * + * Button indices start at 0. Setting the feedback string on a button + * that is reserved by the compositor (i.e. not belonging to any + * wp_tablet_pad_group) does not generate an error but the compositor + * is free to ignore the request. + * + * The provided string 'description' is a UTF-8 encoded string to be + * associated with this ring, and is considered user-visible; general + * internationalization rules apply. + * + * The serial argument will be that of the last + * wp_tablet_pad_group.mode_switch event received for the group of this + * button. Requests providing other serials than the most recent one will + * be ignored. + */ +static inline void +zwp_tablet_pad_v2_set_feedback(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t button, const char *description, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_v2, + ZWP_TABLET_PAD_V2_SET_FEEDBACK, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_v2), 0, button, description, serial); +} + +/** + * @ingroup iface_zwp_tablet_pad_v2 + * + * Destroy the wp_tablet_pad object. Objects created from this object + * are unaffected and should be destroyed separately. + */ +static inline void +zwp_tablet_pad_v2_destroy(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_v2, + ZWP_TABLET_PAD_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_v2), WL_MARSHAL_FLAG_DESTROY); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/host/linux/wayland/tablet-unstable-v2-protocol.c b/examples/host/linux/wayland/tablet-unstable-v2-protocol.c new file mode 100644 index 0000000..60881d9 --- /dev/null +++ b/examples/host/linux/wayland/tablet-unstable-v2-protocol.c @@ -0,0 +1,234 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright 2014 © Stephen "Lyude" Chandler Paul + * Copyright 2015-2016 © Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_seat_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface zwp_tablet_pad_group_v2_interface; +extern const struct wl_interface zwp_tablet_pad_ring_v2_interface; +extern const struct wl_interface zwp_tablet_pad_strip_v2_interface; +extern const struct wl_interface zwp_tablet_pad_v2_interface; +extern const struct wl_interface zwp_tablet_seat_v2_interface; +extern const struct wl_interface zwp_tablet_tool_v2_interface; +extern const struct wl_interface zwp_tablet_v2_interface; + +static const struct wl_interface *tablet_unstable_v2_types[] = { + NULL, + NULL, + NULL, + &zwp_tablet_seat_v2_interface, + &wl_seat_interface, + &zwp_tablet_v2_interface, + &zwp_tablet_tool_v2_interface, + &zwp_tablet_pad_v2_interface, + NULL, + &wl_surface_interface, + NULL, + NULL, + NULL, + &zwp_tablet_v2_interface, + &wl_surface_interface, + &zwp_tablet_pad_ring_v2_interface, + &zwp_tablet_pad_strip_v2_interface, + &zwp_tablet_pad_group_v2_interface, + NULL, + &zwp_tablet_v2_interface, + &wl_surface_interface, + NULL, + &wl_surface_interface, +}; + +static const struct wl_message zwp_tablet_manager_v2_requests[] = { + { "get_tablet_seat", "no", tablet_unstable_v2_types + 3 }, + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_manager_v2_interface = { + "zwp_tablet_manager_v2", 1, + 2, zwp_tablet_manager_v2_requests, + 0, NULL, +}; + +static const struct wl_message zwp_tablet_seat_v2_requests[] = { + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_seat_v2_events[] = { + { "tablet_added", "n", tablet_unstable_v2_types + 5 }, + { "tool_added", "n", tablet_unstable_v2_types + 6 }, + { "pad_added", "n", tablet_unstable_v2_types + 7 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_seat_v2_interface = { + "zwp_tablet_seat_v2", 1, + 1, zwp_tablet_seat_v2_requests, + 3, zwp_tablet_seat_v2_events, +}; + +static const struct wl_message zwp_tablet_tool_v2_requests[] = { + { "set_cursor", "u?oii", tablet_unstable_v2_types + 8 }, + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_tool_v2_events[] = { + { "type", "u", tablet_unstable_v2_types + 0 }, + { "hardware_serial", "uu", tablet_unstable_v2_types + 0 }, + { "hardware_id_wacom", "uu", tablet_unstable_v2_types + 0 }, + { "capability", "u", tablet_unstable_v2_types + 0 }, + { "done", "", tablet_unstable_v2_types + 0 }, + { "removed", "", tablet_unstable_v2_types + 0 }, + { "proximity_in", "uoo", tablet_unstable_v2_types + 12 }, + { "proximity_out", "", tablet_unstable_v2_types + 0 }, + { "down", "u", tablet_unstable_v2_types + 0 }, + { "up", "", tablet_unstable_v2_types + 0 }, + { "motion", "ff", tablet_unstable_v2_types + 0 }, + { "pressure", "u", tablet_unstable_v2_types + 0 }, + { "distance", "u", tablet_unstable_v2_types + 0 }, + { "tilt", "ff", tablet_unstable_v2_types + 0 }, + { "rotation", "f", tablet_unstable_v2_types + 0 }, + { "slider", "i", tablet_unstable_v2_types + 0 }, + { "wheel", "fi", tablet_unstable_v2_types + 0 }, + { "button", "uuu", tablet_unstable_v2_types + 0 }, + { "frame", "u", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_tool_v2_interface = { + "zwp_tablet_tool_v2", 1, + 2, zwp_tablet_tool_v2_requests, + 19, zwp_tablet_tool_v2_events, +}; + +static const struct wl_message zwp_tablet_v2_requests[] = { + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_v2_events[] = { + { "name", "s", tablet_unstable_v2_types + 0 }, + { "id", "uu", tablet_unstable_v2_types + 0 }, + { "path", "s", tablet_unstable_v2_types + 0 }, + { "done", "", tablet_unstable_v2_types + 0 }, + { "removed", "", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_v2_interface = { + "zwp_tablet_v2", 1, + 1, zwp_tablet_v2_requests, + 5, zwp_tablet_v2_events, +}; + +static const struct wl_message zwp_tablet_pad_ring_v2_requests[] = { + { "set_feedback", "su", tablet_unstable_v2_types + 0 }, + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_pad_ring_v2_events[] = { + { "source", "u", tablet_unstable_v2_types + 0 }, + { "angle", "f", tablet_unstable_v2_types + 0 }, + { "stop", "", tablet_unstable_v2_types + 0 }, + { "frame", "u", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_pad_ring_v2_interface = { + "zwp_tablet_pad_ring_v2", 1, + 2, zwp_tablet_pad_ring_v2_requests, + 4, zwp_tablet_pad_ring_v2_events, +}; + +static const struct wl_message zwp_tablet_pad_strip_v2_requests[] = { + { "set_feedback", "su", tablet_unstable_v2_types + 0 }, + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_pad_strip_v2_events[] = { + { "source", "u", tablet_unstable_v2_types + 0 }, + { "position", "u", tablet_unstable_v2_types + 0 }, + { "stop", "", tablet_unstable_v2_types + 0 }, + { "frame", "u", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_pad_strip_v2_interface = { + "zwp_tablet_pad_strip_v2", 1, + 2, zwp_tablet_pad_strip_v2_requests, + 4, zwp_tablet_pad_strip_v2_events, +}; + +static const struct wl_message zwp_tablet_pad_group_v2_requests[] = { + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_pad_group_v2_events[] = { + { "buttons", "a", tablet_unstable_v2_types + 0 }, + { "ring", "n", tablet_unstable_v2_types + 15 }, + { "strip", "n", tablet_unstable_v2_types + 16 }, + { "modes", "u", tablet_unstable_v2_types + 0 }, + { "done", "", tablet_unstable_v2_types + 0 }, + { "mode_switch", "uuu", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_pad_group_v2_interface = { + "zwp_tablet_pad_group_v2", 1, + 1, zwp_tablet_pad_group_v2_requests, + 6, zwp_tablet_pad_group_v2_events, +}; + +static const struct wl_message zwp_tablet_pad_v2_requests[] = { + { "set_feedback", "usu", tablet_unstable_v2_types + 0 }, + { "destroy", "", tablet_unstable_v2_types + 0 }, +}; + +static const struct wl_message zwp_tablet_pad_v2_events[] = { + { "group", "n", tablet_unstable_v2_types + 17 }, + { "path", "s", tablet_unstable_v2_types + 0 }, + { "buttons", "u", tablet_unstable_v2_types + 0 }, + { "done", "", tablet_unstable_v2_types + 0 }, + { "button", "uuu", tablet_unstable_v2_types + 0 }, + { "enter", "uoo", tablet_unstable_v2_types + 18 }, + { "leave", "uo", tablet_unstable_v2_types + 21 }, + { "removed", "", tablet_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zwp_tablet_pad_v2_interface = { + "zwp_tablet_pad_v2", 1, + 2, zwp_tablet_pad_v2_requests, + 8, zwp_tablet_pad_v2_events, +}; + diff --git a/examples/host/linux/wayland/viewporter-client-protocol.h b/examples/host/linux/wayland/viewporter-client-protocol.h new file mode 100644 index 0000000..f286095 --- /dev/null +++ b/examples/host/linux/wayland/viewporter-client-protocol.h @@ -0,0 +1,394 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef VIEWPORTER_CLIENT_PROTOCOL_H +#define VIEWPORTER_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_viewporter The viewporter protocol + * @section page_ifaces_viewporter Interfaces + * - @subpage page_iface_wp_viewporter - surface cropping and scaling + * - @subpage page_iface_wp_viewport - crop and scale interface to a wl_surface + * @section page_copyright_viewporter Copyright + *
+ *
+ * Copyright © 2013-2016 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_surface; +struct wp_viewport; +struct wp_viewporter; + +#ifndef WP_VIEWPORTER_INTERFACE +#define WP_VIEWPORTER_INTERFACE +/** + * @page page_iface_wp_viewporter wp_viewporter + * @section page_iface_wp_viewporter_desc Description + * + * The global interface exposing surface cropping and scaling + * capabilities is used to instantiate an interface extension for a + * wl_surface object. This extended interface will then allow + * cropping and scaling the surface contents, effectively + * disconnecting the direct relationship between the buffer and the + * surface size. + * @section page_iface_wp_viewporter_api API + * See @ref iface_wp_viewporter. + */ +/** + * @defgroup iface_wp_viewporter The wp_viewporter interface + * + * The global interface exposing surface cropping and scaling + * capabilities is used to instantiate an interface extension for a + * wl_surface object. This extended interface will then allow + * cropping and scaling the surface contents, effectively + * disconnecting the direct relationship between the buffer and the + * surface size. + */ +extern const struct wl_interface wp_viewporter_interface; +#endif +#ifndef WP_VIEWPORT_INTERFACE +#define WP_VIEWPORT_INTERFACE +/** + * @page page_iface_wp_viewport wp_viewport + * @section page_iface_wp_viewport_desc Description + * + * An additional interface to a wl_surface object, which allows the + * client to specify the cropping and scaling of the surface + * contents. + * + * This interface works with two concepts: the source rectangle (src_x, + * src_y, src_width, src_height), and the destination size (dst_width, + * dst_height). The contents of the source rectangle are scaled to the + * destination size, and content outside the source rectangle is ignored. + * This state is double-buffered, see wl_surface.commit. + * + * The two parts of crop and scale state are independent: the source + * rectangle, and the destination size. Initially both are unset, that + * is, no scaling is applied. The whole of the current wl_buffer is + * used as the source, and the surface size is as defined in + * wl_surface.attach. + * + * If the destination size is set, it causes the surface size to become + * dst_width, dst_height. The source (rectangle) is scaled to exactly + * this size. This overrides whatever the attached wl_buffer size is, + * unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface + * has no content and therefore no size. Otherwise, the size is always + * at least 1x1 in surface local coordinates. + * + * If the source rectangle is set, it defines what area of the wl_buffer is + * taken as the source. If the source rectangle is set and the destination + * size is not set, then src_width and src_height must be integers, and the + * surface size becomes the source rectangle size. This results in cropping + * without scaling. If src_width or src_height are not integers and + * destination size is not set, the bad_size protocol error is raised when + * the surface state is applied. + * + * The coordinate transformations from buffer pixel coordinates up to + * the surface-local coordinates happen in the following order: + * 1. buffer_transform (wl_surface.set_buffer_transform) + * 2. buffer_scale (wl_surface.set_buffer_scale) + * 3. crop and scale (wp_viewport.set*) + * This means, that the source rectangle coordinates of crop and scale + * are given in the coordinates after the buffer transform and scale, + * i.e. in the coordinates that would be the surface-local coordinates + * if the crop and scale was not applied. + * + * If src_x or src_y are negative, the bad_value protocol error is raised. + * Otherwise, if the source rectangle is partially or completely outside of + * the non-NULL wl_buffer, then the out_of_buffer protocol error is raised + * when the surface state is applied. A NULL wl_buffer does not raise the + * out_of_buffer error. + * + * If the wl_surface associated with the wp_viewport is destroyed, + * all wp_viewport requests except 'destroy' raise the protocol error + * no_surface. + * + * If the wp_viewport object is destroyed, the crop and scale + * state is removed from the wl_surface. The change will be applied + * on the next wl_surface.commit. + * @section page_iface_wp_viewport_api API + * See @ref iface_wp_viewport. + */ +/** + * @defgroup iface_wp_viewport The wp_viewport interface + * + * An additional interface to a wl_surface object, which allows the + * client to specify the cropping and scaling of the surface + * contents. + * + * This interface works with two concepts: the source rectangle (src_x, + * src_y, src_width, src_height), and the destination size (dst_width, + * dst_height). The contents of the source rectangle are scaled to the + * destination size, and content outside the source rectangle is ignored. + * This state is double-buffered, see wl_surface.commit. + * + * The two parts of crop and scale state are independent: the source + * rectangle, and the destination size. Initially both are unset, that + * is, no scaling is applied. The whole of the current wl_buffer is + * used as the source, and the surface size is as defined in + * wl_surface.attach. + * + * If the destination size is set, it causes the surface size to become + * dst_width, dst_height. The source (rectangle) is scaled to exactly + * this size. This overrides whatever the attached wl_buffer size is, + * unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface + * has no content and therefore no size. Otherwise, the size is always + * at least 1x1 in surface local coordinates. + * + * If the source rectangle is set, it defines what area of the wl_buffer is + * taken as the source. If the source rectangle is set and the destination + * size is not set, then src_width and src_height must be integers, and the + * surface size becomes the source rectangle size. This results in cropping + * without scaling. If src_width or src_height are not integers and + * destination size is not set, the bad_size protocol error is raised when + * the surface state is applied. + * + * The coordinate transformations from buffer pixel coordinates up to + * the surface-local coordinates happen in the following order: + * 1. buffer_transform (wl_surface.set_buffer_transform) + * 2. buffer_scale (wl_surface.set_buffer_scale) + * 3. crop and scale (wp_viewport.set*) + * This means, that the source rectangle coordinates of crop and scale + * are given in the coordinates after the buffer transform and scale, + * i.e. in the coordinates that would be the surface-local coordinates + * if the crop and scale was not applied. + * + * If src_x or src_y are negative, the bad_value protocol error is raised. + * Otherwise, if the source rectangle is partially or completely outside of + * the non-NULL wl_buffer, then the out_of_buffer protocol error is raised + * when the surface state is applied. A NULL wl_buffer does not raise the + * out_of_buffer error. + * + * If the wl_surface associated with the wp_viewport is destroyed, + * all wp_viewport requests except 'destroy' raise the protocol error + * no_surface. + * + * If the wp_viewport object is destroyed, the crop and scale + * state is removed from the wl_surface. The change will be applied + * on the next wl_surface.commit. + */ +extern const struct wl_interface wp_viewport_interface; +#endif + +#ifndef WP_VIEWPORTER_ERROR_ENUM +#define WP_VIEWPORTER_ERROR_ENUM +enum wp_viewporter_error { + /** + * the surface already has a viewport object associated + */ + WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS = 0, +}; +#endif /* WP_VIEWPORTER_ERROR_ENUM */ + +#define WP_VIEWPORTER_DESTROY 0 +#define WP_VIEWPORTER_GET_VIEWPORT 1 + + +/** + * @ingroup iface_wp_viewporter + */ +#define WP_VIEWPORTER_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_viewporter + */ +#define WP_VIEWPORTER_GET_VIEWPORT_SINCE_VERSION 1 + +/** @ingroup iface_wp_viewporter */ +static inline void +wp_viewporter_set_user_data(struct wp_viewporter *wp_viewporter, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_viewporter, user_data); +} + +/** @ingroup iface_wp_viewporter */ +static inline void * +wp_viewporter_get_user_data(struct wp_viewporter *wp_viewporter) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_viewporter); +} + +static inline uint32_t +wp_viewporter_get_version(struct wp_viewporter *wp_viewporter) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_viewporter); +} + +/** + * @ingroup iface_wp_viewporter + * + * Informs the server that the client will not be using this + * protocol object anymore. This does not affect any other objects, + * wp_viewport objects included. + */ +static inline void +wp_viewporter_destroy(struct wp_viewporter *wp_viewporter) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_viewporter, + WP_VIEWPORTER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_viewporter), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_wp_viewporter + * + * Instantiate an interface extension for the given wl_surface to + * crop and scale its content. If the given wl_surface already has + * a wp_viewport object associated, the viewport_exists + * protocol error is raised. + */ +static inline struct wp_viewport * +wp_viewporter_get_viewport(struct wp_viewporter *wp_viewporter, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) wp_viewporter, + WP_VIEWPORTER_GET_VIEWPORT, &wp_viewport_interface, wl_proxy_get_version((struct wl_proxy *) wp_viewporter), 0, NULL, surface); + + return (struct wp_viewport *) id; +} + +#ifndef WP_VIEWPORT_ERROR_ENUM +#define WP_VIEWPORT_ERROR_ENUM +enum wp_viewport_error { + /** + * negative or zero values in width or height + */ + WP_VIEWPORT_ERROR_BAD_VALUE = 0, + /** + * destination size is not integer + */ + WP_VIEWPORT_ERROR_BAD_SIZE = 1, + /** + * source rectangle extends outside of the content area + */ + WP_VIEWPORT_ERROR_OUT_OF_BUFFER = 2, + /** + * the wl_surface was destroyed + */ + WP_VIEWPORT_ERROR_NO_SURFACE = 3, +}; +#endif /* WP_VIEWPORT_ERROR_ENUM */ + +#define WP_VIEWPORT_DESTROY 0 +#define WP_VIEWPORT_SET_SOURCE 1 +#define WP_VIEWPORT_SET_DESTINATION 2 + + +/** + * @ingroup iface_wp_viewport + */ +#define WP_VIEWPORT_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_viewport + */ +#define WP_VIEWPORT_SET_SOURCE_SINCE_VERSION 1 +/** + * @ingroup iface_wp_viewport + */ +#define WP_VIEWPORT_SET_DESTINATION_SINCE_VERSION 1 + +/** @ingroup iface_wp_viewport */ +static inline void +wp_viewport_set_user_data(struct wp_viewport *wp_viewport, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_viewport, user_data); +} + +/** @ingroup iface_wp_viewport */ +static inline void * +wp_viewport_get_user_data(struct wp_viewport *wp_viewport) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_viewport); +} + +static inline uint32_t +wp_viewport_get_version(struct wp_viewport *wp_viewport) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_viewport); +} + +/** + * @ingroup iface_wp_viewport + * + * The associated wl_surface's crop and scale state is removed. + * The change is applied on the next wl_surface.commit. + */ +static inline void +wp_viewport_destroy(struct wp_viewport *wp_viewport) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_viewport, + WP_VIEWPORT_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_viewport), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_wp_viewport + * + * Set the source rectangle of the associated wl_surface. See + * wp_viewport for the description, and relation to the wl_buffer + * size. + * + * If all of x, y, width and height are -1.0, the source rectangle is + * unset instead. Any other set of values where width or height are zero + * or negative, or x or y are negative, raise the bad_value protocol + * error. + * + * The crop and scale state is double-buffered, see wl_surface.commit. + */ +static inline void +wp_viewport_set_source(struct wp_viewport *wp_viewport, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_viewport, + WP_VIEWPORT_SET_SOURCE, NULL, wl_proxy_get_version((struct wl_proxy *) wp_viewport), 0, x, y, width, height); +} + +/** + * @ingroup iface_wp_viewport + * + * Set the destination size of the associated wl_surface. See + * wp_viewport for the description, and relation to the wl_buffer + * size. + * + * If width is -1 and height is -1, the destination size is unset + * instead. Any other pair of values for width and height that + * contains zero or negative values raises the bad_value protocol + * error. + * + * The crop and scale state is double-buffered, see wl_surface.commit. + */ +static inline void +wp_viewport_set_destination(struct wp_viewport *wp_viewport, int32_t width, int32_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_viewport, + WP_VIEWPORT_SET_DESTINATION, NULL, wl_proxy_get_version((struct wl_proxy *) wp_viewport), 0, width, height); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/host/linux/wayland/viewporter-protocol.c b/examples/host/linux/wayland/viewporter-protocol.c new file mode 100644 index 0000000..d685858 --- /dev/null +++ b/examples/host/linux/wayland/viewporter-protocol.c @@ -0,0 +1,75 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright © 2013-2016 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wp_viewport_interface; + +static const struct wl_interface *viewporter_types[] = { + NULL, + NULL, + NULL, + NULL, + &wp_viewport_interface, + &wl_surface_interface, +}; + +static const struct wl_message wp_viewporter_requests[] = { + { "destroy", "", viewporter_types + 0 }, + { "get_viewport", "no", viewporter_types + 4 }, +}; + +WL_PRIVATE const struct wl_interface wp_viewporter_interface = { + "wp_viewporter", 1, + 2, wp_viewporter_requests, + 0, NULL, +}; + +static const struct wl_message wp_viewport_requests[] = { + { "destroy", "", viewporter_types + 0 }, + { "set_source", "ffff", viewporter_types + 0 }, + { "set_destination", "ii", viewporter_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface wp_viewport_interface = { + "wp_viewport", 1, + 3, wp_viewport_requests, + 0, NULL, +}; + diff --git a/examples/host/linux/wayland/xdg-decoration-unstable-v1-client-protocol.h b/examples/host/linux/wayland/xdg-decoration-unstable-v1-client-protocol.h new file mode 100644 index 0000000..217af20 --- /dev/null +++ b/examples/host/linux/wayland/xdg-decoration-unstable-v1-client-protocol.h @@ -0,0 +1,384 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_xdg_decoration_unstable_v1 The xdg_decoration_unstable_v1 protocol + * @section page_ifaces_xdg_decoration_unstable_v1 Interfaces + * - @subpage page_iface_zxdg_decoration_manager_v1 - window decoration manager + * - @subpage page_iface_zxdg_toplevel_decoration_v1 - decoration object for a toplevel surface + * @section page_copyright_xdg_decoration_unstable_v1 Copyright + *
+ *
+ * Copyright © 2018 Simon Ser
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct xdg_toplevel; +struct zxdg_decoration_manager_v1; +struct zxdg_toplevel_decoration_v1; + +#ifndef ZXDG_DECORATION_MANAGER_V1_INTERFACE +#define ZXDG_DECORATION_MANAGER_V1_INTERFACE +/** + * @page page_iface_zxdg_decoration_manager_v1 zxdg_decoration_manager_v1 + * @section page_iface_zxdg_decoration_manager_v1_desc Description + * + * This interface allows a compositor to announce support for server-side + * decorations. + * + * A window decoration is a set of window controls as deemed appropriate by + * the party managing them, such as user interface components used to move, + * resize and change a window's state. + * + * A client can use this protocol to request being decorated by a supporting + * compositor. + * + * If compositor and client do not negotiate the use of a server-side + * decoration using this protocol, clients continue to self-decorate as they + * see fit. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zxdg_decoration_manager_v1_api API + * See @ref iface_zxdg_decoration_manager_v1. + */ +/** + * @defgroup iface_zxdg_decoration_manager_v1 The zxdg_decoration_manager_v1 interface + * + * This interface allows a compositor to announce support for server-side + * decorations. + * + * A window decoration is a set of window controls as deemed appropriate by + * the party managing them, such as user interface components used to move, + * resize and change a window's state. + * + * A client can use this protocol to request being decorated by a supporting + * compositor. + * + * If compositor and client do not negotiate the use of a server-side + * decoration using this protocol, clients continue to self-decorate as they + * see fit. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zxdg_decoration_manager_v1_interface; +#endif +#ifndef ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE +#define ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE +/** + * @page page_iface_zxdg_toplevel_decoration_v1 zxdg_toplevel_decoration_v1 + * @section page_iface_zxdg_toplevel_decoration_v1_desc Description + * + * The decoration object allows the compositor to toggle server-side window + * decorations for a toplevel surface. The client can request to switch to + * another mode. + * + * The xdg_toplevel_decoration object must be destroyed before its + * xdg_toplevel. + * @section page_iface_zxdg_toplevel_decoration_v1_api API + * See @ref iface_zxdg_toplevel_decoration_v1. + */ +/** + * @defgroup iface_zxdg_toplevel_decoration_v1 The zxdg_toplevel_decoration_v1 interface + * + * The decoration object allows the compositor to toggle server-side window + * decorations for a toplevel surface. The client can request to switch to + * another mode. + * + * The xdg_toplevel_decoration object must be destroyed before its + * xdg_toplevel. + */ +extern const struct wl_interface zxdg_toplevel_decoration_v1_interface; +#endif + +#define ZXDG_DECORATION_MANAGER_V1_DESTROY 0 +#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION 1 + + +/** + * @ingroup iface_zxdg_decoration_manager_v1 + */ +#define ZXDG_DECORATION_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zxdg_decoration_manager_v1 + */ +#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION_SINCE_VERSION 1 + +/** @ingroup iface_zxdg_decoration_manager_v1 */ +static inline void +zxdg_decoration_manager_v1_set_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zxdg_decoration_manager_v1, user_data); +} + +/** @ingroup iface_zxdg_decoration_manager_v1 */ +static inline void * +zxdg_decoration_manager_v1_get_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zxdg_decoration_manager_v1); +} + +static inline uint32_t +zxdg_decoration_manager_v1_get_version(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1); +} + +/** + * @ingroup iface_zxdg_decoration_manager_v1 + * + * Destroy the decoration manager. This doesn't destroy objects created + * with the manager. + */ +static inline void +zxdg_decoration_manager_v1_destroy(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zxdg_decoration_manager_v1, + ZXDG_DECORATION_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_zxdg_decoration_manager_v1 + * + * Create a new decoration object associated with the given toplevel. + * + * Creating an xdg_toplevel_decoration from an xdg_toplevel which has a + * buffer attached or committed is a client error, and any attempts by a + * client to attach or manipulate a buffer prior to the first + * xdg_toplevel_decoration.configure event must also be treated as + * errors. + */ +static inline struct zxdg_toplevel_decoration_v1 * +zxdg_decoration_manager_v1_get_toplevel_decoration(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, struct xdg_toplevel *toplevel) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) zxdg_decoration_manager_v1, + ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION, &zxdg_toplevel_decoration_v1_interface, wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1), 0, NULL, toplevel); + + return (struct zxdg_toplevel_decoration_v1 *) id; +} + +#ifndef ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM +#define ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM +enum zxdg_toplevel_decoration_v1_error { + /** + * xdg_toplevel has a buffer attached before configure + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER = 0, + /** + * xdg_toplevel already has a decoration object + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ALREADY_CONSTRUCTED = 1, + /** + * xdg_toplevel destroyed before the decoration object + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ORPHANED = 2, + /** + * invalid mode + */ + ZXDG_TOPLEVEL_DECORATION_V1_ERROR_INVALID_MODE = 3, +}; +#endif /* ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM */ + +#ifndef ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM +#define ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * window decoration modes + * + * These values describe window decoration modes. + */ +enum zxdg_toplevel_decoration_v1_mode { + /** + * no server-side window decoration + */ + ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE = 1, + /** + * server-side window decoration + */ + ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE = 2, +}; +#endif /* ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM */ + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * @struct zxdg_toplevel_decoration_v1_listener + */ +struct zxdg_toplevel_decoration_v1_listener { + /** + * notify a decoration mode change + * + * The configure event configures the effective decoration mode. + * The configured state should not be applied immediately. Clients + * must send an ack_configure in response to this event. See + * xdg_surface.configure and xdg_surface.ack_configure for details. + * + * A configure event can be sent at any time. The specified mode + * must be obeyed by the client. + * @param mode the decoration mode + */ + void (*configure)(void *data, + struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, + uint32_t mode); +}; + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +static inline int +zxdg_toplevel_decoration_v1_add_listener(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, + const struct zxdg_toplevel_decoration_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zxdg_toplevel_decoration_v1, + (void (**)(void)) listener, data); +} + +#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY 0 +#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE 1 +#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE 2 + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_CONFIGURE_SINCE_VERSION 1 + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE_SINCE_VERSION 1 +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + */ +#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE_SINCE_VERSION 1 + +/** @ingroup iface_zxdg_toplevel_decoration_v1 */ +static inline void +zxdg_toplevel_decoration_v1_set_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1, user_data); +} + +/** @ingroup iface_zxdg_toplevel_decoration_v1 */ +static inline void * +zxdg_toplevel_decoration_v1_get_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1); +} + +static inline uint32_t +zxdg_toplevel_decoration_v1_get_version(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1); +} + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * + * Switch back to a mode without any server-side decorations at the next + * commit. + */ +static inline void +zxdg_toplevel_decoration_v1_destroy(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1, + ZXDG_TOPLEVEL_DECORATION_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * + * Set the toplevel surface decoration mode. This informs the compositor + * that the client prefers the provided decoration mode. + * + * After requesting a decoration mode, the compositor will respond by + * emitting an xdg_surface.configure event. The client should then update + * its content, drawing it without decorations if the received mode is + * server-side decorations. The client must also acknowledge the configure + * when committing the new content (see xdg_surface.ack_configure). + * + * The compositor can decide not to use the client's mode and enforce a + * different mode instead. + * + * Clients whose decoration mode depend on the xdg_toplevel state may send + * a set_mode request in response to an xdg_surface.configure event and wait + * for the next xdg_surface.configure event to prevent unwanted state. + * Such clients are responsible for preventing configure loops and must + * make sure not to send multiple successive set_mode requests with the + * same decoration mode. + * + * If an invalid mode is supplied by the client, the invalid_mode protocol + * error is raised by the compositor. + */ +static inline void +zxdg_toplevel_decoration_v1_set_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1, + ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), 0, mode); +} + +/** + * @ingroup iface_zxdg_toplevel_decoration_v1 + * + * Unset the toplevel surface decoration mode. This informs the compositor + * that the client doesn't prefer a particular decoration mode. + * + * This request has the same semantics as set_mode. + */ +static inline void +zxdg_toplevel_decoration_v1_unset_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1, + ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), 0); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/host/linux/wayland/xdg-decoration-unstable-v1-protocol.c b/examples/host/linux/wayland/xdg-decoration-unstable-v1-protocol.c new file mode 100644 index 0000000..85496af --- /dev/null +++ b/examples/host/linux/wayland/xdg-decoration-unstable-v1-protocol.c @@ -0,0 +1,76 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright © 2018 Simon Ser + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface xdg_toplevel_interface; +extern const struct wl_interface zxdg_toplevel_decoration_v1_interface; + +static const struct wl_interface *xdg_decoration_unstable_v1_types[] = { + NULL, + &zxdg_toplevel_decoration_v1_interface, + &xdg_toplevel_interface, +}; + +static const struct wl_message zxdg_decoration_manager_v1_requests[] = { + { "destroy", "", xdg_decoration_unstable_v1_types + 0 }, + { "get_toplevel_decoration", "no", xdg_decoration_unstable_v1_types + 1 }, +}; + +WL_PRIVATE const struct wl_interface zxdg_decoration_manager_v1_interface = { + "zxdg_decoration_manager_v1", 1, + 2, zxdg_decoration_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message zxdg_toplevel_decoration_v1_requests[] = { + { "destroy", "", xdg_decoration_unstable_v1_types + 0 }, + { "set_mode", "u", xdg_decoration_unstable_v1_types + 0 }, + { "unset_mode", "", xdg_decoration_unstable_v1_types + 0 }, +}; + +static const struct wl_message zxdg_toplevel_decoration_v1_events[] = { + { "configure", "u", xdg_decoration_unstable_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zxdg_toplevel_decoration_v1_interface = { + "zxdg_toplevel_decoration_v1", 1, + 3, zxdg_toplevel_decoration_v1_requests, + 1, zxdg_toplevel_decoration_v1_events, +}; + diff --git a/examples/host/linux/wayland/xdg-shell-client-protocol.h b/examples/host/linux/wayland/xdg-shell-client-protocol.h new file mode 100644 index 0000000..1f077b4 --- /dev/null +++ b/examples/host/linux/wayland/xdg-shell-client-protocol.h @@ -0,0 +1,2325 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef XDG_SHELL_CLIENT_PROTOCOL_H +#define XDG_SHELL_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_xdg_shell The xdg_shell protocol + * @section page_ifaces_xdg_shell Interfaces + * - @subpage page_iface_xdg_wm_base - create desktop-style surfaces + * - @subpage page_iface_xdg_positioner - child surface positioner + * - @subpage page_iface_xdg_surface - desktop user interface surface base interface + * - @subpage page_iface_xdg_toplevel - toplevel surface + * - @subpage page_iface_xdg_popup - short-lived, popup surfaces for menus + * @section page_copyright_xdg_shell Copyright + *
+ *
+ * Copyright © 2008-2013 Kristian Høgsberg
+ * Copyright © 2013      Rafael Antognolli
+ * Copyright © 2013      Jasper St. Pierre
+ * Copyright © 2010-2013 Intel Corporation
+ * Copyright © 2015-2017 Samsung Electronics Co., Ltd
+ * Copyright © 2015-2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_output; +struct wl_seat; +struct wl_surface; +struct xdg_popup; +struct xdg_positioner; +struct xdg_surface; +struct xdg_toplevel; +struct xdg_wm_base; + +#ifndef XDG_WM_BASE_INTERFACE +#define XDG_WM_BASE_INTERFACE +/** + * @page page_iface_xdg_wm_base xdg_wm_base + * @section page_iface_xdg_wm_base_desc Description + * + * The xdg_wm_base interface is exposed as a global object enabling clients + * to turn their wl_surfaces into windows in a desktop environment. It + * defines the basic functionality needed for clients and the compositor to + * create windows that can be dragged, resized, maximized, etc, as well as + * creating transient windows such as popup menus. + * @section page_iface_xdg_wm_base_api API + * See @ref iface_xdg_wm_base. + */ +/** + * @defgroup iface_xdg_wm_base The xdg_wm_base interface + * + * The xdg_wm_base interface is exposed as a global object enabling clients + * to turn their wl_surfaces into windows in a desktop environment. It + * defines the basic functionality needed for clients and the compositor to + * create windows that can be dragged, resized, maximized, etc, as well as + * creating transient windows such as popup menus. + */ +extern const struct wl_interface xdg_wm_base_interface; +#endif +#ifndef XDG_POSITIONER_INTERFACE +#define XDG_POSITIONER_INTERFACE +/** + * @page page_iface_xdg_positioner xdg_positioner + * @section page_iface_xdg_positioner_desc Description + * + * The xdg_positioner provides a collection of rules for the placement of a + * child surface relative to a parent surface. Rules can be defined to ensure + * the child surface remains within the visible area's borders, and to + * specify how the child surface changes its position, such as sliding along + * an axis, or flipping around a rectangle. These positioner-created rules are + * constrained by the requirement that a child surface must intersect with or + * be at least partially adjacent to its parent surface. + * + * See the various requests for details about possible rules. + * + * At the time of the request, the compositor makes a copy of the rules + * specified by the xdg_positioner. Thus, after the request is complete the + * xdg_positioner object can be destroyed or reused; further changes to the + * object will have no effect on previous usages. + * + * For an xdg_positioner object to be considered complete, it must have a + * non-zero size set by set_size, and a non-zero anchor rectangle set by + * set_anchor_rect. Passing an incomplete xdg_positioner object when + * positioning a surface raises an invalid_positioner error. + * @section page_iface_xdg_positioner_api API + * See @ref iface_xdg_positioner. + */ +/** + * @defgroup iface_xdg_positioner The xdg_positioner interface + * + * The xdg_positioner provides a collection of rules for the placement of a + * child surface relative to a parent surface. Rules can be defined to ensure + * the child surface remains within the visible area's borders, and to + * specify how the child surface changes its position, such as sliding along + * an axis, or flipping around a rectangle. These positioner-created rules are + * constrained by the requirement that a child surface must intersect with or + * be at least partially adjacent to its parent surface. + * + * See the various requests for details about possible rules. + * + * At the time of the request, the compositor makes a copy of the rules + * specified by the xdg_positioner. Thus, after the request is complete the + * xdg_positioner object can be destroyed or reused; further changes to the + * object will have no effect on previous usages. + * + * For an xdg_positioner object to be considered complete, it must have a + * non-zero size set by set_size, and a non-zero anchor rectangle set by + * set_anchor_rect. Passing an incomplete xdg_positioner object when + * positioning a surface raises an invalid_positioner error. + */ +extern const struct wl_interface xdg_positioner_interface; +#endif +#ifndef XDG_SURFACE_INTERFACE +#define XDG_SURFACE_INTERFACE +/** + * @page page_iface_xdg_surface xdg_surface + * @section page_iface_xdg_surface_desc Description + * + * An interface that may be implemented by a wl_surface, for + * implementations that provide a desktop-style user interface. + * + * It provides a base set of functionality required to construct user + * interface elements requiring management by the compositor, such as + * toplevel windows, menus, etc. The types of functionality are split into + * xdg_surface roles. + * + * Creating an xdg_surface does not set the role for a wl_surface. In order + * to map an xdg_surface, the client must create a role-specific object + * using, e.g., get_toplevel, get_popup. The wl_surface for any given + * xdg_surface can have at most one role, and may not be assigned any role + * not based on xdg_surface. + * + * A role must be assigned before any other requests are made to the + * xdg_surface object. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_surface state to take effect. + * + * Creating an xdg_surface from a wl_surface which has a buffer attached or + * committed is a client error, and any attempts by a client to attach or + * manipulate a buffer prior to the first xdg_surface.configure call must + * also be treated as errors. + * + * After creating a role-specific object and setting it up (e.g. by sending + * the title, app ID, size constraints, parent, etc), the client must + * perform an initial commit without any buffer attached. The compositor + * will reply with initial wl_surface state such as + * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure + * event. The client must acknowledge it and is then allowed to attach a + * buffer to map the surface. + * + * Mapping an xdg_surface-based role surface is defined as making it + * possible for the surface to be shown by the compositor. Note that + * a mapped surface is not guaranteed to be visible once it is mapped. + * + * For an xdg_surface to be mapped by the compositor, the following + * conditions must be met: + * (1) the client has assigned an xdg_surface-based role to the surface + * (2) the client has set and committed the xdg_surface state and the + * role-dependent state to the surface + * (3) the client has committed a buffer to the surface + * + * A newly-unmapped surface is considered to have met condition (1) out + * of the 3 required conditions for mapping a surface if its role surface + * has not been destroyed, i.e. the client must perform the initial commit + * again before attaching a buffer. + * @section page_iface_xdg_surface_api API + * See @ref iface_xdg_surface. + */ +/** + * @defgroup iface_xdg_surface The xdg_surface interface + * + * An interface that may be implemented by a wl_surface, for + * implementations that provide a desktop-style user interface. + * + * It provides a base set of functionality required to construct user + * interface elements requiring management by the compositor, such as + * toplevel windows, menus, etc. The types of functionality are split into + * xdg_surface roles. + * + * Creating an xdg_surface does not set the role for a wl_surface. In order + * to map an xdg_surface, the client must create a role-specific object + * using, e.g., get_toplevel, get_popup. The wl_surface for any given + * xdg_surface can have at most one role, and may not be assigned any role + * not based on xdg_surface. + * + * A role must be assigned before any other requests are made to the + * xdg_surface object. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_surface state to take effect. + * + * Creating an xdg_surface from a wl_surface which has a buffer attached or + * committed is a client error, and any attempts by a client to attach or + * manipulate a buffer prior to the first xdg_surface.configure call must + * also be treated as errors. + * + * After creating a role-specific object and setting it up (e.g. by sending + * the title, app ID, size constraints, parent, etc), the client must + * perform an initial commit without any buffer attached. The compositor + * will reply with initial wl_surface state such as + * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure + * event. The client must acknowledge it and is then allowed to attach a + * buffer to map the surface. + * + * Mapping an xdg_surface-based role surface is defined as making it + * possible for the surface to be shown by the compositor. Note that + * a mapped surface is not guaranteed to be visible once it is mapped. + * + * For an xdg_surface to be mapped by the compositor, the following + * conditions must be met: + * (1) the client has assigned an xdg_surface-based role to the surface + * (2) the client has set and committed the xdg_surface state and the + * role-dependent state to the surface + * (3) the client has committed a buffer to the surface + * + * A newly-unmapped surface is considered to have met condition (1) out + * of the 3 required conditions for mapping a surface if its role surface + * has not been destroyed, i.e. the client must perform the initial commit + * again before attaching a buffer. + */ +extern const struct wl_interface xdg_surface_interface; +#endif +#ifndef XDG_TOPLEVEL_INTERFACE +#define XDG_TOPLEVEL_INTERFACE +/** + * @page page_iface_xdg_toplevel xdg_toplevel + * @section page_iface_xdg_toplevel_desc Description + * + * This interface defines an xdg_surface role which allows a surface to, + * among other things, set window-like properties such as maximize, + * fullscreen, and minimize, set application-specific metadata like title and + * id, and well as trigger user interactive operations such as interactive + * resize and move. + * + * A xdg_toplevel by default is responsible for providing the full intended + * visual representation of the toplevel, which depending on the window + * state, may mean things like a title bar, window controls and drop shadow. + * + * Unmapping an xdg_toplevel means that the surface cannot be shown + * by the compositor until it is explicitly mapped again. + * All active operations (e.g., move, resize) are canceled and all + * attributes (e.g. title, state, stacking, ...) are discarded for + * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to + * the state it had right after xdg_surface.get_toplevel. The client + * can re-map the toplevel by performing a commit without any buffer + * attached, waiting for a configure event and handling it as usual (see + * xdg_surface description). + * + * Attaching a null buffer to a toplevel unmaps the surface. + * @section page_iface_xdg_toplevel_api API + * See @ref iface_xdg_toplevel. + */ +/** + * @defgroup iface_xdg_toplevel The xdg_toplevel interface + * + * This interface defines an xdg_surface role which allows a surface to, + * among other things, set window-like properties such as maximize, + * fullscreen, and minimize, set application-specific metadata like title and + * id, and well as trigger user interactive operations such as interactive + * resize and move. + * + * A xdg_toplevel by default is responsible for providing the full intended + * visual representation of the toplevel, which depending on the window + * state, may mean things like a title bar, window controls and drop shadow. + * + * Unmapping an xdg_toplevel means that the surface cannot be shown + * by the compositor until it is explicitly mapped again. + * All active operations (e.g., move, resize) are canceled and all + * attributes (e.g. title, state, stacking, ...) are discarded for + * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to + * the state it had right after xdg_surface.get_toplevel. The client + * can re-map the toplevel by performing a commit without any buffer + * attached, waiting for a configure event and handling it as usual (see + * xdg_surface description). + * + * Attaching a null buffer to a toplevel unmaps the surface. + */ +extern const struct wl_interface xdg_toplevel_interface; +#endif +#ifndef XDG_POPUP_INTERFACE +#define XDG_POPUP_INTERFACE +/** + * @page page_iface_xdg_popup xdg_popup + * @section page_iface_xdg_popup_desc Description + * + * A popup surface is a short-lived, temporary surface. It can be used to + * implement for example menus, popovers, tooltips and other similar user + * interface concepts. + * + * A popup can be made to take an explicit grab. See xdg_popup.grab for + * details. + * + * When the popup is dismissed, a popup_done event will be sent out, and at + * the same time the surface will be unmapped. See the xdg_popup.popup_done + * event for details. + * + * Explicitly destroying the xdg_popup object will also dismiss the popup and + * unmap the surface. Clients that want to dismiss the popup when another + * surface of their own is clicked should dismiss the popup using the destroy + * request. + * + * A newly created xdg_popup will be stacked on top of all previously created + * xdg_popup surfaces associated with the same xdg_toplevel. + * + * The parent of an xdg_popup must be mapped (see the xdg_surface + * description) before the xdg_popup itself. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_popup state to take effect. + * @section page_iface_xdg_popup_api API + * See @ref iface_xdg_popup. + */ +/** + * @defgroup iface_xdg_popup The xdg_popup interface + * + * A popup surface is a short-lived, temporary surface. It can be used to + * implement for example menus, popovers, tooltips and other similar user + * interface concepts. + * + * A popup can be made to take an explicit grab. See xdg_popup.grab for + * details. + * + * When the popup is dismissed, a popup_done event will be sent out, and at + * the same time the surface will be unmapped. See the xdg_popup.popup_done + * event for details. + * + * Explicitly destroying the xdg_popup object will also dismiss the popup and + * unmap the surface. Clients that want to dismiss the popup when another + * surface of their own is clicked should dismiss the popup using the destroy + * request. + * + * A newly created xdg_popup will be stacked on top of all previously created + * xdg_popup surfaces associated with the same xdg_toplevel. + * + * The parent of an xdg_popup must be mapped (see the xdg_surface + * description) before the xdg_popup itself. + * + * The client must call wl_surface.commit on the corresponding wl_surface + * for the xdg_popup state to take effect. + */ +extern const struct wl_interface xdg_popup_interface; +#endif + +#ifndef XDG_WM_BASE_ERROR_ENUM +#define XDG_WM_BASE_ERROR_ENUM +enum xdg_wm_base_error { + /** + * given wl_surface has another role + */ + XDG_WM_BASE_ERROR_ROLE = 0, + /** + * xdg_wm_base was destroyed before children + */ + XDG_WM_BASE_ERROR_DEFUNCT_SURFACES = 1, + /** + * the client tried to map or destroy a non-topmost popup + */ + XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP = 2, + /** + * the client specified an invalid popup parent surface + */ + XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT = 3, + /** + * the client provided an invalid surface state + */ + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE = 4, + /** + * the client provided an invalid positioner + */ + XDG_WM_BASE_ERROR_INVALID_POSITIONER = 5, + /** + * the client didn’t respond to a ping event in time + */ + XDG_WM_BASE_ERROR_UNRESPONSIVE = 6, +}; +#endif /* XDG_WM_BASE_ERROR_ENUM */ + +/** + * @ingroup iface_xdg_wm_base + * @struct xdg_wm_base_listener + */ +struct xdg_wm_base_listener { + /** + * check if the client is alive + * + * The ping event asks the client if it's still alive. Pass the + * serial specified in the event back to the compositor by sending + * a "pong" request back with the specified serial. See + * xdg_wm_base.pong. + * + * Compositors can use this to determine if the client is still + * alive. It's unspecified what will happen if the client doesn't + * respond to the ping request, or in what timeframe. Clients + * should try to respond in a reasonable amount of time. The + * “unresponsive” error is provided for compositors that wish + * to disconnect unresponsive clients. + * + * A compositor is free to ping in any way it wants, but a client + * must always respond to any xdg_wm_base object it created. + * @param serial pass this to the pong request + */ + void (*ping)(void *data, + struct xdg_wm_base *xdg_wm_base, + uint32_t serial); +}; + +/** + * @ingroup iface_xdg_wm_base + */ +static inline int +xdg_wm_base_add_listener(struct xdg_wm_base *xdg_wm_base, + const struct xdg_wm_base_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_wm_base, + (void (**)(void)) listener, data); +} + +#define XDG_WM_BASE_DESTROY 0 +#define XDG_WM_BASE_CREATE_POSITIONER 1 +#define XDG_WM_BASE_GET_XDG_SURFACE 2 +#define XDG_WM_BASE_PONG 3 + +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_PING_SINCE_VERSION 1 + +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_CREATE_POSITIONER_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_wm_base + */ +#define XDG_WM_BASE_PONG_SINCE_VERSION 1 + +/** @ingroup iface_xdg_wm_base */ +static inline void +xdg_wm_base_set_user_data(struct xdg_wm_base *xdg_wm_base, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_wm_base, user_data); +} + +/** @ingroup iface_xdg_wm_base */ +static inline void * +xdg_wm_base_get_user_data(struct xdg_wm_base *xdg_wm_base) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_wm_base); +} + +static inline uint32_t +xdg_wm_base_get_version(struct xdg_wm_base *xdg_wm_base) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_wm_base); +} + +/** + * @ingroup iface_xdg_wm_base + * + * Destroy this xdg_wm_base object. + * + * Destroying a bound xdg_wm_base object while there are surfaces + * still alive created by this xdg_wm_base object instance is illegal + * and will result in a defunct_surfaces error. + */ +static inline void +xdg_wm_base_destroy(struct xdg_wm_base *xdg_wm_base) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_xdg_wm_base + * + * Create a positioner object. A positioner object is used to position + * surfaces relative to some parent surface. See the interface description + * and xdg_surface.get_popup for details. + */ +static inline struct xdg_positioner * +xdg_wm_base_create_positioner(struct xdg_wm_base *xdg_wm_base) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_CREATE_POSITIONER, &xdg_positioner_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL); + + return (struct xdg_positioner *) id; +} + +/** + * @ingroup iface_xdg_wm_base + * + * This creates an xdg_surface for the given surface. While xdg_surface + * itself is not a role, the corresponding surface may only be assigned + * a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is + * illegal to create an xdg_surface for a wl_surface which already has an + * assigned role and this will result in a role error. + * + * This creates an xdg_surface for the given surface. An xdg_surface is + * used as basis to define a role to a given surface, such as xdg_toplevel + * or xdg_popup. It also manages functionality shared between xdg_surface + * based surface roles. + * + * See the documentation of xdg_surface for more details about what an + * xdg_surface is and how it is used. + */ +static inline struct xdg_surface * +xdg_wm_base_get_xdg_surface(struct xdg_wm_base *xdg_wm_base, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_GET_XDG_SURFACE, &xdg_surface_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL, surface); + + return (struct xdg_surface *) id; +} + +/** + * @ingroup iface_xdg_wm_base + * + * A client must respond to a ping event with a pong request or + * the client may be deemed unresponsive. See xdg_wm_base.ping + * and xdg_wm_base.error.unresponsive. + */ +static inline void +xdg_wm_base_pong(struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, + XDG_WM_BASE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, serial); +} + +#ifndef XDG_POSITIONER_ERROR_ENUM +#define XDG_POSITIONER_ERROR_ENUM +enum xdg_positioner_error { + /** + * invalid input provided + */ + XDG_POSITIONER_ERROR_INVALID_INPUT = 0, +}; +#endif /* XDG_POSITIONER_ERROR_ENUM */ + +#ifndef XDG_POSITIONER_ANCHOR_ENUM +#define XDG_POSITIONER_ANCHOR_ENUM +enum xdg_positioner_anchor { + XDG_POSITIONER_ANCHOR_NONE = 0, + XDG_POSITIONER_ANCHOR_TOP = 1, + XDG_POSITIONER_ANCHOR_BOTTOM = 2, + XDG_POSITIONER_ANCHOR_LEFT = 3, + XDG_POSITIONER_ANCHOR_RIGHT = 4, + XDG_POSITIONER_ANCHOR_TOP_LEFT = 5, + XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6, + XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7, + XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8, +}; +#endif /* XDG_POSITIONER_ANCHOR_ENUM */ + +#ifndef XDG_POSITIONER_GRAVITY_ENUM +#define XDG_POSITIONER_GRAVITY_ENUM +enum xdg_positioner_gravity { + XDG_POSITIONER_GRAVITY_NONE = 0, + XDG_POSITIONER_GRAVITY_TOP = 1, + XDG_POSITIONER_GRAVITY_BOTTOM = 2, + XDG_POSITIONER_GRAVITY_LEFT = 3, + XDG_POSITIONER_GRAVITY_RIGHT = 4, + XDG_POSITIONER_GRAVITY_TOP_LEFT = 5, + XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6, + XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7, + XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8, +}; +#endif /* XDG_POSITIONER_GRAVITY_ENUM */ + +#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM +#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM +/** + * @ingroup iface_xdg_positioner + * constraint adjustments + * + * The constraint adjustment value define ways the compositor will adjust + * the position of the surface, if the unadjusted position would result + * in the surface being partly constrained. + * + * Whether a surface is considered 'constrained' is left to the compositor + * to determine. For example, the surface may be partly outside the + * compositor's defined 'work area', thus necessitating the child surface's + * position be adjusted until it is entirely inside the work area. + * + * The adjustments can be combined, according to a defined precedence: 1) + * Flip, 2) Slide, 3) Resize. + */ +enum xdg_positioner_constraint_adjustment { + /** + * don't move the child surface when constrained + * + * Don't alter the surface position even if it is constrained on + * some axis, for example partially outside the edge of an output. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0, + /** + * move along the x axis until unconstrained + * + * Slide the surface along the x axis until it is no longer + * constrained. + * + * First try to slide towards the direction of the gravity on the x + * axis until either the edge in the opposite direction of the + * gravity is unconstrained or the edge in the direction of the + * gravity is constrained. + * + * Then try to slide towards the opposite direction of the gravity + * on the x axis until either the edge in the direction of the + * gravity is unconstrained or the edge in the opposite direction + * of the gravity is constrained. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, + /** + * move along the y axis until unconstrained + * + * Slide the surface along the y axis until it is no longer + * constrained. + * + * First try to slide towards the direction of the gravity on the y + * axis until either the edge in the opposite direction of the + * gravity is unconstrained or the edge in the direction of the + * gravity is constrained. + * + * Then try to slide towards the opposite direction of the gravity + * on the y axis until either the edge in the direction of the + * gravity is unconstrained or the edge in the opposite direction + * of the gravity is constrained. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, + /** + * invert the anchor and gravity on the x axis + * + * Invert the anchor and gravity on the x axis if the surface is + * constrained on the x axis. For example, if the left edge of the + * surface is constrained, the gravity is 'left' and the anchor is + * 'left', change the gravity to 'right' and the anchor to 'right'. + * + * If the adjusted position also ends up being constrained, the + * resulting position of the flip_x adjustment will be the one + * before the adjustment. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, + /** + * invert the anchor and gravity on the y axis + * + * Invert the anchor and gravity on the y axis if the surface is + * constrained on the y axis. For example, if the bottom edge of + * the surface is constrained, the gravity is 'bottom' and the + * anchor is 'bottom', change the gravity to 'top' and the anchor + * to 'top'. + * + * The adjusted position is calculated given the original anchor + * rectangle and offset, but with the new flipped anchor and + * gravity values. + * + * If the adjusted position also ends up being constrained, the + * resulting position of the flip_y adjustment will be the one + * before the adjustment. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, + /** + * horizontally resize the surface + * + * Resize the surface horizontally so that it is completely + * unconstrained. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, + /** + * vertically resize the surface + * + * Resize the surface vertically so that it is completely + * unconstrained. + */ + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, +}; +#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM */ + +#define XDG_POSITIONER_DESTROY 0 +#define XDG_POSITIONER_SET_SIZE 1 +#define XDG_POSITIONER_SET_ANCHOR_RECT 2 +#define XDG_POSITIONER_SET_ANCHOR 3 +#define XDG_POSITIONER_SET_GRAVITY 4 +#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT 5 +#define XDG_POSITIONER_SET_OFFSET 6 +#define XDG_POSITIONER_SET_REACTIVE 7 +#define XDG_POSITIONER_SET_PARENT_SIZE 8 +#define XDG_POSITIONER_SET_PARENT_CONFIGURE 9 + + +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_SIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_ANCHOR_RECT_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_ANCHOR_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_GRAVITY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3 +/** + * @ingroup iface_xdg_positioner + */ +#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3 + +/** @ingroup iface_xdg_positioner */ +static inline void +xdg_positioner_set_user_data(struct xdg_positioner *xdg_positioner, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_positioner, user_data); +} + +/** @ingroup iface_xdg_positioner */ +static inline void * +xdg_positioner_get_user_data(struct xdg_positioner *xdg_positioner) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_positioner); +} + +static inline uint32_t +xdg_positioner_get_version(struct xdg_positioner *xdg_positioner) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_positioner); +} + +/** + * @ingroup iface_xdg_positioner + * + * Notify the compositor that the xdg_positioner will no longer be used. + */ +static inline void +xdg_positioner_destroy(struct xdg_positioner *xdg_positioner) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_xdg_positioner + * + * Set the size of the surface that is to be positioned with the positioner + * object. The size is in surface-local coordinates and corresponds to the + * window geometry. See xdg_surface.set_window_geometry. + * + * If a zero or negative size is set the invalid_input error is raised. + */ +static inline void +xdg_positioner_set_size(struct xdg_positioner *xdg_positioner, int32_t width, int32_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, width, height); +} + +/** + * @ingroup iface_xdg_positioner + * + * Specify the anchor rectangle within the parent surface that the child + * surface will be placed relative to. The rectangle is relative to the + * window geometry as defined by xdg_surface.set_window_geometry of the + * parent surface. + * + * When the xdg_positioner object is used to position a child surface, the + * anchor rectangle may not extend outside the window geometry of the + * positioned child's parent surface. + * + * If a negative size is set the invalid_input error is raised. + */ +static inline void +xdg_positioner_set_anchor_rect(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_ANCHOR_RECT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y, width, height); +} + +/** + * @ingroup iface_xdg_positioner + * + * Defines the anchor point for the anchor rectangle. The specified anchor + * is used derive an anchor point that the child surface will be + * positioned relative to. If a corner anchor is set (e.g. 'top_left' or + * 'bottom_right'), the anchor point will be at the specified corner; + * otherwise, the derived anchor point will be centered on the specified + * edge, or in the center of the anchor rectangle if no edge is specified. + */ +static inline void +xdg_positioner_set_anchor(struct xdg_positioner *xdg_positioner, uint32_t anchor) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_ANCHOR, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, anchor); +} + +/** + * @ingroup iface_xdg_positioner + * + * Defines in what direction a surface should be positioned, relative to + * the anchor point of the parent surface. If a corner gravity is + * specified (e.g. 'bottom_right' or 'top_left'), then the child surface + * will be placed towards the specified gravity; otherwise, the child + * surface will be centered over the anchor point on any axis that had no + * gravity specified. If the gravity is not in the ‘gravity’ enum, an + * invalid_input error is raised. + */ +static inline void +xdg_positioner_set_gravity(struct xdg_positioner *xdg_positioner, uint32_t gravity) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_GRAVITY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, gravity); +} + +/** + * @ingroup iface_xdg_positioner + * + * Specify how the window should be positioned if the originally intended + * position caused the surface to be constrained, meaning at least + * partially outside positioning boundaries set by the compositor. The + * adjustment is set by constructing a bitmask describing the adjustment to + * be made when the surface is constrained on that axis. + * + * If no bit for one axis is set, the compositor will assume that the child + * surface should not change its position on that axis when constrained. + * + * If more than one bit for one axis is set, the order of how adjustments + * are applied is specified in the corresponding adjustment descriptions. + * + * The default adjustment is none. + */ +static inline void +xdg_positioner_set_constraint_adjustment(struct xdg_positioner *xdg_positioner, uint32_t constraint_adjustment) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, constraint_adjustment); +} + +/** + * @ingroup iface_xdg_positioner + * + * Specify the surface position offset relative to the position of the + * anchor on the anchor rectangle and the anchor on the surface. For + * example if the anchor of the anchor rectangle is at (x, y), the surface + * has the gravity bottom|right, and the offset is (ox, oy), the calculated + * surface position will be (x + ox, y + oy). The offset position of the + * surface is the one used for constraint testing. See + * set_constraint_adjustment. + * + * An example use case is placing a popup menu on top of a user interface + * element, while aligning the user interface element of the parent surface + * with some user interface element placed somewhere in the popup surface. + */ +static inline void +xdg_positioner_set_offset(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_OFFSET, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y); +} + +/** + * @ingroup iface_xdg_positioner + * + * When set reactive, the surface is reconstrained if the conditions used + * for constraining changed, e.g. the parent window moved. + * + * If the conditions changed and the popup was reconstrained, an + * xdg_popup.configure event is sent with updated geometry, followed by an + * xdg_surface.configure event. + */ +static inline void +xdg_positioner_set_reactive(struct xdg_positioner *xdg_positioner) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_REACTIVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0); +} + +/** + * @ingroup iface_xdg_positioner + * + * Set the parent window geometry the compositor should use when + * positioning the popup. The compositor may use this information to + * determine the future state the popup should be constrained using. If + * this doesn't match the dimension of the parent the popup is eventually + * positioned against, the behavior is undefined. + * + * The arguments are given in the surface-local coordinate space. + */ +static inline void +xdg_positioner_set_parent_size(struct xdg_positioner *xdg_positioner, int32_t parent_width, int32_t parent_height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_PARENT_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, parent_width, parent_height); +} + +/** + * @ingroup iface_xdg_positioner + * + * Set the serial of an xdg_surface.configure event this positioner will be + * used in response to. The compositor may use this information together + * with set_parent_size to determine what future state the popup should be + * constrained using. + */ +static inline void +xdg_positioner_set_parent_configure(struct xdg_positioner *xdg_positioner, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, + XDG_POSITIONER_SET_PARENT_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, serial); +} + +#ifndef XDG_SURFACE_ERROR_ENUM +#define XDG_SURFACE_ERROR_ENUM +enum xdg_surface_error { + /** + * Surface was not fully constructed + */ + XDG_SURFACE_ERROR_NOT_CONSTRUCTED = 1, + /** + * Surface was already constructed + */ + XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED = 2, + /** + * Attaching a buffer to an unconfigured surface + */ + XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER = 3, + /** + * Invalid serial number when acking a configure event + */ + XDG_SURFACE_ERROR_INVALID_SERIAL = 4, + /** + * Width or height was zero or negative + */ + XDG_SURFACE_ERROR_INVALID_SIZE = 5, + /** + * Surface was destroyed before its role object + */ + XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT = 6, +}; +#endif /* XDG_SURFACE_ERROR_ENUM */ + +/** + * @ingroup iface_xdg_surface + * @struct xdg_surface_listener + */ +struct xdg_surface_listener { + /** + * suggest a surface change + * + * The configure event marks the end of a configure sequence. A + * configure sequence is a set of one or more events configuring + * the state of the xdg_surface, including the final + * xdg_surface.configure event. + * + * Where applicable, xdg_surface surface roles will during a + * configure sequence extend this event as a latched state sent as + * events before the xdg_surface.configure event. Such events + * should be considered to make up a set of atomically applied + * configuration states, where the xdg_surface.configure commits + * the accumulated state. + * + * Clients should arrange their surface for the new states, and + * then send an ack_configure request with the serial sent in this + * configure event at some point before committing the new surface. + * + * If the client receives multiple configure events before it can + * respond to one, it is free to discard all but the last event it + * received. + * @param serial serial of the configure event + */ + void (*configure)(void *data, + struct xdg_surface *xdg_surface, + uint32_t serial); +}; + +/** + * @ingroup iface_xdg_surface + */ +static inline int +xdg_surface_add_listener(struct xdg_surface *xdg_surface, + const struct xdg_surface_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_surface, + (void (**)(void)) listener, data); +} + +#define XDG_SURFACE_DESTROY 0 +#define XDG_SURFACE_GET_TOPLEVEL 1 +#define XDG_SURFACE_GET_POPUP 2 +#define XDG_SURFACE_SET_WINDOW_GEOMETRY 3 +#define XDG_SURFACE_ACK_CONFIGURE 4 + +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_CONFIGURE_SINCE_VERSION 1 + +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_GET_TOPLEVEL_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_GET_POPUP_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_SET_WINDOW_GEOMETRY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_surface + */ +#define XDG_SURFACE_ACK_CONFIGURE_SINCE_VERSION 1 + +/** @ingroup iface_xdg_surface */ +static inline void +xdg_surface_set_user_data(struct xdg_surface *xdg_surface, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_surface, user_data); +} + +/** @ingroup iface_xdg_surface */ +static inline void * +xdg_surface_get_user_data(struct xdg_surface *xdg_surface) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_surface); +} + +static inline uint32_t +xdg_surface_get_version(struct xdg_surface *xdg_surface) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_surface); +} + +/** + * @ingroup iface_xdg_surface + * + * Destroy the xdg_surface object. An xdg_surface must only be destroyed + * after its role object has been destroyed, otherwise + * a defunct_role_object error is raised. + */ +static inline void +xdg_surface_destroy(struct xdg_surface *xdg_surface) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, + XDG_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_xdg_surface + * + * This creates an xdg_toplevel object for the given xdg_surface and gives + * the associated wl_surface the xdg_toplevel role. + * + * See the documentation of xdg_toplevel for more details about what an + * xdg_toplevel is and how it is used. + */ +static inline struct xdg_toplevel * +xdg_surface_get_toplevel(struct xdg_surface *xdg_surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, + XDG_SURFACE_GET_TOPLEVEL, &xdg_toplevel_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL); + + return (struct xdg_toplevel *) id; +} + +/** + * @ingroup iface_xdg_surface + * + * This creates an xdg_popup object for the given xdg_surface and gives + * the associated wl_surface the xdg_popup role. + * + * If null is passed as a parent, a parent surface must be specified using + * some other protocol, before committing the initial state. + * + * See the documentation of xdg_popup for more details about what an + * xdg_popup is and how it is used. + */ +static inline struct xdg_popup * +xdg_surface_get_popup(struct xdg_surface *xdg_surface, struct xdg_surface *parent, struct xdg_positioner *positioner) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, + XDG_SURFACE_GET_POPUP, &xdg_popup_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL, parent, positioner); + + return (struct xdg_popup *) id; +} + +/** + * @ingroup iface_xdg_surface + * + * The window geometry of a surface is its "visible bounds" from the + * user's perspective. Client-side decorations often have invisible + * portions like drop-shadows which should be ignored for the + * purposes of aligning, placing and constraining windows. + * + * The window geometry is double-buffered state, see wl_surface.commit. + * + * When maintaining a position, the compositor should treat the (x, y) + * coordinate of the window geometry as the top left corner of the window. + * A client changing the (x, y) window geometry coordinate should in + * general not alter the position of the window. + * + * Once the window geometry of the surface is set, it is not possible to + * unset it, and it will remain the same until set_window_geometry is + * called again, even if a new subsurface or buffer is attached. + * + * If never set, the value is the full bounds of the surface, + * including any subsurfaces. This updates dynamically on every + * commit. This unset is meant for extremely simple clients. + * + * The arguments are given in the surface-local coordinate space of + * the wl_surface associated with this xdg_surface, and may extend outside + * of the wl_surface itself to mark parts of the subsurface tree as part of + * the window geometry. + * + * When applied, the effective window geometry will be the set window + * geometry clamped to the bounding rectangle of the combined + * geometry of the surface of the xdg_surface and the associated + * subsurfaces. + * + * The effective geometry will not be recalculated unless a new call to + * set_window_geometry is done and the new pending surface state is + * subsequently applied. + * + * The width and height of the effective window geometry must be + * greater than zero. Setting an invalid size will raise an + * invalid_size error. + */ +static inline void +xdg_surface_set_window_geometry(struct xdg_surface *xdg_surface, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, + XDG_SURFACE_SET_WINDOW_GEOMETRY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, x, y, width, height); +} + +/** + * @ingroup iface_xdg_surface + * + * When a configure event is received, if a client commits the + * surface in response to the configure event, then the client + * must make an ack_configure request sometime before the commit + * request, passing along the serial of the configure event. + * + * For instance, for toplevel surfaces the compositor might use this + * information to move a surface to the top left only when the client has + * drawn itself for the maximized or fullscreen state. + * + * If the client receives multiple configure events before it + * can respond to one, it only has to ack the last configure event. + * Acking a configure event that was never sent raises an invalid_serial + * error. + * + * A client is not required to commit immediately after sending + * an ack_configure request - it may even ack_configure several times + * before its next surface commit. + * + * A client may send multiple ack_configure requests before committing, but + * only the last request sent before a commit indicates which configure + * event the client really is responding to. + * + * Sending an ack_configure request consumes the serial number sent with + * the request, as well as serial numbers sent by all configure events + * sent on this xdg_surface prior to the configure event referenced by + * the committed serial. + * + * It is an error to issue multiple ack_configure requests referencing a + * serial from the same configure event, or to issue an ack_configure + * request referencing a serial from a configure event issued before the + * event identified by the last ack_configure request for the same + * xdg_surface. Doing so will raise an invalid_serial error. + */ +static inline void +xdg_surface_ack_configure(struct xdg_surface *xdg_surface, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, + XDG_SURFACE_ACK_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, serial); +} + +#ifndef XDG_TOPLEVEL_ERROR_ENUM +#define XDG_TOPLEVEL_ERROR_ENUM +enum xdg_toplevel_error { + /** + * provided value is not a valid variant of the resize_edge enum + */ + XDG_TOPLEVEL_ERROR_INVALID_RESIZE_EDGE = 0, + /** + * invalid parent toplevel + */ + XDG_TOPLEVEL_ERROR_INVALID_PARENT = 1, + /** + * client provided an invalid min or max size + */ + XDG_TOPLEVEL_ERROR_INVALID_SIZE = 2, +}; +#endif /* XDG_TOPLEVEL_ERROR_ENUM */ + +#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM +#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM +/** + * @ingroup iface_xdg_toplevel + * edge values for resizing + * + * These values are used to indicate which edge of a surface + * is being dragged in a resize operation. + */ +enum xdg_toplevel_resize_edge { + XDG_TOPLEVEL_RESIZE_EDGE_NONE = 0, + XDG_TOPLEVEL_RESIZE_EDGE_TOP = 1, + XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM = 2, + XDG_TOPLEVEL_RESIZE_EDGE_LEFT = 4, + XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT = 5, + XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT = 6, + XDG_TOPLEVEL_RESIZE_EDGE_RIGHT = 8, + XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT = 9, + XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT = 10, +}; +#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM */ + +#ifndef XDG_TOPLEVEL_STATE_ENUM +#define XDG_TOPLEVEL_STATE_ENUM +/** + * @ingroup iface_xdg_toplevel + * types of state on the surface + * + * The different state values used on the surface. This is designed for + * state values like maximized, fullscreen. It is paired with the + * configure event to ensure that both the client and the compositor + * setting the state can be synchronized. + * + * States set in this way are double-buffered, see wl_surface.commit. + */ +enum xdg_toplevel_state { + /** + * the surface is maximized + * the surface is maximized + * + * The surface is maximized. The window geometry specified in the + * configure event must be obeyed by the client, or the + * xdg_wm_base.invalid_surface_state error is raised. + * + * The client should draw without shadow or other decoration + * outside of the window geometry. + */ + XDG_TOPLEVEL_STATE_MAXIMIZED = 1, + /** + * the surface is fullscreen + * the surface is fullscreen + * + * The surface is fullscreen. The window geometry specified in + * the configure event is a maximum; the client cannot resize + * beyond it. For a surface to cover the whole fullscreened area, + * the geometry dimensions must be obeyed by the client. For more + * details, see xdg_toplevel.set_fullscreen. + */ + XDG_TOPLEVEL_STATE_FULLSCREEN = 2, + /** + * the surface is being resized + * the surface is being resized + * + * The surface is being resized. The window geometry specified in + * the configure event is a maximum; the client cannot resize + * beyond it. Clients that have aspect ratio or cell sizing + * configuration can use a smaller size, however. + */ + XDG_TOPLEVEL_STATE_RESIZING = 3, + /** + * the surface is now activated + * the surface is now activated + * + * Client window decorations should be painted as if the window + * is active. Do not assume this means that the window actually has + * keyboard or pointer focus. + */ + XDG_TOPLEVEL_STATE_ACTIVATED = 4, + /** + * the surface’s left edge is tiled + * + * The window is currently in a tiled layout and the left edge is + * considered to be adjacent to another part of the tiling grid. + * + * The client should draw without shadow or other decoration + * outside of the window geometry on the left edge. + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_LEFT = 5, + /** + * the surface’s right edge is tiled + * + * The window is currently in a tiled layout and the right edge + * is considered to be adjacent to another part of the tiling grid. + * + * The client should draw without shadow or other decoration + * outside of the window geometry on the right edge. + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_RIGHT = 6, + /** + * the surface’s top edge is tiled + * + * The window is currently in a tiled layout and the top edge is + * considered to be adjacent to another part of the tiling grid. + * + * The client should draw without shadow or other decoration + * outside of the window geometry on the top edge. + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_TOP = 7, + /** + * the surface’s bottom edge is tiled + * + * The window is currently in a tiled layout and the bottom edge + * is considered to be adjacent to another part of the tiling grid. + * + * The client should draw without shadow or other decoration + * outside of the window geometry on the bottom edge. + * @since 2 + */ + XDG_TOPLEVEL_STATE_TILED_BOTTOM = 8, + /** + * surface repaint is suspended + * + * The surface is currently not ordinarily being repainted; for + * example because its content is occluded by another window, or + * its outputs are switched off due to screen locking. + * @since 6 + */ + XDG_TOPLEVEL_STATE_SUSPENDED = 9, +}; +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_TOP_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION 2 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6 +#endif /* XDG_TOPLEVEL_STATE_ENUM */ + +#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM +#define XDG_TOPLEVEL_WM_CAPABILITIES_ENUM +enum xdg_toplevel_wm_capabilities { + /** + * show_window_menu is available + */ + XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU = 1, + /** + * set_maximized and unset_maximized are available + */ + XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE = 2, + /** + * set_fullscreen and unset_fullscreen are available + */ + XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 3, + /** + * set_minimized is available + */ + XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE = 4, +}; +#endif /* XDG_TOPLEVEL_WM_CAPABILITIES_ENUM */ + +/** + * @ingroup iface_xdg_toplevel + * @struct xdg_toplevel_listener + */ +struct xdg_toplevel_listener { + /** + * suggest a surface change + * + * This configure event asks the client to resize its toplevel + * surface or to change its state. The configured state should not + * be applied immediately. See xdg_surface.configure for details. + * + * The width and height arguments specify a hint to the window + * about how its surface should be resized in window geometry + * coordinates. See set_window_geometry. + * + * If the width or height arguments are zero, it means the client + * should decide its own window dimension. This may happen when the + * compositor needs to configure the state of the surface but + * doesn't have any information about any previous or expected + * dimension. + * + * The states listed in the event specify how the width/height + * arguments should be interpreted, and possibly how it should be + * drawn. + * + * Clients must send an ack_configure in response to this event. + * See xdg_surface.configure and xdg_surface.ack_configure for + * details. + */ + void (*configure)(void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *states); + /** + * surface wants to be closed + * + * The close event is sent by the compositor when the user wants + * the surface to be closed. This should be equivalent to the user + * clicking the close button in client-side decorations, if your + * application has any. + * + * This is only a request that the user intends to close the + * window. The client may choose to ignore this request, or show a + * dialog to ask the user to save their data, etc. + */ + void (*close)(void *data, + struct xdg_toplevel *xdg_toplevel); + /** + * recommended window geometry bounds + * + * The configure_bounds event may be sent prior to a + * xdg_toplevel.configure event to communicate the bounds a window + * geometry size is recommended to constrain to. + * + * The passed width and height are in surface coordinate space. If + * width and height are 0, it means bounds is unknown and + * equivalent to as if no configure_bounds event was ever sent for + * this surface. + * + * The bounds can for example correspond to the size of a monitor + * excluding any panels or other shell components, so that a + * surface isn't created in a way that it cannot fit. + * + * The bounds may change at any point, and in such a case, a new + * xdg_toplevel.configure_bounds will be sent, followed by + * xdg_toplevel.configure and xdg_surface.configure. + * @since 4 + */ + void (*configure_bounds)(void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height); + /** + * compositor capabilities + * + * This event advertises the capabilities supported by the + * compositor. If a capability isn't supported, clients should hide + * or disable the UI elements that expose this functionality. For + * instance, if the compositor doesn't advertise support for + * minimized toplevels, a button triggering the set_minimized + * request should not be displayed. + * + * The compositor will ignore requests it doesn't support. For + * instance, a compositor which doesn't advertise support for + * minimized will ignore set_minimized requests. + * + * Compositors must send this event once before the first + * xdg_surface.configure event. When the capabilities change, + * compositors must send this event again and then send an + * xdg_surface.configure event. + * + * The configured state should not be applied immediately. See + * xdg_surface.configure for details. + * + * The capabilities are sent as an array of 32-bit unsigned + * integers in native endianness. + * @param capabilities array of 32-bit capabilities + * @since 5 + */ + void (*wm_capabilities)(void *data, + struct xdg_toplevel *xdg_toplevel, + struct wl_array *capabilities); +}; + +/** + * @ingroup iface_xdg_toplevel + */ +static inline int +xdg_toplevel_add_listener(struct xdg_toplevel *xdg_toplevel, + const struct xdg_toplevel_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_toplevel, + (void (**)(void)) listener, data); +} + +#define XDG_TOPLEVEL_DESTROY 0 +#define XDG_TOPLEVEL_SET_PARENT 1 +#define XDG_TOPLEVEL_SET_TITLE 2 +#define XDG_TOPLEVEL_SET_APP_ID 3 +#define XDG_TOPLEVEL_SHOW_WINDOW_MENU 4 +#define XDG_TOPLEVEL_MOVE 5 +#define XDG_TOPLEVEL_RESIZE 6 +#define XDG_TOPLEVEL_SET_MAX_SIZE 7 +#define XDG_TOPLEVEL_SET_MIN_SIZE 8 +#define XDG_TOPLEVEL_SET_MAXIMIZED 9 +#define XDG_TOPLEVEL_UNSET_MAXIMIZED 10 +#define XDG_TOPLEVEL_SET_FULLSCREEN 11 +#define XDG_TOPLEVEL_UNSET_FULLSCREEN 12 +#define XDG_TOPLEVEL_SET_MINIMIZED 13 + +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_CONFIGURE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_CLOSE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION 4 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION 5 + +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_PARENT_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_TITLE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_APP_ID_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SHOW_WINDOW_MENU_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_MOVE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_RESIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MAX_SIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MIN_SIZE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MAXIMIZED_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_UNSET_MAXIMIZED_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_FULLSCREEN_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_UNSET_FULLSCREEN_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_toplevel + */ +#define XDG_TOPLEVEL_SET_MINIMIZED_SINCE_VERSION 1 + +/** @ingroup iface_xdg_toplevel */ +static inline void +xdg_toplevel_set_user_data(struct xdg_toplevel *xdg_toplevel, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel, user_data); +} + +/** @ingroup iface_xdg_toplevel */ +static inline void * +xdg_toplevel_get_user_data(struct xdg_toplevel *xdg_toplevel) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel); +} + +static inline uint32_t +xdg_toplevel_get_version(struct xdg_toplevel *xdg_toplevel) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_toplevel); +} + +/** + * @ingroup iface_xdg_toplevel + * + * This request destroys the role surface and unmaps the surface; + * see "Unmapping" behavior in interface section for details. + */ +static inline void +xdg_toplevel_destroy(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set the "parent" of this surface. This surface should be stacked + * above the parent surface and all other ancestor surfaces. + * + * Parent surfaces should be set on dialogs, toolboxes, or other + * "auxiliary" surfaces, so that the parent is raised when the dialog + * is raised. + * + * Setting a null parent for a child surface unsets its parent. Setting + * a null parent for a surface which currently has no parent is a no-op. + * + * Only mapped surfaces can have child surfaces. Setting a parent which + * is not mapped is equivalent to setting a null parent. If a surface + * becomes unmapped, its children's parent is set to the parent of + * the now-unmapped surface. If the now-unmapped surface has no parent, + * its children's parent is unset. If the now-unmapped surface becomes + * mapped again, its parent-child relationship is not restored. + * + * The parent toplevel must not be one of the child toplevel's + * descendants, and the parent must be different from the child toplevel, + * otherwise the invalid_parent protocol error is raised. + */ +static inline void +xdg_toplevel_set_parent(struct xdg_toplevel *xdg_toplevel, struct xdg_toplevel *parent) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_PARENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, parent); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set a short title for the surface. + * + * This string may be used to identify the surface in a task bar, + * window list, or other user interface elements provided by the + * compositor. + * + * The string must be encoded in UTF-8. + */ +static inline void +xdg_toplevel_set_title(struct xdg_toplevel *xdg_toplevel, const char *title) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, title); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set an application identifier for the surface. + * + * The app ID identifies the general class of applications to which + * the surface belongs. The compositor can use this to group multiple + * surfaces together, or to determine how to launch a new application. + * + * For D-Bus activatable applications, the app ID is used as the D-Bus + * service name. + * + * The compositor shell will try to group application surfaces together + * by their app ID. As a best practice, it is suggested to select app + * ID's that match the basename of the application's .desktop file. + * For example, "org.freedesktop.FooViewer" where the .desktop file is + * "org.freedesktop.FooViewer.desktop". + * + * Like other properties, a set_app_id request can be sent after the + * xdg_toplevel has been mapped to update the property. + * + * See the desktop-entry specification [0] for more details on + * application identifiers and how they relate to well-known D-Bus + * names and .desktop files. + * + * [0] https://standards.freedesktop.org/desktop-entry-spec/ + */ +static inline void +xdg_toplevel_set_app_id(struct xdg_toplevel *xdg_toplevel, const char *app_id) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_APP_ID, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, app_id); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Clients implementing client-side decorations might want to show + * a context menu when right-clicking on the decorations, giving the + * user a menu that they can use to maximize or minimize the window. + * + * This request asks the compositor to pop up such a window menu at + * the given position, relative to the local surface coordinates of + * the parent surface. There are no guarantees as to what menu items + * the window menu contains, or even if a window menu will be drawn + * at all. + * + * This request must be used in response to some sort of user action + * like a button press, key press, or touch down event. + */ +static inline void +xdg_toplevel_show_window_menu(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SHOW_WINDOW_MENU, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, x, y); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Start an interactive, user-driven move of the surface. + * + * This request must be used in response to some sort of user action + * like a button press, key press, or touch down event. The passed + * serial is used to determine the type of interactive move (touch, + * pointer, etc). + * + * The server may ignore move requests depending on the state of + * the surface (e.g. fullscreen or maximized), or if the passed serial + * is no longer valid. + * + * If triggered, the surface will lose the focus of the device + * (wl_pointer, wl_touch, etc) used for the move. It is up to the + * compositor to visually indicate that the move is taking place, such as + * updating a pointer cursor, during the move. There is no guarantee + * that the device focus will return when the move is completed. + */ +static inline void +xdg_toplevel_move(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Start a user-driven, interactive resize of the surface. + * + * This request must be used in response to some sort of user action + * like a button press, key press, or touch down event. The passed + * serial is used to determine the type of interactive resize (touch, + * pointer, etc). + * + * The server may ignore resize requests depending on the state of + * the surface (e.g. fullscreen or maximized). + * + * If triggered, the client will receive configure events with the + * "resize" state enum value and the expected sizes. See the "resize" + * enum value for more details about what is required. The client + * must also acknowledge configure events using "ack_configure". After + * the resize is completed, the client will receive another "configure" + * event without the resize state. + * + * If triggered, the surface also will lose the focus of the device + * (wl_pointer, wl_touch, etc) used for the resize. It is up to the + * compositor to visually indicate that the resize is taking place, + * such as updating a pointer cursor, during the resize. There is no + * guarantee that the device focus will return when the resize is + * completed. + * + * The edges parameter specifies how the surface should be resized, and + * is one of the values of the resize_edge enum. Values not matching + * a variant of the enum will cause the invalid_resize_edge protocol error. + * The compositor may use this information to update the surface position + * for example when dragging the top left corner. The compositor may also + * use this information to adapt its behavior, e.g. choose an appropriate + * cursor image. + */ +static inline void +xdg_toplevel_resize(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, uint32_t edges) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, edges); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set a maximum size for the window. + * + * The client can specify a maximum size so that the compositor does + * not try to configure the window beyond this size. + * + * The width and height arguments are in window geometry coordinates. + * See xdg_surface.set_window_geometry. + * + * Values set in this way are double-buffered, see wl_surface.commit. + * + * The compositor can use this information to allow or disallow + * different states like maximize or fullscreen and draw accurate + * animations. + * + * Similarly, a tiling window manager may use this information to + * place and resize client windows in a more effective way. + * + * The client should not rely on the compositor to obey the maximum + * size. The compositor may decide to ignore the values set by the + * client and request a larger size. + * + * If never set, or a value of zero in the request, means that the + * client has no expected maximum size in the given dimension. + * As a result, a client wishing to reset the maximum size + * to an unspecified state can use zero for width and height in the + * request. + * + * Requesting a maximum size to be smaller than the minimum size of + * a surface is illegal and will result in an invalid_size error. + * + * The width and height must be greater than or equal to zero. Using + * strictly negative values for width or height will result in a + * invalid_size error. + */ +static inline void +xdg_toplevel_set_max_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MAX_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Set a minimum size for the window. + * + * The client can specify a minimum size so that the compositor does + * not try to configure the window below this size. + * + * The width and height arguments are in window geometry coordinates. + * See xdg_surface.set_window_geometry. + * + * Values set in this way are double-buffered, see wl_surface.commit. + * + * The compositor can use this information to allow or disallow + * different states like maximize or fullscreen and draw accurate + * animations. + * + * Similarly, a tiling window manager may use this information to + * place and resize client windows in a more effective way. + * + * The client should not rely on the compositor to obey the minimum + * size. The compositor may decide to ignore the values set by the + * client and request a smaller size. + * + * If never set, or a value of zero in the request, means that the + * client has no expected minimum size in the given dimension. + * As a result, a client wishing to reset the minimum size + * to an unspecified state can use zero for width and height in the + * request. + * + * Requesting a minimum size to be larger than the maximum size of + * a surface is illegal and will result in an invalid_size error. + * + * The width and height must be greater than or equal to zero. Using + * strictly negative values for width and height will result in a + * invalid_size error. + */ +static inline void +xdg_toplevel_set_min_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MIN_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Maximize the surface. + * + * After requesting that the surface should be maximized, the compositor + * will respond by emitting a configure event. Whether this configure + * actually sets the window maximized is subject to compositor policies. + * The client must then update its content, drawing in the configured + * state. The client must also acknowledge the configure when committing + * the new content (see ack_configure). + * + * It is up to the compositor to decide how and where to maximize the + * surface, for example which output and what region of the screen should + * be used. + * + * If the surface was already maximized, the compositor will still emit + * a configure event with the "maximized" state. + * + * If the surface is in a fullscreen state, this request has no direct + * effect. It may alter the state the surface is returned to when + * unmaximized unless overridden by the compositor. + */ +static inline void +xdg_toplevel_set_maximized(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Unmaximize the surface. + * + * After requesting that the surface should be unmaximized, the compositor + * will respond by emitting a configure event. Whether this actually + * un-maximizes the window is subject to compositor policies. + * If available and applicable, the compositor will include the window + * geometry dimensions the window had prior to being maximized in the + * configure event. The client must then update its content, drawing it in + * the configured state. The client must also acknowledge the configure + * when committing the new content (see ack_configure). + * + * It is up to the compositor to position the surface after it was + * unmaximized; usually the position the surface had before maximizing, if + * applicable. + * + * If the surface was already not maximized, the compositor will still + * emit a configure event without the "maximized" state. + * + * If the surface is in a fullscreen state, this request has no direct + * effect. It may alter the state the surface is returned to when + * unmaximized unless overridden by the compositor. + */ +static inline void +xdg_toplevel_unset_maximized(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_UNSET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Make the surface fullscreen. + * + * After requesting that the surface should be fullscreened, the + * compositor will respond by emitting a configure event. Whether the + * client is actually put into a fullscreen state is subject to compositor + * policies. The client must also acknowledge the configure when + * committing the new content (see ack_configure). + * + * The output passed by the request indicates the client's preference as + * to which display it should be set fullscreen on. If this value is NULL, + * it's up to the compositor to choose which display will be used to map + * this surface. + * + * If the surface doesn't cover the whole output, the compositor will + * position the surface in the center of the output and compensate with + * with border fill covering the rest of the output. The content of the + * border fill is undefined, but should be assumed to be in some way that + * attempts to blend into the surrounding area (e.g. solid black). + * + * If the fullscreened surface is not opaque, the compositor must make + * sure that other screen content not part of the same surface tree (made + * up of subsurfaces, popups or similarly coupled surfaces) are not + * visible below the fullscreened surface. + */ +static inline void +xdg_toplevel_set_fullscreen(struct xdg_toplevel *xdg_toplevel, struct wl_output *output) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, output); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Make the surface no longer fullscreen. + * + * After requesting that the surface should be unfullscreened, the + * compositor will respond by emitting a configure event. + * Whether this actually removes the fullscreen state of the client is + * subject to compositor policies. + * + * Making a surface unfullscreen sets states for the surface based on the following: + * * the state(s) it may have had before becoming fullscreen + * * any state(s) decided by the compositor + * * any state(s) requested by the client while the surface was fullscreen + * + * The compositor may include the previous window geometry dimensions in + * the configure event, if applicable. + * + * The client must also acknowledge the configure when committing the new + * content (see ack_configure). + */ +static inline void +xdg_toplevel_unset_fullscreen(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_UNSET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); +} + +/** + * @ingroup iface_xdg_toplevel + * + * Request that the compositor minimize your surface. There is no + * way to know if the surface is currently minimized, nor is there + * any way to unset minimization on this surface. + * + * If you are looking to throttle redrawing when minimized, please + * instead use the wl_surface.frame event for this, as this will + * also work with live previews on windows in Alt-Tab, Expose or + * similar compositor features. + */ +static inline void +xdg_toplevel_set_minimized(struct xdg_toplevel *xdg_toplevel) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, + XDG_TOPLEVEL_SET_MINIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); +} + +#ifndef XDG_POPUP_ERROR_ENUM +#define XDG_POPUP_ERROR_ENUM +enum xdg_popup_error { + /** + * tried to grab after being mapped + */ + XDG_POPUP_ERROR_INVALID_GRAB = 0, +}; +#endif /* XDG_POPUP_ERROR_ENUM */ + +/** + * @ingroup iface_xdg_popup + * @struct xdg_popup_listener + */ +struct xdg_popup_listener { + /** + * configure the popup surface + * + * This event asks the popup surface to configure itself given + * the configuration. The configured state should not be applied + * immediately. See xdg_surface.configure for details. + * + * The x and y arguments represent the position the popup was + * placed at given the xdg_positioner rule, relative to the upper + * left corner of the window geometry of the parent surface. + * + * For version 2 or older, the configure event for an xdg_popup is + * only ever sent once for the initial configuration. Starting with + * version 3, it may be sent again if the popup is setup with an + * xdg_positioner with set_reactive requested, or in response to + * xdg_popup.reposition requests. + * @param x x position relative to parent surface window geometry + * @param y y position relative to parent surface window geometry + * @param width window geometry width + * @param height window geometry height + */ + void (*configure)(void *data, + struct xdg_popup *xdg_popup, + int32_t x, + int32_t y, + int32_t width, + int32_t height); + /** + * popup interaction is done + * + * The popup_done event is sent out when a popup is dismissed by + * the compositor. The client should destroy the xdg_popup object + * at this point. + */ + void (*popup_done)(void *data, + struct xdg_popup *xdg_popup); + /** + * signal the completion of a repositioned request + * + * The repositioned event is sent as part of a popup + * configuration sequence, together with xdg_popup.configure and + * lastly xdg_surface.configure to notify the completion of a + * reposition request. + * + * The repositioned event is to notify about the completion of a + * xdg_popup.reposition request. The token argument is the token + * passed in the xdg_popup.reposition request. + * + * Immediately after this event is emitted, xdg_popup.configure and + * xdg_surface.configure will be sent with the updated size and + * position, as well as a new configure serial. + * + * The client should optionally update the content of the popup, + * but must acknowledge the new popup configuration for the new + * position to take effect. See xdg_surface.ack_configure for + * details. + * @param token reposition request token + * @since 3 + */ + void (*repositioned)(void *data, + struct xdg_popup *xdg_popup, + uint32_t token); +}; + +/** + * @ingroup iface_xdg_popup + */ +static inline int +xdg_popup_add_listener(struct xdg_popup *xdg_popup, + const struct xdg_popup_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) xdg_popup, + (void (**)(void)) listener, data); +} + +#define XDG_POPUP_DESTROY 0 +#define XDG_POPUP_GRAB 1 +#define XDG_POPUP_REPOSITION 2 + +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_CONFIGURE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3 + +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_GRAB_SINCE_VERSION 1 +/** + * @ingroup iface_xdg_popup + */ +#define XDG_POPUP_REPOSITION_SINCE_VERSION 3 + +/** @ingroup iface_xdg_popup */ +static inline void +xdg_popup_set_user_data(struct xdg_popup *xdg_popup, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) xdg_popup, user_data); +} + +/** @ingroup iface_xdg_popup */ +static inline void * +xdg_popup_get_user_data(struct xdg_popup *xdg_popup) +{ + return wl_proxy_get_user_data((struct wl_proxy *) xdg_popup); +} + +static inline uint32_t +xdg_popup_get_version(struct xdg_popup *xdg_popup) +{ + return wl_proxy_get_version((struct wl_proxy *) xdg_popup); +} + +/** + * @ingroup iface_xdg_popup + * + * This destroys the popup. Explicitly destroying the xdg_popup + * object will also dismiss the popup, and unmap the surface. + * + * If this xdg_popup is not the "topmost" popup, the + * xdg_wm_base.not_the_topmost_popup protocol error will be sent. + */ +static inline void +xdg_popup_destroy(struct xdg_popup *xdg_popup) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup, + XDG_POPUP_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_xdg_popup + * + * This request makes the created popup take an explicit grab. An explicit + * grab will be dismissed when the user dismisses the popup, or when the + * client destroys the xdg_popup. This can be done by the user clicking + * outside the surface, using the keyboard, or even locking the screen + * through closing the lid or a timeout. + * + * If the compositor denies the grab, the popup will be immediately + * dismissed. + * + * This request must be used in response to some sort of user action like a + * button press, key press, or touch down event. The serial number of the + * event should be passed as 'serial'. + * + * The parent of a grabbing popup must either be an xdg_toplevel surface or + * another xdg_popup with an explicit grab. If the parent is another + * xdg_popup it means that the popups are nested, with this popup now being + * the topmost popup. + * + * Nested popups must be destroyed in the reverse order they were created + * in, e.g. the only popup you are allowed to destroy at all times is the + * topmost one. + * + * When compositors choose to dismiss a popup, they may dismiss every + * nested grabbing popup as well. When a compositor dismisses popups, it + * will follow the same dismissing order as required from the client. + * + * If the topmost grabbing popup is destroyed, the grab will be returned to + * the parent of the popup, if that parent previously had an explicit grab. + * + * If the parent is a grabbing popup which has already been dismissed, this + * popup will be immediately dismissed. If the parent is a popup that did + * not take an explicit grab, an error will be raised. + * + * During a popup grab, the client owning the grab will receive pointer + * and touch events for all their surfaces as normal (similar to an + * "owner-events" grab in X11 parlance), while the top most grabbing popup + * will always have keyboard focus. + */ +static inline void +xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup, + XDG_POPUP_GRAB, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, seat, serial); +} + +/** + * @ingroup iface_xdg_popup + * + * Reposition an already-mapped popup. The popup will be placed given the + * details in the passed xdg_positioner object, and a + * xdg_popup.repositioned followed by xdg_popup.configure and + * xdg_surface.configure will be emitted in response. Any parameters set + * by the previous positioner will be discarded. + * + * The passed token will be sent in the corresponding + * xdg_popup.repositioned event. The new popup position will not take + * effect until the corresponding configure event is acknowledged by the + * client. See xdg_popup.repositioned for details. The token itself is + * opaque, and has no other special meaning. + * + * If multiple reposition requests are sent, the compositor may skip all + * but the last one. + * + * If the popup is repositioned in response to a configure event for its + * parent, the client should send an xdg_positioner.set_parent_configure + * and possibly an xdg_positioner.set_parent_size request to allow the + * compositor to properly constrain the popup. + * + * If the popup is repositioned together with a parent that is being + * resized, but not in response to a configure event, the client should + * send an xdg_positioner.set_parent_size request. + */ +static inline void +xdg_popup_reposition(struct xdg_popup *xdg_popup, struct xdg_positioner *positioner, uint32_t token) +{ + wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup, + XDG_POPUP_REPOSITION, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, positioner, token); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/host/linux/wayland/xdg-shell-protocol.c b/examples/host/linux/wayland/xdg-shell-protocol.c new file mode 100644 index 0000000..d698c2c --- /dev/null +++ b/examples/host/linux/wayland/xdg-shell-protocol.c @@ -0,0 +1,184 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright © 2008-2013 Kristian Høgsberg + * Copyright © 2013 Rafael Antognolli + * Copyright © 2013 Jasper St. Pierre + * Copyright © 2010-2013 Intel Corporation + * Copyright © 2015-2017 Samsung Electronics Co., Ltd + * Copyright © 2015-2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_seat_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface xdg_popup_interface; +extern const struct wl_interface xdg_positioner_interface; +extern const struct wl_interface xdg_surface_interface; +extern const struct wl_interface xdg_toplevel_interface; + +static const struct wl_interface *xdg_shell_types[] = { + NULL, + NULL, + NULL, + NULL, + &xdg_positioner_interface, + &xdg_surface_interface, + &wl_surface_interface, + &xdg_toplevel_interface, + &xdg_popup_interface, + &xdg_surface_interface, + &xdg_positioner_interface, + &xdg_toplevel_interface, + &wl_seat_interface, + NULL, + NULL, + NULL, + &wl_seat_interface, + NULL, + &wl_seat_interface, + NULL, + NULL, + &wl_output_interface, + &wl_seat_interface, + NULL, + &xdg_positioner_interface, + NULL, +}; + +static const struct wl_message xdg_wm_base_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "create_positioner", "n", xdg_shell_types + 4 }, + { "get_xdg_surface", "no", xdg_shell_types + 5 }, + { "pong", "u", xdg_shell_types + 0 }, +}; + +static const struct wl_message xdg_wm_base_events[] = { + { "ping", "u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_wm_base_interface = { + "xdg_wm_base", 6, + 4, xdg_wm_base_requests, + 1, xdg_wm_base_events, +}; + +static const struct wl_message xdg_positioner_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "set_size", "ii", xdg_shell_types + 0 }, + { "set_anchor_rect", "iiii", xdg_shell_types + 0 }, + { "set_anchor", "u", xdg_shell_types + 0 }, + { "set_gravity", "u", xdg_shell_types + 0 }, + { "set_constraint_adjustment", "u", xdg_shell_types + 0 }, + { "set_offset", "ii", xdg_shell_types + 0 }, + { "set_reactive", "3", xdg_shell_types + 0 }, + { "set_parent_size", "3ii", xdg_shell_types + 0 }, + { "set_parent_configure", "3u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_positioner_interface = { + "xdg_positioner", 6, + 10, xdg_positioner_requests, + 0, NULL, +}; + +static const struct wl_message xdg_surface_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "get_toplevel", "n", xdg_shell_types + 7 }, + { "get_popup", "n?oo", xdg_shell_types + 8 }, + { "set_window_geometry", "iiii", xdg_shell_types + 0 }, + { "ack_configure", "u", xdg_shell_types + 0 }, +}; + +static const struct wl_message xdg_surface_events[] = { + { "configure", "u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_surface_interface = { + "xdg_surface", 6, + 5, xdg_surface_requests, + 1, xdg_surface_events, +}; + +static const struct wl_message xdg_toplevel_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "set_parent", "?o", xdg_shell_types + 11 }, + { "set_title", "s", xdg_shell_types + 0 }, + { "set_app_id", "s", xdg_shell_types + 0 }, + { "show_window_menu", "ouii", xdg_shell_types + 12 }, + { "move", "ou", xdg_shell_types + 16 }, + { "resize", "ouu", xdg_shell_types + 18 }, + { "set_max_size", "ii", xdg_shell_types + 0 }, + { "set_min_size", "ii", xdg_shell_types + 0 }, + { "set_maximized", "", xdg_shell_types + 0 }, + { "unset_maximized", "", xdg_shell_types + 0 }, + { "set_fullscreen", "?o", xdg_shell_types + 21 }, + { "unset_fullscreen", "", xdg_shell_types + 0 }, + { "set_minimized", "", xdg_shell_types + 0 }, +}; + +static const struct wl_message xdg_toplevel_events[] = { + { "configure", "iia", xdg_shell_types + 0 }, + { "close", "", xdg_shell_types + 0 }, + { "configure_bounds", "4ii", xdg_shell_types + 0 }, + { "wm_capabilities", "5a", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_toplevel_interface = { + "xdg_toplevel", 6, + 14, xdg_toplevel_requests, + 4, xdg_toplevel_events, +}; + +static const struct wl_message xdg_popup_requests[] = { + { "destroy", "", xdg_shell_types + 0 }, + { "grab", "ou", xdg_shell_types + 22 }, + { "reposition", "3ou", xdg_shell_types + 24 }, +}; + +static const struct wl_message xdg_popup_events[] = { + { "configure", "iiii", xdg_shell_types + 0 }, + { "popup_done", "", xdg_shell_types + 0 }, + { "repositioned", "3u", xdg_shell_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface xdg_popup_interface = { + "xdg_popup", 6, + 3, xdg_popup_requests, + 3, xdg_popup_events, +}; + diff --git a/examples/host/linux/wayland/xdgshell.cpp b/examples/host/linux/wayland/xdgshell.cpp new file mode 100644 index 0000000..403ea9a --- /dev/null +++ b/examples/host/linux/wayland/xdgshell.cpp @@ -0,0 +1,78 @@ +#include "xdgshell.h" + +#include + +using namespace WL; + +void XDGWmBase::bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept +{ + registry(reg, name, version); + + static const xdg_wm_base_listener listener = { + .ping = [](void*, xdg_wm_base *wm_base, uint32_t serial){ + xdg_wm_base_pong(wm_base, serial); + } + }; + + xdg_wm_base_add_listener (c_ptr(), &listener, nullptr); +} + +NativeToplevel::NativeToplevel(const NativeSurface &surface, uint32_t width, uint32_t height) + : m_xdg_surfase(xdg_wm_base_get_xdg_surface( + Display::instance().ensureProtocol().c_ptr(), + surface.c_ptr()), + "Can't create xdg surface") + , m_top(xdg_surface_get_toplevel(m_xdg_surfase.c_ptr()), + "Can't create toplevel role") + , m_decor(Display::instance().protocol() ? + zxdg_decoration_manager_v1_get_toplevel_decoration( + Display::instance().protocol()->c_ptr(), m_top.c_ptr()) + :nullptr) + , m_width(width) + , m_height(height) + , m_state(0) +{ + static const xdg_toplevel_listener toplevel_lsr{ + .configure = [](void* data, xdg_toplevel *tt, + int32_t width, int32_t height, wl_array *states){ + + auto win = static_cast(data); + + xdg_toplevel_state *pos; + win->m_state = 0; + std::cout<<"states "<size<<" W "<data; + (const char *) pos < ((const char *) states->data + states->size); + (pos)++){ + + std::cout<<"--- "<<*pos<m_state |= (1 << *pos); + } + + if (width && height){ + win->m_width = width; + win->m_height = height; + } + }, + .close = [](void *data, xdg_toplevel*){ + auto win = static_cast(data); + win->closed(); + }, + .configure_bounds = [](void* data, xdg_toplevel*, int32_t width, int32_t height){ + + std::cout<<"configure_bound: "<< width<<" "<< height< + +#include "display.h" +#include "xdg-shell-client-protocol.h" +#include "xdg-decoration-unstable-v1-client-protocol.h" + +namespace WL { + +enum XDGState +{ + resizing = 1 << XDG_TOPLEVEL_STATE_RESIZING, + maximized = 1 << XDG_TOPLEVEL_STATE_MAXIMIZED, + activated = 1 << XDG_TOPLEVEL_STATE_ACTIVATED, + fullscreen = 1 << XDG_TOPLEVEL_STATE_FULLSCREEN +}; + +class XDGWmBase final: public Protocol +{ +public: + void bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept override; +}; + +//--------Decoration--------//////////////////////////////////////////// + +using XDGDecorateManager = Protocol; + +class NativeToplevel +{ +public: + NativeToplevel(const NativeSurface &surface, + uint32_t width, + uint32_t height); + + void setTitle(const char* title) + {xdg_toplevel_set_title(m_top.c_ptr(), title);} + + void setAppID(const char* id) + {xdg_toplevel_set_app_id(m_top.c_ptr(), id);} + +private: + Proxy m_xdg_surfase; + Proxy m_top; + Proxy m_decor; + + template + friend class Toplevel; + +protected: + uint32_t m_width ; + uint32_t m_height; + uint32_t m_state ; + + virtual void closed() = 0; +}; + +template +class Toplevel: public Surface, public NativeToplevel +{ +public: + Toplevel(uint32_t width, uint32_t height): + NativeToplevel(*this, width, height) + { + static const xdg_surface_listener surface_lsr{ + .configure = [](void* data, xdg_surface *xdg_surf, uint32_t serial){ + + auto inst = static_cast(data); + xdg_surface_ack_configure(xdg_surf, serial); + + if (!inst->mapped()) { + + if (!inst->makeBuffer(inst->m_width, inst->m_height)) { + std::cerr << "Can't create window frame" << std::endl; + return; + } + + if (inst->configure(inst->m_width, inst->m_height, XDGState::resizing)){ + inst->draw(inst->m_scale); + inst->context().flush(*inst->m_buffer.get()); + } + + return; + } + + if (inst->m_state & XDGState::resizing) + inst->m_buffer->resize(inst->m_width, inst->m_height); + + if (inst->configure(inst->m_width, inst->m_height, inst->m_state)) + inst->refresh(); + }}; + + xdg_surface_add_listener (this->m_xdg_surfase.c_ptr(), &surface_lsr, this); + this->commit(); + } + +protected: + + /** + * @brief configure вызывается композитором при изменении состояния (s) + * или размеров окна (w, h) + * @param w + * @param h + * @param s + * @return должна возвращать true если требуется перерисовка + */ + virtual bool configure(unsigned w, unsigned h, unsigned s) = 0; +}; + + +// struct Positioner: Proxy +// { +// //const WlApplication &global; + +// // explicit Positioner(const XDGWmBase &shell): +// // Proxy( +// // xdg_wm_base_create_positioner(shell.c_ptr()), +// // "Can't create positioner")//, +// // //global(app) +// // {} +// }; + +// class Popup: public Proxy +// { +// public: +// Popup(const Positioner &pos, +// const XDGSurface &parent); + +// //std::function onClosed; + +// int32_t x, y; +// int32_t width, height; +// }; + +} + +#endif // XDGSHELL_H From 4acc825f8bd4867584df284fe165626d868ffeac Mon Sep 17 00:00:00 2001 From: Silo Date: Fri, 28 Mar 2025 19:19:43 +0300 Subject: [PATCH 04/13] Adds native wayland window support to Linux --- CMakeLists.txt.user | 260 -------------------------------------------- 1 file changed, 260 deletions(-) delete mode 100644 CMakeLists.txt.user diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user deleted file mode 100644 index 6624bc5..0000000 --- a/CMakeLists.txt.user +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - EnvironmentId - {23b32c7f-0899-49e8-97cb-f699c52a0902} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 0 - 80 - true - true - 1 - 0 - false - true - false - 2 - true - true - 0 - 8 - true - false - 1 - true - true - true - *.md, *.MD, Makefile - false - true - true - - - - ProjectExplorer.Project.PluginSettings - - - true - false - true - true - true - true - - false - - - 0 - true - - true - true - Builtin.DefaultTidyAndClazy - 4 - true - - - - true - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - Desktop - {627454d1-a178-4e9b-896d-df645d6cef58} - 0 - 0 - 0 - - Debug - 2 - false - - -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} - 0 - /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug - - - - - all - - false - - true - Собрать - CMakeProjectManager.MakeStep - - 1 - Сборка - Сборка - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - Собрать - CMakeProjectManager.MakeStep - - 1 - Очистка - Очистка - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Отладка - CMakeProjectManager.CMakeBuildConfiguration - - - Release - 2 - false - - -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_BUILD_TYPE:STRING=Release --DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} - /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Release - - - - - all - - false - - true - CMakeProjectManager.MakeStep - - 1 - Сборка - Сборка - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - CMakeProjectManager.MakeStep - - 1 - Очистка - Очистка - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Выпуск - CMakeProjectManager.CMakeBuildConfiguration - - 2 - - - 0 - Развёртывание - Развёртывание - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph dwarf,4096 -F 250 - - ProjectExplorer.CustomExecutableRunConfiguration - - false - true - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 22 - - - Version - 22 - - From c6fa2f5354014c0dfb995081e8f3efa27db1a3ad Mon Sep 17 00:00:00 2001 From: Silo Date: Sat, 29 Mar 2025 08:06:38 +0300 Subject: [PATCH 05/13] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e19867..11bf181 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ message(STATUS "Compiler: ${CMAKE_C_COMPILER_ID}") add_subdirectory(lib) -option(ARTIST_BUILD_EXAMPLES "build Artist library examples" ON) +option(ARTIST_BUILD_EXAMPLES "build Artist library examples" OFF) option(ARTIST_BUILD_TESTS "build Artist library tests" ON) if (ARTIST_BUILD_EXAMPLES) From ec0cdb7f9d6536461d85e4535433e68d7fdc6d6b Mon Sep 17 00:00:00 2001 From: Silo Date: Sat, 29 Mar 2025 08:30:32 +0300 Subject: [PATCH 06/13] Update build_test.yml --- .github/workflows/build_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 70abde5..153410d 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -17,8 +17,8 @@ jobs: environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - name: "Ubuntu Latest GCC" os: ubuntu-latest - cc: "gcc-9" - cxx: "g++-9" + cc: "gcc" + cxx: "g++" - name: "macOS Latest Clang" os: macos-latest cc: "clang" From c5dc484687a056a6dabe05ab4bf956ab00e901b3 Mon Sep 17 00:00:00 2001 From: Silo Date: Mon, 21 Apr 2025 00:19:29 +0300 Subject: [PATCH 07/13] Adds X11 window system --- CMakeLists.txt.user | 217 ++++++++- examples/CMakeLists.txt | 73 +-- examples/host/linux/application.h | 51 +++ examples/host/linux/skia_app.cpp | 123 +---- examples/host/linux/skia_context.cpp | 43 ++ examples/host/linux/skia_context.h | 28 ++ examples/host/linux/wayland/application.cpp | 137 ++++++ examples/host/linux/wayland/contextegl.cpp | 114 ++--- examples/host/linux/wayland/contextegl.h | 68 ++- examples/host/linux/wayland/core.cpp | 40 +- examples/host/linux/wayland/core.h | 15 +- .../wayland/cursor-shape-v1-client-protocol.h | 426 ------------------ .../linux/wayland/cursor-shape-v1-protocol.c | 75 --- examples/host/linux/wayland/display.cpp | 165 +++---- examples/host/linux/wayland/display.h | 153 ++----- examples/host/linux/wayland/xdgshell.cpp | 51 ++- examples/host/linux/wayland/xdgshell.h | 56 +-- examples/host/linux/x11/application.cpp | 404 +++++++++++++++++ 18 files changed, 1195 insertions(+), 1044 deletions(-) create mode 100644 examples/host/linux/application.h create mode 100644 examples/host/linux/skia_context.cpp create mode 100644 examples/host/linux/skia_context.h create mode 100644 examples/host/linux/wayland/application.cpp delete mode 100644 examples/host/linux/wayland/cursor-shape-v1-client-protocol.h delete mode 100644 examples/host/linux/wayland/cursor-shape-v1-protocol.c create mode 100644 examples/host/linux/x11/application.cpp diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index 6624bc5..2299d4f 100644 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -13,8 +13,8 @@ ProjectExplorer.Project.EditorSettings + true true - false true Cpp @@ -97,21 +97,21 @@ {627454d1-a178-4e9b-896d-df645d6cef58} 0 0 - 0 + 6 Debug 2 false - -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake + -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON 0 /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug @@ -161,15 +161,15 @@ 2 false - -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake + -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_BUILD_TYPE:STRING=Release --DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Release @@ -180,6 +180,7 @@ false true + Собрать CMakeProjectManager.MakeStep 1 @@ -196,6 +197,7 @@ false true + Собрать CMakeProjectManager.MakeStep 1 @@ -235,14 +237,187 @@ false -e cpu-cycles --call-graph dwarf,4096 -F 250 - - ProjectExplorer.CustomExecutableRunConfiguration - + artist_test + CMakeProjectManager.CMakeRunConfiguration. + artist_test + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/test + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + chessboard + CMakeProjectManager.CMakeRunConfiguration. + chessboard + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + composite_ops + CMakeProjectManager.CMakeRunConfiguration. + composite_ops + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + paths + CMakeProjectManager.CMakeRunConfiguration. + paths + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + rain + CMakeProjectManager.CMakeRunConfiguration. + rain + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + shadow + CMakeProjectManager.CMakeRunConfiguration. + shadow + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + shapes + CMakeProjectManager.CMakeRunConfiguration. + shapes + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + space + CMakeProjectManager.CMakeRunConfiguration. + space + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + tauri + CMakeProjectManager.CMakeRunConfiguration. + tauri + false + true + true + true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples + + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + typography + CMakeProjectManager.CMakeRunConfiguration. + typography false true + true true + /tmp/andrey/.ShareData/Projects/artist/build/Desktop-Debug/examples - 1 + 10 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9d7ae25..2ab2481 100755 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,10 +8,50 @@ project(examples) if (UNIX AND NOT APPLE) find_package(OpenGL REQUIRED COMPONENTS OpenGL) find_package(PkgConfig REQUIRED) - #pkg_check_modules(gtk3 REQUIRED IMPORTED_TARGET gtk+-3.0) - pkg_check_modules(depend REQUIRED IMPORTED_TARGET - wayland-client wayland-cursor wayland-egl xkbcommon egl - ) + + option(X_Win "Use x11 window" ON) + + set(SRC host/linux/skia_app.cpp + host/linux/skia_context.cpp) + + if (X_Win) + pkg_check_modules(depend REQUIRED IMPORTED_TARGET + x11 glx + ) + set(SRC ${SRC} + host/linux/x11/application.cpp + ) + + else() + pkg_check_modules(depend REQUIRED IMPORTED_TARGET + wayland-client wayland-cursor wayland-egl xkbcommon egl + ) + + set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake") + find_package(WaylandScanner REQUIRED) + + set(WORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/host/linux/wayland") + + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/stable/xdg-shell/xdg-shell.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/unstable/tablet/tablet-unstable-v2.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml") + wayland_add_protocol_client(SRC_GEN ${WORK_DIR} + "${WaylandScanner_DATADIR}/stable/viewporter/viewporter.xml") + + set(SRC ${SRC} ${SRC_GEN} + host/linux/wayland/core.cpp + host/linux/wayland/display.cpp + host/linux/wayland/xdgshell.cpp + host/linux/wayland/contextegl.cpp + host/linux/wayland/application.cpp + ) + endif() + endif() file( @@ -81,39 +121,16 @@ function(add_example name) ) elseif (UNIX) - set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake") - find_package(WaylandScanner REQUIRED) - - set(WORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/host/linux/wayland") - - wayland_add_protocol_client(SRC_GEN ${WORK_DIR} - "${WaylandScanner_DATADIR}/stable/xdg-shell/xdg-shell.xml") - wayland_add_protocol_client(SRC_GEN ${WORK_DIR} - "${WaylandScanner_DATADIR}/staging/cursor-shape/cursor-shape-v1.xml") - wayland_add_protocol_client(SRC_GEN ${WORK_DIR} - "${WaylandScanner_DATADIR}/unstable/tablet/tablet-unstable-v2.xml") - wayland_add_protocol_client(SRC_GEN ${WORK_DIR} - "${WaylandScanner_DATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml") - wayland_add_protocol_client(SRC_GEN ${WORK_DIR} - "${WaylandScanner_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml") - wayland_add_protocol_client(SRC_GEN ${WORK_DIR} - "${WaylandScanner_DATADIR}/stable/viewporter/viewporter.xml") add_executable( ${name} ${name}.cpp - host/linux/wayland/core.cpp - host/linux/wayland/display.cpp - host/linux/wayland/xdgshell.cpp - host/linux/wayland/contextegl.cpp - ${SRC_GEN} - host/linux/skia_app.cpp + ${SRC} print_elapsed.cpp ) target_link_libraries( ${name} - #PkgConfig::gtk3 PkgConfig::depend OpenGL::GL ) diff --git a/examples/host/linux/application.h b/examples/host/linux/application.h new file mode 100644 index 0000000..495992a --- /dev/null +++ b/examples/host/linux/application.h @@ -0,0 +1,51 @@ +#ifndef APP_H +#define APP_H + +#include "SkSurface.h" + +class Application +{ +public: + void run(); + void stop(){isRuning = false;} + + class DisplayImpl; + +private: + bool isRuning{false}; +}; + +enum SurfaceState +{ + resizing = 1 << 0, + maximized = 1 << 1, + activated = 1 << 2, + fullscreen = 1 << 3 +}; + +class Surface +{ +public: + Surface(int width, int height); + ~Surface(); + + void setTitle(const char* txt); + +protected: + /* + * Draw frame. Returns true if the next frame needs to be drawn + */ + virtual bool draw(float /*scale*/) = 0; + virtual void configure(unsigned /*w*/, unsigned /*h*/, unsigned /*state*/) = 0; + virtual void closed() = 0; + + sk_sp skia_surf; + +private: + struct Impl; + std::unique_ptr impl; + + friend class Application; +}; + +#endif // APP_H diff --git a/examples/host/linux/skia_app.cpp b/examples/host/linux/skia_app.cpp index 8ff8daa..0b4b633 100644 --- a/examples/host/linux/skia_app.cpp +++ b/examples/host/linux/skia_app.cpp @@ -4,21 +4,14 @@ Distributed under the MIT License [ https://opensource.org/licenses/MIT ] =============================================================================*/ #include "../../app.hpp" -//#include + #include -//#include -#include "GrDirectContext.h" -#include "gl/GrGLInterface.h" -#include "gl/GrGLAssembleInterface.h" -//#include "SkImage.h" -#include "SkColorSpace.h" #include "SkCanvas.h" -#include "SkSurface.h" #include +#include -#include "wayland/contextegl.h" -#include "wayland/xdgshell.h" +#include "application.h" using namespace cycfi::artist; float elapsed_ = 0; // rendering elapsed time @@ -53,103 +46,32 @@ namespace cycfi::artist } } -class PaintContextSkia : public WL::ContextEGL +class Window: public Surface { public: + using Surface::Surface; - class Buffer: public BufferEGL - { - public: - Buffer(PaintContextSkia &ctx, WL::NativeSurface &wl, uint32_t width, uint32_t height): - BufferEGL(ctx, wl, width, height) - { - if (BufferEGL::valid()){ - - GrGLFramebufferInfo framebufferInfo; - framebufferInfo.fFBOID = 0; // assume default framebuffer - framebufferInfo.fFormat = GL_RGBA8; - - SkColorType colorType = kRGBA_8888_SkColorType; - GrBackendRenderTarget target(width, - height, - 1, // sample count - 8, // stencil bits - framebufferInfo); - - skia = SkSurface::MakeFromBackendRenderTarget(ctx._ctx.get(), - target, - kBottomLeft_GrSurfaceOrigin, - colorType, - nullptr, - nullptr); - if (!skia) ctx.destroy(*this); - } - } - - sk_sp skia; - }; - - void flush(Buffer &buf) const - { - buf.skia->flush(); - ContextEGL::flush(buf); - } - void destroy(Buffer &buf) - { - buf.skia.reset(); - ContextEGL::destroy(buf); - } + std::function onClosed; + //std::function onDraw; + std::function onReshape; - PaintContextSkia(bool transparent = false): - ContextEGL(transparent) - { - auto _xface = GrGLMakeNativeInterface(); - if (_xface == nullptr) { - //backup plan. see https://gist.github.com/ad8e/dd150b775ae6aa4d5cf1a092e4713add?permalink_comment_id=4680136#gistcomment-4680136 - _xface = GrGLMakeAssembledInterface( - nullptr, (GrGLGetProc) * [](void *, const char *p) -> void * { - return (void *) eglGetProcAddress(p); - }); - } - - _ctx = GrDirectContext::MakeGL(_xface); - if (!_ctx) - throw std::runtime_error("failed to make Skia context"); - } + bool animate; private: - sk_sp _ctx; -}; + //bool m_opaque; -class Window: public WL::Toplevel, - public WL::SeatListener -{ -public: - Window(int width, int height): - Toplevel(width, height)//, - //m_opaque(ctx.opaque()) + bool draw(float scale) override { - listenerInput(*this); + render(skia_surf->getCanvas(), scale); + return animate; } - std::function onClosed; - std::function onDraw; - std::function onReshape; - -private: - //bool m_opaque; - - void draw(float scale) override - {if (onDraw) onDraw(m_buffer->skia->getCanvas(), scale);} void closed() override {if (onClosed) onClosed();} - bool configure(uint32_t width, uint32_t height, uint32_t state) override + + void configure(uint32_t width, uint32_t height, unsigned state) override { - if (onReshape && state & WL::XDGState::resizing) { - onReshape(width, height); - return true; - } - return false; + onReshape(width, height); } }; @@ -163,18 +85,13 @@ int run_app( { try { - auto& dpy = WL::Display::init(); + Application app; Window window(window_size.x, window_size.y); - window.onClosed = [&dpy](){dpy.stop();}; window.setTitle("Example application"); - window.onDraw = [&window, animate](SkCanvas *surf, float scale ) { - render(surf, scale); - - if (animate) - window.refresh(); - }; + window.animate = animate; + window.onClosed = [&app](){app.stop();}; window.onReshape = [&background_color](int, int) { glClearColor(background_color.red + 0.1, background_color.green, @@ -183,7 +100,7 @@ int run_app( glClear(GL_COLOR_BUFFER_BIT); }; - dpy.start_event(); + app.run(); } catch (const char* err) { std::cerr<<"Error: "< +#include + +void GlSkiaContext::init(GrGLGetProc gl_get_proc) +{ + auto _xface = GrGLMakeNativeInterface(); + if (_xface == nullptr) { + //backup plan. see https://gist.github.com/ad8e/dd150b775ae6aa4d5cf1a092e4713add?permalink_comment_id=4680136#gistcomment-4680136 + _xface = GrGLMakeAssembledInterface( + nullptr, gl_get_proc); + } + + _ctx = GrDirectContext::MakeGL(_xface); + if (!_ctx) + throw std::runtime_error("failed to make Skia context"); +} + +sk_sp GlSkiaContext::makeSurface(int width, int height) noexcept +{ + GrGLFramebufferInfo framebufferInfo; + framebufferInfo.fFBOID = 0; // assume default framebuffer + framebufferInfo.fFormat = GL_RGBA8; + + SkColorType colorType = kRGBA_8888_SkColorType; + target = std::make_unique( + width, + height, + 1, // sample count + 8, // stencil bits + framebufferInfo); + + return target->isValid() ? SkSurface::MakeFromBackendRenderTarget(_ctx.get(), + *target.get(), + kBottomLeft_GrSurfaceOrigin, + colorType, + nullptr, + nullptr) + : nullptr; +} + diff --git a/examples/host/linux/skia_context.h b/examples/host/linux/skia_context.h new file mode 100644 index 0000000..b68667d --- /dev/null +++ b/examples/host/linux/skia_context.h @@ -0,0 +1,28 @@ +#ifndef SKIA_CONTEXT_H +#define SKIA_CONTEXT_H + +#include "GrDirectContext.h" +#include "gl/GrGLAssembleInterface.h" + +#include "SkSurface.h" + +class GlSkiaContext +{ +public: + GlSkiaContext(GlSkiaContext const&) = delete; + GlSkiaContext& operator=(GlSkiaContext const&) = delete; + GlSkiaContext(GlSkiaContext&& other) = delete; + GlSkiaContext& operator=(GlSkiaContext&&) = delete; + + GlSkiaContext() = default; + + void init(GrGLGetProc gl_get_proc); + + sk_sp makeSurface(int width, int height) noexcept; + +private: + sk_sp _ctx; + std::unique_ptr target; +}; + +#endif // SKIA_CONTEXT_H diff --git a/examples/host/linux/wayland/application.cpp b/examples/host/linux/wayland/application.cpp new file mode 100644 index 0000000..ff96d6f --- /dev/null +++ b/examples/host/linux/wayland/application.cpp @@ -0,0 +1,137 @@ +#include "../application.h" + +#include "contextegl.h" +#include "xdgshell.h" + + +struct Surface::Impl: public WL::Toplevel +{ + Impl(const WL::Display &display, ::Surface* holder, int width, int height): + WL::Toplevel(display, width, height), + m_display(display), + m_holder(holder), + m_need_redraw(false) + {} + + ~Impl() + { + m_buffer.destroy(m_context.m_egl_display); + + std::cout << "DestroyWindow " <skia_surf = m_context.makeSurface(m_width, m_height); + if (m_holder->skia_surf) { + m_buffer = cfg.move_buffer(); + m_holder->configure(m_width, m_height, SurfaceState::resizing); + m_need_redraw = true; + } + } + + void draw(float scale) override + { + m_need_redraw = m_holder->draw(scale); + + m_holder->skia_surf->flush(); + m_context.flush(m_buffer); + } + + void configure(unsigned w, unsigned h, unsigned s) override + { + unsigned state = 0; + if (s & WL::resizing) + state |= SurfaceState::resizing; + if (s & WL::maximized) + state |= SurfaceState::maximized; + if (s & WL::activated) + state |= SurfaceState::activated; + if (s & WL::fullscreen) + state |= SurfaceState::fullscreen; + + if (s & WL::resizing){ + m_buffer.resize(w, h); + } + + m_holder->configure(w, h, state); + m_need_redraw = true; + } + + void closed() override + { + m_holder->closed(); + } + + const WL::Display &m_display; + WL::ContextEGL m_context; + WL::ContextEGL::Buffer m_buffer; + + ::Surface* m_holder; + + bool m_need_redraw; +}; + +class Application::DisplayImpl +{ +public: + static DisplayImpl& inst() + { + static DisplayImpl dpy(WL::Display::create_default()); + return dpy; + } + + void start_event(bool &isrun); + + const WL::Display& display(){return m_display;} + +private: + DisplayImpl(WL::Display &&dpy): m_display(std::move(dpy)){} + + WL::Display m_display; + Surface::Impl* m_win{nullptr}; + friend class Surface; +}; + +void Application::DisplayImpl::start_event(bool &isrun) +{ + assert (m_win); + + while (isrun) { + m_display.event_wait(); + m_win->event_process(); + } +} + +void Application::run() +{ + if (isRuning) return; + isRuning = true; + + DisplayImpl::inst().start_event(isRuning); +} + +Surface::~Surface() = default; + +Surface::Surface(int width, int height): + impl{std::make_unique(Application::DisplayImpl::inst().display(), this, width, height)} +{ + Application::DisplayImpl::inst().m_win = impl.get(); +} + +void Surface::setTitle(const char* txt) +{ + impl->setTitle(txt); +} diff --git a/examples/host/linux/wayland/contextegl.cpp b/examples/host/linux/wayland/contextegl.cpp index 94d9f52..207473b 100644 --- a/examples/host/linux/wayland/contextegl.cpp +++ b/examples/host/linux/wayland/contextegl.cpp @@ -1,18 +1,19 @@ #include "contextegl.h" -#include "display.h" +#include "core.h" #include +#include using namespace WL; -ContextEGL::ContextEGL(bool transparent): - m_egl_display(eglGetDisplay(Display::instance().native())) +ContextEGL::Config::Config(wl_display *dpy, const Surface &wl, uint32_t width, uint32_t height): + m_dpy(eglGetDisplay(dpy)) { EGLint majorVersion; EGLint minorVersion; - if (m_egl_display == EGL_NO_DISPLAY || - eglInitialize(m_egl_display, &majorVersion, &minorVersion) != EGL_TRUE) { + if (m_dpy == EGL_NO_DISPLAY || + eglInitialize(m_dpy, &majorVersion, &minorVersion) != EGL_TRUE) { throw std::runtime_error("Can't connect to egl display"); } @@ -20,7 +21,7 @@ ContextEGL::ContextEGL(bool transparent): if (eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) throw std::runtime_error("Can't bind EGL_OPENGL_ES_API"); - std::cerr<<"EGL: "< void * { + return (void *) eglGetProcAddress(p); + }); - std::cerr<<"context GL_VENDOR: "< +#include "../skia_context.h" + #include #include -//#include - namespace WL { -class NativeSurface; -class Display; +class Surface; -class ContextEGL +class ContextEGL: public GlSkiaContext { public: - class BufferEGL + class Buffer { public: - BufferEGL(ContextEGL &ctx, NativeSurface &wl, uint32_t width, uint32_t height); - void resize(uint32_t width, uint32_t height) {wl_egl_window_resize(m_egl_window, width, height, 0, 0);} - bool valid() const {return m_egl_surface != nullptr;} + bool empty() const {return m_egl_surface == nullptr;} + + void destroy(EGLDisplay dpy) + { + if (m_egl_surface){ + eglDestroySurface(dpy, m_egl_surface); + wl_egl_window_destroy(m_egl_window); + m_egl_surface = nullptr; + } + } - protected: + private: wl_egl_window *m_egl_window{nullptr}; EGLSurface m_egl_surface{nullptr}; friend class ContextEGL; }; - using Buffer = BufferEGL; + class Config final + { + public: + explicit Config(wl_display *dpy, + const Surface &wl, + uint32_t width, uint32_t height); + + ~Config() + {m_buffer.destroy(m_dpy);} + + Buffer move_buffer() + { + auto result = m_buffer; + m_buffer = Buffer(); + return result; + } - void makeCurrent(Buffer &buf); + private: + EGLDisplay m_dpy; + EGLConfig m_egl_config; + Buffer m_buffer; + + friend class ContextEGL; + }; + + void init(const Config &cfg); + + void makeCurrent(const Buffer &buf); void flush(Buffer &buf) const; - void destroy(Buffer &buf); - ContextEGL(bool transparent = true); ~ContextEGL(); operator bool() const { return m_egl_display != nullptr; } - bool opaque() const; - + //bool opaque() const; + EGLDisplay m_egl_display{nullptr}; private: - EGLDisplay m_egl_display; - EGLContext m_egl_context; - EGLConfig m_egl_config ; - // static inline ContextEGL *s_instance = nullptr; + EGLContext m_egl_context{nullptr}; + }; } diff --git a/examples/host/linux/wayland/core.cpp b/examples/host/linux/wayland/core.cpp index a7e3445..28bd6f5 100644 --- a/examples/host/linux/wayland/core.cpp +++ b/examples/host/linux/wayland/core.cpp @@ -19,6 +19,37 @@ NativeSurface::NativeSurface(wl_compositor *compositor, m_fscale(manager ? wp_fractional_scale_manager_v1_get_fractional_scale(manager->c_ptr(), c_ptr()) : nullptr) { + static const wl_surface_listener lsr { + .enter = [](void *data, + struct wl_surface *wl_surface, + struct wl_output *output){ + + }, + + .leave = [](void *data, + struct wl_surface *wl_surface, + struct wl_output *output){ + + }, + + .preferred_buffer_scale = [](void *data, + struct wl_surface *wl_surface, + int32_t factor){ + auto surface = static_cast(data); + + if (!surface->m_fscale) + surface->buffer_scale(factor); + }, + + .preferred_buffer_transform = [](void *data, + struct wl_surface *wl_surface, + uint32_t transform){ + + } + }; + + wl_surface_add_listener(c_ptr(), &lsr, this); + if (m_fscale) { static const wp_fractional_scale_v1_listener lsr{ .preferred_scale = [](void *data, wp_fractional_scale_v1 *, uint32_t scale) { @@ -207,13 +238,14 @@ const wl_keyboard_listener Seat::keyboard_listener = { auto seat = static_cast(data); - if (seat->m_focused_surf->onFocused) + if (seat->m_focused_surf && seat->m_focused_surf->onFocused){ seat->m_focused_surf->onFocused(false); - seat->m_focused_surf = nullptr; + seat->m_focused_surf = nullptr; - struct itimerspec timer = {0}; - timerfd_settime(seat->key_repeat_fd, 0, &timer, NULL); + struct itimerspec timer = {0}; + timerfd_settime(seat->key_repeat_fd, 0, &timer, NULL); + } }, .key = [](void *data, wl_keyboard *wl_kd, uint32_t /*serial*/, uint32_t time, diff --git a/examples/host/linux/wayland/core.h b/examples/host/linux/wayland/core.h index 3b23759..c39e9e8 100644 --- a/examples/host/linux/wayland/core.h +++ b/examples/host/linux/wayland/core.h @@ -240,25 +240,24 @@ using FractionalScaleManager = Protocol; -class NativeSurface: public Proxy +class Surface: public Proxy, + public SeatListener { public: - explicit NativeSurface(wl_compositor *compositor, + explicit Surface(wl_compositor *compositor, const FractionalScaleManager *manager); - inline void listenerInput(SeatListener &input) - { wl_surface_set_user_data(c_ptr(), &input); } - inline void commit() { wl_surface_commit(c_ptr()); } - std::function onScale; - protected: void setAreaOpaque(wl_compositor *compositor, int32_t w, int32_t h) const; float m_scale{1}; + virtual void draw(float /*scale*/) = 0; + virtual void buffer_scale(float /*scale*/) = 0; + private: Proxy m_fscale; @@ -271,7 +270,7 @@ using Viewporter = Protocol { public: - Viewport(const WL::Viewporter *vpr, NativeSurface const &surface); + Viewport(const WL::Viewporter *vpr, Surface const &surface); Viewport() = default; void setDestination(int32_t width, int32_t height) diff --git a/examples/host/linux/wayland/cursor-shape-v1-client-protocol.h b/examples/host/linux/wayland/cursor-shape-v1-client-protocol.h deleted file mode 100644 index 72ed2ba..0000000 --- a/examples/host/linux/wayland/cursor-shape-v1-client-protocol.h +++ /dev/null @@ -1,426 +0,0 @@ -/* Generated by wayland-scanner 1.23.1 */ - -#ifndef CURSOR_SHAPE_V1_CLIENT_PROTOCOL_H -#define CURSOR_SHAPE_V1_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_cursor_shape_v1 The cursor_shape_v1 protocol - * @section page_ifaces_cursor_shape_v1 Interfaces - * - @subpage page_iface_wp_cursor_shape_manager_v1 - cursor shape manager - * - @subpage page_iface_wp_cursor_shape_device_v1 - cursor shape for a device - * @section page_copyright_cursor_shape_v1 Copyright - *
- *
- * Copyright 2018 The Chromium Authors
- * Copyright 2023 Simon Ser
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- */ -struct wl_pointer; -struct wp_cursor_shape_device_v1; -struct wp_cursor_shape_manager_v1; -struct zwp_tablet_tool_v2; - -#ifndef WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE -#define WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE -/** - * @page page_iface_wp_cursor_shape_manager_v1 wp_cursor_shape_manager_v1 - * @section page_iface_wp_cursor_shape_manager_v1_desc Description - * - * This global offers an alternative, optional way to set cursor images. This - * new way uses enumerated cursors instead of a wl_surface like - * wl_pointer.set_cursor does. - * - * Warning! The protocol described in this file is currently in the testing - * phase. Backward compatible changes may be added together with the - * corresponding interface version bump. Backward incompatible changes can - * only be done by creating a new major version of the extension. - * @section page_iface_wp_cursor_shape_manager_v1_api API - * See @ref iface_wp_cursor_shape_manager_v1. - */ -/** - * @defgroup iface_wp_cursor_shape_manager_v1 The wp_cursor_shape_manager_v1 interface - * - * This global offers an alternative, optional way to set cursor images. This - * new way uses enumerated cursors instead of a wl_surface like - * wl_pointer.set_cursor does. - * - * Warning! The protocol described in this file is currently in the testing - * phase. Backward compatible changes may be added together with the - * corresponding interface version bump. Backward incompatible changes can - * only be done by creating a new major version of the extension. - */ -extern const struct wl_interface wp_cursor_shape_manager_v1_interface; -#endif -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE -#define WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE -/** - * @page page_iface_wp_cursor_shape_device_v1 wp_cursor_shape_device_v1 - * @section page_iface_wp_cursor_shape_device_v1_desc Description - * - * This interface allows clients to set the cursor shape. - * @section page_iface_wp_cursor_shape_device_v1_api API - * See @ref iface_wp_cursor_shape_device_v1. - */ -/** - * @defgroup iface_wp_cursor_shape_device_v1 The wp_cursor_shape_device_v1 interface - * - * This interface allows clients to set the cursor shape. - */ -extern const struct wl_interface wp_cursor_shape_device_v1_interface; -#endif - -#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY 0 -#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER 1 -#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2 2 - - -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - */ -#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - */ -#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER_SINCE_VERSION 1 -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - */ -#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2_SINCE_VERSION 1 - -/** @ingroup iface_wp_cursor_shape_manager_v1 */ -static inline void -wp_cursor_shape_manager_v1_set_user_data(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wp_cursor_shape_manager_v1, user_data); -} - -/** @ingroup iface_wp_cursor_shape_manager_v1 */ -static inline void * -wp_cursor_shape_manager_v1_get_user_data(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wp_cursor_shape_manager_v1); -} - -static inline uint32_t -wp_cursor_shape_manager_v1_get_version(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1) -{ - return wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1); -} - -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - * - * Destroy the cursor shape manager. - */ -static inline void -wp_cursor_shape_manager_v1_destroy(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1, - WP_CURSOR_SHAPE_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - * - * Obtain a wp_cursor_shape_device_v1 for a wl_pointer object. - * - * When the pointer capability is removed from the wl_seat, the - * wp_cursor_shape_device_v1 object becomes inert. - */ -static inline struct wp_cursor_shape_device_v1 * -wp_cursor_shape_manager_v1_get_pointer(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, struct wl_pointer *pointer) -{ - struct wl_proxy *cursor_shape_device; - - cursor_shape_device = wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1, - WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER, &wp_cursor_shape_device_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), 0, NULL, pointer); - - return (struct wp_cursor_shape_device_v1 *) cursor_shape_device; -} - -/** - * @ingroup iface_wp_cursor_shape_manager_v1 - * - * Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object. - * - * When the zwp_tablet_tool_v2 is removed, the wp_cursor_shape_device_v1 - * object becomes inert. - */ -static inline struct wp_cursor_shape_device_v1 * -wp_cursor_shape_manager_v1_get_tablet_tool_v2(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, struct zwp_tablet_tool_v2 *tablet_tool) -{ - struct wl_proxy *cursor_shape_device; - - cursor_shape_device = wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1, - WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2, &wp_cursor_shape_device_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), 0, NULL, tablet_tool); - - return (struct wp_cursor_shape_device_v1 *) cursor_shape_device; -} - -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM -#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM -/** - * @ingroup iface_wp_cursor_shape_device_v1 - * cursor shapes - * - * This enum describes cursor shapes. - * - * The names are taken from the CSS W3C specification: - * https://w3c.github.io/csswg-drafts/css-ui/#cursor - */ -enum wp_cursor_shape_device_v1_shape { - /** - * default cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT = 1, - /** - * a context menu is available for the object under the cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU = 2, - /** - * help is available for the object under the cursor - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP = 3, - /** - * pointer that indicates a link or another interactive element - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER = 4, - /** - * progress indicator - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS = 5, - /** - * program is busy, user should wait - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT = 6, - /** - * a cell or set of cells may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CELL = 7, - /** - * simple crosshair - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR = 8, - /** - * text may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT = 9, - /** - * vertical text may be selected - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT = 10, - /** - * drag-and-drop: alias of/shortcut to something is to be created - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS = 11, - /** - * drag-and-drop: something is to be copied - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY = 12, - /** - * drag-and-drop: something is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE = 13, - /** - * drag-and-drop: the dragged item cannot be dropped at the current cursor location - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP = 14, - /** - * drag-and-drop: the requested action will not be carried out - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED = 15, - /** - * drag-and-drop: something can be grabbed - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB = 16, - /** - * drag-and-drop: something is being grabbed - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING = 17, - /** - * resizing: the east border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE = 18, - /** - * resizing: the north border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE = 19, - /** - * resizing: the north-east corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE = 20, - /** - * resizing: the north-west corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE = 21, - /** - * resizing: the south border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE = 22, - /** - * resizing: the south-east corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE = 23, - /** - * resizing: the south-west corner is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE = 24, - /** - * resizing: the west border is to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE = 25, - /** - * resizing: the east and west borders are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE = 26, - /** - * resizing: the north and south borders are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE = 27, - /** - * resizing: the north-east and south-west corners are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE = 28, - /** - * resizing: the north-west and south-east corners are to be moved - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE = 29, - /** - * resizing: that the item/column can be resized horizontally - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE = 30, - /** - * resizing: that the item/row can be resized vertically - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE = 31, - /** - * something can be scrolled in any direction - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL = 32, - /** - * something can be zoomed in - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN = 33, - /** - * something can be zoomed out - */ - WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT = 34, -}; -#endif /* WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM */ - -#ifndef WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM -#define WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM -enum wp_cursor_shape_device_v1_error { - /** - * the specified shape value is invalid - */ - WP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE = 1, -}; -#endif /* WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM */ - -#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY 0 -#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE 1 - - -/** - * @ingroup iface_wp_cursor_shape_device_v1 - */ -#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_wp_cursor_shape_device_v1 - */ -#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE_SINCE_VERSION 1 - -/** @ingroup iface_wp_cursor_shape_device_v1 */ -static inline void -wp_cursor_shape_device_v1_set_user_data(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) wp_cursor_shape_device_v1, user_data); -} - -/** @ingroup iface_wp_cursor_shape_device_v1 */ -static inline void * -wp_cursor_shape_device_v1_get_user_data(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1) -{ - return wl_proxy_get_user_data((struct wl_proxy *) wp_cursor_shape_device_v1); -} - -static inline uint32_t -wp_cursor_shape_device_v1_get_version(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1) -{ - return wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1); -} - -/** - * @ingroup iface_wp_cursor_shape_device_v1 - * - * Destroy the cursor shape device. - * - * The device cursor shape remains unchanged. - */ -static inline void -wp_cursor_shape_device_v1_destroy(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_device_v1, - WP_CURSOR_SHAPE_DEVICE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_wp_cursor_shape_device_v1 - * - * Sets the device cursor to the specified shape. The compositor will - * change the cursor image based on the specified shape. - * - * The cursor actually changes only if the input device focus is one of - * the requesting client's surfaces. If any, the previous cursor image - * (surface or shape) is replaced. - * - * The "shape" argument must be a valid enum entry, otherwise the - * invalid_shape protocol error is raised. - * - * This is similar to the wl_pointer.set_cursor and - * zwp_tablet_tool_v2.set_cursor requests, but this request accepts a - * shape instead of contents in the form of a surface. Clients can mix - * set_cursor and set_shape requests. - * - * The serial parameter must match the latest wl_pointer.enter or - * zwp_tablet_tool_v2.proximity_in serial number sent to the client. - * Otherwise the request will be ignored. - */ -static inline void -wp_cursor_shape_device_v1_set_shape(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1, uint32_t serial, uint32_t shape) -{ - wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_device_v1, - WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1), 0, serial, shape); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/examples/host/linux/wayland/cursor-shape-v1-protocol.c b/examples/host/linux/wayland/cursor-shape-v1-protocol.c deleted file mode 100644 index 3c2c1a0..0000000 --- a/examples/host/linux/wayland/cursor-shape-v1-protocol.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Generated by wayland-scanner 1.23.1 */ - -/* - * Copyright 2018 The Chromium Authors - * Copyright 2023 Simon Ser - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include "wayland-util.h" - -#ifndef __has_attribute -# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ -#endif - -#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) -#define WL_PRIVATE __attribute__ ((visibility("hidden"))) -#else -#define WL_PRIVATE -#endif - -extern const struct wl_interface wl_pointer_interface; -extern const struct wl_interface wp_cursor_shape_device_v1_interface; -extern const struct wl_interface zwp_tablet_tool_v2_interface; - -static const struct wl_interface *cursor_shape_v1_types[] = { - NULL, - NULL, - &wp_cursor_shape_device_v1_interface, - &wl_pointer_interface, - &wp_cursor_shape_device_v1_interface, - &zwp_tablet_tool_v2_interface, -}; - -static const struct wl_message wp_cursor_shape_manager_v1_requests[] = { - { "destroy", "", cursor_shape_v1_types + 0 }, - { "get_pointer", "no", cursor_shape_v1_types + 2 }, - { "get_tablet_tool_v2", "no", cursor_shape_v1_types + 4 }, -}; - -WL_PRIVATE const struct wl_interface wp_cursor_shape_manager_v1_interface = { - "wp_cursor_shape_manager_v1", 1, - 3, wp_cursor_shape_manager_v1_requests, - 0, NULL, -}; - -static const struct wl_message wp_cursor_shape_device_v1_requests[] = { - { "destroy", "", cursor_shape_v1_types + 0 }, - { "set_shape", "uu", cursor_shape_v1_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface wp_cursor_shape_device_v1_interface = { - "wp_cursor_shape_device_v1", 1, - 2, wp_cursor_shape_device_v1_requests, - 0, NULL, -}; - diff --git a/examples/host/linux/wayland/display.cpp b/examples/host/linux/wayland/display.cpp index 3848898..aa0f658 100644 --- a/examples/host/linux/wayland/display.cpp +++ b/examples/host/linux/wayland/display.cpp @@ -4,16 +4,13 @@ using namespace WL; -std::unique_ptr Display::s_instance; - Display::Display(const char *dpy_name, std::unique_ptr &&protocols) : m_display(wl_display_connect(dpy_name)) , m_compositor(nullptr) - , m_surfaces(nullptr) - , isRuning(false) + , m_protocols(std::move(protocols)) { if (!m_display) - throw std::runtime_error("display with name 'dpy_name' does not exist"); + throw std::runtime_error("display does not exist"); static const wl_registry_listener lsr = { .global = [](void *data, @@ -23,10 +20,10 @@ Display::Display(const char *dpy_name, std::unique_ptr &&prot uint32_t version) { auto dpy = static_cast(data); - // std::cerr<<"available interface "<m_compositor = - (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, version); + dpy->m_compositor.reset( + (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, version)); else if (auto item = dpy->m_protocols->find(interface)) item->bind(registry, name, version); @@ -37,135 +34,87 @@ Display::Display(const char *dpy_name, std::unique_ptr &&prot } }; - auto registry = wl_display_get_registry(m_display); + auto registry = wl_display_get_registry(m_display.get()); - if (!registry || wl_registry_add_listener(registry, &lsr, this) < 0){ - wl_display_disconnect(m_display); + if (!registry || wl_registry_add_listener(registry, &lsr, this) < 0) throw std::runtime_error("add registry listener failed"); - } - m_protocols = std::move(protocols); - wl_display_roundtrip(m_display); + wl_display_roundtrip(m_display.get()); wl_registry_destroy(registry); - if (!m_compositor) { - m_protocols.reset(nullptr); - wl_display_disconnect(m_display); + if (!m_compositor) throw std::runtime_error("wayland compositor not found"); - } - m_fds[EventT::wayland].fd = wl_display_get_fd(m_display); + m_fds[EventT::wayland].fd = wl_display_get_fd(m_display.get()); m_fds[EventT::wayland].events = POLLIN; - m_fds[EventT::system].fd = -1; -} - -Display::~Display() -{ - if (m_compositor) - wl_proxy_destroy((wl_proxy*) m_compositor); + m_fds[EventT::system].fd = -1; //To do add system interrupts - m_protocols.reset(nullptr); - wl_display_disconnect(m_display); + m_seat = protocol(); + m_fds[EventT::key].fd = m_seat ? m_seat->key_repeat_fd : -1; + m_fds[EventT::key].events = POLLIN; } -void Display::start_event() +void Display::event_wait() { - if (isRuning) return; + auto display = c_ptr(); - isRuning = true; - - auto seat = protocol(); - - if (seat){ - m_fds[EventT::system].fd = seat->key_repeat_fd; - m_fds[EventT::system].events = POLLIN; - m_fds[EventT::system].revents = 0; + while (wl_display_prepare_read(display) != 0) { + if (wl_display_dispatch_pending(display) < 0) + throw std::runtime_error("failed to dispatch pending Wayland events"); } - while (isRuning) { + int ret; - while (wl_display_prepare_read(m_display) != 0) { - if (wl_display_dispatch_pending(m_display) < 0) - throw std::runtime_error("failed to dispatch pending Wayland events"); + while ((ret = wl_display_flush(display)) < 0) { + if (errno == EINTR) { + continue; } - int ret; - - while ((ret = wl_display_flush(m_display)) < 0) { - if (errno == EINTR) { - continue; - } - - if (errno == EAGAIN) { - struct pollfd fds[1]; - fds[0].fd = m_fds[EventT::wayland].fd; - fds[0].events = POLLOUT; - - do { - ret = poll(fds, 1, -1); - } while (ret < 0 && errno == EINTR); - } - } + if (errno == EAGAIN) { + struct pollfd fds[1]; + fds[0].fd = m_fds[EventT::wayland].fd; + fds[0].events = POLLOUT; - if (ret < 0) { - wl_display_cancel_read(m_display); - throw std::runtime_error("failed to display flush"); + do { + ret = poll(fds, 1, -1); + } while (ret < 0 && errno == EINTR); } + } - do { - ret = poll(m_fds, EventT::count, -1); - } while (ret < 0 && errno == EINTR); - - if (ret < 0) { - if (m_fds[0].revents & POLLHUP) - throw std::runtime_error("disconnected from wayland"); + if (ret < 0) { + wl_display_cancel_read(display); + throw std::runtime_error("failed to display flush"); + } - wl_display_cancel_read(m_display); - throw std::runtime_error("failed to poll():"); - } + do { + ret = poll(m_fds, EventT::count - 1, -1); //To do add system interrupts + } while (ret < 0 && errno == EINTR); - if ((m_fds[0].revents & POLLIN)) { + if (ret < 0) { + if (m_fds[0].revents & POLLHUP) + throw std::runtime_error("disconnected from wayland"); - if (wl_display_read_events(m_display) < 0) - throw std::runtime_error("failed to read Wayland events"); - } - else - wl_display_cancel_read(m_display); + wl_display_cancel_read(display); + throw std::runtime_error("failed to poll():"); + } - if (wl_display_dispatch_pending(m_display) < 0) - throw std::runtime_error("failed to dispatch pending Wayland events"); + if ((m_fds[0].revents & POLLIN)) { - if (m_fds[1].revents & POLLIN) { - uint64_t repeats; - if (read(m_fds[1].fd, &repeats, sizeof(repeats)) == 8) { - for (uint64_t i = 0; i < repeats; i++) - seat->emitKeypress(); - } - } + if (wl_display_read_events(display) < 0) + throw std::runtime_error("failed to read Wayland events"); + } + else + wl_display_cancel_read(display); - auto node = m_surfaces; - while (node){ - if (node->draw_f){ - auto cb = std::move(node->draw_f); - cb(); - } + if (wl_display_dispatch_pending(display) < 0) + throw std::runtime_error("failed to dispatch pending Wayland events"); - node = node->next; + if (m_fds[1].revents & POLLIN) { + uint64_t repeats; + if (read(m_fds[1].fd, &repeats, sizeof(repeats)) == 8) { + for (uint64_t i = 0; i < repeats; i++) + m_seat->emitKeypress(); } } } - -void Display::add(Node &node) -{ - if(!m_surfaces){ - m_surfaces = &node; - m_surfaces->prev = m_surfaces; - } - else { - auto last = m_surfaces->prev; - m_surfaces->prev = &node; - node.prev = last; - last->next = &node; - } -} diff --git a/examples/host/linux/wayland/display.h b/examples/host/linux/wayland/display.h index ac2e551..b5edd0c 100644 --- a/examples/host/linux/wayland/display.h +++ b/examples/host/linux/wayland/display.h @@ -21,7 +21,7 @@ class ProtocolContainer public: virtual ~ProtocolContainer() = default; virtual ProtocolBase* find(const char*) noexcept = 0; - virtual ProtocolBase* find(const wl_interface*) noexcept = 0; + virtual const ProtocolBase* find(const wl_interface*) noexcept = 0; }; template @@ -52,7 +52,7 @@ class ProtocolTuple final: public ProtocolContainer return result; } - ProtocolBase* find(const wl_interface* iface) noexcept override + const ProtocolBase* find(const wl_interface* iface) noexcept override { ProtocolBase* result = nullptr; tuple_find([iface, &result](ProtocolBase& gb, @@ -76,21 +76,11 @@ class Display { public: template - static Display& init(const char *name = nullptr) + static Display create_default() { - assert(!s_instance); - - s_instance = std::make_unique(name, - std::make_unique>()); - return *s_instance.get(); - } - - inline static Display& instance() noexcept - { - assert(s_instance); - return *s_instance.get(); + return Display(nullptr, std::make_unique>()); } Display(Display const&) = delete; @@ -98,19 +88,18 @@ class Display Display(Display&& other) = default; Display& operator=(Display&&) = delete; - ~Display(); + Display(const char *name, std::unique_ptr &&protocols); - void start_event(); - void stop(){isRuning = false;} + void event_wait(); - wl_display* native() const {return m_display;} - //wl_compositor* compositor() const {return m_compositor;} + wl_display* c_ptr() const {return m_display.get();} + wl_compositor* compositor() const {return m_compositor.get();} template const G* protocol() const { if (auto search = m_protocols->find(G::iface())) - return static_cast(search); + return static_cast(search); return nullptr; } @@ -119,124 +108,34 @@ class Display const G& ensureProtocol() const { if (auto search = m_protocols->find(G::iface())) - return *static_cast(search); + return *static_cast(search); - std::string err("protocol not find: "); + std::string err("protocol not found: "); throw std::runtime_error(err + G::iface()->name); } - Display(const char *name, std::unique_ptr &&protocols); - private: - wl_display* m_display; - wl_compositor* m_compositor; - - std::unique_ptr m_protocols; - - enum EventT - {wayland, system, count}; - - pollfd m_fds[EventT::count]; - - using DrawFunc = std::function; - struct Node - { - DrawFunc draw_f; - Node *next{nullptr}; - Node *prev{nullptr}; - }; - - //std::vector m_surfaces; - Node *m_surfaces; - void add(Node &node); - - bool isRuning; - static std::unique_ptr s_instance; - - template - friend class Surface; -}; - -template -class Surface : public NativeSurface -{ - using Buffer = std::unique_ptr; - - static inline CTX *s_ctx = nullptr; - static inline void *s_buf = nullptr; - - Display::Node m_node; -public: - Surface(): - NativeSurface(Display::instance().m_compositor, - Display::instance().protocol()) - {} - - ~Surface() + struct Deleter { - s_ctx->destroy(*m_buffer.get()); - - //если окно последнее уничтожаем контекст - if (m_node.prev == &m_node){ - Display::instance().m_surfaces = nullptr; - delete s_ctx; - s_ctx = nullptr; - } - else { - m_node.prev->next = m_node.next; - } - } + void operator()(wl_display* data) const + {wl_display_disconnect(data);} - void refresh() - { - if (mapped()) - m_node.draw_f = [this](){ - if (s_buf != m_buffer.get()){ - s_ctx->makeCurrent(*m_buffer.get()); - s_buf = m_buffer.get(); - } - draw(m_scale); - s_ctx->flush(*m_buffer.get()); - }; - } + void operator()(wl_compositor* data) const + {wl_proxy_destroy((wl_proxy*) data);} + }; -protected: - Buffer m_buffer; + std::unique_ptr m_display; + std::unique_ptr m_compositor; - CTX& context() const - { - //Context динамически создается для предсказуемого удаления т.к. он static - if (!s_ctx) s_ctx = new CTX; - return *s_ctx; - } + const Seat *m_seat; - bool mapped() const {return m_node.prev != nullptr;} - - bool makeBuffer(unsigned &width, unsigned &height) - { - auto scale_width = width * m_scale; - auto scale_height = height * m_scale; - auto buf = std::make_unique( - context(), *this, scale_width, scale_height); - - if (buf->valid()){ - Display::instance().add(m_node); - width = scale_width; - height = scale_height; - s_ctx->makeCurrent(*buf.get()); - s_buf = buf.get(); - m_buffer = std::move(buf); - return true; - } - - return false; - } + std::unique_ptr m_protocols; - void setAreaOpaque(int32_t w, int32_t h) const - {NativeSurface::setAreaOpaque(Display::instance().m_compositor, w, h);} + enum EventT + {wayland, key, system, count}; - virtual void draw(float) = 0; + pollfd m_fds[EventT::count]; }; } diff --git a/examples/host/linux/wayland/xdgshell.cpp b/examples/host/linux/wayland/xdgshell.cpp index 403ea9a..f609bf3 100644 --- a/examples/host/linux/wayland/xdgshell.cpp +++ b/examples/host/linux/wayland/xdgshell.cpp @@ -17,16 +17,15 @@ void XDGWmBase::bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept xdg_wm_base_add_listener (c_ptr(), &listener, nullptr); } -NativeToplevel::NativeToplevel(const NativeSurface &surface, uint32_t width, uint32_t height) - : m_xdg_surfase(xdg_wm_base_get_xdg_surface( - Display::instance().ensureProtocol().c_ptr(), - surface.c_ptr()), +Toplevel::Toplevel(const Display &dpy, uint32_t width, uint32_t height) + : Surface(dpy.compositor(), dpy.protocol()) + , m_xdg_surfase(xdg_wm_base_get_xdg_surface(dpy.ensureProtocol().c_ptr(), c_ptr()), "Can't create xdg surface") , m_top(xdg_surface_get_toplevel(m_xdg_surfase.c_ptr()), "Can't create toplevel role") - , m_decor(Display::instance().protocol() ? + , m_decor(dpy.protocol() ? zxdg_decoration_manager_v1_get_toplevel_decoration( - Display::instance().protocol()->c_ptr(), m_top.c_ptr()) + dpy.protocol()->c_ptr(), m_top.c_ptr()) :nullptr) , m_width(width) , m_height(height) @@ -36,29 +35,30 @@ NativeToplevel::NativeToplevel(const NativeSurface &surface, uint32_t width, uin .configure = [](void* data, xdg_toplevel *tt, int32_t width, int32_t height, wl_array *states){ - auto win = static_cast(data); + auto inst = static_cast(data); xdg_toplevel_state *pos; - win->m_state = 0; - std::cout<<"states "<size<<" W "<m_state = 0; for (pos = (xdg_toplevel_state*)states->data; (const char *) pos < ((const char *) states->data + states->size); (pos)++){ - std::cout<<"--- "<<*pos<m_state |= (1 << *pos); + inst->m_state |= (1 << *pos); } if (width && height){ - win->m_width = width; - win->m_height = height; + inst->m_width = width; + inst->m_height = height; } + + //std::cout<<"states "<m_state<<" W "<(data); - win->closed(); + auto inst = static_cast(data); + inst->closed(); }, .configure_bounds = [](void* data, xdg_toplevel*, int32_t width, int32_t height){ @@ -67,11 +67,30 @@ NativeToplevel::NativeToplevel(const NativeSurface &surface, uint32_t width, uin }, .wm_capabilities = [](void *data, xdg_toplevel *xdg_toplevel, - wl_array *capabilities){} + wl_array *capabilities){ + std::cout<<"wm_capabilities: "<(data); + + // inst->mapped(); + } }; xdg_toplevel_add_listener(m_top.c_ptr(), &toplevel_lsr, this); + static const xdg_surface_listener surface_lsr{ + .configure = [](void* data, xdg_surface *xdg_surf, uint32_t serial){ + + auto inst = static_cast(data); + xdg_surface_ack_configure(xdg_surf, serial); +std::cout<<"xdg_surface_listener states "<m_state<<" W "<m_width<<" H "<m_height<m_state != 0) + inst->configure(inst->m_width, inst->m_height, inst->m_state); + } + }; + + xdg_surface_add_listener (this->m_xdg_surfase.c_ptr(), &surface_lsr, this); + commit(); + if (m_decor) zxdg_toplevel_decoration_v1_set_mode(m_decor.c_ptr(), ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); diff --git a/examples/host/linux/wayland/xdgshell.h b/examples/host/linux/wayland/xdgshell.h index f15990f..fec4aae 100644 --- a/examples/host/linux/wayland/xdgshell.h +++ b/examples/host/linux/wayland/xdgshell.h @@ -1,8 +1,6 @@ #ifndef XDGSHELL_H #define XDGSHELL_H -//#include - #include "display.h" #include "xdg-shell-client-protocol.h" #include "xdg-decoration-unstable-v1-client-protocol.h" @@ -31,12 +29,10 @@ using XDGDecorateManager = Protocol; -class NativeToplevel +class Toplevel: public Surface { public: - NativeToplevel(const NativeSurface &surface, - uint32_t width, - uint32_t height); + Toplevel(const Display &dpy, uint32_t width, uint32_t height); void setTitle(const char* title) {xdg_toplevel_set_title(m_top.c_ptr(), title);} @@ -50,57 +46,12 @@ class NativeToplevel Proxy m_decor; - template - friend class Toplevel; - protected: uint32_t m_width ; uint32_t m_height; uint32_t m_state ; virtual void closed() = 0; -}; - -template -class Toplevel: public Surface, public NativeToplevel -{ -public: - Toplevel(uint32_t width, uint32_t height): - NativeToplevel(*this, width, height) - { - static const xdg_surface_listener surface_lsr{ - .configure = [](void* data, xdg_surface *xdg_surf, uint32_t serial){ - - auto inst = static_cast(data); - xdg_surface_ack_configure(xdg_surf, serial); - - if (!inst->mapped()) { - - if (!inst->makeBuffer(inst->m_width, inst->m_height)) { - std::cerr << "Can't create window frame" << std::endl; - return; - } - - if (inst->configure(inst->m_width, inst->m_height, XDGState::resizing)){ - inst->draw(inst->m_scale); - inst->context().flush(*inst->m_buffer.get()); - } - - return; - } - - if (inst->m_state & XDGState::resizing) - inst->m_buffer->resize(inst->m_width, inst->m_height); - - if (inst->configure(inst->m_width, inst->m_height, inst->m_state)) - inst->refresh(); - }}; - - xdg_surface_add_listener (this->m_xdg_surfase.c_ptr(), &surface_lsr, this); - this->commit(); - } - -protected: /** * @brief configure вызывается композитором при изменении состояния (s) @@ -110,10 +61,9 @@ class Toplevel: public Surface, public NativeToplevel * @param s * @return должна возвращать true если требуется перерисовка */ - virtual bool configure(unsigned w, unsigned h, unsigned s) = 0; + virtual void configure(unsigned w, unsigned h, unsigned s) = 0; }; - // struct Positioner: Proxy // { // //const WlApplication &global; diff --git a/examples/host/linux/x11/application.cpp b/examples/host/linux/x11/application.cpp new file mode 100644 index 0000000..3fa694b --- /dev/null +++ b/examples/host/linux/x11/application.cpp @@ -0,0 +1,404 @@ +#include "../application.h" +#include "../skia_context.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace X11 { + + class ContextGLX final: public GlSkiaContext + { + public: + struct Buffer final + { + Window win_id{0}; + Colormap colormap{0}; + + void destroy(Display* dpy) + { + if (win_id){ + XFreeColormap (dpy, colormap); + XDestroyWindow(dpy, win_id); + } + } + }; + + struct Config final + { + explicit Config(Display* dpy, int width, int height); + ~Config() + {m_buffer.destroy(x11_dpy);} + + Buffer move_buffer() + { + auto id = m_buffer.win_id; + m_buffer.win_id = 0; + + return {id, m_buffer.colormap}; + } + + private: + Display* x11_dpy; + GLXFBConfig fb_config; + Buffer m_buffer; + + friend class ContextGLX; + }; + + void init(const Config &cfg); + void makeCurrent(const Buffer &buf); + void flush(Buffer &buf); + + ~ContextGLX(); + + Display* x11_display{nullptr}; + + private: + GLXContext m_context{nullptr}; + }; + + ContextGLX::Config::Config(Display* dpy, int width, int height): + x11_dpy(dpy) + { + auto screen_id = DefaultScreen(dpy); + + GLint majorGLX, minorGLX = 0; + glXQueryVersion(dpy, &majorGLX, &minorGLX); + std::cout<<"GLX: "< best_num_samp) ) { + best_fbc = i; + best_num_samp = samples; + if (info) + XFree(info); + info = vi; + } + else + XFree(vi); + } + } + + if (best_fbc < 0) + throw std::runtime_error("Failed to get a valid GLX visual"); + + fb_config = fbc[best_fbc]; + XFree(fbc); + + Window window_root_id = RootWindow(dpy, screen_id); + m_buffer.colormap = XCreateColormap(dpy, window_root_id, info->visual, AllocNone); + + XSetWindowAttributes windowAttribs; + windowAttribs.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask; + //windowAttribs.border_pixel = WhitePixel(m_display, screen_id); + //windowAttribs.background_pixel = WhitePixel(dpyx.display, screen_id); + //windowAttribs.override_redirect = True; + windowAttribs.colormap = m_buffer.colormap; + + m_buffer.win_id = XCreateWindow(dpy, + window_root_id, + 0, + 0, + width, + height, + 0, + info->depth, + InputOutput, + info->visual, + CWColormap | CWEventMask, // | CWBackPixel | CWBorderPixel, + &windowAttribs); + XFree(info); + } + + void ContextGLX::init(const Config &cfg) + { + assert(!m_context); // double initialization + + x11_display = cfg.x11_dpy; + + // Create GLX OpenGL context + typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; + glXCreateContextAttribsARB = + (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte*) "glXCreateContextAttribsARB" ); + + int context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + //GLX_CONTEXT_FLAGS_ARB, 0, + 0, 0 + }; + + const char *glxExts = glXQueryExtensionsString(x11_display, DefaultScreen(x11_display)); + if (strstr(glxExts, "GLX_ARB_create_context") == 0) { + std::cout << "GLX_ARB_create_context not supported"< void * { + return (void *) glXGetProcAddress((const GLubyte *)p); + }); + + std::cout << "GL Renderer: " << glGetString(GL_RENDERER) <skia_surf = m_context.makeSurface(width, height); + m_buffer = cfg.move_buffer(); + + XSetWMProtocols(display, m_buffer.win_id, &wm_delete_window_atom, 1); + XClearWindow(display, m_buffer.win_id); + XMapWindow(display, m_buffer.win_id); + } + + ~Impl() + { + m_context.makeCurrent({}); + m_buffer.destroy(m_context.x11_display); + + std::cout << "XDestroyWindow " <configure(xevent.xconfigure.width, + xevent.xconfigure.height, + SurfaceState::resizing); + + /* draw graphics */ + } else if (xevent.type == Expose + && xevent.xexpose.count == 0 ) { + + if (xevent.xexpose.width == 1 && xevent.xexpose.height == 1) { + m_holder->configure(0, 0, SurfaceState::resizing); + continue; + } + + draw(); + + /* close window */ + } else if ( xevent.type == ClientMessage + && xevent.xclient.data.l[0] == wm_delete_window_atom ) { + + m_holder->closed();//std::cout << "XPending " << xevent.type << std::endl; + + }else if ( xevent.type == MapNotify ) { + std::cout << "MapNotify " <draw(1); + + m_holder->skia_surf->flush(); + m_context.flush(m_buffer); + } + + X11::ContextGLX m_context; + X11::ContextGLX::Buffer m_buffer; + Surface* m_holder; + bool m_need_redraw; + Atom wm_delete_window_atom; +}; + +class Application::DisplayImpl +{ +public: + static DisplayImpl& inst() + { + static DisplayImpl dpy; + return dpy; + } + + void start_event(bool &isrun); + + Display* display(){return m_display.get();} + +private: + DisplayImpl(): + m_display(XOpenDisplay(NULL)) + { + if (!m_display) + throw std::runtime_error("Could not open display"); + + std::cout << "DisplayImpl "< m_display; + Surface::Impl* m_win{nullptr}; + friend class Surface; +}; + +void Application::DisplayImpl::start_event(bool &isrun) +{ + auto dpy = m_display.get(); + pollfd m_fds[2]; + + m_fds[0].fd = ConnectionNumber(dpy); + m_fds[0].events = POLLIN; + m_fds[1].fd = -1; //To do add system interrupts + m_fds[1].events = POLLIN; + + XFlush(dpy); + + while (isrun){ + + int ret; + do { + ret = poll(m_fds, 1, -1); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + if (m_fds[0].revents & POLLHUP) + throw std::runtime_error("disconnected by display connection"); + + throw std::runtime_error("failed to poll():"); + } + + m_win->event_process(); + } +} + +void Application::run() +{ + if (isRuning) return; + isRuning = true; + + DisplayImpl::inst().start_event(isRuning); +} + +Surface::~Surface() = default; + +Surface::Surface(int width, int height): + impl(std::make_unique(Application::DisplayImpl::inst().display(), this, width, height)) +{ + Application::DisplayImpl::inst().m_win = impl.get(); +} + +void Surface::setTitle(const char* txt) +{ + XStoreName(impl->m_context.x11_display, impl->m_buffer.win_id, txt); +} + From 6a214c6fbe5eaada247e910c5e601029d1d4962c Mon Sep 17 00:00:00 2001 From: Silo Date: Tue, 22 Apr 2025 16:36:52 +0300 Subject: [PATCH 08/13] Update harfbuzz.cpp --- lib/impl/skia/detail/harfbuzz.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/impl/skia/detail/harfbuzz.cpp b/lib/impl/skia/detail/harfbuzz.cpp index e0b6afd..8f2ce70 100644 --- a/lib/impl/skia/detail/harfbuzz.cpp +++ b/lib/impl/skia/detail/harfbuzz.cpp @@ -11,10 +11,10 @@ #if defined(_MSC_VER) extern "C" { - float roundf(float x) - { - return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); - } + // float roundf(float x) + // { + // return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); + // } } #endif From d56ed8bc4dfce2a1b8b1f96c78a7469f6ff0db2a Mon Sep 17 00:00:00 2001 From: Silo Date: Thu, 24 Apr 2025 06:40:10 +0300 Subject: [PATCH 09/13] Update CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11bf181..9e19867 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ message(STATUS "Compiler: ${CMAKE_C_COMPILER_ID}") add_subdirectory(lib) -option(ARTIST_BUILD_EXAMPLES "build Artist library examples" OFF) +option(ARTIST_BUILD_EXAMPLES "build Artist library examples" ON) option(ARTIST_BUILD_TESTS "build Artist library tests" ON) if (ARTIST_BUILD_EXAMPLES) From 819ebf94e48cb807e0378d55bc5f61bb20a28c2c Mon Sep 17 00:00:00 2001 From: Silo Date: Thu, 24 Apr 2025 06:42:36 +0300 Subject: [PATCH 10/13] Update harfbuzz.cpp --- lib/impl/skia/detail/harfbuzz.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/impl/skia/detail/harfbuzz.cpp b/lib/impl/skia/detail/harfbuzz.cpp index 8f2ce70..d1fcaaa 100644 --- a/lib/impl/skia/detail/harfbuzz.cpp +++ b/lib/impl/skia/detail/harfbuzz.cpp @@ -8,13 +8,13 @@ #include #include -#if defined(_MSC_VER) +#if defined(_MSC_VER) && _MSC_VER < 1800 extern "C" { - // float roundf(float x) - // { - // return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); - // } + float roundf(float x) + { + return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); + } } #endif From 669cf4c970771be9d5b6657abdc360ec3b0e0fef Mon Sep 17 00:00:00 2001 From: Silo Date: Fri, 25 Apr 2025 08:59:00 +0000 Subject: [PATCH 11/13] adds syslog and fixes wayland code --- examples/host/linux/logger.h | 43 +++++ examples/host/linux/skia_context.cpp | 20 ++- examples/host/linux/wayland/application.cpp | 103 ++++++----- examples/host/linux/wayland/contextegl.cpp | 178 ++++++++++++-------- examples/host/linux/wayland/contextegl.h | 61 ++----- examples/host/linux/wayland/core.cpp | 146 ++++++++-------- examples/host/linux/wayland/core.h | 64 +++---- examples/host/linux/wayland/display.h | 7 +- examples/host/linux/wayland/xdgshell.cpp | 27 +-- examples/host/linux/wayland/xdgshell.h | 32 +--- examples/host/linux/x11/application.cpp | 35 ++-- 11 files changed, 368 insertions(+), 348 deletions(-) create mode 100644 examples/host/linux/logger.h diff --git a/examples/host/linux/logger.h b/examples/host/linux/logger.h new file mode 100644 index 0000000..b42d50f --- /dev/null +++ b/examples/host/linux/logger.h @@ -0,0 +1,43 @@ +#ifndef LOG_H +#define LOG_H + +#include + +class Logger final +{ +public: + explicit Logger(const char* app_id) + { + openlog(app_id, LOG_PERROR | LOG_PID, LOG_USER); + } + + ~Logger() + { + closelog(); + } + + template + static void message(const char *msg, Arg&& ...args) noexcept + { + syslog(LOG_INFO, msg, args...); + } + + template + static void error(const char *msg, Arg&& ...args) noexcept + { + syslog(LOG_ERR, msg, args...); + } + + template + static void debug(const char *msg, Arg&& ...args) noexcept + { +#ifndef NDEBUG + syslog(LOG_DEBUG, msg, args...); +#endif + } + +private: + Logger() = default; +}; + +#endif // LOG_H diff --git a/examples/host/linux/skia_context.cpp b/examples/host/linux/skia_context.cpp index a9882d5..d1e4201 100644 --- a/examples/host/linux/skia_context.cpp +++ b/examples/host/linux/skia_context.cpp @@ -2,7 +2,6 @@ #include "SkColorSpace.h" #include -#include void GlSkiaContext::init(GrGLGetProc gl_get_proc) { @@ -32,12 +31,17 @@ sk_sp GlSkiaContext::makeSurface(int width, int height) noexcept 8, // stencil bits framebufferInfo); - return target->isValid() ? SkSurface::MakeFromBackendRenderTarget(_ctx.get(), - *target.get(), - kBottomLeft_GrSurfaceOrigin, - colorType, - nullptr, - nullptr) - : nullptr; + auto result = target->isValid() ? SkSurface::MakeFromBackendRenderTarget(_ctx.get(), + *target.get(), + kBottomLeft_GrSurfaceOrigin, + colorType, + nullptr, + nullptr) + : nullptr; + + if (!result) + throw std::runtime_error("failed to make Skia surface"); + + return std::move(result); } diff --git a/examples/host/linux/wayland/application.cpp b/examples/host/linux/wayland/application.cpp index ff96d6f..c66ed9d 100644 --- a/examples/host/linux/wayland/application.cpp +++ b/examples/host/linux/wayland/application.cpp @@ -1,4 +1,5 @@ #include "../application.h" +#include "../log.h" #include "contextegl.h" #include "xdgshell.h" @@ -8,37 +9,21 @@ struct Surface::Impl: public WL::Toplevel { Impl(const WL::Display &display, ::Surface* holder, int width, int height): WL::Toplevel(display, width, height), - m_display(display), + m_context(display.c_ptr()), m_holder(holder), - m_need_redraw(false) + m_need_redraw(false), + m_is_corrupt(false) {} - ~Impl() - { - m_buffer.destroy(m_context.m_egl_display); - - std::cout << "DestroyWindow " <skia_surf = m_context.makeSurface(m_width, m_height); - if (m_holder->skia_surf) { - m_buffer = cfg.move_buffer(); - m_holder->configure(m_width, m_height, SurfaceState::resizing); - m_need_redraw = true; - } + Logger::debug("buffer_scale %f", scale); } void draw(float scale) override @@ -52,21 +37,43 @@ struct Surface::Impl: public WL::Toplevel void configure(unsigned w, unsigned h, unsigned s) override { unsigned state = 0; - if (s & WL::resizing) - state |= SurfaceState::resizing; - if (s & WL::maximized) - state |= SurfaceState::maximized; - if (s & WL::activated) - state |= SurfaceState::activated; - if (s & WL::fullscreen) - state |= SurfaceState::fullscreen; - - if (s & WL::resizing){ - m_buffer.resize(w, h); - } - m_holder->configure(w, h, state); - m_need_redraw = true; + try { + if (m_buffer.empty()) + { + m_width *= m_scale; + m_height *= m_scale; + + m_buffer.init(*this, m_width, m_height); + m_context.makeCurrent(m_buffer); + + m_holder->skia_surf = m_context.makeSurface(m_width, m_height); + m_holder->configure(w, h, SurfaceState::resizing); + draw(m_scale); + return; + } + else { + if (s & WL::resizing) + state |= SurfaceState::resizing; + if (s & WL::maximized) + state |= SurfaceState::maximized; + if (s & WL::activated) + state |= SurfaceState::activated; + if (s & WL::fullscreen) + state |= SurfaceState::fullscreen; + + if (s & WL::resizing) + m_buffer.resize(w, h); + } + + m_holder->configure(w, h, state); + m_need_redraw = true; + + } catch(const std::runtime_error& e){ + Logger::error("Error configure, the window must be closed : %s", e.what()); + m_need_redraw = false; + m_is_corrupt = true; + } } void closed() override @@ -74,13 +81,13 @@ struct Surface::Impl: public WL::Toplevel m_holder->closed(); } - const WL::Display &m_display; - WL::ContextEGL m_context; WL::ContextEGL::Buffer m_buffer; - + WL::ContextEGL m_context; + ::Surface* m_holder; bool m_need_redraw; + bool m_is_corrupt; }; class Application::DisplayImpl @@ -98,20 +105,25 @@ class Application::DisplayImpl const WL::Display& display(){return m_display;} private: - DisplayImpl(WL::Display &&dpy): m_display(std::move(dpy)){} + DisplayImpl(WL::Display &&dpy): + syslogger("artist_lib_wayland"), + m_display(std::move(dpy)){} + Logger syslogger; WL::Display m_display; + Surface::Impl* m_win{nullptr}; friend class Surface; }; void Application::DisplayImpl::start_event(bool &isrun) { - assert (m_win); + assert(m_win); while (isrun) { m_display.event_wait(); - m_win->event_process(); + if (m_win->event_process()) + throw std::runtime_error("Window is corrupt"); } } @@ -123,14 +135,17 @@ void Application::run() DisplayImpl::inst().start_event(isRuning); } -Surface::~Surface() = default; - Surface::Surface(int width, int height): impl{std::make_unique(Application::DisplayImpl::inst().display(), this, width, height)} { Application::DisplayImpl::inst().m_win = impl.get(); } +Surface::~Surface() +{ + Application::DisplayImpl::inst().m_win = nullptr; +} + void Surface::setTitle(const char* txt) { impl->setTitle(txt); diff --git a/examples/host/linux/wayland/contextegl.cpp b/examples/host/linux/wayland/contextegl.cpp index 207473b..c530955 100644 --- a/examples/host/linux/wayland/contextegl.cpp +++ b/examples/host/linux/wayland/contextegl.cpp @@ -2,18 +2,21 @@ #include "core.h" #include -#include + +#include "../log.h" using namespace WL; -ContextEGL::Config::Config(wl_display *dpy, const Surface &wl, uint32_t width, uint32_t height): - m_dpy(eglGetDisplay(dpy)) +ContextEGL::ContextEGL(EGLNativeDisplayType dpy): + m_display(eglGetDisplay(dpy)), + m_context(EGL_NO_CONTEXT), + m_surface(EGL_NO_SURFACE) { EGLint majorVersion; EGLint minorVersion; - if (m_dpy == EGL_NO_DISPLAY || - eglInitialize(m_dpy, &majorVersion, &minorVersion) != EGL_TRUE) { + if (m_display == EGL_NO_DISPLAY || + eglInitialize(m_display, &majorVersion, &minorVersion) != EGL_TRUE) { throw std::runtime_error("Can't connect to egl display"); } @@ -21,7 +24,7 @@ ContextEGL::Config::Config(wl_display *dpy, const Surface &wl, uint32_t width, u if (eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) throw std::runtime_error("Can't bind EGL_OPENGL_ES_API"); - std::cout<<"EGL: "< void * { - return (void *) eglGetProcAddress(p); - }); - - std::cout<<"context GL_VENDOR: "< void * { + return (void *) eglGetProcAddress(p);}); + + Logger::debug("context GL_VENDOR: %s, GL_RENDERER: %s, GL_VERSION: %s", + glGetString(GL_VENDOR), + glGetString(GL_RENDERER), + glGetString(GL_VERSION)); + } + else + if (!eglMakeCurrent(m_display, + m_surface, + m_surface, + m_context)) + throw std::runtime_error("failed to make EGL context current"); + + buf.m_egl_surface = m_surface; + } + else if (m_surface != buf.m_egl_surface){ + + if (!eglMakeCurrent(m_display, + buf.m_egl_surface, + buf.m_egl_surface, + m_context)) + throw std::runtime_error("failed to make EGL context current"); + + m_surface = buf.m_egl_surface; + } + +} + +void ContextEGL::destroy(Buffer &buf) { - if (buf.empty()) - eglMakeCurrent(m_egl_display, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT); - else - eglMakeCurrent(m_egl_display, - buf.m_egl_surface, - buf.m_egl_surface, - m_egl_context); + if (buf.m_egl_surface != EGL_NO_SURFACE){ + if (buf.m_egl_surface == m_surface){ + eglMakeCurrent(m_display, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + m_context); + + m_surface = EGL_NO_SURFACE; + } + + eglDestroySurface(m_display, buf.m_egl_surface); + + buf.m_egl_surface = EGL_NO_SURFACE; + } } void ContextEGL::flush(Buffer &buf) const { - eglSwapBuffers(m_egl_display, buf.m_egl_surface); + eglSwapBuffers(m_display, buf.m_egl_surface); +} + +void WL::ContextEGL::Buffer::init(const Surface &wl, uint32_t width, uint32_t height) +{ + assert(m_egl_window == nullptr);//duble initialized + + m_egl_window = wl_egl_window_create(wl.c_ptr(), width, height); + if(!m_egl_window) + std::runtime_error("Can't create egl window"); +} + +void WL::ContextEGL::Buffer::resize(uint32_t width, uint32_t height) +{ + assert(m_egl_window);// window not initialized + + wl_egl_window_resize(m_egl_window, width, height, 0, 0); } const char* getEGLErrorString() diff --git a/examples/host/linux/wayland/contextegl.h b/examples/host/linux/wayland/contextegl.h index bd486fb..0ecb11e 100644 --- a/examples/host/linux/wayland/contextegl.h +++ b/examples/host/linux/wayland/contextegl.h @@ -13,70 +13,41 @@ class Surface; class ContextEGL: public GlSkiaContext { public: + explicit ContextEGL(EGLNativeDisplayType dpy); + class Buffer { public: - void resize(uint32_t width, uint32_t height) - {wl_egl_window_resize(m_egl_window, width, height, 0, 0);} + ~Buffer() + {if (!empty()) wl_egl_window_destroy(m_egl_window);} - bool empty() const {return m_egl_surface == nullptr;} + void init(const Surface &wl, uint32_t width, uint32_t height); + void resize(uint32_t width, uint32_t height); - void destroy(EGLDisplay dpy) - { - if (m_egl_surface){ - eglDestroySurface(dpy, m_egl_surface); - wl_egl_window_destroy(m_egl_window); - m_egl_surface = nullptr; - } - } + bool empty() const {return m_egl_window == nullptr;} private: wl_egl_window *m_egl_window{nullptr}; - EGLSurface m_egl_surface{nullptr}; - - friend class ContextEGL; - }; - - class Config final - { - public: - explicit Config(wl_display *dpy, - const Surface &wl, - uint32_t width, uint32_t height); - - ~Config() - {m_buffer.destroy(m_dpy);} - - Buffer move_buffer() - { - auto result = m_buffer; - m_buffer = Buffer(); - return result; - } - - private: - EGLDisplay m_dpy; - EGLConfig m_egl_config; - Buffer m_buffer; + EGLSurface m_egl_surface{EGL_NO_SURFACE}; friend class ContextEGL; }; - void init(const Config &cfg); - - void makeCurrent(const Buffer &buf); + void makeCurrent(Buffer &buf); void flush(Buffer &buf) const; + void destroy(Buffer &buf); ~ContextEGL(); - operator bool() const { return m_egl_display != nullptr; } + operator bool() const { return m_display != nullptr; } //bool opaque() const; - EGLDisplay m_egl_display{nullptr}; + private: - - EGLContext m_egl_context{nullptr}; - + EGLDisplay m_display; + EGLContext m_context; + EGLSurface m_surface; + EGLConfig m_config; }; } diff --git a/examples/host/linux/wayland/core.cpp b/examples/host/linux/wayland/core.cpp index 28bd6f5..d9ff196 100644 --- a/examples/host/linux/wayland/core.cpp +++ b/examples/host/linux/wayland/core.cpp @@ -3,47 +3,46 @@ #include #include #include -//#include #include #include -#include +#include "../log.h" namespace WL { ////////---- Surface Impl ----/////////////////////////////////////// -NativeSurface::NativeSurface(wl_compositor *compositor, - const FractionalScaleManager *manager): - Base(wl_compositor_create_surface(compositor), "Can't create surface"), - m_fscale(manager ? wp_fractional_scale_manager_v1_get_fractional_scale(manager->c_ptr(), c_ptr()) - : nullptr) +Surface::Surface(wl_compositor *compositor, + const FractionalScaleManager *manager): +Base(wl_compositor_create_surface(compositor), "Can't create surface"), +m_scale(1), +m_fscale(manager ? wp_fractional_scale_manager_v1_get_fractional_scale(manager->c_ptr(), c_ptr()) + : nullptr), +m_input_hundler(nullptr) { static const wl_surface_listener lsr { .enter = [](void *data, - struct wl_surface *wl_surface, - struct wl_output *output){ + struct wl_surface *wl_surface, + struct wl_output *output){ }, .leave = [](void *data, - struct wl_surface *wl_surface, - struct wl_output *output){ - + struct wl_surface *wl_surface, + struct wl_output *output){ }, .preferred_buffer_scale = [](void *data, - struct wl_surface *wl_surface, - int32_t factor){ + struct wl_surface *wl_surface, + int32_t factor){ auto surface = static_cast(data); - if (!surface->m_fscale) - surface->buffer_scale(factor); + surface->buffer_scale(factor); }, .preferred_buffer_transform = [](void *data, - struct wl_surface *wl_surface, - uint32_t transform){ + struct wl_surface *wl_surface, + uint32_t transform){ } }; @@ -53,11 +52,11 @@ NativeSurface::NativeSurface(wl_compositor *compositor, if (m_fscale) { static const wp_fractional_scale_v1_listener lsr{ .preferred_scale = [](void *data, wp_fractional_scale_v1 *, uint32_t scale) { - auto self = static_cast(data); + auto surface = static_cast(data); auto val = (float)scale / 120; - self->m_scale = val; - if (self->onScale) self->onScale(val); + surface->m_scale = val; + surface->buffer_scale(val); } }; @@ -65,7 +64,7 @@ NativeSurface::NativeSurface(wl_compositor *compositor, } } -void NativeSurface::setAreaOpaque(wl_compositor *compositor, int32_t w, int32_t h) const +void Surface::setAreaOpaque(wl_compositor *compositor, int32_t w, int32_t h) const { auto region = wl_compositor_create_region(compositor); if (!region) @@ -104,13 +103,13 @@ struct Keyboard::KeyMapper bool Keyboard::KeyMapper::map(int32_t fd, uint32_t size) noexcept { if(!kcontext){ - std::cerr<<"Error: create xkb context"<onKey); - m_focused_surf->onKey(m_keyboard); + m_focused_surf->key(m_keyboard); } const wl_keyboard_listener Seat::keyboard_listener = { @@ -211,14 +209,15 @@ const wl_keyboard_listener Seat::keyboard_listener = { //To Do WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP if(kb.m_mapper){ - if (!kb.m_mapper->map(fd, size)) { + if(!kb.m_mapper->map(fd, size)){ delete kb.m_mapper; kb.m_mapper = nullptr; - //To Do log file + + Logger::error("KEYMAP_FORMAT failed"); } } else - std::cerr<<"KEYMAP_FORMAT not supported, format code: "<(data); + auto surf = static_cast( + wl_surface_get_user_data(surface)); - seat->m_focused_surf = static_cast( - wl_surface_get_user_data(surface)); + if (surf){ + seat->m_focused_surf = surf->m_input_hundler; - if (seat->m_focused_surf && seat->m_focused_surf->onFocused) - seat->m_focused_surf->onFocused(true); + if (seat->m_focused_surf) + seat->m_focused_surf->keyFocused(true); + } }, .leave = [](void *data, wl_keyboard *wl_kd, uint32_t, wl_surface*){ auto seat = static_cast(data); - if (seat->m_focused_surf && seat->m_focused_surf->onFocused){ - seat->m_focused_surf->onFocused(false); + if (seat->m_focused_surf){ + seat->m_focused_surf->keyFocused(false); seat->m_focused_surf = nullptr; struct itimerspec timer = {0}; @@ -255,9 +257,7 @@ const wl_keyboard_listener Seat::keyboard_listener = { auto seat = static_cast(data); auto mapper = seat->m_keyboard.m_mapper; - if (seat->m_focused_surf && - mapper && - seat->m_focused_surf->onKey){ + if (seat->m_focused_surf && mapper){ bool pressed = (state == WL_KEYBOARD_KEY_STATE_PRESSED); @@ -282,7 +282,7 @@ const wl_keyboard_listener Seat::keyboard_listener = { } } - //std::cout<<"repeat_info "<key_repeat_fd, 0, &timer, NULL); @@ -303,21 +303,28 @@ const wl_keyboard_listener Seat::keyboard_listener = { mods_depressed, mods_latched, mods_locked, 0, 0, group); - //std::cout<<"modifiers "<(data); - //std::cout<<"repeat_info "<delay = delay * 1000000; - seat->rate = 1000000000 / rate; + //The protocol guarantees non-zero values, but it doesn't hurt to check. + //Just in case, in Russian + if (rate != 0 && delay != 0){ + + /** + * rate - generation speed (number of characters in sec) + * delay - number of ms during which you need to hold the key before the repeat starts + */ + seat->delay = delay * 1000000; + seat->rate = 1000000000 / rate; + } + else + Logger::error("Incorrect keyboard parameters rate = %i, delay = %i", + rate, delay); } } }; @@ -331,16 +338,16 @@ const wl_pointer_listener Seat::pointer_listener = { if (!surface) return; auto seat = static_cast(data); - auto surf = static_cast( + auto surf = static_cast( wl_surface_get_user_data(surface)); assert(seat && seat->m_pointer.c_ptr() == pointer); if (surf){ - seat->m_hovered_surf = surf; + seat->m_hovered_surf = surf->m_input_hundler; - if (surf->onPoint) - surf->onPoint(SeatListener::enter, 0, seat->m_pointer.set(sx, sy)); + if (seat->m_hovered_surf) + seat->m_hovered_surf->point(SeatListener::enter, 0, seat->m_pointer.set(sx, sy)); } }, .leave = [](void *data, wl_pointer *pointer, @@ -352,9 +359,7 @@ const wl_pointer_listener Seat::pointer_listener = { if (seat->m_hovered_surf) { - if (seat->m_hovered_surf->onPoint) - seat->m_hovered_surf->onPoint(SeatListener::leave, 0, seat->m_pointer); - + seat->m_hovered_surf->point(SeatListener::leave, 0, seat->m_pointer); seat->m_hovered_surf = nullptr; } }, @@ -365,8 +370,8 @@ const wl_pointer_listener Seat::pointer_listener = { assert(seat && seat->m_pointer.c_ptr() == pointer); - if (seat->m_hovered_surf && seat->m_hovered_surf->onPoint) - seat->m_hovered_surf->onPoint(SeatListener::motion, time, seat->m_pointer.set(sx, sy)); + if (seat->m_hovered_surf) + seat->m_hovered_surf->point(SeatListener::motion, time, seat->m_pointer.set(sx, sy)); }, .button = [](void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, @@ -376,7 +381,7 @@ const wl_pointer_listener Seat::pointer_listener = { assert(seat && seat->m_pointer.c_ptr() == pointer); - if (seat->m_hovered_surf && seat->m_hovered_surf->onClick) { + if (seat->m_hovered_surf) { /* count click */ timespec now; @@ -393,7 +398,7 @@ const wl_pointer_listener Seat::pointer_listener = { auto& key = seat->m_keyboard; - seat->m_hovered_surf->onClick((Pointer::BTN)button, true, + seat->m_hovered_surf->click((Pointer::BTN)button, true, seat->m_count_click, key ? key.modifiers(Keyboard::ModSet::effective) : 0, seat->m_pointer ); @@ -402,7 +407,7 @@ const wl_pointer_listener Seat::pointer_listener = { seat->m_last_released_button = button; seat->m_last_time = time; seat->m_stamp = now.tv_sec; - seat->m_hovered_surf->onClick((Pointer::BTN)button, false, 0, 0, seat->m_pointer); + seat->m_hovered_surf->click((Pointer::BTN)button, false, 0, 0, seat->m_pointer); } } }, @@ -413,8 +418,8 @@ const wl_pointer_listener Seat::pointer_listener = { assert(seat && seat->m_pointer.c_ptr() == pointer); - if (seat->m_hovered_surf && seat->m_hovered_surf->onScroll) - seat->m_hovered_surf->onScroll(time, axis, wl_fixed_to_double(value)); + if (seat->m_hovered_surf) + seat->m_hovered_surf->scroll(time, axis, wl_fixed_to_double(value)); } }; @@ -432,13 +437,12 @@ void Seat::bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept .capabilities = [](void *data, wl_seat *wl_seat, uint32_t flags){ auto seat = static_cast(data); - //std::cout<<"capabilities "<m_pointer.reset(pointer); if (wl_pointer_add_listener(pointer, &pointer_listener, seat) < 0) - std::cerr<<"Error: не удалось добавить pointer listener"<m_pointer.reset(nullptr); @@ -447,20 +451,18 @@ void Seat::bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept auto kb = wl_seat_get_keyboard(wl_seat); seat->m_keyboard.reset(kb); if (wl_keyboard_add_listener(kb, &keyboard_listener, seat) < 0) - std::cerr<<"Error: не удалось добавить keyboard listener"<m_keyboard.reset(nullptr); - - //self->touch.init(app, wl_seat, capabilities); }, .name = [](void*, wl_seat*, const char *name){ - std::cout<<"Seat name: "< -//#include - -#include #include #include +#include + #include #include "fractional-scale-v1-client-protocol.h" @@ -174,36 +173,18 @@ class Pointer: public Proxy class SeatListener { public: - std::function onFocused; - std::function onKey; - - //virtual void keyUnfocused() = 0; - //virtual void key(Keyboard const&) = 0; + virtual void keyFocused(bool) = 0; + virtual void key(Keyboard const&) = 0; enum PointerState { enter, leave, motion }; - - std::function onPoint; - std::function onClick; - std::function onScroll; - - // virtual void enter(uint32_t /*serial*/, Pointer const&) = 0; - // virtual void leave() = 0; - // virtual void motion(uint32_t /*time*/, Pointer const&) = 0; - // virtual void click(Pointer::BTN /*button*/ , - // bool /*pressed*/, - // int /*count*/, - // unsigned /*key_mod*/, - // Pointer const&) = 0; - // virtual void scroll(int time, int axis, double value) = 0; - -// protected: -// virtual void keyFocused(bool) = 0; + virtual void point(PointerState, uint32_t /*serial*/, Pointer const&) = 0; + + virtual void click(Pointer::BTN /*button*/ , + bool /*pressed*/, + int /*count*/, + unsigned /*key_mod*/, + Pointer const&) = 0; + virtual void scroll(int time, int axis, double value) = 0; }; class Seat final: public Protocol @@ -213,9 +194,6 @@ class Seat final: public Protocol void bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept override; private: - // Поддерживает только XKB на Linux и FreeBSD платформах - // возможно в дальнейшем этот класс нужно будет сделать более гибким - Keyboard m_keyboard; SeatListener *m_focused_surf = nullptr; static const wl_keyboard_listener keyboard_listener; @@ -229,7 +207,8 @@ class Seat final: public Protocol Pointer m_pointer; SeatListener *m_hovered_surf = nullptr; static const wl_pointer_listener pointer_listener; - //для вычисления нескольких нажатий одной и той же кнопки мыши + + //double click handling uint32_t m_last_time = 0; std::time_t m_stamp; uint32_t m_last_released_button = 0; @@ -240,12 +219,14 @@ using FractionalScaleManager = Protocol; -class Surface: public Proxy, - public SeatListener +class Surface: public Proxy { public: - explicit Surface(wl_compositor *compositor, - const FractionalScaleManager *manager); + Surface(wl_compositor *compositor, + const FractionalScaleManager *manager); + + inline void listenerInput(SeatListener &input) + { m_input_hundler = &input;} inline void commit() { wl_surface_commit(c_ptr()); } @@ -253,7 +234,7 @@ class Surface: public Proxy, protected: void setAreaOpaque(wl_compositor *compositor, int32_t w, int32_t h) const; - float m_scale{1}; + float m_scale; virtual void draw(float /*scale*/) = 0; virtual void buffer_scale(float /*scale*/) = 0; @@ -261,6 +242,9 @@ class Surface: public Proxy, private: Proxy m_fscale; + + SeatListener *m_input_hundler; + friend class Seat; }; using Viewporter = Protocol - #include #include -// #include - -#include +#include #include #include + #include #include "core.h" diff --git a/examples/host/linux/wayland/xdgshell.cpp b/examples/host/linux/wayland/xdgshell.cpp index f609bf3..c6ffba7 100644 --- a/examples/host/linux/wayland/xdgshell.cpp +++ b/examples/host/linux/wayland/xdgshell.cpp @@ -1,7 +1,5 @@ #include "xdgshell.h" -#include - using namespace WL; void XDGWmBase::bind(wl_registry *reg, uint32_t name, uint32_t version) noexcept @@ -44,8 +42,6 @@ Toplevel::Toplevel(const Display &dpy, uint32_t width, uint32_t height) (const char *) pos < ((const char *) states->data + states->size); (pos)++){ - //std::cout<<"--- "<<*pos<m_state |= (1 << *pos); } @@ -53,8 +49,6 @@ Toplevel::Toplevel(const Display &dpy, uint32_t width, uint32_t height) inst->m_width = width; inst->m_height = height; } - - //std::cout<<"states "<m_state<<" W "<(data); @@ -62,16 +56,10 @@ Toplevel::Toplevel(const Display &dpy, uint32_t width, uint32_t height) }, .configure_bounds = [](void* data, xdg_toplevel*, int32_t width, int32_t height){ - std::cout<<"configure_bound: "<< width<<" "<< height<(data); - - // inst->mapped(); + xdg_toplevel *xdg_toplevel, + wl_array *capabilities){ } }; @@ -80,11 +68,10 @@ Toplevel::Toplevel(const Display &dpy, uint32_t width, uint32_t height) static const xdg_surface_listener surface_lsr{ .configure = [](void* data, xdg_surface *xdg_surf, uint32_t serial){ - auto inst = static_cast(data); - xdg_surface_ack_configure(xdg_surf, serial); -std::cout<<"xdg_surface_listener states "<m_state<<" W "<m_width<<" H "<m_height<m_state != 0) - inst->configure(inst->m_width, inst->m_height, inst->m_state); + auto inst = static_cast(data); + xdg_surface_ack_configure(xdg_surf, serial); + + inst->configure(inst->m_width, inst->m_height, inst->m_state); } }; @@ -93,5 +80,5 @@ std::cout<<"xdg_surface_listener states "<m_state<<" W "<m_width<< if (m_decor) zxdg_toplevel_decoration_v1_set_mode(m_decor.c_ptr(), - ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } diff --git a/examples/host/linux/wayland/xdgshell.h b/examples/host/linux/wayland/xdgshell.h index fec4aae..0116d88 100644 --- a/examples/host/linux/wayland/xdgshell.h +++ b/examples/host/linux/wayland/xdgshell.h @@ -54,40 +54,12 @@ class Toplevel: public Surface virtual void closed() = 0; /** - * @brief configure вызывается композитором при изменении состояния (s) - * или размеров окна (w, h) - * @param w - * @param h - * @param s - * @return должна возвращать true если требуется перерисовка + * configure called by the composer when the state (s) + * and/or window dimensions (w, h) change */ virtual void configure(unsigned w, unsigned h, unsigned s) = 0; }; -// struct Positioner: Proxy -// { -// //const WlApplication &global; - -// // explicit Positioner(const XDGWmBase &shell): -// // Proxy( -// // xdg_wm_base_create_positioner(shell.c_ptr()), -// // "Can't create positioner")//, -// // //global(app) -// // {} -// }; - -// class Popup: public Proxy -// { -// public: -// Popup(const Positioner &pos, -// const XDGSurface &parent); - -// //std::function onClosed; - -// int32_t x, y; -// int32_t width, height; -// }; - } #endif // XDGSHELL_H diff --git a/examples/host/linux/x11/application.cpp b/examples/host/linux/x11/application.cpp index 3fa694b..9415614 100644 --- a/examples/host/linux/x11/application.cpp +++ b/examples/host/linux/x11/application.cpp @@ -1,5 +1,6 @@ #include "../application.h" #include "../skia_context.h" +#include "../log.h" #include #include @@ -73,7 +74,8 @@ namespace X11 { GLint majorGLX, minorGLX = 0; glXQueryVersion(dpy, &majorGLX, &minorGLX); - std::cout<<"GLX: "<closed();//std::cout << "XPending " << xevent.type << std::endl; + m_holder->closed(); }else if ( xevent.type == MapNotify ) { std::cout << "MapNotify " < m_display; Surface::Impl* m_win{nullptr}; friend class Surface; From 30f0b2d24d10c238cd07bfe297c27994c3cf5942 Mon Sep 17 00:00:00 2001 From: Silo Date: Fri, 25 Apr 2025 09:30:05 +0000 Subject: [PATCH 12/13] fix file name logger.h --- examples/host/linux/skia_app.cpp | 4 ++-- examples/host/linux/wayland/application.cpp | 2 +- examples/host/linux/wayland/contextegl.cpp | 2 +- examples/host/linux/wayland/core.cpp | 2 +- examples/host/linux/x11/application.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/host/linux/skia_app.cpp b/examples/host/linux/skia_app.cpp index 0b4b633..24d239c 100644 --- a/examples/host/linux/skia_app.cpp +++ b/examples/host/linux/skia_app.cpp @@ -9,8 +9,8 @@ #include "SkCanvas.h" #include -#include +#include "logger.h" #include "application.h" using namespace cycfi::artist; @@ -103,7 +103,7 @@ int run_app( app.run(); } catch (const char* err) { - std::cerr<<"Error: "< -#include "../log.h" +#include "../logger.h" using namespace WL; diff --git a/examples/host/linux/wayland/core.cpp b/examples/host/linux/wayland/core.cpp index d9ff196..ab3be2d 100644 --- a/examples/host/linux/wayland/core.cpp +++ b/examples/host/linux/wayland/core.cpp @@ -6,7 +6,7 @@ #include #include -#include "../log.h" +#include "../logger.h" namespace WL { diff --git a/examples/host/linux/x11/application.cpp b/examples/host/linux/x11/application.cpp index 9415614..4db1ebc 100644 --- a/examples/host/linux/x11/application.cpp +++ b/examples/host/linux/x11/application.cpp @@ -1,6 +1,6 @@ #include "../application.h" #include "../skia_context.h" -#include "../log.h" +#include "../logger.h" #include #include From f843214f52b1115598ccb6e675180dac900e33ec Mon Sep 17 00:00:00 2001 From: Silo Date: Fri, 25 Apr 2025 12:43:29 +0300 Subject: [PATCH 13/13] Update skia_app.cpp --- examples/host/linux/skia_app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/host/linux/skia_app.cpp b/examples/host/linux/skia_app.cpp index 24d239c..5cbf224 100644 --- a/examples/host/linux/skia_app.cpp +++ b/examples/host/linux/skia_app.cpp @@ -102,7 +102,7 @@ int run_app( app.run(); - } catch (const char* err) { + } catch (const std::runtime_error& e) { Logger::error("Error application : %s", e.what()); exit(1); }