More on user inactivity

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

More on user inactivity

Bill Schwab
Hello all,

I need to be able to close UI elements in periods of inactivity.  The
function Blair suggested is working well, and I have something that works
for subpresenters of the app's main shell.

Modal dialogs are a small problem, but I seem to be able to get rid of them
using #exit.  Any thoughts on slick ways to find them rather than having to
keep track of them would be appreciated.

Message boxes appear to be a lot more trouble.  I've added quite a few of
them to idiot proof things, and now find that they are not yielding to my
programmatic attempts to close them.  Any ideas?  An obvious solution is to
replace them with a dialog and use #exit.  Is there an easier approach?

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: More on user inactivity

Blair McGlashan
"Bill Schwab" <[hidden email]> wrote in message
news:bbmsmm$ulc$[hidden email]...
> Hello all,
>
> I need to be able to close UI elements in periods of inactivity.  The
> function Blair suggested is working well, and I have something that works
> for subpresenters of the app's main shell.
>
> Modal dialogs are a small problem, but I seem to be able to get rid of
them
> using #exit.  Any thoughts on slick ways to find them rather than having
to
> keep track of them would be appreciated.
>
> Message boxes appear to be a lot more trouble.  I've added quite a few of
> them to idiot proof things, and now find that they are not yielding to my
> programmatic attempts to close them.  Any ideas?  An obvious solution is
to
> replace them with a dialog and use #exit.  Is there an easier approach?

No guarantees, but the following expression should destroy all "popups",
including common dialogs such as the FileOpen dialog and message boxes too:
(SessionManager current topLevelWindows collect: [:each | each
getLastActivePopup])
 do: [:each | each isNil ifFalse: [each destroy]]


A potential problem is that destroying the MB window programmatically like
this seems to cause the MessageBox code to raise an exception in
MessageBox>>basicOpen - the destruction of the view gets treated as if the
MB failed to open in the first place. I suppose it is actually right to
raise an exception in this case because the MB has been rudely terminated
without receiving a valid response from the user. Although one could
reasonably treat destruction of the view in the same way as the user
"cancelling", not all MBs are of the Yes/No/Cancel form. The code that is
opening the MB ought probably to be trapping the exception and handling it
in whatever way is appropriate in each case.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: More on user inactivity

Bill Schwab-2
Blair,

> No guarantees, but the following expression should destroy all "popups",
> including common dialogs such as the FileOpen dialog and message boxes
too:
> (SessionManager current topLevelWindows collect: [:each | each
> getLastActivePopup])
>  do: [:each | each isNil ifFalse: [each destroy]]

Interestingly, I can't get this to work.  The #getLastActivePopup ***does***
work, and that's likely to be a huge time saver for me.  Prior to posting, I
searched a little and found several "fake a button click" kinds of
solutions.  A draft appears below: any comments/suggestions would be greatly
appreciated.


> A potential problem is that destroying the MB window programmatically like
> this seems to cause the MessageBox code to raise an exception in
> MessageBox>>basicOpen - the destruction of the view gets treated as if the
> MB failed to open in the first place.

On win2k, I'm opening a message box from one workspace, and trying to
clobber it from another.  Is that what you are doing?  If so, maybe XP is
willing to close the message box, and 2k isn't??


> I suppose it is actually right to
> raise an exception in this case because the MB has been rudely terminated
> without receiving a valid response from the user. Although one could
> reasonably treat destruction of the view in the same way as the user
> "cancelling", not all MBs are of the Yes/No/Cancel form. The code that is
> opening the MB ought probably to be trapping the exception and handling it
> in whatever way is appropriate in each case.

That's actually one advantage of the kludge-and-click solution: one can
search for the (hopefully!!!) more benign choices first.  Sadly, I will
probably need to iterate, testing for active popups until there are none =:0


Have a good one,

Bill

--------------------



!View methodsFor!

clickMe
 "Trying to close an offending dialog/message box"

 "SendMessage(wndButton, WM_LBUTTONDOWN, 1, 0x00120025 )
  SendMessage(wndButton, WM_LBUTTONUP,   0, 0x00120025 )"
 self
  sendMessage:WM_LBUTTONDOWN wParam:MK_LBUTTON lParam:16r000A000A;
  sendMessage:WM_LBUTTONUP wParam:0 lParam:16r000A000A.
! !
!View categoriesFor: #clickMe!public! !


!View methodsFor!

clickSomethingToClose
 "Trying to close an offending dialog/message box"

  | views tokens out tryMe |

 out := Array writeStream.
 #( 'Cancel' 'No' 'Quit' 'Abort' 'Done' 'Close' 'Ok' ) do:[ :each |
  out
   nextPut:each asLowercase;
   nextPut:( '&', each ) asLowercase.
 ].
 tokens := out contents.

 views := self subViewsNonDolphin.

 tryMe := views
   detect:[ :each |
    tokens includes:each text asLowercase.
   ]
   ifNone:[ ^nil. ].

 tryMe clickMe.
