Improve maximize behaviour on multi-monitor setups

This commit is contained in:
lm 2025-10-19 18:14:40 +02:00
parent 27c0e55711
commit 50b9aa723c
1 changed files with 46 additions and 16 deletions

View File

@ -446,11 +446,6 @@ class UIBuilderMixin:
max_btn.bind("<Leave>", lambda _e: max_btn.configure(bg=bar_bg))
self._max_button = max_btn
min_btn = tk.Button(title_bar, text="", command=self._minimize_window, **btn_kwargs)
min_btn.pack(side=tk.RIGHT, padx=0, pady=4)
min_btn.bind("<Enter>", lambda _e: min_btn.configure(bg="#2c2c32"))
min_btn.bind("<Leave>", lambda _e: min_btn.configure(bg=bar_bg))
for widget in (title_bar, title_label):
widget.bind("<ButtonPress-1>", self._start_window_drag)
widget.bind("<B1-Motion>", self._perform_window_drag)
@ -491,11 +486,54 @@ class UIBuilderMixin:
except Exception:
pass
def _monitor_work_area(self) -> tuple[int, int, int, int] | None:
try:
import ctypes
from ctypes import wintypes
user32 = ctypes.windll.user32 # type: ignore[attr-defined]
root_x = self.root.winfo_rootx()
root_y = self.root.winfo_rooty()
width = max(self.root.winfo_width(), 1)
height = max(self.root.winfo_height(), 1)
center_x = root_x + width // 2
center_y = root_y + height // 2
class MONITORINFO(ctypes.Structure):
_fields_ = [
("cbSize", wintypes.DWORD),
("rcMonitor", wintypes.RECT),
("rcWork", wintypes.RECT),
("dwFlags", wintypes.DWORD),
]
monitor = user32.MonitorFromPoint(
wintypes.POINT(center_x, center_y), 2 # MONITOR_DEFAULTTONEAREST
)
info = MONITORINFO()
info.cbSize = ctypes.sizeof(MONITORINFO)
if not user32.GetMonitorInfoW(monitor, ctypes.byref(info)):
return None
work = info.rcWork
return work.left, work.top, work.right, work.bottom
except Exception:
return None
def _maximize_window(self) -> None:
self._remember_window_geometry()
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
self.root.geometry(f"{screen_width}x{screen_height}+0+0")
work_area = self._monitor_work_area()
if work_area is None:
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
left = 0
top = 0
width = screen_width
height = screen_height
else:
left, top, right, bottom = work_area
width = max(1, right - left)
height = max(1, bottom - top)
self.root.geometry(f"{width}x{height}+{left}+{top}")
self._is_maximized = True
self._update_maximize_button()
@ -520,14 +558,6 @@ class UIBuilderMixin:
else:
self._restore_window()
def _minimize_window(self) -> None:
try:
self.root.overrideredirect(False)
self.root.iconify()
self.root.after(50, lambda: self.root.overrideredirect(True))
except Exception:
pass
def _update_maximize_button(self) -> None:
button = getattr(self, "_max_button", None)
if button is None: