Wayland pointer lock fixes

This commit is contained in:
IoIxD 2026-03-27 17:15:59 -07:00
commit 252490e2cf
5 changed files with 284 additions and 223 deletions

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project( project(
milsko milsko
) )
include(CheckIncludeFiles) include(CheckIncludeFiles)
@ -20,123 +20,123 @@ option(MW_BUILD_STATIC "Build a static library" OFF)
option(MW_INSTALL_HEADERS "Install headers" ON) option(MW_INSTALL_HEADERS "Install headers" ON)
if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin) if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
option(MW_USE_FREETYPE2 "Use FreeType 2" OFF) option(MW_USE_FREETYPE2 "Use FreeType 2" OFF)
else() else()
option(MW_USE_FREETYPE2 "Use FreeType 2" ON) option(MW_USE_FREETYPE2 "Use FreeType 2" ON)
endif() endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux) if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
option(MW_USE_WAYLAND "Enable Wayland backend" ON) option(MW_USE_WAYLAND "Enable Wayland backend" ON)
endif() endif()
file( file(
GLOB GLOB
SOURCES SOURCES
src/*.c src/cursor/*.c src/icon/*.c src/widget/*.c src/text/*.c src/text/font/*.c src/dialog/*.c src/abstract/*.c external/*.c src/*.c src/cursor/*.c src/icon/*.c src/widget/*.c src/text/*.c src/text/font/*.c src/dialog/*.c src/abstract/*.c external/*.c
) )
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c")
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c")
if(NOT MW_USE_STB_IMAGE) if(NOT MW_USE_STB_IMAGE)
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_image.c") list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_image.c")
endif() endif()
if(NOT MW_USE_STB_TRUETYPE) if(NOT MW_USE_STB_TRUETYPE)
list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_truetype.c") list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_truetype.c")
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/X11R7/include") list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/X11R7/include")
list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/pkg/include") list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/pkg/include")
endif() endif()
if(MW_TRY_OPENGL) if(MW_TRY_OPENGL)
find_package(OpenGL) find_package(OpenGL)
if(OpenGL_FOUND) if(OpenGL_FOUND)
set(MW_BUILD_OPENGL ON) set(MW_BUILD_OPENGL ON)
list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c")
if(APPLE) if(APPLE)
list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m") list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m")
endif() endif()
message(STATUS "OpenGL widget has been enabled") message(STATUS "OpenGL widget has been enabled")
else() else()
message(WARNING "OpenGL widget has been disabled") message(WARNING "OpenGL widget has been disabled")
endif() endif()
endif() endif()
if(MW_TRY_VULKAN) if(MW_TRY_VULKAN)
check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H) check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H)
if(HAVE_VULKAN_VULKAN_H) if(HAVE_VULKAN_VULKAN_H)
set(MW_BUILD_VULKAN ON) set(MW_BUILD_VULKAN ON)
list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c")
message(STATUS "Vulkan widget has been enabled") message(STATUS "Vulkan widget has been enabled")
else() else()
message(WARNING "Vulkan widget has been disabled") message(WARNING "Vulkan widget has been disabled")
endif() endif()
endif() endif()
if(MW_BUILD_STATIC) if(MW_BUILD_STATIC)
message(STATUS "Building Milsko as a static library") message(STATUS "Building Milsko as a static library")
add_library( add_library(
Mw Mw
${SOURCES} ${SOURCES}
) )
elseif(MW_BUILD_SHARED) elseif(MW_BUILD_SHARED)
message(STATUS "Building Milsko as a shared library") message(STATUS "Building Milsko as a shared library")
add_library( add_library(
Mw Mw
SHARED SHARED
${SOURCES} ${SOURCES}
) )
else() else()
message(ERROR "Must either build a shared library or a static library") message(ERROR "Must either build a shared library or a static library")
endif() endif()
if(MW_USE_STB_IMAGE) if(MW_USE_STB_IMAGE)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_STB_IMAGE USE_STB_IMAGE
) )
else() else()
file( file(
GLOB GLOB
IMAGE_SOURCES IMAGE_SOURCES
external/libz/src/*.c external/libjpeg/src/*.c external/libpng/src/*.c external/libz/src/*.c external/libjpeg/src/*.c external/libpng/src/*.c
) )
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
${MW_IMAGE_SOURCES} ${MW_IMAGE_SOURCES}
) )
target_include_directories( target_include_directories(
Mw Mw
PRIVATE PRIVATE
external/libz/include external/libjpeg/include external/libpng/include external/libz/include external/libjpeg/include external/libpng/include
) )
endif() endif()
if(MW_USE_STB_TRUETYPE) if(MW_USE_STB_TRUETYPE)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_STB_TRUETYPE USE_STB_TRUETYPE
) )
endif() endif()
if(MW_USE_FREETYPE2) if(MW_USE_FREETYPE2)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_FREETYPE2 USE_FREETYPE2
) )
find_package(PkgConfig) find_package(PkgConfig)
pkg_check_modules(FT2 REQUIRED freetype2) pkg_check_modules(FT2 REQUIRED freetype2)
list(APPEND INCLUDE_DIRS ${FT2_INCLUDE_DIRS}) list(APPEND INCLUDE_DIRS ${FT2_INCLUDE_DIRS})
list(APPEND LIBRARY_DIRS ${FT2_LIBRARY_DIRS}) list(APPEND LIBRARY_DIRS ${FT2_LIBRARY_DIRS})
list(APPEND LIBRARIES ${FT2_LIBRARIES}) list(APPEND LIBRARIES ${FT2_LIBRARIES})
endif() endif()
if(MW_USE_WAYLAND) if(MW_USE_WAYLAND)
@ -150,10 +150,10 @@ if(MW_USE_WAYLAND)
COMMAND_ECHO STDOUT COMMAND_ECHO STDOUT
) )
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-core-protocol.c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-core-protocol.c
) )
execute_process( execute_process(
COMMAND wayland-scanner client-header /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/wayland-core-protocol.h COMMAND wayland-scanner client-header /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/wayland-core-protocol.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@ -177,10 +177,10 @@ if(MW_USE_WAYLAND)
COMMAND_ECHO STDOUT COMMAND_ECHO STDOUT
) )
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
${proto_c} ${proto_c}
) )
execute_process( execute_process(
COMMAND wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h COMMAND wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@ -193,11 +193,11 @@ if(MW_USE_WAYLAND)
endfunction() endfunction()
check_include_files(wayland-client.h HAVE_WL_H) check_include_files(wayland-client.h HAVE_WL_H)
check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H) check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H)
check_include_files(cairo/cairo.h HAVE_CAIRO_H) check_include_files(cairo/cairo.h HAVE_CAIRO_H)
if(HAVE_WL_H) if(HAVE_WL_H)
if(HAVE_XKBCOMMON_H) if(HAVE_XKBCOMMON_H)
if(HAVE_CAIRO_H) if(HAVE_CAIRO_H)
scan_wayland_protocol_core() scan_wayland_protocol_core()
scan_wayland_protocol("stable" "xdg-shell" "") scan_wayland_protocol("stable" "xdg-shell" "")
scan_wayland_protocol("stable" "viewporter" "") scan_wayland_protocol("stable" "viewporter" "")
@ -207,156 +207,157 @@ if(MW_USE_WAYLAND)
scan_wayland_protocol("unstable" "xdg-decoration" "-unstable-v1") scan_wayland_protocol("unstable" "xdg-decoration" "-unstable-v1")
scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1")
scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1")
scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1")
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
src/backend/wayland.c src/backend/wayland.c
) )
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_WAYLAND USE_WAYLAND
) )
message(STATUS "Wayland backend has been enabled") message(STATUS "Wayland backend has been enabled")
else() else()
message(WARNING "Wayland backend has been disabled") message(WARNING "Wayland backend has been disabled")
endif() endif()
else() else()
message(WARNING "Wayland backend has been disabled") message(WARNING "Wayland backend has been disabled")
endif() endif()
else() else()
message(WARNING "Wayland backend has been disabled") message(WARNING "Wayland backend has been disabled")
endif() endif()
endif() endif()
if(APPLE AND MW_BUILD_OPENGL) if(APPLE AND MW_BUILD_OPENGL)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
GL_SILENCE_DEPRECATION GL_SILENCE_DEPRECATION
) )
endif() endif()
target_include_directories( target_include_directories(
Mw Mw
PUBLIC PUBLIC
include include
) )
if(MW_CLASSIC_THEME) if(MW_CLASSIC_THEME)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_CLASSIC_THEME USE_CLASSIC_THEME
) )
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows") if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
src/backend/gdi.c src/backend/gdi.c
) )
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_GDI USE_GDI
) )
list(APPEND LIBRARIES gdi32) list(APPEND LIBRARIES gdi32)
target_link_options( target_link_options(
Mw Mw
PRIVATE PRIVATE
-static-libgcc -static-libgcc
) )
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
src/backend/cocoa.m src/backend/cocoa.m
) )
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_COCOA USE_COCOA
) )
list(APPEND LIBRARIES objc) list(APPEND LIBRARIES objc)
target_link_options( target_link_options(
Mw Mw
PRIVATE PRIVATE
-framework Cocoa -framework Cocoa
) )
else() else()
find_package(PkgConfig) find_package(PkgConfig)
pkg_check_modules(X11 REQUIRED x11) pkg_check_modules(X11 REQUIRED x11)
pkg_check_modules(XRENDER REQUIRED xrender) pkg_check_modules(XRENDER REQUIRED xrender)
target_sources( target_sources(
Mw Mw
PRIVATE PRIVATE
src/backend/x11.c src/backend/x11.c
) )
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
USE_X11 USE_X11
) )
list(APPEND INCLUDE_DIRS ${X11_INCLUDE_DIRS} ${XRENDER_INCLUDE_DIRS}) list(APPEND INCLUDE_DIRS ${X11_INCLUDE_DIRS} ${XRENDER_INCLUDE_DIRS})
list(APPEND LIBRARY_DIRS ${X11_LIBRARY_DIRS} ${XRENDER_LIBRARY_DIRS}) list(APPEND LIBRARY_DIRS ${X11_LIBRARY_DIRS} ${XRENDER_LIBRARY_DIRS})
list(APPEND LIBRARIES ${X11_LIBRARIES} ${XRENDER_LIBRARIES} m) list(APPEND LIBRARIES ${X11_LIBRARIES} ${XRENDER_LIBRARIES} m)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND LIBRARIES dl) list(APPEND LIBRARIES dl)
endif() endif()
endif() endif()
target_include_directories( target_include_directories(
Mw Mw
PRIVATE PRIVATE
${INCLUDE_DIRS} ${INCLUDE_DIRS}
) )
target_link_directories( target_link_directories(
Mw Mw
PRIVATE PRIVATE
${LIBRARY_DIRS} ${LIBRARY_DIRS}
) )
target_link_libraries( target_link_libraries(
Mw Mw
PRIVATE PRIVATE
${LIBRARIES} ${LIBRARIES}
) )
if(MW_BUILD_VULKAN) if(MW_BUILD_VULKAN)
check_include_files(vulkan/vk_enum_string_helper.h HAS_VK_ENUM_STRING_HELPER) check_include_files(vulkan/vk_enum_string_helper.h HAS_VK_ENUM_STRING_HELPER)
if(HAS_VK_ENUM_STRING_HELPER) if(HAS_VK_ENUM_STRING_HELPER)
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
HAS_VK_ENUM_STRING_HELPER HAS_VK_ENUM_STRING_HELPER
) )
endif() endif()
endif() endif()
target_compile_definitions( target_compile_definitions(
Mw Mw
PRIVATE PRIVATE
_MILSKO _MILSKO
) )
install( install(
TARGETS Mw TARGETS Mw
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
) )
if(MW_INSTALL_HEADERS) if(MW_INSTALL_HEADERS)
install( install(
DIRECTORY include/ DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h" FILES_MATCHING PATTERN "*.h"
) )
endif() endif()
if(MW_BUILD_EXAMPLES) if(MW_BUILD_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif() endif()

View file

@ -289,6 +289,7 @@ MwInline int wayland_load_funcs() {
#include "Wayland/cursor-shape-client-protocol.h" #include "Wayland/cursor-shape-client-protocol.h"
#include "Wayland/primary-selection-client-protocol.h" #include "Wayland/primary-selection-client-protocol.h"
#include "Wayland/pointer-constraints-client-protocol.h" #include "Wayland/pointer-constraints-client-protocol.h"
#include "Wayland/relative-pointer-client-protocol.h"
#include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h"
#endif #endif
@ -426,10 +427,12 @@ struct _MwLLWayland {
struct wp_viewport* vp; struct wp_viewport* vp;
MwBool do_lock_pointer; MwBool do_lock_pointer;
struct zwp_pointer_constraints_v1* pointer_constraints; struct zwp_pointer_constraints_v1* pointer_constraints;
struct zwp_locked_pointer_v1* locked_pointer; struct zwp_relative_pointer_manager_v1* relative_pointer_manager;
MwBool pointer_constrained; struct zwp_relative_pointer_v1* relative_pointer;
struct zwp_locked_pointer_v1* locked_pointer;
MwBool pointer_constrained;
/* clipboard related stuff. /* clipboard related stuff.
* Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/ * Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/

View file

@ -43,6 +43,7 @@ if (grep(/^wayland$/, @backends)) {
scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1"); scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1");
scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1");
scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1");
scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1");
$gl_libs = "-lGL -lGLU"; $gl_libs = "-lGL -lGLU";
} }

View file

@ -118,15 +118,15 @@ static void recursive_dispatch_resize(MwLL handle) {
} }
}; };
/* Recursively dispatch a draw event to a widget and its children */ /* Recursively dispatch a move event to a widget and its children */
static void recursive_dispatch_draw(MwLL handle) { static void recursive_dispatch_move(MwLL handle, MwLLMouse* p) {
MwWidget h = (MwWidget)handle->common.user; MwWidget h = (MwWidget)handle->common.user;
if(h) { if(h) {
int i; int i;
for(i = 0; i < arrlen(h->children); i++) { for(i = 0; i < arrlen(h->children); i++) {
MwDispatch(h->children[i], draw); MwLLDispatch(h->children[i]->lowlevel, move, p);
if(arrlen(h->children[i]->children) > 0) { if(arrlen(h->children[i]->children) > 0) {
recursive_dispatch_draw(h->children[i]->lowlevel); recursive_dispatch_move(h->children[i]->lowlevel, p);
} }
} }
} }
@ -531,24 +531,59 @@ static void xdg_borderless_step(MwLL self, MwLLMouse p, MwU32 serial) {
static MwLL currentlyHeldWidget = NULL; static MwLL currentlyHeldWidget = NULL;
static void relative_pointer_motion(void* data,
struct zwp_relative_pointer_v1* pointer,
uint32_t timeHi,
uint32_t timeLo,
wl_fixed_t dx,
wl_fixed_t dy,
wl_fixed_t dxUnaccel,
wl_fixed_t dyUnaccel) {
MwLL self = data;
MwLLMouse p;
WAYLAND_EVENT_OP_START(self);
p.point.x = wl_fixed_to_int(dxUnaccel);
p.point.y = wl_fixed_to_int(dyUnaccel);
recursive_dispatch_move(self, &p);
if(self->wayland.locked_pointer) zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0,CSD_BORDER_FRAME_TOP);
WAYLAND_EVENT_OP_END(self);
}
struct zwp_relative_pointer_v1_listener relative_pointer_listener =
{
relative_pointer_motion};
/* zwp_primary_selection_device_manager_v1 setup function */
static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) {
printf("Relative pointer\n");
wayland->relative_pointer_manager = wl_registry_bind(wayland->registry, name, &zwp_relative_pointer_manager_v1_interface, 1);
return NULL;
}
static void zwp_relative_pointer_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
}
/* `wl_pointer.motion` callback */ /* `wl_pointer.motion` callback */
static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time,
wl_fixed_t surface_x, wl_fixed_t surface_y) { wl_fixed_t surface_x, wl_fixed_t surface_y) {
MwLL self = data; MwLL self = data;
MwLL topmost_parent = self;
MwLLMouse p; MwLLMouse p;
(void)time; (void)time;
(void)wl_pointer; (void)wl_pointer;
WAYLAND_EVENT_OP_START(self); if(self->wayland.do_lock_pointer) {
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; return;
}
self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x);
self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y);
if(self->wayland.do_lock_pointer) {
self->wayland.cur_mouse_pos.x -= topmost_parent->wayland.ww / 2.;
self->wayland.cur_mouse_pos.y -= topmost_parent->wayland.wh / 2.;
}
p.point = self->wayland.cur_mouse_pos; p.point = self->wayland.cur_mouse_pos;
MwLLDispatch(self, move, &p); MwLLDispatch(self, move, &p);
@ -556,13 +591,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
MwLLDispatch(currentlyHeldWidget, down, &p); MwLLDispatch(currentlyHeldWidget, down, &p);
} }
if(self->wayland.do_lock_pointer) {
topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
zwp_locked_pointer_v1_set_cursor_position_hint(topmost_parent->wayland.locked_pointer, wl_fixed_from_double(topmost_parent->wayland.ww / 2.), wl_fixed_from_double(topmost_parent->wayland.wh / 2.));
wl_surface_commit(topmost_parent->wayland.backbuffer.surface);
zwp_locked_pointer_v1_destroy(topmost_parent->wayland.locked_pointer);
}
WAYLAND_EVENT_OP_END(self); WAYLAND_EVENT_OP_END(self);
}; };
@ -735,6 +763,10 @@ static void keyboard_key(void* data,
if(self->wayland.framebuffer.surface) { if(self->wayland.framebuffer.surface) {
inArea |= self->wayland.framebuffer.surface == curSurface; inArea |= self->wayland.framebuffer.surface == curSurface;
} }
if(self->wayland.backbuffer.surface) {
inArea |= self->wayland.backbuffer.surface == curSurface;
}
if(inArea) { if(inArea) {
xkb_layout_index_t layout; xkb_layout_index_t layout;
MwU32 levels; MwU32 levels;
@ -1183,7 +1215,7 @@ static void xdg_toplevel_configure(void* data,
recursive_dispatch_resize(self); recursive_dispatch_resize(self);
if(self->wayland.pointer_constrained) { if(self->wayland.pointer_constrained) {
zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, wl_fixed_from_double(self->wayland.ww / 2.), wl_fixed_from_double(self->wayland.wh / 2.)); zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0,CSD_BORDER_FRAME_TOP);
wl_surface_commit(self->wayland.framebuffer.surface); wl_surface_commit(self->wayland.framebuffer.surface);
} }
}; };
@ -1290,10 +1322,10 @@ static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) {
if(!buffer->setup) { if(!buffer->setup) {
return; return;
} }
wl_buffer_destroy(buffer->shm_buffer); if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer);
wl_buffer_destroy(buffer->shm_buffer_back); if(buffer->shm_buffer_back) wl_buffer_destroy(buffer->shm_buffer_back);
wl_shm_pool_destroy(buffer->shm_pool); if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool);
wl_shm_pool_destroy(buffer->shm_pool_back); if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back);
close(buffer->fd); close(buffer->fd);
close(buffer->fd_back); close(buffer->fd_back);
buffer->setup = MwFALSE; buffer->setup = MwFALSE;
@ -1426,6 +1458,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) {
WL_INTERFACE(wl_data_device_manager); WL_INTERFACE(wl_data_device_manager);
WL_INTERFACE(zwp_primary_selection_device_manager_v1); WL_INTERFACE(zwp_primary_selection_device_manager_v1);
WL_INTERFACE(zwp_pointer_constraints_v1); WL_INTERFACE(zwp_pointer_constraints_v1);
WL_INTERFACE(zwp_relative_pointer_manager_v1);
WL_INTERFACE(xdg_wm_base); WL_INTERFACE(xdg_wm_base);
if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { if(wayland->type == MWLL_WAYLAND_TOPLEVEL) {
WL_INTERFACE(wp_viewporter); WL_INTERFACE(wp_viewporter);
@ -1563,6 +1596,12 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
r->wayland.registry = wl_display_get_registry(parent->wayland.display); r->wayland.registry = wl_display_get_registry(parent->wayland.display);
r->wayland.display = parent->wayland.display; r->wayland.display = parent->wayland.display;
if(parent->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
r->wayland.sublevel->xdg_surface = parent->wayland.toplevel->xdg_surface;
} else {
r->wayland.sublevel->xdg_surface = parent->wayland.sublevel->xdg_surface;
}
wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r);
if(wl_display_roundtrip(r->wayland.display) == -1) { if(wl_display_roundtrip(r->wayland.display) == -1) {
printf("roundtrip failed\n"); printf("roundtrip failed\n");
@ -1571,8 +1610,6 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
} }
r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor);
r->wayland.sublevel->xdg_surface =
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface);
r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.framebuffer.surface, parent_surface); r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.framebuffer.surface, parent_surface);
@ -2400,10 +2437,29 @@ static void MwLLFocusImpl(MwLL handle) {
} }
static void MwLLGrabPointerImpl(MwLL handle, int toggle) { static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
if(handle->wayland.pointer_constraints) { MwLL topmost_parent = handle;
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
if(handle->wayland.pointer_constraints && handle->wayland.relative_pointer_manager) {
if(toggle) {
topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
wl_surface_commit(topmost_parent->wayland.backbuffer.surface);
zwp_locked_pointer_v1_set_cursor_position_hint(topmost_parent->wayland.locked_pointer, 0,CSD_BORDER_FRAME_TOP);
handle->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, handle->wayland.pointer);
zwp_relative_pointer_v1_add_listener(handle->wayland.relative_pointer, &relative_pointer_listener, topmost_parent);
printf("%p\n", handle->wayland.relative_pointer);
} else {
if(topmost_parent->wayland.locked_pointer) {
zwp_locked_pointer_v1_destroy(topmost_parent->wayland.locked_pointer);
topmost_parent->wayland.locked_pointer = NULL;
}
if(topmost_parent->wayland.relative_pointer) {
zwp_relative_pointer_v1_destroy(topmost_parent->wayland.relative_pointer);
topmost_parent->wayland.relative_pointer = NULL;
}
}
handle->wayland.do_lock_pointer = toggle; handle->wayland.do_lock_pointer = toggle;
} else { } else {
printf("[WARNING] MwLLGrabPointer not supported in Wayland session, zwp_pointer_constraints_v1 required.\n"); printf("[WARNING] MwLLGrabPointer not supported in Wayland session, zwp_pointer_constraints_v1 and relative_pointer_manager_v1 are required.\n");
} }
} }

View file

@ -316,6 +316,7 @@ static int create(MwWidget handle) {
if(!eglMakeCurrent(display, surface, surface, context)) { if(!eglMakeCurrent(display, surface, surface, context)) {
printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError());
} }
eglSwapInterval(o->egl_display, 0);
o->egl_display = display; o->egl_display = display;
o->egl_surface = surface; o->egl_surface = surface;
@ -425,8 +426,6 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) {
o->egl_context)) { o->egl_context)) {
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
} }
eglSwapInterval(o->egl_display, 1);
} }
#endif #endif
} }
@ -450,6 +449,7 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) {
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if(handle->lowlevel->common.type == MwLLBackendWayland) {
waylandopengl_t* o = handle->internal; waylandopengl_t* o = handle->internal;
eglSwapInterval(o->egl_display, 0);
if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { if(!eglSwapBuffers(o->egl_display, o->egl_surface)) {
printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); printf("ERROR: eglSwapBuffers, %0X\n", eglGetError());
}; };