diff --git a/app/gui/ui.py b/app/gui/ui.py index ab483d6..0f930f6 100644 --- a/app/gui/ui.py +++ b/app/gui/ui.py @@ -446,11 +446,6 @@ class UIBuilderMixin: max_btn.bind("", 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("", lambda _e: min_btn.configure(bg="#2c2c32")) - min_btn.bind("", lambda _e: min_btn.configure(bg=bar_bg)) - for widget in (title_bar, title_label): widget.bind("", self._start_window_drag) widget.bind("", 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: