diff options
author | Gary Wong <gtw@gnu.org> | 2009-08-22 22:31:14 -0600 |
---|---|---|
committer | Gary Wong <gtw@gnu.org> | 2009-08-22 22:31:14 -0600 |
commit | f56f44b401baa435693efe497b0cda8749a279fe (patch) | |
tree | a59f7b711c8a5bdbe19f034d49123d7c0739100d /root.c |
Initial commit (gwm-basic 1.0).
Diffstat (limited to 'root.c')
-rw-r--r-- | root.c | 223 |
1 files changed, 223 insertions, 0 deletions
@@ -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 */ +}; |