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_curtime
);
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 /* similar to the openbox dock for dockapps, don't let user actions give
1115 focus to 3rd-party docks (panels) either (unless they ask for it
1117 if (data
->client
.any
.c
->type
!= OB_CLIENT_TYPE_DOCK
) {
1118 /* if using focus_delay, stop the timer now so that focus doesn't go
1120 event_halt_focus_delay();
1122 client_activate(data
->activate
.any
.c
, data
->activate
.here
, TRUE
);
1126 void action_focus(union ActionData
*data
)
1128 /* similar to the openbox dock for dockapps, don't let user actions give
1129 focus to 3rd-party docks (panels) either (unless they ask for it
1131 if (data
->client
.any
.c
->type
!= OB_CLIENT_TYPE_DOCK
) {
1132 /* if using focus_delay, stop the timer now so that focus doesn't go
1134 event_halt_focus_delay();
1136 client_focus(data
->client
.any
.c
);
1140 void action_unfocus (union ActionData
*data
)
1142 if (data
->client
.any
.c
== focus_client
)
1143 focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING
);
1146 void action_iconify(union ActionData
*data
)
1148 client_action_start(data
);
1149 client_iconify(data
->client
.any
.c
, TRUE
, TRUE
);
1150 client_action_end(data
);
1153 void action_focus_order_to_bottom(union ActionData
*data
)
1155 focus_order_to_bottom(data
->client
.any
.c
);
1158 void action_raiselower(union ActionData
*data
)
1160 ObClient
*c
= data
->client
.any
.c
;
1162 gboolean raise
= FALSE
;
1164 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
1165 if (WINDOW_IS_CLIENT(it
->data
)) {
1166 ObClient
*cit
= it
->data
;
1168 if (cit
== c
) break;
1169 if (client_normal(cit
) == client_normal(c
) &&
1170 cit
->layer
== c
->layer
&&
1171 cit
->frame
->visible
&&
1172 !client_search_transient(c
, cit
))
1174 if (RECT_INTERSECTS_RECT(cit
->frame
->area
, c
->frame
->area
)) {
1188 void action_raise(union ActionData
*data
)
1190 client_action_start(data
);
1191 stacking_raise(CLIENT_AS_WINDOW(data
->client
.any
.c
), data
->stacking
.group
);
1192 client_action_end(data
);
1195 void action_unshaderaise(union ActionData
*data
)
1197 if (data
->client
.any
.c
->shaded
)
1198 action_unshade(data
);
1203 void action_shadelower(union ActionData
*data
)
1205 if (data
->client
.any
.c
->shaded
)
1211 void action_lower(union ActionData
*data
)
1213 client_action_start(data
);
1214 stacking_lower(CLIENT_AS_WINDOW(data
->client
.any
.c
), data
->stacking
.group
);
1215 client_action_end(data
);
1218 void action_close(union ActionData
*data
)
1220 client_close(data
->client
.any
.c
);
1223 void action_kill(union ActionData
*data
)
1225 client_kill(data
->client
.any
.c
);
1228 void action_shade(union ActionData
*data
)
1230 client_action_start(data
);
1231 client_shade(data
->client
.any
.c
, TRUE
);
1232 client_action_end(data
);
1235 void action_unshade(union ActionData
*data
)
1237 client_action_start(data
);
1238 client_shade(data
->client
.any
.c
, FALSE
);
1239 client_action_end(data
);
1242 void action_toggle_shade(union ActionData
*data
)
1244 client_action_start(data
);
1245 client_shade(data
->client
.any
.c
, !data
->client
.any
.c
->shaded
);
1246 client_action_end(data
);
1249 void action_toggle_omnipresent(union ActionData
*data
)
1251 client_set_desktop(data
->client
.any
.c
,
1252 data
->client
.any
.c
->desktop
== DESKTOP_ALL
?
1253 screen_desktop
: DESKTOP_ALL
, FALSE
);
1256 void action_move_relative_horz(union ActionData
*data
)
1258 ObClient
*c
= data
->relative
.any
.c
;
1259 client_action_start(data
);
1260 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
);
1261 client_action_end(data
);
1264 void action_move_relative_vert(union ActionData
*data
)
1266 ObClient
*c
= data
->relative
.any
.c
;
1267 client_action_start(data
);
1268 client_move(c
, c
->area
.x
, c
->area
.y
+ data
->relative
.deltax
);
1269 client_action_end(data
);
1272 void action_move_to_center(union ActionData
*data
)
1274 ObClient
*c
= data
->client
.any
.c
;
1276 area
= screen_area_monitor(c
->desktop
, 0);
1277 client_action_start(data
);
1278 client_move(c
, area
->width
/ 2 - c
->area
.width
/ 2,
1279 area
->height
/ 2 - c
->area
.height
/ 2);
1280 client_action_end(data
);
1283 void action_resize_relative_horz(union ActionData
*data
)
1285 ObClient
*c
= data
->relative
.any
.c
;
1286 client_action_start(data
);
1288 c
->area
.width
+ data
->relative
.deltax
* c
->size_inc
.width
,
1290 client_action_end(data
);
1293 void action_resize_relative_vert(union ActionData
*data
)
1295 ObClient
*c
= data
->relative
.any
.c
;
1297 client_action_start(data
);
1298 client_resize(c
, c
->area
.width
, c
->area
.height
+
1299 data
->relative
.deltax
* c
->size_inc
.height
);
1300 client_action_end(data
);
1304 void action_move_relative(union ActionData
*data
)
1306 ObClient
*c
= data
->relative
.any
.c
;
1307 client_action_start(data
);
1308 client_move(c
, c
->area
.x
+ data
->relative
.deltax
, c
->area
.y
+
1309 data
->relative
.deltay
);
1310 client_action_end(data
);
1313 void action_resize_relative(union ActionData
*data
)
1315 ObClient
*c
= data
->relative
.any
.c
;
1316 client_action_start(data
);
1317 client_move_resize(c
,
1318 c
->area
.x
- data
->relative
.deltaxl
* c
->size_inc
.width
,
1319 c
->area
.y
- data
->relative
.deltayu
* c
->size_inc
.height
,
1320 c
->area
.width
+ data
->relative
.deltax
* c
->size_inc
.width
1321 + data
->relative
.deltaxl
* c
->size_inc
.width
,
1322 c
->area
.height
+ data
->relative
.deltay
* c
->size_inc
.height
1323 + data
->relative
.deltayu
* c
->size_inc
.height
);
1324 client_action_end(data
);
1327 void action_maximize_full(union ActionData
*data
)
1329 client_action_start(data
);
1330 client_maximize(data
->client
.any
.c
, TRUE
, 0, TRUE
);
1331 client_action_end(data
);
1334 void action_unmaximize_full(union ActionData
*data
)
1336 client_action_start(data
);
1337 client_maximize(data
->client
.any
.c
, FALSE
, 0, TRUE
);
1338 client_action_end(data
);
1341 void action_toggle_maximize_full(union ActionData
*data
)
1343 client_action_start(data
);
1344 client_maximize(data
->client
.any
.c
,
1345 !(data
->client
.any
.c
->max_horz
||
1346 data
->client
.any
.c
->max_vert
),
1348 client_action_end(data
);
1351 void action_maximize_horz(union ActionData
*data
)
1353 client_action_start(data
);
1354 client_maximize(data
->client
.any
.c
, TRUE
, 1, TRUE
);
1355 client_action_end(data
);
1358 void action_unmaximize_horz(union ActionData
*data
)
1360 client_action_start(data
);
1361 client_maximize(data
->client
.any
.c
, FALSE
, 1, TRUE
);
1362 client_action_end(data
);
1365 void action_toggle_maximize_horz(union ActionData
*data
)
1367 client_action_start(data
);
1368 client_maximize(data
->client
.any
.c
,
1369 !data
->client
.any
.c
->max_horz
, 1, TRUE
);
1370 client_action_end(data
);
1373 void action_maximize_vert(union ActionData
*data
)
1375 client_action_start(data
);
1376 client_maximize(data
->client
.any
.c
, TRUE
, 2, TRUE
);
1377 client_action_end(data
);
1380 void action_unmaximize_vert(union ActionData
*data
)
1382 client_action_start(data
);
1383 client_maximize(data
->client
.any
.c
, FALSE
, 2, TRUE
);
1384 client_action_end(data
);
1387 void action_toggle_maximize_vert(union ActionData
*data
)
1389 client_action_start(data
);
1390 client_maximize(data
->client
.any
.c
,
1391 !data
->client
.any
.c
->max_vert
, 2, TRUE
);
1392 client_action_end(data
);
1395 void action_toggle_fullscreen(union ActionData
*data
)
1397 client_action_start(data
);
1398 client_fullscreen(data
->client
.any
.c
,
1399 !(data
->client
.any
.c
->fullscreen
), TRUE
);
1400 client_action_end(data
);
1403 void action_send_to_desktop(union ActionData
*data
)
1405 ObClient
*c
= data
->sendto
.any
.c
;
1407 if (!client_normal(c
)) return;
1409 if (data
->sendto
.desk
< screen_num_desktops
||
1410 data
->sendto
.desk
== DESKTOP_ALL
) {
1411 client_set_desktop(c
, data
->sendto
.desk
, data
->sendto
.follow
);
1412 if (data
->sendto
.follow
)
1413 screen_set_desktop(data
->sendto
.desk
);
1417 void action_desktop(union ActionData
*data
)
1419 static guint first
= (unsigned) -1;
1421 if (data
->inter
.any
.interactive
&& first
== (unsigned) -1)
1422 first
= screen_desktop
;
1424 if (!data
->inter
.any
.interactive
||
1425 (!data
->inter
.cancel
&& !data
->inter
.final
))
1427 if (data
->desktop
.desk
< screen_num_desktops
||
1428 data
->desktop
.desk
== DESKTOP_ALL
)
1430 screen_set_desktop(data
->desktop
.desk
);
1431 if (data
->inter
.any
.interactive
)
1432 screen_desktop_popup(data
->desktop
.desk
, TRUE
);
1434 } else if (data
->inter
.cancel
) {
1435 screen_set_desktop(first
);
1438 if (!data
->inter
.any
.interactive
|| data
->inter
.final
) {
1439 screen_desktop_popup(0, FALSE
);
1440 first
= (unsigned) -1;
1444 void action_desktop_dir(union ActionData
*data
)
1448 d
= screen_cycle_desktop(data
->desktopdir
.dir
,
1449 data
->desktopdir
.wrap
,
1450 data
->desktopdir
.linear
,
1451 data
->desktopdir
.inter
.any
.interactive
,
1452 data
->desktopdir
.inter
.final
,
1453 data
->desktopdir
.inter
.cancel
);
1454 if (!data
->sendtodir
.inter
.any
.interactive
||
1455 !data
->sendtodir
.inter
.final
||
1456 data
->sendtodir
.inter
.cancel
)
1458 screen_set_desktop(d
);
1462 void action_send_to_desktop_dir(union ActionData
*data
)
1464 ObClient
*c
= data
->sendtodir
.inter
.any
.c
;
1467 if (!client_normal(c
)) return;
1469 d
= screen_cycle_desktop(data
->sendtodir
.dir
, data
->sendtodir
.wrap
,
1470 data
->sendtodir
.linear
,
1471 data
->sendtodir
.inter
.any
.interactive
,
1472 data
->sendtodir
.inter
.final
,
1473 data
->sendtodir
.inter
.cancel
);
1474 if (!data
->sendtodir
.inter
.any
.interactive
||
1475 !data
->sendtodir
.inter
.final
||
1476 data
->sendtodir
.inter
.cancel
)
1478 client_set_desktop(c
, d
, data
->sendtodir
.follow
);
1479 if (data
->sendtodir
.follow
)
1480 screen_set_desktop(d
);
1484 void action_desktop_last(union ActionData
*data
)
1486 screen_set_desktop(screen_last_desktop
);
1489 void action_toggle_decorations(union ActionData
*data
)
1491 ObClient
*c
= data
->client
.any
.c
;
1493 client_action_start(data
);
1494 client_set_undecorated(c
, !c
->undecorated
);
1495 client_action_end(data
);
1498 static guint32
pick_corner(gint x
, gint y
, gint cx
, gint cy
, gint cw
, gint ch
)
1500 if (config_resize_four_corners
) {
1501 if (x
- cx
> cw
/ 2) {
1502 if (y
- cy
> ch
/ 2)
1503 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1505 return prop_atoms
.net_wm_moveresize_size_topright
;
1507 if (y
- cy
> ch
/ 2)
1508 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1510 return prop_atoms
.net_wm_moveresize_size_topleft
;
1513 if (x
- cx
> cw
* 2 / 3) {
1514 if (y
- cy
> ch
* 2 / 3)
1515 return prop_atoms
.net_wm_moveresize_size_bottomright
;
1516 else if (y
- cy
< ch
/ 3)
1517 return prop_atoms
.net_wm_moveresize_size_topright
;
1519 return prop_atoms
.net_wm_moveresize_size_right
;
1520 } else if (x
- cx
< cw
/ 3) {
1521 if (y
- cy
> ch
* 2 / 3)
1522 return prop_atoms
.net_wm_moveresize_size_bottomleft
;
1523 else if (y
- cy
< ch
/ 3)
1524 return prop_atoms
.net_wm_moveresize_size_topleft
;
1526 return prop_atoms
.net_wm_moveresize_size_left
;
1528 if (y
- cy
> ch
* 2 / 3)
1529 return prop_atoms
.net_wm_moveresize_size_bottom
;
1530 else if (y
- cy
< ch
/ 3)
1531 return prop_atoms
.net_wm_moveresize_size_top
;
1533 return prop_atoms
.net_wm_moveresize_move
;
1537 void action_moveresize(union ActionData
*data
)
1539 ObClient
*c
= data
->moveresize
.any
.c
;
1542 if (!client_normal(c
)) return;
1544 if (data
->moveresize
.keyboard
) {
1545 corner
= (data
->moveresize
.move
?
1546 prop_atoms
.net_wm_moveresize_move_keyboard
:
1547 prop_atoms
.net_wm_moveresize_size_keyboard
);
1549 corner
= (data
->moveresize
.move
?
1550 prop_atoms
.net_wm_moveresize_move
:
1551 pick_corner(data
->any
.x
, data
->any
.y
,
1552 c
->frame
->area
.x
, c
->frame
->area
.y
,
1553 /* use the client size because the frame
1554 can be differently sized (shaded
1555 windows) and we want this based on the
1557 c
->area
.width
+ c
->frame
->size
.left
+
1558 c
->frame
->size
.right
,
1559 c
->area
.height
+ c
->frame
->size
.top
+
1560 c
->frame
->size
.bottom
));
1563 moveresize_start(c
, data
->any
.x
, data
->any
.y
, data
->any
.button
, corner
);
1566 void action_reconfigure(union ActionData
*data
)
1571 void action_restart(union ActionData
*data
)
1573 ob_restart_other(data
->execute
.path
);
1576 void action_exit(union ActionData
*data
)
1581 void action_showmenu(union ActionData
*data
)
1583 if (data
->showmenu
.name
) {
1584 menu_show(data
->showmenu
.name
, data
->any
.x
, data
->any
.y
,
1585 data
->showmenu
.any
.c
);
1589 void action_cycle_windows(union ActionData
*data
)
1591 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1593 event_halt_focus_delay();
1595 focus_cycle(data
->cycle
.forward
, data
->cycle
.linear
, data
->any
.interactive
,
1597 data
->cycle
.inter
.final
, data
->cycle
.inter
.cancel
);
1600 void action_directional_focus(union ActionData
*data
)
1602 /* if using focus_delay, stop the timer now so that focus doesn't go moving
1604 event_halt_focus_delay();
1606 focus_directional_cycle(data
->interdiraction
.direction
,
1607 data
->any
.interactive
,
1608 data
->interdiraction
.dialog
,
1609 data
->interdiraction
.inter
.final
,
1610 data
->interdiraction
.inter
.cancel
);
1613 void action_movetoedge(union ActionData
*data
)
1616 ObClient
*c
= data
->diraction
.any
.c
;
1618 x
= c
->frame
->area
.x
;
1619 y
= c
->frame
->area
.y
;
1621 switch(data
->diraction
.direction
) {
1622 case OB_DIRECTION_NORTH
:
1623 y
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
,
1624 data
->diraction
.hang
)
1625 - (data
->diraction
.hang
? c
->frame
->area
.height
: 0);
1627 case OB_DIRECTION_WEST
:
1628 x
= client_directional_edge_search(c
, OB_DIRECTION_WEST
,
1629 data
->diraction
.hang
)
1630 - (data
->diraction
.hang
? c
->frame
->area
.width
: 0);
1632 case OB_DIRECTION_SOUTH
:
1633 y
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
,
1634 data
->diraction
.hang
)
1635 - (data
->diraction
.hang
? 0 : c
->frame
->area
.height
);
1637 case OB_DIRECTION_EAST
:
1638 x
= client_directional_edge_search(c
, OB_DIRECTION_EAST
,
1639 data
->diraction
.hang
)
1640 - (data
->diraction
.hang
? 0 : c
->frame
->area
.width
);
1643 g_assert_not_reached();
1645 frame_frame_gravity(c
->frame
, &x
, &y
);
1646 client_action_start(data
);
1647 client_move(c
, x
, y
);
1648 client_action_end(data
);
1651 void action_growtoedge(union ActionData
*data
)
1653 gint x
, y
, width
, height
, dest
;
1654 ObClient
*c
= data
->diraction
.any
.c
;
1657 //FIXME growtoedge resizes shaded windows to 0 height
1661 a
= screen_area(c
->desktop
);
1662 x
= c
->frame
->area
.x
;
1663 y
= c
->frame
->area
.y
;
1664 width
= c
->frame
->area
.width
;
1665 height
= c
->frame
->area
.height
;
1667 switch(data
->diraction
.direction
) {
1668 case OB_DIRECTION_NORTH
:
1669 dest
= client_directional_edge_search(c
, OB_DIRECTION_NORTH
, FALSE
);
1671 height
= c
->frame
->area
.height
/ 2;
1673 height
= c
->frame
->area
.y
+ c
->frame
->area
.height
- dest
;
1677 case OB_DIRECTION_WEST
:
1678 dest
= client_directional_edge_search(c
, OB_DIRECTION_WEST
, FALSE
);
1680 width
= c
->frame
->area
.width
/ 2;
1682 width
= c
->frame
->area
.x
+ c
->frame
->area
.width
- dest
;
1686 case OB_DIRECTION_SOUTH
:
1687 dest
= client_directional_edge_search(c
, OB_DIRECTION_SOUTH
, FALSE
);
1688 if (a
->y
+ a
->height
== y
+ c
->frame
->area
.height
) {
1689 height
= c
->frame
->area
.height
/ 2;
1690 y
= a
->y
+ a
->height
- height
;
1692 height
= dest
- c
->frame
->area
.y
;
1693 y
+= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1694 height
-= (height
- c
->frame
->area
.height
) % c
->size_inc
.height
;
1696 case OB_DIRECTION_EAST
:
1697 dest
= client_directional_edge_search(c
, OB_DIRECTION_EAST
, FALSE
);
1698 if (a
->x
+ a
->width
== x
+ c
->frame
->area
.width
) {
1699 width
= c
->frame
->area
.width
/ 2;
1700 x
= a
->x
+ a
->width
- width
;
1702 width
= dest
- c
->frame
->area
.x
;
1703 x
+= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1704 width
-= (width
- c
->frame
->area
.width
) % c
->size_inc
.width
;
1707 g_assert_not_reached();
1709 frame_frame_gravity(c
->frame
, &x
, &y
);
1710 width
-= c
->frame
->size
.left
+ c
->frame
->size
.right
;
1711 height
-= c
->frame
->size
.top
+ c
->frame
->size
.bottom
;
1712 client_action_start(data
);
1713 client_move_resize(c
, x
, y
, width
, height
);
1714 client_action_end(data
);
1717 void action_send_to_layer(union ActionData
*data
)
1719 client_set_layer(data
->layer
.any
.c
, data
->layer
.layer
);
1722 void action_toggle_layer(union ActionData
*data
)
1724 ObClient
*c
= data
->layer
.any
.c
;
1726 client_action_start(data
);
1727 if (data
->layer
.layer
< 0)
1728 client_set_layer(c
, c
->below
? 0 : -1);
1729 else if (data
->layer
.layer
> 0)
1730 client_set_layer(c
, c
->above
? 0 : 1);
1731 client_action_end(data
);
1734 void action_toggle_dockautohide(union ActionData
*data
)
1736 config_dock_hide
= !config_dock_hide
;
1740 void action_toggle_show_desktop(union ActionData
*data
)
1742 screen_show_desktop(!screen_showing_desktop
);
1745 void action_show_desktop(union ActionData
*data
)
1747 screen_show_desktop(TRUE
);
1750 void action_unshow_desktop(union ActionData
*data
)
1752 screen_show_desktop(FALSE
);