Wayland: Add support for arbitrary fullscreen size

This makes fullscreen glfwCreateWindow() and glfwSetWindowMonitor()
obey the requested width and height parameters when the compositor
supports the wp_viewporter protocol.  The previous behaviour is kept
when this protocol isn’t supported.
This commit is contained in:
Emmanuel Gil Peyrot 2018-05-20 15:08:13 +02:00
parent 5595fa3ae6
commit 74483142b9
4 changed files with 113 additions and 34 deletions

View File

@ -183,18 +183,17 @@ static void pointerHandleMotion(void* data,
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
return; return;
else
{ window->wl.cursorPosX = wl_fixed_to_double(sx) * window->wl.cursorScale;
window->wl.cursorPosX = wl_fixed_to_double(sx); window->wl.cursorPosY = wl_fixed_to_double(sy) * window->wl.cursorScale;
window->wl.cursorPosY = wl_fixed_to_double(sy); printf("cursor: %fx%f @%f\n", window->wl.cursorPosX, window->wl.cursorPosY, window->wl.cursorScale);
}
switch (window->wl.decorations.focus) switch (window->wl.decorations.focus)
{ {
case mainWindow: case mainWindow:
_glfwInputCursorPos(window, _glfwInputCursorPos(window,
wl_fixed_to_double(sx), window->wl.cursorPosX,
wl_fixed_to_double(sy)); window->wl.cursorPosY);
return; return;
case topDecoration: case topDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)

View File

@ -191,6 +191,7 @@ typedef struct _GLFWwindowWayland
_GLFWcursor* currentCursor; _GLFWcursor* currentCursor;
double cursorPosX, cursorPosY; double cursorPosX, cursorPosY;
double cursorScale;
char* title; char* title;
@ -218,6 +219,8 @@ typedef struct _GLFWwindowWayland
int focus; int focus;
} decorations; } decorations;
struct wp_viewport* viewport;
} _GLFWwindowWayland; } _GLFWwindowWayland;
// Wayland-specific global data // Wayland-specific global data

View File

