scan: fix array indice
[awesome.git] / placement.c
blob7cde51a50ed09ec31eb7161082a6dba008f3467c
1 /*
2 * placement.c - client placement management
4 * Copyright © 2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "placement.h"
23 #include "screen.h"
24 #include "client.h"
25 #include "titlebar.h"
26 #include "layouts/floating.h"
28 extern awesome_t globalconf;
30 const name_func_link_t FloatingPlacementList[] =
32 { "smart", placement_smart },
33 { "under_mouse", placement_under_mouse },
34 { NULL, NULL }
37 static area_t
38 placement_fix_offscreen(area_t geometry, int screen, int border)
40 area_t screen_geometry;
42 screen_geometry = screen_area_get(&globalconf.screens[screen].geometry,
43 globalconf.screens[screen].statusbar,
44 &globalconf.screens[screen].padding);
46 /* fix offscreen */
47 if(AREA_RIGHT(geometry) > AREA_RIGHT(screen_geometry))
48 geometry.x = screen_geometry.x + screen_geometry.width - (geometry.width + 2 * border);
49 else if(AREA_LEFT(geometry) < AREA_LEFT(screen_geometry))
50 geometry.x = screen_geometry.x;
52 if(AREA_BOTTOM(geometry) > AREA_BOTTOM(screen_geometry))
53 geometry.y = screen_geometry.y + screen_geometry.height - (geometry.height + 2 * border);
54 else if(AREA_TOP(geometry) < AREA_TOP(screen_geometry))
55 geometry.y = screen_geometry.y;
57 return geometry;
60 /** Compute smart coordinates for a client window
61 * \param c The client to place.
62 * \return new geometry
64 area_t
65 placement_smart(client_t *c)
67 client_t *client;
68 area_t newgeometry = { 0, 0, 0, 0 };
69 area_t screen_geometry;
70 area_array_t areas;
71 bool found = false;
72 layout_t *layout;
73 int i;
75 area_array_init(&areas);
76 screen_geometry = screen_area_get(&globalconf.screens[c->screen].geometry,
77 globalconf.screens[c->screen].statusbar,
78 &globalconf.screens[c->screen].padding);
80 layout = layout_get_current(c->screen);
81 area_array_append(&areas, screen_geometry);
83 for(client = globalconf.clients; client; client = client->next)
84 if(client != c && (client->isfloating || layout == layout_floating)
85 && client_isvisible(client, c->screen))
87 newgeometry = client->f_geometry;
88 newgeometry.width += 2 * client->border;
89 newgeometry.height += 2 * client->border;
90 newgeometry = titlebar_geometry_add(c->titlebar, c->border, newgeometry);
91 area_array_remove(&areas, newgeometry);
94 newgeometry.x = c->f_geometry.x;
95 newgeometry.y = c->f_geometry.y;
96 newgeometry.width = 0;
97 newgeometry.height = 0;
99 for(i = areas.len - 1; i >= 0; i--)
101 area_t *r = &areas.tab[i];
103 if(r->width >= c->f_geometry.width && r->height >= c->f_geometry.height
104 && r->width * r->height > newgeometry.width * newgeometry.height)
106 found = true;
107 newgeometry = *r;
111 /* we did not found a space with enough space for our size:
112 * just take the biggest available and go in */
113 if(!found)
114 for(i = 0; i < areas.len; i++)
116 area_t *r = &areas.tab[i];
117 if(r->width * r->height > newgeometry.width * newgeometry.height)
118 newgeometry = *r;
121 /* restore height and width */
122 newgeometry.width = c->f_geometry.width;
123 newgeometry.height = c->f_geometry.height;
125 newgeometry = titlebar_geometry_add(c->titlebar, c->border, newgeometry);
126 newgeometry = placement_fix_offscreen(newgeometry, c->screen, c->border);
127 newgeometry = titlebar_geometry_remove(c->titlebar, c->border, newgeometry);
129 area_array_wipe(&areas);
130 return newgeometry;
133 /** Compute placement for a window centered under the mouse.
134 * \param c The client.
135 * \return The proposed geometry.
137 area_t
138 placement_under_mouse(client_t *c)
140 xcb_query_pointer_cookie_t qp_c;
141 xcb_query_pointer_reply_t *qp_r;
142 area_t finalgeometry = c->f_geometry;
144 qp_c = xcb_query_pointer_unchecked(globalconf.connection,
145 xutil_screen_get(globalconf.connection,
146 c->phys_screen)->root);
147 if((qp_r = xcb_query_pointer_reply(globalconf.connection, qp_c, NULL)))
149 finalgeometry.x = qp_r->root_x - c->f_geometry.width / 2;
150 finalgeometry.y = qp_r->root_y - c->f_geometry.height / 2;
152 p_delete(&qp_r);
155 finalgeometry = titlebar_geometry_add(c->titlebar, c->border, finalgeometry);
156 finalgeometry = placement_fix_offscreen(finalgeometry, c->screen, c->border);
157 finalgeometry = titlebar_geometry_remove(c->titlebar, c->border, finalgeometry);
159 return finalgeometry;
161 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80