2 * screen.c - screen management
4 * Copyright © 2007 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 "statusbar.h"
29 * \param disp Display ref
30 * \param screen Screen number
31 * \param statusbar statusbar
32 * \return ScreenInfo struct array with all screens info
35 get_screen_info(Display
*disp
, int screen
, Statusbar
*statusbar
)
37 int i
, screen_number
= 0;
40 if(XineramaIsActive(disp
))
41 si
= XineramaQueryScreens(disp
, &screen_number
);
44 /* emulate Xinerama info but only fill the screen we want */
45 si
= p_new(ScreenInfo
, screen
+ 1);
46 si
[screen
].width
= DisplayWidth(disp
, screen
);
47 si
[screen
].height
= DisplayHeight(disp
, screen
);
50 screen_number
= screen
+ 1;
54 for(i
= 0; i
< screen_number
; i
++)
55 switch(statusbar
->position
)
58 si
[i
].y_org
+= statusbar
->height
;
60 si
[i
].height
-= statusbar
->height
;
63 si
[i
].x_org
+= statusbar
->height
;
65 si
[i
].width
-= statusbar
->height
;
73 * \param disp Display ref
74 * \param screen Screen number
75 * \param statusbar the statusbar
76 * \return ScreenInfo struct pointer with all display info
79 get_display_info(Display
*disp
, int screen
, Statusbar
*statusbar
)
83 si
= p_new(ScreenInfo
, 1);
86 si
->y_org
= statusbar
&& statusbar
->position
== BarTop
? statusbar
->height
: 0;
87 si
->width
= DisplayWidth(disp
, screen
);
88 si
->height
= DisplayHeight(disp
, screen
) -
89 (statusbar
&& (statusbar
->position
== BarTop
|| statusbar
->position
== BarBot
) ? statusbar
->height
: 0);
94 /** Return the Xinerama screen number where the coordinates belongs to
95 * \param disp Display ref
96 * \param x x coordinate of the window
97 * \param y y coordinate of the window
98 * \return screen number or DefaultScreen of disp on no match
101 get_screen_bycoord(Display
*disp
, int x
, int y
)
106 /* don't waste our time */
107 if(!XineramaIsActive(disp
))
108 return DefaultScreen(disp
);
110 si
= get_screen_info(disp
, 0, NULL
);
112 for(i
= 0; i
< get_screen_count(disp
); i
++)
113 if((x
< 0 || (x
>= si
[i
].x_org
&& x
< si
[i
].x_org
+ si
[i
].width
))
114 && (y
< 0 || (y
>= si
[i
].y_org
&& y
< si
[i
].y_org
+ si
[i
].height
)))
121 return DefaultScreen(disp
);
124 /** Return the actual screen count
125 * \param disp Display ref
126 * \return the number of screen available
129 get_screen_count(Display
*disp
)
133 if(XineramaIsActive(disp
))
134 XineramaQueryScreens(disp
, &screen_number
);
136 return ScreenCount(disp
);
138 return screen_number
;
141 /** This returns the real X screen number for a logical
142 * screen if Xinerama is active.
143 * \param disp Display ref
144 * \param screen the logical screen
145 * \return the X screen
148 get_phys_screen(Display
*disp
, int screen
)
150 if(XineramaIsActive(disp
))
151 return DefaultScreen(disp
);
155 /** Move a client to a virtual screen
156 * \param c the client
157 * \param acf_new the awesome_config for the new screen
158 * \param doresize set to True if we also move the client to the new x_org and
159 * y_org of the new screen
162 move_client_to_screen(Client
*c
, awesome_config
*acf_new
, Bool doresize
)
164 int old_screen
= c
->screen
;
166 c
->screen
= acf_new
->screen
;
168 if(doresize
&& old_screen
!= c
->screen
)
170 ScreenInfo
*si
, *si_old
;
172 si
= get_screen_info(c
->display
, c
->screen
, NULL
);
173 si_old
= get_screen_info(c
->display
, old_screen
, NULL
);
175 /* compute new coords in new screen */
176 c
->rx
= (c
->rx
- si_old
[old_screen
].x_org
) + si
[c
->screen
].x_org
;
177 c
->ry
= (c
->ry
- si_old
[old_screen
].y_org
) + si
[c
->screen
].y_org
;
178 /* check that new coords are still in the screen */
179 if(c
->rw
> si
[c
->screen
].width
)
180 c
->rw
= si
[c
->screen
].width
;
181 if(c
->rh
> si
[c
->screen
].height
)
182 c
->rh
= si
[c
->screen
].height
;
183 if(c
->rx
+ c
->rw
>= si
[c
->screen
].x_org
+ si
[c
->screen
].width
)
184 c
->rx
= si
[c
->screen
].x_org
+ si
[c
->screen
].width
- c
->rw
- 2 * c
->border
;
185 if(c
->ry
+ c
->rh
>= si
[c
->screen
].y_org
+ si
[c
->screen
].height
)
186 c
->ry
= si
[c
->screen
].y_org
+ si
[c
->screen
].height
- c
->rh
- 2 * c
->border
;
188 client_resize(c
, c
->rx
, c
->ry
, c
->rw
, c
->rh
, acf_new
, True
, False
);
194 focus(c
, True
, acf_new
);
196 /* redraw statusbar on all screens */
197 drawstatusbar(&acf_new
[old_screen
- acf_new
->screen
]);
198 drawstatusbar(acf_new
);
201 /** Move mouse pointer to x_org and y_xorg of specified screen
202 * \param disp display ref
203 * \param screen screen number
206 move_mouse_pointer_to_screen(Display
*disp
, int screen
)
208 if(XineramaIsActive(disp
))
210 ScreenInfo
*si
= get_screen_info(disp
, screen
, NULL
);
211 XWarpPointer(disp
, None
, DefaultRootWindow(disp
), 0, 0, 0, 0, si
[screen
].x_org
, si
[screen
].y_org
);
215 XWarpPointer(disp
, None
, RootWindow(disp
, screen
), 0, 0, 0, 0, 0, 0);
219 uicb_screen_focusnext(awesome_config
* awesomeconf
,
220 const char *arg
__attribute__ ((unused
)))
223 int next_screen
= awesomeconf
->screen
+ 1 >= get_screen_count(awesomeconf
->display
) ? 0 : awesomeconf
->screen
+ 1;
225 for(c
= *awesomeconf
->clients
; c
&& !isvisible(c
, next_screen
, awesomeconf
[next_screen
- awesomeconf
->screen
].tags
, awesomeconf
[next_screen
- awesomeconf
->screen
].ntags
); c
= c
->next
);
228 focus(c
, True
, &awesomeconf
[next_screen
- awesomeconf
->screen
]);
229 restack(&awesomeconf
[next_screen
- awesomeconf
->screen
]);
231 move_mouse_pointer_to_screen(awesomeconf
->display
, next_screen
);
235 uicb_screen_focusprev(awesome_config
* awesomeconf
,
236 const char *arg
__attribute__ ((unused
)))
239 int prev_screen
= awesomeconf
->screen
- 1 < 0 ? get_screen_count(awesomeconf
->display
) - 1 : awesomeconf
->screen
- 1;
241 for(c
= *awesomeconf
->clients
; c
&& !isvisible(c
, prev_screen
, awesomeconf
[prev_screen
- awesomeconf
->screen
].tags
, awesomeconf
[prev_screen
- awesomeconf
->screen
].ntags
); c
= c
->next
);
244 focus(c
, True
, &awesomeconf
[prev_screen
- awesomeconf
->screen
]);
245 restack(&awesomeconf
[prev_screen
- awesomeconf
->screen
]);
247 move_mouse_pointer_to_screen(awesomeconf
->display
, prev_screen
);
250 /** Move client to a virtual screen (if Xinerama is active)
251 * \param awesomeconf awesome config
252 * \param arg screen number
253 * \ingroup ui_callback
256 uicb_client_movetoscreen(awesome_config
* awesomeconf
,
259 int new_screen
, prev_screen
;
260 Client
*sel
= get_current_tag(awesomeconf
->tags
, awesomeconf
->ntags
)->client_sel
;
262 if(!sel
|| !XineramaIsActive(awesomeconf
->display
))
266 new_screen
= compute_new_value_from_arg(arg
, sel
->screen
);
268 new_screen
= sel
->screen
+ 1;
270 if(new_screen
>= get_screen_count(awesomeconf
->display
))
272 else if(new_screen
< 0)
273 new_screen
= get_screen_count(awesomeconf
->display
) - 1;
275 prev_screen
= sel
->screen
;
276 tag_client_with_current_selected(sel
, &awesomeconf
[new_screen
- awesomeconf
->screen
]);
277 move_client_to_screen(sel
, &awesomeconf
[new_screen
- awesomeconf
->screen
], True
);
278 move_mouse_pointer_to_screen(awesomeconf
->display
, new_screen
);
279 arrange(&awesomeconf
[prev_screen
- awesomeconf
->screen
]);
280 arrange(&awesomeconf
[new_screen
- awesomeconf
->screen
]);
282 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99