Added basic icon support.
[gwm.git] / actions.c
blob69897fa9f376167a0e81a96d3fa4589bdb61de38
1 /*
2 * actions.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 <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #if HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <xcb/xcb.h>
34 #include "gwm.h"
36 #include "actions.h"
37 #include "frame.h"
38 #include "managed.h"
39 #include "menu.h"
40 #include "window-table.h"
42 static void external_command( char *name, ... ) {
44 if( !fork() ) {
45 va_list val;
46 int n;
47 char **args;
49 va_start( val, name );
50 for( n = 0; va_arg( val, char * ); n++ )
52 va_end( val );
54 args = alloca( ( n + 2 ) * sizeof *args );
56 args[ 0 ] = name;
58 va_start( val, name );
59 n = 1;
60 while( ( args[ n++ ] = va_arg( val, char * ) ) )
62 va_end( val );
64 setpgid( 0, 0 );
66 execvp( name, args );
68 _exit( 1 );
72 extern void action_raise_lowest( struct gwm_window *window,
73 xcb_generic_event_t *ev,
74 union callback_param cp ) {
76 xcb_circulate_window( c, XCB_CIRCULATE_RAISE_LOWEST,
77 screens[ window->screen ]->root );
80 extern void action_stack_opposite( struct gwm_window *window,
81 xcb_generic_event_t *ev,
82 union callback_param cp ) {
84 if( window->type == WINDOW_FRAME ) {
85 uint32_t n = XCB_STACK_MODE_OPPOSITE;
87 xcb_configure_window( c, window->w, XCB_CONFIG_WINDOW_STACK_MODE,
88 &n );
92 extern void action_root_menu( struct gwm_window *window,
93 xcb_generic_event_t *ev,
94 union callback_param cp ) {
96 /* FIXME this should be configurable, of course */
97 const struct menuitem root_menu[] = {
98 { "Map all icons", action_map_all_icons },
99 { "Raise lowest window", action_raise_lowest },
100 { "xterm", action_start_xterm },
101 { NULL },
102 { "Exit", action_exit }
105 popup_menu( window, ev, sizeof root_menu / sizeof *root_menu, root_menu );
108 extern void action_iconify_window( struct gwm_window *window,
109 xcb_generic_event_t *ev,
110 union callback_param cp ) {
112 if( window->type == WINDOW_FRAME )
113 window = window->u.frame.child;
115 if( window->type == WINDOW_MANAGED &&
116 window->u.managed.state == STATE_NORMAL )
117 normal_to_iconic( window );
120 extern void action_deiconify_window( struct gwm_window *window,
121 xcb_generic_event_t *ev,
122 union callback_param cp ) {
124 if( window->type == WINDOW_FRAME )
125 window = window->u.frame.child;
127 if( window->type == WINDOW_MANAGED &&
128 window->u.managed.state == STATE_ICONIC )
129 iconic_to_normal( window );
132 extern void action_map_raise( struct gwm_window *window,
133 xcb_generic_event_t *ev,
134 union callback_param cp ) {
136 if( window->type == WINDOW_FRAME )
137 window = window->u.frame.child;
139 if( window->type == WINDOW_MANAGED ) {
140 uint32_t n;
142 n = XCB_STACK_MODE_ABOVE;
143 xcb_configure_window( c, window->u.managed.frame->w,
144 XCB_CONFIG_WINDOW_STACK_MODE, &n );
146 if( window->u.managed.state == STATE_ICONIC )
147 iconic_to_normal( window );
151 extern void action_map_all_icons( struct gwm_window *window,
152 xcb_generic_event_t *ev,
153 union callback_param cp ) {
155 int i;
157 for( i = 0; i < windows.used; i++ )
158 if( windows.values[ i ]->type == WINDOW_MANAGED &&
159 windows.values[ i ]->u.managed.state == STATE_ICONIC )
160 iconic_to_normal( windows.values[ i ] );
163 extern void action_start_xterm( struct gwm_window *window,
164 xcb_generic_event_t *ev,
165 union callback_param cp ) {
167 external_command( "xterm", NULL );
170 extern void action_window_menu( struct gwm_window *window,
171 xcb_generic_event_t *ev,
172 union callback_param cp ) {
174 /* FIXME this should be configurable, of course */
175 const struct menuitem window_menu[] = {
176 { "Iconify", action_iconify_window },
177 { "Raise/lower", action_stack_opposite }
180 popup_menu( window, ev, sizeof window_menu / sizeof *window_menu,
181 window_menu );
184 static void window_list_activate( struct gwm_window *window,
185 xcb_generic_event_t *ev,
186 union callback_param cp ) {
188 struct gwm_window *window_param;
190 if( ( window_param = lookup_window( cp.l ) ) ) {
191 union callback_param param;
193 param.p = NULL;
194 action_map_raise( window_param, ev, param );
198 extern void action_window_list_menu( struct gwm_window *window,
199 xcb_generic_event_t *ev,
200 union callback_param cp ) {
202 int i, num_items;
203 struct menuitem *items;
205 for( i = 0, num_items = 0; i < windows.used; i++ )
206 if( windows.values[ i ]->type == WINDOW_MANAGED )
207 num_items++;
209 items = alloca( num_items * sizeof *items );
211 for( i = 0, num_items = 0; i < windows.used; i++ )
212 if( windows.values[ i ]->type == WINDOW_MANAGED ) {
213 struct gwm_window *managed = windows.values[ i ];
214 char *name = managed->u.managed.name ? managed->u.managed.name :
215 "(Untitled)";
217 if( managed->u.managed.state == STATE_ICONIC ) {
218 int len = strlen( name );
219 char *new = alloca( len + 3 );
221 new[ 0 ] = '[';
222 strcpy( new + 1, name );
223 new[ len + 1 ] = ']';
224 new[ len + 2 ] = 0;
226 name = new;
229 items[ num_items ].label = name;
230 items[ num_items ].action = window_list_activate;
231 items[ num_items ].cp.l = managed->w;
232 items[ num_items ].icon = managed;
234 num_items++;
237 popup_menu( window, ev, num_items, items );
240 extern void action_exit( struct gwm_window *window, xcb_generic_event_t *ev,
241 union callback_param cp ) {
243 /* FIXME prompt for confirmation of exit */
245 signal_caught = -1;
248 /* FIXME make the current frame bindings (move, resize, close?) actions too */