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.
29 #include "common/xutil.h"
31 extern awesome_t globalconf
;
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
)
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
,
50 sw
->ctx
.pixmap
, s
->root
,
51 sw
->geometry
.height
, sw
->geometries
.internal
.width
);
52 draw_context_init(&sw
->ctx
, phys_screen
,
53 sw
->geometry
.height
, sw
->geometries
.internal
.width
,
54 sw
->ctx
.pixmap
, &fg
, &bg
);
57 draw_context_init(&sw
->ctx
, phys_screen
,
58 sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
,
59 sw
->pixmap
, &fg
, &bg
);
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.
74 simplewindow_init(simple_window_t
*sw
,
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
;
92 /* The real protocol window. */
93 sw
->geometries
.internal
.x
= geometry
.x
;
94 sw
->geometries
.internal
.y
= geometry
.y
;
95 sw
->geometries
.internal
.width
= geometry
.width
- 2*border_width
;
96 sw
->geometries
.internal
.height
= geometry
.height
- 2*border_width
;
98 sw
->orientation
= orientation
;
102 create_win_val
[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE
;
103 create_win_val
[1] = 1;
104 create_win_val
[2] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
105 | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
| XCB_EVENT_MASK_ENTER_WINDOW
106 | XCB_EVENT_MASK_LEAVE_WINDOW
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
107 | XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE
108 | XCB_EVENT_MASK_POINTER_MOTION
| XCB_EVENT_MASK_EXPOSURE
;
110 sw
->window
= xcb_generate_id(globalconf
.connection
);
111 xcb_create_window(globalconf
.connection
, s
->root_depth
, sw
->window
, s
->root
,
112 sw
->geometries
.internal
.x
, sw
->geometries
.internal
.y
, sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
,
113 border_width
, XCB_COPY_FROM_PARENT
, s
->root_visual
,
114 XCB_CW_BACK_PIXMAP
| XCB_CW_OVERRIDE_REDIRECT
| XCB_CW_EVENT_MASK
,
117 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
118 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
,
119 sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
);
121 sw
->ctx
.phys_screen
= phys_screen
;
122 simplewindow_draw_context_update(sw
, s
);
124 /* The default GC is just a newly created associated to the root window */
125 sw
->gc
= xcb_generate_id(globalconf
.connection
);
126 xcb_create_gc(globalconf
.connection
, sw
->gc
, s
->root
, gc_mask
, gc_values
);
129 /** Destroy all resources of a simple window.
130 * \param sw The simple_window_t to wipe.
133 simplewindow_wipe(simple_window_t
*sw
)
137 xcb_destroy_window(globalconf
.connection
, sw
->window
);
138 sw
->window
= XCB_NONE
;
142 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
143 sw
->pixmap
= XCB_NONE
;
147 xcb_free_gc(globalconf
.connection
, sw
->gc
);
150 draw_context_wipe(&sw
->ctx
);
153 /** Move a simple window.
154 * \param sw The simple window to move.
155 * \param x New x coordinate.
156 * \param y New y coordinate.
159 simplewindow_move(simple_window_t
*sw
, int x
, int y
)
161 const uint32_t move_win_vals
[] = { x
, y
};
163 if(x
!= sw
->geometries
.internal
.x
|| y
!= sw
->geometries
.internal
.y
)
165 sw
->geometry
.x
= sw
->geometries
.internal
.x
= x
;
166 sw
->geometry
.y
= sw
->geometries
.internal
.y
= y
;
167 xcb_configure_window(globalconf
.connection
, sw
->window
,
168 XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
,
173 /** Resize a simple window.
174 * \param sw The simple_window_t to resize.
175 * \param w New width.
176 * \param h New height.
179 simplewindow_resize(simple_window_t
*sw
, int w
, int h
)
181 int iw
= w
- 2 * sw
->border
.width
;
182 int ih
= h
- 2 * sw
->border
.width
;
184 if(iw
> 0 && ih
> 0 &&
185 (sw
->geometries
.internal
.width
!= iw
|| sw
->geometries
.internal
.height
!= ih
))
187 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
188 uint32_t resize_win_vals
[2];
190 sw
->geometries
.internal
.width
= resize_win_vals
[0] = iw
;
191 sw
->geometries
.internal
.height
= resize_win_vals
[1] = ih
;
192 sw
->geometry
.width
= w
;
193 sw
->geometry
.height
= h
;
194 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
195 /* orientation != East */
196 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
197 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
198 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
199 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
, iw
, ih
);
200 xcb_configure_window(globalconf
.connection
, sw
->window
,
201 XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT
,
203 simplewindow_draw_context_update(sw
, s
);
207 /** Move and resize a window in one call.
208 * \param sw The simple window to move and resize.
209 * \param geom The new geometry.
212 simplewindow_moveresize(simple_window_t
*sw
, area_t geom
)
214 uint32_t moveresize_win_vals
[4], mask_vals
= 0;
215 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
217 area_t geom_internal
= geom
;
218 geom_internal
.width
-= 2 * sw
->border
.width
;
219 geom_internal
.height
-= 2* sw
->border
.width
;
221 if(sw
->geometries
.internal
.x
!= geom_internal
.x
|| sw
->geometries
.internal
.y
!= geom_internal
.y
)
223 sw
->geometries
.internal
.x
= moveresize_win_vals
[0] = geom_internal
.x
;
224 sw
->geometries
.internal
.y
= moveresize_win_vals
[1] = geom_internal
.y
;
225 mask_vals
|= XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
;
228 if(sw
->geometry
.width
!= geom
.width
|| sw
->geometry
.height
!= geom
.height
)
232 sw
->geometries
.internal
.width
= moveresize_win_vals
[2] = geom_internal
.width
;
233 sw
->geometries
.internal
.height
= moveresize_win_vals
[3] = geom_internal
.height
;
237 sw
->geometries
.internal
.width
= moveresize_win_vals
[0] = geom_internal
.width
;
238 sw
->geometries
.internal
.height
= moveresize_win_vals
[1] = geom_internal
.height
;
240 mask_vals
|= XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT
;
241 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
242 /* orientation != East */
243 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
244 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
245 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
246 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
, geom_internal
.width
, geom_internal
.height
);
247 simplewindow_draw_context_update(sw
, s
);
250 /* Also save geometry including border. */
253 xcb_configure_window(globalconf
.connection
, sw
->window
, mask_vals
, moveresize_win_vals
);
256 /** Refresh the window content by copying its pixmap data to its window.
257 * \param sw The simple window to refresh.
260 simplewindow_refresh_pixmap_partial(simple_window_t
*sw
,
261 int16_t x
, int16_t y
,
262 uint16_t w
, uint16_t h
)
264 xcb_copy_area(globalconf
.connection
, sw
->pixmap
,
265 sw
->window
, sw
->gc
, x
, y
, x
, y
,
269 /** Set a simple window border width.
270 * \param sw The simple window to change border width.
271 * \param border_width The border width in pixel.
274 simplewindow_border_width_set(simple_window_t
*sw
, uint32_t border_width
)
276 xcb_configure_window(globalconf
.connection
, sw
->window
, XCB_CONFIG_WINDOW_BORDER_WIDTH
,
278 sw
->border
.width
= border_width
;
281 /** Set a simple window border color.
282 * \param sw The simple window to change border width.
283 * \param color The border color.
286 simplewindow_border_color_set(simple_window_t
*sw
, const xcolor_t
*color
)
288 xcb_change_window_attributes(globalconf
.connection
, sw
->window
,
289 XCB_CW_BORDER_PIXEL
, &color
->pixel
);
290 sw
->border
.color
= *color
;
293 /** Set simple window orientation.
294 * \param sw The simple window.
295 * \param o The new orientation
298 simplewindow_orientation_set(simple_window_t
*sw
, orientation_t o
)
300 if(o
!= sw
->orientation
)
302 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
304 /* orientation != East */
305 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
306 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
307 simplewindow_draw_context_update(sw
, s
);
311 /** Set simple window cursor.
312 * \param sw The simple window.
313 * \param c The cursor.
316 simplewindow_cursor_set(simple_window_t
*sw
, xcb_cursor_t c
)
320 const uint32_t change_win_vals
[] = { c
};
321 xcb_change_window_attributes(globalconf
.connection
, sw
->window
, XCB_CW_CURSOR
, change_win_vals
);
325 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80