From 6e0f39a6cb07230a54fd96930fd5d0d0c0fcc079 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 9 Apr 2016 00:42:58 +0100 Subject: [PATCH 1/6] wayland: Implement window size limits and aspect ratio --- include/GLFW/glfw3.h | 2 +- src/wl_window.c | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index f8ca3d61a..cedecfcbb 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -2049,7 +2049,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); /*! @brief Sets the size limits of the specified window. * * This function sets the size limits of the client area of the specified - * window. If the window is full screen, the size limits only take effect if + * window. If the window is full screen, the size limits only take effect * once it is made windowed. If the window is not resizable, this function * does nothing. * diff --git a/src/wl_window.c b/src/wl_window.c index 6a86f9e9c..1c85772e5 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -55,7 +55,32 @@ static void handleConfigure(void* data, int32_t height) { _GLFWwindow* window = data; - _glfwInputFramebufferSize(window, width, height); + float aspectRatio; + float targetRatio; + + if (!window->monitor) + { + if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) + { + aspectRatio = (float)width / (float)height; + targetRatio = (float)window->numer / (float)window->denom; + if (aspectRatio < targetRatio) + height = width / targetRatio; + else if (aspectRatio > targetRatio) + width = height * targetRatio; + } + + if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth) + width = window->minwidth; + else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth) + width = window->maxwidth; + + if (window->minheight != GLFW_DONT_CARE && height < window->minheight) + height = window->minheight; + else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight) + height = window->maxheight; + } + _glfwInputWindowSize(window, width, height); _glfwPlatformSetWindowSize(window, width, height); _glfwInputWindowDamage(window); @@ -429,14 +454,14 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight) { - // TODO - fprintf(stderr, "_glfwPlatformSetWindowSizeLimits not implemented yet\n"); + // TODO: find out how to trigger a resize. + // The actual limits are checked in the wl_shell_surface::configure handler. } void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) { - // TODO - fprintf(stderr, "_glfwPlatformSetWindowAspectRatio not implemented yet\n"); + // TODO: find out how to trigger a resize. + // The actual limits are checked in the wl_shell_surface::configure handler. } void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) From 01a58b81385b70403ae8a49576ef5274ad023882 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 9 Apr 2016 00:51:48 +0100 Subject: [PATCH 2/6] wayland: Handle hidden window as not having a shell surface. --- src/wl_platform.h | 2 ++ src/wl_window.c | 69 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index 100b12bc0..c538936c5 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -91,6 +91,8 @@ typedef struct _GLFWwindowWayland _GLFWcursor* currentCursor; double cursorPosX, cursorPosY; + char* title; + // We need to track the monitors the window spans on to calculate the // optimal scaling factor. int scale; diff --git a/src/wl_window.c b/src/wl_window.c index 1c85772e5..033e11e40 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -193,6 +193,15 @@ static GLFWbool createSurface(_GLFWwindow* window, if (!window->wl.native) return GLFW_FALSE; + window->wl.width = wndconfig->width; + window->wl.height = wndconfig->height; + window->wl.scale = 1; + + return GLFW_TRUE; +} + +static GLFWbool createShellSurface(_GLFWwindow* window) +{ window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell, window->wl.surface); if (!window->wl.shell_surface) @@ -202,9 +211,21 @@ static GLFWbool createSurface(_GLFWwindow* window, &shellSurfaceListener, window); - window->wl.width = wndconfig->width; - window->wl.height = wndconfig->height; - window->wl.scale = 1; + if (window->wl.title) + wl_shell_surface_set_title(window->wl.shell_surface, window->wl.title); + + if (window->monitor) + { + wl_shell_surface_set_fullscreen( + window->wl.shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, + window->monitor->wl.output); + } + else + { + wl_shell_surface_set_toplevel(window->wl.shell_surface); + } return GLFW_TRUE; } @@ -354,17 +375,20 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, return GLFW_FALSE; } - if (window->monitor) + if (wndconfig->title) + window->wl.title = strdup(wndconfig->title); + + if (wndconfig->visible) { - wl_shell_surface_set_fullscreen( - window->wl.shell_surface, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, - 0, - window->monitor->wl.output); + if (!createShellSurface(window)) + return GLFW_FALSE; + + window->wl.visible = GLFW_TRUE; } else { - wl_shell_surface_set_toplevel(window->wl.shell_surface); + window->wl.shell_surface = NULL; + window->wl.visible = GLFW_FALSE; } window->wl.currentCursor = NULL; @@ -400,12 +424,17 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->wl.surface) wl_surface_destroy(window->wl.surface); + free(window->wl.title); free(window->wl.monitors); } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) { - wl_shell_surface_set_title(window->wl.shell_surface, title); + if (window->wl.title) + free(window->wl.title); + window->wl.title = strdup(title); + if (window->wl.shell_surface) + wl_shell_surface_set_title(window->wl.shell_surface, title); } void _glfwPlatformSetWindowIcon(_GLFWwindow* window, @@ -499,13 +528,22 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window) { - wl_shell_surface_set_toplevel(window->wl.shell_surface); + if (!window->monitor) + { + if (!window->wl.shell_surface) + createShellSurface(window); + window->wl.visible = GLFW_TRUE; + } } void _glfwPlatformHideWindow(_GLFWwindow* window) { - wl_surface_attach(window->wl.surface, NULL, 0, 0); - wl_surface_commit(window->wl.surface); + if (!window->monitor) + { + if (window->wl.shell_surface) + wl_shell_surface_destroy(window->wl.shell_surface); + window->wl.visible = GLFW_FALSE; + } } void _glfwPlatformFocusWindow(_GLFWwindow* window) @@ -538,8 +576,7 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowVisible(_GLFWwindow* window) { - // TODO - return GLFW_FALSE; + return window->wl.visible; } int _glfwPlatformWindowMaximized(_GLFWwindow* window) From c3a5a56e4d2b9d6998579bb068a0528331324e22 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 9 Apr 2016 00:53:03 +0100 Subject: [PATCH 3/6] wayland: Implement glfwSetWindowMonitor. --- src/wl_window.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 033e11e40..c254f41b4 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -558,8 +558,19 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, int width, int height, int refreshRate) { - // TODO - fprintf(stderr, "_glfwPlatformSetWindowMonitor not implemented yet\n"); + if (monitor) + { + wl_shell_surface_set_fullscreen( + window->wl.shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + refreshRate * 1000, // Convert Hz to mHz. + monitor->wl.output); + } + else + { + wl_shell_surface_set_toplevel(window->wl.shell_surface); + } + _glfwInputWindowMonitorChange(window, monitor); } int _glfwPlatformWindowFocused(_GLFWwindow* window) From 5bf428c516099fae599d0031037a377916526bdd Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 9 Apr 2016 00:54:23 +0100 Subject: [PATCH 4/6] wayland: Implement maximized state. --- src/wl_platform.h | 1 + src/wl_window.c | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index c538936c5..d75c025e5 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -83,6 +83,7 @@ typedef struct _GLFWwindowWayland { int width, height; GLFWbool visible; + GLFWbool maximized; struct wl_surface* surface; struct wl_egl_window* native; struct wl_shell_surface* shell_surface; diff --git a/src/wl_window.c b/src/wl_window.c index c254f41b4..085863009 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -222,6 +222,10 @@ static GLFWbool createShellSurface(_GLFWwindow* window) 0, window->monitor->wl.output); } + else if (window->wl.maximized) + { + wl_shell_surface_set_maximized(window->wl.shell_surface, NULL); + } else { wl_shell_surface_set_toplevel(window->wl.shell_surface); @@ -516,14 +520,27 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window) void _glfwPlatformRestoreWindow(_GLFWwindow* window) { - // TODO - fprintf(stderr, "_glfwPlatformRestoreWindow not implemented yet\n"); + // TODO: also do the same for iconified. + if (window->monitor || window->wl.maximized) + { + if (window->wl.shell_surface) + wl_shell_surface_set_toplevel(window->wl.shell_surface); + + window->wl.maximized = GLFW_FALSE; + } } void _glfwPlatformMaximizeWindow(_GLFWwindow* window) { - // TODO - fprintf(stderr, "_glfwPlatformMaximizeWindow not implemented yet\n"); + if (!window->monitor && !window->wl.maximized) + { + if (window->wl.shell_surface) + { + // Let the compositor select the best output. + wl_shell_surface_set_maximized(window->wl.shell_surface, NULL); + } + window->wl.maximized = GLFW_TRUE; + } } void _glfwPlatformShowWindow(_GLFWwindow* window) @@ -592,8 +609,7 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window) int _glfwPlatformWindowMaximized(_GLFWwindow* window) { - // TODO - return GLFW_FALSE; + return window->wl.maximized; } void _glfwPlatformPollEvents(void) From 1bc4b2781e4b803c0464c27b756cbcfe4c0dd77e Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 9 Apr 2016 00:55:03 +0100 Subject: [PATCH 5/6] wayland: Implement remaining getters. --- src/wl_window.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 085863009..e4f4c6857 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -508,8 +508,8 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom) { - // TODO - fprintf(stderr, "_glfwPlatformGetWindowFrameSize not implemented yet\n"); + // TODO: will need a proper implementation once decorations are + // implemented, but for now just leave everything as 0. } void _glfwPlatformIconifyWindow(_GLFWwindow* window) @@ -592,13 +592,12 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, int _glfwPlatformWindowFocused(_GLFWwindow* window) { - // TODO - return GLFW_FALSE; + return _glfw.wl.keyboardFocus == window; } int _glfwPlatformWindowIconified(_GLFWwindow* window) { - // TODO + // TODO: move to xdg_shell, wl_shell doesn't have any iconified concept. return GLFW_FALSE; } From 247cfcdca38fc3dc7be4902681e138fff5104fe4 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 9 Apr 2016 00:47:55 +0100 Subject: [PATCH 6/6] wayland: Report a proper error on unsupported operations. --- src/wl_monitor.c | 6 ++++-- src/wl_window.c | 23 +++++++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 7c58c8f84..3b2b95fed 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -244,13 +244,15 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { // TODO - fprintf(stderr, "_glfwPlatformGetGammaRamp not implemented yet\n"); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Gamma ramp getting not supported yet"); } void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { // TODO - fprintf(stderr, "_glfwPlatformSetGammaRamp not implemented yet\n"); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Gamma ramp setting not supported yet"); } diff --git a/src/wl_window.c b/src/wl_window.c index e4f4c6857..194c0ecab 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -444,8 +444,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images) { - // TODO - fprintf(stderr, "_glfwPlatformSetWindowIcon not implemented yet\n"); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Setting window icon not supported"); } void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) @@ -514,8 +514,9 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, void _glfwPlatformIconifyWindow(_GLFWwindow* window) { - // TODO - fprintf(stderr, "_glfwPlatformIconifyWindow not implemented yet\n"); + // TODO: move to xdg_shell instead of wl_shell. + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Iconify window not supported"); } void _glfwPlatformRestoreWindow(_GLFWwindow* window) @@ -565,8 +566,8 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformFocusWindow(_GLFWwindow* window) { - // TODO - fprintf(stderr, "_glfwPlatformFocusWindow not implemented yet\n"); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Focusing a window requires user interaction"); } void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, @@ -677,7 +678,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, if (fd < 0) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Creating a buffer file for %d B failed: %m\n", + "Wayland: Creating a buffer file for %d B failed: %m", length); return GLFW_FALSE; } @@ -686,7 +687,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, if (data == MAP_FAILED) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Cursor mmap failed: %m\n"); + "Wayland: Cursor mmap failed: %m"); close(fd); return GLFW_FALSE; } @@ -925,13 +926,15 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { // TODO - fprintf(stderr, "_glfwPlatformSetClipboardString not implemented yet\n"); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Clipboard setting not implemented yet"); } const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) { // TODO - fprintf(stderr, "_glfwPlatformGetClipboardString not implemented yet\n"); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Clipboard getting not implemented yet"); return NULL; }