Merge branch 'glfw:master' into drag-window-dev

This commit is contained in:
Naveen Karuthedath 2022-07-22 22:38:11 +05:30 committed by GitHub
commit 673f5dd4fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 137 additions and 129 deletions

View File

@ -82,6 +82,7 @@ video tutorials.
- Jonathan Hale - Jonathan Hale
- hdf89shfdfs - hdf89shfdfs
- Sylvain Hellegouarch - Sylvain Hellegouarch
- Björn Hempel
- Matthew Henry - Matthew Henry
- heromyth - heromyth
- Lucas Hinderberger - Lucas Hinderberger
@ -186,6 +187,7 @@ video tutorials.
- Philip Rideout - Philip Rideout
- Eddie Ringle - Eddie Ringle
- Max Risuhin - Max Risuhin
- Joe Roback
- Jorge Rodriguez - Jorge Rodriguez
- Jari Ronkainen - Jari Ronkainen
- Luca Rood - Luca Rood

View File

@ -373,8 +373,10 @@ information on what to include when reporting a bug.
wlroots compositors (#1268) wlroots compositors (#1268)
- [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG - [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG
decorations decorations
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
- [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Removed use of deprecated function `gettimeofday`
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
- [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043)
- [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072)
- [NSGL] Removed enforcement of forward-compatible flag for core contexts - [NSGL] Removed enforcement of forward-compatible flag for core contexts
- [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer

View File

@ -157,7 +157,7 @@ static GLFWbool openJoystickDevice(const char* path)
} }
// Ensure this device supports the events expected of a joystick // Ensure this device supports the events expected of a joystick
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits)) if (!isBitSet(EV_ABS, evBits))
{ {
close(linjs.fd); close(linjs.fd);
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -335,6 +335,38 @@ static void createKeyTables(void)
} }
} }
static GLFWbool loadCursorTheme(void)
{
int cursorSize = 32;
const char* sizeString = getenv("XCURSOR_SIZE");
if (sizeString)
{
errno = 0;
const long cursorSizeLong = strtol(sizeString, NULL, 10);
if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX)
cursorSize = (int) cursorSizeLong;
}
const char* themeName = getenv("XCURSOR_THEME");
_glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load default cursor theme");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm);
_glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
return GLFW_TRUE;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -472,14 +504,8 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
int _glfwInitWayland(void) int _glfwInitWayland(void)
{ {
const char* cursorTheme;
const char* cursorSizeStr;
char* cursorSizeEnd;
long cursorSizeLong;
int cursorSize;
// These must be set before any failure checks // These must be set before any failure checks
_glfw.wl.timerfd = -1; _glfw.wl.keyRepeatTimerfd = -1;
_glfw.wl.cursorTimerfd = -1; _glfw.wl.cursorTimerfd = -1;
_glfw.wl.client.display_flush = (PFN_wl_display_flush) _glfw.wl.client.display_flush = (PFN_wl_display_flush)
@ -640,7 +666,10 @@ int _glfwInitWayland(void)
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); {
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
#endif #endif
if (!_glfw.wl.wmBase) if (!_glfw.wl.wmBase)
@ -650,33 +679,15 @@ int _glfwInitWayland(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (_glfw.wl.pointer && _glfw.wl.shm) if (!_glfw.wl.shm)
{
cursorTheme = getenv("XCURSOR_THEME");
cursorSizeStr = getenv("XCURSOR_SIZE");
cursorSize = 32;
if (cursorSizeStr)
{
errno = 0;
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
cursorSize = (int)cursorSizeLong;
}
_glfw.wl.cursorTheme =
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load default cursor theme"); "Wayland: Failed to find wl_shm in your compositor");
return GLFW_FALSE; return GLFW_FALSE;
} }
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI = if (!loadCursorTheme())
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); return GLFW_FALSE;
_glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
{ {
@ -773,8 +784,8 @@ void _glfwTerminateWayland(void)
wl_display_disconnect(_glfw.wl.display); wl_display_disconnect(_glfw.wl.display);
} }
if (_glfw.wl.timerfd >= 0) if (_glfw.wl.keyRepeatTimerfd >= 0)
close(_glfw.wl.timerfd); close(_glfw.wl.keyRepeatTimerfd);
if (_glfw.wl.cursorTimerfd >= 0) if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd); close(_glfw.wl.cursorTimerfd);

View File

@ -322,12 +322,12 @@ typedef struct _GLFWlibraryWayland
uint32_t serial; uint32_t serial;
uint32_t pointerEnterSerial; uint32_t pointerEnterSerial;
int32_t keyboardRepeatRate; int keyRepeatTimerfd;
int32_t keyboardRepeatDelay; int32_t keyRepeatRate;
int keyboardLastKey; int32_t keyRepeatDelay;
int keyboardLastScancode; int keyRepeatScancode;
char* clipboardString; char* clipboardString;
int timerfd;
short int keycodes[256]; short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5]; char keynames[GLFW_KEY_LAST + 1][5];
@ -516,7 +516,6 @@ void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwAddOutputWayland(uint32_t name, uint32_t version);
void _glfwUpdateContentScaleWayland(_GLFWwindow* window); void _glfwUpdateContentScaleWayland(_GLFWwindow* window);
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);
void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddSeatListenerWayland(struct wl_seat* seat);
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);

