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>
31 #include "statusbar.h"
37 #include "layouts/tile.h"
38 #include "layouts/floating.h"
41 extern AwesomeConf globalconf
;
44 handle_mouse_button_press(int screen
, unsigned int button
, unsigned int state
,
45 Button
*buttons
, char *arg
)
49 for(b
= buttons
; b
; b
= b
->next
)
50 if(button
== b
->button
&& CLEANMASK(state
) == b
->mod
&& b
->func
)
55 b
->func(screen
, b
->arg
);
61 handle_event_buttonpress(XEvent
*e
)
63 int i
, screen
, x
= 0, y
= 0;
69 XButtonPressedEvent
*ev
= &e
->xbutton
;
71 for(screen
= 0; screen
< get_screen_count(); screen
++)
72 for(statusbar
= globalconf
.screens
[screen
].statusbar
; statusbar
; statusbar
= statusbar
->next
)
73 if(statusbar
->window
== ev
->window
)
75 if(statusbar
->position
== Top
76 || globalconf
.screens
[screen
].statusbar
->position
== Bottom
)
78 for(widget
= statusbar
->widgets
; widget
; widget
= widget
->next
)
79 if(ev
->x
>= widget
->area
.x
&& ev
->x
<= widget
->area
.x
+ widget
->area
.width
)
81 widget
->button_press(widget
, ev
);
85 else if(statusbar
->position
== Right
)
87 for(widget
= statusbar
->widgets
; widget
; widget
= widget
->next
)
88 if(ev
->y
>= widget
->area
.x
&& ev
->y
<= widget
->area
.x
+ widget
->area
.width
)
90 widget
->button_press(widget
, ev
);
96 for(widget
= statusbar
->widgets
; widget
; widget
= widget
->next
)
97 if(statusbar
->width
- ev
->y
>= widget
->area
.x
98 && statusbar
->width
- ev
->y
<= widget
->area
.x
+ widget
->area
.width
)
100 widget
->button_press(widget
, ev
);
106 if((c
= get_client_bywin(globalconf
.clients
, ev
->window
)))
108 focus(c
, ev
->same_screen
, c
->screen
);
109 if(CLEANMASK(ev
->state
) == NoSymbol
110 && ev
->button
== Button1
)
113 XAllowEvents(globalconf
.display
, ReplayPointer
, CurrentTime
);
114 window_grabbuttons(get_phys_screen(c
->screen
), c
->win
, True
, True
);
117 handle_mouse_button_press(c
->screen
, ev
->button
, ev
->state
, globalconf
.buttons
.client
, NULL
);
120 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
121 if(RootWindow(e
->xany
.display
, screen
) == ev
->window
122 && XQueryPointer(e
->xany
.display
,
127 screen
= get_screen_bycoord(x
, y
);
128 handle_mouse_button_press(screen
, ev
->button
, ev
->state
,
129 globalconf
.buttons
.root
, NULL
);
135 handle_event_configurerequest(XEvent
* e
)
138 XConfigureRequestEvent
*ev
= &e
->xconfigurerequest
;
142 if((c
= get_client_bywin(globalconf
.clients
, ev
->window
)))
146 if(ev
->value_mask
& CWX
)
147 c
->rx
= c
->x
= ev
->x
- c
->border
;
148 if(ev
->value_mask
& CWY
)
149 c
->ry
= c
->y
= ev
->y
- c
->border
;
150 if(ev
->value_mask
& CWWidth
)
151 c
->rw
= c
->w
= ev
->width
;
152 if(ev
->value_mask
& CWHeight
)
153 c
->rh
= c
->h
= ev
->height
;
154 if((ev
->value_mask
& (CWX
| CWY
)) && !(ev
->value_mask
& (CWWidth
| CWHeight
)))
155 window_configure(c
->win
, c
->x
, c
->y
, c
->w
, c
->h
, c
->border
);
156 /* recompute screen */
157 old_screen
= c
->screen
;
158 c
->screen
= get_screen_bycoord(c
->x
, c
->y
);
159 if(old_screen
!= c
->screen
)
161 move_client_to_screen(c
, c
->screen
, False
);
162 statusbar_draw_all(old_screen
);
163 statusbar_draw_all(c
->screen
);
165 tag_client_with_rules(c
);
166 XMoveResizeWindow(e
->xany
.display
, c
->win
, c
->rx
, c
->ry
, c
->rw
, c
->rh
);
170 window_configure(c
->win
, c
->x
, c
->y
, c
->w
, c
->h
, c
->border
);
176 wc
.width
= ev
->width
;
177 wc
.height
= ev
->height
;
178 wc
.border_width
= ev
->border_width
;
179 wc
.sibling
= ev
->above
;
180 wc
.stack_mode
= ev
->detail
;
181 XConfigureWindow(e
->xany
.display
, ev
->window
, ev
->value_mask
, &wc
);
183 XSync(e
->xany
.display
, False
);
187 handle_event_configurenotify(XEvent
* e
)
189 XConfigureEvent
*ev
= &e
->xconfigure
;
193 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
194 if(ev
->window
== RootWindow(e
->xany
.display
, screen
)
195 && (ev
->width
!= DisplayWidth(e
->xany
.display
, screen
)
196 || ev
->height
!= DisplayHeight(e
->xany
.display
, screen
)))
198 DisplayWidth(e
->xany
.display
, screen
) = ev
->width
;
199 DisplayHeight(e
->xany
.display
, screen
) = ev
->height
;
201 /* update statusbar */
202 area
= get_screen_area(screen
, NULL
, &globalconf
.screens
[screen
].padding
);
203 globalconf
.screens
[screen
].statusbar
->width
= area
.width
;
205 XResizeWindow(e
->xany
.display
,
206 globalconf
.screens
[screen
].statusbar
->window
,
207 globalconf
.screens
[screen
].statusbar
->width
,
208 globalconf
.screens
[screen
].statusbar
->height
);
210 statusbar_draw_all(screen
);
216 handle_event_destroynotify(XEvent
* e
)
219 XDestroyWindowEvent
*ev
= &e
->xdestroywindow
;
221 if((c
= get_client_bywin(globalconf
.clients
, ev
->window
)))
222 client_unmanage(c
, WithdrawnState
);
226 handle_event_enternotify(XEvent
* e
)
229 XCrossingEvent
*ev
= &e
->xcrossing
;
233 if(ev
->mode
!= NotifyNormal
|| ev
->detail
== NotifyInferior
)
235 if((c
= get_client_bywin(globalconf
.clients
, ev
->window
)) && globalconf
.screens
[c
->screen
].sloppy_focus
)
237 focus(c
, ev
->same_screen
, c
->screen
);
238 curtags
= get_current_tags(c
->screen
);
239 if (c
->isfloating
|| curtags
[0]->layout
->arrange
== layout_floating
)
240 window_grabbuttons(get_phys_screen(c
->screen
), c
->win
, True
, False
);
244 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
245 if(ev
->window
== RootWindow(e
->xany
.display
, screen
))
246 focus(NULL
, True
, screen
);
250 handle_event_expose(XEvent
*e
)
252 XExposeEvent
*ev
= &e
->xexpose
;
254 Statusbar
*statusbar
;
257 for(screen
= 0; screen
< get_screen_count(); screen
++)
258 for(statusbar
= globalconf
.screens
[screen
].statusbar
; statusbar
; statusbar
= statusbar
->next
)
259 if(statusbar
->window
== ev
->window
)
261 statusbar_display(statusbar
);
267 handle_event_keypress(XEvent
* e
)
272 XKeyEvent
*ev
= &e
->xkey
;
276 keysym
= XKeycodeToKeysym(e
->xany
.display
, (KeyCode
) ev
->keycode
, 0);
278 /* find the right screen for this event */
279 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
280 if(XQueryPointer(e
->xany
.display
, RootWindow(e
->xany
.display
, screen
), &dummy
, &dummy
, &x
, &y
, &d
, &d
, &m
))
282 /* if screen is 0, we are on first Zaphod screen or on the
283 * only screen in Xinerama, so we can ask for a better screen
284 * number with get_screen_bycoord: we'll get 0 in Zaphod mode
285 * so it's the same, or maybe the real Xinerama screen */
287 screen
= get_screen_bycoord(x
, y
);
291 for(k
= globalconf
.keys
; k
; k
= k
->next
)
292 if(keysym
== k
->keysym
&& k
->func
293 && CLEANMASK(k
->mod
) == CLEANMASK(ev
->state
))
295 k
->func(screen
, k
->arg
);
301 handle_event_leavenotify(XEvent
* e
)
303 XCrossingEvent
*ev
= &e
->xcrossing
;
306 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
307 if((ev
->window
== RootWindow(e
->xany
.display
, screen
)) && !ev
->same_screen
)
308 focus(NULL
, ev
->same_screen
, screen
);
312 handle_event_mappingnotify(XEvent
* e
)
314 XMappingEvent
*ev
= &e
->xmapping
;
317 XRefreshKeyboardMapping(ev
);
318 if(ev
->request
== MappingKeyboard
)
319 for(screen
= 0; screen
< ScreenCount(e
->xany
.display
); screen
++)
320 grabkeys(get_phys_screen(screen
));
324 handle_event_maprequest(XEvent
* e
)
326 static XWindowAttributes wa
;
327 XMapRequestEvent
*ev
= &e
->xmaprequest
;
332 if(!XGetWindowAttributes(e
->xany
.display
, ev
->window
, &wa
))
334 if(wa
.override_redirect
)
336 if(!get_client_bywin(globalconf
.clients
, ev
->window
))
338 for(screen
= 0; wa
.screen
!= ScreenOfDisplay(e
->xany
.display
, screen
); screen
++);
339 if(screen
== 0 && XQueryPointer(e
->xany
.display
, RootWindow(e
->xany
.display
, screen
),
340 &dummy
, &dummy
, &x
, &y
, &d
, &d
, &m
))
341 screen
= get_screen_bycoord(x
, y
);
342 client_manage(ev
->window
, &wa
, screen
);
347 handle_event_propertynotify(XEvent
* e
)
351 XPropertyEvent
*ev
= &e
->xproperty
;
353 if(ev
->state
== PropertyDelete
)
355 if((c
= get_client_bywin(globalconf
.clients
, ev
->window
)))
359 case XA_WM_TRANSIENT_FOR
:
360 XGetTransientForHint(e
->xany
.display
, c
->win
, &trans
);
361 if(!c
->isfloating
&& (c
->isfloating
= (get_client_bywin(globalconf
.clients
, trans
) != NULL
)))
364 case XA_WM_NORMAL_HINTS
:
365 client_updatesizehints(c
);
368 client_updatewmhints(c
);
369 statusbar_draw_all(c
->screen
);
372 if(ev
->atom
== XA_WM_NAME
|| ev
->atom
== XInternAtom(globalconf
.display
, "_NET_WM_NAME", False
))
374 client_updatetitle(c
);
375 if(c
== globalconf
.focus
->client
)
376 statusbar_draw_all(c
->screen
);
382 handle_event_unmapnotify(XEvent
* e
)
385 XUnmapEvent
*ev
= &e
->xunmap
;
387 if((c
= get_client_bywin(globalconf
.clients
, ev
->window
))
388 && ev
->event
== RootWindow(e
->xany
.display
, get_phys_screen(c
->screen
))
389 && ev
->send_event
&& window_getstate(c
->win
) == NormalState
)
390 client_unmanage(c
, WithdrawnState
);
394 handle_event_shape(XEvent
* e
)
396 XShapeEvent
*ev
= (XShapeEvent
*) e
;
397 Client
*c
= get_client_bywin(globalconf
.clients
, ev
->window
);
400 window_setshape(get_phys_screen(c
->screen
), c
->win
);
404 handle_event_randr_screen_change_notify(XEvent
*e
)
406 XRRUpdateConfiguration(e
);
410 handle_event_clientmessage(XEvent
*e
)
412 ewmh_process_client_message(&e
->xclient
);
416 grabkeys(int phys_screen
)
421 XUngrabKey(globalconf
.display
, AnyKey
, AnyModifier
, RootWindow(globalconf
.display
, phys_screen
));
422 for(k
= globalconf
.keys
; k
; k
= k
->next
)
424 if((code
= XKeysymToKeycode(globalconf
.display
, k
->keysym
)) == NoSymbol
)
426 XGrabKey(globalconf
.display
, code
, k
->mod
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
427 XGrabKey(globalconf
.display
, code
, k
->mod
| LockMask
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
428 XGrabKey(globalconf
.display
, code
, k
->mod
| globalconf
.numlockmask
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
429 XGrabKey(globalconf
.display
, code
, k
->mod
| globalconf
.numlockmask
| LockMask
, RootWindow(globalconf
.display
, phys_screen
), True
, GrabModeAsync
, GrabModeAsync
);
432 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80