awful.menu: prevent menus from poping outside the work area
[awesome.git] / swindow.c
blobc1926ce7bce608449490ac20d36ea3178c689d03
1 /*
2 * swindow.c - simple window handling functions
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 <math.h>
24 #include <xcb/xcb.h>
26 #include "structs.h"
27 #include "swindow.h"
28 #include "draw.h"
29 #include "common/xutil.h"
31 extern awesome_t globalconf;
33 static void
34 simplewindow_draw_context_update(simple_window_t *sw, xcb_screen_t *s)
36 xcolor_t fg = sw->ctx.fg, bg = sw->ctx.bg;
37 int phys_screen = sw->ctx.phys_screen;
39 draw_context_wipe(&sw->ctx);
41 /* update draw context */
42 switch(sw->orientation)
44 case South:
45 case North:
46 /* we need a new pixmap this way [ ] to render */
47 sw->ctx.pixmap = xcb_generate_id(globalconf.connection);
48 xcb_create_pixmap(globalconf.connection,
49 s->root_depth,
50 sw->ctx.pixmap, s->root,
51 sw->geometry.height, sw->geometry.width);
52 draw_context_init(&sw->ctx, phys_screen,
53 sw->geometry.height, sw->geometry.width,
54 sw->ctx.pixmap, &fg, &bg);
55 break;
56 case East:
57 draw_context_init(&sw->ctx, phys_screen,
58 sw->geometry.width, sw->geometry.height,
59 sw->pixmap, &fg, &bg);
60 break;
64 /** Initialize a simple window.
65 * \param sw The simple window to initialize.
66 * \param phys_screen Physical screen number.
67 * \param geometry Window geometry.
68 * \param border_width Window border width.
69 * \param orientation The rendering orientation.
70 * \param bg Default foreground color.
71 * \param bg Default background color.
73 void
74 simplewindow_init(simple_window_t *sw,
75 int phys_screen,
76 area_t geometry,
77 uint16_t border_width,
78 orientation_t orientation,
79 const xcolor_t *fg, const xcolor_t *bg)
81 xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
82 uint32_t create_win_val[3];
83 const uint32_t gc_mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
84 const uint32_t gc_values[2] = { s->black_pixel, s->white_pixel };
86 sw->geometry.x = geometry.x;
87 sw->geometry.y = geometry.y;
88 sw->geometry.width = geometry.width;
89 sw->geometry.height = geometry.height;
90 sw->border.width = border_width;
91 sw->orientation = orientation;
92 sw->ctx.fg = *fg;
93 sw->ctx.bg = *bg;
95 create_win_val[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE;
96 create_win_val[1] = 1;
97 create_win_val[2] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
98 | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW
99 | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY
100 | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
101 | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE;
103 sw->window = xcb_generate_id(globalconf.connection);
104 xcb_create_window(globalconf.connection, s->root_depth, sw->window, s->root,
105 geometry.x, geometry.y, geometry.width, geometry.height,
106 border_width, XCB_COPY_FROM_PARENT, s->root_visual,
107 XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
108 create_win_val);
110 sw->pixmap = xcb_generate_id(globalconf.connection);
111 xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root,
112 geometry.width, geometry.height);
114 simplewindow_draw_context_update(sw, s);
116 /* The default GC is just a newly created associated to the root window */
117 sw->gc = xcb_generate_id(globalconf.connection);
118 xcb_create_gc(globalconf.connection, sw->gc, s->root, gc_mask, gc_values);
121 /** Destroy all resources of a simple window.
122 * \param sw The simple_window_t to wipe.
124 void
125 simplewindow_wipe(simple_window_t *sw)
127 if(sw->window)
129 xcb_destroy_window(globalconf.connection, sw->window);
130 sw->window = XCB_NONE;
132 if(sw->pixmap)
134 xcb_free_pixmap(globalconf.connection, sw->pixmap);
135 sw->pixmap = XCB_NONE;
137 if(sw->gc)
139 xcb_free_gc(globalconf.connection, sw->gc);
140 sw->gc = XCB_NONE;
142 draw_context_wipe(&sw->ctx);
145 /** Move a simple window.
146 * \param sw The simple window to move.
147 * \param x New x coordinate.
148 * \param y New y coordinate.
150 void
151 simplewindow_move(simple_window_t *sw, int x, int y)
153 const uint32_t move_win_vals[] = { x, y };
155 if(x != sw->geometry.x || y != sw->geometry.y)
157 sw->geometry.x = x;
158 sw->geometry.y = y;
159 xcb_configure_window(globalconf.connection, sw->window,
160 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
161 move_win_vals);
165 /** Resize a simple window.
166 * \param sw The simple_window_t to resize.
167 * \param w New width.
168 * \param h New height.
170 void
171 simplewindow_resize(simple_window_t *sw, int w, int h)
173 if(w > 0 && h > 0 && (sw->geometry.width != w || sw->geometry.height != h))
175 xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
176 uint32_t resize_win_vals[2];
178 sw->geometry.width = resize_win_vals[0] = w;
179 sw->geometry.height = resize_win_vals[1] = h;
180 xcb_free_pixmap(globalconf.connection, sw->pixmap);
181 /* orientation != East */
182 if(sw->pixmap != sw->ctx.pixmap)
183 xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
184 sw->pixmap = xcb_generate_id(globalconf.connection);
185 xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, w, h);
186 xcb_configure_window(globalconf.connection, sw->window,
187 XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
188 resize_win_vals);
189 simplewindow_draw_context_update(sw, s);
193 /** Move and resize a window in one call.
194 * \param sw The simple window to move and resize.
195 * \param geom The new gometry.
197 void
198 simplewindow_moveresize(simple_window_t *sw, area_t geom)
200 uint32_t moveresize_win_vals[4], mask_vals = 0;
201 xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
203 if(sw->geometry.x != geom.x || sw->geometry.y != geom.y)
205 sw->geometry.x = moveresize_win_vals[0] = geom.x;
206 sw->geometry.y = moveresize_win_vals[1] = geom.y;
207 mask_vals |= XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
210 if(sw->geometry.width != geom.width || sw->geometry.height != geom.height)
212 if(mask_vals)
214 sw->geometry.width = moveresize_win_vals[2] = geom.width;
215 sw->geometry.height = moveresize_win_vals[3] = geom.height;
217 else
219 sw->geometry.width = moveresize_win_vals[0] = geom.width;
220 sw->geometry.height = moveresize_win_vals[1] = geom.height;
222 mask_vals |= XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
223 xcb_free_pixmap(globalconf.connection, sw->pixmap);
224 /* orientation != East */
225 if(sw->pixmap != sw->ctx.pixmap)
226 xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
227 sw->pixmap = xcb_generate_id(globalconf.connection);
228 xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, geom.width, geom.height);
229 simplewindow_draw_context_update(sw, s);
232 xcb_configure_window(globalconf.connection, sw->window, mask_vals, moveresize_win_vals);
235 /** Refresh the window content by copying its pixmap data to its window.
236 * \param sw The simple window to refresh.
238 void
239 simplewindow_refresh_pixmap_partial(simple_window_t *sw,
240 int16_t x, int16_t y,
241 uint16_t w, uint16_t h)
243 xcb_copy_area(globalconf.connection, sw->pixmap,
244 sw->window, sw->gc, x, y, x, y,
245 w, h);
248 /** Set a simple window border width.
249 * \param sw The simple window to change border width.
250 * \param border_width The border width in pixel.
252 void
253 simplewindow_border_width_set(simple_window_t *sw, uint32_t border_width)
255 xcb_configure_window(globalconf.connection, sw->window, XCB_CONFIG_WINDOW_BORDER_WIDTH,
256 &border_width);
257 sw->border.width = border_width;
260 /** Set a simple window border color.
261 * \param sw The simple window to change border width.
262 * \param color The border color.
264 void
265 simplewindow_border_color_set(simple_window_t *sw, const xcolor_t *color)
267 xcb_change_window_attributes(globalconf.connection, sw->window,
268 XCB_CW_BORDER_PIXEL, &color->pixel);
269 sw->border.color = *color;
272 /** Set simple window orientation.
273 * \param sw The simple window.
274 * \param o The new orientation
276 void
277 simplewindow_orientation_set(simple_window_t *sw, orientation_t o)
279 if(o != sw->orientation)
281 xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
282 sw->orientation = o;
283 /* orientation != East */
284 if(sw->pixmap != sw->ctx.pixmap)
285 xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
286 simplewindow_draw_context_update(sw, s);
290 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80