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 Ben 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"
39 inline void client_action_start(union ActionData
*data
)
41 if (config_focus_follow
)
42 if (data
->any
.context
!= OB_FRAME_CONTEXT_CLIENT
&& !data
->any
.button
)
43 grab_pointer(TRUE
, OB_CURSOR_NONE
);
46 inline void client_action_end(union ActionData
*data
)
48 if (config_focus_follow
)
49 if (data
->any
.context
!= OB_FRAME_CONTEXT_CLIENT
) {
50 if (!data
->any
.button
) {
51 grab_pointer(FALSE
, OB_CURSOR_NONE
);
55 /* usually this is sorta redundant, but with a press action
56 the enter event will come as a GrabNotify which is
57 ignored, so this will handle that case */
58 if ((c
= client_under_pointer()))
59 event_enter_client(c
);
67 void (*func
)(union ActionData
*);
68 void (*setup
)(ObAction
**, ObUserAction uact
);
71 static ObAction
*action_new(void (*func
)(union ActionData
*data
))
73 ObAction
*a
= g_new0(ObAction
, 1);
80 void action_ref(ObAction
*a
)
85 void action_unref(ObAction
*a
)
87 if (a
== NULL
) return;
89 if (--a
->ref
> 0) return;
91 /* deal with pointers */
92 if (a
->func
== action_execute
|| a
->func
== action_restart
)
93 g_free(a
->data
.execute
.path
);
94 else if (a
->func
== action_showmenu
)
95 g_free(a
->data
.showmenu
.name
);
100 ObAction
* action_copy(const ObAction
*src
)
102 ObAction
*a
= action_new(src
->func
);
106 /* deal with pointers */
107 if (a
->func
== action_execute
|| a
->func
== action_restart
)
108 a
->data
.execute
.path
= g_strdup(a
->data
.execute
.path
);
109 else if (a
->func
== action_showmenu
)
110 a
->data
.showmenu
.name
= g_strdup(a
->data
.showmenu
.name
);
115 void setup_action_directional_focus_north(ObAction
**a
, ObUserAction uact
)
117 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
118 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTH
;
119 (*a
)->data
.interdiraction
.dialog
= TRUE
;
122 void setup_action_directional_focus_east(ObAction
**a
, ObUserAction uact
)
124 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
125 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_EAST
;
126 (*a
)->data
.interdiraction
.dialog
= TRUE
;
129 void setup_action_directional_focus_south(ObAction
**a
, ObUserAction uact
)
131 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
132 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTH
;
133 (*a
)->data
.interdiraction
.dialog
= TRUE
;
136 void setup_action_directional_focus_west(ObAction
**a
, ObUserAction uact
)
138 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
139 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_WEST
;
140 (*a
)->data
.interdiraction
.dialog
= TRUE
;
143 void setup_action_directional_focus_northeast(ObAction
**a
, ObUserAction uact
)
145 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
146 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTHEAST
;
147 (*a
)->data
.interdiraction
.dialog
= TRUE
;
150 void setup_action_directional_focus_southeast(ObAction
**a
, ObUserAction uact
)
152 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
153 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTHEAST
;
154 (*a
)->data
.interdiraction
.dialog
= TRUE
;
157 void setup_action_directional_focus_southwest(ObAction
**a
, ObUserAction uact
)
159 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
160 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_SOUTHWEST
;
161 (*a
)->data
.interdiraction
.dialog
= TRUE
;
164 void setup_action_directional_focus_northwest(ObAction
**a
, ObUserAction uact
)
166 (*a
)->data
.interdiraction
.inter
.any
.interactive
= TRUE
;
167 (*a
)->data
.interdiraction
.direction
= OB_DIRECTION_NORTHWEST
;
168 (*a
)->data
.interdiraction
.dialog
= TRUE
;
171 void setup_action_send_to_desktop(ObAction
**a
, ObUserAction uact
)
173 (*a
)->data
.sendto
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
174 (*a
)->data
.sendto
.follow
= TRUE
;
177 void setup_action_send_to_desktop_prev(ObAction
**a
, ObUserAction uact
)
179 (*a
)->data
.sendtodir
.inter
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
180 (*a
)->data
.sendtodir
.inter
.any
.interactive
= TRUE
;
181 (*a
)->data
.sendtodir
.dir
= OB_DIRECTION_WEST
;
182 (*a
)->data
.sendtodir
.linear
= TRUE
;
183 (*a
)->data
.sendtodir
.wrap
= TRUE
;
184 (*a
)->data
.sendtodir
.follow
= TRUE
;
187 void setup_action_send_to_desktop_next(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_EAST
;
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_left(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_WEST
;
202 (*a
)->data
.sendtodir
.linear
= FALSE
;
203 (*a
)->data
.sendtodir
.wrap
= TRUE
;
204 (*a
)->data
.sendtodir
.follow
= TRUE
;
207 void setup_action_send_to_desktop_right(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_EAST
;
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_up(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_NORTH
;
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_down(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_SOUTH
;
232 (*a
)->data
.sendtodir
.linear
= FALSE
;
233 (*a
)->data
.sendtodir
.wrap
= TRUE
;
234 (*a
)->data
.sendtodir
.follow
= TRUE
;
237 void setup_action_desktop(ObAction
**a
, ObUserAction uact
)
239 (*a
)->data
.desktop
.inter
.any
.interactive
= FALSE
;
242 void setup_action_desktop_prev(ObAction
**a
, ObUserAction uact
)
244 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
245 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_WEST
;
246 (*a
)->data
.desktopdir
.linear
= TRUE
;
247 (*a
)->data
.desktopdir
.wrap
= TRUE
;
250 void setup_action_desktop_next(ObAction
**a
, ObUserAction uact
)
252 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
253 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_EAST
;
254 (*a
)->data
.desktopdir
.linear
= TRUE
;
255 (*a
)->data
.desktopdir
.wrap
= TRUE
;
258 void setup_action_desktop_left(ObAction
**a
, ObUserAction uact
)
260 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
261 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_WEST
;
262 (*a
)->data
.desktopdir
.linear
= FALSE
;
263 (*a
)->data
.desktopdir
.wrap
= TRUE
;
266 void setup_action_desktop_right(ObAction
**a
, ObUserAction uact
)
268 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
269 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_EAST
;
270 (*a
)->data
.desktopdir
.linear
= FALSE
;
271 (*a
)->data
.desktopdir
.wrap
= TRUE
;
274 void setup_action_desktop_up(ObAction
**a
, ObUserAction uact
)
276 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
277 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_NORTH
;
278 (*a
)->data
.desktopdir
.linear
= FALSE
;
279 (*a
)->data
.desktopdir
.wrap
= TRUE
;
282 void setup_action_desktop_down(ObAction
**a
, ObUserAction uact
)
284 (*a
)->data
.desktopdir
.inter
.any
.interactive
= TRUE
;
285 (*a
)->data
.desktopdir
.dir
= OB_DIRECTION_SOUTH
;
286 (*a
)->data
.desktopdir
.linear
= FALSE
;
287 (*a
)->data
.desktopdir
.wrap
= TRUE
;
290 void setup_action_cycle_windows_next(ObAction
**a
, ObUserAction uact
)
292 (*a
)->data
.cycle
.inter
.any
.interactive
= TRUE
;
293 (*a
)->data
.cycle
.linear
= FALSE
;
294 (*a
)->data
.cycle
.forward
= TRUE
;
295 (*a
)->data
.cycle
.dialog
= TRUE
;
298 void setup_action_cycle_windows_previous(ObAction
**a
, ObUserAction uact
)
300 (*a
)->data
.cycle
.inter
.any
.interactive
= TRUE
;
301 (*a
)->data
.cycle
.linear
= FALSE
;
302 (*a
)->data
.cycle
.forward
= FALSE
;
303 (*a
)->data
.cycle
.dialog
= TRUE
;
306 void setup_action_movefromedge_north(ObAction
**a
, ObUserAction uact
)
308 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
309 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
310 (*a
)->data
.diraction
.hang
= TRUE
;
313 void setup_action_movefromedge_south(ObAction
**a
, ObUserAction uact
)
315 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
316 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
317 (*a
)->data
.diraction
.hang
= TRUE
;
320 void setup_action_movefromedge_east(ObAction
**a
, ObUserAction uact
)
322 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
323 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
324 (*a
)->data
.diraction
.hang
= TRUE
;
327 void setup_action_movefromedge_west(ObAction
**a
, ObUserAction uact
)
329 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
330 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
331 (*a
)->data
.diraction
.hang
= TRUE
;
334 void setup_action_movetoedge_north(ObAction
**a
, ObUserAction uact
)
336 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
337 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
338 (*a
)->data
.diraction
.hang
= FALSE
;
341 void setup_action_movetoedge_south(ObAction
**a
, ObUserAction uact
)
343 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
344 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
345 (*a
)->data
.diraction
.hang
= FALSE
;
348 void setup_action_movetoedge_east(ObAction
**a
, ObUserAction uact
)
350 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
351 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
352 (*a
)->data
.diraction
.hang
= FALSE
;
355 void setup_action_movetoedge_west(ObAction
**a
, ObUserAction uact
)
357 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
358 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
359 (*a
)->data
.diraction
.hang
= FALSE
;
362 void setup_action_growtoedge_north(ObAction
**a
, ObUserAction uact
)
364 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
365 (*a
)->data
.diraction
.direction
= OB_DIRECTION_NORTH
;
368 void setup_action_growtoedge_south(ObAction
**a
, ObUserAction uact
)
370 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
371 (*a
)->data
.diraction
.direction
= OB_DIRECTION_SOUTH
;
374 void setup_action_growtoedge_east(ObAction
**a
, ObUserAction uact
)
376 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
377 (*a
)->data
.diraction
.direction
= OB_DIRECTION_EAST
;
380 void setup_action_growtoedge_west(ObAction
**a
, ObUserAction uact
)
382 (*a
)->data
.diraction
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
383 (*a
)->data
.diraction
.direction
= OB_DIRECTION_WEST
;
386 void setup_action_top_layer(ObAction
**a
, ObUserAction uact
)
388 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
389 (*a
)->data
.layer
.layer
= 1;
392 void setup_action_normal_layer(ObAction
**a
, ObUserAction uact
)
394 (*a
)->data
.layer
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
395 (*a
)->data
.layer
.layer
= 0;
398 void setup_action_bottom_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_move(ObAction
**a
, ObUserAction uact
)
406 (*a
)->data
.moveresize
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
407 (*a
)->data
.moveresize
.move
= TRUE
;
408 (*a
)->data
.moveresize
.keyboard
=
409 (uact
== OB_USER_ACTION_NONE
||
410 uact
== OB_USER_ACTION_KEYBOARD_KEY
||
411 uact
== OB_USER_ACTION_MENU_SELECTION
);
414 void setup_action_resize(ObAction
**a
, ObUserAction uact
)
416 (*a
)->data
.moveresize
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
417 (*a
)->data
.moveresize
.move
= FALSE
;
418 (*a
)->data
.moveresize
.keyboard
=
419 (uact
== OB_USER_ACTION_NONE
||
420 uact
== OB_USER_ACTION_KEYBOARD_KEY
||
421 uact
== OB_USER_ACTION_MENU_SELECTION
);
424 void setup_action_showmenu(ObAction
**a
, ObUserAction uact
)
426 (*a
)->data
.showmenu
.any
.client_action
= OB_CLIENT_ACTION_OPTIONAL
;
427 /* you cannot call ShowMenu from inside a menu, cuz the menu code makes
428 assumptions that there is only one menu (and submenus) open at
430 if (uact
== OB_USER_ACTION_MENU_SELECTION
) {
436 void setup_client_action(ObAction
**a
, ObUserAction uact
)
438 (*a
)->data
.any
.client_action
= OB_CLIENT_ACTION_ALWAYS
;
441 ActionString actionstrings
[] =
449 "directionalfocusnorth",
450 action_directional_focus
,
451 setup_action_directional_focus_north
454 "directionalfocuseast",
455 action_directional_focus
,
456 setup_action_directional_focus_east
459 "directionalfocussouth",
460 action_directional_focus
,
461 setup_action_directional_focus_south
464 "directionalfocuswest",
465 action_directional_focus
,
466 setup_action_directional_focus_west
469 "directionalfocusnortheast",
470 action_directional_focus
,
471 setup_action_directional_focus_northeast
474 "directionalfocussoutheast",
475 action_directional_focus
,
476 setup_action_directional_focus_southeast
479 "directionalfocussouthwest",
480 action_directional_focus
,
481 setup_action_directional_focus_southwest
484 "directionalfocusnorthwest",
485 action_directional_focus
,
486 setup_action_directional_focus_northwest
510 action_focus_order_to_bottom
,
565 action_toggle_omnipresent
,
570 action_move_relative_horz
,
575 action_move_relative_vert
,
580 action_move_to_center
,
584 "resizerelativehorz",
585 action_resize_relative_horz
,
589 "resizerelativevert",
590 action_resize_relative_vert
,
595 action_move_relative
,
600 action_resize_relative
,
605 action_maximize_full
,
610 action_unmaximize_full
,
614 "togglemaximizefull",
615 action_toggle_maximize_full
,
620 action_maximize_horz
,
625 action_unmaximize_horz
,
629 "togglemaximizehorz",
630 action_toggle_maximize_horz
,
635 action_maximize_vert
,
640 action_unmaximize_vert
,
644 "togglemaximizevert",
645 action_toggle_maximize_vert
,
650 action_toggle_fullscreen
,
655 action_send_to_desktop
,
656 setup_action_send_to_desktop
660 action_send_to_desktop_dir
,
661 setup_action_send_to_desktop_next
664 "sendtodesktopprevious",
665 action_send_to_desktop_dir
,
666 setup_action_send_to_desktop_prev
669 "sendtodesktopright",
670 action_send_to_desktop_dir
,
671 setup_action_send_to_desktop_right
675 action_send_to_desktop_dir
,
676 setup_action_send_to_desktop_left
680 action_send_to_desktop_dir
,
681 setup_action_send_to_desktop_up
685 action_send_to_desktop_dir
,
686 setup_action_send_to_desktop_down
696 setup_action_desktop_next
701 setup_action_desktop_prev
706 setup_action_desktop_right
711 setup_action_desktop_left
716 setup_action_desktop_up
721 setup_action_desktop_down
725 action_toggle_decorations
,
739 "toggledockautohide",
740 action_toggle_dockautohide
,
745 action_toggle_show_desktop
,
755 action_unshow_desktop
,
781 setup_action_showmenu
785 action_send_to_layer
,
786 setup_action_top_layer
791 setup_action_top_layer
795 action_send_to_layer
,
796 setup_action_normal_layer
800 action_send_to_layer
,
801 setup_action_bottom_layer
804 "togglealwaysonbottom",
806 setup_action_bottom_layer
810 action_cycle_windows
,
811 setup_action_cycle_windows_next
815 action_cycle_windows
,
816 setup_action_cycle_windows_previous
821 setup_action_movefromedge_north
826 setup_action_movefromedge_south
831 setup_action_movefromedge_west
836 setup_action_movefromedge_east
841 setup_action_movetoedge_north
846 setup_action_movetoedge_south
851 setup_action_movetoedge_west
856 setup_action_movetoedge_east
861 setup_action_growtoedge_north
866 setup_action_growtoedge_south
871 setup_action_growtoedge_west
876 setup_action_growtoedge_east
885 /* only key bindings can be interactive. thus saith the xor.
886 because of how the mouse is grabbed, mouse events dont even get
887 read during interactive events, so no dice! >:) */
888 #define INTERACTIVE_LIMIT(a, uact) \
889 if (uact != OB_USER_ACTION_KEYBOARD_KEY) \
890 a->data.any.interactive = FALSE;
892 ObAction
*action_from_string(const gchar
*name
, ObUserAction uact
)
895 gboolean exist
= FALSE
;
898 for (i
= 0; actionstrings
[i
].name
; i
++)
899 if (!g_ascii_strcasecmp(name
, actionstrings
[i
].name
)) {
901 a
= action_new(actionstrings
[i
].func
);
902 if (actionstrings
[i
].setup
)
903 actionstrings
[i
].setup(&a
, uact
);
905 INTERACTIVE_LIMIT(a
, uact
);
909 g_warning("Invalid action '%s' requested. No such action exists.",
912 g_warning("Invalid use of action '%s'. Action will be ignored.", name
);
916 ObAction
*action_parse(ObParseInst
*i
, xmlDocPtr doc
, xmlNodePtr node
,
920 ObAction
*act
= NULL
;
923 if (parse_attr_string("name", node
, &actname
)) {
924 if ((act
= action_from_string(actname
, uact
))) {
925 if (act
->func
== action_execute
|| act
->func
== action_restart
) {
926 if ((n
= parse_find_node("execute", node
->xmlChildrenNode
))) {
927 gchar
*s
= parse_string(doc
, n
);
928 act
->data
.execute
.path
= parse_expand_tilde(s
);
931 } else if (act
->func
== action_showmenu
) {
932 if ((n
= parse_find_node("menu", node
->xmlChildrenNode
)))
933 act
->data
.showmenu
.name
= parse_string(doc
, n
);
934 } else if (act
->func
== action_move_relative_horz
||
935 act
->func
== action_move_relative_vert
||
936 act
->func
== action_resize_relative_horz
||
937 act
->func
== action_resize_relative_vert
) {
938 if ((n
= parse_find_node("delta", node
->xmlChildrenNode
)))
939 act
->data
.relative
.deltax
= parse_int(doc
, n
);
940 } else if (act
->func
== action_move_relative
) {
941 if ((n
= parse_find_node("x", node
->xmlChildrenNode
)))
942 act
->data
.relative
.deltax
= parse_int(doc
, n
);
943 if ((n
= parse_find_node("y", node
->xmlChildrenNode
)))
944 act
->data
.relative
.deltay
= parse_int(doc
, n
);
945 } else if (act
->func
== action_resize_relative
) {
946 if ((n
= parse_find_node("left", node
->xmlChildrenNode
)))
947 act
->data
.relative
.deltaxl
= parse_int(doc
, n
);
948 if ((n
= parse_find_node("up", node
->xmlChildrenNode
)))
949 act
->data
.relative
.deltayu
= parse_int(doc
, n
);
950 if ((n
= parse_find_node("right", node
->xmlChildrenNode
)))
951 act
->data
.relative
.deltax
= parse_int(doc
, n
);
952 if ((n
= parse_find_node("down", node
->xmlChildrenNode
)))
953 act
->data
.relative
.deltay
= parse_int(doc
, n
);
954 } else if (act
->func
== action_desktop
) {
955 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
956 act
->data
.desktop
.desk
= parse_int(doc
, n
);
957 if (act
->data
.desktop
.desk
> 0) act
->data
.desktop
.desk
--;
958 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
959 act
->data
.desktop
.inter
.any
.interactive
=
961 } else if (act
->func
== action_send_to_desktop
) {
962 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
963 act
->data
.sendto
.desk
= parse_int(doc
, n
);
964 if (act
->data
.sendto
.desk
> 0) act
->data
.sendto
.desk
--;
965 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
966 act
->data
.sendto
.follow
= parse_bool(doc
, n
);
967 } else if (act
->func
== action_desktop_dir
) {
968 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
969 act
->data
.desktopdir
.wrap
= parse_bool(doc
, n
);
970 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
971 act
->data
.desktopdir
.inter
.any
.interactive
=
973 } else if (act
->func
== action_send_to_desktop_dir
) {
974 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
975 act
->data
.sendtodir
.wrap
= parse_bool(doc
, n
);
976 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
977 act
->data
.sendtodir
.follow
= parse_bool(doc
, n
);
978 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
979 act
->data
.sendtodir
.inter
.any
.interactive
=
981 } else if (act
->func
== action_activate
) {
982 if ((n
= parse_find_node("here", node
->xmlChildrenNode
)))
983 act
->data
.activate
.here
= parse_bool(doc
, n
);
984 } else if (act
->func
== action_cycle_windows
) {
985 if ((n
= parse_find_node("linear", node
->xmlChildrenNode
)))
986 act
->data
.cycle
.linear
= parse_bool(doc
, n
);
987 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
988 act
->data
.cycle
.dialog
= parse_bool(doc
, n
);
989 } else if (act
->func
== action_directional_focus
) {
990 if ((n
= parse_find_node("dialog", node
->xmlChildrenNode
)))
991 act
->data
.cycle
.dialog
= parse_bool(doc
, n
);
992 } else if (act
->func
== action_raise
||
993 act
->func
== action_lower
||
994 act
->func
== action_raiselower
||
995 act
->func
== action_shadelower
||
996 act
->func
== action_unshaderaise
) {
997 if ((n
= parse_find_node("group", node
->xmlChildrenNode
)))
998 act
->data
.stacking
.group
= parse_bool(doc
, n
);
1000 INTERACTIVE_LIMIT(act
, uact
);
1007 void action_run_list(GSList
*acts
, ObClient
*c
, ObFrameContext context
,
1008 guint state
, guint button
, gint x
, gint y
,
1009 gboolean cancel
, gboolean done
)
1013 gboolean inter
= FALSE
;
1019 screen_pointer_pos(&x
, &y
);
1021 if (grab_on_keyboard())
1024 for (it
= acts
; it
; it
= g_slist_next(it
)) {
1026 if (a
->data
.any
.interactive
) {
1033 /* sometimes when we execute another app as an action,
1034 it won't work right unless we XUngrabKeyboard first,
1035 even though we grabbed the key/button Asychronously.
1036 e.g. "gnome-panel-control --main-menu" */
1037 XUngrabKeyboard(ob_display
, event_lasttime
);
1040 for (it
= acts
; it
; it
= g_slist_next(it
)) {
1043 if (!(a
->data
.any
.client_action
== OB_CLIENT_ACTION_ALWAYS
&& !c
)) {
1044 a
->data
.any
.c
= a
->data
.any
.client_action
? c
: NULL
;
1045 a
->data
.any
.context
= context
;
1049 a
->data
.any
.button
= button
;
1051 if (a
->data
.any
.interactive
) {
1052 a
->data
.inter
.cancel
= cancel
;
1053 a
->data
.inter
.final
= done
;
1054 if (!(cancel
|| done
))
1055 if (!keyboard_interactive_grab(state
, a
->data
.any
.c
, a
))
1059 /* XXX UGLY HACK race with motion event starting a move and the
1060 button release gettnig processed first. answer: don't queue
1061 moveresize starts. UGLY HACK XXX */
1062 if (a
->data
.any
.interactive
|| a
->func
== action_moveresize
) {
1063 /* interactive actions are not queued */
1066 ob_main_loop_queue_action(ob_main_loop
, a
);
1071 void action_run_string(const gchar
*name
, struct _ObClient
*c
)
1076 a
= action_from_string(name
, OB_USER_ACTION_NONE
);
1079 l
= g_slist_append(NULL
, a
);
1081 action_run(l
, c
, 0);
1084 void action_execute(union ActionData
*data
)
1087 gchar
*cmd
, **argv
= 0;
1088 if (data
->execute
.path
) {
1089 cmd
= g_filename_from_utf8(data
->execute
.path
, -1, NULL
, NULL
, NULL
);
1091 if (!g_shell_parse_argv (cmd
, NULL
, &argv
, &e
)) {
1092 g_warning("failed to execute '%s': %s",
1096 if (!g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
|
1097 G_SPAWN_DO_NOT_REAP_CHILD
,
1098 NULL
, NULL
, NULL
, &e
)) {
1099 g_warning("failed to execute '%s': %s",
1107 g_warning("failed to convert '%s' from utf8", data
->execute
.path
);
1112 void action_activate(union ActionData
*data
)
1114 client_activate(data
->activate
.any
.c
, data
->activate
.here
);
1117 void action_focus(union ActionData
*data
)
1119 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1121 event_halt_focus_delay();
1123 client_focus(data
->client
.any
.c
);
1126 void action_unfocus (union ActionData
*data
)
1128 if (data
->client
.any
.c
== focus_client
)
1129 focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING
);
1132 void action_iconify(union ActionData
*data
)
1134 client_action_start(data
);
1135 client_iconify(data
->client
.any
.c
, TRUE
, TRUE
);
1136 client_action_end(data
);
1139 void action_focus_order_to_bottom(union ActionData
*data
)
1141 focus_order_to_bottom(data
->client
.any
.c
);
1144 void action_raiselower(union ActionData
*data
)
1146 ObClient
*c
= data
->client
.any
.c
;
1148 gboolean raise
= FALSE
;
1150 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
1151 if (WINDOW_IS_CLIENT(it
->data
)) {
1152 ObClient
*cit
= it
->data
;
1154 if (cit
== c
) break;
1155 if (client_normal(cit
) == client_normal(c
) &&
1156 cit
->layer
== c
->layer
&&
1157 cit
->frame
->visible
&&
1158 !client_search_transient(c
, cit
))
1160 if (RECT_INTERSECTS_RECT(cit
->frame
->area
, c
->frame
->area
)) {
1174 void action_raise(union ActionData
*data
)
1176 client_action_start(data
);
1177 stacking_raise(CLIENT_AS_WINDOW(data
->client
.any
.c
), data
->stacking
.group
);
1178 client_action_end(data
);
1181 void action_unshaderaise(union ActionData
*data
)
1183 if (data
->client
.any
.c
->shaded
)
1184 action_unshade(data
);
1189 void action_shadelower(union ActionData
*data
)
1191 if (data
->client
.any
.c
->shaded
)
1197 void action_lower(union ActionData
*data
)
1199 client_action_start(data
);
1200 stacking_lower(CLIENT_AS_WINDOW(data
->client
.any
.c
), data
->stacking
.group
);
1201 client_action_end(data
);
1204 void action_close(union ActionData
*data
)
1206 client_close(data
->client
.any
.c
);
1209 void action_kill(union ActionData
*data
)
1211 client_kill(data
->client
.any
.c
);
1214 void action_shade(union ActionData
*data
)
1216 client_action_start(data
);
1217 client_shade(data
->client
.any
.c
, TRUE
);
1218 client_action_end(data
);
1221 void action_unshade(union ActionData
*data
)
1223 client_action_start(data
);
1224 client_shade(data
->client
.any
.c
, FALSE
);
1225 client_action_end(data
);
1228 void action_toggle_shade(union ActionData
*data
)
1230 client_action_start(data
);
1231 client_shade(data
->client
.any
.c
, !data
->client
.any
.c
->shaded
);
1232 client_action_end(data
);
1235 void action_toggle_omnipresent(union ActionData
*data
)
1237 client_set_desktop(data
->client
.any
.c
,
1238 data
->client
.any
.c
->desktop
== DESKTOP_ALL
?
1239 screen_desktop
: DESKTOP_ALL
, FALSE
);
1242 void action_move_relative_horz(union ActionData
*data
)
1244 ObClient
*c
= data
->relative
.any
.c
;
1245 client_action_start(data
);
1246 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
);
1247 client_action_end(data
);
1250 void action_move_relative_vert(union ActionData
*data
)
1252 ObClient
*c
= data
->relative
.any
.c
;
1253 client_action_start(data
);
1254 client_move(c
, c
->area
.x
, c
->area
.y
+ data
->relative
.deltax
);
1255 client_action_end(data
);
1258 void action_move_to_center(union ActionData
*data
)
1260 ObClient
*c
= data
->client
.any
.c
;
1262 area
= screen_area_monitor(c
->desktop
, 0);
1263 client_action_start(data
);
1264 client_move(c
, area
->width
/ 2 - c
->area
.width
/ 2,
1265 area
->height
/ 2 - c
->area
.height
/ 2);
1266 client_action_end(data
);
1269 void action_resize_relative_horz(union ActionData
*data
)
1271 ObClient
*c
= data
->relative
.any
.c
;
1272 client_action_start(data
);
1274 c
->area
.width
+ data
->relative
.deltax
* c
->size_inc
.width
,
1276 client_action_end(data
);
1279 void action_resize_relative_vert(union ActionData
*data
)
1281 ObClient
*c
= data
->relative
.any
.c
;
1283 client_action_start(data
);
1284 client_resize(c
, c
->area
.width
, c
->area
.height
+
1285 data
->relative
.deltax
* c
->size_inc
.height
);
1286 client_action_end(data
);
1290 void action_move_relative(union ActionData
*data
)
1292 ObClient
*c
= data
->relative
.any
.c
;
1293 client_action_start(data
);
1294 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
+
1295 data
->relative
.deltay
);
1296 client_action_end(data
);
1299 void action_resize_relative(union ActionData
*data
)
1301 ObClient
*c
= data
->relative
.any
.c
;
1302 client_action_start(data
);
1303 client_move_resize(c
,
1304 c
->area
.x
- data
->relative
.deltaxl
* c
->size_inc
.width
,
1305 c
->area
.y
- data
->relative
.deltayu
* c
->size_inc
.height
,
1306 c
->area
.width
+ data
->relative
.deltax
* c
->size_inc
.width
1307 + data
->relative
.deltaxl
* c
->size_inc
.width
,
1308 c
->area
.height
+ data
->relative
.deltay
* c
->size_inc
.height
1309 + data
->relative
.deltayu
* c
->size_inc
.height
);
1310 client_action_end(data
);
1313 void action_maximize_full(union ActionData
*data
)
1315 client_action_start(data
);
1316 client_maximize(data
->client
.any
.c
, TRUE
, 0, TRUE
);
1317 client_action_end(data
);
1320 void action_unmaximize_full(union ActionData
*data
)
1322 client_action_start(data
);
1323 client_maximize(data
->client
.any
.c
, FALSE
, 0, TRUE
);
1324 client_action_end(data
);
1327 void action_toggle_maximize_full(union ActionData
*data
)
1329 client_action_start(data
);
1330 client_maximize(data
->client
.any
.c
,
1331 !(data
->client
.any
.c
->max_horz
||
1332 data
->client
.any
.c
->max_vert
),
1334 client_action_end(data
);
1337 void action_maximize_horz(union ActionData
*data
)
1339 client_action_start(data
);
1340 client_maximize(data
->client
.any
.c
, TRUE
, 1, TRUE
);
1341 client_action_end(data
);
1344 void action_unmaximize_horz(union ActionData
*data
)
1346 client_action_start(data
);
1347 client_maximize(data
->client
.any
.c
, FALSE
, 1, TRUE
);
1348 client_action_end(data
);
1351 void action_toggle_maximize_horz(union ActionData
*data
)
1353 client_action_start(data
);
1354 client_maximize(data
->client
.any
.c
,
1355 !data
->client
.any
.c
->max_horz
, 1, TRUE
);
1356 client_action_end(data
);
1359 void action_maximize_vert(union ActionData
*data
)
1361 client_action_start(data
);
1362 client_maximize(data
->client
.any
.c
, TRUE
, 2, TRUE
);
1363 client_action_end(data
);
1366 void action_unmaximize_vert(union ActionData
*data
)
1368 client_action_start(data
);
1369 client_maximize(data
->client
.any
.c
, FALSE
, 2, TRUE
);
1370 client_action_end(data
);
1373 void action_toggle_maximize_vert(union ActionData
*data
)
1375 client_action_start(data
);
1376 client_maximize(data
->client
.any
.c
,
1377 !data
->client
.any
.c
->max_vert
, 2, TRUE
);
1378 client_action_end(data
);
1381 void action_toggle_fullscreen(union ActionData
*data
)
1383 client_action_start(data
);
1384 client_fullscreen(data
->client
.any
.c
,
1385 !(data
->client
.any
.c
->fullscreen
), TRUE
);
1386 client_action_end(data
);
1389 void action_send_to_desktop(union ActionData
*data
)
1391 ObClient
*c
= data
->sendto
.any
.c
;
1393 if (!client_normal(c
)) return;
1395 if (data
->sendto
.desk
< screen_num_desktops
||
1396 data
->sendto
.desk
== DESKTOP_ALL
) {
1397 client_set_desktop(c
, data
->sendto
.desk
, data
->sendto
.follow
);
1398 if (data
->sendto
.follow
)
1399 screen_set_desktop(data
->sendto
.desk
);
1403 void action_desktop(union ActionData
*data
)
1405 static guint first
= (unsigned) -1;
1407 if (data
->inter
.any
.interactive
&& first
== (unsigned) -1)
1408 first
= screen_desktop
;
1410 if (!data
->inter
.any
.interactive
||
1411 (!data
->inter
.cancel
&& !data
->inter
.final
))
1413 if (data
->desktop
.desk
< screen_num_desktops
||
1414 data
->desktop
.desk
== DESKTOP_ALL
)
1416 screen_set_desktop(data
->desktop
.desk
);
1417 if (data
->inter
.any
.interactive
)
1418 screen_desktop_popup(data
->desktop
.desk
, TRUE
);
1420 } else if (data
->inter
.cancel
) {
1421 screen_set_desktop(first
);
1424 if (!data
->inter
.any
.interactive
|| data
->inter
.final
) {
1425 screen_desktop_popup(0, FALSE
);
1426 first
= (unsigned) -1;
1430 void action_desktop_dir(union ActionData
*data
)
1434 d
= screen_cycle_desktop(data
->desktopdir
.dir
,
1435 data
->desktopdir
.wrap
,
1436 data
->desktopdir
.linear
,
1437 data
->desktopdir
.inter
.any
.interactive
,
1438 data
->desktopdir
.inter
.final
,
1439 data
->desktopdir
.inter
.cancel
);
1440 if (!data
->sendtodir
.inter
.any
.interactive
||
1441 !data
->sendtodir
.inter
.final
||
1442 data
->sendtodir
.inter
.cancel
)
1444 screen_set_desktop(d
);
1448 void action_send_to_desktop_dir(union ActionData
*data
)
1450 ObClient
*c
= data
->sendtodir
.inter
.any
.c
;
1453 if (!client_normal(c
)) return;
1455 d
= screen_cycle_desktop(data
->sendtodir
.dir
, data
->sendtodir
.wrap
,
1456 data
->sendtodir
.linear
,
1457 data
->sendtodir
.inter
.any
.interactive
,
1458 data
->sendtodir
.inter
.final
,
1459 data
->sendtodir
.inter
.cancel
);
1460 if (!data
->sendtodir
.inter
.any
.interactive
||
1461 !data
->sendtodir
.inter
.final
||
1462 data
->sendtodir
.inter
.cancel
)
1464 client_set_desktop(c
, d
, data
->sendtodir
.follow
);
1465 if (data
->sendtodir
.follow
)
1466 screen_set_desktop(d
);
1470 void action_desktop_last(union ActionData
*data
)
1472 screen_set_desktop(screen_last_desktop
);
1475 void action_toggle_decorations(union ActionData
*data
)
1477 ObClient
*c
= data
->client
.any
.c
;
1479 client_action_start(data
);
1480 client_set_undecorated(c
, !c
->undecorated
);
1481 client_action_end(data
);
1484 static guint32
pick_corner(gint x
, gint y
, gint cx
, gint cy
, gint cw
, gint ch
)
1486 if (config_resize_four_corners
) {
1487 if (x
- cx
> cw
/ 2) {
1488 if (y
- cy
> ch
/ 2)
1489 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1491 return prop_atoms
.net_wm_moveresize_size_topright
;
1493 if (y
- cy
> ch
/ 2)
1494 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1496 return prop_atoms
.net_wm_moveresize_size_topleft
;
1499 if (x
- cx
> cw
* 2 / 3) {
1500 if (y
- cy
> ch
* 2 / 3)
1501 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1502 else if (y
- cy
< ch
/ 3)
1503 return prop_atoms
.net_wm_moveresize_size_topright
;
1505 return prop_atoms
.net_wm_moveresize_size_right
;
1506 } else if (x
- cx
< cw
/ 3) {
1507 if (y
- cy
> ch
* 2 / 3)
1508 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1509 else if (y
- cy
< ch
/ 3)
1510 return prop_atoms
.net_wm_moveresize_size_topleft
;
1512 return prop_atoms
.net_wm_moveresize_size_left
;
1514 if (y
- cy
> ch
* 2 / 3)
1515 return prop_atoms
.net_wm_moveresize_size_bottom
;
1516 else if (y
- cy
< ch
/ 3)
1517 return prop_atoms
.net_wm_moveresize_size_top
;
1519 return prop_atoms
.net_wm_moveresize_move
;
1523 void action_moveresize(union ActionData
*data
)
1525 ObClient
*c
= data
->moveresize
.any
.c
;
1528 if (!client_normal(c
)) return;
1530 if (data
->moveresize
.keyboard
) {
1531 corner
= (data
->moveresize
.move
?
1532 prop_atoms
.net_wm_moveresize_move_keyboard
:
1533 prop_atoms
.net_wm_moveresize_size_keyboard
);
1535 corner
= (data
->moveresize
.move
?
1536 prop_atoms
.net_wm_moveresize_move
:
1537 pick_corner(data
->any
.x
, data
->any
.y
,
1538 c
->frame
->area
.x
, c
->frame
->area
.y
,
1539 /* use the client size because the frame
1540 can be differently sized (shaded
1541 windows) and we want this based on the
1543 c
->area
.width
+ c
->frame
->size
.left
+
1544 c
->frame
->size
.right
,
1545 c
->area
.height
+ c
->frame
->size
.top
+
1546 c
->frame
->size
.bottom
));
1549 moveresize_start(c
, data
->any
.x
, data
->any
.y
, data
->any
.button
, corner
);
1552 void action_reconfigure(union ActionData
*data
)
1557 void action_restart(union ActionData
*data
)
1559 ob_restart_other(data
->execute
.path
);
1562 void action_exit(union ActionData
*data
)
1567 void action_showmenu(union ActionData
*data
)
1569 if (data
->showmenu
.name
) {
1570 menu_show(data
->showmenu
.name
, data
->any
.x
, data
->any
.y
,
1571 data
->showmenu
.any
.c
);
1575 void action_cycle_windows(union ActionData
*data
)
1577 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1579 event_halt_focus_delay();
1581 focus_cycle(data
->cycle
.forward
, data
->cycle
.linear
, data
->any
.interactive
,
1583 data
->cycle
.inter
.final
, data
->cycle
.inter
.cancel
);
1586 void action_directional_focus(union ActionData
*data
)
1588 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1590 event_halt_focus_delay();
1592 focus_directional_cycle(data
->interdiraction
.direction
,
1593 data
->any
.interactive
,
1594 data
->interdiraction
.dialog
,
1595 data
->interdiraction
.inter
.final
,
1596 data
->interdiraction
.inter
.cancel
);
1599 void action_movetoedge(union ActionData
*data
)
1602 ObClient
*c
= data
->diraction
.any
.c
;
1604 x
= c
->frame
->area
.x
;
1605 y
= c
->frame
->area
.y
;
1607 switch(data
->diraction
.direction
) {
1608 case OB_DIRECTION_NORTH
:
1609 y
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
,
1610 data
->diraction
.hang
)
1611 - (data
->diraction
.hang
? c
->frame
->area
.height
: 0);
1613 case OB_DIRECTION_WEST
:
1614 x
= client_directional_edge_search(c
, OB_DIRECTION_WEST
,
1615 data
->diraction
.hang
)
1616 - (data
->diraction
.hang
? c
->frame
->area
.width
: 0);
1618 case OB_DIRECTION_SOUTH
:
1619 y
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
,
1620 data
->diraction
.hang
)
1621 - (data
->diraction
.hang
? 0 : c
->frame
->area
.height
);
1623 case OB_DIRECTION_EAST
:
1624 x
= client_directional_edge_search(c
, OB_DIRECTION_EAST
,
1625 data
->diraction
.hang
)
1626 - (data
->diraction
.hang
? 0 : c
->frame
->area
.width
);
1629 g_assert_not_reached();
1631 frame_frame_gravity(c
->frame
, &x
, &y
);
1632 client_action_start(data
);
1633 client_move(c
, x
, y
);
1634 client_action_end(data
);
1637 void action_growtoedge(union ActionData
*data
)
1639 gint x
, y
, width
, height
, dest
;
1640 ObClient
*c
= data
->diraction
.any
.c
;
1643 //FIXME growtoedge resizes shaded windows to 0 height
1647 a
= screen_area(c
->desktop
);
1648 x
= c
->frame
->area
.x
;
1649 y
= c
->frame
->area
.y
;
1650 width
= c
->frame
->area
.width
;
1651 height
= c
->frame
->area
.height
;
1653 switch(data
->diraction
.direction
) {
1654 case OB_DIRECTION_NORTH
:
1655 dest
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
, FALSE
);
1657 height
= c
->frame
->area
.height
/ 2;
1659 height
= c
->frame
->area
.y
+ c
->frame
->area
.height
- dest
;
1663 case OB_DIRECTION_WEST
:
1664 dest
= client_directional_edge_search(c
, OB_DIRECTION_WEST
, FALSE
);
1666 width
= c
->frame
->area
.width
/ 2;
1668 width
= c
->frame
->area
.x
+ c
->frame
->area
.width
- dest
;
1672 case OB_DIRECTION_SOUTH
:
1673 dest
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
, FALSE
);
1674 if (a
->y
+ a
->height
== y
+ c
->frame
->area
.height
) {
1675 height
= c
->frame
->area
.height
/ 2;
1676 y
= a
->y
+ a
->height
- height
;
1678 height
= dest
- c
->frame
->area
.y
;
1679 y
+= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1680 height
-= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1682 case OB_DIRECTION_EAST
:
1683 dest
= client_directional_edge_search(c
, OB_DIRECTION_EAST
, FALSE
);
1684 if (a
->x
+ a
->width
== x
+ c
->frame
->area
.width
) {
1685 width
= c
->frame
->area
.width
/ 2;
1686 x
= a
->x
+ a
->width
- width
;
1688 width
= dest
- c
->frame
->area
.x
;
1689 x
+= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1690 width
-= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1693 g_assert_not_reached();
1695 frame_frame_gravity(c
->frame
, &x
, &y
);
1696 width
-= c
->frame
->size
.left
+ c
->frame
->size
.right
;
1697 height
-= c
->frame
->size
.top
+ c
->frame
->size
.bottom
;
1698 client_action_start(data
);
1699 client_move_resize(c
, x
, y
, width
, height
);
1700 client_action_end(data
);
1703 void action_send_to_layer(union ActionData
*data
)
1705 client_set_layer(data
->layer
.any
.c
, data
->layer
.layer
);
1708 void action_toggle_layer(union ActionData
*data
)
1710 ObClient
*c
= data
->layer
.any
.c
;
1712 client_action_start(data
);
1713 if (data
->layer
.layer
< 0)
1714 client_set_layer(c
, c
->below
? 0 : -1);
1715 else if (data
->layer
.layer
> 0)
1716 client_set_layer(c
, c
->above
? 0 : 1);
1717 client_action_end(data
);
1720 void action_toggle_dockautohide(union ActionData
*data
)
1722 config_dock_hide
= !config_dock_hide
;
1726 void action_toggle_show_desktop(union ActionData
*data
)
1728 screen_show_desktop(!screen_showing_desktop
);
1731 void action_show_desktop(union ActionData
*data
)
1733 screen_show_desktop(TRUE
);
1736 void action_unshow_desktop(union ActionData
*data
)
1738 screen_show_desktop(FALSE
);