Initialise feedback->u.feedback.
[gwm.git] / root.c
blob39a09a9efa67ba1ba99cec378bfd4c096eea74e9
1 /*
2 * root.c
4 * Part of gwm, the Gratuitous Window Manager,
5 * by Gary Wong, <gtw@gnu.org>.
7 * Copyright (C) 2009 Gary Wong
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of version 3 of the GNU General Public License as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * $Id$
24 #include <config.h>
26 #include <xcb/xcb.h>
28 #include "gwm.h"
30 #include "actions.h"
31 #include "keyboard.h"
32 #include "managed.h"
33 #include "root.h"
34 #include "window-table.h"
36 static void root_key_press( struct gwm_window *window,
37 xcb_key_press_event_t *ev ) {
39 int i;
41 for( i = 0; i < NUM_KEY_ACTIONS; i++ )
42 if( keyboard_map[ ev->detail ][ 0 ] == key_actions[ i ].keysym &&
43 ( ev->state & 0xFF & key_actions[ i ].modifiers ) ==
44 key_actions[ i ].modifiers ) {
45 key_actions[ i ].handler( window, (xcb_generic_event_t *) ev );
47 break;
51 static const struct button_action {
52 int button;
53 xcb_mod_mask_t modifiers;
54 void ( *handler )( struct gwm_window *window, xcb_generic_event_t *ev );
55 } button_actions[] = {
56 /* FIXME This table should be configurable, of course. */
57 { 1, 0, action_map_all_icons },
58 { 3, 0, action_start_xterm }
61 #define NUM_BUTTON_ACTIONS ( sizeof button_actions / sizeof *button_actions )
63 static void root_button_press( struct gwm_window *window,
64 xcb_button_press_event_t *ev ) {
66 int i;
68 if( ev->child )
69 return;
71 for( i = 0; i < NUM_BUTTON_ACTIONS; i++ )
72 if( ev->detail == button_actions[ i ].button &&
73 ( ev->state & 0xFF & button_actions[ i ].modifiers ) ==
74 button_actions[ i ].modifiers ) {
75 button_actions[ i ].handler( window, (xcb_generic_event_t *) ev );
77 break;
81 static void root_enter_notify( struct gwm_window *window,
82 xcb_enter_notify_event_t *ev ) {
84 if( focus_frame && ( ev->detail == XCB_NOTIFY_DETAIL_INFERIOR ||
85 ev->detail == XCB_NOTIFY_DETAIL_NONLINEAR ) ) {
86 deactivate_focus_frame();
88 xcb_set_input_focus( c, XCB_INPUT_FOCUS_NONE,
89 XCB_INPUT_FOCUS_POINTER_ROOT, ev->time );
91 focus_frame = NULL;
94 install_window_colormap( window->screen, NULL, ev->time );
97 static void root_circulate_request( struct gwm_window *window,
98 xcb_circulate_request_event_t *ev ) {
100 uint32_t value = ev->place == XCB_PLACE_ON_TOP ? XCB_STACK_MODE_ABOVE :
101 XCB_STACK_MODE_BELOW;
103 /* Circulating children of the root -- honour the request as is. */
104 xcb_configure_window( c, ev->window, XCB_CONFIG_WINDOW_STACK_MODE,
105 &value );
108 static void root_synthetic( struct gwm_window *root,
109 xcb_generic_event_t *ev ) {
111 xcb_unmap_notify_event_t *unmap = (xcb_unmap_notify_event_t *) ev;
112 xcb_configure_request_event_t *config =
113 (xcb_configure_request_event_t *) ev;
114 struct gwm_window *window;
116 switch( ev->response_type & ~SEND_EVENT_MASK ) {
117 case XCB_UNMAP_NOTIFY:
118 /* Handle a synthetic UnmapNotify request to move a window to
119 the Withdrawn state (see ICCCM 2.0, section 4.1.4). */
120 if( ( window = lookup_window( unmap->window ) ) &&
121 window->type == WINDOW_MANAGED )
122 unmanage_window( window );
124 break;
126 case XCB_CONFIGURE_REQUEST:
127 /* Handle a synthetic ConfigureRequest, which should be used
128 only to restack managed windows relative to windows which
129 were originally siblings (see ICCCM 4.1.5). */
130 if( ( config->value_mask & XCB_CONFIG_WINDOW_STACK_MODE ) &&
131 ( window = lookup_window( config->window ) ) &&
132 window->type == WINDOW_MANAGED ) {
133 struct gwm_window *sibling;
134 uint32_t values[ 2 ];
136 if( ( sibling = lookup_window( config->sibling ) ) &&
137 sibling->type == WINDOW_MANAGED )
138 sibling = sibling->u.managed.frame;
140 values[ 0 ] = sibling ? sibling->w : config->sibling;
141 values[ 1 ] = config->stack_mode;
143 handle_error_reply( xcb_configure_window(
144 c, window->u.managed.frame->w,
145 XCB_CONFIG_WINDOW_SIBLING |
146 XCB_CONFIG_WINDOW_STACK_MODE,
147 values ),
148 ERR_MASK_VALUE | ERR_MASK_WINDOW |
149 ERR_MASK_MATCH );
152 break;
156 event_handler root_handlers[] = {
157 NULL, /* Error */
158 NULL, /* Reply */
159 (event_handler) root_key_press,
160 NULL, /* KeyRelease */
161 (event_handler) root_button_press,
162 NULL, /* ButtonRelease */
163 NULL, /* MotionNotify */
164 (event_handler) root_enter_notify,
165 NULL, /* LeaveNotify */
166 NULL, /* FocusIn */
167 NULL, /* FocusOut */
168 NULL, /* KeymapNotify */
169 NULL, /* Expose */
170 NULL, /* GraphicsExpose */
171 NULL, /* NoExposure */
172 NULL, /* VisibilityNotify */
173 NULL, /* CreateNotify */
174 NULL, /* DestroyNotify */
175 NULL, /* UnmapNotify */
176 NULL, /* MapNotify */
177 (event_handler) withdrawn_map_request,
178 NULL, /* ReparentNotify */
179 NULL, /* ConfigureNotify */
180 (event_handler) withdrawn_configure_request,
181 NULL, /* GravityNotify */
182 NULL, /* ResizeRequest */
183 NULL, /* CirculateNotify */
184 (event_handler) root_circulate_request,
185 NULL, /* PropertyNotify */
186 NULL, /* SelectionClear */
187 NULL, /* SelectionRequest */
188 NULL, /* SelectionNotify */
189 NULL, /* ColormapNotify */
190 NULL, /* ClientMessage */
191 NULL, /* MappingNotify */
192 (event_handler) root_synthetic,
193 NULL /* ShapeNotify */