diff --git a/ardupilot_methodic_configurator/frontend_tkinter_progress_window.py b/ardupilot_methodic_configurator/frontend_tkinter_progress_window.py index 8dbbf2015..98db42057 100644 --- a/ardupilot_methodic_configurator/frontend_tkinter_progress_window.py +++ b/ardupilot_methodic_configurator/frontend_tkinter_progress_window.py @@ -18,7 +18,7 @@ from ardupilot_methodic_configurator.frontend_tkinter_base_window import BaseWindow -class ProgressWindow: +class ProgressWindow: # pylint: disable=too-many-instance-attributes """ A class for creating and managing a progress window in the application. @@ -42,6 +42,7 @@ def __init__( # pylint: disable=too-many-arguments, too-many-positional-argumen self.progress_window = tk.Toplevel(self.parent) # Withdraw immediately to prevent flicker while setting up self.progress_window.withdraw() + self._is_aqua = self.progress_window.tk.call("tk", "windowingsystem") == "aqua" self.progress_window.title(title) try: dpi = self.progress_window.winfo_fpixels("1i") @@ -117,9 +118,12 @@ def update_progress_bar(self, current_value: int, max_value: int) -> None: return if self.only_show_when_update_progress_called and not self._shown: + self.progress_window.update_idletasks() # Calculate widgets first self.progress_window.deiconify() self._center_progress_window() self.progress_window.lift() + if getattr(self, "_is_aqua", False): + self.progress_window.update() # macOS needs this to paint pixels NOW self._shown = True elif not self.only_show_when_update_progress_called: self.progress_window.lift() @@ -143,6 +147,9 @@ def update_progress_bar(self, current_value: int, max_value: int) -> None: # other windows while a blocking upload/download is in flight. self.progress_bar.update_idletasks() + if getattr(self, "_is_aqua", False): + self.progress_window.update() + # Close the progress window when the process is complete if current_value == max_value: self.progress_window.destroy() diff --git a/ardupilot_methodic_configurator/frontend_tkinter_show.py b/ardupilot_methodic_configurator/frontend_tkinter_show.py index 95bca5d93..443cc03eb 100644 --- a/ardupilot_methodic_configurator/frontend_tkinter_show.py +++ b/ardupilot_methodic_configurator/frontend_tkinter_show.py @@ -481,9 +481,11 @@ def __init__( # pylint: disable=too-many-arguments, too-many-positional-argumen if tag_name and isinstance(self.widget, tk.Text): self.widget.tag_bind(tag_name, "", self.schedule_show, "+") self.widget.tag_bind(tag_name, "", self.destroy_hide, "+") + self.widget.tag_bind(tag_name, "", self.destroy_hide, "+") else: self.widget.bind("", self.schedule_show, "+") self.widget.bind("", self.destroy_hide, "+") + self.widget.bind("", self.destroy_hide, "+") self.widget.bind("", self._on_widget_destroy, "+") @@ -497,15 +499,11 @@ def _cancel_timer(self, name: str) -> None: def _cancel_show(self) -> None: self._cancel_timer("show") - def _on_widget_destroy(self, event: Optional[tk.Event] = None) -> None: # noqa: ARG002 # pylint: disable=unused-argument + def _on_widget_destroy(self, event: Optional[tk.Event] = None) -> None: """Stop any active timers if the widget is destroyed.""" - self._cancel_show() - self._cancel_timer("alpha") - - if self.tooltip: - with contextlib.suppress(tk.TclError): - self.tooltip.destroy() - self.tooltip = None + if event and getattr(event, "widget", None) is not self.widget: + return + self.force_hide() def _hide_active_tooltip(self) -> None: """Hide another active tooltip before showing this one.""" @@ -539,8 +537,12 @@ def create_show(self, _event: Optional[tk.Event] = None) -> None: return # Avoid redundant tooltip creation self.tooltip = cast("tk.Toplevel", self.toplevel_class(self.widget, bg="#ffffe0")) + + # Remove the window buttons on all OSs self.tooltip.wm_overrideredirect(True) # noqa: FBT003 - self.tooltip.withdraw() + + if not self._is_aqua: + self.tooltip.withdraw() if self._is_aqua: self.tooltip.attributes("-alpha", 0.0)