mouse buttons are now configurable for click on tag names
[awesome.git] / screen.c
blob1715a5becced6a97393931fa91e41a5288bc8dcf
1 /*
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.
22 #include "util.h"
23 #include "screen.h"
24 #include "tag.h"
25 #include "layout.h"
26 #include "statusbar.h"
28 /** Get screens info
29 * \param disp Display ref
30 * \param screen Screen number
31 * \param statusbar statusbar
32 * \return ScreenInfo struct array with all screens info
34 ScreenInfo *
35 get_screen_info(Display *disp, int screen, Statusbar *statusbar)
37 int i, screen_number = 0;
38 ScreenInfo *si;
40 if(XineramaIsActive(disp))
41 si = XineramaQueryScreens(disp, &screen_number);
42 else
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);
48 si[screen].x_org = 0;
49 si[screen].y_org = 0;
50 screen_number = screen + 1;
53 if(statusbar)
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;
63 return si;
66 /** Get display info
67 * \param disp Display ref
68 * \param screen Screen number
69 * \param statusbar the statusbar
70 * \return ScreenInfo struct pointer with all display info
72 ScreenInfo *
73 get_display_info(Display *disp, int screen, Statusbar *statusbar)
75 ScreenInfo *si;
77 si = p_new(ScreenInfo, 1);
79 si->x_org = 0;
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);
85 return si;
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
94 int
95 get_screen_bycoord(Display *disp, int x, int y)
97 ScreenInfo *si;
98 int i;
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)))
110 p_delete(&si);
111 return i;
114 p_delete(&si);
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)
125 int screen_number;
127 if(XineramaIsActive(disp))
128 XineramaQueryScreens(disp, &screen_number);
129 else
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);
146 return screen;
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
155 void
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);
188 p_delete(&si);
189 p_delete(&si_old);
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
203 static void
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);
210 p_delete(&si);
212 else
213 XWarpPointer(disp, None, RootWindow(disp, screen), 0, 0, 0, 0, 0, 0);
216 void
217 uicb_focusnextscreen(awesome_config * awesomeconf,
218 const char *arg __attribute__ ((unused)))
220 Client *c;
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);
224 if(c)
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);
232 void
233 uicb_focusprevscreen(awesome_config * awesomeconf,
234 const char *arg __attribute__ ((unused)))
236 Client *c;
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);
240 if(c)
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
253 void
254 uicb_movetoscreen(awesome_config * awesomeconf,
255 const char *arg)
257 int new_screen, prev_screen;
258 Client *sel = get_current_tag(awesomeconf->tags, awesomeconf->ntags)->client_sel;
260 if(!sel || !XineramaIsActive(awesomeconf->display))
261 return;
263 if(arg)
264 new_screen = compute_new_value_from_arg(arg, sel->screen);
265 else
266 new_screen = sel->screen + 1;
268 if(new_screen >= get_screen_count(awesomeconf->display))
269 new_screen = 0;
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