darcs patch: add configurable X Event handling

Question:
Should it be eventHooks :: [Event -> X Bool] instead of eventHook :: Event ->
X Bool, or should there be a composeEvents function, like ManageHook.composeAll?
Sun Nov 11 17:46:16 EST 2007 Devin Mullins

On Sun, Nov 11, 2007 at 05:56:39PM -0500, Devin Mullins wrote:
Question: Should it be eventHooks :: [Event -> X Bool] instead of eventHook :: Event -> X Bool, or should there be a composeEvents function, like ManageHook.composeAll?
I'd actually prefer something like :: type EventHook = Event -> X (Bool, Maybe EventHook) This way, we could define an event hook that will remove itself, or modify itself (or store state). As it is, this eventHook is rather limited. then: eventHook :: EventHook And we could define one or more composeEvents functions. I think I'd also prefer for the EventHook to accept a SomeMessage, rather than an X event. This would allow us to communicate with EventHooks using our existing sendMessage function... or allow EventHooks to be written that intercept messages. So that we could (if we chose) unify EventHooks with some of the aspects of ManageHooks simply by sending Messages on new-window-creation. So my real preference would be: type MessageHook = SomeMessage -> X (Bool, Maybe MessageHook) and then we'd send all Events or Messages to the MessageHook before processing them with handle or the layout. At this point, I wonder whether we should follow the layouts more closely and make the MessageHooks be data rather than functions, so that they can store state that persists across mod-q. So we'd have something like: class Show mh => MessageHandler mh where handleMessage :: mh -> SomeMessage -> X (Bool, Maybe mh) handleMessage mh m = do b <- staticHandle mh m return (b, Nothing) staticHandle :: mh -> SomeMessage -> X Bool staticHandle mh m = observeMessage m >> return False observeMessage :: mh -> SomeMessage -> X () observeMessage _ _ = return () At this point, we've got message handlers that can store state across restarts (using the same mechanism we use for Layouts), can intercept any Message, etc. I defined three methods so folks who don't want changing state, or don't want to actually intercept messages don't have to worry about how to return more complicated state correctly. So your example would be: data FocusDoesntFollowMouse = FocusDoesntFollowMouse deriving ( Read, Show ) instance MessageHandler FocusDoesntFollowMouse where staticHandle _ m | Just (CrossingEvent {}) = return False | otherwise = return False It's a bit more verbose, but of course, we'd want it in XMC, so the user wouldn't be much bothered by this. The user would just specify something like defaultConfig { messageHandler = FocusDoesntFollowMouse } Of course, we'd want combinators, but those'd be pretty straightforward. Thoughts? -- David Roundy Department of Physics Oregon State University

At this point, I wonder whether we should follow the layouts more closely and make the MessageHooks be data rather than functions, so that they can store state that persists across mod-q. So we'd have something like: *That's* specifically what I don't want. The whole point of eventHook (or messageHook) is that it avoids the Read/Show requirement, so users can specify custom (in this case) urgency hooks without a load of class/instance boilerplate. Otherwise, I'd just leave it as a LayoutModifier, as it is now.
I'm intrigued with the state idea. What did you have in mind?

