~ubuntu-branches/ubuntu/wily/xcb-util/wily

« back to all changes in this revision

Viewing changes to wm/xcbwm-test.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Danjou
  • Date: 2009-05-29 11:51:03 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090529115103-dl18nqybpcvw7uat
Tags: 0.3.5-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
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>
6
 
 *
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:
14
 
 *
15
 
 * The above copyright notice and this permission notice shall be
16
 
 * included in all copies or substantial portions of the Software.
17
 
 *
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.
25
 
 *
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.
30
 
 */
31
 
#include <pthread.h>
32
 
#include <string.h>
33
 
#include <stdlib.h>
34
 
#include <stdio.h>
35
 
#include <assert.h>
36
 
 
37
 
#include <xcb/xcb.h>
38
 
#include "reply_formats.h"
39
 
#include "xcb_aux.h"
40
 
#include "xcb_event.h"
41
 
#include "xcb_atom.h"
42
 
#include "xcb_icccm.h"
43
 
#include "xcb_wm.h"
44
 
 
45
 
static const int TOP = 20;
46
 
static const int LEFT = 5;
47
 
static const int BOTTOM = 5;
48
 
static const int RIGHT = 5;
49
 
 
50
 
static const int TEST_THREADS = 1;
51
 
static const int TEST_WATCH_ROOT = 1;
52
 
 
53
 
static int16_t move_from_x = -1;
54
 
static int16_t move_from_y = -1;
55
 
 
56
 
static int handleEvent(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e)
57
 
{
58
 
        return format_event(e);
59
 
}
60
 
 
61
 
static int handleButtonPressEvent(void *data, xcb_connection_t *c, xcb_button_press_event_t *e)
62
 
{
63
 
        if(move_from_x != -1 && move_from_y != -1)
64
 
        {
65
 
                printf("Weird. Got ButtonPress after ButtonPress.\n");
66
 
                return 0;
67
 
        }
68
 
        move_from_x = e->root_x;
69
 
        move_from_y = e->root_y;
70
 
        return 1;
71
 
}
72
 
 
73
 
static int handleButtonReleaseEvent(void *data, xcb_connection_t *c, xcb_button_release_event_t *e)
74
 
{
75
 
        uint32_t values[2];
76
 
        if(move_from_x == -1 && move_from_y == -1)
77
 
        {
78
 
                printf("Weird. Got ButtonRelease without ButtonPress.\n");
79
 
                return 0;
80
 
        }
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);
84
 
        xcb_flush(c);
85
 
        move_from_x = -1;
86
 
        move_from_y = -1;
87
 
        return 1;
88
 
}
89
 
 
90
 
static int addClientWindow(xcb_window_t child, xcb_window_t parent, xcb_gcontext_t titlegc)
91
 
{
92
 
        int success;
93
 
        client_window_t *record = malloc(sizeof(client_window_t));
94
 
        assert(record);
95
 
        record->child = child;
96
 
        record->parent = parent;
97
 
        record->name_len = 0;
98
 
        record->name = 0;
99
 
        record->titlegc = titlegc;
100
 
        success = table_put(byParent, parent, record) &&
101
 
                table_put(byChild, child, record);
102
 
        assert(success);
103
 
        return 1;
104
 
}
105
 
 
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)
109
 
{
110
 
        xcb_window_t w;
111
 
        xcb_drawable_t drawable;
112
 
        uint32_t mask = 0;
113
 
        uint32_t values[3];
114
 
        xcb_screen_t *root = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
115
 
        xcb_gcontext_t titlegc;
116
 
 
117
 
        w = xcb_generate_id(c);
118
 
 
119
 
        mask |= XCB_CW_BACK_PIXEL;
120
 
        values[0] = root->white_pixel;
121
 
 
122
 
        mask |= XCB_CW_OVERRIDE_REDIRECT;
123
 
        values[1] = 1;
124
 
 
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 */;
128
 
 
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);
135
 
 
136
 
        titlegc = xcb_generate_id(c);
137
 
 
138
 
        mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
139
 
        values[0] = root->black_pixel;
140
 
        values[1] = root->white_pixel;
141
 
        drawable = w;
142
 
        xcb_create_gc(c, titlegc, drawable, mask, values);
143
 
        addClientWindow(child, w, titlegc);
144
 
 
145
 
        xcb_reparent_window(c, child, w, LEFT - 1, TOP - 1);
146
 
 
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);
150
 
 
151
 
        xcb_flush(c);
152
 
}
153
 
 
154
 
static void redrawWindow(xcb_connection_t *c, client_window_t *client)
155
 
{
156
 
        xcb_drawable_t d = { client->parent };
157
 
        if(!client->name_len)
158
 
                return;
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);
162
 
        xcb_flush(c);
163
 
}
164
 
 
165
 
static int handleExposeEvent(void *data, xcb_connection_t *c, xcb_expose_event_t *e)
166
 
{
167
 
        client_window_t *client = table_get(byParent, e->window);
168
 
        if(!client || e->count != 0)
169
 
                return 1;
170
 
        redrawWindow(c, client);
171
 
        return 1;
172
 
}
173
 
 
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)
175
 
{
176
 
        client_window_t *client = table_get(byChild, window);
177
 
        printf("WM_NAME change: Window 0x%08x ", window);
178
 
        if(!client)
179
 
        {
180
 
                printf("is not being managed.\n");
181
 
                return 0;
182
 
        }
183
 
        if(client->name)
184
 
        {
185
 
                printf("was named \"%.*s\"; now ", client->name_len, client->name);
186
 
                free(client->name);
187
 
        }
188
 
        if(!prop)
189
 
        {
190
 
                client->name_len = 0;
191
 
                client->name = 0;
192
 
                printf("has no name.\n");
193
 
                return 1;
194
 
        }
195
 
 
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);
201
 
 
202
 
        redrawWindow(c, client);
203
 
        return 1;
204
 
}
205
 
 
206
 
int main(int argc, char **argv)
207
 
{
208
 
        xcb_connection_t *c;
209
 
        xcb_event_handlers_t evenths;
210
 
        xcb_property_handlers_t prophs;
211
 
        xcb_window_t root;
212
 
        pthread_t event_thread;
213
 
        int screen_nbr;
214
 
        int i;
215
 
 
216
 
        byChild = alloc_table();
217
 
        byParent = alloc_table();
218
 
 
219
 
        c = xcb_connect(NULL, &screen_nbr);
220
 
 
221
 
        xcb_event_handlers_init(c, &evenths);
222
 
 
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);
231
 
 
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);
235
 
 
236
 
        if(TEST_THREADS)
237
 
        {
238
 
                pthread_create(&event_thread, 0, (void *(*)(void *))xcb_event_wait_for_event_loop, &evenths);
239
 
        }
240
 
 
241
 
        root = xcb_aux_get_screen(c, screen_nbr)->root;
242
 
 
243
 
        {
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);
247
 
        }
248
 
        xcb_flush(c);
249
 
 
250
 
        manage_existing_windows(c, &prophs, root);
251
 
 
252
 
        /* Terminate only when the event loop terminates */
253
 
        if(TEST_THREADS)
254
 
                pthread_join(event_thread, 0);
255
 
        else
256
 
                xcb_event_wait_for_event_loop(&evenths);
257
 
 
258
 
        exit(0);
259
 
        /*NOTREACHED*/
260
 
}