2 * screen.c - screen management
4 * Copyright © 2007-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.
26 #include "layouts/floating.h"
28 extern AwesomeConf globalconf
;
31 * \param screen Screen number
32 * \param statusbar statusbar
33 * \param padding Padding
37 screen_get_area(int screen
, Statusbar
*statusbar
, Padding
*padding
)
39 area_t area
= globalconf
.screens_info
->geometry
[screen
];
42 /* make padding corrections */
45 area
.x
+= padding
->left
;
46 area
.y
+= padding
->top
;
47 area
.width
-= padding
->left
+ padding
->right
;
48 area
.height
-= padding
->top
+ padding
->bottom
;
51 for(sb
= statusbar
; sb
; sb
= sb
->next
)
57 area
.height
-= sb
->height
;
62 area
.width
-= sb
->height
;
72 * \param screen Screen number
73 * \param statusbar the statusbar
74 * \param padding Padding
78 get_display_area(int screen
, Statusbar
*statusbar
, Padding
*padding
)
80 area_t area
= { 0, 0, 0, 0, NULL
, NULL
};
83 area
.width
= DisplayWidth(globalconf
.display
, screen
);
84 area
.height
= DisplayHeight(globalconf
.display
, screen
);
86 for(sb
= statusbar
; sb
; sb
= sb
->next
)
88 area
.y
+= sb
->position
== Top
? sb
->height
: 0;
89 area
.height
-= (sb
->position
== Top
|| sb
->position
== Bottom
) ? sb
->height
: 0;
92 /* make padding corrections */
95 area
.x
+= padding
->left
;
96 area
.y
+= padding
->top
;
97 area
.width
-= padding
->left
+ padding
->right
;
98 area
.height
-= padding
->top
+ padding
->bottom
;
103 /** This returns the real X screen number for a logical
104 * screen if Xinerama is active.
105 * \param screen the logical screen
106 * \return the X screen
109 screen_virttophys(int screen
)
111 if(globalconf
.screens_info
->xinerama_is_active
)
112 return DefaultScreen(globalconf
.display
);
116 /** Move a client to a virtual screen
117 * \param c the client
118 * \param new_screen The destinatiuon screen
119 * \param doresize set to True if we also move the client to the new x and
120 * y of the new screen
123 move_client_to_screen(Client
*c
, int new_screen
, Bool doresize
)
126 int old_screen
= c
->screen
;
129 for(tag
= globalconf
.screens
[old_screen
].tags
; tag
; tag
= tag
->next
)
130 untag_client(c
, tag
);
132 c
->screen
= new_screen
;
134 /* tag client with new screen tags */
135 tag_client_with_current_selected(c
);
137 /* resize the windows if it's floating */
138 if(doresize
&& old_screen
!= c
->screen
)
140 area_t new_geometry
, new_f_geometry
;
141 new_f_geometry
= c
->f_geometry
;
143 to
= screen_get_area(c
->screen
, NULL
, NULL
);
144 from
= screen_get_area(old_screen
, NULL
, NULL
);
146 /* compute new coords in new screen */
147 new_f_geometry
.x
= (c
->f_geometry
.x
- from
.x
) + to
.x
;
148 new_f_geometry
.y
= (c
->f_geometry
.y
- from
.y
) + to
.y
;
150 /* check that new coords are still in the screen */
151 if(new_f_geometry
.width
> to
.width
)
152 new_f_geometry
.width
= to
.width
;
153 if(new_f_geometry
.height
> to
.height
)
154 new_f_geometry
.height
= to
.height
;
155 if(new_f_geometry
.x
+ new_f_geometry
.width
>= to
.x
+ to
.width
)
156 new_f_geometry
.x
= to
.x
+ to
.width
- new_f_geometry
.width
- 2 * c
->border
;
157 if(new_f_geometry
.y
+ new_f_geometry
.height
>= to
.y
+ to
.height
)
158 new_f_geometry
.y
= to
.y
+ to
.height
- new_f_geometry
.height
- 2 * c
->border
;
162 new_geometry
= c
->geometry
;
164 /* compute new coords in new screen */
165 new_geometry
.x
= (c
->geometry
.x
- from
.x
) + to
.x
;
166 new_geometry
.y
= (c
->geometry
.y
- from
.y
) + to
.y
;
168 /* check that new coords are still in the screen */
169 if(new_geometry
.width
> to
.width
)
170 new_geometry
.width
= to
.width
;
171 if(new_geometry
.height
> to
.height
)
172 new_geometry
.height
= to
.height
;
173 if(new_geometry
.x
+ new_geometry
.width
>= to
.x
+ to
.width
)
174 new_geometry
.x
= to
.x
+ to
.width
- new_geometry
.width
- 2 * c
->border
;
175 if(new_geometry
.y
+ new_geometry
.height
>= to
.y
+ to
.height
)
176 new_geometry
.y
= to
.y
+ to
.height
- new_geometry
.height
- 2 * c
->border
;
178 /* compute new coords for max in new screen */
179 c
->m_geometry
.x
= (c
->m_geometry
.x
- from
.x
) + to
.x
;
180 c
->m_geometry
.y
= (c
->m_geometry
.y
- from
.y
) + to
.y
;
182 /* check that new coords are still in the screen */
183 if(c
->m_geometry
.width
> to
.width
)
184 c
->m_geometry
.width
= to
.width
;
185 if(c
->m_geometry
.height
> to
.height
)
186 c
->m_geometry
.height
= to
.height
;
187 if(c
->m_geometry
.x
+ c
->m_geometry
.width
>= to
.x
+ to
.width
)
188 c
->m_geometry
.x
= to
.x
+ to
.width
- c
->m_geometry
.width
- 2 * c
->border
;
189 if(c
->m_geometry
.y
+ c
->m_geometry
.height
>= to
.y
+ to
.height
)
190 c
->m_geometry
.y
= to
.y
+ to
.height
- c
->m_geometry
.height
- 2 * c
->border
;
192 client_resize(c
, new_geometry
, False
);
194 /* if floating, move to this new coords */
195 else if(c
->isfloating
)
196 client_resize(c
, new_f_geometry
, False
);
197 /* otherwise just register them */
200 c
->f_geometry
= new_f_geometry
;
201 globalconf
.screens
[old_screen
].need_arrange
= True
;
202 globalconf
.screens
[c
->screen
].need_arrange
= True
;
207 /** Move mouse pointer to x_org and y_xorg of specified screen
208 * \param screen screen number
211 move_mouse_pointer_to_screen(int phys_screen
)
213 if(globalconf
.screens_info
->xinerama_is_active
)
215 area_t area
= screen_get_area(phys_screen
, NULL
, NULL
);
216 XWarpPointer(globalconf
.display
,
218 DefaultRootWindow(globalconf
.display
),
219 0, 0, 0, 0, area
.x
, area
.y
);
222 XWarpPointer(globalconf
.display
,
224 RootWindow(globalconf
.display
, phys_screen
),
229 /** Switch focus to a specified screen
230 * \param screen Screen ID
231 * \param arg screen number
232 * \ingroup ui_callback
235 uicb_screen_focus(int screen
, char *arg
)
240 new_screen
= compute_new_value_from_arg(arg
, screen
);
242 new_screen
= screen
+ 1;
245 new_screen
= globalconf
.screens_info
->nscreen
- 1;
246 if (new_screen
> (globalconf
.screens_info
->nscreen
- 1))
249 client_focus(NULL
, new_screen
, True
);
251 move_mouse_pointer_to_screen(new_screen
);
254 /** Move client to a virtual screen (if Xinerama is active)
255 * \param screen Screen ID
256 * \param arg screen number
257 * \ingroup ui_callback
260 uicb_client_movetoscreen(int screen
__attribute__ ((unused
)), char *arg
)
262 int new_screen
, prev_screen
;
263 Client
*sel
= globalconf
.focus
->client
;
265 if(!sel
|| !globalconf
.screens_info
->xinerama_is_active
)
269 new_screen
= compute_new_value_from_arg(arg
, sel
->screen
);
271 new_screen
= sel
->screen
+ 1;
273 if(new_screen
>= globalconf
.screens_info
->nscreen
)
275 else if(new_screen
< 0)
276 new_screen
= globalconf
.screens_info
->nscreen
- 1;
278 prev_screen
= sel
->screen
;
279 move_client_to_screen(sel
, new_screen
, True
);
280 move_mouse_pointer_to_screen(new_screen
);
281 client_focus(sel
, sel
->screen
, True
);
283 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80