View File

@ -142,11 +142,8 @@ static int createAnonymousFile(off_t size)
static struct wl_buffer* createShmBuffer(const GLFWimage* image) static struct wl_buffer* createShmBuffer(const GLFWimage* image)
{ {
struct wl_shm_pool* pool; const int stride = image->width * 4;
struct wl_buffer* buffer; const int length = image->width * image->height * 4;
int stride = image->width * 4;
int length = image->width * image->height * 4;
void* data;
const int fd = createAnonymousFile(length); const int fd = createAnonymousFile(length);
if (fd < 0) if (fd < 0)
@ -157,7 +154,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return NULL; return NULL;
} }
data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); void* data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) if (data == MAP_FAILED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -166,9 +163,10 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return NULL; return NULL;
} }
pool = wl_shm_create_pool(_glfw.wl.shm, fd, length); struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
close(fd); close(fd);
unsigned char* source = (unsigned char*) image->pixels; unsigned char* source = (unsigned char*) image->pixels;
unsigned char* target = data; unsigned char* target = data;
for (int i = 0; i < image->width * image->height; i++, source += 4) for (int i = 0; i < image->width * image->height; i++, source += 4)
@ -181,7 +179,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
*target++ = (unsigned char) alpha; *target++ = (unsigned char) alpha;
} }
buffer = struct wl_buffer* buffer =
wl_shm_pool_create_buffer(pool, 0, wl_shm_pool_create_buffer(pool, 0,
image->width, image->width,
image->height, image->height,
@ -743,7 +741,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
static void setCursorImage(_GLFWwindow* window, static void setCursorImage(_GLFWwindow* window,
_GLFWcursorWayland* cursorWayland) _GLFWcursorWayland* cursorWayland)
{ {
struct itimerspec timer = {}; struct itimerspec timer = {0};
struct wl_cursor* wlCursor = cursorWayland->cursor; struct wl_cursor* wlCursor = cursorWayland->cursor;
struct wl_cursor_image* image; struct wl_cursor_image* image;
struct wl_buffer* buffer; struct wl_buffer* buffer;
@ -821,13 +819,59 @@ static GLFWbool flushDisplay(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
static int translateKey(uint32_t scancode)
{
if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[scancode];
return GLFW_KEY_UNKNOWN;
}
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
{
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
return sym;
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
!= XKB_COMPOSE_FEED_ACCEPTED)
return sym;
switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
{
case XKB_COMPOSE_COMPOSED:
return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
case XKB_COMPOSE_COMPOSING:
case XKB_COMPOSE_CANCELLED:
return XKB_KEY_NoSymbol;
case XKB_COMPOSE_NOTHING:
default:
return sym;
}
}
static void inputText(_GLFWwindow* window, uint32_t scancode)
{
const xkb_keysym_t* keysyms;
const xkb_keycode_t keycode = scancode + 8;
if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
{
const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
{
const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, codepoint, mods, plain);
}
}
}
static void handleEvents(double* timeout) static void handleEvents(double* timeout)
{ {
GLFWbool event = GLFW_FALSE; GLFWbool event = GLFW_FALSE;
struct pollfd fds[] = struct pollfd fds[] =
{ {
{ wl_display_get_fd(_glfw.wl.display), POLLIN }, { wl_display_get_fd(_glfw.wl.display), POLLIN },
{ _glfw.wl.timerfd, POLLIN }, { _glfw.wl.keyRepeatTimerfd, POLLIN },
{ _glfw.wl.cursorTimerfd, POLLIN }, { _glfw.wl.cursorTimerfd, POLLIN },
}; };
@ -871,17 +915,16 @@ static void handleEvents(double* timeout)
{ {
uint64_t repeats; uint64_t repeats;
if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8) if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8)
{ {
for (uint64_t i = 0; i < repeats; i++) for (uint64_t i = 0; i < repeats; i++)
{ {
_glfwInputKey(_glfw.wl.keyboardFocus, _glfwInputKey(_glfw.wl.keyboardFocus,
_glfw.wl.keyboardLastKey, translateKey(_glfw.wl.keyRepeatScancode),
_glfw.wl.keyboardLastScancode, _glfw.wl.keyRepeatScancode,
GLFW_PRESS, GLFW_PRESS,
_glfw.wl.xkb.modifiers); _glfw.wl.xkb.modifiers);
_glfwInputTextWayland(_glfw.wl.keyboardFocus, inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyRepeatScancode);
_glfw.wl.keyboardLastScancode);
} }
event = GLFW_TRUE; event = GLFW_TRUE;
@ -1044,8 +1087,8 @@ static void pointerHandleLeave(void* userData,
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL; _glfw.wl.pointerFocus = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE);
_glfw.wl.cursorPreviousName = NULL; _glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE);
} }
static void setCursor(_GLFWwindow* window, const char* name) static void setCursor(_GLFWwindow* window, const char* name)
@ -1116,8 +1159,8 @@ static void pointerHandleMotion(void* userData,
switch (window->wl.decorations.focus) switch (window->wl.decorations.focus)
{ {
case mainWindow: case mainWindow:
_glfwInputCursorPos(window, x, y);
_glfw.wl.cursorPreviousName = NULL; _glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, x, y);
return; return;
case topDecoration: case topDecoration:
if (y < GLFW_BORDER_SIZE) if (y < GLFW_BORDER_SIZE)
@ -1397,62 +1440,14 @@ static void keyboardHandleLeave(void* userData,
if (!window) if (!window)
return; return;
struct itimerspec timer = {}; struct itimerspec timer = {0};
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = NULL; _glfw.wl.keyboardFocus = NULL;
_glfwInputWindowFocus(window, GLFW_FALSE); _glfwInputWindowFocus(window, GLFW_FALSE);
} }
static int translateKey(uint32_t scancode)
{
if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[scancode];
return GLFW_KEY_UNKNOWN;
}
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
{
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
return sym;
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
!= XKB_COMPOSE_FEED_ACCEPTED)
return sym;
switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
{
case XKB_COMPOSE_COMPOSED:
return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
case XKB_COMPOSE_COMPOSING:
case XKB_COMPOSE_CANCELLED:
return XKB_KEY_NoSymbol;
case XKB_COMPOSE_NOTHING:
default:
return sym;
}
}
GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode)
{
const xkb_keysym_t* keysyms;
const xkb_keycode_t keycode = scancode + 8;
if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
{
const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
{
const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, codepoint, mods, plain);
}
}
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode);
}
static void keyboardHandleKey(void* userData, static void keyboardHandleKey(void* userData,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard,
uint32_t serial, uint32_t serial,
@ -1469,29 +1464,33 @@ static void keyboardHandleKey(void* userData,
state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
_glfw.wl.serial = serial; _glfw.wl.serial = serial;
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
struct itimerspec timer = {}; struct itimerspec timer = {0};
if (action == GLFW_PRESS) if (action == GLFW_PRESS)
{ {
const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode); const xkb_keycode_t keycode = scancode + 8;
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) if (xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode) &&
_glfw.wl.keyRepeatRate > 0)
{ {
_glfw.wl.keyboardLastKey = key; _glfw.wl.keyRepeatScancode = scancode;
_glfw.wl.keyboardLastScancode = scancode; if (_glfw.wl.keyRepeatRate > 1)
if (_glfw.wl.keyboardRepeatRate > 1) timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyRepeatRate;
timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
else else
timer.it_interval.tv_sec = 1; timer.it_interval.tv_sec = 1;
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000; timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000; timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
} }
} }
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
if (action == GLFW_PRESS)
inputText(window, scancode);
} }
static void keyboardHandleModifiers(void* userData, static void keyboardHandleModifiers(void* userData,
@ -1551,8 +1550,8 @@ static void keyboardHandleRepeatInfo(void* userData,
if (keyboard != _glfw.wl.keyboard) if (keyboard != _glfw.wl.keyboard)
return; return;
_glfw.wl.keyboardRepeatRate = rate; _glfw.wl.keyRepeatRate = rate;
_glfw.wl.keyboardRepeatDelay = delay; _glfw.wl.keyRepeatDelay = delay;
} }
#endif #endif
@ -1843,15 +1842,10 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
void _glfwDestroyWindowWayland(_GLFWwindow* window) void _glfwDestroyWindowWayland(_GLFWwindow* window)
{ {
if (window == _glfw.wl.pointerFocus) if (window == _glfw.wl.pointerFocus)
{
_glfw.wl.pointerFocus = NULL; _glfw.wl.pointerFocus = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE);
}
if (window == _glfw.wl.keyboardFocus) if (window == _glfw.wl.keyboardFocus)
{
_glfw.wl.keyboardFocus = NULL; _glfw.wl.keyboardFocus = NULL;
_glfwInputWindowFocus(window, GLFW_FALSE);
}
if (window->wl.idleInhibitor) if (window->wl.idleInhibitor)
zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor); zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);

View File

@ -642,7 +642,7 @@ int main(int argc, char** argv)
glfwMakeContextCurrent(slots[i].window); glfwMakeContextCurrent(slots[i].window);
gladLoadGL(glfwGetProcAddress); gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1); glfwSwapBuffers(slots[i].window);
} }
printf("Main loop starting\n"); printf("Main loop starting\n");