• Looking for non-modal alternatives to tk_messageBox

    From Michael Soyka@21:1/5 to All on Thu Apr 14 18:54:22 2022
    I have a Tk application that runs diagnostics on a remote system. It displays the tests and test results in a text widget. When a test fails, the operator is notified using tk_messageBox and given the option of rerunning or bypassing the test (retry/
    cancel). To make a decision the operator reviews the information displayed in the text widget which could involve engaging the scrollbar. However, the scrollbar is unresponsive, I assume because tk_messageBox is blocking the event loop.

    I've addressed this problem by writing my own tk_messageBox that uses tkwait but, being intellectually curious, I'd like to know what alternatives might exist. They could be existing packages or some design choice that permits the use of tk_messageBox
    but any other suggestions would be welcomed.

    Thanks in advance,
    -mike

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Michael Soyka on Thu Apr 14 22:29:40 2022
    On 4/14/22 9:54 PM, Michael Soyka wrote:

    I've addressed this problem by writing my own tk_messageBox that uses tkwait but, being intellectually curious, I'd like to know what alternatives might exist. They could be existing packages or some design choice that permits the use of tk_messageBox
    but any other suggestions would be welcomed.


    Hello,

    I am sure most everybody has faced the same and come up with a similar solution. However, it is good to point out that you can achieve your
    goal with the built-in tk_messageBox. Here is a quick example:

    package req Tk

    toplevel .hidden
    wm withdraw .hidden

    # rest of your script

    tk_messageBox -message "Not blocking anything..." -parent .hidden

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to [email protected] on Fri Apr 15 12:53:39 2022
    On Thursday, April 14, 2022 at 10:29:45 PM UTC-4, [email protected] wrote:
    On 4/14/22 9:54 PM, Michael Soyka wrote:

    I've addressed this problem by writing my own tk_messageBox that uses tkwait but, being intellectually curious, I'd like to know what alternatives might exist. They could be existing packages or some design choice that permits the use of tk_
    messageBox but any other suggestions would be welcomed.

    Hello,

    I am sure most everybody has faced the same and come up with a similar solution. However, it is good to point out that you can achieve your
    goal with the built-in tk_messageBox. Here is a quick example:

    package req Tk

    toplevel .hidden
    wm withdraw .hidden

    # rest of your script

    tk_messageBox -message "Not blocking anything..." -parent .hidden

    I don't see how this makes tk_messageBox usable in my context. If the window is withdrawn while the message box exists, the operator can't review the text widget contents.
    Please explain how this helps.

    Also, I would guess that tk_messageBox blocks the event loop whether or not the -parent option is specified. Perhaps its effect on the event loop should be mentioned in the documentation, unless I'm missing something (wouldn't be the first time!).

    Nonetheless, thank you for responding,
    -mike

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Leitgeb@21:1/5 to Michael Soyka on Fri Apr 15 20:37:26 2022
    Michael Soyka <[email protected]> wrote:
    Also, I would guess that tk_messageBox blocks the event loop whether or
    not the -parent option is specified.

    You would guess effectively right, but in detail it runs it's
    own message loop and specifically suppresses gui-events for
    anything but itself.

    Anyway, a messageBox without "modality" is just a toplevel with
    a message widget and a couple of buttons arranged in frames...

    I vaguely remember times when tk_messageBox was itself just a
    procedure setting up the complete dialog.

    It is still a procedure, but nowadays only a wrapper for
    ::tk::MessageBox, which itself cannot be inspected as a proc.

    Using my standard debug-trick when running wish from a terminal
    window (on linux. might not work on purely graphical OSes):
    % fileevent stdin readable { puts stderr "[catch [gets stdin] r]: $r" }

    now:
    % ::tk::MessageBox -message message -detail detail -title title
    # dialog pops up - wish's own repl is busy, but filevent stdin still fires. winfo children .
    0: .__tk__messagebox
    winfo children .__tk__messagebox
    0: .__tk__messagebox.bot .__tk__messagebox.top .__tk__messagebox.msg .__tk__messagebox.dtl .__tk__messagebox.bitmap .__tk__messagebox.ok
    winfo class .__tk__messagebox.bot
    0: TFrame
    winfo class .__tk__messagebox.msg
    0: TLabel
    winfo class .__tk__messagebox.dtl
    0: TLabel
    .__tk__messagebox.dtl conf
    0: {-background ...[too long]

    and step by step one could examine the actual layout and recreate it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to Andreas Leitgeb on Fri Apr 15 16:52:05 2022
    At Fri, 15 Apr 2022 20:37:26 -0000 (UTC) Andreas Leitgeb <[email protected]> wrote:


    Michael Soyka <[email protected]> wrote:
    Also, I would guess that tk_messageBox blocks the event loop whether or
    not the -parent option is specified.

    You would guess effectively right, but in detail it runs it's
    own message loop and specifically suppresses gui-events for
    anything but itself.

    No, it just does a "grab":

    grab(3tk) Tk Built-In Commands grab(3tk)

    ______________________________________________________________________________

    NAME
    grab - Confine pointer and keyboard events to a window sub-tree

    SYNOPSIS
    grab ?-global? window

    grab option ?arg arg ...? ______________________________________________________________________________

    DESCRIPTION
    This command implements simple pointer and keyboard grabs for Tk. Tk's
    grabs are different than the grabs described in the Xlib documentation.
    When a grab is set for a particular window, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy.
    Whenever the pointer is within the grab window's subtree, the pointer
    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion. When the pointer is
    outside window's tree, button presses and releases and mouse motion
    events are reported to window, and window entry and window exit events
    are ignored. The grab subtree "owns" the pointer: windows outside the
    grab subtree will be visible on the screen but they will be insensitive
    until the grab is released. The tree of windows underneath the grab
    window can include top-level windows, in which case all of those top-
    level windows and their descendants will continue to receive mouse
    events during the grab.

    Basically, a modal toplevel does this:

    toplevel .foo
    (build the rest of .foo)
    set oldgrab [grab current .foo]
    grab .foo
    set oldfocus [focus]
    focus .foo
    tkwait window .foo;# could wait on a global set by a close/cancel button.
    if {$oldgrab ne {}} {
    grab $oldgrab
    }
    if {$oldfocus ne {}} {
    focus $oldfocus
    }

    Removing all of the grab infrastructure and tossing the tkwait, yields a non-modal toplevel.


    Anyway, a messageBox without "modality" is just a toplevel with
    a message widget and a couple of buttons arranged in frames...

    I vaguely remember times when tk_messageBox was itself just a
    procedure setting up the complete dialog.

    It is still a procedure, but nowadays only a wrapper for
    ::tk::MessageBox, which itself cannot be inspected as a proc.

    Using my standard debug-trick when running wish from a terminal
    window (on linux. might not work on purely graphical OSes):
    % fileevent stdin readable { puts stderr "[catch [gets stdin] r]: $r" }

    now:
    % ::tk::MessageBox -message message -detail detail -title title
    # dialog pops up - wish's own repl is busy, but filevent stdin still fires.
    winfo children .
    0: .__tk__messagebox
    winfo children .__tk__messagebox
    0: .__tk__messagebox.bot .__tk__messagebox.top .__tk__messagebox.msg .__tk__messagebox.dtl .__tk__messagebox.bitmap .__tk__messagebox.ok
    winfo class .__tk__messagebox.bot
    0: TFrame
    winfo class .__tk__messagebox.msg
    0: TLabel
    winfo class .__tk__messagebox.dtl
    0: TLabel
    .__tk__messagebox.dtl conf
    0: {-background ...[too long]

    and step by step one could examine the actual layout and recreate it.




    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jtyler@21:1/5 to Michael Soyka on Fri Apr 15 14:39:29 2022
    On 4/15/2022 12:53 PM, Michael Soyka wrote:
    On Thursday, April 14, 2022 at 10:29:45 PM UTC-4, [email protected] wrote:
    On 4/14/22 9:54 PM, Michael Soyka wrote:

    I've addressed this problem by writing my own tk_messageBox that uses tkwait but, being intellectually curious, I'd like to know what alternatives might exist. They could be existing packages or some design choice that permits the use of tk_
    messageBox but any other suggestions would be welcomed.

    Hello,

    I am sure most everybody has faced the same and come up with a similar
    solution. However, it is good to point out that you can achieve your
    goal with the built-in tk_messageBox. Here is a quick example:

    package req Tk

    toplevel .hidden
    wm withdraw .hidden

    # rest of your script

    tk_messageBox -message "Not blocking anything..." -parent .hidden

    I don't see how this makes tk_messageBox usable in my context. If the window is withdrawn while the message box exists, the operator can't review the text widget contents.
    Please explain how this helps.

    Also, I would guess that tk_messageBox blocks the event loop whether or not the -parent option is specified. Perhaps its effect on the event loop should be mentioned in the documentation, unless I'm missing something (wouldn't be the first time!).

    Nonetheless, thank you for responding,
    -mike

    It is the new toplevel window .hidden which is withdrawn, not your text
    widget which would be in another window, most likely using the . window.

    Notice the -parent .hidden, which makes the message box part of the new toplevel. I confess to not fully understanding why this works, I'm gonna
    guess that separate toplevels are the key.

    Another way, but probably overkill, since the above seems to work just
    as well, would be to do the message box in a separate thread. Threads
    have their own event loop which is separate from the one in the main thread.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Michael Soyka on Fri Apr 15 20:07:04 2022
    On 4/15/22 3:53 PM, Michael Soyka wrote:

    package req Tk

    toplevel .hidden
    wm withdraw .hidden

    # rest of your script

    tk_messageBox -message "Not blocking anything..." -parent .hidden


    Hello,

    Did you try it? It should have worked.

    As jtyler explained in his reply, there are a couple of more lines to
    add to your code. They create a new toplevel, and immediately hide it.
    Then when you call tk_messageBox, you use that toplevel as the parent.

    As to why it works, message and dialog boxes are assumed to be "modal";
    i.e., the rough idea is that they are meant to interrupt the current
    flow of program/user actions and wait for a "decision" to be made before proceeding. They achieve this by blocking interactivity on the toplevel
    window identified as parent (either implicitly or explicitly). This is
    done via a grab as explained by Robert Heller in another reply.
    However, that block is local to that single toplevel window only. That
    is why your code would not allow the user to scroll up/down or do
    anything else in the main window while the message box was displayed.

    However, you can create a new toplevel and set it as the parent of the tk_messageBox. Since the new toplevel is not displayed at all, the
    message box will just sit there all by its lonely self without blocking anything that belongs in your actual script.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to [email protected] on Fri Apr 15 17:48:26 2022
    On Friday, April 15, 2022 at 8:07:16 PM UTC-4, [email protected] wrote:
    On 4/15/22 3:53 PM, Michael Soyka wrote:

    package req Tk

    toplevel .hidden
    wm withdraw .hidden

    # rest of your script

    tk_messageBox -message "Not blocking anything..." -parent .hidden

    Hello,

    Did you try it? It should have worked.

    My apologies, it does work as you've described.
    When I tried your suggestion I was under the misconception that my text widget would be part of .hidden.


    As jtyler explained in his reply, there are a couple of more lines to
    add to your code. They create a new toplevel, and immediately hide it.
    Then when you call tk_messageBox, you use that toplevel as the parent.

    As to why it works, message and dialog boxes are assumed to be "modal";
    i.e., the rough idea is that they are meant to interrupt the current
    flow of program/user actions and wait for a "decision" to be made before proceeding. They achieve this by blocking interactivity on the toplevel window identified as parent (either implicitly or explicitly). This is
    done via a grab as explained by Robert Heller in another reply.
    However, that block is local to that single toplevel window only. That
    is why your code would not allow the user to scroll up/down or do
    anything else in the main window while the message box was displayed.

    However, you can create a new toplevel and set it as the parent of the tk_messageBox. Since the new toplevel is not displayed at all, the
    message box will just sit there all by its lonely self without blocking anything that belongs in your actual script.

    Again, thanks for taking the time to explain.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to Robert Heller on Fri Apr 15 17:55:30 2022
    On Friday, April 15, 2022 at 5:52:14 PM UTC-4, Robert Heller wrote:
    At Fri, 15 Apr 2022 20:37:26 -0000 (UTC) Andreas Leitgeb <[email protected]> wrote:


    Michael Soyka <[email protected]> wrote:
    Also, I would guess that tk_messageBox blocks the event loop whether or not the -parent option is specified.

    You would guess effectively right, but in detail it runs it's
    own message loop and specifically suppresses gui-events for
    anything but itself.
    No, it just does a "grab":

    grab(3tk) Tk Built-In Commands grab(3tk)

    ______________________________________________________________________________

    NAME
    grab - Confine pointer and keyboard events to a window sub-tree

    SYNOPSIS
    grab ?-global? window

    grab option ?arg arg ...? ______________________________________________________________________________

    DESCRIPTION
    This command implements simple pointer and keyboard grabs for Tk. Tk's
    grabs are different than the grabs described in the Xlib documentation.
    When a grab is set for a particular window, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy. Whenever the pointer is within the grab window's subtree, the pointer
    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion. When the pointer is outside window's tree, button presses and releases and mouse motion
    events are reported to window, and window entry and window exit events
    are ignored. The grab subtree "owns" the pointer: windows outside the
    grab subtree will be visible on the screen but they will be insensitive
    until the grab is released. The tree of windows underneath the grab
    window can include top-level windows, in which case all of those top-
    level windows and their descendants will continue to receive mouse
    events during the grab.

    Basically, a modal toplevel does this:

    toplevel .foo
    (build the rest of .foo)
    set oldgrab [grab current .foo]
    grab .foo
    set oldfocus [focus]
    focus .foo
    tkwait window .foo;# could wait on a global set by a close/cancel button.
    if {$oldgrab ne {}} {
    grab $oldgrab
    }
    if {$oldfocus ne {}} {
    focus $oldfocus
    }

    Removing all of the grab infrastructure and tossing the tkwait, yields a non-modal toplevel.

    Thank you for your explanation, this clarifies both the behavior and solution. And I've learned something new- who could ask for more?

    Much obliged.

    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Leitgeb@21:1/5 to [email protected] on Sat Apr 16 14:47:38 2022
    [email protected] <[email protected]> wrote:
    On 4/15/22 3:53 PM, Michael Soyka wrote:
    package req Tk
    toplevel .hidden
    wm withdraw .hidden
    # rest of your script
    tk_messageBox -message "Not blocking anything..." -parent .hidden
    Did you try it? It should have worked.

    The strange thing is, I did try it from an interactive "wish", and I did:

    toplevel .hidden; wm withdraw .hidden

    in a single line, to avoid the toplevel to pop up first (to mimic
    its behaviour in a script)

    Then I created (and packed) a text widget ".t" in ".", then I started
    the message box with the removed toplevel .hidden as its parent.

    And...

    while the messagebox was open, the text was deaf to all my actions,
    until I closed the popup.

    Conclusion: Maybe, the behaviour for invisible parent toplevels is OS-dependent.
    (in my case that was on Linux)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to Andreas Leitgeb on Sat Apr 16 08:23:26 2022
    On Saturday, April 16, 2022 at 10:47:42 AM UTC-4, Andreas Leitgeb wrote:
    [email protected] <[email protected]> wrote:
    On 4/15/22 3:53 PM, Michael Soyka wrote:
    package req Tk
    toplevel .hidden
    wm withdraw .hidden
    # rest of your script
    tk_messageBox -message "Not blocking anything..." -parent .hidden
    Did you try it? It should have worked.
    The strange thing is, I did try it from an interactive "wish", and I did: toplevel .hidden; wm withdraw .hidden
    in a single line, to avoid the toplevel to pop up first (to mimic
    its behaviour in a script)

    Then I created (and packed) a text widget ".t" in ".", then I started
    the message box with the removed toplevel .hidden as its parent.

    And...

    while the messagebox was open, the text was deaf to all my actions,
    until I closed the popup.

    Conclusion: Maybe, the behaviour for invisible parent toplevels is OS-dependent.
    (in my case that was on Linux)

    I'm running ActiveState 8.6.6 on Windows 10 and, if I use your create sequence, my text widget is alive and kicking; likewise if created in the other order.
    However, on my linux box running Tk 8.6.9 neither order works, i.e., the text widget is unresponsive.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Michael Soyka on Sat Apr 16 12:20:10 2022
    On 4/16/22 11:23 AM, Michael Soyka wrote:

    However, on my linux box running Tk 8.6.9 neither order works, i.e., the text widget is unresponsive.


    Hello,

    That is interesting. It looks like Linux side only has global grab vs.
    local. Also consider that Linux has several window managers and I
    believe some give you options to control this specific behavior. I
    don't have a Linux handy at the moment to test, though.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to Michael Soyka on Sat Apr 16 11:15:18 2022
    At Sat, 16 Apr 2022 08:23:26 -0700 (PDT) Michael Soyka <[email protected]> wrote:


    On Saturday, April 16, 2022 at 10:47:42 AM UTC-4, Andreas Leitgeb wrote:
    [email protected] <[email protected]> wrote:
    On 4/15/22 3:53 PM, Michael Soyka wrote:
    package req Tk
    toplevel .hidden
    wm withdraw .hidden
    # rest of your script
    tk_messageBox -message "Not blocking anything..." -parent .hidden
    Did you try it? It should have worked.
    The strange thing is, I did try it from an interactive "wish", and I did: toplevel .hidden; wm withdraw .hidden
    in a single line, to avoid the toplevel to pop up first (to mimic
    its behaviour in a script)

    Then I created (and packed) a text widget ".t" in ".", then I started
    the message box with the removed toplevel .hidden as its parent.

    And...

    while the messagebox was open, the text was deaf to all my actions,
    until I closed the popup.

    Conclusion: Maybe, the behaviour for invisible parent toplevels is OS-dependent.
    (in my case that was on Linux)

    I'm running ActiveState 8.6.6 on Windows 10 and, if I use your create sequence, my text widget is alive and kicking; likewise if created in the other order.
    However, on my linux box running Tk 8.6.9 neither order works, i.e., the text widget is unresponsive.



    This suggests that the .hidden "trick" is not a reliable cross-platform
    option.

    Note: a non-modal version of Tk_messageBox is easy enough to just write using something like this sequence:

    toplevel .messageBox
    wm title .messageBox "Some Title"
    wm transient .messageBox $parent
    wm protocol .messageBox WM_DELETE_WINDOW <some script...>
    message .messageBox.message
    pack .messageBox.message -expand yes -fill both
    button .messageBox.dismis -text {Dismis} -command {destory .messageBox}
    pack .messageBox.dismis -expand yes -fill x

    This could be easily wrapped in a proc that uses some options and/or
    parameters to fill things in parametricly.




    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jtyler@21:1/5 to [email protected] on Sun Apr 17 22:52:14 2022
    On 4/16/2022 9:20 AM, [email protected] wrote:
    On 4/16/22 11:23 AM, Michael Soyka wrote:

    However, on my linux box running Tk 8.6.9 neither order works, i.e.,
    the text widget is unresponsive.


    Hello,

    That is interesting.  It looks like Linux side only has global grab vs. local.  Also consider that Linux has several window managers and I
    believe some give you options to control this specific behavior.  I
    don't have a Linux handy at the moment to test, though.

    Well, maybe then using a thread is not overkill :)

    [1650]$ rlwrap -pred tclsh
    % package require Thread
    2.8.4
    % set tid [thread::create {package require Tk;wm withdraw . ; thread::wait}] tid0x7fad67cdb700
    % package require Tk
    8.6.9
    % button .b -text hello -command {puts hi} ; pack .b
    % hi
    hi
    hi

    % thread::send -async $tid {tk_messageBox -message "hello world"}
    % hi
    hi
    hi

    In the above, I clicked on button, that produced the "hi" regardless of
    the message box being present or not.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Schelte@21:1/5 to jtyler on Mon Apr 18 12:18:32 2022
    On 18/04/2022 07:52, jtyler wrote:
    Well, maybe then using a thread is not overkill :)

    It is. You can achieve the same result with just a slave interpreter:
    % interp create foo
    foo
    % foo eval {package require Tk; wm withdraw .}
    % package require Tk
    8.6.12
    % button .b -text hello -command {puts hi}; pack .b
    % foo eval {tk_messageBox -message "hello world"}


    Schelte.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to Robert Heller on Mon Apr 18 07:18:24 2022
    On Friday, April 15, 2022 at 5:52:14 PM UTC-4, Robert Heller wrote:


    grab(3tk) Tk Built-In Commands grab(3tk)

    ______________________________________________________________________________

    NAME
    grab - Confine pointer and keyboard events to a window sub-tree

    SYNOPSIS
    grab ?-global? window

    grab option ?arg arg ...? ______________________________________________________________________________

    DESCRIPTION
    This command implements simple pointer and keyboard grabs for Tk. Tk's
    grabs are different than the grabs described in the Xlib documentation.
    When a grab is set for a particular window, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy. Whenever the pointer is within the grab window's subtree, the pointer
    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion.

    It was suggested in an earlier post to associate the tk_messageBox window with a hidden toplevel as a way of keeping my text widget responsive. This worked on Windows but not linux. If I understand the following two sentences in the manpage, does it
    not follow that the linux behavior correctly implements "grab" and that Windows does not?

    When the pointer is
    outside window's tree, button presses and releases and mouse motion
    events are reported to window, and window entry and window exit events
    are ignored. The grab subtree "owns" the pointer: windows outside the
    grab subtree will be visible on the screen but they will be insensitive until the grab is released. The tree of windows underneath the grab
    window can include top-level windows, in which case all of those top-
    level windows and their descendants will continue to receive mouse
    events during the grab.


    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to Michael Soyka on Mon Apr 18 10:37:20 2022
    At Mon, 18 Apr 2022 07:18:24 -0700 (PDT) Michael Soyka <[email protected]> wrote:


    On Friday, April 15, 2022 at 5:52:14 PM UTC-4, Robert Heller wrote:


    grab(3tk) Tk Built-In Commands grab(3tk)

    ______________________________________________________________________________

    NAME
    grab - Confine pointer and keyboard events to a window sub-tree

    SYNOPSIS
    grab ?-global? window

    grab option ?arg arg ...? ______________________________________________________________________________

    DESCRIPTION
    This command implements simple pointer and keyboard grabs for Tk. Tk's grabs are different than the grabs described in the Xlib documentation. When a grab is set for a particular window, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy. Whenever the pointer is within the grab window's subtree, the pointer
    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion.

    It was suggested in an earlier post to associate the tk_messageBox window with a hidden toplevel as a way of keeping my text widget responsive. This worked on Windows but not linux. If I understand the following two sentences in the manpage, does it
    not follow that the linux behavior correctly implements "grab" and that Windows does not?

    Quite possibly. OTOH, implementing a non-modal version of tk_messageBox is pretty easy...


    When the pointer is
    outside window's tree, button presses and releases and mouse motion
    events are reported to window, and window entry and window exit events
    are ignored. The grab subtree "owns" the pointer: windows outside the
    grab subtree will be visible on the screen but they will be insensitive until the grab is released. The tree of windows underneath the grab
    window can include top-level windows, in which case all of those top-
    level windows and their descendants will continue to receive mouse
    events during the grab.


    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services [email protected] -- Webhosting Services



    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Michael Soyka on Mon Apr 18 12:27:52 2022
    On 4/18/22 10:18 AM, Michael Soyka wrote:
    ______________________________________________________________________________

    DESCRIPTION
    This command implements simple pointer and keyboard grabs for Tk. Tk's
    grabs are different than the grabs described in the Xlib documentation.
    When a grab is set for a particular window, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy.
    Whenever the pointer is within the grab window's subtree, the pointer
    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion.

    It was suggested in an earlier post to associate the tk_messageBox window with a hidden toplevel as a way of keeping my text widget responsive. This worked on Windows but not linux. If I understand the following two sentences in the manpage, does it
    not follow that the linux behavior correctly implements "grab" and that Windows does not?



    Hello,

    First, a brief comment on the above and then a solution that should work
    on Linux just as it does on Windows.

    Widget hierarchy is a tree structure - top-down from a toplevel all the
    way down through various frames to individual widgets. So when the documentation says "subtree" and its "descendants", it refers to that
    pathway from the toplevel down. A "subtree" does not include widgets
    from another toplevel. For example, ".a.b.c" and ".x.b.c.d" have
    nothing in common except for sharing the root window as parent.
    Hopefully this description is clear.

    Now, as to why the original suggestion did not work on Linux: I think it
    comes down to the ".hidden" window being invisible. We can fix it by
    keeping it visible but not too distracting to the user.

    Please try this code on Linux and see if it works better:


    package req Tk

    toplevel .hidden
    wm overrideredirect .hidden 1
    wm geometry .hidden 1x1+0+0


    # insert your script here

    tk_messageBox -message "Not blocking anything..." -parent .hidden

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to [email protected] on Mon Apr 18 12:42:14 2022
    At Mon, 18 Apr 2022 12:27:52 -0400 [email protected] wrote:


    On 4/18/22 10:18 AM, Michael Soyka wrote:
    ______________________________________________________________________________

    DESCRIPTION
    This command implements simple pointer and keyboard grabs for Tk. Tk's
    grabs are different than the grabs described in the Xlib documentation.
    When a grab is set for a particular window, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy.
    Whenever the pointer is within the grab window's subtree, the pointer
    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion.

    It was suggested in an earlier post to associate the tk_messageBox window with a hidden toplevel as a way of keeping my text widget responsive. This worked on Windows but not linux. If I understand the following two sentences in the manpage, does
    it not follow that the linux behavior correctly implements "grab" and that Windows does not?



    Hello,

    First, a brief comment on the above and then a solution that should work
    on Linux just as it does on Windows.

    Widget hierarchy is a tree structure - top-down from a toplevel all the
    way down through various frames to individual widgets. So when the documentation says "subtree" and its "descendants", it refers to that
    pathway from the toplevel down. A "subtree" does not include widgets
    from another toplevel. For example, ".a.b.c" and ".x.b.c.d" have
    nothing in common except for sharing the root window as parent.
    Hopefully this description is clear.

    Now, as to why the original suggestion did not work on Linux: I think it comes down to the ".hidden" window being invisible. We can fix it by
    keeping it visible but not too distracting to the user.

    Please try this code on Linux and see if it works better:


    package req Tk

    toplevel .hidden
    wm overrideredirect .hidden 1
    wm geometry .hidden 1x1+0+0


    # insert your script here

    tk_messageBox -message "Not blocking anything..." -parent .hidden

    Really, the best way is to just implement a non-modal version of
    tk_messageBox. Which is really quite simple...

    Playing games with hidden or almost hidden toplevels is just plain hokey...

    Actually, in most of my applications, I make very minimual use of tk_messageBox. Instead I have a general purpose Dialog widget class, which
    has a flag for being modal or not. In some applications where I have a lot of non-modal informational windows, I create a widget class just for that. (It
    is not rocket science...)

    If all you want to put up a non-modal message box that looks exactly like tk_messageBox, just grap the code in /usr/share/tcltk/tk8.6/msgbox.tcl and remove some (all) of the code starting with the line "# 8. Set a grab and
    claim the focus too." -- this is where all of the modal fun and games starts. Change the name of the function and you are all set.

















    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Schelte@21:1/5 to [email protected] on Mon Apr 18 20:43:17 2022
    On 18/04/2022 18:27, [email protected] wrote:
    So when the documentation says "subtree" and its "descendants", it
    refers to that pathway from the toplevel down. A "subtree" does not
    include widgets from another toplevel.

    The documentation refers to "the grab window and its descendants" *as*
    the "subtree". So it's not from the toplevel down, but from the grab
    window down. And only that part of the window hierarchy is active. All
    the rest is blocked. That includes other toplevels and their descendants.

    Just to confirm: I tried your modified version on linux and it doesn't
    work either.

    Robert Heller is right. Just create your own non-modal message box. It's
    not hard.


    Schelte.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Robert Heller on Mon Apr 18 14:56:10 2022
    On 4/18/22 1:42 PM, Robert Heller wrote:

    Really, the best way is to just implement a non-modal version of tk_messageBox. Which is really quite simple...


    Hello,

    I agree with you that it is indeed simple. I believe I mentioned as
    much at the very beginning. The OP had already solved it himself before posting, and any of the alternatives suggested here would work fine and
    be OK.


    Playing games with hidden or almost hidden toplevels is just plain hokey...


    I respectfully disagree completely. What is tricky or hokey about it?
    Look tk_messageBox up in the manual and you will see that it is a valid command, and it has a "-parent" option, which is implicitly assigned if
    not given by the user. If the OP has other windows, he can simply use
    that other window as the parent and he will still gain interactivity of
    his target window. I used an extra toplevel to eliminate that guesswork
    and provide a quick solution.

    If anything, I'd call it a case of a lack of understanding of the tk_messageBox. It is one of the fundamental widgets in UI and I think
    it is important to know what it does, properly.



    Actually, in most of my applications, I make very minimual use of tk_messageBox. Instead I have a general purpose Dialog widget class, which
    ...

    If all you want to put up a non-modal message box that looks exactly like tk_messageBox, just grap the code in /usr/share/tcltk/tk8.6/msgbox.tcl and



    I'd categorize this as technical debt. It may be easy to roll your own
    or hack it from the distribution but one will always need to ensure its compliance with future changes. If it could be avoided by an existing
    command already, why bother?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Schelte on Mon Apr 18 15:09:45 2022
    On 4/18/22 2:43 PM, Schelte wrote:
    On 18/04/2022 18:27, [email protected] wrote:
    So when the documentation says "subtree" and its "descendants", it
    refers to that pathway from the toplevel down. A "subtree" does not
    include widgets from another toplevel.

    The documentation refers to "the grab window and its descendants" *as*
    the "subtree". So it's not from the toplevel down, but from the grab


    I think we are saying the same thing. Just to clarify, per the man
    page, the target of a grab is a window; not a widget. And the hierarchy
    by definition must include the top/root end.


    window down. And only that part of the window hierarchy is active. All
    the rest is blocked. That includes other toplevels and their descendants.


    I am not sure I read you correctly. Are you saying all other toplevels
    are also locked due to the grab? If so, I would be surprised as it is
    contrary to my experience and to the documentation. The manual would
    have to refer to the "application" and not the "window".

    Also see the man page for grab. You can set it as global meaning application-wide, or local, meaning a single toplevel.


    From the man page:

    DESCRIPTION

    When a grab is set for a ***particular window***, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy.

    Please pay attention to "a particular window".

    The phrase "its descendants" refers to "the grab window".


    Whenever the pointer is within the grab window's subtree, the pointer

    "subtree" refers to any widget that is contained or is a child of the
    "grab window".





    will behave exactly the same as if there had been no grab at all and
    all events will be reported in the normal fashion. When the pointer is
    outside window's tree, button presses and releases and mouse motion
    events are reported to window, and window entry and window exit events
    are ignored. The grab subtree "owns" the pointer: windows outside the
    grab subtree will be visible on the screen but they will be insensitive
    until the grab is released. The tree of windows underneath the grab
    window can include top-level windows, in which case all of those top-
    level windows and their descendants will continue to receive mouse
    events during the grab.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to Robert Heller on Mon Apr 18 11:24:59 2022
    On Monday, April 18, 2022 at 1:42:23 PM UTC-4, Robert Heller wrote:

    Really, the best way is to just implement a non-modal version of tk_messageBox. Which is really quite simple...

    and, as I mentioned in my initial post, I've done that and it works just fine (and it was easy).

    My reason for posting was to learn from others about possible alternatives. So far, threads and slave interpreters were mentioned and those are the kinds of responses I was hoping for. Nonetheless, I do appreciate the explanations of how tk_messageBox
    works and it caused to crack-open my old Tk books, something I should have done from the start (RTFM as some might say).

    Playing games with hidden or almost hidden toplevels is just plain hokey...

    Actually, in most of my applications, I make very minimual use of tk_messageBox. Instead I have a general purpose Dialog widget class, which has a flag for being modal or not. In some applications where I have a lot of
    non-modal informational windows, I create a widget class just for that. (It is not rocket science...)

    By the way, what you describe is sounds similar to the custom dialog implementation given in "Effective Tcl/Tk Programming" by Harrison & McLennan except for the modality flag.


    If all you want to put up a non-modal message box that looks exactly like tk_messageBox, just grap the code in /usr/share/tcltk/tk8.6/msgbox.tcl and remove some (all) of the code starting with the line "# 8. Set a grab and claim the focus too." -- this is where all of the modal fun and games starts.
    Change the name of the function and you are all set.

    All I needed was a non-modal replacement with retry/cancel capability , the visual appearance of tk_messageBox served as a useful guide.

    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to Michael Soyka on Mon Apr 18 14:12:00 2022
    At Mon, 18 Apr 2022 11:24:59 -0700 (PDT) Michael Soyka <[email protected]> wrote:


    On Monday, April 18, 2022 at 1:42:23 PM UTC-4, Robert Heller wrote:

    Really, the best way is to just implement a non-modal version of tk_messageBox. Which is really quite simple...

    and, as I mentioned in my initial post, I've done that and it works just fine (and it was easy).

    My reason for posting was to learn from others about possible alternatives. So far, threads and slave interpreters were mentioned and those are the kinds of responses I was hoping for. Nonetheless, I do appreciate the explanations of how tk_
    messageBox works and it caused to crack-open my old Tk books, something I should have done from the start (RTFM as some might say).

    Using the event loop in more than one thread is possibly a bad idea. I don't think events will necessarily be delivered to multiple instances of the event loop.


    Playing games with hidden or almost hidden toplevels is just plain hokey...

    Actually, in most of my applications, I make very minimual use of tk_messageBox. Instead I have a general purpose Dialog widget class, which has a flag for being modal or not. In some applications where I have a lot of
    non-modal informational windows, I create a widget class just for that. (It is not rocket science...)

    By the way, what you describe is sounds similar to the custom dialog implementation given in "Effective Tcl/Tk Programming" by Harrison & McLennan except for the modality flag.

    Convergent Evolution... :-)



    If all you want to put up a non-modal message box that looks exactly like tk_messageBox, just grap the code in /usr/share/tcltk/tk8.6/msgbox.tcl and remove some (all) of the code starting with the line "# 8. Set a grab and claim the focus too." -- this is where all of the modal fun and games starts.
    Change the name of the function and you are all set.

    All I needed was a non-modal replacement with retry/cancel capability , the visual appearance of tk_messageBox served as a useful guide.

    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services [email protected] -- Webhosting Services



    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to Schelte on Mon Apr 18 15:27:57 2022
    On 4/18/22 2:43 PM, Schelte wrote:

    Just to confirm: I tried your modified version on linux and it doesn't
    work either.


    Thank you for trying it. Interrrresting....

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Leitgeb@21:1/5 to [email protected] on Mon Apr 18 20:47:36 2022
    [email protected] <[email protected]> wrote:
    I am not sure I read you correctly. Are you saying all other toplevels
    are also locked due to the grab? If so, I would be surprised as it is contrary to my experience and to the documentation. The manual would
    have to refer to the "application" and not the "window".

    Also see the man page for grab. You can set it as global meaning application-wide, or local, meaning a single toplevel.

    The "grabwindow" is really the start of the subtree that can still
    receive events.

    From the man page:
    DESCRIPTION
    When a grab is set for a ***particular window***, Tk restricts all pointer
    events to the grab window and its descendants in Tk's window hierarchy.

    I understood the phrase "X restricts Y to Z" such that that X causes Y
    to be "allowed only with Z".

    I can imagine that other people might read it entirely different,
    thinking of "pointer events to Z" as the object of restriction, and
    reading the object of restriction as a thing being forbidden...

    And finally, there is a windows-specific behaviour: that applications
    cannot just grab the whole screen exclusively.
    So, on Windows, a global grad is (as far as I've read long ago) really
    also just a local grab.

    Otoh., a global grab on Linux has the power of locking the user's session completely, e.g. like a screen-lock would be expected to do
    Instead, a local grab just blocks the rest of the same application - that
    is: all this application's toplevels, but would not interfere with a
    switch to other applications.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Andreas Leitgeb on Mon Apr 18 21:37:30 2022
    Andreas Leitgeb <[email protected]> wrote:
    [email protected] <[email protected]> wrote:
    I am not sure I read you correctly. Are you saying all other toplevels
    are also locked due to the grab? If so, I would be surprised as it is
    contrary to my experience and to the documentation. The manual would
    have to refer to the "application" and not the "window".

    The "grabwindow" is really the start of the subtree that can still
    receive events.

    From the man page:
    DESCRIPTION
    When a grab is set for a ***particular window***, Tk
    restricts all pointer events to the grab window and its
    descendants in Tk's window hierarchy.

    I understood the phrase "X restricts Y to Z" such that that X causes Y
    to be "allowed only with Z".

    Your understanding is how a 'grab' is intended to function.

    A language tweak to the grab man page to clear up the possible
    ambiguity could be:

    When a grab is set for a ***particular window***, Tk restricts all
    pointer events to __be sent only to__ the grab window and its
    descendants in Tk's window hierarchy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)