[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: problem with view-deactivate-event-handler

[apologies for selective editing of your three posts, but the lesson will
make more sense this way...I hope. :-)]

In article <9502132245.AA25348@media.mit.edu>, abegel@media.mit.edu wrote:

|I tried defining this method on a window I had, so that when it was deactivated
|it would go to the back of all of the windows.
|(defmethod view-deactivate-event-handler ((window procs-window))
|  (set-window-layer window (length (windows)))
|  (call-next-method))
|Theorectically, this should have worked.

Er, no.  You call (set-window-layer > 0) on a window that's *STILL* the
active window [because you haven't even done call-next-method, much less
any :after or :around methods on view-deactivate-event-handler of
procs-window, and it's going to be moved to the back so set-window-layer
calls view-deactivate-event-handler which calls set-window-layer on a
window that's *STILL* the active window...

If you think about what's going on, you'll realize that the bizarreness is
pretty expected.  You're recursively moving the front-window to the back,
but you never even come close to moving it there.

|I switched the call-next-method in front of the set-window-layer command, 
|thinking that call-next-method tried something funny with the placement of
|the windows, and that I could do my call after it. No dice.
|(defmethod view-deactivate-event-handler ((window procs-window))
|  (call-next-method)
|  (window-select cc-window))
|I tried this, and got incorrect behavior when cc-window wasn't the window I
|clicked on to deactivate my procs-window. I had procs-window active, clicked
|on some other window, and both that window and the cc-window showed up to be
|active, but the active key handler was in the one I had clicked...
|How can I do this?

Now, when you switched the two statements, you had a more reasonable shot
at it, but who's to say that the implementors didn't put in the
cleanup/deactivate code in an :after or :around
view-deactivate-event-handler method?  ie, until
view-deactivate-event-handler RETURNS, the window is still the front one,
or, more likely, in some sort of limbo/mu state where neither procs-window
nor the clicked window [and certainly not cc-window] can be said to be the

Also, view-deactivate-event-handler is being called by the clicked
window's click-event-handler, or, possibly, its
view-activate-event-handler, or maybe it's window-manager's
click-event-handler.  Whatever.  Any of those routines probably mucks with
window state to finalize the clicked window's 'frontness' after telling
procs-window it ain't top dog no more.

Probably something in an :after or :around method of
view-deactivate-event-handler is finalizing the clicked window as the
front-window after you've called window-select on cc-window to make *it*
the front-window...but you did so right smack dab in the middle of the

The most likely solution in this form, which probably still won't work,
but you may learn more about view-deactivate-event-handler is:

(defmethod view-deactivate-event-handler :around ((window procs-window))
  (set-window-layer window (length (windows))))

|I finally had to resort to 
|(defmethod view-deactivate-event-handler ((window procs-window))
|  (when (eql (front-window) window)     
|     (set-window-layer window (length (windows))))
|  (call-next-method))
|which worked. It circumvented the recursion. But, hey! What gives with this
|bizarre crash causing bug?

Basically, set-window-layer is a high-level function that calls the
various activate- and deactivate-event-handlers [which make murky trap
calls to the OS].  Now you're trying to call set-window-layer from inside
the low-level calls.  Guaranteed to be trouble, even if it happens to work
this week.

Oh, you can also change eql to eq [a style thing more than saving cycles]
since you're comparing the window to itself.

|Something is up with this set-window-layer command, and might someone be 
|able to tell me what it is?

You're misusing it badly.  :-)

[evil grin on]
You are doing a *BAD* thing.  Stop it.  If the user clicks on a window,
give the user that window.  Don't shove some other damn window to the
front.  That's rude.

[back to serious]
Most likely, you've got a good reason for doing whatever it is you're
trying to do.  Post what it is and what you're thinking and you'll
probably get much better advice than just how to circumvent the correct
behaviour of windows.

Here are some possibilities that probably have nothing to do with what
you're doing, but I'm guessing:

dialog, like the "Save XXXX before closing?" which has saved so many

procs-window [A] to cc-window [B], with A going to the back, consider
adding a button to A with an action that does

(window-select B)
(set-window-layer A (length (windows)))

But even this is pretty icky, because users expect windows to behave the
same in all applications, so moving A to the back is a no-no.  That's the
whole point of having user interface guidelines.
[There are exceptions, so if you've got one of them go ahead...but be damn
sure you're right.]

(defmethod view-activate-event-handler :around ((view procs-window))
;;;maybe wrap (without-interrupts to you don't have cc-window appearing in front
;;;however briefly...
  (window-select cc-window)

This will 'pre-set' cc-window to be behind procs-window when procs-window
is selected.  This may make more sense philosophically than trying to
force it to the front when the user clicks on something else.  Of course,
it's still pretty icky, since you are now bringing two windows to the
front together when the user asked for just one.  And it's still violating
the low-level calling high-level circularity paradigm, though probably in
a safe way.

MCL, see windoid].  Or, maybe procs-window should be a windoid.  Or, maybe
whatever it is that you're clicking on that never makes it to the front
should be a windoid.  Or, maybe I'm on completely the wrong track.

window, accessed from a button on cc-window, but now I'm starting to
second-guess way too much.  :-)

|How can I tell if my application has been sent to the background?
|I'm doing some low-level assebly drawing stuff that I want to 
|disable if my application is not in the foreground. Right now, I do it
|when the window that I'm drawing in gets deactivated, but if I have
|a screen saver, the window isn't deactivated and will keep drawing
|over the screen saver!

Check out Lynch Lib at ftp.cambridge.apple.com in pub/MCL2/contrib?

There's code there that catches suspend-resume events.  Holler at me if
you have any trouble with it.  I'm not sure I've uploaded the most recent
patch. :-(

Also, check out oou13, oodles-of-utils.  It provides functions for
handling multiple monitors, which it sounds like you need to consider if
you haven't already.

-- "TANSTAAFL"  Rich lynch@ils.nwu.edu