Modal-loop Event-handling question

  • Hi all.

    In our client-server app we sometimes present modal sheets on our main window. Following server notifications we sometimes have to dismiss these sheets (user is expelled, or otherwise status-changed).

    We do this using the [mainWindow attachedSheet] endSheet];

    However, If we do this while the user holds one of the sheet buttons pressed --- within the mouse-tracking loop --- than endSheet happens, and then the mouseUp event reaches a released object (the sheet) which then crashes the application.

    All this happens in the main thread of the application, and it seems that the modal-event-loop of the sheet does not block network-born events. We have plenty of different sheets, so I prefer not to tailor each one, but rather have a general fix.

    Is there a "right way" to go about this? somehow clear the event queue, or close the mouse-tracking loop when I need to end the sheet programmatically? somehow handle the mouse-up in an appropriate way? maybe my whole approach is wrong here?

    Any insight will be appreciated --- Thanks.

    Motti Shneor
    Spectrum Reflections Ltd.
    ---
    Ceterum censeo Microsoftinem delendam esse
  • On Apr 30, 2012, at 1:24 AM, Motti Shneor wrote:

    > In our client-server app we sometimes present modal sheets on our main window. Following server notifications we sometimes have to dismiss these sheets (user is expelled, or otherwise status-changed).

    To me, dismissing a sheet without any user intervention sounds like a problematic UI design. It could be confusing if the user was about to do something with the sheet (or was halfway through) when it disappeared. In the worst case the user might be about to click an item in the sheet, and end up clicking through to whatever control was underneath it in the main window.

    I would suggest either making this UI modeless, or keeping the sheet up but adding a banner or something to it alerting the user that she’s been logged out.

    > However, If we do this while the user holds one of the sheet buttons pressed --- within the mouse-tracking loop --- than endSheet happens, and then the mouseUp event reaches a released object (the sheet) which then crashes the application.

    Ouch. The best workaround to this that I can think of is to check the current runloop mode, and if it’s NSEventTrackingRunloopMode give up without messing with the sheet (or check again later.)

    —Jens
  • Thanks Jens, for your enlightening comments.

    On 30/04/2012, at 20:55, Jens Alfke wrote:
    >
    > On Apr 30, 2012, at 1:24 AM, Motti Shneor wrote:
    >
    >> In our client-server app we sometimes present modal sheets on our main window. Following server notifications we sometimes have to dismiss these sheets (user is expelled, or otherwise status-changed).
    >
    > To me, dismissing a sheet without any user intervention sounds like a problematic UI design. It could be confusing if the user was about to do something with the sheet (or was halfway through) when it disappeared. In the worst case the user might be about to click an item in the sheet, and end up clicking through to whatever control was underneath it in the main window.
    >

    I agree this is not "nice" user experience, but ours is a "virtual meeting" system. Please compare: You talk to someone on the phone, then line is lost. Indeed some of your words will go down a dead line. This is the kind of situation I'm describing. In such situations, where the dialog (whether modal or modeless) has no meaning anymore, and whatever the user will do in it, makes no difference, because the context is gone (e.g. you want to send a little note to another participant. You open that dialog, and start typing.... Then the host expels you. Or the meeting is closed (scheduled) or... whatever. What good is to keep the dead UI, and thus mislead the user that he can complete the action he started?

    > I would suggest either making this UI modeless, or keeping the sheet up but adding a banner or something to it alerting the user that she’s been logged out.

    I'd rather replace the whole contents of the sheet with that banner you insinuate, but that's another discussion. Currently I need to overcome this crashing bug.

    >
    >> However, If we do this while the user holds one of the sheet buttons pressed --- within the mouse-tracking loop --- than endSheet happens, and then the mouseUp event reaches a released object (the sheet) which then crashes the application.
    >
    > Ouch. The best workaround to this that I can think of is to check the current runloop mode, and if it’s NSEventTrackingRunloopMode give up without messing with the sheet (or check again later.)
    >

    I can't just "give up" when I'm tracking the mouse.
    To avoid the crash, we tried to defer the "endSheet" via "performSelecor:@selector(closeAnyOpenSheet) afterDelay:0.0". This prevents the releasing of the dialog before the "mouseUp" event is received. However, when  "mouseUp" event comes, the didEndSelector is called for the sheet-alert (before our deferred "endSheet" has a chance to happen), and then we face another problem --- we try to accomplish user command, in a dead context. No problem to patch a few "sheetDidEnd"  methods, but we have dozens of them (all very different) and I would prefer general treatment for the problem.

    Do you know anything about the difference between "stopModal" and "abortModal" methods? Do you know which of these is being called by "endSheet" ? Is there a lower-level programmatic way to close the sheet and the modal session, giving up whatever event-loop is there?

    Thanks again@

    Motti Shneor,
    Spectrum Reflections Ltd.
  • On May 1, 2012, at 12:30 PM, Motti Shneor wrote:

    > To avoid the crash, we tried to defer the "endSheet" via "performSelecor:@selector(closeAnyOpenSheet) afterDelay:0.0". This prevents the releasing of the dialog before the "mouseUp" event is received. However, when  "mouseUp" event comes, the didEndSelector is called for the sheet-alert (before our deferred "endSheet" has a chance to happen), and then we face another problem --- we try to accomplish user command, in a dead context.

    There are always going to be race conditions like this — the user can always press a button at exactly the same time something asynchronously makes the button meaningless. Your code just has to deal with it safely. Presumably something underneath will return a kSessionClosedError, and the UI code will just ignore it because the sheet’s gone already.

    —Jens
previous month april 2012 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            
Go to today