Repository: beeware/toga

Issue:
Add content argument to MainWindow instantiation
### What is the problem or limitation you are having?

Right now, to create a MainWindow and add content to it, we have to do it in two steps and in a not so elegant way:

```
self.main_window = toga.MainWindow(
	title=self.formal_name
)

self.main_window.content = self.main_box
```

### Describe the solution you'd like

Allow assigning "content" during instantiation of MainWindow as well, so we can do it in one step and more elegantly:

```
self.main_window = toga.MainWindow(
	title=self.formal_name,
	content=self.main_box
)
```

This would be consistent with, for example, ScrollContainer.

### Describe alternatives you've considered

1. Make it consistent with other classes — that use "children" — and use "child" instead:

```
self.main_window = toga.MainWindow(
	title=self.formal_name,
	child=self.main_box
)
```

2. Or keep things as they are, at least until other higher priority tasks are completed, as this is a minor improvement

### Additional context

_No response_


Discussion:
That's an odd inconsistency - I'm surprised I didn't notice this before. Agreed that it's something we should address. 

`content=` would seem the obvious API spelling.

Resolving patch:
diff --git a/core/src/toga/app.py b/core/src/toga/app.py
--- a/core/src/toga/app.py
+++ b/core/src/toga/app.py
@@ -144,6 +144,7 @@ def __init__(
         minimizable: bool = True,
         resizeable=None,  # DEPRECATED
         closeable=None,  # DEPRECATED
+        content: Widget | None = None,
     ):
         """Create a new main window.
 
@@ -158,6 +159,7 @@ def __init__(
         :param minimizable: Can the window be minimized by the user?
         :param resizeable: **DEPRECATED** - Use ``resizable``.
         :param closeable: **DEPRECATED** - Use ``closable``.
+        :param content: Window content
         """
         super().__init__(
             id=id,
@@ -167,6 +169,7 @@ def __init__(
             resizable=resizable,
             closable=True,
             minimizable=minimizable,
+            content=content,
             # Deprecated arguments
             resizeable=resizeable,
             closeable=closeable,
diff --git a/core/src/toga/window.py b/core/src/toga/window.py
--- a/core/src/toga/window.py
+++ b/core/src/toga/window.py
@@ -73,6 +73,7 @@ def __init__(
         on_close: OnCloseHandler | None = None,
         resizeable=None,  # DEPRECATED
         closeable=None,  # DEPRECATED
+        content: Widget | None = None,
     ) -> None:
         """Create a new Window.
 
@@ -117,7 +118,6 @@ def __init__(
 
         self._id = str(id if id else identifier(self))
         self._impl = None
-        self._content = None
         self._is_full_screen = False
         self._closed = False
 
@@ -144,6 +144,8 @@ def __init__(
 
         self.on_close = on_close
 
+        self._content = content
+
     @property
     def id(self) -> str:
         """A unique identifier for the window."""


Test patch:
diff --git a/core/tests/test_window.py b/core/tests/test_window.py
--- a/core/tests/test_window.py
+++ b/core/tests/test_window.py
@@ -99,6 +99,14 @@ def test_set_app_with_content(window, app):
     assert content.app == app
 
 
+def test_set_app_with_content_at_instantiation(app):
+    """A window can be created with content"""
+    content = toga.Box()
+    window = toga.Window(content=content)
+
+    assert window.content == content
+
+
 @pytest.mark.parametrize(
     "value, expected",
     [
diff --git a/testbed/tests/test_window.py b/testbed/tests/test_window.py
--- a/testbed/tests/test_window.py
+++ b/testbed/tests/test_window.py
@@ -744,3 +744,10 @@ async def test_select_folder_dialog(
     ):
         result = result[-1:]
     await assert_dialog_result(main_window, dialog_result, on_result_handler, result)
+
+
+async def test_instantiate_window_with_content(app):
+    content = toga.Box()
+    window = toga.Window(content=content)
+
+    assert window.content == content