@ -46,6 +46,20 @@ static void shellSurfaceHandlePing(void* data,
wl_shell_surface_pong(shellSurface, serial); wl_shell_surface_pong(shellSurface, serial);
} }
static void resizeWindow(_GLFWwindow* window);
static void computeFullscreenSize(_GLFWwindow* window, float* width, float* height)
{
float aspectRatio = *width / *height;
float targetRatio = (float)window->wl.width / (float)window->wl.height;
if (aspectRatio < targetRatio)
*height = *width / targetRatio;
else if (aspectRatio > targetRatio)
*width = *height * targetRatio;
window->wl.cursorScale = (float)window->wl.width / *width;
}
static void shellSurfaceHandleConfigure(void* data, static void shellSurfaceHandleConfigure(void* data,
struct wl_shell_surface* shellSurface, struct wl_shell_surface* shellSurface,
uint32_t edges, uint32_t edges,
@ -56,6 +70,7 @@ static void shellSurfaceHandleConfigure(void* data,
float aspectRatio; float aspectRatio;
float targetRatio; float targetRatio;
printf("before: configure=%dx%d window->wl=%dx%d videoMode=%dx%d\n", width, height, window->wl.width, window->wl.height, window->videoMode.width, window->videoMode.height);
if (!window->monitor) if (!window->monitor)
{ {
if (_glfw.wl.viewporter && window->decorated) if (_glfw.wl.viewporter && window->decorated)
@ -87,10 +102,23 @@ static void shellSurfaceHandleConfigure(void* data,
height = window->minheight; height = window->minheight;
else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight) else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight)
height = window->maxheight; height = window->maxheight;
window->wl.cursorScale = 1.0;
window->wl.width = width;
window->wl.height = height;
resizeWindow(window);
}
else if (window->wl.viewport)
{
float floatWidth = width, floatHeight = height;
computeFullscreenSize(window, &floatWidth, &floatHeight);
width = floatWidth;
height = floatHeight;
wp_viewport_set_destination(window->wl.viewport, width, height);
} }
printf("after: configure=%dx%d window->wl=%dx%d videoMode=%dx%d\n", width, height, window->wl.width, window->wl.height, window->videoMode.width, window->videoMode.height);
_glfwInputWindowSize(window, width, height); _glfwInputWindowSize(window, width, height);
_glfwPlatformSetWindowSize(window, width, height);
_glfwInputWindowDamage(window); _glfwInputWindowDamage(window);
} }
@ -355,9 +383,30 @@ static void setOpaqueRegion(_GLFWwindow* window)
static void resizeWindow(_GLFWwindow* window) static void resizeWindow(_GLFWwindow* window)
{ {
int width = window->wl.width;
int height = window->wl.height;
int scale = window->wl.scale; int scale = window->wl.scale;
int scaledWidth = window->wl.width * scale;
int scaledHeight = window->wl.height * scale; printf("resizeWindow\n");
if (window->monitor)
{
if (window->wl.xdg.toplevel)
{
xdg_toplevel_set_fullscreen(
window->wl.xdg.toplevel,
window->monitor->wl.output);
}
else if (window->wl.shellSurface)
{
wl_shell_surface_set_fullscreen(
window->wl.shellSurface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0, window->monitor->wl.output);
}
}
int scaledWidth = width * scale;
int scaledHeight = height * scale;
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0); wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
if (!window->wl.transparent) if (!window->wl.transparent)
setOpaqueRegion(window); setOpaqueRegion(window);
@ -369,26 +418,26 @@ static void resizeWindow(_GLFWwindow* window)
// Top decoration. // Top decoration.
wp_viewport_set_destination(window->wl.decorations.top.viewport, wp_viewport_set_destination(window->wl.decorations.top.viewport,
window->wl.width, _GLFW_DECORATION_TOP); width, _GLFW_DECORATION_TOP);
wl_surface_commit(window->wl.decorations.top.surface); wl_surface_commit(window->wl.decorations.top.surface);
// Left decoration. // Left decoration.
wp_viewport_set_destination(window->wl.decorations.left.viewport, wp_viewport_set_destination(window->wl.decorations.left.viewport,
_GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP); _GLFW_DECORATION_WIDTH, height + _GLFW_DECORATION_TOP);
wl_surface_commit(window->wl.decorations.left.surface); wl_surface_commit(window->wl.decorations.left.surface);
// Right decoration. // Right decoration.
wl_subsurface_set_position(window->wl.decorations.right.subsurface, wl_subsurface_set_position(window->wl.decorations.right.subsurface,
window->wl.width, -_GLFW_DECORATION_TOP); width, -_GLFW_DECORATION_TOP);
wp_viewport_set_destination(window->wl.decorations.right.viewport, wp_viewport_set_destination(window->wl.decorations.right.viewport,
_GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP); _GLFW_DECORATION_WIDTH, height + _GLFW_DECORATION_TOP);
wl_surface_commit(window->wl.decorations.right.surface); wl_surface_commit(window->wl.decorations.right.surface);
// Bottom decoration. // Bottom decoration.
wl_subsurface_set_position(window->wl.decorations.bottom.subsurface, wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,
-_GLFW_DECORATION_WIDTH, window->wl.height); -_GLFW_DECORATION_WIDTH, height);
wp_viewport_set_destination(window->wl.decorations.bottom.viewport, wp_viewport_set_destination(window->wl.decorations.bottom.viewport,
window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH); width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
wl_surface_commit(window->wl.decorations.bottom.surface); wl_surface_commit(window->wl.decorations.bottom.surface);
} }
@ -398,6 +447,7 @@ static void checkScaleChange(_GLFWwindow* window)
int i; int i;
int monitorScale; int monitorScale;
printf("checkScaleChange\n");
// Check if we will be able to set the buffer scale or not. // Check if we will be able to set the buffer scale or not.
if (_glfw.wl.compositorVersion < 3) if (_glfw.wl.compositorVersion < 3)
return; return;
@ -513,6 +563,7 @@ static GLFWbool createSurface(_GLFWwindow* window,
} }
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
int width, int height,
int refreshRate) int refreshRate)
{ {
if (window->wl.xdg.toplevel) if (window->wl.xdg.toplevel)
@ -532,9 +583,13 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
setIdleInhibitor(window, GLFW_TRUE); setIdleInhibitor(window, GLFW_TRUE);
if (!window->wl.decorations.serverSide) if (!window->wl.decorations.serverSide)
destroyDecorations(window); destroyDecorations(window);
if (_glfw.wl.viewporter) {
window->wl.viewport =
wp_viewporter_get_viewport(_glfw.wl.viewporter, window->wl.surface);
}
} }
static GLFWbool createShellSurface(_GLFWwindow* window) static GLFWbool createShellSurface(_GLFWwindow* window, int width, int height)
{ {
if (!_glfw.wl.shell) if (!_glfw.wl.shell)
{ {
@ -561,7 +616,7 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
{ {
setFullscreen(window, window->monitor, 0); setFullscreen(window, window->monitor, width, height, 0);
} }
else if (window->wl.maximized) else if (window->wl.maximized)
{ {
@ -615,21 +670,39 @@ static void xdgToplevelHandleConfigure(void* data,
if (width != 0 && height != 0) if (width != 0 && height != 0)
{ {
if (!maximized && !fullscreen) if (fullscreen)
{ {
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) if (window->wl.viewport)
{ {
aspectRatio = (float)width / (float)height; aspectRatio = (float)width / (float)height;
targetRatio = (float)window->numer / (float)window->denom; targetRatio = (float)window->wl.width / (float)window->wl.height;
if (aspectRatio < targetRatio) if (aspectRatio < targetRatio)
height = width / targetRatio; height = width / targetRatio;
else if (aspectRatio > targetRatio) else if (aspectRatio > targetRatio)
width = height * targetRatio; width = height * targetRatio;
wp_viewport_set_destination(window->wl.viewport, width, height);
width = window->wl.width;
height = window->wl.height;
}
}
else
{
if (!maximized)
{
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;
}
} }
} }
_glfwInputWindowSize(window, width, height); _glfwInputWindowSize(window, width, height);
_glfwPlatformSetWindowSize(window, width, height);
_glfwInputWindowDamage(window); _glfwInputWindowDamage(window);
} }
@ -683,7 +756,7 @@ static void setXdgDecorations(_GLFWwindow* window)
} }
} }
static GLFWbool createXdgSurface(_GLFWwindow* window) static GLFWbool createXdgSurface(_GLFWwindow* window, int width, int height)
{ {
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase, window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
window->wl.surface); window->wl.surface);
@ -722,9 +795,7 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
{ {
xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, setFullscreen(window, window->monitor, width, height, 0);
window->monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE);
} }
else if (window->wl.maximized) else if (window->wl.maximized)
{ {
@ -937,12 +1008,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{ {
if (_glfw.wl.wmBase) if (_glfw.wl.wmBase)
{ {
if (!createXdgSurface(window)) if (!createXdgSurface(window, wndconfig->width, wndconfig->height))
return GLFW_FALSE; return GLFW_FALSE;
} }
else else
{ {
if (!createShellSurface(window)) if (!createShellSurface(window, wndconfig->width, wndconfig->height))
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -1055,6 +1126,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{ {
printf("SetWindowSize\n");
window->wl.width = width; window->wl.width = width;
window->wl.height = height; window->wl.height = height;
resizeWindow(window); resizeWindow(window);
@ -1178,9 +1250,9 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
if (!window->wl.visible) if (!window->wl.visible)
{ {
if (_glfw.wl.wmBase) if (_glfw.wl.wmBase)
createXdgSurface(window); createXdgSurface(window, window->wl.width, window->wl.height);
else if (!window->wl.shellSurface) else if (!window->wl.shellSurface)
createShellSurface(window); createShellSurface(window, window->wl.width, window->wl.height);
window->wl.visible = GLFW_TRUE; window->wl.visible = GLFW_TRUE;
} }
} }
@ -1223,7 +1295,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
{ {
if (monitor) if (monitor)
{ {
setFullscreen(window, monitor, refreshRate); setFullscreen(window, monitor, width, height, refreshRate);
} }
else else
{ {
@ -1232,8 +1304,10 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else if (window->wl.shellSurface) else if (window->wl.shellSurface)
wl_shell_surface_set_toplevel(window->wl.shellSurface); wl_shell_surface_set_toplevel(window->wl.shellSurface);
setIdleInhibitor(window, GLFW_FALSE); setIdleInhibitor(window, GLFW_FALSE);
if (!_glfw.wl.decorationManager) if (!_glfw.wl.decorationManager && window->decorated)
createDecorations(window); createDecorations(window);
if (window->wl.viewport)
wp_viewport_destroy(window->wl.viewport);
} }
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
} }

View File

@ -188,8 +188,8 @@ int main(int argc, char** argv)
monitor = glfwGetPrimaryMonitor(); monitor = glfwGetPrimaryMonitor();
mode = glfwGetVideoMode(monitor); mode = glfwGetVideoMode(monitor);
width = mode->width; width = 640;
height = mode->height; height = 480;
} }
else else
{ {
@ -230,6 +230,9 @@ int main(int argc, char** argv)
glfwPollEvents(); glfwPollEvents();
sample_input(window); sample_input(window);
if (frame_count == 30)
glfwSetWindowSize(window, 640, rand() % 1200);
glfwGetWindowSize(window, &width, &height); glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height); area = nk_rect(0.f, 0.f, (float) width, (float) height);