mirror of
https://github.com/glfw/glfw.git
synced 2025-12-21 14:42:06 +00:00
Compare commits
14 Commits
8e3f0f2656
...
b4c6d510f5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4c6d510f5 | ||
|
|
0d2d85d19c | ||
|
|
768e81a0eb | ||
|
|
161fb1b6f6 | ||
|
|
645a35a38e | ||
|
|
7523b0e6bd | ||
|
|
5190a30d8a | ||
|
|
ddbb8e0f2c | ||
|
|
5245180c56 | ||
|
|
7b51a8eb31 | ||
|
|
06f21df20e | ||
|
|
c31de75111 | ||
|
|
f269a6af97 | ||
|
|
f1f869acf7 |
@ -68,6 +68,7 @@ video tutorials.
|
||||
- Jan Ekström
|
||||
- Siavash Eliasi
|
||||
- er-azh
|
||||
- Jan Hendrik Farr
|
||||
- Ahmad Fatoum
|
||||
- Nikita Fediuchin
|
||||
- Felipe Ferreira
|
||||
@ -295,6 +296,7 @@ video tutorials.
|
||||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
- Leonard König
|
||||
- Alex Sanchez-Stern
|
||||
- All the unmentioned and anonymous contributors in the GLFW community, for bug
|
||||
reports, patches, feedback, testing and encouragement
|
||||
|
||||
|
||||
12
README.md
12
README.md
@ -134,12 +134,21 @@ information on what to include when reporting a bug.
|
||||
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#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: 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)
|
||||
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
|
||||
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
||||
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to
|
||||
`GLFW_NATIVE_CONTEXT_API` (#2518)
|
||||
|
||||
- [X11] Added `getSelectionRequestHandler`, `setSelectionRequestHander`,
|
||||
`getGLFWDisplay`, and `getGLFWHelperWindow` functions. to allow
|
||||
clients to implement more X clipboard functionality than is
|
||||
built-in; with these primitives clients can add copy paste support
|
||||
for files, images, colors, and other non-text data types.
|
||||
|
||||
## Contact
|
||||
|
||||
@ -155,4 +164,3 @@ request, please file it in the
|
||||
|
||||
Finally, if you're interested in helping out with the development of GLFW or
|
||||
porting it to your favorite platform, join us on the forum or GitHub.
|
||||
|
||||
|
||||
@ -973,6 +973,53 @@ The contents of the system clipboard can be set to a UTF-8 encoded string with
|
||||
glfwSetClipboardString(NULL, "A string with words in it");
|
||||
```
|
||||
|
||||
\par Advanced Usage
|
||||
While GLFW does not directly support using other data types with the
|
||||
system clipboard, on many platforms this is possible using platform
|
||||
specific code. If you are primarily targetting a small set of
|
||||
platforms, this may be viable for your application.
|
||||
|
||||
\par
|
||||
On Windows, you can do clipboard operations directly using <a
|
||||
href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/">winuser.h</a>,
|
||||
allowing you to copy and paste datatypes other than text. On X11 you
|
||||
can also use the platform specific API to get this functionality, but
|
||||
you must hook into GLFW's X11 event handling code to allow copying
|
||||
<i>out</i> of your application. Example code for most of this functionality
|
||||
can be found in general X11 documentation like <a
|
||||
href="http://www.uninformativ.de/blog/postings/2017-04-02/0/POSTING-en.html">this
|
||||
page</a>; the GLFW-specific part is including
|
||||
|
||||
\par
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <X11/Xlib.h>
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#include <GLFW/glfw3native.h>
|
||||
@endcode
|
||||
|
||||
\par
|
||||
At the top of your file (guarded by platform), and then running
|
||||
|
||||
\par
|
||||
@code
|
||||
setSelectionRequestHandler(myHandler);
|
||||
@endcode
|
||||
|
||||
\par
|
||||
on initialization. Your selection handler must have the signature:
|
||||
|
||||
\par
|
||||
@code
|
||||
void myHandler(XEvent*);
|
||||
@endcode
|
||||
|
||||
\par
|
||||
and it will receive all X Selection events. To ensure compatibility
|
||||
use `getGLFWDisplay()` to get a display object instead of
|
||||
`XOpenDisplay()` and use the result of `getGLFWHelperWindow()` as the
|
||||
target window for the selection.
|
||||
|
||||
|
||||
## Path drop input {#path_drop}
|
||||
|
||||
|
||||
25
docs/news.md
25
docs/news.md
@ -14,6 +14,25 @@ values over 8. For compatibility with older versions, the
|
||||
@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of
|
||||
this.
|
||||
|
||||
|
||||
### Support for custom X11 clipboard functionality {#x11_custom_selection}
|
||||
|
||||
This change allows clients to implement custom X11 clipboard
|
||||
functionality like the copying and pasting of files across
|
||||
applications.
|
||||
|
||||
GLFW itself only allows plain text to be copied to the
|
||||
clipboard and back on all platforms. On some platforms, like Windows,
|
||||
you can use platform specific APIs to add extra clipboard
|
||||
functionality like copying of other data types. However, on X11, this
|
||||
was previously not fully possible due to the fact that GLFW internal
|
||||
code has full control over the X11 event queue.
|
||||
|
||||
This change exposes several new symbols that allow you to get and set
|
||||
the handler for X11 selection events that GLFW will use. It also
|
||||
allows getting the internal display connection and selection helper
|
||||
window, for use in that kind of code.
|
||||
|
||||
## Caveats {#caveats}
|
||||
|
||||
## Deprecations {#deprecations}
|
||||
@ -39,6 +58,12 @@ actively maintained and available on many platforms.
|
||||
|
||||
### New functions {#new_functions}
|
||||
|
||||
#### X11-specific
|
||||
- @ref getSelectionRequestHandler
|
||||
- @ref setSelectionRequestHanddler
|
||||
- @ref getGLFWDisplay
|
||||
- @ref getGLFWHelperWindow
|
||||
|
||||
### New types {#new_types}
|
||||
|
||||
### New constants {#new_constants}
|
||||
|
||||
@ -442,6 +442,13 @@ GLFWAPI void glfwSetX11SelectionString(const char* string);
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI const char* glfwGetX11SelectionString(void);
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
void (*getSelectionRequestHandler(void))(XEvent*);
|
||||
void setSelectionRequestHandler(void (*handler)(XEvent*));
|
||||
Display* getGLFWDisplay(void);
|
||||
Window getGLFWHelperWindow(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||
|
||||
@ -413,6 +413,8 @@ typedef struct _GLFWwindowWayland
|
||||
struct wl_buffer* buffer;
|
||||
_GLFWfallbackEdgeWayland top, left, right, bottom;
|
||||
struct wl_surface* focus;
|
||||
wl_fixed_t pointerX, pointerY;
|
||||
const char* cursorName;
|
||||
} fallback;
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
@ -454,7 +456,6 @@ typedef struct _GLFWlibraryWayland
|
||||
struct wl_cursor_theme* cursorTheme;
|
||||
struct wl_cursor_theme* cursorThemeHiDPI;
|
||||
struct wl_surface* cursorSurface;
|
||||
const char* cursorPreviousName;
|
||||
int cursorTimerfd;
|
||||
uint32_t serial;
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
struct zxdg_toplevel_decoration_v1* decoration,
|
||||
uint32_t mode)
|
||||
@ -1417,7 +1557,6 @@ static void pointerHandleLeave(void* userData,
|
||||
|
||||
_glfw.wl.serial = serial;
|
||||
_glfw.wl.pointerFocus = NULL;
|
||||
_glfw.wl.cursorPreviousName = NULL;
|
||||
|
||||
if (window->wl.hovered)
|
||||
{
|
||||
@ -1427,7 +1566,10 @@ static void pointerHandleLeave(void* userData,
|
||||
else
|
||||
{
|
||||
if (window->wl.fallback.decorations)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
_glfw.wl.cursorPreviousName = NULL;
|
||||
_glfwInputCursorPos(window, xpos, ypos);
|
||||
return;
|
||||
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
||||
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
||||
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (window->wl.fallback.decorations)
|
||||
{
|
||||
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;
|
||||
}
|
||||
updateFallbackDecorationCursor(window, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1552,62 +1618,11 @@ static void pointerHandleButton(void* userData,
|
||||
button - BTN_LEFT,
|
||||
state == WL_POINTER_BUTTON_STATE_PRESSED,
|
||||
_glfw.wl.xkb.modifiers);
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (window->wl.fallback.decorations)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
handleFallbackDecorationButton(window, serial, button);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1621,12 +1636,15 @@ static void pointerHandleAxis(void* userData,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (window->wl.hovered)
|
||||
{
|
||||
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
|
||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
|
||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_pointer_listener pointerListener =
|
||||
{
|
||||
@ -1802,10 +1820,11 @@ static void keyboardHandleKey(void* userData,
|
||||
|
||||
timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;
|
||||
timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@ -1315,6 +1315,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
|
||||
_glfw.x11.xlib.handle = module;
|
||||
|
||||
*platform = x11;
|
||||
|
||||
handleSelectionRequest = handleSelectionRequest_;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -896,6 +896,8 @@ typedef struct _GLFWcursorX11
|
||||
Cursor handle;
|
||||
} _GLFWcursorX11;
|
||||
|
||||
extern void (*handleSelectionRequest)(XEvent*);
|
||||
void handleSelectionRequest_(XEvent* event);
|
||||
|
||||
GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform);
|
||||
int _glfwInitX11(void);
|
||||
|
||||
@ -921,7 +921,8 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
return None;
|
||||
}
|
||||
|
||||
static void handleSelectionRequest(XEvent* event)
|
||||
void (*handleSelectionRequest)(XEvent*);
|
||||
void handleSelectionRequest_(XEvent* event)
|
||||
{
|
||||
const XSelectionRequestEvent* request = &event->xselectionrequest;
|
||||
|
||||
@ -3356,6 +3357,18 @@ GLFWAPI const char* glfwGetX11SelectionString(void)
|
||||
|
||||
return getSelectionString(_glfw.x11.PRIMARY);
|
||||
}
|
||||
void (*getSelectionRequestHandler(void))(XEvent*) {
|
||||
return handleSelectionRequest;
|
||||
}
|
||||
void setSelectionRequestHandler(void (*handler)(XEvent*)) {
|
||||
handleSelectionRequest = handler;
|
||||
}
|
||||
Display* getGLFWDisplay(void) {
|
||||
return _glfw.x11.display;
|
||||
}
|
||||
|
||||
Window getGLFWHelperWindow(void) {
|
||||
return _glfw.x11.helperWindowHandle;
|
||||
}
|
||||
|
||||
#endif // _GLFW_X11
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user