Improve maximize behaviour on multi-monitor setups
This commit is contained in:
parent
27c0e55711
commit
50b9aa723c
|
|
@ -446,11 +446,6 @@ class UIBuilderMixin:
|
||||||
max_btn.bind("<Leave>", lambda _e: max_btn.configure(bg=bar_bg))
|
max_btn.bind("<Leave>", lambda _e: max_btn.configure(bg=bar_bg))
|
||||||
self._max_button = max_btn
|
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):
|
for widget in (title_bar, title_label):
|
||||||
widget.bind("<ButtonPress-1>", self._start_window_drag)
|
widget.bind("<ButtonPress-1>", self._start_window_drag)
|
||||||
widget.bind("<B1-Motion>", self._perform_window_drag)
|
widget.bind("<B1-Motion>", self._perform_window_drag)
|
||||||
|
|
@ -491,11 +486,54 @@ class UIBuilderMixin:
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
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:
|
def _maximize_window(self) -> None:
|
||||||
self._remember_window_geometry()
|
self._remember_window_geometry()
|
||||||
|
work_area = self._monitor_work_area()
|
||||||
|
if work_area is None:
|
||||||
screen_width = self.root.winfo_screenwidth()
|
screen_width = self.root.winfo_screenwidth()
|
||||||
screen_height = self.root.winfo_screenheight()
|
screen_height = self.root.winfo_screenheight()
|
||||||
self.root.geometry(f"{screen_width}x{screen_height}+0+0")
|
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._is_maximized = True
|
||||||
self._update_maximize_button()
|
self._update_maximize_button()
|
||||||
|
|
||||||
|
|
@ -520,14 +558,6 @@ class UIBuilderMixin:
|
||||||
else:
|
else:
|
||||||
self._restore_window()
|
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:
|
def _update_maximize_button(self) -> None:
|
||||||
button = getattr(self, "_max_button", None)
|
button = getattr(self, "_max_button", None)
|
||||||
if button is None:
|
if button is None:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue