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