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 geometry
, int screen
, int border
)
38 Area screen_geometry
, newgeometry
= geometry
;
40 screen_geometry
= screen_get_area(screen
,
41 globalconf
.screens
[screen
].statusbar
,
42 &globalconf
.screens
[screen
].padding
);
45 if(AREA_RIGHT(newgeometry
) > AREA_RIGHT(screen_geometry
))
46 newgeometry
.x
= screen_geometry
.x
+ screen_geometry
.width
- (newgeometry
.width
+ 2 * border
);
47 else if(AREA_LEFT(newgeometry
) < AREA_LEFT(screen_geometry
))
48 newgeometry
.x
= screen_geometry
.x
;
50 if(AREA_BOTTOM(newgeometry
) > AREA_BOTTOM(screen_geometry
))
51 newgeometry
.y
= screen_geometry
.y
+ screen_geometry
.height
- (newgeometry
.height
+ 2 * border
);
52 else if(AREA_TOP(newgeometry
) < AREA_TOP(screen_geometry
))
53 newgeometry
.y
= screen_geometry
.y
;
58 /** Compute smart coordinates for a client window
59 * \param geometry current/requested client geometry
60 * \param screen screen used
61 * \return new geometry
64 placement_smart(Area geometry
, int border
, int screen
)
67 Area newgeometry
= { 0, 0, 0, 0, NULL
};
68 Area
*screen_geometry
, *arealist
= NULL
, *r
;
71 screen_geometry
= p_new(Area
, 1);
73 *screen_geometry
= screen_get_area(screen
,
74 globalconf
.screens
[screen
].statusbar
,
75 &globalconf
.screens
[screen
].padding
);
77 area_list_push(&arealist
, screen_geometry
);
79 for(c
= globalconf
.clients
; c
; c
= c
->next
)
80 if(client_isvisible(c
, screen
))
82 newgeometry
= c
->f_geometry
;
83 newgeometry
.width
+= 2 * c
->border
;
84 newgeometry
.height
+= 2 * c
->border
;
85 area_list_remove(&arealist
, &newgeometry
);
88 newgeometry
.x
= geometry
.x
;
89 newgeometry
.y
= geometry
.y
;
90 newgeometry
.width
= 0;
91 newgeometry
.height
= 0;
93 for(r
= arealist
; r
; r
= r
->next
)
94 if(r
->width
>= geometry
.width
&& r
->height
>= geometry
.height
95 && r
->width
* r
->height
> newgeometry
.width
* newgeometry
.height
)
101 /* we did not found a space with enough space for our size:
102 * just take the biggest available and go in */
104 for(r
= arealist
; r
; r
= r
->next
)
105 if(r
->width
* r
->height
> newgeometry
.width
* newgeometry
.height
)
108 /* restore height and width */
109 newgeometry
.width
= geometry
.width
;
110 newgeometry
.height
= geometry
.height
;
112 newgeometry
= placement_fix_offscreen(newgeometry
, screen
, border
);
114 area_list_wipe(&arealist
);
120 placement_under_mouse(Area geometry
, int border
, int screen
)
125 Area finalgeometry
= geometry
;
127 if(XQueryPointer(globalconf
.display
, RootWindow(globalconf
.display
, get_phys_screen(screen
)),
128 &dummy
, &dummy
, &x
, &y
, &d
, &d
, &m
))
130 finalgeometry
.x
= x
- geometry
.width
/ 2;
131 finalgeometry
.y
= y
- geometry
.height
/ 2;
134 finalgeometry
= placement_fix_offscreen(finalgeometry
, screen
, border
);
136 return finalgeometry
;
138 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80