mirror of
https://github.com/glfw/glfw.git
synced 2025-12-21 14:42:06 +00:00
Compare commits
12 Commits
18a72beacd
...
55d45f7a7a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55d45f7a7a | ||
|
|
768e81a0eb | ||
|
|
161fb1b6f6 | ||
|
|
645a35a38e | ||
|
|
7523b0e6bd | ||
|
|
5190a30d8a | ||
|
|
ddbb8e0f2c | ||
|
|
5245180c56 | ||
|
|
26a8ef471a | ||
|
|
6cbd003914 | ||
|
|
a2f8d94a7b | ||
|
|
1ae5376a31 |
@ -33,6 +33,7 @@ cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on
|
|||||||
"WIN32" OFF)
|
"WIN32" OFF)
|
||||||
cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
|
cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
|
||||||
"MSVC" OFF)
|
"MSVC" OFF)
|
||||||
|
option(GLFW_BUILD_WEBGPU "Build support for WebGPU" OFF)
|
||||||
|
|
||||||
set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING
|
set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING
|
||||||
"Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)")
|
"Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)")
|
||||||
@ -66,6 +67,9 @@ endif()
|
|||||||
if (GLFW_BUILD_X11)
|
if (GLFW_BUILD_X11)
|
||||||
message(STATUS "Including X11 support")
|
message(STATUS "Including X11 support")
|
||||||
endif()
|
endif()
|
||||||
|
if (GLFW_BUILD_WEBGPU)
|
||||||
|
message(STATUS "Including WebGPU support")
|
||||||
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Apply Microsoft C runtime library option
|
# Apply Microsoft C runtime library option
|
||||||
|
|||||||
@ -68,6 +68,7 @@ video tutorials.
|
|||||||
- Jan Ekström
|
- Jan Ekström
|
||||||
- Siavash Eliasi
|
- Siavash Eliasi
|
||||||
- er-azh
|
- er-azh
|
||||||
|
- Jan Hendrik Farr
|
||||||
- Ahmad Fatoum
|
- Ahmad Fatoum
|
||||||
- Nikita Fediuchin
|
- Nikita Fediuchin
|
||||||
- Felipe Ferreira
|
- Felipe Ferreira
|
||||||
|
|||||||
@ -135,6 +135,10 @@ information on what to include when reporting a bug.
|
|||||||
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
|
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
|
||||||
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
|
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
|
||||||
- [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736)
|
- [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736)
|
||||||
|
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
|
||||||
|
fallback decorations
|
||||||
|
- [Wayland] Bugfix: Fallback decorations would report scroll events
|
||||||
|
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
|
||||||
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
|
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
|
||||||
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
|
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
|
||||||
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
||||||
|
|||||||
@ -247,6 +247,10 @@ extern "C" {
|
|||||||
|
|
||||||
#endif /* OpenGL and OpenGL ES headers */
|
#endif /* OpenGL and OpenGL ES headers */
|
||||||
|
|
||||||
|
#if defined(GLFW_INCLUDE_WEBGPU)
|
||||||
|
#include <webgpu/webgpu.h>
|
||||||
|
#endif /* webgpu header */
|
||||||
|
|
||||||
#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
|
#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
|
||||||
/* GLFW_DLL must be defined by applications that are linking against the DLL
|
/* GLFW_DLL must be defined by applications that are linking against the DLL
|
||||||
* version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW
|
* version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW
|
||||||
@ -6525,6 +6529,29 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window
|
|||||||
|
|
||||||
#endif /*VK_VERSION_1_0*/
|
#endif /*VK_VERSION_1_0*/
|
||||||
|
|
||||||
|
#if defined(WEBGPU_H_)
|
||||||
|
|
||||||
|
/*! @brief Creates a WebGPU surface for the specified window.
|
||||||
|
*
|
||||||
|
* This function creates a WGPUSurface object for the specified window.
|
||||||
|
*
|
||||||
|
* If the surface cannot be created, this function returns `NULL`.
|
||||||
|
*
|
||||||
|
* It is the responsibility of the caller to destroy the window surface. The
|
||||||
|
* window surface must be destroyed using `wgpuSurfaceRelease`.
|
||||||
|
*
|
||||||
|
* @param[in] instance The WebGPU instance to create the surface in.
|
||||||
|
* @param[in] window The window to create the surface for.
|
||||||
|
* @return The handle of the surface. This is set to `NULL` if an error
|
||||||
|
* occurred.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.4.
|
||||||
|
*
|
||||||
|
* @ingroup webgpu
|
||||||
|
*/
|
||||||
|
GLFWAPI WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window);
|
||||||
|
|
||||||
|
#endif /* WEBGPU_H_ */
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* Global definition cleanup
|
* Global definition cleanup
|
||||||
|
|||||||
@ -3,9 +3,10 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
|
|||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
|
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
|
||||||
internal.h platform.h mappings.h
|
internal.h platform.h mappings.h
|
||||||
context.c init.c input.c monitor.c platform.c vulkan.c window.c
|
context.c init.c input.c monitor.c platform.c vulkan.c webgpu.c
|
||||||
egl_context.c osmesa_context.c null_platform.h null_joystick.h
|
window.c egl_context.c osmesa_context.c null_platform.h
|
||||||
null_init.c null_monitor.c null_window.c null_joystick.c)
|
null_joystick.h null_init.c null_monitor.c null_window.c
|
||||||
|
null_joystick.c)
|
||||||
|
|
||||||
# The time, thread and module code is shared between all backends on a given OS,
|
# The time, thread and module code is shared between all backends on a given OS,
|
||||||
# including the null backend, which still needs those bits to be functional
|
# including the null backend, which still needs those bits to be functional
|
||||||
@ -265,6 +266,15 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||||||
target_compile_definitions(glfw PRIVATE _DEFAULT_SOURCE)
|
target_compile_definitions(glfw PRIVATE _DEFAULT_SOURCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (GLFW_BUILD_WEBGPU)
|
||||||
|
target_compile_definitions(glfw PRIVATE _GLFW_BUILD_WEBGPU)
|
||||||
|
if (GLFW_BUILD_COCOA)
|
||||||
|
target_compile_options(glfw PRIVATE -x objective-c)
|
||||||
|
target_link_libraries(glfw PRIVATE "-framework QuartzCore")
|
||||||
|
set(glfw_PKG_LIBS "${glfw_PKG_LIBS} -framework QuartzCore")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (GLFW_BUILD_SHARED_LIBRARY)
|
if (GLFW_BUILD_SHARED_LIBRARY)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
|
|||||||
198
src/webgpu.c
Normal file
198
src/webgpu.c
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.4 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2022-2024 Elie Michel <eliemichelfr@gmail.com> and the
|
||||||
|
// wgpu-native authors.
|
||||||
|
// Most of the code from this file comes from the wgpu-native triangle example:
|
||||||
|
// https://github.com/gfx-rs/wgpu-native/blob/master/examples/triangle/main.c
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#if defined(_GLFW_BUILD_WEBGPU)
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
# define GLFW_EXPOSE_NATIVE_EMSCRIPTEN
|
||||||
|
# ifndef GLFW_PLATFORM_EMSCRIPTEN // not defined in older versions of emscripten
|
||||||
|
# define GLFW_PLATFORM_EMSCRIPTEN 0
|
||||||
|
# endif
|
||||||
|
#else // __EMSCRIPTEN__
|
||||||
|
# ifdef _GLFW_X11
|
||||||
|
# define GLFW_EXPOSE_NATIVE_X11
|
||||||
|
# endif
|
||||||
|
# ifdef _GLFW_WAYLAND
|
||||||
|
# define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
# endif
|
||||||
|
# ifdef _GLFW_COCOA
|
||||||
|
# define GLFW_EXPOSE_NATIVE_COCOA
|
||||||
|
# endif
|
||||||
|
# ifdef _GLFW_WIN32
|
||||||
|
# define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
# endif
|
||||||
|
#endif // __EMSCRIPTEN__
|
||||||
|
|
||||||
|
#ifdef GLFW_EXPOSE_NATIVE_COCOA
|
||||||
|
# include <Foundation/Foundation.h>
|
||||||
|
# include <QuartzCore/CAMetalLayer.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
# include <GLFW/glfw3native.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
WGPUSurface glfwCreateWindowWGPUSurface(WGPUInstance instance, GLFWwindow* window) {
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
switch (glfwGetPlatform()) {
|
||||||
|
#else
|
||||||
|
// glfwGetPlatform is not available in older versions of emscripten
|
||||||
|
switch (GLFW_PLATFORM_EMSCRIPTEN) {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GLFW_EXPOSE_NATIVE_X11
|
||||||
|
case GLFW_PLATFORM_X11: {
|
||||||
|
Display* x11_display = glfwGetX11Display();
|
||||||
|
Window x11_window = glfwGetX11Window(window);
|
||||||
|
|
||||||
|
# ifdef WEBGPU_BACKEND_DAWN
|
||||||
|
WGPUSurfaceSourceXlibWindow fromXlibWindow;
|
||||||
|
fromXlibWindow.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
|
||||||
|
# else
|
||||||
|
WGPUSurfaceDescriptorFromXlibWindow fromXlibWindow;
|
||||||
|
fromXlibWindow.chain.sType = WGPUSType_SurfaceDescriptorFromXlibWindow;
|
||||||
|
# endif
|
||||||
|
fromXlibWindow.chain.next = NULL;
|
||||||
|
fromXlibWindow.display = x11_display;
|
||||||
|
fromXlibWindow.window = x11_window;
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surfaceDescriptor;
|
||||||
|
surfaceDescriptor.nextInChain = &fromXlibWindow.chain;
|
||||||
|
surfaceDescriptor.label = NULL;
|
||||||
|
|
||||||
|
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
|
||||||
|
}
|
||||||
|
#endif // GLFW_EXPOSE_NATIVE_X11
|
||||||
|
|
||||||
|
#ifdef GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
case GLFW_PLATFORM_WAYLAND: {
|
||||||
|
struct wl_display* wayland_display = glfwGetWaylandDisplay();
|
||||||
|
struct wl_surface* wayland_surface = glfwGetWaylandWindow(window);
|
||||||
|
|
||||||
|
# ifdef WEBGPU_BACKEND_DAWN
|
||||||
|
WGPUSurfaceSourceWaylandSurface fromWaylandSurface;
|
||||||
|
fromWaylandSurface.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
|
||||||
|
# else
|
||||||
|
WGPUSurfaceDescriptorFromWaylandSurface fromWaylandSurface;
|
||||||
|
fromWaylandSurface.chain.sType = WGPUSType_SurfaceDescriptorFromWaylandSurface;
|
||||||
|
# endif
|
||||||
|
fromWaylandSurface.chain.next = NULL;
|
||||||
|
fromWaylandSurface.display = wayland_display;
|
||||||
|
fromWaylandSurface.surface = wayland_surface;
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surfaceDescriptor;
|
||||||
|
surfaceDescriptor.nextInChain = &fromWaylandSurface.chain;
|
||||||
|
surfaceDescriptor.label = NULL;
|
||||||
|
|
||||||
|
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
|
||||||
|
}
|
||||||
|
#endif // GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
|
||||||
|
#ifdef GLFW_EXPOSE_NATIVE_COCOA
|
||||||
|
case GLFW_PLATFORM_COCOA: {
|
||||||
|
id metal_layer = [CAMetalLayer layer];
|
||||||
|
NSWindow* ns_window = glfwGetCocoaWindow(window);
|
||||||
|
[ns_window.contentView setWantsLayer : YES] ;
|
||||||
|
[ns_window.contentView setLayer : metal_layer] ;
|
||||||
|
|
||||||
|
# ifdef WEBGPU_BACKEND_DAWN
|
||||||
|
WGPUSurfaceSourceMetalLayer fromMetalLayer;
|
||||||
|
fromMetalLayer.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
|
||||||
|
# else
|
||||||
|
WGPUSurfaceDescriptorFromMetalLayer fromMetalLayer;
|
||||||
|
fromMetalLayer.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
|
||||||
|
# endif
|
||||||
|
fromMetalLayer.chain.next = NULL;
|
||||||
|
fromMetalLayer.layer = metal_layer;
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surfaceDescriptor;
|
||||||
|
surfaceDescriptor.nextInChain = &fromMetalLayer.chain;
|
||||||
|
surfaceDescriptor.label = NULL;
|
||||||
|
|
||||||
|
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
|
||||||
|
}
|
||||||
|
#endif // GLFW_EXPOSE_NATIVE_COCOA
|
||||||
|
|
||||||
|
#ifdef GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
case GLFW_PLATFORM_WIN32: {
|
||||||
|
HWND hwnd = glfwGetWin32Window(window);
|
||||||
|
HINSTANCE hinstance = GetModuleHandle(NULL);
|
||||||
|
|
||||||
|
# ifdef WEBGPU_BACKEND_DAWN
|
||||||
|
WGPUSurfaceSourceWindowsHWND fromWindowsHWND;
|
||||||
|
fromWindowsHWND.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
|
||||||
|
# else
|
||||||
|
WGPUSurfaceDescriptorFromWindowsHWND fromWindowsHWND;
|
||||||
|
fromWindowsHWND.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
|
||||||
|
# endif
|
||||||
|
fromWindowsHWND.chain.next = NULL;
|
||||||
|
fromWindowsHWND.hinstance = hinstance;
|
||||||
|
fromWindowsHWND.hwnd = hwnd;
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surfaceDescriptor;
|
||||||
|
surfaceDescriptor.nextInChain = &fromWindowsHWND.chain;
|
||||||
|
surfaceDescriptor.label = NULL;
|
||||||
|
|
||||||
|
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
|
||||||
|
}
|
||||||
|
#endif // GLFW_EXPOSE_NATIVE_X11
|
||||||
|
|
||||||
|
#ifdef GLFW_EXPOSE_NATIVE_EMSCRIPTEN
|
||||||
|
case GLFW_PLATFORM_EMSCRIPTEN: {
|
||||||
|
# ifdef WEBGPU_BACKEND_DAWN
|
||||||
|
WGPUSurfaceSourceCanvasHTMLSelector_Emscripten fromCanvasHTMLSelector;
|
||||||
|
fromCanvasHTMLSelector.chain.sType = WGPUSType_SurfaceSourceCanvasHTMLSelector_Emscripten;
|
||||||
|
# else
|
||||||
|
WGPUSurfaceDescriptorFromCanvasHTMLSelector fromCanvasHTMLSelector;
|
||||||
|
fromCanvasHTMLSelector.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
||||||
|
# endif
|
||||||
|
fromCanvasHTMLSelector.chain.next = NULL;
|
||||||
|
fromCanvasHTMLSelector.selector = "canvas";
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surfaceDescriptor;
|
||||||
|
surfaceDescriptor.nextInChain = &fromCanvasHTMLSelector.chain;
|
||||||
|
surfaceDescriptor.label = NULL;
|
||||||
|
|
||||||
|
return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
|
||||||
|
}
|
||||||
|
#endif // GLFW_EXPOSE_NATIVE_X11
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unsupported platform
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _GLFW_BUILD_WEBGPU */
|
||||||
@ -413,6 +413,8 @@ typedef struct _GLFWwindowWayland
|
|||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
_GLFWfallbackEdgeWayland top, left, right, bottom;
|
_GLFWfallbackEdgeWayland top, left, right, bottom;
|
||||||
struct wl_surface* focus;
|
struct wl_surface* focus;
|
||||||
|
wl_fixed_t pointerX, pointerY;
|
||||||
|
const char* cursorName;
|
||||||
} fallback;
|
} fallback;
|
||||||
} _GLFWwindowWayland;
|
} _GLFWwindowWayland;
|
||||||
|
|
||||||
@ -454,7 +456,6 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct wl_cursor_theme* cursorTheme;
|
struct wl_cursor_theme* cursorTheme;
|
||||||
struct wl_cursor_theme* cursorThemeHiDPI;
|
struct wl_cursor_theme* cursorThemeHiDPI;
|
||||||
struct wl_surface* cursorSurface;
|
struct wl_surface* cursorSurface;
|
||||||
const char* cursorPreviousName;
|
|
||||||
int cursorTimerfd;
|
int cursorTimerfd;
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
uint32_t pointerEnterSerial;
|
uint32_t pointerEnterSerial;
|
||||||
|
|||||||
299
src/wl_window.c
299
src/wl_window.c
@ -275,6 +275,146 @@ static void destroyFallbackDecorations(_GLFWwindow* window)
|
|||||||
destroyFallbackEdge(&window->wl.fallback.bottom);
|
destroyFallbackEdge(&window->wl.fallback.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateFallbackDecorationCursor(_GLFWwindow* window,
|
||||||
|
wl_fixed_t sx,
|
||||||
|
wl_fixed_t sy)
|
||||||
|
{
|
||||||
|
window->wl.fallback.pointerX = sx;
|
||||||
|
window->wl.fallback.pointerY = sy;
|
||||||
|
|
||||||
|
const double xpos = wl_fixed_to_double(sx);
|
||||||
|
const double ypos = wl_fixed_to_double(sy);
|
||||||
|
const char* cursorName = "left_ptr";
|
||||||
|
|
||||||
|
if (window->resizable)
|
||||||
|
{
|
||||||
|
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
|
||||||
|
{
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
cursorName = "n-resize";
|
||||||
|
}
|
||||||
|
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
|
||||||
|
{
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
cursorName = "nw-resize";
|
||||||
|
else
|
||||||
|
cursorName = "w-resize";
|
||||||
|
}
|
||||||
|
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
|
||||||
|
{
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
cursorName = "ne-resize";
|
||||||
|
else
|
||||||
|
cursorName = "e-resize";
|
||||||
|
}
|
||||||
|
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
|
||||||
|
{
|
||||||
|
if (xpos < GLFW_BORDER_SIZE)
|
||||||
|
cursorName = "sw-resize";
|
||||||
|
else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
|
||||||
|
cursorName = "se-resize";
|
||||||
|
else
|
||||||
|
cursorName = "s-resize";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->wl.fallback.cursorName != cursorName)
|
||||||
|
{
|
||||||
|
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
||||||
|
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
|
||||||
|
int scale = 1;
|
||||||
|
|
||||||
|
if (window->wl.bufferScale > 1 && _glfw.wl.cursorThemeHiDPI)
|
||||||
|
{
|
||||||
|
// We only support up to scale=2 for now, since libwayland-cursor
|
||||||
|
// requires us to load a different theme for each size.
|
||||||
|
scale = 2;
|
||||||
|
theme = _glfw.wl.cursorThemeHiDPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName);
|
||||||
|
if (!cursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: handle animated cursors too.
|
||||||
|
struct wl_cursor_image* image = cursor->images[0];
|
||||||
|
if (!image)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
|
||||||
|
surface,
|
||||||
|
image->hotspot_x / scale,
|
||||||
|
image->hotspot_y / scale);
|
||||||
|
wl_surface_set_buffer_scale(surface, scale);
|
||||||
|
wl_surface_attach(surface, buffer, 0, 0);
|
||||||
|
wl_surface_damage(surface, 0, 0, image->width, image->height);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
|
||||||
|
window->wl.fallback.cursorName = cursorName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleFallbackDecorationButton(_GLFWwindow* window,
|
||||||
|
uint32_t serial,
|
||||||
|
uint32_t button)
|
||||||
|
{
|
||||||
|
const double xpos = wl_fixed_to_double(window->wl.fallback.pointerX);
|
||||||
|
const double ypos = wl_fixed_to_double(window->wl.fallback.pointerY);
|
||||||
|
|
||||||
|
if (button == BTN_LEFT)
|
||||||
|
{
|
||||||
|
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
||||||
|
|
||||||
|
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
|
||||||
|
{
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
||||||
|
else
|
||||||
|
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
|
||||||
|
}
|
||||||
|
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
|
||||||
|
{
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
|
||||||
|
else
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
|
||||||
|
}
|
||||||
|
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
|
||||||
|
{
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
|
||||||
|
else
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
|
||||||
|
}
|
||||||
|
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
|
||||||
|
{
|
||||||
|
if (xpos < GLFW_BORDER_SIZE)
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
||||||
|
else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
||||||
|
else
|
||||||
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
|
||||||
|
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges);
|
||||||
|
}
|
||||||
|
else if (button == BTN_RIGHT)
|
||||||
|
{
|
||||||
|
if (window->wl.xdg.toplevel)
|
||||||
|
{
|
||||||
|
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
|
||||||
|
_glfw.wl.seat, serial,
|
||||||
|
window->wl.cursorPosX,
|
||||||
|
window->wl.cursorPosY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void xdgDecorationHandleConfigure(void* userData,
|
static void xdgDecorationHandleConfigure(void* userData,
|
||||||
struct zxdg_toplevel_decoration_v1* decoration,
|
struct zxdg_toplevel_decoration_v1* decoration,
|
||||||
uint32_t mode)
|
uint32_t mode)
|
||||||
@ -1417,7 +1557,6 @@ static void pointerHandleLeave(void* userData,
|
|||||||
|
|
||||||
_glfw.wl.serial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfw.wl.cursorPreviousName = NULL;
|
|
||||||
|
|
||||||
if (window->wl.hovered)
|
if (window->wl.hovered)
|
||||||
{
|
{
|
||||||
@ -1427,7 +1566,10 @@ static void pointerHandleLeave(void* userData,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
|
{
|
||||||
window->wl.fallback.focus = NULL;
|
window->wl.fallback.focus = NULL;
|
||||||
|
window->wl.fallback.cursorName = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1444,92 +1586,16 @@ static void pointerHandleMotion(void* userData,
|
|||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const double xpos = wl_fixed_to_double(sx);
|
|
||||||
const double ypos = wl_fixed_to_double(sy);
|
|
||||||
window->wl.cursorPosX = xpos;
|
|
||||||
window->wl.cursorPosY = ypos;
|
|
||||||
|
|
||||||
if (window->wl.hovered)
|
if (window->wl.hovered)
|
||||||
{
|
{
|
||||||
_glfw.wl.cursorPreviousName = NULL;
|
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
||||||
_glfwInputCursorPos(window, xpos, ypos);
|
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
||||||
return;
|
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
{
|
updateFallbackDecorationCursor(window, sx, sy);
|
||||||
const char* cursorName = "left_ptr";
|
|
||||||
|
|
||||||
if (window->resizable)
|
|
||||||
{
|
|
||||||
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
|
|
||||||
{
|
|
||||||
if (ypos < GLFW_BORDER_SIZE)
|
|
||||||
cursorName = "n-resize";
|
|
||||||
}
|
|
||||||
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
|
|
||||||
{
|
|
||||||
if (ypos < GLFW_BORDER_SIZE)
|
|
||||||
cursorName = "nw-resize";
|
|
||||||
else
|
|
||||||
cursorName = "w-resize";
|
|
||||||
}
|
|
||||||
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
|
|
||||||
{
|
|
||||||
if (ypos < GLFW_BORDER_SIZE)
|
|
||||||
cursorName = "ne-resize";
|
|
||||||
else
|
|
||||||
cursorName = "e-resize";
|
|
||||||
}
|
|
||||||
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
|
|
||||||
{
|
|
||||||
if (xpos < GLFW_BORDER_SIZE)
|
|
||||||
cursorName = "sw-resize";
|
|
||||||
else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
|
|
||||||
cursorName = "se-resize";
|
|
||||||
else
|
|
||||||
cursorName = "s-resize";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wl.cursorPreviousName != cursorName)
|
|
||||||
{
|
|
||||||
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
|
||||||
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
|
|
||||||
int scale = 1;
|
|
||||||
|
|
||||||
if (window->wl.bufferScale > 1 && _glfw.wl.cursorThemeHiDPI)
|
|
||||||
{
|
|
||||||
// We only support up to scale=2 for now, since libwayland-cursor
|
|
||||||
// requires us to load a different theme for each size.
|
|
||||||
scale = 2;
|
|
||||||
theme = _glfw.wl.cursorThemeHiDPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName);
|
|
||||||
if (!cursor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO: handle animated cursors too.
|
|
||||||
struct wl_cursor_image* image = cursor->images[0];
|
|
||||||
if (!image)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);
|
|
||||||
if (!buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
|
|
||||||
surface,
|
|
||||||
image->hotspot_x / scale,
|
|
||||||
image->hotspot_y / scale);
|
|
||||||
wl_surface_set_buffer_scale(surface, scale);
|
|
||||||
wl_surface_attach(surface, buffer, 0, 0);
|
|
||||||
wl_surface_damage(surface, 0, 0, image->width, image->height);
|
|
||||||
wl_surface_commit(surface);
|
|
||||||
|
|
||||||
_glfw.wl.cursorPreviousName = cursorName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1552,62 +1618,11 @@ static void pointerHandleButton(void* userData,
|
|||||||
button - BTN_LEFT,
|
button - BTN_LEFT,
|
||||||
state == WL_POINTER_BUTTON_STATE_PRESSED,
|
state == WL_POINTER_BUTTON_STATE_PRESSED,
|
||||||
_glfw.wl.xkb.modifiers);
|
_glfw.wl.xkb.modifiers);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
{
|
handleFallbackDecorationButton(window, serial, button);
|
||||||
if (button == BTN_LEFT)
|
|
||||||
{
|
|
||||||
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
|
||||||
|
|
||||||
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
|
|
||||||
{
|
|
||||||
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
|
||||||
else
|
|
||||||
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
|
|
||||||
}
|
|
||||||
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
|
|
||||||
{
|
|
||||||
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
|
|
||||||
else
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
|
|
||||||
}
|
|
||||||
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
|
|
||||||
{
|
|
||||||
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
|
|
||||||
else
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
|
|
||||||
}
|
|
||||||
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
|
|
||||||
{
|
|
||||||
if (window->wl.cursorPosX < GLFW_BORDER_SIZE)
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
|
||||||
else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE)
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
|
||||||
else
|
|
||||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
|
|
||||||
{
|
|
||||||
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
|
|
||||||
serial, edges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (button == BTN_RIGHT)
|
|
||||||
{
|
|
||||||
if (window->wl.xdg.toplevel)
|
|
||||||
{
|
|
||||||
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
|
|
||||||
_glfw.wl.seat, serial,
|
|
||||||
window->wl.cursorPosX,
|
|
||||||
window->wl.cursorPosY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1621,11 +1636,14 @@ static void pointerHandleAxis(void* userData,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (window->wl.hovered)
|
||||||
|
{
|
||||||
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
|
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
|
||||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||||
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
|
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
|
||||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
|
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_pointer_listener pointerListener =
|
static const struct wl_pointer_listener pointerListener =
|
||||||
@ -1820,10 +1838,11 @@ static void keyboardHandleKey(void* userData,
|
|||||||
|
|
||||||
timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;
|
timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;
|
||||||
timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
|
timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
|
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
|
||||||
|
}
|
||||||
|
} else if (scancode == _glfw.wl.keyRepeatScancode) {
|
||||||
|
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
|
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user