Skip to content

Commit 5f2a76a

Browse files
authored
Merge pull request #445 from Tom94/windows-title-bar
feat(imageviewer): respect window frame when resizing if possible
2 parents 77279be + 2d63930 commit 5f2a76a

3 files changed

Lines changed: 52 additions & 23 deletions

File tree

include/tev/Common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,13 @@ std::string errorString(int errorId);
613613
fs::path homeDirectory();
614614
fs::path runtimeDirectory();
615615

616+
struct FramePadding {
617+
nanogui::Vector2i topLeft;
618+
nanogui::Vector2i bottomRight;
619+
};
620+
621+
FramePadding framePadding(GLFWwindow* window);
622+
616623
void toggleConsole();
617624

618625
bool shuttingDown();

src/Common.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,21 @@ fs::path runtimeDirectory() {
450450
#endif
451451
}
452452

453+
FramePadding framePadding(GLFWwindow* window) {
454+
FramePadding result;
455+
#ifdef _WIN32
456+
// glfwGetWindowFrameSize is a bit too conservative on Windows -- it includes CXPADDEDBORDER on all sides -- which looks like quite a
457+
// lot of empty space to the sides and bottom of the window. Therefore, we use a bit of custom logic here that still allows resizing the
458+
// window from all sides (exposes the frame part) while making space tighter.
459+
const Vector2i border = {GetSystemMetrics(SM_CXSIZEFRAME), GetSystemMetrics(SM_CYSIZEFRAME)};
460+
result.topLeft = result.bottomRight = border;
461+
result.topLeft.y() += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXPADDEDBORDER);
462+
#else
463+
glfwGetWindowFrameSize(window, &result.topLeft.x(), &result.topLeft.y(), &result.bottomRight.x(), &result.bottomRight.y());
464+
#endif
465+
return result;
466+
}
467+
453468
void toggleConsole() {
454469
#ifdef _WIN32
455470
HWND console = GetConsoleWindow();

src/ImageViewer.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,19 @@ ImageViewer::ImageViewer(
116116
monitorMax = max(monitorMax, monitorPos + monitorSize);
117117
}
118118

119+
const auto padding = framePadding(m_glfw_window);
120+
monitorMin += padding.topLeft;
121+
monitorMax -= padding.bottomRight;
122+
119123
mMinWindowPos = monitorMin;
120124
mMaxWindowSize = min(mMaxWindowSize, Vector2f{max(monitorMax - monitorMin, Vector2i{1024, 800})});
125+
126+
#if defined(_WIN32) || defined(__linux__) || defined(EMSCRIPTEN)
127+
mMinWindowPos = mMinWindowPos / pixel_ratio();
128+
mMaxWindowSize = mMaxWindowSize / pixel_ratio();
129+
#endif
130+
131+
tlog::debug("Initial monitor: pos={} size={}", mMinWindowPos, mMaxWindowSize);
121132
}
122133
}
123134

@@ -2170,19 +2181,7 @@ void ImageViewer::resizeToFit(Vector2f targetSize) {
21702181
targetSize = max(Vector2f{m_size}, targetSize);
21712182
// For sanity, don't make us larger than 8192x8192 to ensure that we don't break any texture size limitations of the user's GPU.
21722183

2173-
auto maxSize = mMaxWindowSize;
2174-
2175-
const Vector2f padding = {
2176-
#ifdef _WIN32
2177-
2
2178-
#else
2179-
0
2180-
#endif
2181-
};
2182-
2183-
maxSize -= 2 * padding;
2184-
2185-
targetSize = min(targetSize, maxSize);
2184+
targetSize = min(targetSize, mMaxWindowSize);
21862185
if (targetSize == m_size) {
21872186
return;
21882187
}
@@ -2195,15 +2194,19 @@ void ImageViewer::resizeToFit(Vector2f targetSize) {
21952194
move_window(-sizeDiff / 2);
21962195

21972196
// Ensure the window does not go off-screen by clamping its position. This does not work on Wayland, because Wayland does not allow
2198-
// windows to control their own position. On Windows, we add additional padding because, otherwise, moving the mouse to the edge of the
2199-
// screen does not allow the user to resize the window anymore.
2197+
// windows to control their own position.
22002198
if (glfwGetPlatform() != GLFW_PLATFORM_WAYLAND) {
2201-
const auto minWindowPos = Vector2i{mMinWindowPos + padding};
2202-
const auto maxWindowPos = Vector2i{mMinWindowPos + maxSize - targetSize + padding};
2199+
auto minWindowPos = mMinWindowPos;
2200+
auto maxWindowPos = mMinWindowPos + mMaxWindowSize - targetSize;
2201+
2202+
#if defined(_WIN32) || defined(__linux__) || defined(EMSCRIPTEN)
2203+
minWindowPos *= pixel_ratio();
2204+
maxWindowPos *= pixel_ratio();
2205+
#endif
22032206

22042207
Vector2i pos;
22052208
glfwGetWindowPos(m_glfw_window, &pos.x(), &pos.y());
2206-
pos = min(max(pos, minWindowPos), maxWindowPos);
2209+
pos = min(max(pos, Vector2i{minWindowPos}), Vector2i{maxWindowPos});
22072210
glfwSetWindowPos(m_glfw_window, pos.x(), pos.y());
22082211
}
22092212

@@ -2986,12 +2989,16 @@ shared_ptr<Image> ImageViewer::imageByName(string_view imageName) {
29862989

29872990
void ImageViewer::updateCurrentMonitorSize() {
29882991
if (GLFWmonitor* monitor = glfwGetWindowCurrentMonitor(m_glfw_window)) {
2989-
Vector2i pos, size;
2992+
Vector2i pos{0}, size{0};
29902993
glfwGetMonitorWorkarea(monitor, &pos.x(), &pos.y(), &size.x(), &size.y());
29912994
if (size == Vector2i{0, 0}) {
29922995
return;
29932996
}
29942997

2998+
const auto padding = framePadding(m_glfw_window);
2999+
pos += padding.topLeft;
3000+
size -= padding.topLeft + padding.bottomRight;
3001+
29953002
// On some systems (notably Hyprland and some other tiling window managers / compositors), windows are always flagged as
29963003
// maximized, even if they are technically not, to get them to play nicely with decorations. In the following, we detect
29973004
// such cases (only after a current monitor was detected to give enough time for the compositor to set up the window) and
@@ -3004,10 +3011,10 @@ void ImageViewer::updateCurrentMonitorSize() {
30043011
auto posf = Vector2f{pos};
30053012
auto sizef = Vector2f{size};
30063013

3007-
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
3008-
posf = posf / pixel_ratio();
3009-
sizef = sizef / pixel_ratio();
3010-
}
3014+
#if defined(_WIN32) || defined(__linux__) || defined(EMSCRIPTEN)
3015+
posf = posf / pixel_ratio();
3016+
sizef = sizef / pixel_ratio();
3017+
#endif
30113018

30123019
if (posf == mMinWindowPos && sizef == mMaxWindowSize) {
30133020
return;

0 commit comments

Comments
 (0)