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 orientation_t orientation
,
77 const xcolor_t
*fg
, const xcolor_t
*bg
)
79 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, phys_screen
);
80 uint32_t create_win_val
[3];
81 const uint32_t gc_mask
= XCB_GC_FOREGROUND
| XCB_GC_BACKGROUND
;
82 const uint32_t gc_values
[2] = { s
->black_pixel
, s
->white_pixel
};
84 sw
->geometry
.x
= geometry
.x
;
85 sw
->geometry
.y
= geometry
.y
;
86 sw
->geometry
.width
= geometry
.width
;
87 sw
->geometry
.height
= geometry
.height
;
88 sw
->border
.width
= border_width
;
90 /* The real protocol window. */
91 sw
->geometries
.internal
.x
= geometry
.x
;
92 sw
->geometries
.internal
.y
= geometry
.y
;
93 sw
->geometries
.internal
.width
= geometry
.width
;
94 sw
->geometries
.internal
.height
= geometry
.height
;
96 sw
->orientation
= orientation
;
100 create_win_val
[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE
;
101 create_win_val
[1] = 1;
102 create_win_val
[2] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
103 | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
| XCB_EVENT_MASK_ENTER_WINDOW
104 | XCB_EVENT_MASK_LEAVE_WINDOW
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
105 | XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE
106 | XCB_EVENT_MASK_POINTER_MOTION
| XCB_EVENT_MASK_EXPOSURE
;
108 sw
->window
= xcb_generate_id(globalconf
.connection
);
109 xcb_create_window(globalconf
.connection
, s
->root_depth
, sw
->window
, s
->root
,
110 sw
->geometries
.internal
.x
, sw
->geometries
.internal
.y
, sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
,
111 border_width
, XCB_COPY_FROM_PARENT
, s
->root_visual
,
112 XCB_CW_BACK_PIXMAP
| XCB_CW_OVERRIDE_REDIRECT
| XCB_CW_EVENT_MASK
,
115 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
116 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
,
117 sw
->geometries
.internal
.width
, sw
->geometries
.internal
.height
);
119 sw
->ctx
.phys_screen
= phys_screen
;
120 simplewindow_draw_context_update(sw
, s
);
122 /* The default GC is just a newly created associated to the root window */
123 sw
->gc
= xcb_generate_id(globalconf
.connection
);
124 xcb_create_gc(globalconf
.connection
, sw
->gc
, s
->root
, gc_mask
, gc_values
);
127 /** Destroy all resources of a simple window.
128 * \param sw The simple_window_t to wipe.
131 simplewindow_wipe(simple_window_t
*sw
)
135 xcb_destroy_window(globalconf
.connection
, sw
->window
);
136 sw
->window
= XCB_NONE
;
140 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
141 sw
->pixmap
= XCB_NONE
;
145 xcb_free_gc(globalconf
.connection
, sw
->gc
);
148 draw_context_wipe(&sw
->ctx
);
151 /** Move a simple window.
152 * \param sw The simple window to move.
153 * \param x New x coordinate.
154 * \param y New y coordinate.
157 simplewindow_move(simple_window_t
*sw
, int x
, int y
)
159 const uint32_t move_win_vals
[] = { x
, y
};
161 if(x
!= sw
->geometries
.internal
.x
|| y
!= sw
->geometries
.internal
.y
)
163 sw
->geometry
.x
= sw
->geometries
.internal
.x
= x
;
164 sw
->geometry
.y
= sw
->geometries
.internal
.y
= y
;
165 xcb_configure_window(globalconf
.connection
, sw
->window
,
166 XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
,
171 /** Resize a simple window.
172 * \param sw The simple_window_t to resize.
173 * \param w New width.
174 * \param h New height.
177 simplewindow_resize(simple_window_t
*sw
, int w
, int h
)
179 int iw
= w
- 2 * sw
->border
.width
;
180 int ih
= h
- 2 * sw
->border
.width
;
182 if(iw
> 0 && ih
> 0 &&
183 (sw
->geometries
.internal
.width
!= iw
|| sw
->geometries
.internal
.height
!= ih
))
185 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
186 uint32_t resize_win_vals
[2];
188 sw
->geometries
.internal
.width
= resize_win_vals
[0] = iw
;
189 sw
->geometries
.internal
.height
= resize_win_vals
[1] = ih
;
190 sw
->geometry
.width
= w
;
191 sw
->geometry
.height
= h
;
192 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
193 /* orientation != East */
194 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
195 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
196 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
197 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
, iw
, ih
);
198 xcb_configure_window(globalconf
.connection
, sw
->window
,
199 XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT
,
201 simplewindow_draw_context_update(sw
, s
);
205 /** Move and resize a window in one call.
206 * \param sw The simple window to move and resize.
207 * \param geom The new geometry.
210 simplewindow_moveresize(simple_window_t
*sw
, area_t geom
)
212 uint32_t moveresize_win_vals
[4], mask_vals
= 0;
213 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
215 area_t geom_internal
= geom
;
216 geom_internal
.width
-= 2 * sw
->border
.width
;
217 geom_internal
.height
-= 2* sw
->border
.width
;
219 if(sw
->geometries
.internal
.x
!= geom_internal
.x
|| sw
->geometries
.internal
.y
!= geom_internal
.y
)
221 sw
->geometries
.internal
.x
= moveresize_win_vals
[0] = geom_internal
.x
;
222 sw
->geometries
.internal
.y
= moveresize_win_vals
[1] = geom_internal
.y
;
223 mask_vals
|= XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y
;
226 if(sw
->geometry
.width
!= geom
.width
|| sw
->geometry
.height
!= geom
.height
)
230 sw
->geometries
.internal
.width
= moveresize_win_vals
[2] = geom_internal
.width
;
231 sw
->geometries
.internal
.height
= moveresize_win_vals
[3] = geom_internal
.height
;
235 sw
->geometries
.internal
.width
= moveresize_win_vals
[0] = geom_internal
.width
;
236 sw
->geometries
.internal
.height
= moveresize_win_vals
[1] = geom_internal
.height
;
238 mask_vals
|= XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT
;
239 xcb_free_pixmap(globalconf
.connection
, sw
->pixmap
);
240 /* orientation != East */
241 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
242 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
243 sw
->pixmap
= xcb_generate_id(globalconf
.connection
);
244 xcb_create_pixmap(globalconf
.connection
, s
->root_depth
, sw
->pixmap
, s
->root
, geom_internal
.width
, geom_internal
.height
);
245 simplewindow_draw_context_update(sw
, s
);
248 /* Also save geometry including border. */
251 xcb_configure_window(globalconf
.connection
, sw
->window
, mask_vals
, moveresize_win_vals
);
254 /** Refresh the window content by copying its pixmap data to its window.
255 * \param sw The simple window to refresh.
258 simplewindow_refresh_pixmap_partial(simple_window_t
*sw
,
259 int16_t x
, int16_t y
,
260 uint16_t w
, uint16_t h
)
262 xcb_copy_area(globalconf
.connection
, sw
->pixmap
,
263 sw
->window
, sw
->gc
, x
, y
, x
, y
,
267 /** Set a simple window border width.
268 * \param sw The simple window to change border width.
269 * \param border_width The border width in pixel.
272 simplewindow_border_width_set(simple_window_t
*sw
, uint32_t border_width
)
274 xcb_configure_window(globalconf
.connection
, sw
->window
, XCB_CONFIG_WINDOW_BORDER_WIDTH
,
276 sw
->border
.width
= border_width
;
279 /** Set a simple window border color.
280 * \param sw The simple window to change border width.
281 * \param color The border color.
284 simplewindow_border_color_set(simple_window_t
*sw
, const xcolor_t
*color
)
286 xcb_change_window_attributes(globalconf
.connection
, sw
->window
,
287 XCB_CW_BORDER_PIXEL
, &color
->pixel
);
288 sw
->border
.color
= *color
;
291 /** Set simple window orientation.
292 * \param sw The simple window.
293 * \param o The new orientation
296 simplewindow_orientation_set(simple_window_t
*sw
, orientation_t o
)
298 if(o
!= sw
->orientation
)
300 xcb_screen_t
*s
= xutil_screen_get(globalconf
.connection
, sw
->ctx
.phys_screen
);
302 /* orientation != East */
303 if(sw
->pixmap
!= sw
->ctx
.pixmap
)
304 xcb_free_pixmap(globalconf
.connection
, sw
->ctx
.pixmap
);
305 simplewindow_draw_context_update(sw
, s
);
309 /** Set simple window cursor.
310 * \param sw The simple window.
311 * \param c The cursor.
314 simplewindow_cursor_set(simple_window_t
*sw
, xcb_cursor_t c
)
318 const uint32_t change_win_vals
[] = { c
};
319 xcb_change_window_attributes(globalconf
.connection
, sw
->window
, XCB_CW_CURSOR
, change_win_vals
);
323 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80