1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 action.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
23 #include "moveresize.h"
36 #include "startupnotify.h"
41 inline void client_action_start(union ActionData
*data
)
43 if (config_focus_follow
)
44 if (data
->any
.context
!= OB_FRAME_CONTEXT_CLIENT
&& !data
->any
.button
)
45 grab_pointer(TRUE
, FALSE
, OB_CURSOR_NONE
);
48 inline void client_action_end(union ActionData
*data
)
50 if (config_focus_follow
)
51 if (data
->any
.context
!= OB_FRAME_CONTEXT_CLIENT
) {
52 if (!data
->any
.button
) {
53 grab_pointer(FALSE
, FALSE
, OB_CURSOR_NONE
);
57 /* usually this is sorta redundant, but with a press action
58 the enter event will come as a GrabNotify which is
59 ignored, so this will handle that case */
60 if ((c
= client_under_pointer()))
61 event_enter_client(c
);
69 void (*func
)(union ActionData
*);
70 void (*setup
)(ObAction
**, ObUserAction uact
);
73 static ObAction
*action_new(void (*func
)(union ActionData
*data
))
75 ObAction
*a
= g_new0(ObAction
, 1);
82 void action_ref(ObAction
*a
)
87 void action_unref(ObAction
*a
)
89 if (a
== NULL
) return;
91 if (--a
->ref
> 0) return;
93 /* deal with pointers */
94 if (a
->func
== action_execute
|| a
->func
== action_restart
)
95 g_free(a
->data
.execute
.path
);
96 else if (a
->func
== action_showmenu
)
97 g_free(a
->data
.showmenu
.name
);
102 ObAction
* action_copy(const ObAction
*src
)
104 ObAction
*a
= action_new(src
->func
);
108 /* deal with pointers */
109 if (a
->func
== action_execute
|| a
->func
== action_restart
)
110 a
->data
.execute
.path
= g_strdup(a
->data
.execute
.path
);
111 else if (a
->func
== action_showmenu
)
112 a
->data
.showmenu
.name
= g_strdup(a
->data
.showmenu
.name
);
117 void setup_action_directional_focus_north(ObAction
**a
, ObUserAction uact
)
119 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
120 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTH
;
121 (*a
)->data
.interdiraction
.dialog
= TRUE
;
122 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
125 void setup_action_directional_focus_east(ObAction
**a
, ObUserAction uact
)
127 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
128 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_EAST
;
129 (*a
)->data
.interdiraction
.dialog
= TRUE
;
130 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
133 void setup_action_directional_focus_south(ObAction
**a
, ObUserAction uact
)
135 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
136 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTH
;
137 (*a
)->data
.interdiraction
.dialog
= TRUE
;
138 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
141 void setup_action_directional_focus_west(ObAction
**a
, ObUserAction uact
)
143 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
144 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_WEST
;
145 (*a
)->data
.interdiraction
.dialog
= TRUE
;
146 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
149 void setup_action_directional_focus_northeast(ObAction
**a
, ObUserAction uact
)
151 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
152 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTHEAST
;
153 (*a
)->data
.interdiraction
.dialog
= TRUE
;
154 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
157 void setup_action_directional_focus_southeast(ObAction
**a
, ObUserAction uact
)
159 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
160 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTHEAST
;
161 (*a
)->data
.interdiraction
.dialog
= TRUE
;
162 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
165 void setup_action_directional_focus_southwest(ObAction
**a
, ObUserAction uact
)
167 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
168 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTHWEST
;
169 (*a
)->data
.interdiraction
.dialog
= TRUE
;
170 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
173 void setup_action_directional_focus_northwest(ObAction
**a
, ObUserAction uact
)
175 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
176 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTHWEST
;
177 (*a
)->data
.interdiraction
.dialog
= TRUE
;
178 (*a
)->data
.interdiraction
.dock_windows
= FALSE
;
181 void setup_action_send_to_desktop(ObAction
**a
, ObUserAction uact
)
183 (*a
)->data
.sendto
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
184 (*a
)->data
.sendto
.follow
= TRUE
;
187 void setup_action_send_to_desktop_prev(ObAction
**a
, ObUserAction uact
)
189 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
190 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
191 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_WEST
;
192 (*a
)->data
.sendtodir
.linear
= TRUE
;
193 (*a
)->data
.sendtodir
.wrap
= TRUE
;
194 (*a
)->data
.sendtodir
.follow
= TRUE
;
197 void setup_action_send_to_desktop_next(ObAction
**a
, ObUserAction uact
)
199 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
200 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
201 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_EAST
;
202 (*a
)->data
.sendtodir
.linear
= TRUE
;
203 (*a
)->data
.sendtodir
.wrap
= TRUE
;
204 (*a
)->data
.sendtodir
.follow
= TRUE
;
207 void setup_action_send_to_desktop_left(ObAction
**a
, ObUserAction uact
)
209 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
210 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
211 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_WEST
;
212 (*a
)->data
.sendtodir
.linear
= FALSE
;
213 (*a
)->data
.sendtodir
.wrap
= TRUE
;
214 (*a
)->data
.sendtodir
.follow
= TRUE
;
217 void setup_action_send_to_desktop_right(ObAction
**a
, ObUserAction uact
)
219 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
220 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
221 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_EAST
;
222 (*a
)->data
.sendtodir
.linear
= FALSE
;
223 (*a
)->data
.sendtodir
.wrap
= TRUE
;
224 (*a
)->data
.sendtodir
.follow
= TRUE
;
227 void setup_action_send_to_desktop_up(ObAction
**a
, ObUserAction uact
)
229 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
230 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
231 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_NORTH
;
232 (*a
)->data
.sendtodir
.linear
= FALSE
;
233 (*a
)->data
.sendtodir
.wrap
= TRUE
;
234 (*a
)->data
.sendtodir
.follow
= TRUE
;
237 void setup_action_send_to_desktop_down(ObAction
**a
, ObUserAction uact
)
239 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
240 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
241 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_SOUTH
;
242 (*a
)->data
.sendtodir
.linear
= FALSE
;
243 (*a
)->data
.sendtodir
.wrap
= TRUE
;
244 (*a
)->data
.sendtodir
.follow
= TRUE
;
247 void setup_action_desktop(ObAction
**a
, ObUserAction uact
)
249 (*a
)->data
.desktop
.inter
.any
.interactive
= FALSE
;
252 void setup_action_desktop_prev(ObAction
**a
, ObUserAction uact
)
254 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
255 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_WEST
;
256 (*a
)->data
.desktopdir
.linear
= TRUE
;
257 (*a
)->data
.desktopdir
.wrap
= TRUE
;
260 void setup_action_desktop_next(ObAction
**a
, ObUserAction uact
)
262 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
263 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_EAST
;
264 (*a
)->data
.desktopdir
.linear
= TRUE
;
265 (*a
)->data
.desktopdir
.wrap
= TRUE
;
268 void setup_action_desktop_left(ObAction
**a
, ObUserAction uact
)
270 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
271 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_WEST
;
272 (*a
)->data
.desktopdir
.linear
= FALSE
;
273 (*a
)->data
.desktopdir
.wrap
= TRUE
;
276 void setup_action_desktop_right(ObAction
**a
, ObUserAction uact
)
278 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
279 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_EAST
;
280 (*a
)->data
.desktopdir
.linear
= FALSE
;
281 (*a
)->data
.desktopdir
.wrap
= TRUE
;
284 void setup_action_desktop_up(ObAction
**a
, ObUserAction uact
)
286 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
287 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_NORTH
;
288 (*a
)->data
.desktopdir
.linear
= FALSE
;
289 (*a
)->data
.desktopdir
.wrap
= TRUE
;
292 void setup_action_desktop_down(ObAction
**a
, ObUserAction uact
)
294 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
295 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_SOUTH
;
296 (*a
)->data
.desktopdir
.linear
= FALSE
;
297 (*a
)->data
.desktopdir
.wrap
= TRUE
;
300 void setup_action_cycle_windows_next(ObAction
**a
, ObUserAction uact
)
302 (*a
)->data
.cycle
.inter
.any
.interactive
= TRUE
;
303 (*a
)->data
.cycle
.linear
= FALSE
;
304 (*a
)->data
.cycle
.forward
= TRUE
;
305 (*a
)->data
.cycle
.dialog
= TRUE
;
306 (*a
)->data
.cycle
.dock_windows
= FALSE
;
309 void setup_action_cycle_windows_previous(ObAction
**a
, ObUserAction uact
)
311 (*a
)->data
.cycle
.inter
.any
.interactive
= TRUE
;
312 (*a
)->data
.cycle
.linear
= FALSE
;
313 (*a
)->data
.cycle
.forward
= FALSE
;
314 (*a
)->data
.cycle
.dialog
= TRUE
;
315 (*a
)->data
.cycle
.dock_windows
= FALSE
;
318 void setup_action_movefromedge_north(ObAction
**a
, ObUserAction uact
)
320 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
321 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
322 (*a
)->data
.diraction
.hang
= TRUE
;
325 void setup_action_movefromedge_south(ObAction
**a
, ObUserAction uact
)
327 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
328 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
329 (*a
)->data
.diraction
.hang
= TRUE
;
332 void setup_action_movefromedge_east(ObAction
**a
, ObUserAction uact
)
334 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
335 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
336 (*a
)->data
.diraction
.hang
= TRUE
;
339 void setup_action_movefromedge_west(ObAction
**a
, ObUserAction uact
)
341 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
342 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
343 (*a
)->data
.diraction
.hang
= TRUE
;
346 void setup_action_movetoedge_north(ObAction
**a
, ObUserAction uact
)
348 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
349 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
350 (*a
)->data
.diraction
.hang
= FALSE
;
353 void setup_action_movetoedge_south(ObAction
**a
, ObUserAction uact
)
355 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
356 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
357 (*a
)->data
.diraction
.hang
= FALSE
;
360 void setup_action_movetoedge_east(ObAction
**a
, ObUserAction uact
)
362 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
363 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
364 (*a
)->data
.diraction
.hang
= FALSE
;
367 void setup_action_movetoedge_west(ObAction
**a
, ObUserAction uact
)
369 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
370 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
371 (*a
)->data
.diraction
.hang
= FALSE
;
374 void setup_action_growtoedge_north(ObAction
**a
, ObUserAction uact
)
376 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
377 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
380 void setup_action_growtoedge_south(ObAction
**a
, ObUserAction uact
)
382 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
383 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
386 void setup_action_growtoedge_east(ObAction
**a
, ObUserAction uact
)
388 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
389 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
392 void setup_action_growtoedge_west(ObAction
**a
, ObUserAction uact
)
394 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
395 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
398 void setup_action_top_layer(ObAction
**a
, ObUserAction uact
)
400 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
401 (*a
)->data
.layer
.layer
= 1;
404 void setup_action_normal_layer(ObAction
**a
, ObUserAction uact
)
406 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
407 (*a
)->data
.layer
.layer
= 0;
410 void setup_action_bottom_layer(ObAction
**a
, ObUserAction uact
)
412 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
413 (*a
)->data
.layer
.layer
= -1;
416 void setup_action_move(ObAction
**a
, ObUserAction uact
)
418 (*a
)->data
.moveresize
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
419 (*a
)->data
.moveresize
.move
= TRUE
;
420 (*a
)->data
.moveresize
.keyboard
=
421 (uact
== OB_USER_ACTION_NONE
||
422 uact
== OB_USER_ACTION_KEYBOARD_KEY
||
423 uact
== OB_USER_ACTION_MENU_SELECTION
);
426 void setup_action_resize(ObAction
**a
, ObUserAction uact
)
428 (*a
)->data
.moveresize
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
429 (*a
)->data
.moveresize
.move
= FALSE
;
430 (*a
)->data
.moveresize
.keyboard
=
431 (uact
== OB_USER_ACTION_NONE
||
432 uact
== OB_USER_ACTION_KEYBOARD_KEY
||
433 uact
== OB_USER_ACTION_MENU_SELECTION
);
436 void setup_action_showmenu(ObAction
**a
, ObUserAction uact
)
438 (*a
)->data
.showmenu
.any
.client_action
= OB_CLIENT_ACTION_OPTIONAL
;
439 /* you cannot call ShowMenu from inside a menu, cuz the menu code makes
440 assumptions that there is only one menu (and submenus) open at
442 if (uact
== OB_USER_ACTION_MENU_SELECTION
) {
448 void setup_action_focus(ObAction
**a
, ObUserAction uact
)
450 (*a
)->data
.any
.client_action
= OB_CLIENT_ACTION_OPTIONAL
;
453 void setup_client_action(ObAction
**a
, ObUserAction uact
)
455 (*a
)->data
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
458 ActionString actionstrings
[] =
466 "directionalfocusnorth",
467 action_directional_focus
,
468 setup_action_directional_focus_north
471 "directionalfocuseast",
472 action_directional_focus
,
473 setup_action_directional_focus_east
476 "directionalfocussouth",
477 action_directional_focus
,
478 setup_action_directional_focus_south
481 "directionalfocuswest",
482 action_directional_focus
,
483 setup_action_directional_focus_west
486 "directionalfocusnortheast",
487 action_directional_focus
,
488 setup_action_directional_focus_northeast
491 "directionalfocussoutheast",
492 action_directional_focus
,
493 setup_action_directional_focus_southeast
496 "directionalfocussouthwest",
497 action_directional_focus
,
498 setup_action_directional_focus_southwest
501 "directionalfocusnorthwest",
502 action_directional_focus
,
503 setup_action_directional_focus_northwest
527 action_focus_order_to_bottom
,
582 action_toggle_omnipresent
,
587 action_move_relative_horz
,
592 action_move_relative_vert
,
597 action_move_to_center
,
601 "resizerelativehorz",
602 action_resize_relative_horz
,
606 "resizerelativevert",
607 action_resize_relative_vert
,
612 action_move_relative
,
617 action_resize_relative
,
622 action_maximize_full
,
627 action_unmaximize_full
,
631 "togglemaximizefull",
632 action_toggle_maximize_full
,
637 action_maximize_horz
,
642 action_unmaximize_horz
,
646 "togglemaximizehorz",
647 action_toggle_maximize_horz
,
652 action_maximize_vert
,
657 action_unmaximize_vert
,
661 "togglemaximizevert",
662 action_toggle_maximize_vert
,
667 action_toggle_fullscreen
,
672 action_send_to_desktop
,
673 setup_action_send_to_desktop
677 action_send_to_desktop_dir
,
678 setup_action_send_to_desktop_next
681 "sendtodesktopprevious",
682 action_send_to_desktop_dir
,
683 setup_action_send_to_desktop_prev
686 "sendtodesktopright",
687 action_send_to_desktop_dir
,
688 setup_action_send_to_desktop_right
692 action_send_to_desktop_dir
,
693 setup_action_send_to_desktop_left
697 action_send_to_desktop_dir
,
698 setup_action_send_to_desktop_up
702 action_send_to_desktop_dir
,
703 setup_action_send_to_desktop_down
713 setup_action_desktop_next
718 setup_action_desktop_prev
723 setup_action_desktop_right
728 setup_action_desktop_left
733 setup_action_desktop_up
738 setup_action_desktop_down
742 action_toggle_decorations
,
756 "toggledockautohide",
757 action_toggle_dockautohide
,
762 action_toggle_show_desktop
,
772 action_unshow_desktop
,
798 setup_action_showmenu
802 action_send_to_layer
,
803 setup_action_top_layer
808 setup_action_top_layer
812 action_send_to_layer
,
813 setup_action_normal_layer
817 action_send_to_layer
,
818 setup_action_bottom_layer
821 "togglealwaysonbottom",
823 setup_action_bottom_layer
827 action_cycle_windows
,
828 setup_action_cycle_windows_next
832 action_cycle_windows
,
833 setup_action_cycle_windows_previous
838 setup_action_movefromedge_north
843 setup_action_movefromedge_south
848 setup_action_movefromedge_west
853 setup_action_movefromedge_east
858 setup_action_movetoedge_north
863 setup_action_movetoedge_south
868 setup_action_movetoedge_west
873 setup_action_movetoedge_east
878 setup_action_growtoedge_north
883 setup_action_growtoedge_south
888 setup_action_growtoedge_west
893 setup_action_growtoedge_east
902 /* only key bindings can be interactive. thus saith the xor.
903 because of how the mouse is grabbed, mouse events dont even get
904 read during interactive events, so no dice! >:) */
905 #define INTERACTIVE_LIMIT(a, uact) \
906 if (uact != OB_USER_ACTION_KEYBOARD_KEY) \
907 a->data.any.interactive = FALSE;
909 ObAction
*action_from_string(const gchar
*name
, ObUserAction uact
)
912 gboolean exist
= FALSE
;
915 for (i
= 0; actionstrings
[i
].name
; i
++)
916 if (!g_ascii_strcasecmp(name
, actionstrings
[i
].name
)) {
918 a
= action_new(actionstrings
[i
].func
);
919 if (actionstrings
[i
].setup
)
920 actionstrings
[i
].setup(&a
, uact
);
922 INTERACTIVE_LIMIT(a
, uact
);
926 g_message(_("Invalid action '%s' requested. No such action exists."),
929 g_message(_("Invalid use of action '%s'. Action will be ignored."),
934 ObAction
*action_parse(ObParseInst
*i
, xmlDocPtr doc
, xmlNodePtr node
,
938 ObAction
*act
= NULL
;
941 if (parse_attr_string("name", node
, &actname
)) {
942 if ((act
= action_from_string(actname
, uact
))) {
943 if (act
->func
== action_execute
|| act
->func
== action_restart
) {
944 if ((n
= parse_find_node("execute", node
->xmlChildrenNode
))) {
945 gchar
*s
= parse_string(doc
, n
);
946 act
->data
.execute
.path
= parse_expand_tilde(s
);
949 if ((n
= parse_find_node("startupnotify", node
->xmlChildrenNode
))) {
951 if ((m
= parse_find_node("enabled", n
->xmlChildrenNode
)))
952 act
->data
.execute
.startupnotify
= parse_bool(doc
, m
);
953 if ((m
= parse_find_node("name", n
->xmlChildrenNode
)))
954 act
->data
.execute
.name
= parse_string(doc
, m
);
955 if ((m
= parse_find_node("icon", n
->xmlChildrenNode
)))
956 act
->data
.execute
.icon_name
= parse_string(doc
, m
);
958 } else if (act
->func
== action_showmenu
) {
959 if ((n
= parse_find_node("menu", node
->xmlChildrenNode
)))
960 act
->data
.showmenu
.name
= parse_string(doc
, n
);
961 } else if (act
->func
== action_move_relative_horz
||
962 act
->func
== action_move_relative_vert
||
963 act
->func
== action_resize_relative_horz
||
964 act
->func
== action_resize_relative_vert
) {
965 if ((n
= parse_find_node("delta", node
->xmlChildrenNode
)))
966 act
->data
.relative
.deltax
= parse_int(doc
, n
);
967 } else if (act
->func
== action_move_relative
) {
968 if ((n
= parse_find_node("x", node
->xmlChildrenNode
)))
969 act
->data
.relative
.deltax
= parse_int(doc
, n
);
970 if ((n
= parse_find_node("y", node
->xmlChildrenNode
)))
971 act
->data
.relative
.deltay
= parse_int(doc
, n
);
972 } else if (act
->func
== action_resize_relative
) {
973 if ((n
= parse_find_node("left", node
->xmlChildrenNode
)))
974 act
->data
.relative
.deltaxl
= parse_int(doc
, n
);
975 if ((n
= parse_find_node("up", node
->xmlChildrenNode
)))
976 act
->data
.relative
.deltayu
= parse_int(doc
, n
);
977 if ((n
= parse_find_node("right", node
->xmlChildrenNode
)))
978 act
->data
.relative
.deltax
= parse_int(doc
, n
);
979 if ((n
= parse_find_node("down", node
->xmlChildrenNode
)))
980 act
->data
.relative
.deltay
= parse_int(doc
, n
);
981 } else if (act
->func
== action_desktop
) {
982 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
983 act
->data
.desktop
.desk
= parse_int(doc
, n
);
984 if (act
->data
.desktop
.desk
> 0) act
->data
.desktop
.desk
--;
985 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
986 act
->data
.desktop
.inter
.any
.interactive
=
988 } else if (act
->func
== action_send_to_desktop
) {
989 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
990 act
->data
.sendto
.desk
= parse_int(doc
, n
);
991 if (act
->data
.sendto
.desk
> 0) act
->data
.sendto
.desk
--;
992 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
993 act
->data
.sendto
.follow
= parse_bool(doc
, n
);
994 } else if (act
->func
== action_desktop_dir
) {
995 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
996 act
->data
.desktopdir
.wrap
= parse_bool(doc
, n
);
997 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
998 act
->data
.desktopdir
.inter
.any
.interactive
=
1000 } else if (act
->func
== action_send_to_desktop_dir
) {
1001 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
1002 act
->data
.sendtodir
.wrap
= parse_bool(doc
, n
);
1003 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
1004 act
->data
.sendtodir
.follow
= parse_bool(doc
, n
);
1005 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
1006 act
->data
.sendtodir
.inter
.any
.interactive
=
1008 } else if (act
->func
== action_activate
) {
1009 if ((n
= parse_find_node("here", node
->xmlChildrenNode
)))
1010 act
->data
.activate
.here
= parse_bool(doc
, n
);
1011 } else if (act
->func
== action_cycle_windows
) {
1012 if ((n
= parse_find_node("linear", node
->xmlChildrenNode
)))
1013 act
->data
.cycle
.linear
= parse_bool(doc
, n
);
1014 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
1015 act
->data
.cycle
.dialog
= parse_bool(doc
, n
);
1016 if ((n
= parse_find_node("panels", node
->xmlChildrenNode
)))
1017 act
->data
.cycle
.dock_windows
= parse_bool(doc
, n
);
1018 } else if (act
->func
== action_directional_focus
) {
1019 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
1020 act
->data
.interdiraction
.dialog
= parse_bool(doc
, n
);
1021 if ((n
= parse_find_node("panels", node
->xmlChildrenNode
)))
1022 act
->data
.interdiraction
.dock_windows
= parse_bool(doc
, n
);
1023 } else if (act
->func
== action_raise
||
1024 act
->func
== action_lower
||
1025 act
->func
== action_raiselower
||
1026 act
->func
== action_shadelower
||
1027 act
->func
== action_unshaderaise
) {
1029 INTERACTIVE_LIMIT(act
, uact
);
1036 void action_run_list(GSList
*acts
, ObClient
*c
, ObFrameContext context
,
1037 guint state
, guint button
, gint x
, gint y
, Time time
,
1038 gboolean cancel
, gboolean done
)
1042 gboolean inter
= FALSE
;
1048 screen_pointer_pos(&x
, &y
);
1050 if (grab_on_keyboard())
1053 for (it
= acts
; it
; it
= g_slist_next(it
)) {
1055 if (a
->data
.any
.interactive
) {
1062 /* sometimes when we execute another app as an action,
1063 it won't work right unless we XUngrabKeyboard first,
1064 even though we grabbed the key/button Asychronously.
1065 e.g. "gnome-panel-control --main-menu" */
1066 grab_keyboard(FALSE
);
1069 for (it
= acts
; it
; it
= g_slist_next(it
)) {
1072 if (!(a
->data
.any
.client_action
== OB_CLIENT_ACTION_ALWAYS
&& !c
)) {
1073 a
->data
.any
.c
= a
->data
.any
.client_action
? c
: NULL
;
1074 a
->data
.any
.context
= context
;
1078 a
->data
.any
.button
= button
;
1080 a
->data
.any
.time
= time
;
1082 if (a
->data
.any
.interactive
) {
1083 a
->data
.inter
.cancel
= cancel
;
1084 a
->data
.inter
.final
= done
;
1085 if (!(cancel
|| done
))
1086 if (!keyboard_interactive_grab(state
, a
->data
.any
.c
, a
))
1090 /* XXX UGLY HACK race with motion event starting a move and the
1091 button release gettnig processed first. answer: don't queue
1092 moveresize starts. UGLY HACK XXX */
1093 if (a
->data
.any
.interactive
|| a
->func
== action_moveresize
) {
1094 /* interactive actions are not queued */
1097 ob_main_loop_queue_action(ob_main_loop
, a
);
1102 void action_run_string(const gchar
*name
, struct _ObClient
*c
, Time time
)
1107 a
= action_from_string(name
, OB_USER_ACTION_NONE
);
1110 l
= g_slist_append(NULL
, a
);
1112 action_run(l
, c
, 0, time
);
1115 void action_execute(union ActionData
*data
)
1118 gchar
*cmd
, **argv
= 0;
1119 if (data
->execute
.path
) {
1120 cmd
= g_filename_from_utf8(data
->execute
.path
, -1, NULL
, NULL
, NULL
);
1122 if (!g_shell_parse_argv (cmd
, NULL
, &argv
, &e
)) {
1123 g_message(_("Failed to execute '%s': %s"),
1126 } else if (data
->execute
.startupnotify
) {
1129 program
= g_path_get_basename(argv
[0]);
1130 /* sets up the environment */
1131 sn_setup_spawn_environment(program
,
1133 data
->execute
.icon_name
,
1134 /* launch it on the current
1137 data
->execute
.any
.time
);
1138 if (!g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
|
1139 G_SPAWN_DO_NOT_REAP_CHILD
,
1140 NULL
, NULL
, NULL
, &e
)) {
1141 g_message(_("Failed to execute '%s': %s"),
1146 unsetenv("DESKTOP_STARTUP_ID");
1150 if (!g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
|
1151 G_SPAWN_DO_NOT_REAP_CHILD
,
1152 NULL
, NULL
, NULL
, &e
))
1154 g_message(_("Failed to execute '%s': %s"),
1162 g_message(_("Failed to convert the path '%s' from utf8"),
1163 data
->execute
.path
);
1168 void action_activate(union ActionData
*data
)
1170 /* similar to the openbox dock for dockapps, don't let user actions give
1171 focus to 3rd-party docks (panels) either (unless they ask for it
1173 if (data
->client
.any
.c
->type
!= OB_CLIENT_TYPE_DOCK
) {
1174 /* if using focus_delay, stop the timer now so that focus doesn't go
1176 event_halt_focus_delay();
1178 client_activate(data
->activate
.any
.c
, data
->activate
.here
, TRUE
);
1182 void action_focus(union ActionData
*data
)
1184 if (data
->client
.any
.c
) {
1185 /* similar to the openbox dock for dockapps, don't let user actions
1186 give focus to 3rd-party docks (panels) either (unless they ask for
1188 if (data
->client
.any
.c
->type
!= OB_CLIENT_TYPE_DOCK
) {
1189 /* if using focus_delay, stop the timer now so that focus doesn't
1191 event_halt_focus_delay();
1193 client_focus(data
->client
.any
.c
);
1196 /* focus action on something other than a client, make keybindings
1197 work for this openbox instance, but don't focus any specific client
1203 void action_unfocus (union ActionData
*data
)
1205 if (data
->client
.any
.c
== focus_client
)
1206 focus_fallback(FALSE
);
1209 void action_iconify(union ActionData
*data
)
1211 client_action_start(data
);
1212 client_iconify(data
->client
.any
.c
, TRUE
, TRUE
);
1213 client_action_end(data
);
1216 void action_focus_order_to_bottom(union ActionData
*data
)
1218 focus_order_to_bottom(data
->client
.any
.c
);
1221 void action_raiselower(union ActionData
*data
)
1223 ObClient
*c
= data
->client
.any
.c
;
1225 gboolean raise
= FALSE
;
1227 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
1228 if (WINDOW_IS_CLIENT(it
->data
)) {
1229 ObClient
*cit
= it
->data
;
1231 if (cit
== c
) break;
1232 if (client_normal(cit
) == client_normal(c
) &&
1233 cit
->layer
== c
->layer
&&
1234 cit
->frame
->visible
&&
1235 !client_search_transient(c
, cit
))
1237 if (RECT_INTERSECTS_RECT(cit
->frame
->area
, c
->frame
->area
)) {
1251 void action_raise(union ActionData
*data
)
1253 client_action_start(data
);
1254 stacking_raise(CLIENT_AS_WINDOW(data
->client
.any
.c
));
1255 client_action_end(data
);
1258 void action_unshaderaise(union ActionData
*data
)
1260 if (data
->client
.any
.c
->shaded
)
1261 action_unshade(data
);
1266 void action_shadelower(union ActionData
*data
)
1268 if (data
->client
.any
.c
->shaded
)
1274 void action_lower(union ActionData
*data
)
1276 client_action_start(data
);
1277 stacking_lower(CLIENT_AS_WINDOW(data
->client
.any
.c
));
1278 client_action_end(data
);
1281 void action_close(union ActionData
*data
)
1283 client_close(data
->client
.any
.c
);
1286 void action_kill(union ActionData
*data
)
1288 client_kill(data
->client
.any
.c
);
1291 void action_shade(union ActionData
*data
)
1293 client_action_start(data
);
1294 client_shade(data
->client
.any
.c
, TRUE
);
1295 client_action_end(data
);
1298 void action_unshade(union ActionData
*data
)
1300 client_action_start(data
);
1301 client_shade(data
->client
.any
.c
, FALSE
);
1302 client_action_end(data
);
1305 void action_toggle_shade(union ActionData
*data
)
1307 client_action_start(data
);
1308 client_shade(data
->client
.any
.c
, !data
->client
.any
.c
->shaded
);
1309 client_action_end(data
);
1312 void action_toggle_omnipresent(union ActionData
*data
)
1314 client_set_desktop(data
->client
.any
.c
,
1315 data
->client
.any
.c
->desktop
== DESKTOP_ALL
?
1316 screen_desktop
: DESKTOP_ALL
, FALSE
);
1319 void action_move_relative_horz(union ActionData
*data
)
1321 ObClient
*c
= data
->relative
.any
.c
;
1322 client_action_start(data
);
1323 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
);
1324 client_action_end(data
);
1327 void action_move_relative_vert(union ActionData
*data
)
1329 ObClient
*c
= data
->relative
.any
.c
;
1330 client_action_start(data
);
1331 client_move(c
, c
->area
.x
, c
->area
.y
+ data
->relative
.deltax
);
1332 client_action_end(data
);
1335 void action_move_to_center(union ActionData
*data
)
1337 ObClient
*c
= data
->client
.any
.c
;
1339 area
= screen_area_monitor(c
->desktop
, 0);
1340 client_action_start(data
);
1341 client_move(c
, area
->width
/ 2 - c
->area
.width
/ 2,
1342 area
->height
/ 2 - c
->area
.height
/ 2);
1343 client_action_end(data
);
1346 void action_resize_relative_horz(union ActionData
*data
)
1348 ObClient
*c
= data
->relative
.any
.c
;
1349 client_action_start(data
);
1351 c
->area
.width
+ data
->relative
.deltax
* c
->size_inc
.width
,
1353 client_action_end(data
);
1356 void action_resize_relative_vert(union ActionData
*data
)
1358 ObClient
*c
= data
->relative
.any
.c
;
1360 client_action_start(data
);
1361 client_resize(c
, c
->area
.width
, c
->area
.height
+
1362 data
->relative
.deltax
* c
->size_inc
.height
);
1363 client_action_end(data
);
1367 void action_move_relative(union ActionData
*data
)
1369 ObClient
*c
= data
->relative
.any
.c
;
1370 client_action_start(data
);
1371 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
+
1372 data
->relative
.deltay
);
1373 client_action_end(data
);
1376 void action_resize_relative(union ActionData
*data
)
1378 ObClient
*c
= data
->relative
.any
.c
;
1379 gint x
, y
, ow
, w
, oh
, h
, lw
, lh
;
1381 client_action_start(data
);
1386 w
= ow
+ data
->relative
.deltax
* c
->size_inc
.width
1387 + data
->relative
.deltaxl
* c
->size_inc
.width
;
1388 oh
= c
->area
.height
;
1389 h
= oh
+ data
->relative
.deltay
* c
->size_inc
.height
1390 + data
->relative
.deltayu
* c
->size_inc
.height
;
1392 client_try_configure(c
, OB_CORNER_TOPLEFT
, &x
, &y
, &w
, &h
, &lw
, &lh
, TRUE
);
1393 client_move_resize(c
, x
+ (ow
- w
), y
+ (oh
- h
), w
, h
);
1394 client_action_end(data
);
1397 void action_maximize_full(union ActionData
*data
)
1399 client_action_start(data
);
1400 client_maximize(data
->client
.any
.c
, TRUE
, 0);
1401 client_action_end(data
);
1404 void action_unmaximize_full(union ActionData
*data
)
1406 client_action_start(data
);
1407 client_maximize(data
->client
.any
.c
, FALSE
, 0);
1408 client_action_end(data
);
1411 void action_toggle_maximize_full(union ActionData
*data
)
1413 client_action_start(data
);
1414 client_maximize(data
->client
.any
.c
,
1415 !(data
->client
.any
.c
->max_horz
||
1416 data
->client
.any
.c
->max_vert
),
1418 client_action_end(data
);
1421 void action_maximize_horz(union ActionData
*data
)
1423 client_action_start(data
);
1424 client_maximize(data
->client
.any
.c
, TRUE
, 1);
1425 client_action_end(data
);
1428 void action_unmaximize_horz(union ActionData
*data
)
1430 client_action_start(data
);
1431 client_maximize(data
->client
.any
.c
, FALSE
, 1);
1432 client_action_end(data
);
1435 void action_toggle_maximize_horz(union ActionData
*data
)
1437 client_action_start(data
);
1438 client_maximize(data
->client
.any
.c
,
1439 !data
->client
.any
.c
->max_horz
, 1);
1440 client_action_end(data
);
1443 void action_maximize_vert(union ActionData
*data
)
1445 client_action_start(data
);
1446 client_maximize(data
->client
.any
.c
, TRUE
, 2);
1447 client_action_end(data
);
1450 void action_unmaximize_vert(union ActionData
*data
)
1452 client_action_start(data
);
1453 client_maximize(data
->client
.any
.c
, FALSE
, 2);
1454 client_action_end(data
);
1457 void action_toggle_maximize_vert(union ActionData
*data
)
1459 client_action_start(data
);
1460 client_maximize(data
->client
.any
.c
,
1461 !data
->client
.any
.c
->max_vert
, 2);
1462 client_action_end(data
);
1465 void action_toggle_fullscreen(union ActionData
*data
)
1467 client_action_start(data
);
1468 client_fullscreen(data
->client
.any
.c
, !(data
->client
.any
.c
->fullscreen
));
1469 client_action_end(data
);
1472 void action_send_to_desktop(union ActionData
*data
)
1474 ObClient
*c
= data
->sendto
.any
.c
;
1476 if (!client_normal(c
)) return;
1478 if (data
->sendto
.desk
< screen_num_desktops
||
1479 data
->sendto
.desk
== DESKTOP_ALL
) {
1480 client_set_desktop(c
, data
->sendto
.desk
, data
->sendto
.follow
);
1481 if (data
->sendto
.follow
)
1482 screen_set_desktop(data
->sendto
.desk
);
1486 void action_desktop(union ActionData
*data
)
1488 static guint first
= (unsigned) -1;
1490 if (data
->inter
.any
.interactive
&& first
== (unsigned) -1)
1491 first
= screen_desktop
;
1493 if (!data
->inter
.any
.interactive
||
1494 (!data
->inter
.cancel
&& !data
->inter
.final
))
1496 if (data
->desktop
.desk
< screen_num_desktops
||
1497 data
->desktop
.desk
== DESKTOP_ALL
)
1499 screen_set_desktop(data
->desktop
.desk
);
1500 if (data
->inter
.any
.interactive
)
1501 screen_desktop_popup(data
->desktop
.desk
, TRUE
);
1503 } else if (data
->inter
.cancel
) {
1504 screen_set_desktop(first
);
1507 if (!data
->inter
.any
.interactive
|| data
->inter
.final
) {
1508 screen_desktop_popup(0, FALSE
);
1509 first
= (unsigned) -1;
1513 void action_desktop_dir(union ActionData
*data
)
1517 d
= screen_cycle_desktop(data
->desktopdir
.dir
,
1518 data
->desktopdir
.wrap
,
1519 data
->desktopdir
.linear
,
1520 data
->desktopdir
.inter
.any
.interactive
,
1521 data
->desktopdir
.inter
.final
,
1522 data
->desktopdir
.inter
.cancel
);
1523 if (!data
->sendtodir
.inter
.any
.interactive
||
1524 !data
->sendtodir
.inter
.final
||
1525 data
->sendtodir
.inter
.cancel
)
1527 screen_set_desktop(d
);
1531 void action_send_to_desktop_dir(union ActionData
*data
)
1533 ObClient
*c
= data
->sendtodir
.inter
.any
.c
;
1536 if (!client_normal(c
)) return;
1538 d
= screen_cycle_desktop(data
->sendtodir
.dir
, data
->sendtodir
.wrap
,
1539 data
->sendtodir
.linear
,
1540 data
->sendtodir
.inter
.any
.interactive
,
1541 data
->sendtodir
.inter
.final
,
1542 data
->sendtodir
.inter
.cancel
);
1543 if (!data
->sendtodir
.inter
.any
.interactive
||
1544 !data
->sendtodir
.inter
.final
||
1545 data
->sendtodir
.inter
.cancel
)
1547 client_set_desktop(c
, d
, data
->sendtodir
.follow
);
1548 if (data
->sendtodir
.follow
)
1549 screen_set_desktop(d
);
1553 void action_desktop_last(union ActionData
*data
)
1555 screen_set_desktop(screen_last_desktop
);
1558 void action_toggle_decorations(union ActionData
*data
)
1560 ObClient
*c
= data
->client
.any
.c
;
1562 client_action_start(data
);
1563 client_set_undecorated(c
, !c
->undecorated
);
1564 client_action_end(data
);
1567 static guint32
pick_corner(gint x
, gint y
, gint cx
, gint cy
, gint cw
, gint ch
)
1569 /* let's make x and y client relative instead of screen relative */
1571 y
= ch
- (y
- cy
); /* y is inverted, 0 is at the bottom of the window */
1574 #define A -4*X + 7*ch/3
1575 #define B 4*X -15*ch/9
1576 #define C -X/4 + 2*ch/3
1577 #define D X/4 + 5*ch/12
1578 #define E X/4 + ch/3
1579 #define F -X/4 + 7*ch/12
1580 #define G 4*X - 4*ch/3
1581 #define H -4*X + 8*ch/3
1582 #define a (y > 5*ch/9)
1583 #define b (x < 4*cw/9)
1584 #define c (x > 5*cw/9)
1585 #define d (y < 4*ch/9)
1588 Each of these defines (except X which is just there for fun), represents
1589 the equation of a line. The lines they represent are shown in the diagram
1590 below. Checking y against these lines, we are able to choose a region
1591 of the window as shown.
1593 +---------------------A-------|-------|-------B---------------------+
1600 | northwest | A north B | northeast |
1603 C---------------------+----A--+-------+--B----+---------------------D
1604 |CCCCCCC | A B | DDDDDDD|
1605 | CCCCCCCC | A | | B | DDDDDDDD |
1606 | CCCCCCC A B DDDDDDD |
1607 - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - -
1609 | west | b move c | east |
1611 - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - -
1612 | EEEEEEE G H FFFFFFF |
1613 | EEEEEEEE | G | | H | FFFFFFFF |
1614 |EEEEEEE | G H | FFFFFFF|
1615 E---------------------+----G--+-------+--H----+---------------------F
1618 | southwest | G south H | southeast |
1625 +---------------------G-------|-------|-------H---------------------+
1628 if (y
< A
&& y
>= C
)
1629 return prop_atoms
.net_wm_moveresize_size_topleft
;
1630 else if (y
>= A
&& y
>= B
&& a
)
1631 return prop_atoms
.net_wm_moveresize_size_top
;
1632 else if (y
< B
&& y
>= D
)
1633 return prop_atoms
.net_wm_moveresize_size_topright
;
1634 else if (y
< C
&& y
>= E
&& b
)
1635 return prop_atoms
.net_wm_moveresize_size_left
;
1636 else if (y
< D
&& y
>= F
&& c
)
1637 return prop_atoms
.net_wm_moveresize_size_right
;
1638 else if (y
< E
&& y
>= G
)
1639 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1640 else if (y
< G
&& y
< H
&& d
)
1641 return prop_atoms
.net_wm_moveresize_size_bottom
;
1642 else if (y
>= H
&& y
< F
)
1643 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1645 return prop_atoms
.net_wm_moveresize_move
;
1662 void action_moveresize(union ActionData
*data
)
1664 ObClient
*c
= data
->moveresize
.any
.c
;
1667 if (!client_normal(c
)) return;
1669 if (data
->moveresize
.keyboard
) {
1670 corner
= (data
->moveresize
.move
?
1671 prop_atoms
.net_wm_moveresize_move_keyboard
:
1672 prop_atoms
.net_wm_moveresize_size_keyboard
);
1674 corner
= (data
->moveresize
.move
?
1675 prop_atoms
.net_wm_moveresize_move
:
1676 pick_corner(data
->any
.x
, data
->any
.y
,
1677 c
->frame
->area
.x
, c
->frame
->area
.y
,
1678 /* use the client size because the frame
1679 can be differently sized (shaded
1680 windows) and we want this based on the
1682 c
->area
.width
+ c
->frame
->size
.left
+
1683 c
->frame
->size
.right
,
1684 c
->area
.height
+ c
->frame
->size
.top
+
1685 c
->frame
->size
.bottom
));
1687 if (corner
== prop_atoms
.net_wm_moveresize_size_topright
)
1689 else if (corner
== prop_atoms
.net_wm_moveresize_size_top
)
1691 else if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
)
1693 else if (corner
== prop_atoms
.net_wm_moveresize_size_right
)
1695 else if (corner
== prop_atoms
.net_wm_moveresize_move
)
1697 else if (corner
== prop_atoms
.net_wm_moveresize_size_left
)
1699 else if (corner
== prop_atoms
.net_wm_moveresize_size_bottomright
)
1701 else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
)
1703 else if (corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
1705 ob_debug("corner: %s\n", c
);
1708 moveresize_start(c
, data
->any
.x
, data
->any
.y
, data
->any
.button
, corner
);
1711 void action_reconfigure(union ActionData
*data
)
1716 void action_restart(union ActionData
*data
)
1718 ob_restart_other(data
->execute
.path
);
1721 void action_exit(union ActionData
*data
)
1726 void action_showmenu(union ActionData
*data
)
1728 if (data
->showmenu
.name
) {
1729 menu_show(data
->showmenu
.name
, data
->any
.x
, data
->any
.y
,
1730 data
->showmenu
.any
.c
);
1734 void action_cycle_windows(union ActionData
*data
)
1736 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1738 event_halt_focus_delay();
1740 focus_cycle(data
->cycle
.forward
,
1741 data
->cycle
.dock_windows
,
1742 data
->cycle
.linear
, data
->any
.interactive
,
1744 data
->cycle
.inter
.final
, data
->cycle
.inter
.cancel
);
1747 void action_directional_focus(union ActionData
*data
)
1749 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1751 event_halt_focus_delay();
1753 focus_directional_cycle(data
->interdiraction
.direction
,
1754 data
->interdiraction
.dock_windows
,
1755 data
->any
.interactive
,
1756 data
->interdiraction
.dialog
,
1757 data
->interdiraction
.inter
.final
,
1758 data
->interdiraction
.inter
.cancel
);
1761 void action_movetoedge(union ActionData
*data
)
1764 ObClient
*c
= data
->diraction
.any
.c
;
1766 x
= c
->frame
->area
.x
;
1767 y
= c
->frame
->area
.y
;
1769 switch(data
->diraction
.direction
) {
1770 case OB_DIRECTION_NORTH
:
1771 y
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
,
1772 data
->diraction
.hang
)
1773 - (data
->diraction
.hang
? c
->frame
->area
.height
: 0);
1775 case OB_DIRECTION_WEST
:
1776 x
= client_directional_edge_search(c
, OB_DIRECTION_WEST
,
1777 data
->diraction
.hang
)
1778 - (data
->diraction
.hang
? c
->frame
->area
.width
: 0);
1780 case OB_DIRECTION_SOUTH
:
1781 y
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
,
1782 data
->diraction
.hang
)
1783 - (data
->diraction
.hang
? 0 : c
->frame
->area
.height
);
1785 case OB_DIRECTION_EAST
:
1786 x
= client_directional_edge_search(c
, OB_DIRECTION_EAST
,
1787 data
->diraction
.hang
)
1788 - (data
->diraction
.hang
? 0 : c
->frame
->area
.width
);
1791 g_assert_not_reached();
1793 frame_frame_gravity(c
->frame
, &x
, &y
);
1794 client_action_start(data
);
1795 client_move(c
, x
, y
);
1796 client_action_end(data
);
1799 void action_growtoedge(union ActionData
*data
)
1801 gint x
, y
, width
, height
, dest
;
1802 ObClient
*c
= data
->diraction
.any
.c
;
1805 //FIXME growtoedge resizes shaded windows to 0 height
1809 a
= screen_area(c
->desktop
);
1810 x
= c
->frame
->area
.x
;
1811 y
= c
->frame
->area
.y
;
1812 width
= c
->frame
->area
.width
;
1813 height
= c
->frame
->area
.height
;
1815 switch(data
->diraction
.direction
) {
1816 case OB_DIRECTION_NORTH
:
1817 dest
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
, FALSE
);
1819 height
= c
->frame
->area
.height
/ 2;
1821 height
= c
->frame
->area
.y
+ c
->frame
->area
.height
- dest
;
1825 case OB_DIRECTION_WEST
:
1826 dest
= client_directional_edge_search(c
, OB_DIRECTION_WEST
, FALSE
);
1828 width
= c
->frame
->area
.width
/ 2;
1830 width
= c
->frame
->area
.x
+ c
->frame
->area
.width
- dest
;
1834 case OB_DIRECTION_SOUTH
:
1835 dest
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
, FALSE
);
1836 if (a
->y
+ a
->height
== y
+ c
->frame
->area
.height
) {
1837 height
= c
->frame
->area
.height
/ 2;
1838 y
= a
->y
+ a
->height
- height
;
1840 height
= dest
- c
->frame
->area
.y
;
1841 y
+= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1842 height
-= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1844 case OB_DIRECTION_EAST
:
1845 dest
= client_directional_edge_search(c
, OB_DIRECTION_EAST
, FALSE
);
1846 if (a
->x
+ a
->width
== x
+ c
->frame
->area
.width
) {
1847 width
= c
->frame
->area
.width
/ 2;
1848 x
= a
->x
+ a
->width
- width
;
1850 width
= dest
- c
->frame
->area
.x
;
1851 x
+= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1852 width
-= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1855 g_assert_not_reached();
1857 frame_frame_gravity(c
->frame
, &x
, &y
);
1858 width
-= c
->frame
->size
.left
+ c
->frame
->size
.right
;
1859 height
-= c
->frame
->size
.top
+ c
->frame
->size
.bottom
;
1860 client_action_start(data
);
1861 client_move_resize(c
, x
, y
, width
, height
);
1862 client_action_end(data
);
1865 void action_send_to_layer(union ActionData
*data
)
1867 client_set_layer(data
->layer
.any
.c
, data
->layer
.layer
);
1870 void action_toggle_layer(union ActionData
*data
)
1872 ObClient
*c
= data
->layer
.any
.c
;
1874 client_action_start(data
);
1875 if (data
->layer
.layer
< 0)
1876 client_set_layer(c
, c
->below
? 0 : -1);
1877 else if (data
->layer
.layer
> 0)
1878 client_set_layer(c
, c
->above
? 0 : 1);
1879 client_action_end(data
);
1882 void action_toggle_dockautohide(union ActionData
*data
)
1884 config_dock_hide
= !config_dock_hide
;
1888 void action_toggle_show_desktop(union ActionData
*data
)
1890 screen_show_desktop(!screen_showing_desktop
);
1893 void action_show_desktop(union ActionData
*data
)
1895 screen_show_desktop(TRUE
);
1898 void action_unshow_desktop(union ActionData
*data
)
1900 screen_show_desktop(FALSE
);