diff --git a/changes/1894.feature.rst b/changes/1894.feature.rst new file mode 100644 index 0000000000..63eaef269a --- /dev/null +++ b/changes/1894.feature.rst @@ -0,0 +1 @@ +Winforms now supports hiding and re-showing the app cursor. diff --git a/examples/window/window/app.py b/examples/window/window/app.py index 708d22f440..2e770f561d 100644 --- a/examples/window/window/app.py +++ b/examples/window/window/app.py @@ -75,6 +75,15 @@ async def do_current_window_cycling(self, widget, **kwargs): self.label.text = f"Current window is {self.current_window.id}" await asyncio.sleep(1) + async def do_hide_cursor(self, widget, **kwargs): + self.hide_cursor() + self.label.text = "Momentarily hiding cursor..." + + await asyncio.sleep(2) + + self.show_cursor() + self.label.text = "Cursor should be back!" + def do_report(self, widget, **kwargs): self.label.text = ( f"Window {self.main_window.title!r} " @@ -148,6 +157,11 @@ def startup(self): on_press=self.do_current_window_cycling, style=btn_style, ) + btn_do_hide_cursor = toga.Button( + "Hide cursor", + on_press=self.do_hide_cursor, + style=btn_style, + ) btn_do_report = toga.Button("Report", on_press=self.do_report, style=btn_style) btn_change_content = toga.Button( "Change content", on_press=self.do_next_content, style=btn_style @@ -165,6 +179,7 @@ def startup(self): btn_do_title, btn_do_new_windows, btn_do_current_window_cycling, + btn_do_hide_cursor, btn_do_report, btn_change_content, btn_hide, diff --git a/winforms/src/toga_winforms/app.py b/winforms/src/toga_winforms/app.py index 2f54c6673c..32f0dc31c3 100644 --- a/winforms/src/toga_winforms/app.py +++ b/winforms/src/toga_winforms/app.py @@ -49,6 +49,11 @@ def __init__(self, interface): # window-level close handling. self._is_exiting = False + # Winforms cursor visibility is a stack; If you call hide N times, you + # need to call Show N times to make the cursor re-appear. Store a local + # boolean to allow us to avoid building a deep stack. + self._cursor_visible = True + self.loop = WinformsProactorEventLoop() asyncio.set_event_loop(self.loop) @@ -305,14 +310,15 @@ def exit_full_screen(self, windows): for window in windows: window._impl.set_full_screen(False) - def set_cursor(self, value): - self.interface.factory.not_implemented("App.set_cursor()") - def show_cursor(self): - self.interface.factory.not_implemented("App.show_cursor()") + if not self._cursor_visible: + WinForms.Cursor.Show() + self._cursor_visible = True def hide_cursor(self): - self.interface.factory.not_implemented("App.hide_cursor()") + if self._cursor_visible: + WinForms.Cursor.Hide() + self._cursor_visible = False class DocumentApp(App):