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"
32 simplewindow_draw_context_update(simple_window_t
*sw
, xcb_screen_t
*s
)
34 xcolor_t fg
= sw
->ctx
.fg
, bg
= sw
->ctx
.bg
;
35 int phys_screen
= sw
->ctx
.phys_screen
;
37 draw_context_wipe(&sw
->ctx
);
39 /* update draw context */
40 switch(sw
->orientation
)
44 /* we need a new pixmap this way [ ] to render */
45 sw
->ctx
.pixmap
= xcb_generate_id(globalconf
.connection
);
46 xcb_create_pixmap(globalconf
.connection
,
48 sw
->ctx
.pixmap
, s
->root
,
49 sw
->geometries
.internal
.height
, sw
->geometries
.internal
.width
);
50 draw_context_init(&sw
->ctx
, phys_screen
,
51 sw
->geometries
.internal
.height
, sw
->geometries
.internal
.width
,
52 sw
->ctx
.pixmap
, &fg
, &bg
);
55 draw_context_init(&sw
->ctx
, phys_screen
,
56 sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
,
57 sw
->pixmap
, &fg
, &bg
);
62 /** Initialize a simple window.
63 * \param sw The simple window to initialize.
64 * \param phys_screen Physical screen number.
65 * \param geometry Window geometry.
66 * \param border_width Window border width.
67 * \param orientation The rendering orientation.
68 * \param bg Default foreground color.
69 * \param bg Default background color.
72 simplewindow_init(simple_window_t
*sw
,
75 uint16_t border_width
,
76 const xcolor_t
*border_color
,
77 orientation_t orientation
,
78 const xcolor_t
*fg
, const xcolor_t
*bg
)
80 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, phys_screen
);
81 uint32_t create_win_val
[4];
82 const uint32_t gc_mask
= XCB_GC_FOREGROUND
| XCB_GC_BACKGROUND
;
83 const uint32_t gc_values
[2] = { s
->black_pixel
, s
->white_pixel
};
85 sw
->geometry
.x
= geometry
.x
;
86 sw
->geometry
.y
= geometry
.y
;
87 sw
->geometry
.width
= geometry
.width
;
88 sw
->geometry
.height
= geometry
.height
;
89 sw
->border
.width
= border_width
;
91 /* The real protocol window. */
92 sw
->geometries
.internal
.x
= geometry
.x
;
93 sw
->geometries
.internal
.y
= geometry
.y
;
94 sw
->geometries
.internal
.width
= geometry
.width
;
95 sw
->geometries
.internal
.height
= geometry
.height
;
97 sw
->orientation
= orientation
;
100 sw
->border
.color
= *border_color
;
102 create_win_val
[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE
;
103 create_win_val
[1] = border_color
->pixel
;
104 create_win_val
[2] = 1;
105 create_win_val
[3] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
106 | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
| XCB_EVENT_MASK_ENTER_WINDOW
107 | XCB_EVENT_MASK_LEAVE_WINDOW
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
108 | XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE
109 | XCB_EVENT_MASK_POINTER_MOTION
| XCB_EVENT_MASK_EXPOSURE
110 | XCB_EVENT_MASK_PROPERTY_CHANGE
;
112 sw
->window
= xcb_generate_id(globalconf
.connection
);
113 xcb_create_window(globalconf
.connection
, s
->root_depth
, sw
->window
, s
->root
,
114 sw
->geometries
.internal
.x
, sw
->geometries
.internal
.y
, sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
,
115 border_width
, XCB_COPY_FROM_PARENT
, s
->root_visual
,
116 XCB_CW_BACK_PIXMAP
| XCB_CW_BORDER_PIXEL
| XCB_CW_OVERRIDE_REDIRECT
| XCB_CW_EVENT_MASK
,
119 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
120 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
,
121 sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
);
123 sw
->ctx
.phys_screen
= phys_screen
;
124 simplewindow_draw_context_update(sw
, s
);
126 /* The default GC is just a newly created associated to the root window */
127 sw
->gc
= xcb_generate_id(globalconf
.connection
);
128 xcb_create_gc(globalconf
.connection
, sw
->gc
, s
->root
, gc_mask
, gc_values
);
131 /** Destroy all resources of a simple window.
132 * \param sw The simple_window_t to wipe.
135 simplewindow_wipe(simple_window_t
*sw
)
139 xcb_destroy_window(globalconf
.connection
, sw
->window
);
140 sw
->window
= XCB_NONE
;
144 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
145 sw
->pixmap
= XCB_NONE
;
149 xcb_free_gc(globalconf
.connection
, sw
->gc
);
152 draw_context_wipe(&sw
->ctx
);
155 /** Move a simple window.
156 * \param sw The simple window to move.
157 * \param x New x coordinate.
158 * \param y New y coordinate.
161 simplewindow_move(simple_window_t
*sw
, int x
, int y
)
163 const uint32_t move_win_vals
[] = { x
, y
};
165 if(x
!= sw
->geometries
.internal
.x
|| y
!= sw
->geometries
.internal
.y
)
167 sw
->geometry
.x
= sw
->geometries
.internal
.x
= x
;
168 sw
->geometry
.y
= sw
->geometries
.internal
.y
= y
;
169 xcb_configure_window(globalconf
.connection
, sw
->window
,
170 XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
,
175 /** Resize a simple window.
176 * \param sw The simple_window_t to resize.
177 * \param w New width.
178 * \param h New height.
181 simplewindow_resize(simple_window_t
*sw
, int w
, int h
)
183 int iw
= w
- 2 * sw
->border
.width
;
184 int ih
= h
- 2 * sw
->border
.width
;
186 if(iw
> 0 && ih
> 0 &&
187 (sw
->geometries
.internal
.width
!= iw
|| sw
->geometries
.internal
.height
!= ih
))
189 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
190 uint32_t resize_win_vals
[2];
192 sw
->geometries
.internal
.width
= resize_win_vals
[0] = iw
;
193 sw
->geometries
.internal
.height
= resize_win_vals
[1] = ih
;
194 sw
->geometry
.width
= w
;
195 sw
->geometry
.height
= h
;
196 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
197 /* orientation != East */
198 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
199 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
200 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
201 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
, iw
, ih
);
202 xcb_configure_window(globalconf
.connection
, sw
->window
,
203 XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT
,
205 simplewindow_draw_context_update(sw
, s
);
209 /** Move and resize a window in one call.
210 * \param sw The simple window to move and resize.
211 * \param geom The new geometry.
214 simplewindow_moveresize(simple_window_t
*sw
, area_t geom
)
216 uint32_t moveresize_win_vals
[4], mask_vals
= 0;
217 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
219 area_t geom_internal
= geom
;
220 geom_internal
.width
-= 2 * sw
->border
.width
;
221 geom_internal
.height
-= 2* sw
->border
.width
;
223 if(sw
->geometries
.internal
.x
!= geom_internal
.x
|| sw
->geometries
.internal
.y
!= geom_internal
.y
)
225 sw
->geometries
.internal
.x
= moveresize_win_vals
[0] = geom_internal
.x
;
226 sw
->geometries
.internal
.y
= moveresize_win_vals
[1] = geom_internal
.y
;
227 mask_vals
|= XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
;
230 if(sw
->geometry
.width
!= geom
.width
|| sw
->geometry
.height
!= geom
.height
)
234 sw
->geometries
.internal
.width
= moveresize_win_vals
[2] = geom_internal
.width
;
235 sw
->geometries
.internal
.height
= moveresize_win_vals
[3] = geom_internal
.height
;
239 sw
->geometries
.internal
.width
= moveresize_win_vals
[0] = geom_internal
.width
;
240 sw
->geometries
.internal
.height
= moveresize_win_vals
[1] = geom_internal
.height
;
242 mask_vals
|= XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT
;
243 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
244 /* orientation != East */
245 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
246 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
247 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
248 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
, geom_internal
.width
, geom_internal
.height
);
249 simplewindow_draw_context_update(sw
, s
);
252 /* Also save geometry including border. */
255 xcb_configure_window(globalconf
.connection
, sw
->window
, mask_vals
, moveresize_win_vals
);
258 /** Refresh the window content by copying its pixmap data to its window.
259 * \param sw The simple window to refresh.
262 simplewindow_refresh_pixmap_partial(simple_window_t
*sw
,
263 int16_t x
, int16_t y
,
264 uint16_t w
, uint16_t h
)
266 xcb_copy_area(globalconf
.connection
, sw
->pixmap
,
267 sw
->window
, sw
->gc
, x
, y
, x
, y
,
271 /** Set a simple window border width.
272 * \param sw The simple window to change border width.
273 * \param border_width The border width in pixel.
276 simplewindow_border_width_set(simple_window_t
*sw
, uint32_t border_width
)
278 xcb_configure_window(globalconf
.connection
, sw
->window
, XCB_CONFIG_WINDOW_BORDER_WIDTH
,
280 sw
->border
.width
= border_width
;
283 /** Set a simple window border color.
284 * \param sw The simple window to change border width.
285 * \param color The border color.
288 simplewindow_border_color_set(simple_window_t
*sw
, const xcolor_t
*color
)
290 xcb_change_window_attributes(globalconf
.connection
, sw
->window
,
291 XCB_CW_BORDER_PIXEL
, &color
->pixel
);
292 sw
->border
.color
= *color
;
295 /** Set simple window orientation.
296 * \param sw The simple window.
297 * \param o The new orientation
300 simplewindow_orientation_set(simple_window_t
*sw
, orientation_t o
)
302 if(o
!= sw
->orientation
)
304 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
306 /* orientation != East */
307 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
308 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
309 simplewindow_draw_context_update(sw
, s
);
313 /** Set simple window cursor.
314 * \param sw The simple window.
315 * \param c The cursor.
318 simplewindow_cursor_set(simple_window_t
*sw
, xcb_cursor_t c
)
322 const uint32_t change_win_vals
[] = { c
};
323 xcb_change_window_attributes(globalconf
.connection
, sw
->window
, XCB_CW_CURSOR
, change_win_vals
);
327 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80