! !
!View categoriesFor: #clickSomethingToClose!public! !



!View methodsFor!

subViewsNonDolphin
 "Answer a sequenceable collection of the sub views of the receiver in
 z-order sequence"

 | subviews child childView |
 subviews := OrderedCollection new.
 child := self getFirstChild.
 [ child notNil ] whileTrue: [
  childView := View withHandle: child.
  childView notNil
   ifTrue: [ subviews addLast: childView ]
   ifFalse: [ childView := View fromHandle: child. subviews
addLast:childView. ].
  child := UserLibrary default getWindow: childView asParameter uCmd:
GW_HWNDNEXT].
 ^subviews
 ! !
!View categoriesFor: #subViewsNonDolphin!hierarchy!public!sub views! !


--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: More on user inactivity

Bill Schwab-2
Blair,

A quick follow up: #clickMe seems to work better with a #setFocus before the
SendMessage() calls.  I'm especially curious about any problems that might
lurk in #subViewsNonDolphin.

Thanks!

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: More on user inactivity

Blair McGlashan
In reply to this post by Bill Schwab-2
"Bill Schwab" <[hidden email]> wrote in message
news:bbo5mu$bpbgk$[hidden email]...

> Blair,
>
> > No guarantees, but the following expression should destroy all "popups",
> > including common dialogs such as the FileOpen dialog and message boxes
> too:
> > (SessionManager current topLevelWindows collect: [:each | each
> > getLastActivePopup])
> >  do: [:each | each isNil ifFalse: [each destroy]]
>
> Interestingly, I can't get this to work.  The #getLastActivePopup
***does***
> work, and that's likely to be a huge time saver for me.  ...

Hmmm, it worked in my initial experiment (which was to cause a prompt to
save changes to come up in a browser and then go and evaluate the expression
in another workspace), but not when I tried to get a background task to kill
a MB opened on the workspace. I had some success with posting a WM_CLOSE,
but I'm not sure that always works either. Another possibility is to pass
the MB a WM_SYSCOMMAND(SC_CLOSE). Finally the MSDN knowledge base article
Q181934 "HOWTO: Create a Timed Message Box" may help. It seems that a
WM_QUIT is needed to get the MB to take notice, but the problem then is how
to ignore it subsequently and avoid shutting down the entire app, unless
that is what you want to do anyway. If you don't want to shut it down, then
your next problem will be to ensure it is in a consistent state, which might
not be easy if you've closed dialogs, etc.

I can't help thinking it would be better to just configure the screen saver
to come up after your preferred period of inactivity, and set it up to
require a password.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: More on user inactivity

Bill Schwab-2
Blair,

> Hmmm, it worked in my initial experiment (which was to cause a prompt to
> save changes to come up in a browser and then go and evaluate the
expression
> in another workspace), but not when I tried to get a background task to
kill
> a MB opened on the workspace. I had some success with posting a WM_CLOSE,
> but I'm not sure that always works either. Another possibility is to pass
> the MB a WM_SYSCOMMAND(SC_CLOSE). Finally the MSDN knowledge base article
> Q181934 "HOWTO: Create a Timed Message Box" may help. It seems that a
> WM_QUIT is needed to get the MB to take notice, but the problem then is
how
> to ignore it subsequently and avoid shutting down the entire app, unless
> that is what you want to do anyway. If you don't want to shut it down,
then
> your next problem will be to ensure it is in a consistent state, which
might
> not be easy if you've closed dialogs, etc.

Hopefully canceling them isn't too bad to do - if it's idiot proof,
hopefully it's time-out proof too.  Point taken though =:0


> I can't help thinking it would be better to just configure the screen
saver
> to come up after your preferred period of inactivity, and set it up to
> require a password.

Agreed.  I already had plans to suggest that as a partial/backup solution,
but it isn't really what we want.  One additional problem is that the
"document" is locked when open, hence a requirement to let go of it, even
absent user input.  There's more to this, but I'll have to explain that off
line.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: More on user inactivity

Christopher J. Demers
"Bill Schwab" <[hidden email]> wrote in message
news:bboku9$bo3t0$[hidden email]...

> Blair,
>
> > I can't help thinking it would be better to just configure the screen
> saver
> > to come up after your preferred period of inactivity, and set it up to
> > require a password.
>
> Agreed.  I already had plans to suggest that as a partial/backup solution,
> but it isn't really what we want.  One additional problem is that the
> "document" is locked when open, hence a requirement to let go of it, even
> absent user input.  There's more to this, but I'll have to explain that
off
> line.

What about writing a Dolphin screen saver, and then using IPC to talk with
the Dolphin application to tell it to let go of the document, or to get
whatever you want displayed on the screen saver?  I have not done anything
like this so I don't know how involved it would be.

Chris