Commit 06479ba5 authored by Emmanuel Gil Peyrot's avatar Emmanuel Gil Peyrot Committed by Jonas Ådahl
Browse files

Wayland: Implement HiDPI support

Windows now keep track of the monitors they are on, so we can calculate
the best scaling factor for them, by using the maximum of each of the
monitors.

The compositor scales down the buffer automatically when it is on a
lower density monitor, instead of the previous way where it was scaling
up the buffer on higher density monitors, which makes the application
look much better on those ones.
parent ecd04539
......@@ -36,6 +36,11 @@
#include <wayland-cursor.h>
static inline int min(int n1, int n2)
{
return n1 < n2 ? n1 : n2;
}
static void pointerHandleEnter(void* data,
struct wl_pointer* pointer,
uint32_t serial,
......@@ -381,7 +386,8 @@ static void registryHandleGlobal(void* data,
if (strcmp(interface, "wl_compositor") == 0)
{
_glfw.wl.compositor =
wl_registry_bind(registry, name, &wl_compositor_interface, 1);
wl_registry_bind(registry, name, &wl_compositor_interface,
min(3, version));
}
else if (strcmp(interface, "wl_shm") == 0)
{
......
......@@ -97,6 +97,9 @@ static void scale(void* data,
struct wl_output* output,
int32_t factor)
{
struct _GLFWmonitor *monitor = data;
monitor->wl.scale = factor;
}
static const struct wl_output_listener output_listener = {
......@@ -142,6 +145,8 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
monitor->wl.modes = calloc(4, sizeof(_GLFWvidmodeWayland));
monitor->wl.modesSize = 4;
monitor->wl.scale = 1;
monitor->wl.output = output;
wl_output_add_listener(output, &output_listener, monitor);
......
......@@ -65,8 +65,16 @@ typedef struct _GLFWwindowWayland
struct wl_egl_window* native;
struct wl_shell_surface* shell_surface;
struct wl_callback* callback;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
// We need to track the monitors the window spans on to calculate the
// optimal scaling factor.
int scale;
_GLFWmonitor** monitors;
int monitorsCount;
int monitorsSize;
} _GLFWwindowWayland;
......@@ -123,7 +131,7 @@ typedef struct _GLFWmonitorWayland
int x;
int y;
int scale;
} _GLFWmonitorWayland;
......
......@@ -72,6 +72,79 @@ static const struct wl_shell_surface_listener shellSurfaceListener = {
handlePopupDone
};
static void checkScaleChange(_GLFWwindow* window)
{
int scaledWidth, scaledHeight;
int scale = 1;
int i;
int monitorScale;
// Get the scale factor from the highest scale monitor.
for (i = 0; i < window->wl.monitorsCount; ++i)
{
monitorScale = window->wl.monitors[i]->wl.scale;
if (scale < monitorScale)
scale = monitorScale;
}
// Only change the framebuffer size if the scale changed.
if (scale != window->wl.scale)
{
window->wl.scale = scale;
scaledWidth = window->wl.width * scale;
scaledHeight = window->wl.height * scale;
wl_surface_set_buffer_scale(window->wl.surface, scale);
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
}
}
static void handleEnter(void *data,
struct wl_surface *surface,
struct wl_output *output)
{
_GLFWwindow* window = data;
_GLFWmonitor* monitor = wl_output_get_user_data(output);
if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)
{
++window->wl.monitorsSize;
window->wl.monitors =
realloc(window->wl.monitors,
window->wl.monitorsSize * sizeof(_GLFWmonitor*));
}
window->wl.monitors[window->wl.monitorsCount++] = monitor;
checkScaleChange(window);
}
static void handleLeave(void *data,
struct wl_surface *surface,
struct wl_output *output)
{
_GLFWwindow* window = data;
_GLFWmonitor* monitor = wl_output_get_user_data(output);
GLFWbool found;
int i;
for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i)
{
if (monitor == window->wl.monitors[i])
found = GLFW_TRUE;
if (found)
window->wl.monitors[i] = window->wl.monitors[i + 1];
}
window->wl.monitors[--window->wl.monitorsCount] = NULL;
checkScaleChange(window);
}
static const struct wl_surface_listener surfaceListener = {
handleEnter,
handleLeave
};
static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
......@@ -79,6 +152,10 @@ static GLFWbool createSurface(_GLFWwindow* window,
if (!window->wl.surface)
return GLFW_FALSE;
wl_surface_add_listener(window->wl.surface,
&surfaceListener,
window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.native = wl_egl_window_create(window->wl.surface,
......@@ -98,6 +175,7 @@ static GLFWbool createSurface(_GLFWwindow* window,
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
return GLFW_TRUE;
}
......@@ -262,6 +340,10 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
window->wl.currentCursor = NULL;
window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
window->wl.monitorsCount = 0;
window->wl.monitorsSize = 1;
return GLFW_TRUE;
}
......@@ -288,6 +370,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->wl.surface)
wl_surface_destroy(window->wl.surface);
free(window->wl.monitors);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
......@@ -322,9 +406,12 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
wl_egl_window_resize(window->wl.native, width, height, 0, 0);
int scaledWidth = width * window->wl.scale;
int scaledHeight = height * window->wl.scale;
window->wl.width = width;
window->wl.height = height;
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
......@@ -344,6 +431,8 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
_glfwPlatformGetWindowSize(window, width, height);
*width *= window->wl.scale;
*height *= window->wl.scale;
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment