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"
26 extern AwesomeConf globalconf
;
28 name_func_link_t FloatingPlacementList
[] =
30 { "smart", placement_smart
},
31 { "under_mouse", placement_under_mouse
},
36 placement_fix_offscreen(area_t geometry
, int screen
, int border
)
38 area_t screen_geometry
;
40 screen_geometry
= screen_get_area(screen
,
41 globalconf
.screens
[screen
].statusbar
,
42 &globalconf
.screens
[screen
].padding
);
45 if(AREA_RIGHT(geometry
) > AREA_RIGHT(screen_geometry
))
46 geometry
.x
= screen_geometry
.x
+ screen_geometry
.width
- (geometry
.width
+ 2 * border
);
47 else if(AREA_LEFT(geometry
) < AREA_LEFT(screen_geometry
))
48 geometry
.x
= screen_geometry
.x
;
50 if(AREA_BOTTOM(geometry
) > AREA_BOTTOM(screen_geometry
))
51 geometry
.y
= screen_geometry
.y
+ screen_geometry
.height
- (geometry
.height
+ 2 * border
);
52 else if(AREA_TOP(geometry
) < AREA_TOP(screen_geometry
))
53 geometry
.y
= screen_geometry
.y
;
59 placement_geometry_add_titlebar(Titlebar
*t
, area_t geometry
)
67 geometry
.y
-= t
->sw
->geometry
.height
;
68 geometry
.height
+= t
->sw
->geometry
.height
;
71 geometry
.height
+= t
->sw
->geometry
.height
;
74 geometry
.x
-= t
->sw
->geometry
.width
;
75 geometry
.width
+= t
->sw
->geometry
.width
;
78 geometry
.width
+= t
->sw
->geometry
.width
;
87 /** Compute smart coordinates for a client window
88 * \param geometry current/requested client geometry
89 * \param screen screen used
90 * \return new geometry
93 placement_smart(Client
*c
)
96 area_t newgeometry
= { 0, 0, 0, 0, NULL
, NULL
};
97 area_t
*screen_geometry
, *arealist
= NULL
, *r
;
100 screen_geometry
= p_new(area_t
, 1);
102 *screen_geometry
= screen_get_area(c
->screen
,
103 globalconf
.screens
[c
->screen
].statusbar
,
104 &globalconf
.screens
[c
->screen
].padding
);
106 area_list_push(&arealist
, screen_geometry
);
108 for(client
= globalconf
.clients
; client
; client
= client
->next
)
109 if(client_isvisible(client
, c
->screen
))
111 newgeometry
= client
->f_geometry
;
112 newgeometry
.width
+= 2 * client
->border
;
113 newgeometry
.height
+= 2 * client
->border
;
114 newgeometry
= placement_geometry_add_titlebar(&client
->titlebar
, newgeometry
);
115 area_list_remove(&arealist
, &newgeometry
);
118 newgeometry
.x
= c
->f_geometry
.x
;
119 newgeometry
.y
= c
->f_geometry
.y
;
120 newgeometry
.width
= 0;
121 newgeometry
.height
= 0;
123 for(r
= arealist
; r
; r
= r
->next
)
124 if(r
->width
>= c
->f_geometry
.width
&& r
->height
>= c
->f_geometry
.height
125 && r
->width
* r
->height
> newgeometry
.width
* newgeometry
.height
)
131 /* we did not found a space with enough space for our size:
132 * just take the biggest available and go in */
134 for(r
= arealist
; r
; r
= r
->next
)
135 if(r
->width
* r
->height
> newgeometry
.width
* newgeometry
.height
)
138 /* restore height and width */
139 newgeometry
.width
= c
->f_geometry
.width
;
140 newgeometry
.height
= c
->f_geometry
.height
;
142 newgeometry
= placement_geometry_add_titlebar(&c
->titlebar
, newgeometry
);
143 newgeometry
= placement_fix_offscreen(newgeometry
, c
->screen
, c
->border
);
145 /* restore height and width again */
146 newgeometry
.width
= c
->f_geometry
.width
;
147 newgeometry
.height
= c
->f_geometry
.height
;
149 area_list_wipe(&arealist
);
155 placement_under_mouse(Client
*c
)
160 area_t finalgeometry
= c
->f_geometry
;
162 if(XQueryPointer(globalconf
.display
, RootWindow(globalconf
.display
, get_phys_screen(c
->screen
)),
163 &dummy
, &dummy
, &x
, &y
, &d
, &d
, &m
))
165 finalgeometry
.x
= x
- c
->f_geometry
.width
/ 2;
166 finalgeometry
.y
= y
- c
->f_geometry
.height
/ 2;
169 finalgeometry
= placement_geometry_add_titlebar(&c
->titlebar
, finalgeometry
);
170 finalgeometry
= placement_fix_offscreen(finalgeometry
, c
->screen
, c
->border
);
172 /* restore height and width */
173 finalgeometry
.height
= c
->f_geometry
.height
;
174 finalgeometry
.width
= c
->f_geometry
.width
;
176 return finalgeometry
;
178 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80