diff --git a/src/siwin/build_utils/tasks.nim b/src/siwin/build_utils/tasks.nim index 4c64749..66931ca 100644 --- a/src/siwin/build_utils/tasks.nim +++ b/src/siwin/build_utils/tasks.nim @@ -61,7 +61,7 @@ task installTestDeps, "install test dependencies": const testTargets = [ "t_opengl_es", "t_opengl", "t_swrendering", "t_multiwindow", "t_vulkan", - "t_offscreen", "t_macos_live_resize", "t_event_loop", + "t_offscreen", "t_macos_live_resize", "t_event_loop", "t_x11_size_hints", ] proc shouldSkipTarget(target, args: string): bool = diff --git a/src/siwin/offscreen.nim b/src/siwin/offscreen.nim index abb28d7..37356d9 100644 --- a/src/siwin/offscreen.nim +++ b/src/siwin/offscreen.nim @@ -5,6 +5,7 @@ when not siwin_use_lib: when defined(android): import ./platforms/android/window elif defined(linux) or defined(bsd): + import ./platforms/x11/window as x11Window import ./platforms/x11/[offscreen, siwinGlobals] import ./platforms/wayland/[siwinGlobals] elif defined(windows): diff --git a/src/siwin/platforms/x11/window.nim b/src/siwin/platforms/x11/window.nim index d7715f4..dd4eb32 100644 --- a/src/siwin/platforms/x11/window.nim +++ b/src/siwin/platforms/x11/window.nim @@ -958,14 +958,32 @@ method `visible=`*(window: WindowX11, v: bool) = discard window.globals.display.XUnmapWindow(window.handle) +proc applyMinSizeHint*(hints: var XSizeHints, size: IVec2) = + if size.x <= 0 or size.y <= 0: + hints.flags = hints.flags and not PMinSize + else: + hints.flags = hints.flags or PMinSize + hints.minWidth = size.x + hints.minHeight = size.y + + +proc applyMaxSizeHint*(hints: var XSizeHints, size: IVec2) = + if size.x <= 0 or size.y <= 0: + hints.flags = hints.flags and not PMaxSize + else: + hints.flags = hints.flags or PMaxSize + hints.maxWidth = size.x + hints.maxHeight = size.y + + method `resizable=`*(window: WindowX11, v: bool) = window.m_resizable = v let size = window.size var hints: XSizeHints discard window.globals.display.XGetNormalHints(window.handle, hints.addr) - if v: hints.flags = hints.flags and not 0b110000 - else: hints.flags = hints.flags or 0b110000 + if v: hints.flags = hints.flags and not (PMinSize or PMaxSize) + else: hints.flags = hints.flags or PMinSize or PMaxSize hints.minWidth = size.x hints.minHeight = size.y hints.maxWidth = size.x @@ -977,9 +995,7 @@ method `minSize=`*(window: WindowX11, v: IVec2) = window.m_minSize = v var hints: XSizeHints discard window.globals.display.XGetNormalHints(window.handle, hints.addr) - hints.flags = hints.flags or 0b010000 - hints.minWidth = v.x - hints.minHeight = v.y + hints.applyMinSizeHint(v) discard window.globals.display.XSetNormalHints(window.handle, hints.addr) @@ -987,9 +1003,7 @@ method `maxSize=`*(window: WindowX11, v: IVec2) = window.m_maxSize = v var hints: XSizeHints discard window.globals.display.XGetNormalHints(window.handle, hints.addr) - hints.flags = hints.flags or 0b100000 - hints.maxWidth = v.x - hints.maxHeight = v.y + hints.applyMaxSizeHint(v) discard window.globals.display.XSetNormalHints(window.handle, hints.addr) diff --git a/tests/t_event_loop.nim b/tests/t_event_loop.nim index aa8d52a..73f4829 100644 --- a/tests/t_event_loop.nim +++ b/tests/t_event_loop.nim @@ -1,6 +1,6 @@ import std/[assertions, times] -import siwin/platforms/any/eventLoop +import siwin/platforms/any/timeutils const diff --git a/tests/t_x11_size_hints.nim b/tests/t_x11_size_hints.nim new file mode 100644 index 0000000..4c02c4e --- /dev/null +++ b/tests/t_x11_size_hints.nim @@ -0,0 +1,57 @@ +when defined(linux) or defined(bsd): + import unittest + + import pkg/vmath + import x11/xutil + import siwin/platforms/x11/window + + suite "X11 window size hints": + test "positive minimum size sets only the minimum constraint": + var hints: XSizeHints + hints.flags = PSize + + hints.applyMinSizeHint(ivec2(320, 180)) + + check (hints.flags and PSize) != 0 + check (hints.flags and PMinSize) != 0 + check (hints.flags and PMaxSize) == 0 + check hints.minWidth == 320 + check hints.minHeight == 180 + + test "unbounded minimum size clears the minimum constraint": + var hints: XSizeHints + hints.flags = PSize or PMinSize + hints.minWidth = 320 + hints.minHeight = 180 + + hints.applyMinSizeHint(ivec2(320, 0)) + + check (hints.flags and PSize) != 0 + check (hints.flags and PMinSize) == 0 + check hints.minWidth == 320 + check hints.minHeight == 180 + + test "positive maximum size sets only the maximum constraint": + var hints: XSizeHints + hints.flags = PSize + + hints.applyMaxSizeHint(ivec2(1920, 1080)) + + check (hints.flags and PSize) != 0 + check (hints.flags and PMinSize) == 0 + check (hints.flags and PMaxSize) != 0 + check hints.maxWidth == 1920 + check hints.maxHeight == 1080 + + test "unbounded maximum size clears the maximum constraint": + var hints: XSizeHints + hints.flags = PSize or PMaxSize + hints.maxWidth = 1920 + hints.maxHeight = 1080 + + hints.applyMaxSizeHint(ivec2(0, 1080)) + + check (hints.flags and PSize) != 0 + check (hints.flags and PMaxSize) == 0 + check hints.maxWidth == 1920 + check hints.maxHeight == 1080