[WM_ROT] support for rotating prediction window without virtual keyboard
[platform/core/uifw/e17.git] / src / bin / e_maximize.c
1 #include "e.h"
2
3 typedef struct _E_Maximize_Rect E_Maximize_Rect;
4
5 struct _E_Maximize_Rect
6 {
7    int x1, yy1, x2, y2;
8 };
9
10 #define OBSTACLE(_x1, _y1, _x2, _y2) \
11    { \
12       r = E_NEW(E_Maximize_Rect, 1); \
13       r->x1 = (_x1); r->yy1 = (_y1); r->x2 = (_x2); r->y2 = (_y2); \
14       rects = eina_list_append(rects, r); \
15    }
16
17 static void _e_maximize_border_rects_fill(E_Border *bd, Eina_List *list, int *x1, int *yy1, int *x2, int *y2, E_Maximize dir);
18 static void _e_maximize_border_rects_fill_both(E_Border *bd, Eina_List *rects, int *x1, int *yy1, int *x2, int *y2);
19 static void _e_maximize_border_rects_fill_horiz(E_Border *bd, Eina_List *rects, int *x1, int *x2, int *bx, int *by, int *bw, int *bh);
20 static void _e_maximize_border_rects_fill_vert(E_Border *bd, Eina_List *rects, int *yy1, int *y2, int *bx, int *by, int *bw, int *bh);
21
22 EAPI void
23 e_maximize_border_shelf_fit(E_Border *bd, int *x1, int *yy1, int *x2, int *y2, E_Maximize dir)
24 {
25    e_maximize_border_shelf_fill(bd, x1, yy1, x2, y2, dir);
26 }
27
28 EAPI void
29 e_maximize_border_dock_fit(E_Border *bd, int *x1, int *yy1, int *x2, int *y2)
30 {
31    E_Border_List *bl;
32    E_Border *bd2;
33    int cx1, cx2, cy1, cy2;
34
35    cx1 = bd->zone->x;
36    if (x1) cx1 = *x1;
37
38    cy1 = bd->zone->y;
39    if (yy1) cy1 = *yy1;
40
41    cx2 = bd->zone->x + bd->zone->w;
42    if (x2) cx2 = *x2;
43
44    cy2 = bd->zone->y + bd->zone->h;
45    if (y2) cy2 = *y2;
46
47    bl = e_container_border_list_first(bd->zone->container);
48    while ((bd2 = e_container_border_list_next(bl)))
49      {
50         enum {
51              NONE,
52              TOP,
53              RIGHT,
54              BOTTOM,
55              LEFT
56         } edge = NONE;
57
58         if ((bd2->zone != bd->zone) || (bd2 == bd) ||
59             (bd2->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK))
60           continue;
61
62         if (((bd2->x == bd2->zone->x) || ((bd2->x + bd2->w) == (bd2->zone->x + bd2->zone->w))) &&
63             ((bd2->y == bd2->zone->y) || ((bd2->x + bd2->h) == (bd2->zone->x + bd2->zone->h))))
64           {
65              /* corner */
66              if (bd2->w > bd2->h)
67                {
68                   if (bd2->y == bd2->zone->y)
69                     edge = TOP;
70                   else if ((bd2->y + bd2->h) == (bd2->zone->y + bd2->zone->h))
71                     edge = BOTTOM;
72                }
73              else
74                {
75                   if ((bd2->x + bd2->w) == (bd2->zone->x + bd2->zone->w))
76                     edge = RIGHT;
77                   else if (bd2->x == bd2->zone->x)
78                     edge = LEFT;
79                }
80           }
81         else
82           {
83              if (bd2->y == bd2->zone->y)
84                edge = TOP;
85              else if ((bd2->y + bd2->h) == (bd2->zone->y + bd2->zone->h))
86                edge = BOTTOM;
87              else if (bd2->x == bd2->zone->x)
88                edge = LEFT;
89              else if ((bd2->x + bd2->w) == (bd2->zone->x + bd2->zone->w))
90                edge = RIGHT;
91           }
92
93         switch (edge)
94           {
95            case TOP:
96               if ((bd2->y + bd2->h) > cy1)
97                 cy1 = (bd2->y + bd2->h);
98               break;
99            case RIGHT:
100               if (bd2->x < cx2)
101                 cx2 = bd2->x;
102               break;
103            case BOTTOM:
104               if (bd2->y < cy2)
105                 cy2 = bd2->y;
106               break;
107            case LEFT:
108               if ((bd2->x + bd2->w) > cx1)
109                 cx1 = (bd2->x + bd2->w);
110               break;
111            case NONE:
112               printf("Crazy people. Dock isn't at the edge.\n");
113               break;
114           }
115      }
116    e_container_border_list_free(bl);
117
118    if (x1) *x1 = cx1;
119    if (yy1) *yy1 = cy1;
120    if (x2) *x2 = cx2;
121    if (y2) *y2 = cy2;
122 }
123
124 EAPI void
125 e_maximize_border_shelf_fill(E_Border *bd, int *x1, int *yy1, int *x2, int *y2, E_Maximize dir)
126 {
127    Eina_List *l, *rects = NULL;
128    E_Shelf *es;
129    E_Maximize_Rect *r;
130
131    EINA_LIST_FOREACH(e_shelf_list(), l, es)
132      {
133         Eina_List *ll;
134         E_Config_Shelf_Desk *sd;
135
136         if (es->cfg->overlap) continue;
137         if (es->zone != bd->zone) continue;
138         if (es->cfg->desk_show_mode)
139           {
140              EINA_LIST_FOREACH(es->cfg->desk_list, ll, sd)
141                {
142                   if (!sd) continue;
143                   if ((sd->x == bd->desk->x) && (sd->y == bd->desk->y))
144                     {
145                        OBSTACLE(es->x + es->zone->x, es->y + es->zone->y,
146                                 es->x + es->zone->x + es->w, es->y + es->zone->y + es->h);
147                        break;
148                     }
149                }
150           }
151         else
152           {
153              OBSTACLE(es->x + es->zone->x, es->y + es->zone->y,
154                       es->x + es->zone->x + es->w, es->y + es->zone->y + es->h);
155           }
156      }
157    if (rects)
158      {
159         _e_maximize_border_rects_fill(bd, rects, x1, yy1, x2, y2, dir);
160         E_FREE_LIST(rects, free);
161      }
162 }
163
164 EAPI void
165 e_maximize_border_border_fill(E_Border *bd, int *x1, int *yy1, int *x2, int *y2, E_Maximize dir)
166 {
167    Eina_List *rects = NULL;
168    E_Border_List *bl;
169    E_Maximize_Rect *r;
170    E_Border *bd2;
171
172    bl = e_container_border_list_first(bd->zone->container);
173    while ((bd2 = e_container_border_list_next(bl)))
174      {
175         if ((bd2->zone != bd->zone) || (bd == bd2) || (bd2->desk != bd->desk && !bd2->sticky) || (bd2->iconic))
176           continue;
177         OBSTACLE(bd2->x, bd2->y, bd2->x + bd2->w, bd2->y + bd2->h);
178      }
179    e_container_border_list_free(bl);
180    if (rects)
181      {
182         _e_maximize_border_rects_fill(bd, rects, x1, yy1, x2, y2, dir);
183         E_FREE_LIST(rects, free);
184      }
185 }
186
187 static void
188 _e_maximize_border_rects_fill(E_Border *bd, Eina_List *rects, int *x1, int *yy1, int *x2, int *y2, E_Maximize dir)
189 {
190    if ((dir & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
191      {
192         _e_maximize_border_rects_fill_both(bd, rects, x1, yy1, x2, y2);
193      }
194    else
195      {
196         int bx, by, bw, bh;
197
198         bx = bd->x;
199         by = bd->y;
200         bw = bd->w;
201         bh = bd->h;
202
203         if ((dir & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
204           _e_maximize_border_rects_fill_horiz(bd, rects, x1, x2, &bx, &by, &bw, &bh);
205         else if ((dir & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
206           _e_maximize_border_rects_fill_vert(bd, rects, yy1, y2, &bx, &by, &bw, &bh);
207      }
208 }
209
210 static void
211 _e_maximize_border_rects_fill_both(E_Border *bd, Eina_List *rects, int *x1, int *yy1, int *x2, int *y2)
212 {
213    int hx1, hy1, hx2, hy2;
214    int vx1, vy1, vx2, vy2;
215    int bx, by, bw, bh;
216
217    hx1 = vx1 = bd->zone->x;
218    if (x1) hx1 = vx1 = *x1;
219
220    hy1 = vy1 = bd->zone->y;
221    if (yy1) hy1 = vy1 = *yy1;
222
223    hx2 = vx2 = bd->zone->x + bd->zone->w;
224    if (x2) hx2 = vx2 = *x2;
225
226    hy2 = vy2 = bd->zone->y + bd->zone->h;
227    if (y2) hy2 = vy2 = *y2;
228
229    /* Init working values, try maximizing horizontally first */
230    bx = bd->x;
231    by = bd->y;
232    bw = bd->w;
233    bh = bd->h;
234    _e_maximize_border_rects_fill_horiz(bd, rects, &hx1, &hx2, &bx, &by, &bw, &bh);
235    _e_maximize_border_rects_fill_vert(bd, rects, &hy1, &hy2, &bx, &by, &bw, &bh);
236
237    /* Reset working values, try maximizing vertically first */
238    bx = bd->x;
239    by = bd->y;
240    bw = bd->w;
241    bh = bd->h;
242    _e_maximize_border_rects_fill_vert(bd, rects, &vy1, &vy2, &bx, &by, &bw, &bh);
243    _e_maximize_border_rects_fill_horiz(bd, rects, &vx1, &vx2, &bx, &by, &bw, &bh);
244
245    /* Use the result set that gives the largest volume */
246    if (((hx2 - hx1) * (hy2 - hy1)) > ((vx2 - vx1) * (vy2 - vy1)))
247      {
248         if (x1) *x1 = hx1;
249         if (yy1) *yy1 = hy1;
250         if (x2) *x2 = hx2;
251         if (y2) *y2 = hy2;
252      }
253    else
254      {
255         if (x1) *x1 = vx1;
256         if (yy1) *yy1 = vy1;
257         if (x2) *x2 = vx2;
258         if (y2) *y2 = vy2;
259      }
260 }
261
262 static void
263 _e_maximize_border_rects_fill_horiz(E_Border *bd, Eina_List *rects, int *x1, int *x2, int *bx, int *by, int *bw, int *bh)
264 {
265    Eina_List *l;
266    E_Maximize_Rect *rect;
267    int cx1, cx2;
268
269    cx1 = bd->zone->x;
270    if (x1) cx1 = *x1;
271
272    cx2 = bd->zone->x + bd->zone->w;
273    if (x2) cx2 = *x2;
274
275    /* Expand left */
276    EINA_LIST_FOREACH(rects, l, rect)
277      {
278         if ((rect->x2 > cx1) && (rect->x2 <= *bx) &&
279             E_INTERSECTS(0, rect->yy1, bd->zone->w, (rect->y2 - rect->yy1), 0, *by, bd->zone->w, *bh))
280           {
281              cx1 = rect->x2;
282           }
283      }
284    *bw += (*bx - cx1);
285    *bx = cx1;
286
287    /* Expand right */
288    EINA_LIST_FOREACH(rects, l, rect)
289      {
290         if ((rect->x1 < cx2) && (rect->x1 >= (*bx + *bw)) &&
291             E_INTERSECTS(0, rect->yy1, bd->zone->w, (rect->y2 - rect->yy1), 0, *by, bd->zone->w, *bh))
292           {
293              cx2 = rect->x1;
294           }
295      }
296    *bw = (cx2 - cx1);
297
298    if (x1) *x1 = cx1;
299    if (x2) *x2 = cx2;
300 }
301
302 static void
303 _e_maximize_border_rects_fill_vert(E_Border *bd, Eina_List *rects, int *yy1, int *y2, int *bx, int *by, int *bw, int *bh)
304 {
305    Eina_List *l;
306    E_Maximize_Rect *rect;
307    int cy1, cy2;
308
309    cy1 = bd->zone->y;
310    if (yy1) cy1 = *yy1;
311
312    cy2 = bd->zone->y + bd->zone->h;
313    if (y2) cy2 = *y2;
314
315    /* Expand up */
316    EINA_LIST_FOREACH(rects, l, rect)
317      {
318         if ((rect->y2 > cy1) && (rect->y2 <= *by) &&
319             E_INTERSECTS(rect->x1, 0, (rect->x2 - rect->x1), bd->zone->h, *bx, 0, *bw, bd->zone->h))
320           {
321              cy1 = rect->y2;
322           }
323      }
324    *bh += (*by - cy1);
325    *by = cy1;
326
327    /* Expand down */
328    EINA_LIST_FOREACH(rects, l, rect)
329      {
330         if ((rect->yy1 < cy2) && (rect->yy1 >= (*by + *bh)) &&
331             E_INTERSECTS(rect->x1, 0, (rect->x2 - rect->x1), bd->zone->h, *bx, 0, *bw, bd->zone->h))
332           {
333              cy2 = rect->yy1;
334           }
335      }
336    *bh = (cy2 - cy1);
337
338    if (yy1) *yy1 = cy1;
339    if (y2) *y2 = cy2;
340 }