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