From 3a7ff0d179cb48a92e057e3ccd83cb13fdefdbb3 Mon Sep 17 00:00:00 2001 From: Alexis Howells Date: Fri, 19 Apr 2024 21:47:14 +0100 Subject: [PATCH] Consider transform when calculating monitor size (#88) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using a rotated monitor, the width value is incorrect and most of the widgets are off screen. When taking the transform into account (swapping width and height when 90/270° rotation is applied) the width is correct. --- src/Wayland.cpp | 22 ++++++++++++++++++++-- src/Wayland.h | 1 + src/Window.cpp | 22 ++++++++++++++++++++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/Wayland.cpp b/src/Wayland.cpp index dcb66ae..cb15b2e 100644 --- a/src/Wayland.cpp +++ b/src/Wayland.cpp @@ -179,7 +179,25 @@ namespace Wayland // Output Callbacks // Very bloated, indeed - static void OnOutputGeometry(void*, wl_output*, int32_t, int32_t, int32_t, int32_t, int32_t, const char*, const char*, int32_t) {} + static void OnOutputGeometry(void*, wl_output* output, int32_t, int32_t, int32_t, int32_t, int32_t, const char*, const char*, int32_t transform) + { + auto it = monitors.find(output); + ASSERT(it != monitors.end(), "Error: OnOutputGeometry called on unknown monitor"); + switch (transform) + { + case WL_OUTPUT_TRANSFORM_NORMAL: + case WL_OUTPUT_TRANSFORM_FLIPPED: it->second.rotation = 0; break; + + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: it->second.rotation = 90; break; + + case WL_OUTPUT_TRANSFORM_180: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: it->second.rotation = 180; break; + + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: it->second.rotation = 270; break; + } + } static void OnOutputMode(void*, wl_output* output, uint32_t, int32_t width, int32_t height, int32_t) { auto it = monitors.find(output); @@ -211,7 +229,7 @@ namespace Wayland if (strcmp(interface, "wl_output") == 0) { wl_output* output = (wl_output*)wl_registry_bind(registry, name, &wl_output_interface, 4); - Monitor mon = Monitor{"", name, 0, 0, 0, nullptr, (uint32_t)monitors.size()}; + Monitor mon = Monitor{"", name, 0, 0, 0, 0, nullptr, (uint32_t)monitors.size()}; monitors.emplace(output, mon); LOG("Wayland: Register at ID " << mon.ID); diff --git a/src/Wayland.h b/src/Wayland.h index 7a594b8..009618e 100644 --- a/src/Wayland.h +++ b/src/Wayland.h @@ -13,6 +13,7 @@ namespace Wayland int32_t width; int32_t height; int32_t scale; // TODO: Handle fractional scaling + uint32_t rotation; zext_workspace_group_handle_v1* workspaceGroup; // The Gdk monitor index. This is only a hacky approximation, since there is no way to get the wl_output from a GdkMonitor uint32_t ID; diff --git a/src/Window.cpp b/src/Window.cpp index 50120be..65d7f8d 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -246,7 +246,16 @@ int Window::GetWidth() const const Wayland::Monitor* mon = Wayland::FindMonitorByName(m_MonitorName); ASSERT(mon, "Window: Couldn't find monitor"); - return mon->width / mon->scale; + + int viewedWidth = mon->width; + + // A 90/270 rotation should use the height for the viewed width + switch (mon->rotation) + { + case 90: + case 270: viewedWidth = mon->height; break; + } + return viewedWidth / mon->scale; } int Window::GetHeight() const @@ -257,7 +266,16 @@ int Window::GetHeight() const const Wayland::Monitor* mon = Wayland::FindMonitorByName(m_MonitorName); ASSERT(mon, "Window: Couldn't find monitor"); - return mon->height / mon->scale; + + int viewedHeight = mon->height; + + // A 90/270 rotation should use the width for the viewed height + switch (mon->rotation) + { + case 90: + case 270: viewedHeight = mon->width; break; + } + return viewedHeight / mon->scale; } void Window::MonitorAdded(GdkDisplay*, GdkMonitor*)