summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Wong <gtw@gnu.org>2009-09-01 21:27:49 -0600
committerGary Wong <gtw@gnu.org>2009-09-01 21:27:49 -0600
commitcc9aee3cc95f16bc95537535ef2413da50686623 (patch)
tree7cbaea0581170e3309e346783445657b98a85057
parentdb6024a4eb1f55605e344d9cb640424038a239be (diff)
Add new icon handling actions.
-rw-r--r--ChangeLog11
-rw-r--r--actions.c26
-rw-r--r--actions.h8
-rw-r--r--gwm.c57
-rw-r--r--gwm.h2
-rw-r--r--keyboard.c6
-rw-r--r--keyboard.h5
-rw-r--r--managed.c57
-rw-r--r--managed.h5
-rw-r--r--root.c2
10 files changed, 116 insertions, 63 deletions
diff --git a/ChangeLog b/ChangeLog
index 41f9c28..bee1e73 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2009-09-01 Gary Wong <gtw@gnu.org>
+ * actions.c (action_iconify_window, action_deiconify_window): New
+ functions.
+ * keyboard.c (establish_grabs): Replace NUM_KEY_ACTIONS with new
+ num_key_actions symbol.
+ * managed.c (set_managed_state, iconic_to_normal): Moved from gwm.c.
+ (normal_to_iconic): New function.
+ * gwm.c (handle_client_message): Use new normal_to_iconic() function.
+ * root.c (root_key_press): Likewise.
+
+2009-09-01 Gary Wong <gtw@gnu.org>
+
* menu.c, menu.h: New files.
* actions.c: Added callback parameter to all actions. All callers
changed.
diff --git a/actions.c b/actions.c
index 8c49b6b..f29403e 100644
--- a/actions.c
+++ b/actions.c
@@ -34,6 +34,7 @@
#include "actions.h"
#include "frame.h"
+#include "managed.h"
#include "menu.h"
#include "window-table.h"
@@ -101,6 +102,30 @@ extern void action_root_menu( struct gwm_window *window,
popup_menu( window, ev, sizeof root_menu / sizeof *root_menu, root_menu );
}
+extern void action_iconify_window( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp ) {
+
+ if( window->type == WINDOW_FRAME )
+ window = window->u.frame.child;
+
+ if( window->type == WINDOW_MANAGED &&
+ window->u.managed.state == STATE_NORMAL )
+ normal_to_iconic( window );
+}
+
+extern void action_deiconify_window( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp ) {
+
+ if( window->type == WINDOW_FRAME )
+ window = window->u.frame.child;
+
+ if( window->type == WINDOW_MANAGED &&
+ window->u.managed.state == STATE_ICONIC )
+ iconic_to_normal( window );
+}
+
extern void action_map_all_icons( struct gwm_window *window,
xcb_generic_event_t *ev,
union callback_param cp ) {
@@ -126,6 +151,7 @@ extern void action_window_menu( struct gwm_window *window,
/* FIXME this should be configurable, of course */
const struct menuitem window_menu[] = {
+ { "Iconify", action_iconify_window },
{ "Raise/lower", action_stack_opposite }
};
diff --git a/actions.h b/actions.h
index 9a74525..5abb2c4 100644
--- a/actions.h
+++ b/actions.h
@@ -13,6 +13,14 @@ extern void action_root_menu( struct gwm_window *window,
xcb_generic_event_t *ev,
union callback_param cp );
+extern void action_iconify_window( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp );
+
+extern void action_deiconify_window( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp );
+
extern void action_map_all_icons( struct gwm_window *window,
xcb_generic_event_t *ev,
union callback_param cp );
diff --git a/gwm.c b/gwm.c
index bb846f6..daa923f 100644
--- a/gwm.c
+++ b/gwm.c
@@ -1012,21 +1012,6 @@ static void stop_listening( struct gwm_window *window ) {
#endif
}
-static void set_managed_state( struct gwm_window *window, int state ) {
-
- uint32_t values[ 2 ];
-
- assert( window->type == WINDOW_MANAGED );
-
- /* Place a WM_STATE property on the client window (ICCCM 2.0, section
- 4.1.3.1). */
- values[ 0 ] = window->u.managed.state = state;
- values[ 1 ] = XCB_NONE;
- xcb_change_property( c, XCB_PROP_MODE_REPLACE, window->w,
- atoms[ ATOM_WM_STATE ], atoms[ ATOM_WM_STATE ],
- 32, 2, values );
-}
-
static void place_window( struct gwm_window *window, int *x, int *y,
int width, int height ) {
@@ -1436,15 +1421,6 @@ extern void unmanage_window( struct gwm_window *window ) {
frame->type = WINDOW_CHILDLESS;
}
-extern void iconic_to_normal( struct gwm_window *window ) {
-
- assert( window->type == WINDOW_MANAGED );
-
- set_managed_state( window, STATE_NORMAL );
- xcb_map_window( c, window->w );
- xcb_map_window( c, window->u.managed.frame->w );
-}
-
extern void generic_expose( struct gwm_window *window,
xcb_expose_event_t *ev ) {
@@ -2143,37 +2119,8 @@ static void handle_client_message( xcb_client_message_event_t *ev ) {
if( ( window = lookup_window( ev->window ) ) &&
window->type == WINDOW_MANAGED &&
window->u.managed.state == STATE_NORMAL &&
- ev->data.data32[ 0 ] == STATE_ICONIC ) {
- uint32_t n;
-
- set_managed_state( window, STATE_ICONIC );
- /* We need to unmap our child without invoking the normal
- UnmapNotify handler response. Unfortunately it's very
- difficult to communicate to the handler the distinction
- between the resultant UnmapNotify from an unmap here
- and an unrelated event. Checking the request sequence
- is not robust, because asynchronous events might not be
- assigned unique sequence numbers. Instead, we grab
- the server and temporarily change our event mask, which
- seems a heavyweight approach but does guarantee that
- only this event will be ignored. */
- xcb_grab_server( c );
-
- n = XCB_EVENT_MASK_PROPERTY_CHANGE |
- XCB_EVENT_MASK_COLOR_MAP_CHANGE;
- xcb_change_window_attributes( c, window->w, XCB_CW_EVENT_MASK, &n );
-
- xcb_unmap_window( c, window->w );
-
- n = XCB_EVENT_MASK_STRUCTURE_NOTIFY |
- XCB_EVENT_MASK_PROPERTY_CHANGE |
- XCB_EVENT_MASK_COLOR_MAP_CHANGE;
- xcb_change_window_attributes( c, window->w, XCB_CW_EVENT_MASK, &n );
-
- xcb_ungrab_server( c );
-
- xcb_unmap_window( c, window->u.managed.frame->w );
- }
+ ev->data.data32[ 0 ] == STATE_ICONIC )
+ normal_to_iconic( window );
} else if( ev->type == atoms[ ATOM_WM_COLORMAP_NOTIFY ] ) {
struct gwm_window *window;
diff --git a/gwm.h b/gwm.h
index 63e7534..d3c9337 100644
--- a/gwm.h
+++ b/gwm.h
@@ -345,8 +345,6 @@ extern void install_window_colormap( int screen, struct gwm_window *window,
extern void generic_expose( struct gwm_window *window,
xcb_expose_event_t *ev );
-extern void iconic_to_normal( struct gwm_window *window );
-
extern void manage_window( xcb_window_t w, int map_request );
extern void unmanage_window( struct gwm_window *window );
diff --git a/keyboard.c b/keyboard.c
index f9193de..0532c6e 100644
--- a/keyboard.c
+++ b/keyboard.c
@@ -66,11 +66,13 @@ xcb_keysym_t keyboard_map[ 0x100 ][ 4 ];
/* Map of modifiers, indexed by xcb_map_index_t. */
xcb_keycode_t *modifier_map[ 8 ];
-const struct key_action key_actions[ NUM_KEY_ACTIONS ] = {
+const struct key_action key_actions[] = {
/* FIXME This table should be configurable, of course. */
{ KEYSYM_TAB, XCB_MOD_MASK_1, action_raise_lowest },
+ { KEYSYM_F1, XCB_MOD_MASK_1, action_iconify_window },
{ KEYSYM_F5, XCB_MOD_MASK_1, action_stack_opposite }
};
+const int num_key_actions = sizeof key_actions / sizeof *key_actions;
static void establish_grabs( void ) {
@@ -103,7 +105,7 @@ static void establish_grabs( void ) {
xcb_ungrab_key( c, XCB_GRAB_ANY, screens[ screen ]->root,
XCB_GRAB_ANY );
- for( i = 0; i < NUM_KEY_ACTIONS; i++ ) {
+ for( i = 0; i < num_key_actions; i++ ) {
for( j = 0; j < 0x100 &&
keyboard_map[ j ][ 0 ] != key_actions[ i ].keysym; j++ )
;
diff --git a/keyboard.h b/keyboard.h
index 06e100b..fee0573 100644
--- a/keyboard.h
+++ b/keyboard.h
@@ -6,14 +6,13 @@ extern xcb_keysym_t keyboard_map[ 0x100 ][ 4 ];
/* Map of modifiers, indexed by xcb_map_index_t. */
extern xcb_keycode_t *modifier_map[ 8 ];
-#define NUM_KEY_ACTIONS 2
-
extern const struct key_action {
xcb_keysym_t keysym;
xcb_mod_mask_t modifiers;
void ( *handler )( struct gwm_window *window, xcb_generic_event_t *ev,
union callback_param cp );
-} key_actions[ NUM_KEY_ACTIONS ];
+} key_actions[];
+extern const int num_key_actions;
extern void get_keyboard_mapping( int first, int count );
extern void get_modifier_mapping( void );
diff --git a/managed.c b/managed.c
index abb1e99..b577573 100644
--- a/managed.c
+++ b/managed.c
@@ -38,6 +38,63 @@
#include "utf8.h"
#include "window-table.h"
+extern void set_managed_state( struct gwm_window *window, int state ) {
+
+ uint32_t values[ 2 ];
+
+ assert( window->type == WINDOW_MANAGED );
+
+ /* Place a WM_STATE property on the client window (ICCCM 2.0, section
+ 4.1.3.1). */
+ values[ 0 ] = window->u.managed.state = state;
+ values[ 1 ] = XCB_NONE;
+ xcb_change_property( c, XCB_PROP_MODE_REPLACE, window->w,
+ atoms[ ATOM_WM_STATE ], atoms[ ATOM_WM_STATE ],
+ 32, 2, values );
+}
+
+extern void iconic_to_normal( struct gwm_window *window ) {
+
+ assert( window->type == WINDOW_MANAGED );
+
+ set_managed_state( window, STATE_NORMAL );
+ xcb_map_window( c, window->w );
+ xcb_map_window( c, window->u.managed.frame->w );
+}
+
+extern void normal_to_iconic( struct gwm_window *window ) {
+
+ uint32_t n;
+
+ assert( window->type == WINDOW_MANAGED );
+
+ set_managed_state( window, STATE_ICONIC );
+
+ /* We need to unmap our child without invoking the normal
+ UnmapNotify handler response. Unfortunately it's very
+ difficult to communicate to the handler the distinction between
+ the resultant UnmapNotify from an unmap here and an unrelated
+ event. Checking the request sequence is not robust, because
+ asynchronous events might not be assigned unique sequence
+ numbers. Instead, we grab the server and temporarily change
+ our event mask, which seems a heavyweight approach but does
+ guarantee that only this event will be ignored. */
+ xcb_grab_server( c );
+
+ n = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+ xcb_change_window_attributes( c, window->w, XCB_CW_EVENT_MASK, &n );
+
+ xcb_unmap_window( c, window->w );
+
+ n = XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE |
+ XCB_EVENT_MASK_COLOR_MAP_CHANGE;
+ xcb_change_window_attributes( c, window->w, XCB_CW_EVENT_MASK, &n );
+
+ xcb_ungrab_server( c );
+
+ xcb_unmap_window( c, window->u.managed.frame->w );
+}
+
static void managed_destroy_notify( struct gwm_window *window,
xcb_destroy_notify_event_t *ev ) {
diff --git a/managed.h b/managed.h
index f421d64..e20633c 100644
--- a/managed.h
+++ b/managed.h
@@ -1,6 +1,11 @@
#ifndef MANAGED_H
#define MANAGED_H
+extern void iconic_to_normal( struct gwm_window *window );
+extern void normal_to_iconic( struct gwm_window *window );
+
+extern void set_managed_state( struct gwm_window *window, int state );
+
#if USE_SHAPE
extern void match_managed_shape( struct gwm_window *window );
#endif
diff --git a/root.c b/root.c
index fa64df8..cf00d8c 100644
--- a/root.c
+++ b/root.c
@@ -39,7 +39,7 @@ static void root_key_press( struct gwm_window *window,
int i;
- for( i = 0; i < NUM_KEY_ACTIONS; 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 ) {