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

Messagebox minimizes window automatically on Linux #236

Closed
demberto opened this issue Mar 24, 2022 · 5 comments
Closed

Messagebox minimizes window automatically on Linux #236

demberto opened this issue Mar 24, 2022 · 5 comments

Comments

@demberto
Copy link

Desktop (please complete the following information):

ttkbootstrap: 1.7.1
OS: Lubuntu 20.04 64-bit

Describe the bug

Raising a Messagebox through one of its methods, automatically minimizes the parent/root window as well as itself. This behaviour is not exhibited on Windows.

To Reproduce

import ttkbootstrap as tk
from ttkbootstrap.dialogs import Messagebox

wnd = tk.Window()
Messagebox.show_error("", parent=wnd)

Expected behavior

It shouldn't minimize itself or the window.

Screenshots

No response

Additional context

tkinter's own show_error method doesn't cause this.

@demberto demberto added the bug Something isn't working label Mar 24, 2022
@israel-dryer
Copy link
Owner

@demberto, the Window object is hidden by default until explicitly run with Window.mainloop() or unless you call deiconify on the window. The reason for this behavior is so that the window will update with all of it's components before showing... this avoids showing the user all of the flashes of screen drawing, etc...

Because you've set wnd as the logical parent of the Messagebox, that is why it is hidden along with the window in this case.

You can also show the messagebox without specifying a parent if you wish.

@israel-dryer israel-dryer removed the bug Something isn't working label Mar 26, 2022
@demberto
Copy link
Author

I see what you mean, this code is what I ran in IDLE which has a slightly different behaviour with tkinter. wnd is put in mainloop the moment itis initialised. Removing the parent argument has the same effect. I found out this when I was testing my application DyCall. I also mentioned that this doesn't happen on Windows.

@laggykiller
Copy link

laggykiller commented Feb 9, 2023

As mentioned, the behavior is weird on Linux. The window gets minimized, and you have to open the window again before the messagebox appear. This does not occur in Windows. Setting parent=None does not resolve this problem. Here is a demo with a tkinter application I made:

Windows:
demo-windows

Linux:
demo-linux

Note that the Window / TopLevel set as parent get minimized. I suspect that in Linux version, somehow the parent get iconify() wrongfully? Or maybe deiconify() not working on Linux?

@laggykiller
Copy link

laggykiller commented Feb 9, 2023

In src/ttkbootstrap/dialogs/dialogs.py Dialog.build:

    def build(self):
        """Build the dialog from settings"""

        # setup toplevel based on widowing system
        if self._winsys == "win32":
            self._toplevel = ttk.Toplevel(
                transient=self.master,
                title=self._title,
                resizable=(0, 0),
                minsize=(250, 15),
                iconify=True,
            )
        else:
            self._toplevel = ttk.Toplevel(
                transient=self.master,
                title=self._title,
                resizable=(0, 0),
                windowtype="dialog",
                iconify=True,
            )
    # Function continues below...

If I set iconify=False, the whole problem disappear (Nothing get minimized).

If I comment out transient=self.master, the messagebox started in minimized state.

Minimal working example:

import ttkbootstrap as ttk
from ttkbootstrap.dialogs import Messagebox

def callback(*args):
    Messagebox.ok('test')

if __name__ == '__main__':
    root = ttk.Window()
    button = ttk.Button(root, text='Open messagebox', command=callback)
    button.pack()
    root.mainloop()

@laggykiller
Copy link

laggykiller commented Feb 9, 2023

Mystery solved. If self._toplevel is created with iconify=True, then execution is stuck until opening back the window. This is caused by src/ttkbootstrap/window.py Window.__init__ and Toplevel.__init__:

# Function continue above...

if iconify:
    self.iconify()

# Function continues...

if alpha is not None:
    if self.winsys == 'x11':
        self.wait_visibility(self)
    self.attributes("-alpha", alpha)

# Function continue below...

Linux uses x11 display system. The Window/Toplevel was iconified before setting alpha, which causes wait_visibility() to get stuck until user open back the window. Hence, deiconify() in src/ttkbootstrap/dialogs/dialogs Dialog.build could not be called until user open back the window.

It seems like the visbility check is introduced by 2abfeb4 in response to #108 so removing that check is not an option.

I propose setting iconify=False when creating dialog in Linux, or swap iconify() and set alpha such that alpha is set when 'visbible' before iconifying

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants