From 11a4d55938d3f3bbefac806981abd64839626229 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 6 Nov 2022 13:13:03 +0800 Subject: [PATCH 1/5] Ensure the Cocoa NSWindow has back references to the interface and window. --- src/cocoa/src/toga_cocoa/window.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cocoa/src/toga_cocoa/window.py b/src/cocoa/src/toga_cocoa/window.py index b5d35e1276..4b6f0232c1 100644 --- a/src/cocoa/src/toga_cocoa/window.py +++ b/src/cocoa/src/toga_cocoa/window.py @@ -139,6 +139,11 @@ def onToolbarButtonPress_(self, obj) -> None: item.action(obj) +class TogaWindow(NSWindow): + interface = objc_property(object, weak=True) + impl = objc_property(object, weak=True) + + class Window: def __init__(self, interface, title, position, size): self.interface = interface @@ -156,12 +161,14 @@ def __init__(self, interface, title, position, size): # Create the window with a default frame; # we'll update size and position later. - self.native = NSWindow.alloc().initWithContentRect( + self.native = TogaWindow.alloc().initWithContentRect( NSMakeRect(0, 0, 0, 0), styleMask=mask, backing=NSBackingStoreBuffered, defer=False, ) + self.native.interface = self.interface + self.native._impl = self self.set_title(title) self.set_size(size) From 97f3df33d1a39071347b471bbd74d02593a99dd8 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 6 Nov 2022 13:38:40 +0800 Subject: [PATCH 2/5] Don't add widgets to the app registry before setting content. --- src/core/src/toga/window.py | 1 - src/core/tests/test_window.py | 25 +++++++++++++++++++------ src/dummy/src/toga_dummy/window.py | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/core/src/toga/window.py b/src/core/src/toga/window.py index 0de005a00b..5f639753b4 100644 --- a/src/core/src/toga/window.py +++ b/src/core/src/toga/window.py @@ -104,7 +104,6 @@ def app(self, app): self._app = app self._impl.set_app(app._impl) - app.widgets.update(self.widgets) if self.content: self.content.app = app diff --git a/src/core/tests/test_window.py b/src/core/tests/test_window.py index d3cdc12a1a..f8d10108bd 100644 --- a/src/core/tests/test_window.py +++ b/src/core/tests/test_window.py @@ -124,19 +124,32 @@ def test_set_app_after_content(self): def test_set_app_adds_window_widgets_to_app(self): - id1, id2, id3 = "id1", "id2", "id3" + id0, id1, id2, id3 = "id0", "id1", "id2", "id3" widget1, widget2, widget3 = ( - toga.Widget(id=id1), - toga.Widget(id=id2), - toga.Widget(id=id3), + toga.Label(id=id1, text="label 1"), + toga.Label(id=id2, text="label 1"), + toga.Label(id=id3, text="label 1"), ) - self.window.widgets.update({widget1, widget2, widget3}) + content = toga.Box(id=id0, children=[widget1, widget2, widget3]) + self.window.content = content + + # The window has widgets in it's repository + self.assertEqual(len(self.window.widgets), 4) + self.assertEqual(self.window.widgets[id0], content) + self.assertEqual(self.window.widgets[id1], widget1) + self.assertEqual(self.window.widgets[id2], widget2) + self.assertEqual(self.window.widgets[id3], widget3) + + # The app doesn't know about the widgets self.assertEqual(len(self.app.widgets), 0) + # Assign the window to the app self.window.app = self.app - self.assertEqual(len(self.app.widgets), 3) + # The window's content widgets are now known to the app. + self.assertEqual(len(self.app.widgets), 4) + self.assertEqual(self.app.widgets[id0], content) self.assertEqual(self.app.widgets[id1], widget1) self.assertEqual(self.app.widgets[id2], widget2) self.assertEqual(self.app.widgets[id3], widget3) diff --git a/src/dummy/src/toga_dummy/window.py b/src/dummy/src/toga_dummy/window.py index 041524724a..cc9f6e4a13 100644 --- a/src/dummy/src/toga_dummy/window.py +++ b/src/dummy/src/toga_dummy/window.py @@ -1,6 +1,21 @@ from .utils import LoggedObject, not_required, not_required_on +class Viewport: + def __init__(self, window): + self.baseline_dpi = 96 + self.dpi = 96 + self.window = window + + @property + def width(self): + return self.window.get_size()[0] + + @property + def height(self): + return self.window.get_size()[1] + + class Window(LoggedObject): def __init__(self, interface, title, position, size): super().__init__() @@ -18,6 +33,8 @@ def clear_content(self): def set_content(self, widget): self._action("set content", widget=widget) + self._set_value("content", widget) + widget.viewport = Viewport(self) def get_title(self): return self._get_value("title") From f5218eb93393c30e35773ca1d825239d45119590 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 6 Nov 2022 14:03:12 +0800 Subject: [PATCH 3/5] Add changenotes. --- changes/1659.bugfix.rst | 1 + changes/1660.bugfix.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changes/1659.bugfix.rst create mode 100644 changes/1660.bugfix.rst diff --git a/changes/1659.bugfix.rst b/changes/1659.bugfix.rst new file mode 100644 index 0000000000..56ab0c4873 --- /dev/null +++ b/changes/1659.bugfix.rst @@ -0,0 +1 @@ +An error caused by retrieving `app.current_window` on macOS has been resolved. diff --git a/changes/1660.bugfix.rst b/changes/1660.bugfix.rst new file mode 100644 index 0000000000..ec524a5b96 --- /dev/null +++ b/changes/1660.bugfix.rst @@ -0,0 +1 @@ +If a window has existing content when it is added to an app, the widget registry no longer raises an error. From 9fab1785f765b632b8b1475ea47066a924218f08 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 6 Nov 2022 14:13:30 +0800 Subject: [PATCH 4/5] Exclude Viewport from the required interface. --- src/dummy/src/toga_dummy/window.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dummy/src/toga_dummy/window.py b/src/dummy/src/toga_dummy/window.py index cc9f6e4a13..843359d801 100644 --- a/src/dummy/src/toga_dummy/window.py +++ b/src/dummy/src/toga_dummy/window.py @@ -1,6 +1,7 @@ from .utils import LoggedObject, not_required, not_required_on +@not_required class Viewport: def __init__(self, window): self.baseline_dpi = 96 From 08f0b6cbc7b44337df66e000ab6183b3b82d907f Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 7 Nov 2022 08:11:58 +0800 Subject: [PATCH 5/5] Actually use the weak reference attribute for impl. --- src/cocoa/src/toga_cocoa/window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cocoa/src/toga_cocoa/window.py b/src/cocoa/src/toga_cocoa/window.py index 4b6f0232c1..586196ff4a 100644 --- a/src/cocoa/src/toga_cocoa/window.py +++ b/src/cocoa/src/toga_cocoa/window.py @@ -168,7 +168,7 @@ def __init__(self, interface, title, position, size): defer=False, ) self.native.interface = self.interface - self.native._impl = self + self.native.impl = self self.set_title(title) self.set_size(size)