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 #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
},
38 placement_fix_offscreen(area_t geometry
, int screen
, int border
)
40 area_t screen_geometry
;
42 screen_geometry
= screen_area_get(screen
,
43 globalconf
.screens
[screen
].statusbar
,
44 &globalconf
.screens
[screen
].padding
);
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
;
60 /** Compute smart coordinates for a client window
61 * \param c The client to place.
62 * \return new geometry
65 placement_smart(client_t
*c
)
68 area_t newgeometry
= { 0, 0, 0, 0 };
69 area_t screen_geometry
;
75 area_array_init(&areas
);
76 screen_geometry
= screen_area_get(c
->screen
,
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
)
111 /* we did not found a space with enough space for our size:
112 * just take the biggest available and go in */
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
)
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
);
133 /** Compute placement for a window centered under the mouse.
134 * \param c The client.
135 * \return The proposed geometry.
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;
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