add moveto/fromedge actions
[dana/openbox.git] / openbox / action.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    action.c for the Openbox window manager
4    Copyright (c) 2006        Mikael Magnusson
5    Copyright (c) 2003-2007   Dana Jansens
6
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.
11
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.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "debug.h"
21 #include "client.h"
22 #include "focus.h"
23 #include "focus_cycle.h"
24 #include "moveresize.h"
25 #include "menu.h"
26 #include "prop.h"
27 #include "stacking.h"
28 #include "screen.h"
29 #include "action.h"
30 #include "openbox.h"
31 #include "grab.h"
32 #include "keyboard.h"
33 #include "event.h"
34 #include "dock.h"
35 #include "config.h"
36 #include "mainloop.h"
37 #include "startupnotify.h"
38 #include "gettext.h"
39
40 #include <glib.h>
41
42
43
44
45 void setup_action_growtoedge_north(ObAction **a, ObUserAction uact)
46 {
47     (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
48     (*a)->data.diraction.direction = OB_DIRECTION_NORTH;
49 }
50
51 void setup_action_growtoedge_south(ObAction **a, ObUserAction uact)
52 {
53     (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
54     (*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
55 }
56
57 void setup_action_growtoedge_east(ObAction **a, ObUserAction uact)
58 {
59     (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
60     (*a)->data.diraction.direction = OB_DIRECTION_EAST;
61 }
62
63 void setup_action_growtoedge_west(ObAction **a, ObUserAction uact)
64 {
65     (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
66     (*a)->data.diraction.direction = OB_DIRECTION_WEST;
67 }
68
69 void setup_action_top_layer(ObAction **a, ObUserAction uact)
70 {
71     (*a)->data.layer.any.client_action = OB_CLIENT_ACTION_ALWAYS;
72     (*a)->data.layer.layer = 1;
73 }
74
75 void setup_action_normal_layer(ObAction **a, ObUserAction uact)
76 {
77     (*a)->data.layer.any.client_action = OB_CLIENT_ACTION_ALWAYS;
78     (*a)->data.layer.layer = 0;
79 }
80
81 void setup_action_bottom_layer(ObAction **a, ObUserAction uact)
82 {
83     (*a)->data.layer.any.client_action = OB_CLIENT_ACTION_ALWAYS;
84     (*a)->data.layer.layer = -1;
85 }
86
87 void setup_client_action(ObAction **a, ObUserAction uact)
88 {
89     (*a)->data.any.client_action = OB_CLIENT_ACTION_ALWAYS;
90 }
91
92 ActionString actionstrings[] =
93 {
94     {
95         "shadelower",
96         action_shadelower,
97         setup_client_action
98     },
99     {
100         "unshaderaise",
101         action_unshaderaise,
102         setup_client_action
103     },
104     {
105         "growtoedgenorth",
106         action_growtoedge,
107         setup_action_growtoedge_north
108     },
109     {
110         "growtoedgesouth",
111         action_growtoedge,
112         setup_action_growtoedge_south
113     },
114     {
115         "growtoedgewest",
116         action_growtoedge,
117         setup_action_growtoedge_west
118     },
119     {
120         "growtoedgeeast",
121         action_growtoedge,
122         setup_action_growtoedge_east
123     },
124     {
125         NULL,
126         NULL,
127         NULL
128     }
129 };
130
131 void action_unshaderaise(union ActionData *data)
132 {
133     if (data->client.any.c->shaded)
134         action_unshade(data);
135     else
136         action_raise(data);
137 }
138
139 void action_shadelower(union ActionData *data)
140 {
141     if (data->client.any.c->shaded)
142         action_lower(data);
143     else
144         action_shade(data);
145 }
146
147 void action_growtoedge(union ActionData *data)
148 {
149     gint x, y, width, height, dest;
150     ObClient *c = data->diraction.any.c;
151     Rect *a;
152
153     a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area);
154     x = c->frame->area.x;
155     y = c->frame->area.y;
156     /* get the unshaded frame's dimensions..if it is shaded */
157     width = c->area.width + c->frame->size.left + c->frame->size.right;
158     height = c->area.height + c->frame->size.top + c->frame->size.bottom;
159
160     switch(data->diraction.direction) {
161     case OB_DIRECTION_NORTH:
162         if (c->shaded) break; /* don't allow vertical resize if shaded */
163
164         dest = client_directional_edge_search(c, OB_DIRECTION_NORTH, FALSE);
165         if (a->y == y)
166             height = height / 2;
167         else {
168             height = c->frame->area.y + height - dest;
169             y = dest;
170         }
171         break;
172     case OB_DIRECTION_WEST:
173         dest = client_directional_edge_search(c, OB_DIRECTION_WEST, FALSE);
174         if (a->x == x)
175             width = width / 2;
176         else {
177             width = c->frame->area.x + width - dest;
178             x = dest;
179         }
180         break;
181     case OB_DIRECTION_SOUTH:
182         if (c->shaded) break; /* don't allow vertical resize if shaded */
183
184         dest = client_directional_edge_search(c, OB_DIRECTION_SOUTH, FALSE);
185         if (a->y + a->height == y + c->frame->area.height) {
186             height = c->frame->area.height / 2;
187             y = a->y + a->height - height;
188         } else
189             height = dest - c->frame->area.y;
190         y += (height - c->frame->area.height) % c->size_inc.height;
191         height -= (height - c->frame->area.height) % c->size_inc.height;
192         break;
193     case OB_DIRECTION_EAST:
194         dest = client_directional_edge_search(c, OB_DIRECTION_EAST, FALSE);
195         if (a->x + a->width == x + c->frame->area.width) {
196             width = c->frame->area.width / 2;
197             x = a->x + a->width - width;
198         } else
199             width = dest - c->frame->area.x;
200         x += (width - c->frame->area.width) % c->size_inc.width;
201         width -= (width - c->frame->area.width) % c->size_inc.width;
202         break;
203     default:
204         g_assert_not_reached();
205     }
206     width -= c->frame->size.left + c->frame->size.right;
207     height -= c->frame->size.top + c->frame->size.bottom;
208     frame_frame_gravity(c->frame, &x, &y, width, height);
209     client_action_start(data);
210     client_move_resize(c, x, y, width, height);
211     client_action_end(data, FALSE);
212     g_free(a);
213 }