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
++)
56 if(statusbar
->position
== BarTop
57 || statusbar
->position
== BarBot
)
58 si
[i
].height
-= statusbar
->height
;
59 if(statusbar
->position
== BarTop
)
60 si
[i
].y_org
+= statusbar
->height
;
67 * \param disp Display ref
68 * \param screen Screen number
69 * \param statusbar the statusbar
70 * \return ScreenInfo struct pointer with all display info
73 get_display_info(Display
*disp
, int screen
, Statusbar
*statusbar
)
77 si
= p_new(ScreenInfo
, 1);
80 si
->y_org
= statusbar
&& statusbar
->position
== BarTop
? statusbar
->height
: 0;
81 si
->width
= DisplayWidth(disp
, screen
);
82 si
->height
= DisplayHeight(disp
, screen
) -
83 (statusbar
&& (statusbar
->position
== BarTop
|| statusbar
->position
== BarBot
) ? statusbar
->height
: 0);
88 /** Return the Xinerama screen number where the coordinates belongs to
89 * \param disp Display ref
90 * \param x x coordinate of the window
91 * \param y y coordinate of the window
92 * \return screen number or DefaultScreen of disp on no match
95 get_screen_bycoord(Display
*disp
, int x
, int y
)
100 /* don't waste our time */
101 if(!XineramaIsActive(disp
))
102 return DefaultScreen(disp
);
104 si
= get_screen_info(disp
, 0, NULL
);
106 for(i
= 0; i
< get_screen_count(disp
); i
++)
107 if((x
< 0 || (x
>= si
[i
].x_org
&& x
< si
[i
].x_org
+ si
[i
].width
))
108 && (y
< 0 || (y
>= si
[i
].y_org
&& y
< si
[i
].y_org
+ si
[i
].height
)))
115 return DefaultScreen(disp
);
118 /** Return the actual screen count
119 * \param disp Display ref
120 * \return the number of screen available
123 get_screen_count(Display
*disp
)
127 if(XineramaIsActive(disp
))
128 XineramaQueryScreens(disp
, &screen_number
);
130 return ScreenCount(disp
);
132 return screen_number
;
135 /** This returns the real X screen number for a logical
136 * screen if Xinerama is active.
137 * \param disp Display ref
138 * \param screen the logical screen
139 * \return the X screen
142 get_phys_screen(Display
*disp
, int screen
)
144 if(XineramaIsActive(disp
))
145 return DefaultScreen(disp
);
149 /** Move a client to a virtual screen
150 * \param c the client
151 * \param acf_new the awesome_config for the new screen
152 * \param doresize set to True if we also move the client to the new x_org and
153 * y_org of the new screen
156 move_client_to_screen(Client
*c
, awesome_config
*acf_new
, Bool doresize
)
158 int i
, old_screen
= c
->screen
;
160 c
->screen
= acf_new
->screen
;
162 p_realloc(&c
->tags
, acf_new
->ntags
);
163 for(i
= 0; i
< acf_new
->ntags
; i
++)
164 c
->tags
[i
] = acf_new
->tags
[i
].selected
;
166 if(doresize
&& old_screen
!= c
->screen
)
168 ScreenInfo
*si
, *si_old
;
170 si
= get_screen_info(c
->display
, c
->screen
, NULL
);
171 si_old
= get_screen_info(c
->display
, old_screen
, NULL
);
173 /* compute new coords in new screen */
174 c
->rx
= (c
->rx
- si_old
[old_screen
].x_org
) + si
[c
->screen
].x_org
;
175 c
->ry
= (c
->ry
- si_old
[old_screen
].y_org
) + si
[c
->screen
].y_org
;
176 /* check that new coords are still in the screen */
177 if(c
->rw
> si
[c
->screen
].width
)
178 c
->rw
= si
[c
->screen
].width
;
179 if(c
->rh
> si
[c
->screen
].height
)
180 c
->rh
= si
[c
->screen
].height
;
181 if(c
->rx
+ c
->rw
>= si
[c
->screen
].x_org
+ si
[c
->screen
].width
)
182 c
->rx
= si
[c
->screen
].x_org
+ si
[c
->screen
].width
- c
->rw
- 2 * c
->border
;
183 if(c
->ry
+ c
->rh
>= si
[c
->screen
].y_org
+ si
[c
->screen
].height
)
184 c
->ry
= si
[c
->screen
].y_org
+ si
[c
->screen
].height
- c
->rh
- 2 * c
->border
;
186 client_resize(c
, c
->rx
, c
->ry
, c
->rw
, c
->rh
, acf_new
, True
, False
);
192 focus(c
, True
, acf_new
);
194 /* redraw statusbar on all screens */
195 drawstatusbar(&acf_new
[old_screen
- acf_new
->screen
]);
196 drawstatusbar(acf_new
);
199 /** Move mouse pointer to x_org and y_xorg of specified screen
200 * \param disp display ref
201 * \param screen screen number
204 move_mouse_pointer_to_screen(Display
*disp
, int screen
)
206 if(XineramaIsActive(disp
))
208 ScreenInfo
*si
= get_screen_info(disp
, screen
, NULL
);
209 XWarpPointer(disp
, None
, DefaultRootWindow(disp
), 0, 0, 0, 0, si
[screen
].x_org
, si
[screen
].y_org
);
213 XWarpPointer(disp
, None
, RootWindow(disp
, screen
), 0, 0, 0, 0, 0, 0);
217 uicb_focusnextscreen(awesome_config
* awesomeconf
,
218 const char *arg
__attribute__ ((unused
)))
221 int next_screen
= awesomeconf
->screen
+ 1 >= get_screen_count(awesomeconf
->display
) ? 0 : awesomeconf
->screen
+ 1;
223 for(c
= *awesomeconf
->clients
; c
&& !isvisible(c
, next_screen
, awesomeconf
[next_screen
- awesomeconf
->screen
].tags
, awesomeconf
[next_screen
- awesomeconf
->screen
].ntags
); c
= c
->next
);
226 focus(c
, True
, &awesomeconf
[next_screen
- awesomeconf
->screen
]);
227 restack(&awesomeconf
[next_screen
- awesomeconf
->screen
]);
229 move_mouse_pointer_to_screen(awesomeconf
->display
, next_screen
);
233 uicb_focusprevscreen(awesome_config
* awesomeconf
,
234 const char *arg
__attribute__ ((unused
)))
237 int prev_screen
= awesomeconf
->screen
- 1 < 0 ? get_screen_count(awesomeconf
->display
) - 1 : awesomeconf
->screen
- 1;
239 for(c
= *awesomeconf
->clients
; c
&& !isvisible(c
, prev_screen
, awesomeconf
[prev_screen
- awesomeconf
->screen
].tags
, awesomeconf
[prev_screen
- awesomeconf
->screen
].ntags
); c
= c
->next
);
242 focus(c
, True
, &awesomeconf
[prev_screen
- awesomeconf
->screen
]);
243 restack(&awesomeconf
[prev_screen
- awesomeconf
->screen
]);
245 move_mouse_pointer_to_screen(awesomeconf
->display
, prev_screen
);
248 /** Move client to a virtual screen (if Xinerama is active)
249 * \param awesomeconf awesome config
250 * \param arg screen number
251 * \ingroup ui_callback
254 uicb_movetoscreen(awesome_config
* awesomeconf
,
257 int new_screen
, prev_screen
;
258 Client
*sel
= get_current_tag(awesomeconf
->tags
, awesomeconf
->ntags
)->client_sel
;
260 if(!sel
|| !XineramaIsActive(awesomeconf
->display
))
264 new_screen
= compute_new_value_from_arg(arg
, sel
->screen
);
266 new_screen
= sel
->screen
+ 1;
268 if(new_screen
>= get_screen_count(awesomeconf
->display
))
270 else if(new_screen
< 0)
271 new_screen
= get_screen_count(awesomeconf
->display
) - 1;
273 prev_screen
= sel
->screen
;
274 move_client_to_screen(sel
, &awesomeconf
[new_screen
- awesomeconf
->screen
], True
);
275 move_mouse_pointer_to_screen(awesomeconf
->display
, new_screen
);
276 arrange(&awesomeconf
[prev_screen
- awesomeconf
->screen
]);
277 arrange(&awesomeconf
[new_screen
- awesomeconf
->screen
]);
279 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99