Hijack Window Events
Today I was fiddling around with events on Windows, and I wanted to see if it would be possible to steal any and all events from a window, without having to define a new class. This is something that is relatively easy to do in a windowing system with DOM-Event-like objects, where you can listen for an event and tell it to stop propagating right at the top of the tree. However, Cincom® VisualWorks® events don’t work like that; they’ve always been very object-message-centric, not “announcement”-centric.
So typically, you would define a new controller and implement the methods on it that you wanted to handle the different events and set that controller on a window. But, what if you didn’t want to make a new class just for that? What if you wanted to just -script- it?
I came up with this little ploy today. In it, I take the focused window, grab mouse events and then capture the events in that window so that I can handle them in a block. I like blocks.
| window eventDispatcher eventHandler | window := Screen default focusedWindow. eventDispatcher := window eventDispatcher. eventHandler := PushButton new. eventHandler eventReactions initialize. (eventHandler eventReactions reactionFor: #Button1Up) addDefaultAction: [:event | Transcript cr; nextPutAll: ‘ungrabbing mouse’. eventDispatcher ungrabMouseEventFor: eventHandler]. (eventHandler eventReactions reactionFor: #MouseMoved) addDefaultAction: [:event | Transcript cr; nextPutAll: ‘mouse moved: ‘; print: event point]. Transcript cr; nextPutAll: ‘grabbing mouse’. eventDispatcher grabMouseEventFor: eventHandler.
This is made possible because of the ongoing work to implement Skinny in VisualWorks 7.9. The eventReactions is part of an effort to modernize the widgets; in this case, by implementing nice state machines. Here, we create a push button and hijack its state machine with #initialize to reset it, then set up our button and movement callbacks.
Unfortunately we can only do this for mouse events so far. The EventDispatcher has special code to “reroute” mouse events if the window is “grabbed.” Keyboard events head to the KeyboardProcessor, not to a currentKeyboardConsumer. The same goes for events like window resizing, etc.
May be in the future …