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
;
124 void setup_action_directional_focus_east(ObAction
**a
, ObUserAction uact
)
126 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
127 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_EAST
;
128 (*a
)->data
.interdiraction
.dialog
= TRUE
;
131 void setup_action_directional_focus_south(ObAction
**a
, ObUserAction uact
)
133 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
134 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTH
;
135 (*a
)->data
.interdiraction
.dialog
= TRUE
;
138 void setup_action_directional_focus_west(ObAction
**a
, ObUserAction uact
)
140 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
141 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_WEST
;
142 (*a
)->data
.interdiraction
.dialog
= TRUE
;
145 void setup_action_directional_focus_northeast(ObAction
**a
, ObUserAction uact
)
147 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
148 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTHEAST
;
149 (*a
)->data
.interdiraction
.dialog
= TRUE
;
152 void setup_action_directional_focus_southeast(ObAction
**a
, ObUserAction uact
)
154 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
155 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTHEAST
;
156 (*a
)->data
.interdiraction
.dialog
= TRUE
;
159 void setup_action_directional_focus_southwest(ObAction
**a
, ObUserAction uact
)
161 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
162 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTHWEST
;
163 (*a
)->data
.interdiraction
.dialog
= TRUE
;
166 void setup_action_directional_focus_northwest(ObAction
**a
, ObUserAction uact
)
168 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
169 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTHWEST
;
170 (*a
)->data
.interdiraction
.dialog
= TRUE
;
173 void setup_action_send_to_desktop(ObAction
**a
, ObUserAction uact
)
175 (*a
)->data
.sendto
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
176 (*a
)->data
.sendto
.follow
= TRUE
;
179 void setup_action_send_to_desktop_prev(ObAction
**a
, ObUserAction uact
)
181 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
182 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
183 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_WEST
;
184 (*a
)->data
.sendtodir
.linear
= TRUE
;
185 (*a
)->data
.sendtodir
.wrap
= TRUE
;
186 (*a
)->data
.sendtodir
.follow
= TRUE
;
189 void setup_action_send_to_desktop_next(ObAction
**a
, ObUserAction uact
)
191 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
192 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
193 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_EAST
;
194 (*a
)->data
.sendtodir
.linear
= TRUE
;
195 (*a
)->data
.sendtodir
.wrap
= TRUE
;
196 (*a
)->data
.sendtodir
.follow
= TRUE
;
199 void setup_action_send_to_desktop_left(ObAction
**a
, ObUserAction uact
)
201 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
202 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
203 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_WEST
;
204 (*a
)->data
.sendtodir
.linear
= FALSE
;
205 (*a
)->data
.sendtodir
.wrap
= TRUE
;
206 (*a
)->data
.sendtodir
.follow
= TRUE
;
209 void setup_action_send_to_desktop_right(ObAction
**a
, ObUserAction uact
)
211 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
212 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
213 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_EAST
;
214 (*a
)->data
.sendtodir
.linear
= FALSE
;
215 (*a
)->data
.sendtodir
.wrap
= TRUE
;
216 (*a
)->data
.sendtodir
.follow
= TRUE
;
219 void setup_action_send_to_desktop_up(ObAction
**a
, ObUserAction uact
)
221 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
222 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
223 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_NORTH
;
224 (*a
)->data
.sendtodir
.linear
= FALSE
;
225 (*a
)->data
.sendtodir
.wrap
= TRUE
;
226 (*a
)->data
.sendtodir
.follow
= TRUE
;
229 void setup_action_send_to_desktop_down(ObAction
**a
, ObUserAction uact
)
231 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
232 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
233 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_SOUTH
;
234 (*a
)->data
.sendtodir
.linear
= FALSE
;
235 (*a
)->data
.sendtodir
.wrap
= TRUE
;
236 (*a
)->data
.sendtodir
.follow
= TRUE
;
239 void setup_action_desktop(ObAction
**a
, ObUserAction uact
)
241 (*a
)->data
.desktop
.inter
.any
.interactive
= FALSE
;
244 void setup_action_desktop_prev(ObAction
**a
, ObUserAction uact
)
246 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
247 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_WEST
;
248 (*a
)->data
.desktopdir
.linear
= TRUE
;
249 (*a
)->data
.desktopdir
.wrap
= TRUE
;
252 void setup_action_desktop_next(ObAction
**a
, ObUserAction uact
)
254 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
255 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_EAST
;
256 (*a
)->data
.desktopdir
.linear
= TRUE
;
257 (*a
)->data
.desktopdir
.wrap
= TRUE
;
260 void setup_action_desktop_left(ObAction
**a
, ObUserAction uact
)
262 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
263 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_WEST
;
264 (*a
)->data
.desktopdir
.linear
= FALSE
;
265 (*a
)->data
.desktopdir
.wrap
= TRUE
;
268 void setup_action_desktop_right(ObAction
**a
, ObUserAction uact
)
270 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
271 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_EAST
;
272 (*a
)->data
.desktopdir
.linear
= FALSE
;
273 (*a
)->data
.desktopdir
.wrap
= TRUE
;
276 void setup_action_desktop_up(ObAction
**a
, ObUserAction uact
)
278 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
279 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_NORTH
;
280 (*a
)->data
.desktopdir
.linear
= FALSE
;
281 (*a
)->data
.desktopdir
.wrap
= TRUE
;
284 void setup_action_desktop_down(ObAction
**a
, ObUserAction uact
)
286 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
287 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_SOUTH
;
288 (*a
)->data
.desktopdir
.linear
= FALSE
;
289 (*a
)->data
.desktopdir
.wrap
= TRUE
;
292 void setup_action_cycle_windows_next(ObAction
**a
, ObUserAction uact
)
294 (*a
)->data
.cycle
.inter
.any
.interactive
= TRUE
;
295 (*a
)->data
.cycle
.linear
= FALSE
;
296 (*a
)->data
.cycle
.forward
= TRUE
;
297 (*a
)->data
.cycle
.dialog
= TRUE
;
300 void setup_action_cycle_windows_previous(ObAction
**a
, ObUserAction uact
)
302 (*a
)->data
.cycle
.inter
.any
.interactive
= TRUE
;
303 (*a
)->data
.cycle
.linear
= FALSE
;
304 (*a
)->data
.cycle
.forward
= FALSE
;
305 (*a
)->data
.cycle
.dialog
= TRUE
;
308 void setup_action_movefromedge_north(ObAction
**a
, ObUserAction uact
)
310 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
311 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
312 (*a
)->data
.diraction
.hang
= TRUE
;
315 void setup_action_movefromedge_south(ObAction
**a
, ObUserAction uact
)
317 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
318 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
319 (*a
)->data
.diraction
.hang
= TRUE
;
322 void setup_action_movefromedge_east(ObAction
**a
, ObUserAction uact
)
324 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
325 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
326 (*a
)->data
.diraction
.hang
= TRUE
;
329 void setup_action_movefromedge_west(ObAction
**a
, ObUserAction uact
)
331 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
332 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
333 (*a
)->data
.diraction
.hang
= TRUE
;
336 void setup_action_movetoedge_north(ObAction
**a
, ObUserAction uact
)
338 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
339 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
340 (*a
)->data
.diraction
.hang
= FALSE
;
343 void setup_action_movetoedge_south(ObAction
**a
, ObUserAction uact
)
345 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
346 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
347 (*a
)->data
.diraction
.hang
= FALSE
;
350 void setup_action_movetoedge_east(ObAction
**a
, ObUserAction uact
)
352 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
353 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
354 (*a
)->data
.diraction
.hang
= FALSE
;
357 void setup_action_movetoedge_west(ObAction
**a
, ObUserAction uact
)
359 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
360 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
361 (*a
)->data
.diraction
.hang
= FALSE
;
364 void setup_action_growtoedge_north(ObAction
**a
, ObUserAction uact
)
366 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
367 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
370 void setup_action_growtoedge_south(ObAction
**a
, ObUserAction uact
)
372 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
373 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
376 void setup_action_growtoedge_east(ObAction
**a
, ObUserAction uact
)
378 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
379 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
382 void setup_action_growtoedge_west(ObAction
**a
, ObUserAction uact
)
384 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
385 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
388 void setup_action_top_layer(ObAction
**a
, ObUserAction uact
)
390 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
391 (*a
)->data
.layer
.layer
= 1;
394 void setup_action_normal_layer(ObAction
**a
, ObUserAction uact
)
396 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
397 (*a
)->data
.layer
.layer
= 0;
400 void setup_action_bottom_layer(ObAction
**a
, ObUserAction uact
)
402 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
403 (*a
)->data
.layer
.layer
= -1;
406 void setup_action_move(ObAction
**a
, ObUserAction uact
)
408 (*a
)->data
.moveresize
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
409 (*a
)->data
.moveresize
.move
= TRUE
;
410 (*a
)->data
.moveresize
.keyboard
=
411 (uact
== OB_USER_ACTION_NONE
||
412 uact
== OB_USER_ACTION_KEYBOARD_KEY
||
413 uact
== OB_USER_ACTION_MENU_SELECTION
);
416 void setup_action_resize(ObAction
**a
, ObUserAction uact
)
418 (*a
)->data
.moveresize
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
419 (*a
)->data
.moveresize
.move
= FALSE
;
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_showmenu(ObAction
**a
, ObUserAction uact
)
428 (*a
)->data
.showmenu
.any
.client_action
= OB_CLIENT_ACTION_OPTIONAL
;
429 /* you cannot call ShowMenu from inside a menu, cuz the menu code makes
430 assumptions that there is only one menu (and submenus) open at
432 if (uact
== OB_USER_ACTION_MENU_SELECTION
) {
438 void setup_action_focus(ObAction
**a
, ObUserAction uact
)
440 (*a
)->data
.any
.client_action
= OB_CLIENT_ACTION_OPTIONAL
;
443 void setup_client_action(ObAction
**a
, ObUserAction uact
)
445 (*a
)->data
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
448 ActionString actionstrings
[] =
456 "directionalfocusnorth",
457 action_directional_focus
,
458 setup_action_directional_focus_north
461 "directionalfocuseast",
462 action_directional_focus
,
463 setup_action_directional_focus_east
466 "directionalfocussouth",
467 action_directional_focus
,
468 setup_action_directional_focus_south
471 "directionalfocuswest",
472 action_directional_focus
,
473 setup_action_directional_focus_west
476 "directionalfocusnortheast",
477 action_directional_focus
,
478 setup_action_directional_focus_northeast
481 "directionalfocussoutheast",
482 action_directional_focus
,
483 setup_action_directional_focus_southeast
486 "directionalfocussouthwest",
487 action_directional_focus
,
488 setup_action_directional_focus_southwest
491 "directionalfocusnorthwest",
492 action_directional_focus
,
493 setup_action_directional_focus_northwest
517 action_focus_order_to_bottom
,
572 action_toggle_omnipresent
,
577 action_move_relative_horz
,
582 action_move_relative_vert
,
587 action_move_to_center
,
591 "resizerelativehorz",
592 action_resize_relative_horz
,
596 "resizerelativevert",
597 action_resize_relative_vert
,
602 action_move_relative
,
607 action_resize_relative
,
612 action_maximize_full
,
617 action_unmaximize_full
,
621 "togglemaximizefull",
622 action_toggle_maximize_full
,
627 action_maximize_horz
,
632 action_unmaximize_horz
,
636 "togglemaximizehorz",
637 action_toggle_maximize_horz
,
642 action_maximize_vert
,
647 action_unmaximize_vert
,
651 "togglemaximizevert",
652 action_toggle_maximize_vert
,
657 action_toggle_fullscreen
,
662 action_send_to_desktop
,
663 setup_action_send_to_desktop
667 action_send_to_desktop_dir
,
668 setup_action_send_to_desktop_next
671 "sendtodesktopprevious",
672 action_send_to_desktop_dir
,
673 setup_action_send_to_desktop_prev
676 "sendtodesktopright",
677 action_send_to_desktop_dir
,
678 setup_action_send_to_desktop_right
682 action_send_to_desktop_dir
,
683 setup_action_send_to_desktop_left
687 action_send_to_desktop_dir
,
688 setup_action_send_to_desktop_up
692 action_send_to_desktop_dir
,
693 setup_action_send_to_desktop_down
703 setup_action_desktop_next
708 setup_action_desktop_prev
713 setup_action_desktop_right
718 setup_action_desktop_left
723 setup_action_desktop_up
728 setup_action_desktop_down
732 action_toggle_decorations
,
746 "toggledockautohide",
747 action_toggle_dockautohide
,
752 action_toggle_show_desktop
,
762 action_unshow_desktop
,
788 setup_action_showmenu
792 action_send_to_layer
,
793 setup_action_top_layer
798 setup_action_top_layer
802 action_send_to_layer
,
803 setup_action_normal_layer
807 action_send_to_layer
,
808 setup_action_bottom_layer
811 "togglealwaysonbottom",
813 setup_action_bottom_layer
817 action_cycle_windows
,
818 setup_action_cycle_windows_next
822 action_cycle_windows
,
823 setup_action_cycle_windows_previous
828 setup_action_movefromedge_north
833 setup_action_movefromedge_south
838 setup_action_movefromedge_west
843 setup_action_movefromedge_east
848 setup_action_movetoedge_north
853 setup_action_movetoedge_south
858 setup_action_movetoedge_west
863 setup_action_movetoedge_east
868 setup_action_growtoedge_north
873 setup_action_growtoedge_south
878 setup_action_growtoedge_west
883 setup_action_growtoedge_east
892 /* only key bindings can be interactive. thus saith the xor.
893 because of how the mouse is grabbed, mouse events dont even get
894 read during interactive events, so no dice! >:) */
895 #define INTERACTIVE_LIMIT(a, uact) \
896 if (uact != OB_USER_ACTION_KEYBOARD_KEY) \
897 a->data.any.interactive = FALSE;
899 ObAction
*action_from_string(const gchar
*name
, ObUserAction uact
)
902 gboolean exist
= FALSE
;
905 for (i
= 0; actionstrings
[i
].name
; i
++)
906 if (!g_ascii_strcasecmp(name
, actionstrings
[i
].name
)) {
908 a
= action_new(actionstrings
[i
].func
);
909 if (actionstrings
[i
].setup
)
910 actionstrings
[i
].setup(&a
, uact
);
912 INTERACTIVE_LIMIT(a
, uact
);
916 g_message(_("Invalid action '%s' requested. No such action exists."),
919 g_message(_("Invalid use of action '%s'. Action will be ignored."),
924 ObAction
*action_parse(ObParseInst
*i
, xmlDocPtr doc
, xmlNodePtr node
,
928 ObAction
*act
= NULL
;
931 if (parse_attr_string("name", node
, &actname
)) {
932 if ((act
= action_from_string(actname
, uact
))) {
933 if (act
->func
== action_execute
|| act
->func
== action_restart
) {
934 if ((n
= parse_find_node("execute", node
->xmlChildrenNode
))) {
935 gchar
*s
= parse_string(doc
, n
);
936 act
->data
.execute
.path
= parse_expand_tilde(s
);
939 if ((n
= parse_find_node("startupnotify", node
->xmlChildrenNode
))) {
941 if ((m
= parse_find_node("enabled", n
->xmlChildrenNode
)))
942 act
->data
.execute
.startupnotify
= parse_bool(doc
, m
);
943 if ((m
= parse_find_node("name", n
->xmlChildrenNode
)))
944 act
->data
.execute
.name
= parse_string(doc
, m
);
945 if ((m
= parse_find_node("icon", n
->xmlChildrenNode
)))
946 act
->data
.execute
.icon_name
= parse_string(doc
, m
);
948 } else if (act
->func
== action_showmenu
) {
949 if ((n
= parse_find_node("menu", node
->xmlChildrenNode
)))
950 act
->data
.showmenu
.name
= parse_string(doc
, n
);
951 } else if (act
->func
== action_move_relative_horz
||
952 act
->func
== action_move_relative_vert
||
953 act
->func
== action_resize_relative_horz
||
954 act
->func
== action_resize_relative_vert
) {
955 if ((n
= parse_find_node("delta", node
->xmlChildrenNode
)))
956 act
->data
.relative
.deltax
= parse_int(doc
, n
);
957 } else if (act
->func
== action_move_relative
) {
958 if ((n
= parse_find_node("x", node
->xmlChildrenNode
)))
959 act
->data
.relative
.deltax
= parse_int(doc
, n
);
960 if ((n
= parse_find_node("y", node
->xmlChildrenNode
)))
961 act
->data
.relative
.deltay
= parse_int(doc
, n
);
962 } else if (act
->func
== action_resize_relative
) {
963 if ((n
= parse_find_node("left", node
->xmlChildrenNode
)))
964 act
->data
.relative
.deltaxl
= parse_int(doc
, n
);
965 if ((n
= parse_find_node("up", node
->xmlChildrenNode
)))
966 act
->data
.relative
.deltayu
= parse_int(doc
, n
);
967 if ((n
= parse_find_node("right", node
->xmlChildrenNode
)))
968 act
->data
.relative
.deltax
= parse_int(doc
, n
);
969 if ((n
= parse_find_node("down", node
->xmlChildrenNode
)))
970 act
->data
.relative
.deltay
= parse_int(doc
, n
);
971 } else if (act
->func
== action_desktop
) {
972 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
973 act
->data
.desktop
.desk
= parse_int(doc
, n
);
974 if (act
->data
.desktop
.desk
> 0) act
->data
.desktop
.desk
--;
975 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
976 act
->data
.desktop
.inter
.any
.interactive
=
978 } else if (act
->func
== action_send_to_desktop
) {
979 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
980 act
->data
.sendto
.desk
= parse_int(doc
, n
);
981 if (act
->data
.sendto
.desk
> 0) act
->data
.sendto
.desk
--;
982 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
983 act
->data
.sendto
.follow
= parse_bool(doc
, n
);
984 } else if (act
->func
== action_desktop_dir
) {
985 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
986 act
->data
.desktopdir
.wrap
= parse_bool(doc
, n
);
987 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
988 act
->data
.desktopdir
.inter
.any
.interactive
=
990 } else if (act
->func
== action_send_to_desktop_dir
) {
991 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
992 act
->data
.sendtodir
.wrap
= parse_bool(doc
, n
);
993 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
994 act
->data
.sendtodir
.follow
= parse_bool(doc
, n
);
995 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
996 act
->data
.sendtodir
.inter
.any
.interactive
=
998 } else if (act
->func
== action_activate
) {
999 if ((n
= parse_find_node("here", node
->xmlChildrenNode
)))
1000 act
->data
.activate
.here
= parse_bool(doc
, n
);
1001 } else if (act
->func
== action_cycle_windows
) {
1002 if ((n
= parse_find_node("linear", node
->xmlChildrenNode
)))
1003 act
->data
.cycle
.linear
= parse_bool(doc
, n
);
1004 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
1005 act
->data
.cycle
.dialog
= parse_bool(doc
, n
);
1006 } else if (act
->func
== action_directional_focus
) {
1007 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
1008 act
->data
.cycle
.dialog
= parse_bool(doc
, n
);
1009 } else if (act
->func
== action_raise
||
1010 act
->func
== action_lower
||
1011 act
->func
== action_raiselower
||
1012 act
->func
== action_shadelower
||
1013 act
->func
== action_unshaderaise
) {
1015 INTERACTIVE_LIMIT(act
, uact
);
1022 void action_run_list(GSList
*acts
, ObClient
*c
, ObFrameContext context
,
1023 guint state
, guint button
, gint x
, gint y
, Time time
,
1024 gboolean cancel
, gboolean done
)
1028 gboolean inter
= FALSE
;
1034 screen_pointer_pos(&x
, &y
);
1036 if (grab_on_keyboard())
1039 for (it
= acts
; it
; it
= g_slist_next(it
)) {
1041 if (a
->data
.any
.interactive
) {
1048 /* sometimes when we execute another app as an action,
1049 it won't work right unless we XUngrabKeyboard first,
1050 even though we grabbed the key/button Asychronously.
1051 e.g. "gnome-panel-control --main-menu" */
1052 grab_keyboard(FALSE
);
1055 for (it
= acts
; it
; it
= g_slist_next(it
)) {
1058 if (!(a
->data
.any
.client_action
== OB_CLIENT_ACTION_ALWAYS
&& !c
)) {
1059 a
->data
.any
.c
= a
->data
.any
.client_action
? c
: NULL
;
1060 a
->data
.any
.context
= context
;
1064 a
->data
.any
.button
= button
;
1066 a
->data
.any
.time
= time
;
1068 if (a
->data
.any
.interactive
) {
1069 a
->data
.inter
.cancel
= cancel
;
1070 a
->data
.inter
.final
= done
;
1071 if (!(cancel
|| done
))
1072 if (!keyboard_interactive_grab(state
, a
->data
.any
.c
, a
))
1076 /* XXX UGLY HACK race with motion event starting a move and the
1077 button release gettnig processed first. answer: don't queue
1078 moveresize starts. UGLY HACK XXX */
1079 if (a
->data
.any
.interactive
|| a
->func
== action_moveresize
) {
1080 /* interactive actions are not queued */
1083 ob_main_loop_queue_action(ob_main_loop
, a
);
1088 void action_run_string(const gchar
*name
, struct _ObClient
*c
, Time time
)
1093 a
= action_from_string(name
, OB_USER_ACTION_NONE
);
1096 l
= g_slist_append(NULL
, a
);
1098 action_run(l
, c
, 0, time
);
1101 void action_execute(union ActionData
*data
)
1104 gchar
*cmd
, **argv
= 0;
1105 if (data
->execute
.path
) {
1106 cmd
= g_filename_from_utf8(data
->execute
.path
, -1, NULL
, NULL
, NULL
);
1108 if (!g_shell_parse_argv (cmd
, NULL
, &argv
, &e
)) {
1109 g_message(_("Failed to execute '%s': %s"),
1112 } else if (data
->execute
.startupnotify
) {
1115 program
= g_path_get_basename(argv
[0]);
1116 /* sets up the environment */
1117 sn_setup_spawn_environment(program
,
1119 data
->execute
.icon_name
,
1120 /* launch it on the current
1123 data
->execute
.any
.time
);
1124 if (!g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
|
1125 G_SPAWN_DO_NOT_REAP_CHILD
,
1126 NULL
, NULL
, NULL
, &e
)) {
1127 g_message(_("Failed to execute '%s': %s"),
1132 unsetenv("DESKTOP_STARTUP_ID");
1136 if (!g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
|
1137 G_SPAWN_DO_NOT_REAP_CHILD
,
1138 NULL
, NULL
, NULL
, &e
))
1140 g_message(_("Failed to execute '%s': %s"),
1148 g_message(_("Failed to convert the path '%s' from utf8"),
1149 data
->execute
.path
);
1154 void action_activate(union ActionData
*data
)
1156 /* similar to the openbox dock for dockapps, don't let user actions give
1157 focus to 3rd-party docks (panels) either (unless they ask for it
1159 if (data
->client
.any
.c
->type
!= OB_CLIENT_TYPE_DOCK
) {
1160 /* if using focus_delay, stop the timer now so that focus doesn't go
1162 event_halt_focus_delay();
1164 client_activate(data
->activate
.any
.c
, data
->activate
.here
, TRUE
);
1168 void action_focus(union ActionData
*data
)
1170 if (data
->client
.any
.c
) {
1171 /* similar to the openbox dock for dockapps, don't let user actions
1172 give focus to 3rd-party docks (panels) either (unless they ask for
1174 if (data
->client
.any
.c
->type
!= OB_CLIENT_TYPE_DOCK
) {
1175 /* if using focus_delay, stop the timer now so that focus doesn't
1177 event_halt_focus_delay();
1179 client_focus(data
->client
.any
.c
);
1182 /* focus action on something other than a client, make keybindings
1183 work for this openbox instance, but don't focus any specific client
1189 void action_unfocus (union ActionData
*data
)
1191 if (data
->client
.any
.c
== focus_client
)
1192 focus_fallback(FALSE
);
1195 void action_iconify(union ActionData
*data
)
1197 client_action_start(data
);
1198 client_iconify(data
->client
.any
.c
, TRUE
, TRUE
);
1199 client_action_end(data
);
1202 void action_focus_order_to_bottom(union ActionData
*data
)
1204 focus_order_to_bottom(data
->client
.any
.c
);
1207 void action_raiselower(union ActionData
*data
)
1209 ObClient
*c
= data
->client
.any
.c
;
1211 gboolean raise
= FALSE
;
1213 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
1214 if (WINDOW_IS_CLIENT(it
->data
)) {
1215 ObClient
*cit
= it
->data
;
1217 if (cit
== c
) break;
1218 if (client_normal(cit
) == client_normal(c
) &&
1219 cit
->layer
== c
->layer
&&
1220 cit
->frame
->visible
&&
1221 !client_search_transient(c
, cit
))
1223 if (RECT_INTERSECTS_RECT(cit
->frame
->area
, c
->frame
->area
)) {
1237 void action_raise(union ActionData
*data
)
1239 client_action_start(data
);
1240 stacking_raise(CLIENT_AS_WINDOW(data
->client
.any
.c
));
1241 client_action_end(data
);
1244 void action_unshaderaise(union ActionData
*data
)
1246 if (data
->client
.any
.c
->shaded
)
1247 action_unshade(data
);
1252 void action_shadelower(union ActionData
*data
)
1254 if (data
->client
.any
.c
->shaded
)
1260 void action_lower(union ActionData
*data
)
1262 client_action_start(data
);
1263 stacking_lower(CLIENT_AS_WINDOW(data
->client
.any
.c
));
1264 client_action_end(data
);
1267 void action_close(union ActionData
*data
)
1269 client_close(data
->client
.any
.c
);
1272 void action_kill(union ActionData
*data
)
1274 client_kill(data
->client
.any
.c
);
1277 void action_shade(union ActionData
*data
)
1279 client_action_start(data
);
1280 client_shade(data
->client
.any
.c
, TRUE
);
1281 client_action_end(data
);
1284 void action_unshade(union ActionData
*data
)
1286 client_action_start(data
);
1287 client_shade(data
->client
.any
.c
, FALSE
);
1288 client_action_end(data
);
1291 void action_toggle_shade(union ActionData
*data
)
1293 client_action_start(data
);
1294 client_shade(data
->client
.any
.c
, !data
->client
.any
.c
->shaded
);
1295 client_action_end(data
);
1298 void action_toggle_omnipresent(union ActionData
*data
)
1300 client_set_desktop(data
->client
.any
.c
,
1301 data
->client
.any
.c
->desktop
== DESKTOP_ALL
?
1302 screen_desktop
: DESKTOP_ALL
, FALSE
);
1305 void action_move_relative_horz(union ActionData
*data
)
1307 ObClient
*c
= data
->relative
.any
.c
;
1308 client_action_start(data
);
1309 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
);
1310 client_action_end(data
);
1313 void action_move_relative_vert(union ActionData
*data
)
1315 ObClient
*c
= data
->relative
.any
.c
;
1316 client_action_start(data
);
1317 client_move(c
, c
->area
.x
, c
->area
.y
+ data
->relative
.deltax
);
1318 client_action_end(data
);
1321 void action_move_to_center(union ActionData
*data
)
1323 ObClient
*c
= data
->client
.any
.c
;
1325 area
= screen_area_monitor(c
->desktop
, 0);
1326 client_action_start(data
);
1327 client_move(c
, area
->width
/ 2 - c
->area
.width
/ 2,
1328 area
->height
/ 2 - c
->area
.height
/ 2);
1329 client_action_end(data
);
1332 void action_resize_relative_horz(union ActionData
*data
)
1334 ObClient
*c
= data
->relative
.any
.c
;
1335 client_action_start(data
);
1337 c
->area
.width
+ data
->relative
.deltax
* c
->size_inc
.width
,
1339 client_action_end(data
);
1342 void action_resize_relative_vert(union ActionData
*data
)
1344 ObClient
*c
= data
->relative
.any
.c
;
1346 client_action_start(data
);
1347 client_resize(c
, c
->area
.width
, c
->area
.height
+
1348 data
->relative
.deltax
* c
->size_inc
.height
);
1349 client_action_end(data
);
1353 void action_move_relative(union ActionData
*data
)
1355 ObClient
*c
= data
->relative
.any
.c
;
1356 client_action_start(data
);
1357 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
+
1358 data
->relative
.deltay
);
1359 client_action_end(data
);
1362 void action_resize_relative(union ActionData
*data
)
1364 ObClient
*c
= data
->relative
.any
.c
;
1365 gint x
, y
, ow
, w
, oh
, h
, lw
, lh
;
1367 client_action_start(data
);
1372 w
= ow
+ data
->relative
.deltax
* c
->size_inc
.width
1373 + data
->relative
.deltaxl
* c
->size_inc
.width
;
1374 oh
= c
->area
.height
;
1375 h
= oh
+ data
->relative
.deltay
* c
->size_inc
.height
1376 + data
->relative
.deltayu
* c
->size_inc
.height
;
1378 client_try_configure(c
, OB_CORNER_TOPLEFT
, &x
, &y
, &w
, &h
, &lw
, &lh
, TRUE
);
1379 client_move_resize(c
, x
+ (ow
- w
), y
+ (oh
- h
), w
, h
);
1380 client_action_end(data
);
1383 void action_maximize_full(union ActionData
*data
)
1385 client_action_start(data
);
1386 client_maximize(data
->client
.any
.c
, TRUE
, 0);
1387 client_action_end(data
);
1390 void action_unmaximize_full(union ActionData
*data
)
1392 client_action_start(data
);
1393 client_maximize(data
->client
.any
.c
, FALSE
, 0);
1394 client_action_end(data
);
1397 void action_toggle_maximize_full(union ActionData
*data
)
1399 client_action_start(data
);
1400 client_maximize(data
->client
.any
.c
,
1401 !(data
->client
.any
.c
->max_horz
||
1402 data
->client
.any
.c
->max_vert
),
1404 client_action_end(data
);
1407 void action_maximize_horz(union ActionData
*data
)
1409 client_action_start(data
);
1410 client_maximize(data
->client
.any
.c
, TRUE
, 1);
1411 client_action_end(data
);
1414 void action_unmaximize_horz(union ActionData
*data
)
1416 client_action_start(data
);
1417 client_maximize(data
->client
.any
.c
, FALSE
, 1);
1418 client_action_end(data
);
1421 void action_toggle_maximize_horz(union ActionData
*data
)
1423 client_action_start(data
);
1424 client_maximize(data
->client
.any
.c
,
1425 !data
->client
.any
.c
->max_horz
, 1);
1426 client_action_end(data
);
1429 void action_maximize_vert(union ActionData
*data
)
1431 client_action_start(data
);
1432 client_maximize(data
->client
.any
.c
, TRUE
, 2);
1433 client_action_end(data
);
1436 void action_unmaximize_vert(union ActionData
*data
)
1438 client_action_start(data
);
1439 client_maximize(data
->client
.any
.c
, FALSE
, 2);
1440 client_action_end(data
);
1443 void action_toggle_maximize_vert(union ActionData
*data
)
1445 client_action_start(data
);
1446 client_maximize(data
->client
.any
.c
,
1447 !data
->client
.any
.c
->max_vert
, 2);
1448 client_action_end(data
);
1451 void action_toggle_fullscreen(union ActionData
*data
)
1453 client_action_start(data
);
1454 client_fullscreen(data
->client
.any
.c
, !(data
->client
.any
.c
->fullscreen
));
1455 client_action_end(data
);
1458 void action_send_to_desktop(union ActionData
*data
)
1460 ObClient
*c
= data
->sendto
.any
.c
;
1462 if (!client_normal(c
)) return;
1464 if (data
->sendto
.desk
< screen_num_desktops
||
1465 data
->sendto
.desk
== DESKTOP_ALL
) {
1466 client_set_desktop(c
, data
->sendto
.desk
, data
->sendto
.follow
);
1467 if (data
->sendto
.follow
)
1468 screen_set_desktop(data
->sendto
.desk
);
1472 void action_desktop(union ActionData
*data
)
1474 static guint first
= (unsigned) -1;
1476 if (data
->inter
.any
.interactive
&& first
== (unsigned) -1)
1477 first
= screen_desktop
;
1479 if (!data
->inter
.any
.interactive
||
1480 (!data
->inter
.cancel
&& !data
->inter
.final
))
1482 if (data
->desktop
.desk
< screen_num_desktops
||
1483 data
->desktop
.desk
== DESKTOP_ALL
)
1485 screen_set_desktop(data
->desktop
.desk
);
1486 if (data
->inter
.any
.interactive
)
1487 screen_desktop_popup(data
->desktop
.desk
, TRUE
);
1489 } else if (data
->inter
.cancel
) {
1490 screen_set_desktop(first
);
1493 if (!data
->inter
.any
.interactive
|| data
->inter
.final
) {
1494 screen_desktop_popup(0, FALSE
);
1495 first
= (unsigned) -1;
1499 void action_desktop_dir(union ActionData
*data
)
1503 d
= screen_cycle_desktop(data
->desktopdir
.dir
,
1504 data
->desktopdir
.wrap
,
1505 data
->desktopdir
.linear
,
1506 data
->desktopdir
.inter
.any
.interactive
,
1507 data
->desktopdir
.inter
.final
,
1508 data
->desktopdir
.inter
.cancel
);
1509 if (!data
->sendtodir
.inter
.any
.interactive
||
1510 !data
->sendtodir
.inter
.final
||
1511 data
->sendtodir
.inter
.cancel
)
1513 screen_set_desktop(d
);
1517 void action_send_to_desktop_dir(union ActionData
*data
)
1519 ObClient
*c
= data
->sendtodir
.inter
.any
.c
;
1522 if (!client_normal(c
)) return;
1524 d
= screen_cycle_desktop(data
->sendtodir
.dir
, data
->sendtodir
.wrap
,
1525 data
->sendtodir
.linear
,
1526 data
->sendtodir
.inter
.any
.interactive
,
1527 data
->sendtodir
.inter
.final
,
1528 data
->sendtodir
.inter
.cancel
);
1529 if (!data
->sendtodir
.inter
.any
.interactive
||
1530 !data
->sendtodir
.inter
.final
||
1531 data
->sendtodir
.inter
.cancel
)
1533 client_set_desktop(c
, d
, data
->sendtodir
.follow
);
1534 if (data
->sendtodir
.follow
)
1535 screen_set_desktop(d
);
1539 void action_desktop_last(union ActionData
*data
)
1541 screen_set_desktop(screen_last_desktop
);
1544 void action_toggle_decorations(union ActionData
*data
)
1546 ObClient
*c
= data
->client
.any
.c
;
1548 client_action_start(data
);
1549 client_set_undecorated(c
, !c
->undecorated
);
1550 client_action_end(data
);
1553 static guint32
pick_corner(gint x
, gint y
, gint cx
, gint cy
, gint cw
, gint ch
)
1555 if (config_resize_four_corners
) {
1556 if (x
- cx
> cw
/ 2) {
1557 if (y
- cy
> ch
/ 2)
1558 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1560 return prop_atoms
.net_wm_moveresize_size_topright
;
1562 if (y
- cy
> ch
/ 2)
1563 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1565 return prop_atoms
.net_wm_moveresize_size_topleft
;
1568 if (x
- cx
> cw
* 2 / 3) {
1569 if (y
- cy
> ch
* 2 / 3)
1570 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1571 else if (y
- cy
< ch
/ 3)
1572 return prop_atoms
.net_wm_moveresize_size_topright
;
1574 return prop_atoms
.net_wm_moveresize_size_right
;
1575 } else if (x
- cx
< cw
/ 3) {
1576 if (y
- cy
> ch
* 2 / 3)
1577 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1578 else if (y
- cy
< ch
/ 3)
1579 return prop_atoms
.net_wm_moveresize_size_topleft
;
1581 return prop_atoms
.net_wm_moveresize_size_left
;
1583 if (y
- cy
> ch
* 2 / 3)
1584 return prop_atoms
.net_wm_moveresize_size_bottom
;
1585 else if (y
- cy
< ch
/ 3)
1586 return prop_atoms
.net_wm_moveresize_size_top
;
1588 return prop_atoms
.net_wm_moveresize_move
;
1592 void action_moveresize(union ActionData
*data
)
1594 ObClient
*c
= data
->moveresize
.any
.c
;
1597 if (!client_normal(c
)) return;
1599 if (data
->moveresize
.keyboard
) {
1600 corner
= (data
->moveresize
.move
?
1601 prop_atoms
.net_wm_moveresize_move_keyboard
:
1602 prop_atoms
.net_wm_moveresize_size_keyboard
);
1604 corner
= (data
->moveresize
.move
?
1605 prop_atoms
.net_wm_moveresize_move
:
1606 pick_corner(data
->any
.x
, data
->any
.y
,
1607 c
->frame
->area
.x
, c
->frame
->area
.y
,
1608 /* use the client size because the frame
1609 can be differently sized (shaded
1610 windows) and we want this based on the
1612 c
->area
.width
+ c
->frame
->size
.left
+
1613 c
->frame
->size
.right
,
1614 c
->area
.height
+ c
->frame
->size
.top
+
1615 c
->frame
->size
.bottom
));
1618 moveresize_start(c
, data
->any
.x
, data
->any
.y
, data
->any
.button
, corner
);
1621 void action_reconfigure(union ActionData
*data
)
1626 void action_restart(union ActionData
*data
)
1628 ob_restart_other(data
->execute
.path
);
1631 void action_exit(union ActionData
*data
)
1636 void action_showmenu(union ActionData
*data
)
1638 if (data
->showmenu
.name
) {
1639 menu_show(data
->showmenu
.name
, data
->any
.x
, data
->any
.y
,
1640 data
->showmenu
.any
.c
);
1644 void action_cycle_windows(union ActionData
*data
)
1646 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1648 event_halt_focus_delay();
1650 focus_cycle(data
->cycle
.forward
, data
->cycle
.linear
, data
->any
.interactive
,
1652 data
->cycle
.inter
.final
, data
->cycle
.inter
.cancel
);
1655 void action_directional_focus(union ActionData
*data
)
1657 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1659 event_halt_focus_delay();
1661 focus_directional_cycle(data
->interdiraction
.direction
,
1662 data
->any
.interactive
,
1663 data
->interdiraction
.dialog
,
1664 data
->interdiraction
.inter
.final
,
1665 data
->interdiraction
.inter
.cancel
);
1668 void action_movetoedge(union ActionData
*data
)
1671 ObClient
*c
= data
->diraction
.any
.c
;
1673 x
= c
->frame
->area
.x
;
1674 y
= c
->frame
->area
.y
;
1676 switch(data
->diraction
.direction
) {
1677 case OB_DIRECTION_NORTH
:
1678 y
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
,
1679 data
->diraction
.hang
)
1680 - (data
->diraction
.hang
? c
->frame
->area
.height
: 0);
1682 case OB_DIRECTION_WEST
:
1683 x
= client_directional_edge_search(c
, OB_DIRECTION_WEST
,
1684 data
->diraction
.hang
)
1685 - (data
->diraction
.hang
? c
->frame
->area
.width
: 0);
1687 case OB_DIRECTION_SOUTH
:
1688 y
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
,
1689 data
->diraction
.hang
)
1690 - (data
->diraction
.hang
? 0 : c
->frame
->area
.height
);
1692 case OB_DIRECTION_EAST
:
1693 x
= client_directional_edge_search(c
, OB_DIRECTION_EAST
,
1694 data
->diraction
.hang
)
1695 - (data
->diraction
.hang
? 0 : c
->frame
->area
.width
);
1698 g_assert_not_reached();
1700 frame_frame_gravity(c
->frame
, &x
, &y
);
1701 client_action_start(data
);
1702 client_move(c
, x
, y
);
1703 client_action_end(data
);
1706 void action_growtoedge(union ActionData
*data
)
1708 gint x
, y
, width
, height
, dest
;
1709 ObClient
*c
= data
->diraction
.any
.c
;
1712 //FIXME growtoedge resizes shaded windows to 0 height
1716 a
= screen_area(c
->desktop
);
1717 x
= c
->frame
->area
.x
;
1718 y
= c
->frame
->area
.y
;
1719 width
= c
->frame
->area
.width
;
1720 height
= c
->frame
->area
.height
;
1722 switch(data
->diraction
.direction
) {
1723 case OB_DIRECTION_NORTH
:
1724 dest
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
, FALSE
);
1726 height
= c
->frame
->area
.height
/ 2;
1728 height
= c
->frame
->area
.y
+ c
->frame
->area
.height
- dest
;
1732 case OB_DIRECTION_WEST
:
1733 dest
= client_directional_edge_search(c
, OB_DIRECTION_WEST
, FALSE
);
1735 width
= c
->frame
->area
.width
/ 2;
1737 width
= c
->frame
->area
.x
+ c
->frame
->area
.width
- dest
;
1741 case OB_DIRECTION_SOUTH
:
1742 dest
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
, FALSE
);
1743 if (a
->y
+ a
->height
== y
+ c
->frame
->area
.height
) {
1744 height
= c
->frame
->area
.height
/ 2;
1745 y
= a
->y
+ a
->height
- height
;
1747 height
= dest
- c
->frame
->area
.y
;
1748 y
+= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1749 height
-= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1751 case OB_DIRECTION_EAST
:
1752 dest
= client_directional_edge_search(c
, OB_DIRECTION_EAST
, FALSE
);
1753 if (a
->x
+ a
->width
== x
+ c
->frame
->area
.width
) {
1754 width
= c
->frame
->area
.width
/ 2;
1755 x
= a
->x
+ a
->width
- width
;
1757 width
= dest
- c
->frame
->area
.x
;
1758 x
+= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1759 width
-= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1762 g_assert_not_reached();
1764 frame_frame_gravity(c
->frame
, &x
, &y
);
1765 width
-= c
->frame
->size
.left
+ c
->frame
->size
.right
;
1766 height
-= c
->frame
->size
.top
+ c
->frame
->size
.bottom
;
1767 client_action_start(data
);
1768 client_move_resize(c
, x
, y
, width
, height
);
1769 client_action_end(data
);
1772 void action_send_to_layer(union ActionData
*data
)
1774 client_set_layer(data
->layer
.any
.c
, data
->layer
.layer
);
1777 void action_toggle_layer(union ActionData
*data
)
1779 ObClient
*c
= data
->layer
.any
.c
;
1781 client_action_start(data
);
1782 if (data
->layer
.layer
< 0)
1783 client_set_layer(c
, c
->below
? 0 : -1);
1784 else if (data
->layer
.layer
> 0)
1785 client_set_layer(c
, c
->above
? 0 : 1);
1786 client_action_end(data
);
1789 void action_toggle_dockautohide(union ActionData
*data
)
1791 config_dock_hide
= !config_dock_hide
;
1795 void action_toggle_show_desktop(union ActionData
*data
)
1797 screen_show_desktop(!screen_showing_desktop
);
1800 void action_show_desktop(union ActionData
*data
)
1802 screen_show_desktop(TRUE
);
1805 void action_unshow_desktop(union ActionData
*data
)
1807 screen_show_desktop(FALSE
);