summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Wong <gtw@gnu.org>2009-09-01 22:17:03 -0600
committerGary Wong <gtw@gnu.org>2009-09-01 22:17:03 -0600
commit38546109c98e98b933a6e3a8e29572e29e16c1b1 (patch)
tree382610b57a978905be235abf8288f435db952803
parentcc9aee3cc95f16bc95537535ef2413da50686623 (diff)
Add a menu for selecting a window to map and raise.
-rw-r--r--ChangeLog17
-rw-r--r--actions.c87
-rw-r--r--actions.h12
-rw-r--r--gwm.c9
-rw-r--r--gwm.h3
-rw-r--r--menu.c17
-rw-r--r--root.c2
7 files changed, 132 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index bee1e73..aa3ed1f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2009-09-01 Gary Wong <gtw@gnu.org>
+ * actions.c (action_map_raise, action_window_list_menu)
+ (action_exit, window_list_activate): New functions.
+ * gwm.c (main): Use which_signal -1 to indicate a graceful exit.
+
+ * menu.c (menu_button_release, popup_menu): Remember the window
+ parameter by resource ID, instead of by pointer. That way, it is
+ simple to detect whether the window has been destroyed between
+ creation and activation of the menu.
+
+ * menu.c (menu_enter_notify): Don't try to measure the active item
+ when nothing is active.
+
+ * menu.c (destroy_menu): Don't free NULL labels.
+ (popup_menu): Don't strdup() NULL labels.
+
+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
diff --git a/actions.c b/actions.c
index f29403e..3e65c09 100644
--- a/actions.c
+++ b/actions.c
@@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdlib.h>
+#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -96,7 +97,9 @@ extern void action_root_menu( struct gwm_window *window,
const struct menuitem root_menu[] = {
{ "Map all icons", action_map_all_icons },
{ "Raise lowest window", action_raise_lowest },
- { "xterm", action_start_xterm }
+ { "xterm", action_start_xterm },
+ { NULL },
+ { "Exit", action_exit }
};
popup_menu( window, ev, sizeof root_menu / sizeof *root_menu, root_menu );
@@ -126,6 +129,25 @@ extern void action_deiconify_window( struct gwm_window *window,
iconic_to_normal( window );
}
+extern void action_map_raise( 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 ) {
+ uint32_t n;
+
+ n = XCB_STACK_MODE_ABOVE;
+ xcb_configure_window( c, window->u.managed.frame->w,
+ XCB_CONFIG_WINDOW_STACK_MODE, &n );
+
+ if( 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 ) {
@@ -159,4 +181,67 @@ extern void action_window_menu( struct gwm_window *window,
window_menu );
}
+static void window_list_activate( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp ) {
+
+ struct gwm_window *window_param;
+
+ if( ( window_param = lookup_window( cp.l ) ) ) {
+ union callback_param param;
+
+ param.p = NULL;
+ action_map_raise( window_param, ev, param );
+ }
+}
+
+extern void action_window_list_menu( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp ) {
+
+ int i, num_items;
+ struct menuitem *items;
+
+ for( i = 0, num_items = 0; i < windows.used; i++ )
+ if( windows.values[ i ]->type == WINDOW_MANAGED )
+ num_items++;
+
+ items = alloca( num_items * sizeof *items );
+
+ for( i = 0, num_items = 0; i < windows.used; i++ )
+ if( windows.values[ i ]->type == WINDOW_MANAGED ) {
+ struct gwm_window *managed = windows.values[ i ];
+ char *name = managed->u.managed.name ? managed->u.managed.name :
+ "(Untitled)";
+
+ if( managed->u.managed.state == STATE_ICONIC ) {
+ int len = strlen( name );
+ char *new = alloca( len + 3 );
+
+ new[ 0 ] = '[';
+ strcpy( new + 1, name );
+ new[ len + 1 ] = ']';
+ new[ len + 2 ] = 0;
+
+ name = new;
+ }
+
+ items[ num_items ].label = name;
+ items[ num_items ].action = window_list_activate;
+ items[ num_items ].cp.l = managed->w;
+
+ num_items++;
+ }
+
+ popup_menu( window, ev, num_items, items );
+}
+
+extern void action_exit( struct gwm_window *window, xcb_generic_event_t *ev,
+ union callback_param cp ) {
+
+ /* FIXME prompt for confirmation of exit */
+
+ signal_caught = -1;
+}
+
/* FIXME make the current frame bindings (move, resize, close?) actions too */
diff --git a/actions.h b/actions.h
index 5abb2c4..7cf498e 100644
--- a/actions.h
+++ b/actions.h
@@ -21,6 +21,10 @@ extern void action_deiconify_window( struct gwm_window *window,
xcb_generic_event_t *ev,
union callback_param cp );
+extern void action_map_raise( 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 );
@@ -32,5 +36,13 @@ extern void action_start_xterm( struct gwm_window *window,
extern void action_window_menu( struct gwm_window *window,
xcb_generic_event_t *ev,
union callback_param cp );
+
+extern void action_window_list_menu( struct gwm_window *window,
+ xcb_generic_event_t *ev,
+ union callback_param cp );
+
+extern void action_exit( struct gwm_window *window, xcb_generic_event_t *ev,
+ union callback_param cp );
+
#endif
diff --git a/gwm.c b/gwm.c
index daa923f..c770d33 100644
--- a/gwm.c
+++ b/gwm.c
@@ -147,7 +147,7 @@ static int flag_replace, flag_force;
static int flag_debug;
#endif
-static volatile int signal_caught;
+volatile int signal_caught;
static void ( *update_window )( struct gwm_window *window );
void ( *window_size )( struct gwm_window *window, int *width, int *height );
@@ -2353,9 +2353,8 @@ static void handle_events( void ) {
/* FIXME other features:
- make override-redirect windows translucent
- - desktop menu & other key/pointer bindings
- - when in the window menu, turn all windows translucent
- except for the selected item (temporarily raise that one?)
+ - when in the window menu, turn all windows translucent
+ except for the selected item (temporarily raise that one?)
- root background/cursor? (no; xsetroot for non composite case)
- standard colourmaps? (no; xstdcmap does that)
- DPMS
@@ -2594,7 +2593,7 @@ extern int main( int argc, char *argv[] ) {
shutdown_display();
- if( which_signal ) {
+ if( which_signal > 0 ) {
raise( which_signal );
return 1;
diff --git a/gwm.h b/gwm.h
index d3c9337..94c1226 100644
--- a/gwm.h
+++ b/gwm.h
@@ -257,7 +257,7 @@ struct gwm_window {
struct gwm_window *frame;
} button;
struct _gwm_menu {
- struct gwm_window *window_param;
+ xcb_window_t window_param;
int num_items, active_item;
int width;
struct gwm_window **items; /* must be free()d */
@@ -286,6 +286,7 @@ extern struct gwm_window *fake_window; /* a window created solely to hold the
WM_Sn selections */
extern const char *argv0;
+extern volatile int signal_caught;
extern FORMAT( printf, 1, 2 ) void warning( char *format, ... );
extern FORMAT( printf, 1, 2 ) NORETURN void fatal( char *format, ... );
diff --git a/menu.c b/menu.c
index 3497103..6b1e573 100644
--- a/menu.c
+++ b/menu.c
@@ -44,7 +44,8 @@ static void destroy_menu( struct gwm_window *menu ) {
int i;
for( i = 0; i < menu->u.menu.num_items; i++ ) {
- free( menu->u.menu.items[ i ]->u.menuitem.label );
+ if( menu->u.menu.items[ i ]->u.menuitem.label )
+ free( menu->u.menu.items[ i ]->u.menuitem.label );
forget_window( menu->u.menu.items[ i ] );
}
@@ -65,7 +66,7 @@ static void menu_button_release( struct gwm_window *window,
if( final_release( ev ) ) {
if( window->u.menu.active_item >= 0 ) {
- window_param = window->u.menu.window_param;
+ window_param = lookup_window( window->u.menu.window_param );
action = window->u.menu.items[ window->u.menu.active_item ]->
u.menuitem.action;
cp = window->u.menu.items[ window->u.menu.active_item ]->
@@ -75,7 +76,7 @@ static void menu_button_release( struct gwm_window *window,
destroy_menu( window );
- if( action )
+ if( action && window_param )
action( window_param, (xcb_generic_event_t *) ev, cp );
}
}
@@ -103,8 +104,9 @@ static void menu_enter_notify( struct gwm_window *window,
if( child->u.menuitem.label )
window_size( child, &width, &height );
else {
- window_size( window->u.menu.items[ window->u.menu.active_item ],
- &width, &height );
+ if( window->u.menu.active_item >= 0 )
+ window_size( window->u.menu.items[ window->u.menu.active_item ],
+ &width, &height );
i = -1;
}
@@ -180,7 +182,7 @@ extern void popup_menu( struct gwm_window *window, xcb_generic_event_t *ev,
menu = add_window( xcb_generate_id( c ) );
menu->screen = screen;
menu->type = WINDOW_MENU;
- menu->u.menu.window_param = window;
+ menu->u.menu.window_param = window->w;
menu->u.menu.num_items = num_items;
menu->u.menu.active_item = -1;
menu->u.menu.items = xmalloc( num_items * sizeof *menu->u.menu.items );
@@ -194,7 +196,8 @@ extern void popup_menu( struct gwm_window *window, xcb_generic_event_t *ev,
item->screen = screen;
item->type = WINDOW_MENUITEM;
item->u.menuitem.menu = menu;
- item->u.menuitem.label = strdup( items[ i ].label );
+ item->u.menuitem.label = items[ i ].label ? strdup( items[ i ].label ) :
+ NULL;
item->u.menuitem.action = items[ i ].action;
item->u.menuitem.cp = items[ i ].cp;
window_size( item, widths + i, heights + i );
diff --git a/root.c b/root.c
index cf00d8c..16b60b9 100644
--- a/root.c
+++ b/root.c
@@ -61,7 +61,7 @@ static const struct button_action {
} button_actions[] = {
/* FIXME This table should be configurable, of course. */
{ 1, 0, action_root_menu },
- { 2, 0, action_map_all_icons },
+ { 2, 0, action_window_list_menu },
{ 3, 0, action_start_xterm }
};