summaryrefslogtreecommitdiff
path: root/root.c
diff options
context:
space:
mode:
authorGary Wong <gtw@gnu.org>2009-08-22 22:31:14 -0600
committerGary Wong <gtw@gnu.org>2009-08-22 22:31:14 -0600
commitf56f44b401baa435693efe497b0cda8749a279fe (patch)
treea59f7b711c8a5bdbe19f034d49123d7c0739100d /root.c
Initial commit (gwm-basic 1.0).
Diffstat (limited to 'root.c')
-rw-r--r--root.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/root.c b/root.c
new file mode 100644
index 0000000..9964bef
--- /dev/null
+++ b/root.c
@@ -0,0 +1,223 @@
+/*
+ * root.c
+ *
+ * Part of gwm, the Gratuitous Window Manager,
+ * by Gary Wong, <gtw@gnu.org>.
+ *
+ * Copyright (C) 2009 Gary Wong
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $Id$
+ */
+
+#include <config.h>
+
+#include <xcb/xcb.h>
+
+#include "gwm.h"
+
+#include "actions.h"
+#include "keyboard.h"
+#include "root.h"
+#include "window-table.h"
+
+static void root_key_press( struct gwm_window *window,
+ xcb_key_press_event_t *ev ) {
+
+ int i;
+
+ for( i = 0; i < NUM_KEY_ACTIONS; i++ )
+ if( keyboard_map[ ev->detail ][ 0 ] == key_actions[ i ].keysym &&
+ ( ev->state & 0xFF & key_actions[ i ].modifiers ) ==
+ key_actions[ i ].modifiers ) {
+ key_actions[ i ].handler( window, (xcb_generic_event_t *) ev );
+
+ break;
+ }
+}
+
+static const struct button_action {
+ int button;
+ xcb_mod_mask_t modifiers;
+ void ( *handler )( struct gwm_window *window, xcb_generic_event_t *ev );
+} button_actions[] = {
+ /* This table should be configurable, of course. */
+ { 1, 0, action_map_all_icons },
+ { 3, 0, action_start_xterm }
+};
+
+#define NUM_BUTTON_ACTIONS ( sizeof button_actions / sizeof *button_actions )
+
+static void root_button_press( struct gwm_window *window,
+ xcb_button_press_event_t *ev ) {
+
+ int i;
+
+ if( ev->child )
+ return;
+
+ for( i = 0; i < NUM_BUTTON_ACTIONS; i++ )
+ if( ev->detail == button_actions[ i ].button &&
+ ( ev->state & 0xFF & button_actions[ i ].modifiers ) ==
+ button_actions[ i ].modifiers ) {
+ button_actions[ i ].handler( window, (xcb_generic_event_t *) ev );
+
+ break;
+ }
+}
+
+static void root_enter_notify( struct gwm_window *window,
+ xcb_enter_notify_event_t *ev ) {
+
+ if( focus_frame && ( ev->detail == XCB_NOTIFY_DETAIL_INFERIOR ||
+ ev->detail == XCB_NOTIFY_DETAIL_NONLINEAR ) ) {
+ deactivate_focus_frame();
+
+ xcb_set_input_focus( c, XCB_INPUT_FOCUS_NONE,
+ XCB_INPUT_FOCUS_POINTER_ROOT, ev->time );
+
+ focus_frame = NULL;
+ }
+
+ install_window_colormap( window->screen, NULL, ev->time );
+}
+
+static void root_map_request( struct gwm_window *window,
+ xcb_map_request_event_t *ev ) {
+
+ manage_window( ev->window, TRUE );
+}
+
+static void root_configure_request( struct gwm_window *window,
+ xcb_configure_request_event_t *ev ) {
+ int i = 0;
+ uint32_t values[ 7 ];
+
+ /* Configuring an unmanaged window -- just honour the request as is. */
+ if( ev->value_mask & XCB_CONFIG_WINDOW_X )
+ values[ i++ ] = ev->x;
+ if( ev->value_mask & XCB_CONFIG_WINDOW_Y )
+ values[ i++ ] = ev->y;
+ if( ev->value_mask & XCB_CONFIG_WINDOW_WIDTH )
+ values[ i++ ] = ev->width;
+ if( ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT )
+ values[ i++ ] = ev->height;
+ if( ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH )
+ values[ i++ ] = ev->border_width;
+ if( ev->value_mask & XCB_CONFIG_WINDOW_SIBLING )
+ values[ i++ ] = ev->sibling;
+ if( ev->value_mask & XCB_CONFIG_WINDOW_STACK_MODE )
+ values[ i++ ] = ev->stack_mode;
+
+ xcb_configure_window( c, ev->window, ev->value_mask, values );
+}
+
+static void root_circulate_request( struct gwm_window *window,
+ xcb_circulate_request_event_t *ev ) {
+
+ uint32_t value = ev->place == XCB_PLACE_ON_TOP ? XCB_STACK_MODE_ABOVE :
+ XCB_STACK_MODE_BELOW;
+
+ /* Circulating children of the root -- honour the request as is. */
+ xcb_configure_window( c, ev->window, XCB_CONFIG_WINDOW_STACK_MODE,
+ &value );
+}
+
+static void root_synthetic( struct gwm_window *root,
+ xcb_generic_event_t *ev ) {
+
+ xcb_unmap_notify_event_t *unmap = (xcb_unmap_notify_event_t *) ev;
+ xcb_configure_request_event_t *config =
+ (xcb_configure_request_event_t *) ev;
+ struct gwm_window *window;
+
+ switch( ev->response_type & ~SEND_EVENT_MASK ) {
+ case XCB_UNMAP_NOTIFY:
+ /* Handle a synthetic UnmapNotify request to move a window to
+ the Withdrawn state (see ICCCM 2.0, section 4.1.4). */
+ if( ( window = lookup_window( unmap->window ) ) &&
+ window->type == WINDOW_MANAGED )
+ unmanage_window( window );
+
+ break;
+
+ case XCB_CONFIGURE_REQUEST:
+ /* Handle a synthetic ConfigureRequest, which should be used
+ only to restack managed windows relative to windows which
+ were originally siblings (see ICCCM 4.1.5). */
+ if( ( config->value_mask & XCB_CONFIG_WINDOW_STACK_MODE ) &&
+ ( window = lookup_window( config->window ) ) &&
+ window->type == WINDOW_MANAGED ) {
+ struct gwm_window *sibling;
+ uint32_t values[ 2 ];
+
+ if( ( sibling = lookup_window( config->sibling ) ) &&
+ sibling->type == WINDOW_MANAGED )
+ sibling = sibling->u.managed.frame;
+
+ values[ 0 ] = sibling ? sibling->w : config->sibling;
+ values[ 1 ] = config->stack_mode;
+
+ handle_error_reply( xcb_configure_window(
+ c, window->u.managed.frame->w,
+ XCB_CONFIG_WINDOW_SIBLING |
+ XCB_CONFIG_WINDOW_STACK_MODE,
+ values ),
+ ERR_MASK_VALUE | ERR_MASK_WINDOW |
+ ERR_MASK_MATCH );
+ }
+
+ break;
+ }
+}
+
+event_handler root_handlers[] = {
+ NULL, /* Error */
+ NULL, /* Reply */
+ (event_handler) root_key_press,
+ NULL, /* KeyRelease */
+ (event_handler) root_button_press,
+ NULL, /* ButtonRelease */
+ NULL, /* MotionNotify */
+ (event_handler) root_enter_notify,
+ NULL, /* LeaveNotify */
+ NULL, /* FocusIn */
+ NULL, /* FocusOut */
+ NULL, /* KeymapNotify */
+ NULL, /* Expose */
+ NULL, /* GraphicsExpose */
+ NULL, /* NoExposure */
+ NULL, /* VisibilityNotify */
+ NULL, /* CreateNotify */
+ NULL, /* DestroyNotify */
+ NULL, /* UnmapNotify */
+ NULL, /* MapNotify */
+ (event_handler) root_map_request,
+ NULL, /* ReparentNotify */
+ NULL, /* ConfigureNotify */
+ (event_handler) root_configure_request,
+ NULL, /* GravityNotify */
+ NULL, /* ResizeRequest */
+ NULL, /* CirculateNotify */
+ (event_handler) root_circulate_request,
+ NULL, /* PropertyNotify */
+ NULL, /* SelectionClear */
+ NULL, /* SelectionRequest */
+ NULL, /* SelectionNotify */
+ NULL, /* ColormapNotify */
+ NULL, /* ClientMessage */
+ NULL, /* MappingNotify */
+ (event_handler) root_synthetic,
+ NULL /* ShapeNotify */
+};