if windows on screen are going to be moved, then do the ReplayPointer before that...
[mikachu/openbox.git] / openbox / actions / resize.c
1 #include "openbox/actions.h"
2 #include "openbox/prop.h"
3 #include "openbox/moveresize.h"
4 #include "openbox/client.h"
5 #include "openbox/frame.h"
6
7 typedef struct {
8     gboolean corner_specified;
9     guint32 corner;
10 } Options;
11
12 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
13 static void     free_func(gpointer options);
14 static gboolean run_func(ObActionsData *data, gpointer options);
15
16 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
17                            gboolean shaded);
18
19 void action_resize_startup(void)
20 {
21     actions_register("Resize",
22                      setup_func,
23                      free_func,
24                      run_func,
25                      NULL, NULL);
26 }
27
28 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
29 {
30     xmlNodePtr n;
31     Options *o;
32
33     o = g_new0(Options, 1);
34
35     if ((n = parse_find_node("edge", node))) {
36         gchar *s = parse_string(doc, n);
37
38         o->corner_specified = TRUE;
39         if (!g_ascii_strcasecmp(s, "top"))
40             o->corner = prop_atoms.net_wm_moveresize_size_top;
41         else if (!g_ascii_strcasecmp(s, "bottom"))
42             o->corner = prop_atoms.net_wm_moveresize_size_bottom;
43         else if (!g_ascii_strcasecmp(s, "left"))
44             o->corner = prop_atoms.net_wm_moveresize_size_left;
45         else if (!g_ascii_strcasecmp(s, "right"))
46             o->corner = prop_atoms.net_wm_moveresize_size_right;
47         else if (!g_ascii_strcasecmp(s, "topleft"))
48             o->corner = prop_atoms.net_wm_moveresize_size_topleft;
49         else if (!g_ascii_strcasecmp(s, "topright"))
50             o->corner = prop_atoms.net_wm_moveresize_size_topright;
51         else if (!g_ascii_strcasecmp(s, "bottomleft"))
52             o->corner = prop_atoms.net_wm_moveresize_size_bottomleft;
53         else if (!g_ascii_strcasecmp(s, "bottomright"))
54             o->corner = prop_atoms.net_wm_moveresize_size_bottomright;
55         else
56             o->corner_specified = FALSE;
57
58         g_free(s);
59     }
60     return o;
61 }
62
63 static void free_func(gpointer options)
64 {
65     Options *o = options;
66
67     g_free(o);
68 }
69
70 /* Always return FALSE because its not interactive */
71 static gboolean run_func(ObActionsData *data, gpointer options)
72 {
73     Options *o = options;
74
75     if (data->client) {
76         ObClient *c = data->client;
77         guint32 corner;
78
79         if (!data->button)
80             corner = prop_atoms.net_wm_moveresize_size_keyboard;
81         else if (o->corner_specified)
82             corner = o->corner; /* it was specified in the binding */
83         else
84             corner = pick_corner(data->x, data->y,
85                                  c->frame->area.x, c->frame->area.y,
86                                  /* use the client size because the frame
87                                     can be differently sized (shaded
88                                     windows) and we want this based on the
89                                     clients size */
90                                  c->area.width + c->frame->size.left +
91                                  c->frame->size.right,
92                                  c->area.height + c->frame->size.top +
93                                  c->frame->size.bottom, c->shaded);
94
95         moveresize_start(c, data->x, data->y, data->button, corner);
96     }
97
98     return FALSE;
99 }
100
101 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
102                            gboolean shaded)
103 {
104     /* let's make x and y client relative instead of screen relative */
105     x = x - cx;
106     y = ch - (y - cy); /* y is inverted, 0 is at the bottom of the window */
107
108 #define X x*ch/cw
109 #define A -4*X + 7*ch/3
110 #define B  4*X -15*ch/9
111 #define C -X/4 + 2*ch/3
112 #define D  X/4 + 5*ch/12
113 #define E  X/4 +   ch/3
114 #define F -X/4 + 7*ch/12
115 #define G  4*X - 4*ch/3
116 #define H -4*X + 8*ch/3
117 #define a (y > 5*ch/9)
118 #define b (x < 4*cw/9)
119 #define c (x > 5*cw/9)
120 #define d (y < 4*ch/9)
121
122     /*
123       Each of these defines (except X which is just there for fun), represents
124       the equation of a line. The lines they represent are shown in the diagram
125       below. Checking y against these lines, we are able to choose a region
126       of the window as shown.
127
128       +---------------------A-------|-------|-------B---------------------+
129       |                     |A                     B|                     |
130       |                     |A      |       |      B|                     |
131       |                     | A                   B |                     |
132       |                     | A     |       |     B |                     |
133       |                     |  A                 B  |                     |
134       |                     |  A    |       |    B  |                     |
135       |        northwest    |   A     north     B   |   northeast         |
136       |                     |   A   |       |   B   |                     |
137       |                     |    A             B    |                     |
138       C---------------------+----A--+-------+--B----+---------------------D
139       |CCCCCCC              |     A           B     |              DDDDDDD|
140       |       CCCCCCCC      |     A |       | B     |      DDDDDDDD       |
141       |               CCCCCCC      A         B      DDDDDDD               |
142       - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - - -
143       |                     |       b       c       |                     | sh
144       |             west    |       b  move c       |   east              | ad
145       |                     |       b       c       |                     | ed
146       - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - -  -
147       |               EEEEEEE      G         H      FFFFFFF               |
148       |       EEEEEEEE      |     G |       | H     |      FFFFFFFF       |
149       |EEEEEEE              |     G           H     |              FFFFFFF|
150       E---------------------+----G--+-------+--H----+---------------------F
151       |                     |    G             H    |                     |
152       |                     |   G   |       |   H   |                     |
153       |        southwest    |   G     south     H   |   southeast         |
154       |                     |  G    |       |    H  |                     |
155       |                     |  G                 H  |                     |
156       |                     | G     |       |     H |                     |
157       |                     | G                   H |                     |
158       |                     |G      |       |      H|                     |
159       |                     |G                     H|                     |
160       +---------------------G-------|-------|-------H---------------------+
161     */
162
163     if (shaded) {
164         /* for shaded windows, you can only resize west/east and move */
165         if (b)
166             return prop_atoms.net_wm_moveresize_size_left;
167         if (c)
168             return prop_atoms.net_wm_moveresize_size_right;
169         return prop_atoms.net_wm_moveresize_move;
170     }
171
172     if (y < A && y >= C)
173         return prop_atoms.net_wm_moveresize_size_topleft;
174     else if (y >= A && y >= B && a)
175         return prop_atoms.net_wm_moveresize_size_top;
176     else if (y < B && y >= D)
177         return prop_atoms.net_wm_moveresize_size_topright;
178     else if (y < C && y >= E && b)
179         return prop_atoms.net_wm_moveresize_size_left;
180     else if (y < D && y >= F && c)
181         return prop_atoms.net_wm_moveresize_size_right;
182     else if (y < E && y >= G)
183         return prop_atoms.net_wm_moveresize_size_bottomleft;
184     else if (y < G && y < H && d)
185         return prop_atoms.net_wm_moveresize_size_bottom;
186     else if (y >= H && y < F)
187         return prop_atoms.net_wm_moveresize_size_bottomright;
188     else
189         return prop_atoms.net_wm_moveresize_move;
190
191 #undef X
192 #undef A
193 #undef B
194 #undef C
195 #undef D
196 #undef E
197 #undef F
198 #undef G
199 #undef H
200 #undef a
201 #undef b
202 #undef c
203 #undef d
204 }