2 * event.c - event handlers
4 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <X11/keysym.h>
23 #include <X11/Xatom.h>
24 #include <X11/Xutil.h>
25 #include <X11/extensions/shape.h>
26 #include <X11/extensions/Xrandr.h>
27 #include <X11/extensions/Xinerama.h>
32 #include "statusbar.h"
40 #include "layouts/tile.h"
41 #include "layouts/floating.h"
43 extern AwesomeConf globalconf
;
46 handle_mouse_button_press(int screen
, unsigned int button
, unsigned int state
,
47 Button
*buttons
, char *arg
)
51 for(b
= buttons
; b
; b
= b
->next
)
52 if(button
== b
->button
&& CLEANMASK(state
) == b
->mod
&& b
->func
)
57 b
->func(screen
, b
->arg
);
63 handle_event_buttonpress(XEvent
*e
)
65 int i
, screen
, x
= 0, y
= 0;
71 XButtonPressedEvent
*ev
= &e
->xbutton
;
73 for(screen
= 0; screen
< globalconf
.nscreen
; screen
++)
74 for(statusbar
= globalconf
.screens
[screen
].statusbar
; statusbar
; statusbar
= statusbar
->next
)
75 if(statusbar
->sw
->window
== ev
->window
|| statusbar
->sw
->window
== ev
->subwindow
)
77 switch(statusbar
->position
)
81 for(widget
= statusbar
->widgets
; widget
; widget
= widget
->next
)
82 if(ev
->x
>= widget
->area
.x
&& ev
->x
< widget
->area
.x
+ widget
->area
.width
83 && ev
->y
>= widget
->area
.y
&& ev
->y
< widget
->area
.y
+ widget
->area
.height
)
85 widget
->button_press(widget
, ev
);
90 for(widget
= statusbar
->widgets
; widget
; widget
= widget
->next
)
91 if(ev
->y
>= widget
->area
.x
&& ev
->y
< widget
->area
.x
+ widget
->area
.width
92 && statusbar
->sw
->geometry
.width
- ev
->x
>= widget
->area
.y
93 && statusbar
->sw
->geometry
.width
- ev
->x
94 < widget
->area
.y
+ widget
->area
.height
)
96 widget
->button_press(widget
, ev
);
101 for(widget
= statusbar
->widgets
; widget
; widget
= widget
->next
)
102 if(statusbar
->sw
->geometry
.height
- ev
->y
>= widget
->area
.x
103 && statusbar
->sw
->geometry
.height
- ev
->y
104 < widget
->area
.x
+ widget
->area
.width
105 && ev
->x
>= widget
->area
.y
&& ev
->x
< widget
->area
.y
+ widget
->area
.height
)
107 widget
->button_press(widget
, ev
);
114 /* return if no widget match */
118 if((c
= client_get_bywin(globalconf
.clients
, ev
->window
)))
120 client_focus(c
, c
->screen
, True
);
121 if(CLEANMASK(ev
->state
) == NoSymbol
122 && ev
->button
== Button1
)
124 XAllowEvents(globalconf
.display
, ReplayPointer
, CurrentTime
);
125 window_grabbuttons(get_phys_screen(c
->screen
), c
->win
);
128 handle_mouse_button_press(c
->screen
, ev
->button
, ev
->state
, globalconf
.buttons
.client
, NULL
);
131 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
132 if(RootWindow(e
->xany
.display
, screen
) == ev
->window
133 && XQueryPointer(e
->xany
.display
,
138 screen
= screen_get_bycoord(screen
, x
, y
);
139 handle_mouse_button_press(screen
, ev
->button
, ev
->state
,
140 globalconf
.buttons
.root
, NULL
);
146 handle_event_configurerequest(XEvent
* e
)
149 XConfigureRequestEvent
*ev
= &e
->xconfigurerequest
;
154 if((c
= client_get_bywin(globalconf
.clients
, ev
->window
)))
156 geometry
= c
->geometry
;
158 if(ev
->value_mask
& CWX
)
160 if(ev
->value_mask
& CWY
)
162 if(ev
->value_mask
& CWWidth
)
163 geometry
.width
= ev
->width
;
164 if(ev
->value_mask
& CWHeight
)
165 geometry
.height
= ev
->height
;
167 if(geometry
.x
!= c
->geometry
.x
|| geometry
.y
!= c
->geometry
.y
168 || geometry
.width
!= c
->geometry
.width
|| geometry
.height
!= c
->geometry
.height
)
170 old_screen
= c
->screen
;
172 client_resize(c
, geometry
, False
);
174 tag_client_with_rule(c
, rule_matching_client(c
));
177 globalconf
.screens
[c
->screen
].need_arrange
= True
;
180 window_configure(c
->win
, geometry
, c
->border
);
186 wc
.width
= ev
->width
;
187 wc
.height
= ev
->height
;
188 wc
.border_width
= ev
->border_width
;
189 wc
.sibling
= ev
->above
;
190 wc
.stack_mode
= ev
->detail
;
191 XConfigureWindow(e
->xany
.display
, ev
->window
, ev
->value_mask
, &wc
);
196 handle_event_configurenotify(XEvent
* e
)
198 XConfigureEvent
*ev
= &e
->xconfigure
;
201 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
202 if(ev
->window
== RootWindow(e
->xany
.display
, screen
)
203 && (ev
->width
!= DisplayWidth(e
->xany
.display
, screen
)
204 || ev
->height
!= DisplayHeight(e
->xany
.display
, screen
)))
205 /* it's not that we panic, but restart */
206 uicb_exec(0, globalconf
.argv
);
210 handle_event_destroynotify(XEvent
* e
)
213 XDestroyWindowEvent
*ev
= &e
->xdestroywindow
;
215 if((c
= client_get_bywin(globalconf
.clients
, ev
->window
)))
220 handle_event_enternotify(XEvent
* e
)
223 XCrossingEvent
*ev
= &e
->xcrossing
;
226 if(ev
->mode
!= NotifyNormal
)
229 if((c
= client_get_bywin(globalconf
.clients
, ev
->window
)))
231 window_grabbuttons(get_phys_screen(c
->screen
), c
->win
);
232 if(globalconf
.screens
[c
->screen
].sloppy_focus
)
233 client_focus(c
, c
->screen
,
234 (globalconf
.screens
[c
->screen
].sloppy_focus
235 && globalconf
.screens
[c
->screen
].sloppy_focus_raise
));
238 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
239 if(ev
->window
== RootWindow(e
->xany
.display
, screen
))
240 window_root_grabbuttons(screen
);
244 handle_event_expose(XEvent
*e
)
246 XExposeEvent
*ev
= &e
->xexpose
;
248 Statusbar
*statusbar
;
251 for(screen
= 0; screen
< globalconf
.nscreen
; screen
++)
252 for(statusbar
= globalconf
.screens
[screen
].statusbar
; statusbar
; statusbar
= statusbar
->next
)
253 if(statusbar
->sw
->window
== ev
->window
)
255 statusbar_display(statusbar
);
261 handle_event_keypress(XEvent
* e
)
265 XKeyEvent
*ev
= &e
->xkey
;
269 /* find the right screen for this event */
270 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
271 if(XQueryPointer(e
->xany
.display
, RootWindow(e
->xany
.display
, screen
), &dummy
, &dummy
, &x
, &y
, &d
, &d
, &m
))
273 /* if screen is 0, we are on first Zaphod screen or on the
274 * only screen in Xinerama, so we can ask for a better screen
275 * number with screen_get_bycoord: we'll get 0 in Zaphod mode
276 * so it's the same, or maybe the real Xinerama screen */
277 screen
= screen_get_bycoord(screen
, x
, y
);
281 for(k
= globalconf
.keys
; k
; k
= k
->next
)
282 if(ev
->keycode
== k
->keycode
&&
283 k
->func
&& CLEANMASK(k
->mod
) == CLEANMASK(ev
->state
))
285 k
->func(screen
, k
->arg
);
291 handle_event_leavenotify(XEvent
* e
)
293 XCrossingEvent
*ev
= &e
->xcrossing
;
296 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
297 if((ev
->window
== RootWindow(e
->xany
.display
, screen
)) && !ev
->same_screen
)
298 client_focus(NULL
, screen
, True
);
302 handle_event_mappingnotify(XEvent
*e
)
304 XMappingEvent
*ev
= &e
->xmapping
;
307 XRefreshKeyboardMapping(ev
);
308 if(ev
->request
== MappingKeyboard
)
309 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
310 grabkeys(get_phys_screen(screen
));
314 handle_event_maprequest(XEvent
*e
)
316 static XWindowAttributes wa
;
317 XMapRequestEvent
*ev
= &e
->xmaprequest
;
318 int screen
= 0, x
, y
, d
;
322 if(!XGetWindowAttributes(e
->xany
.display
, ev
->window
, &wa
))
324 if(wa
.override_redirect
)
326 if(!client_get_bywin(globalconf
.clients
, ev
->window
))
328 if(XineramaIsActive(globalconf
.display
)
329 && XQueryPointer(e
->xany
.display
, RootWindow(e
->xany
.display
, screen
),
330 &dummy
, &dummy
, &x
, &y
, &d
, &d
, &m
))
331 screen
= screen_get_bycoord(screen
, x
, y
);
333 for(screen
= 0; wa
.screen
!= ScreenOfDisplay(e
->xany
.display
, screen
); screen
++);
335 client_manage(ev
->window
, &wa
, screen
);
340 handle_event_propertynotify(XEvent
* e
)
344 XPropertyEvent
*ev
= &e
->xproperty
;
346 if(ev
->state
== PropertyDelete
)
348 if((c
= client_get_bywin(globalconf
.clients
, ev
->window
)))
352 case XA_WM_TRANSIENT_FOR
:
353 XGetTransientForHint(e
->xany
.display
, c
->win
, &trans
);
355 && (c
->isfloating
= (client_get_bywin(globalconf
.clients
, trans
) != NULL
)))
356 globalconf
.screens
[c
->screen
].need_arrange
= True
;
358 case XA_WM_NORMAL_HINTS
:
359 client_updatesizehints(c
);
362 client_updatewmhints(c
);
365 if(ev
->atom
== XA_WM_NAME
|| ev
->atom
== XInternAtom(globalconf
.display
, "_NET_WM_NAME", False
))
366 client_updatetitle(c
);
371 handle_event_unmapnotify(XEvent
* e
)
374 XUnmapEvent
*ev
= &e
->xunmap
;
376 if((c
= client_get_bywin(globalconf
.clients
, ev
->window
))
377 && ev
->event
== RootWindow(e
->xany
.display
, get_phys_screen(c
->screen
))
378 && ev
->send_event
&& window_getstate(c
->win
) == NormalState
)
383 handle_event_shape(XEvent
* e
)
385 XShapeEvent
*ev
= (XShapeEvent
*) e
;
386 Client
*c
= client_get_bywin(globalconf
.clients
, ev
->window
);
389 window_setshape(get_phys_screen(c
->screen
), c
->win
);
393 handle_event_randr_screen_change_notify(XEvent
*e
)
395 XRRUpdateConfiguration(e
);
396 uicb_exec(0, globalconf
.argv
);
400 handle_event_clientmessage(XEvent
*e
)
402 ewmh_process_client_message(&e
->xclient
);
406 grabkeys(int phys_screen
)
411 XUngrabKey(globalconf
.display
, AnyKey
, AnyModifier
, RootWindow(globalconf
.display
, phys_screen
));
412 for(k
= globalconf
.keys
; k
; k
= k
->next
)
414 if((code
= k
->keycode
) == 0)
416 XGrabKey(globalconf
.display
, code
, k
->mod
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
417 XGrabKey(globalconf
.display
, code
, k
->mod
| LockMask
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
418 XGrabKey(globalconf
.display
, code
, k
->mod
| globalconf
.numlockmask
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
419 XGrabKey(globalconf
.display
, code
, k
->mod
| globalconf
.numlockmask
| LockMask
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
422 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80