On Mon, Nov 12, 2007 at 12:11:06PM -0500, Devin Mullins wrote:
At this point, I wonder whether we should follow the layouts more closely and make the MessageHooks be data rather than functions, so that they can store state that persists across mod-q. So we'd have something like:
*That's* specifically what I don't want. The whole point of eventHook (or messageHook) is that it avoids the Read/Show requirement, so users can specify custom (in this case) urgency hooks without a load of class/instance boilerplate. Otherwise, I'd just leave it as a LayoutModifier, as it is now.
I suppose it's a bit of a tossup. I don't see that as the whole point. To me, the whole point would be to allow the definition of hooks that aren't workspace-specific, as is the case with layout hooks. Also note that you could make a read-failing messageHook, as you did (I believe) with your layout modifier, and the users' result would be much less annoying than losing state. And we could also allow storing of state without maintaining it across restarts, which would capture most of the usefulness of state-storing.
I'm intrigued with the state idea. What did you have in mind?
What do you mean? How it'd work or what it'd be used for? The most obvious use would be to simultaneously eliminate the unsafePerformIO global variable hack from for the urgency hooks, and simultaneously allow the list of urgent windows to be maintained on restart (if that's what we want). Another obvious use for state would be to allow us to implement notification windows (to work with urgent hooks) for instance. Or to allow dynamic switching between focus-follows-mouse and click-to-focus behavior. Or perhaps implementing a "sticky" bit for windows, which causes them to be automatically added to any new workspaces. I'm sure more uses will follow that I haven't yet imagined. But basically, my expectation would be that just as layouts are now used for interesting features that are unrelated to the original "layout" feature (e.g. WorkspaceDir, WindowNavigation, your urgency layout modifier) I suspect a general event hook will soon be expected to do more than a static function can describe. In fact, I think your UrgencyHook is a perfect example: it already requires the storage of state. -- David Roundy Department of Physics Oregon State University

On Mon, Nov 12, 2007 at 09:48:11AM -0800, David Roundy wrote:
I suppose it's a bit of a tossup. I don't see that as the whole point. To me, the whole point would be to allow the definition of hooks that aren't workspace-specific, as is the case with layout hooks.
Well, the only reason I am so eager to see it in core, and wrote the patch, was to avoid the Read/Show requirement. So it's the whole point for me.
Also note that you could make a read-failing messageHook, as you did (I believe) with your layout modifier, and the users' result would be much less annoying than losing state. And we could also allow storing of state without maintaining it across restarts, which would capture most of the usefulness of state-storing.
WithUrgencyHook is not read-failing. If it were, that would suck, as every user would have to suffer losing layout state accross restart. If it were silently read-failing (e.g. Invisible), I wouldn't know how to construct an urgency hook after read start, since it's not statically linked (as of the config/main inversion). Rather, it's a simple subclass of (Read,Show) that contains a single urgencyHook method.* (Thanks to sjanssen for that idea.) Now, I suppose with eventHooks :: [EventHook] you could isolate the read failure...
What do you mean? How it'd work or what it'd be used for? The most obvious use would be to simultaneously eliminate the unsafePerformIO global variable hack from for the urgency hooks, and simultaneously allow the list of urgent windows to be maintained on restart (if that's what we want).
The former could be done without state, by prepending to the main IO action. (On a side note, I wonder if a better signature for these "main-modifiers" isn't something like (XConfig l -> IO (), XConfig l) -> (XConfig l' -> IO (), XConfig l') which is able to compose.) The latter; hrm... how can we have readable state without a readable event hook (cleanly)?
that I haven't yet imagined. But basically, my expectation would be that just as layouts are now used for interesting features that are unrelated to the original "layout" feature (e.g. WorkspaceDir, WindowNavigation, your urgency layout modifier) I suspect a general event hook will soon be expected to do more than a static function can describe. In fact, I think
Good point. I'm sold on the state thing (so long as it can be implemented cleanly), and you had me at hello with the Message thing, but I haven't budged as regards the Read/Show requirement.

On Mon, Nov 12, 2007 at 02:01:26PM -0500, Devin Mullins wrote:
On Mon, Nov 12, 2007 at 09:48:11AM -0800, David Roundy wrote:
I suppose it's a bit of a tossup. I don't see that as the whole point. To me, the whole point would be to allow the definition of hooks that aren't workspace-specific, as is the case with layout hooks.
Well, the only reason I am so eager to see it in core, and wrote the patch, was to avoid the Read/Show requirement. So it's the whole point for me.
Okay.
Also note that you could make a read-failing messageHook, as you did (I believe) with your layout modifier, and the users' result would be much less annoying than losing state. And we could also allow storing of state without maintaining it across restarts, which would capture most of the usefulness of state-storing.
WithUrgencyHook is not read-failing. If it were, that would suck, as every user would have to suffer losing layout state accross restart. If it were silently read-failing (e.g. Invisible), I wouldn't know how to construct an urgency hook after read start, since it's not statically linked (as of the config/main inversion). Rather, it's a simple subclass of (Read,Show) that contains a single urgencyHook method.* (Thanks to sjanssen for that idea.)
Ah, I hadn't looked at that. Clever (of sjanssen, I suppose).
Now, I suppose with eventHooks :: [EventHook] you could isolate the read failure...
Yeah, that could be a real advantage. We ought to be able to have a mixture of state-preserving and non-state-preserving hooks (with care).
What do you mean? How it'd work or what it'd be used for? The most obvious use would be to simultaneously eliminate the unsafePerformIO global variable hack from for the urgency hooks, and simultaneously allow the list of urgent windows to be maintained on restart (if that's what we want).
The former could be done without state, by prepending to the main IO action. (On a side note, I wonder if a better signature for these "main-modifiers" isn't something like (XConfig l -> IO (), XConfig l) -> (XConfig l' -> IO (), XConfig l') which is able to compose.) The latter; hrm... how can we have readable state without a readable event hook (cleanly)?
I think the two would need to go together over restart.
that I haven't yet imagined. But basically, my expectation would be that just as layouts are now used for interesting features that are unrelated to the original "layout" feature (e.g. WorkspaceDir, WindowNavigation, your urgency layout modifier) I suspect a general event hook will soon be expected to do more than a static function can describe. In fact, I think
Good point.
I'm sold on the state thing (so long as it can be implemented cleanly), and you had me at hello with the Message thing, but I haven't budged as regards the Read/Show requirement.
Fortunately, that last also seems to me to be the least important. I'd lean towards including it, since it seems like if you introduce a read-failing event-hook, all you've lost is whatever was gained by introducing the Read/Show requirement. So you don't lose anything by introducing the change (so far as I know). But it'll certainly be easier without state-preservation-across-restart, which means that even if we wanted Read/Show, it'd be a good idea to implement the hooks without that feature first. So we could delay the debate until there are folks who don't want to reconfigure their xmonad because they'll lose their eventhook state. -- David Roundy Department of Physics Oregon State University

On Mon, Nov 12, 2007 at 01:00:15PM -0800, David Roundy wrote:
On Mon, Nov 12, 2007 at 02:01:26PM -0500, Devin Mullins wrote:
which is able to compose.) The latter; hrm... how can we have readable state without a readable event hook (cleanly)?
I think the two would need to go together over restart.
Wired together, yes, but is there much chance of an eventHook changing itself? Even a toggle would contain both hooks and state about which hook is selected. So we'd just need a way to tie the event to the state. (By name, akin to how you serialize objects in a OOPL.)
I'm sold on the state thing (so long as it can be implemented cleanly), and you had me at hello with the Message thing, but I haven't budged as regards the Read/Show requirement.
Fortunately, that last also seems to me to be the least important. I'd lean towards including it, since it seems like if you introduce a read-failing event-hook, all you've lost is whatever was gained by introducing the Read/Show requirement. So you don't lose anything by introducing the change (so far as I know).
Grrr. Events were very easy to do -- just intercept the call to handle. Messages come from several places, but (the important ones?) pass through broadcastMessage. However, unhandled Events do, too. Double trigger seems bad. Devin

On Tue, Nov 13, 2007 at 09:58:52AM -0500, Devin Mullins wrote:
On Mon, Nov 12, 2007 at 01:00:15PM -0800, David Roundy wrote:
I'm sold on the state thing (so long as it can be implemented cleanly), and you had me at hello with the Message thing, but I haven't budged as regards the Read/Show requirement.
Fortunately, that last also seems to me to be the least important. I'd lean towards including it, since it seems like if you introduce a read-failing event-hook, all you've lost is whatever was gained by introducing the Read/Show requirement. So you don't lose anything by introducing the change (so far as I know).
Grrr. Events were very easy to do -- just intercept the call to handle. Messages come from several places, but (the important ones?) pass through broadcastMessage. However, unhandled Events do, too. Double trigger seems bad.
True, it would require a bit of restructuring. Really, there are three ways messages should originate: either as an unhandled Event (currently broadcast), or via sendMessage or broadcastMessage. The latter two differ in that sendMessage sends it only to the focussed layout, while broadcastMessage sends the message to all layouts. I think we ought to be able to handle this with a minimal amount of restructuring. handle itself could trivially be rewritten as a messageHook. Then the main event look could simply call broadcastMessage on every X Event that comes down the pipeline. broadcastMessage would first supply the message to the messageHook (or messageHooks), and if it isn't handled would then supply it to all layouts. sendMessage (I imagine) would first give the message to the messageHook and then to the focussed layout. To me, subsuming handle in the messageHook framework sounds highly appealing. One advantage of this self-modifying hook framework would be that we ought to be able to eliminate the "dragging" field in XState, which is really just there to hold an eventHook. One advantage of *not* making MessageHooks readable is that it'd make it easier to write a self-removing hook, which would be what we'd want for something like a dragging hook: we'd want it to just disappear when the dragging is finished. I think we've got lots of good ideas here. Do you think you can code up a prototype? I have a feeling we could stick most of the code in contrib, so we could develop together and test it with only minimal changes to core. We could, for instance, replicate all of XMonad.Main in contrib, so that we (and other users) could simply call XMonad.Hooks.Main.xmonad instead of XMonad.Main.xmonad. I think that'd be an ideal testing ground, and would allow us to develop this in a leisurely manner without conflicting with core changes. Then acceptance into core would consist of a simple copy of XMonad.Hooks.Main to XMonad.Main and a redefinition of XMonad.Operations.broadcastMessage. I think handling sendMessage could be done subsequently. We might not even want sendMessage to go to messageHooks, since in a sense it is a "targeted" message, sent specifically to the current layout. In any case, we could wait on rewriting sendMessage to go throught the messageHooks. Have you (Devlin) got time to get this going? -- David Roundy Department of Physics Oregon State University

On Tue, Nov 13, 2007 at 10:43:23PM -0500, Devin Mullins wrote:
On Tue, Nov 13, 2007 at 07:27:08AM -0800, David Roundy wrote:
Have you (Devlin) got time to get this going?
I will give it a shot (just making handle a MessageHook, at first -- looking at state after that). No promises, especially since you called me Devlin.
Just to ay that this thread is very interesting and I hope I'll be able to be of some help, even with my (presently) limited time. Davin, are you working on the Main replication stuff or just on the new MessageHook? Thanks Andrea

On Wed, Nov 14, 2007 at 12:31:14PM +0100, Andrea Rossato wrote:
Davin, are you working on the Main replication stuff or just on the new MessageHook?
I think they go hand in hand, Andrew, though I'd like to replicate (and have to keep in sync) as little as possible. It should be possible to make a mainMessageHook :: SomeMessage -> X Bool that wraps handle, though I can't think of the existential voodoo off-hand to make that happen.
participants (3)
-
Andrea Rossato
-
David Roundy
-
Devin Mullins