Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On Android, MainWindow.size is (0, 0) until after startup method is complete #2274

Open
freakboy3742 opened this issue Dec 12, 2023 Discussed in #2273 · 2 comments
Open
Labels
android The issue relates to Android mobile support. bug A crash or error in behavior.

Comments

@freakboy3742
Copy link
Member

Discussed in #2273

via @cozimus

The following minimum working example work differently on windows and android.

import toga
from toga.style import Pack
from toga.style.pack import COLUMN

class Application(toga.App):
    def startup(self):
        self.main_window = toga.MainWindow(title=self.formal_name)
        self.btn = toga.Button("click here", on_press=self.my_func)
        main_box = toga.Box(style=Pack(flex=1, direction=COLUMN))
        main_box.add(self.btn)
        self.main_window.content = main_box
        self.my_func()
        self.main_window.show()

    def my_func(self, widget=None):
        self.btn.text = self.main_window.size


def main():
    return Application("Application", "com.example")


if __name__ == "__main__":
    app = main()
    app.main_loop()

On windows the button text change when the application is started, and it shows the real window dimension (e.g. (640,480)), while on android when the application is started it shows (0,0). However when I press the button, my_func works ok and it gives the real window size.

@freakboy3742
Copy link
Member Author

Initial investigation has revealed that the window size doesn't appear to be available in any capacity until the first onGlobalLayout event.

The same problem doesn't exist on Windows or macOS, as the Window object exists immediately, even if it isn't visible. It doesn't exist on iOS because the window size is determine as a proxy of the device, rather than the layout. However, on Android, the window size is being determined as the size of the ContentFrameLayout, rather than some proxy of the actual device/window.

An immediate workaround in this case is to use a background worker:

    def startup(self):
        ...
        add_background_task(self.deferred)

    async def deferred(self, app, **kwargs):
        self.my_func()

This will queue a background task that will be invoked as soon as possible after the creation of the window; but this will occur after the first redraw event, so the window size will exist.

@freakboy3742
Copy link
Member Author

As of #2678, the add_background_task() approach has been deprecated; you can now override on_running() to inject logic that will be executed as soon as the app loop is running.

@mhsmith mhsmith changed the title MainWindow.size is (0, 0) until after startup method is complete On Android, MainWindow.size is (0, 0) until after startup method is complete Jun 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android The issue relates to Android mobile support. bug A crash or error in behavior.
Projects
None yet
Development

No branches or pull requests

1 participant