1 #include "openbox/actions.h"
2 #include "openbox/moveresize.h"
3 #include "openbox/client.h"
4 #include "openbox/frame.h"
8 gboolean corner_specified
;
12 static gpointer
setup_func(xmlNodePtr node
);
13 static gboolean
run_func(ObActionsData
*data
, gpointer options
);
15 static guint32
pick_corner(gint x
, gint y
, gint cx
, gint cy
, gint cw
, gint ch
,
18 void action_resize_startup(void)
20 actions_register("Resize", setup_func
, g_free
, run_func
, NULL
, NULL
);
23 static gpointer
setup_func(xmlNodePtr node
)
28 o
= g_new0(Options
, 1);
30 if ((n
= obt_parse_find_node(node
, "edge"))) {
31 gchar
*s
= obt_parse_node_string(n
);
33 o
->corner_specified
= TRUE
;
34 if (!g_ascii_strcasecmp(s
, "top"))
35 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP
);
36 else if (!g_ascii_strcasecmp(s
, "bottom"))
37 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM
);
38 else if (!g_ascii_strcasecmp(s
, "left"))
39 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT
);
40 else if (!g_ascii_strcasecmp(s
, "right"))
41 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT
);
42 else if (!g_ascii_strcasecmp(s
, "topleft"))
43 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT
);
44 else if (!g_ascii_strcasecmp(s
, "topright"))
45 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT
);
46 else if (!g_ascii_strcasecmp(s
, "bottomleft"))
47 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
);
48 else if (!g_ascii_strcasecmp(s
, "bottomright"))
49 o
->corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
);
51 o
->corner_specified
= FALSE
;
58 /* Always return FALSE because its not interactive */
59 static gboolean
run_func(ObActionsData
*data
, gpointer options
)
64 ObClient
*c
= data
->client
;
68 corner
= OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD
);
69 else if (o
->corner_specified
)
70 corner
= o
->corner
; /* it was specified in the binding */
72 corner
= pick_corner(data
->x
, data
->y
,
73 c
->frame
->area
.x
, c
->frame
->area
.y
,
74 /* use the client size because the frame
75 can be differently sized (shaded
76 windows) and we want this based on the
78 c
->area
.width
+ c
->frame
->size
.left
+
80 c
->area
.height
+ c
->frame
->size
.top
+
81 c
->frame
->size
.bottom
, c
->shaded
);
83 moveresize_start(c
, data
->x
, data
->y
, data
->button
, corner
);
89 static guint32
pick_corner(gint x
, gint y
, gint cx
, gint cy
, gint cw
, gint ch
,
92 /* let's make x and y client relative instead of screen relative */
94 y
= ch
- (y
- cy
); /* y is inverted, 0 is at the bottom of the window */
97 #define A -4*X + 7*ch/3
98 #define B 4*X -15*ch/9
99 #define C -X/4 + 2*ch/3
100 #define D X/4 + 5*ch/12
102 #define F -X/4 + 7*ch/12
103 #define G 4*X - 4*ch/3
104 #define H -4*X + 8*ch/3
105 #define a (y > 5*ch/9)
106 #define b (x < 4*cw/9)
107 #define c (x > 5*cw/9)
108 #define d (y < 4*ch/9)
111 Each of these defines (except X which is just there for fun), represents
112 the equation of a line. The lines they represent are shown in the diagram
113 below. Checking y against these lines, we are able to choose a region
114 of the window as shown.
116 +---------------------A-------|-------|-------B---------------------+
123 | northwest | A north B | northeast |
126 C---------------------+----A--+-------+--B----+---------------------D
127 |CCCCCCC | A B | DDDDDDD|
128 | CCCCCCCC | A | | B | DDDDDDDD |
129 | CCCCCCC A B DDDDDDD |
130 - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - - -
132 | west | b move c | east | ad
134 - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - - -
135 | EEEEEEE G H FFFFFFF |
136 | EEEEEEEE | G | | H | FFFFFFFF |
137 |EEEEEEE | G H | FFFFFFF|
138 E---------------------+----G--+-------+--H----+---------------------F
141 | southwest | G south H | southeast |
148 +---------------------G-------|-------|-------H---------------------+
152 /* for shaded windows, you can only resize west/east and move */
154 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT
);
156 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT
);
157 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE
);
161 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT
);
162 else if (y
>= A
&& y
>= B
&& a
)
163 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP
);
164 else if (y
< B
&& y
>= D
)
165 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT
);
166 else if (y
< C
&& y
>= E
&& b
)
167 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT
);
168 else if (y
< D
&& y
>= F
&& c
)
169 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT
);
170 else if (y
< E
&& y
>= G
)
171 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
);
172 else if (y
< G
&& y
< H
&& d
)
173 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM
);
174 else if (y
>= H
&& y
< F
)
175 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
);
177 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE
);