1 #include "openbox/actions.h"
2 #include "openbox/moveresize.h"
3 #include "openbox/client.h"
4 #include "openbox/engine_interface.h"
6 #include "openbox/openbox.h"
11 gboolean corner_specified;
15 static gpointer setup_func(xmlNodePtr node);
16 static gboolean run_func(ObActionsData *data, gpointer options);
18 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
21 void action_resize_startup(void)
23 actions_register("Resize", setup_func, g_free, run_func, NULL, NULL);
26 static gpointer setup_func(xmlNodePtr node)
31 o = g_new0(Options, 1);
33 if ((n = obt_parse_find_node(node, "edge"))) {
34 gchar *s = obt_parse_node_string(n);
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);
54 o->corner_specified = FALSE;
61 /* Always return FALSE because its not interactive */
62 static gboolean run_func(ObActionsData *data, gpointer options)
67 ObClient *c = data->client;
70 Strut c_size = render_plugin->frame_get_size(c->frame);
71 Rect c_area = render_plugin->frame_get_window_area(c->frame);
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 */
77 corner = pick_corner(data->x, data->y,
79 /* use the client size because the frame
80 can be differently sized (shaded
81 windows) and we want this based on the
83 c->area.width + c_size.left +
85 c->area.height + c_size.top +
86 c_size.bottom, c->shaded);
88 moveresize_start(c, data->x, data->y, data->button, corner);
94 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
97 /* let's make x and y client relative instead of screen relative */
99 y = ch - (y - cy); /* y is inverted, 0 is at the bottom of the window */
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
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)
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.
121 +---------------------A-------|-------|-------B---------------------+
128 | northwest | A north B | northeast |
131 C---------------------+----A--+-------+--B----+---------------------D
132 |CCCCCCC | A B | DDDDDDD|
133 | CCCCCCCC | A | | B | DDDDDDDD |
134 | CCCCCCC A B DDDDDDD |
135 - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - - -
137 | west | b move c | east | ad
139 - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - - -
140 | EEEEEEE G H FFFFFFF |
141 | EEEEEEEE | G | | H | FFFFFFFF |
142 |EEEEEEE | G H | FFFFFFF|
143 E---------------------+----G--+-------+--H----+---------------------F
146 | southwest | G south H | southeast |
153 +---------------------G-------|-------|-------H---------------------+
157 /* for shaded windows, you can only resize west/east and move */
159 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
161 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
162 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
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);
182 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);