2
* Copyright © 2008 Ian Osgood <iano@quirkster.com>
3
* Copyright © 2008 Jamey Sharp <jamey@minilop.net>
4
* Copyright © 2008 Josh Triplett <josh@freedesktop.org>
5
* Copyright © 2008 Julien Danjou <julien@danjou.info>
7
* Permission is hereby granted, free of charge, to any person
8
* obtaining a copy of this software and associated documentation
9
* files (the "Software"), to deal in the Software without
10
* restriction, including without limitation the rights to use, copy,
11
* modify, merge, publish, distribute, sublicense, and/or sell copies
12
* of the Software, and to permit persons to whom the Software is
13
* furnished to do so, subject to the following conditions:
15
* The above copyright notice and this permission notice shall be
16
* included in all copies or substantial portions of the Software.
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
22
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
* Except as contained in this notice, the names of the authors or
27
* their institutions shall not be used in advertising or otherwise to
28
* promote the sale, use or other dealings in this Software without
29
* prior written authorization from the authors.
38
#include "reply_formats.h"
40
#include "xcb_event.h"
42
#include "xcb_icccm.h"
45
static const int TOP = 20;
46
static const int LEFT = 5;
47
static const int BOTTOM = 5;
48
static const int RIGHT = 5;
50
static const int TEST_THREADS = 1;
51
static const int TEST_WATCH_ROOT = 1;
53
static int16_t move_from_x = -1;
54
static int16_t move_from_y = -1;
56
static int handleEvent(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e)
58
return format_event(e);
61
static int handleButtonPressEvent(void *data, xcb_connection_t *c, xcb_button_press_event_t *e)
63
if(move_from_x != -1 && move_from_y != -1)
65
printf("Weird. Got ButtonPress after ButtonPress.\n");
68
move_from_x = e->root_x;
69
move_from_y = e->root_y;
73
static int handleButtonReleaseEvent(void *data, xcb_connection_t *c, xcb_button_release_event_t *e)
76
if(move_from_x == -1 && move_from_y == -1)
78
printf("Weird. Got ButtonRelease without ButtonPress.\n");
81
values[0] = /* x */ e->root_x;
82
values[1] = /* y */ e->root_y;
83
xcb_configure_window(c, e->event, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
90
static int addClientWindow(xcb_window_t child, xcb_window_t parent, xcb_gcontext_t titlegc)
93
client_window_t *record = malloc(sizeof(client_window_t));
95
record->child = child;
96
record->parent = parent;
99
record->titlegc = titlegc;
100
success = table_put(byParent, parent, record) &&
101
table_put(byChild, child, record);
106
void reparent_window(xcb_connection_t *c, xcb_window_t child,
107
xcb_visualid_t v, xcb_window_t r, uint8_t d,
108
int16_t x, int16_t y, uint16_t width, uint16_t height)
111
xcb_drawable_t drawable;
114
xcb_screen_t *root = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
115
xcb_gcontext_t titlegc;
117
w = xcb_generate_id(c);
119
mask |= XCB_CW_BACK_PIXEL;
120
values[0] = root->white_pixel;
122
mask |= XCB_CW_OVERRIDE_REDIRECT;
125
mask |= XCB_CW_EVENT_MASK;
126
values[2] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
127
| XCB_EVENT_MASK_EXPOSURE /* | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW */;
129
printf("Reparenting 0x%08x under 0x%08x.\n", child, w);
130
xcb_create_window(c, d, w, r, x, y,
131
width + LEFT + RIGHT, height + TOP + BOTTOM,
132
/* border_width */ 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, v, mask, values);
133
xcb_change_save_set(c, XCB_SET_MODE_INSERT, child);
134
xcb_map_window(c, w);
136
titlegc = xcb_generate_id(c);
138
mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
139
values[0] = root->black_pixel;
140
values[1] = root->white_pixel;
142
xcb_create_gc(c, titlegc, drawable, mask, values);
143
addClientWindow(child, w, titlegc);
145
xcb_reparent_window(c, child, w, LEFT - 1, TOP - 1);
147
mask = XCB_CW_EVENT_MASK;
148
values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
149
xcb_change_window_attributes(c, child, mask, values);
154
static void redrawWindow(xcb_connection_t *c, client_window_t *client)
156
xcb_drawable_t d = { client->parent };
157
if(!client->name_len)
159
xcb_clear_area(c, 0, d, 0, 0, 0, 0);
160
xcb_image_text_8(c, client->name_len, d, client->titlegc,
161
LEFT - 1, TOP - 4, client->name);
165
static int handleExposeEvent(void *data, xcb_connection_t *c, xcb_expose_event_t *e)
167
client_window_t *client = table_get(byParent, e->window);
168
if(!client || e->count != 0)
170
redrawWindow(c, client);
174
static int handleWMNameChange(void *data, xcb_connection_t *c, uint8_t state, xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop)
176
client_window_t *client = table_get(byChild, window);
177
printf("WM_NAME change: Window 0x%08x ", window);
180
printf("is not being managed.\n");
185
printf("was named \"%.*s\"; now ", client->name_len, client->name);
190
client->name_len = 0;
192
printf("has no name.\n");
196
client->name_len = xcb_get_property_value_length(prop);
197
client->name = malloc(client->name_len);
198
assert(client->name);
199
strncpy(client->name, xcb_get_property_value(prop), client->name_len);
200
printf("is named \"%.*s\".\n", client->name_len, client->name);
202
redrawWindow(c, client);
206
int main(int argc, char **argv)
209
xcb_event_handlers_t evenths;
210
xcb_property_handlers_t prophs;
212
pthread_t event_thread;
216
byChild = alloc_table();
217
byParent = alloc_table();
219
c = xcb_connect(NULL, &screen_nbr);
221
xcb_event_handlers_init(c, &evenths);
223
for(i = 2; i < 128; ++i)
224
xcb_event_set_handler(&evenths, i, handleEvent, 0);
225
for(i = 0; i < 256; ++i)
226
xcb_event_set_error_handler(&evenths, i, (xcb_generic_error_handler_t) handleEvent, 0);
227
xcb_event_set_button_press_handler(&evenths, handleButtonPressEvent, 0);
228
xcb_event_set_button_release_handler(&evenths, handleButtonReleaseEvent, 0);
229
xcb_event_set_unmap_notify_handler(&evenths, handle_unmap_notify_event, 0);
230
xcb_event_set_expose_handler(&evenths, handleExposeEvent, 0);
232
xcb_property_handlers_init(&prophs, &evenths);
233
xcb_event_set_map_notify_handler(&evenths, handle_map_notify_event, &prophs);
234
xcb_watch_wm_name(&prophs, 40, handleWMNameChange, 0);
238
pthread_create(&event_thread, 0, (void *(*)(void *))xcb_event_wait_for_event_loop, &evenths);
241
root = xcb_aux_get_screen(c, screen_nbr)->root;
244
uint32_t mask = XCB_CW_EVENT_MASK;
245
uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE };
246
xcb_change_window_attributes(c, root, mask, values);
250
manage_existing_windows(c, &prophs, root);
252
/* Terminate only when the event loop terminates */
254
pthread_join(event_thread, 0);
256
xcb_event_wait_for_event_loop(&evenths);