diff --git a/android/src/toga_android/app.py b/android/src/toga_android/app.py index ff5dc08910..269219586f 100644 --- a/android/src/toga_android/app.py +++ b/android/src/toga_android/app.py @@ -392,3 +392,6 @@ def request_permissions(self, permissions, on_complete): self._listener.permission_requests[code] = on_complete self._native_requestPermissions(permissions, code) + + def focus(self): + pass # No-op on Android diff --git a/cocoa/src/toga_cocoa/app.py b/cocoa/src/toga_cocoa/app.py index b1c59c4a85..e26dfdb98d 100644 --- a/cocoa/src/toga_cocoa/app.py +++ b/cocoa/src/toga_cocoa/app.py @@ -352,7 +352,7 @@ def show_about_dialog(self): if self.interface.author is None: options["Copyright"] = "" else: - options["Copyright"] = f"Copyright © {self.interface.author}" + options["Copyright"] = f"Copyright {self.interface.author}" self.native.orderFrontStandardAboutPanelWithOptions(options) @@ -385,3 +385,6 @@ def get_current_window(self): def set_current_window(self, window): window._impl.native.makeKeyAndOrderFront(window._impl.native) + + def focus(self): + self.native.activateIgnoringOtherApps_(True) diff --git a/core/src/toga/app.py b/core/src/toga/app.py index aca728de74..eabcac69f8 100644 --- a/core/src/toga/app.py +++ b/core/src/toga/app.py @@ -1020,6 +1020,16 @@ def set_full_screen(self, *windows: Window) -> None: # End backwards compatibility ###################################################################### + def focus(self): + """Bring the application into focus. + + This method will attempt to bring the application window into focus. Note that + it is generally considered poor practice for applications to steal focus from + the user, so use this method sparingly. + + This is a no-op on mobile and console platforms. + """ + self._impl.focus() ###################################################################### # 2024-08: Backwards compatibility diff --git a/gtk/src/toga_gtk/app.py b/gtk/src/toga_gtk/app.py index cfffc512c9..25e5be07c8 100644 --- a/gtk/src/toga_gtk/app.py +++ b/gtk/src/toga_gtk/app.py @@ -248,3 +248,7 @@ def get_current_window(self): # pragma: no-cover-if-linux-wayland def set_current_window(self, window): window._impl.native.present() + + def focus(self): + # GTK doesn't provide a reliable way to bring an app into focus + pass diff --git a/web/src/toga_web/app.py b/web/src/toga_web/app.py index fec494d7d7..ed1c10ff5b 100644 --- a/web/src/toga_web/app.py +++ b/web/src/toga_web/app.py @@ -90,7 +90,7 @@ def show_about_dialog(self): name_and_version += f" v{self.interface.version}" if self.interface.author is not None: - copyright = f"\n\nCopyright © {self.interface.author}" + copyright = f"\n\nCopyright {self.interface.author}" close_button = create_element( "sl-button", slot="footer", variant="primary", content="Ok" @@ -156,3 +156,6 @@ def enter_presentation_mode(self, screen_window_dict): def exit_presentation_mode(self): self.interface.factory.not_implemented("App.exit_presentation_mode()") + + def focus(self): + pass # No-op on web platform diff --git a/winforms/src/toga_winforms/app.py b/winforms/src/toga_winforms/app.py index f26445b6f1..a9e73fe750 100644 --- a/winforms/src/toga_winforms/app.py +++ b/winforms/src/toga_winforms/app.py @@ -264,3 +264,8 @@ def get_current_window(self): def set_current_window(self, window): window._impl.native.Activate() + + def focus(self): + # Bring the app's main window into focus if it exists + if self.interface.main_window: + self.interface.main_window._impl.native.Activate()