blob: 93a912b052b8a5fd7f5ed2590c95b10870670c34 [file] [log] [blame]
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
Daniel Stonec228e232013-05-22 18:03:19 +030023#include "config.h"
Kristian Høgsberg380deee2012-05-21 17:12:41 -040024
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28#include <sys/socket.h>
29#include <sys/un.h>
30#include <fcntl.h>
31#include <errno.h>
32#include <unistd.h>
33#include <signal.h>
Tiago Vignatti90fada42012-07-16 12:02:08 -040034#include <X11/Xcursor/Xcursor.h>
Kristian Høgsberg380deee2012-05-21 17:12:41 -040035
36#include "xwayland.h"
37
38#include "../../shared/cairo-util.h"
39#include "../compositor.h"
40#include "xserver-server-protocol.h"
41#include "hash.h"
42
43struct motif_wm_hints {
44 uint32_t flags;
45 uint32_t functions;
46 uint32_t decorations;
47 int32_t input_mode;
48 uint32_t status;
49};
50
51#define MWM_HINTS_FUNCTIONS (1L << 0)
52#define MWM_HINTS_DECORATIONS (1L << 1)
53#define MWM_HINTS_INPUT_MODE (1L << 2)
54#define MWM_HINTS_STATUS (1L << 3)
55
56#define MWM_FUNC_ALL (1L << 0)
57#define MWM_FUNC_RESIZE (1L << 1)
58#define MWM_FUNC_MOVE (1L << 2)
59#define MWM_FUNC_MINIMIZE (1L << 3)
60#define MWM_FUNC_MAXIMIZE (1L << 4)
61#define MWM_FUNC_CLOSE (1L << 5)
62
63#define MWM_DECOR_ALL (1L << 0)
64#define MWM_DECOR_BORDER (1L << 1)
65#define MWM_DECOR_RESIZEH (1L << 2)
66#define MWM_DECOR_TITLE (1L << 3)
67#define MWM_DECOR_MENU (1L << 4)
68#define MWM_DECOR_MINIMIZE (1L << 5)
69#define MWM_DECOR_MAXIMIZE (1L << 6)
70
71#define MWM_INPUT_MODELESS 0
72#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
73#define MWM_INPUT_SYSTEM_MODAL 2
74#define MWM_INPUT_FULL_APPLICATION_MODAL 3
75#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
76
77#define MWM_TEAROFF_WINDOW (1L<<0)
78
79#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
80#define _NET_WM_MOVERESIZE_SIZE_TOP 1
81#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
82#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
83#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
84#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
85#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
86#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
87#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
88#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
89#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
90#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
91
MoD31700122013-06-11 19:58:55 -050092#define SEND_EVENT_MASK (0x80)
93#define EVENT_TYPE(event) ((event)->response_type & ~SEND_EVENT_MASK)
94
Kristian Høgsberg380deee2012-05-21 17:12:41 -040095struct weston_wm_window {
96 struct weston_wm *wm;
97 xcb_window_t id;
98 xcb_window_t frame_id;
99 cairo_surface_t *cairo_surface;
100 struct weston_surface *surface;
101 struct shell_surface *shsurf;
102 struct wl_listener surface_destroy_listener;
103 struct wl_event_source *repaint_source;
Kristian Høgsberga61ca062012-05-22 16:05:52 -0400104 struct wl_event_source *configure_source;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400105 int properties_dirty;
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +0300106 int pid;
107 char *machine;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400108 char *class;
109 char *name;
110 struct weston_wm_window *transient_for;
111 uint32_t protocols;
112 xcb_atom_t type;
113 int width, height;
114 int x, y;
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500115 int saved_width, saved_height;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400116 int decorate;
Tiago Vignatti771241e2012-06-04 20:01:45 +0300117 int override_redirect;
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500118 int fullscreen;
MoD384a11a2013-06-22 11:04:21 -0500119 int has_alpha;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400120};
121
122static struct weston_wm_window *
123get_wm_window(struct weston_surface *surface);
124
Kristian Høgsbergeaee7842012-05-22 10:04:20 -0400125static void
126weston_wm_window_schedule_repaint(struct weston_wm_window *window);
127
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400128static int __attribute__ ((format (printf, 1, 2)))
129wm_log(const char *fmt, ...)
130{
131#ifdef WM_DEBUG
132 int l;
133 va_list argp;
134
135 va_start(argp, fmt);
136 l = weston_vlog(fmt, argp);
137 va_end(argp);
138
139 return l;
140#else
141 return 0;
142#endif
143}
144
145static int __attribute__ ((format (printf, 1, 2)))
146wm_log_continue(const char *fmt, ...)
147{
148#ifdef WM_DEBUG
149 int l;
150 va_list argp;
151
152 va_start(argp, fmt);
153 l = weston_vlog_continue(fmt, argp);
154 va_end(argp);
155
156 return l;
157#else
158 return 0;
159#endif
160}
161
162
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400163const char *
164get_atom_name(xcb_connection_t *c, xcb_atom_t atom)
165{
166 xcb_get_atom_name_cookie_t cookie;
167 xcb_get_atom_name_reply_t *reply;
168 xcb_generic_error_t *e;
169 static char buffer[64];
170
171 if (atom == XCB_ATOM_NONE)
172 return "None";
173
174 cookie = xcb_get_atom_name (c, atom);
175 reply = xcb_get_atom_name_reply (c, cookie, &e);
MoD55375b92013-06-11 19:59:42 -0500176
177 if(reply) {
178 snprintf(buffer, sizeof buffer, "%.*s",
179 xcb_get_atom_name_name_length (reply),
180 xcb_get_atom_name_name (reply));
181 } else {
182 snprintf(buffer, sizeof buffer, "(atom %u)", atom);
183 }
184
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400185 free(reply);
186
187 return buffer;
188}
189
Tiago Vignatti90fada42012-07-16 12:02:08 -0400190static xcb_cursor_t
191xcb_cursor_image_load_cursor(struct weston_wm *wm, const XcursorImage *img)
192{
193 xcb_connection_t *c = wm->conn;
194 xcb_screen_iterator_t s = xcb_setup_roots_iterator(xcb_get_setup(c));
195 xcb_screen_t *screen = s.data;
196 xcb_gcontext_t gc;
197 xcb_pixmap_t pix;
198 xcb_render_picture_t pic;
199 xcb_cursor_t cursor;
200 int stride = img->width * 4;
201
202 pix = xcb_generate_id(c);
203 xcb_create_pixmap(c, 32, pix, screen->root, img->width, img->height);
204
205 pic = xcb_generate_id(c);
206 xcb_render_create_picture(c, pic, pix, wm->format_rgba.id, 0, 0);
207
208 gc = xcb_generate_id(c);
209 xcb_create_gc(c, gc, pix, 0, 0);
210
211 xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, pix, gc,
212 img->width, img->height, 0, 0, 0, 32,
213 stride * img->height, (uint8_t *) img->pixels);
214 xcb_free_gc(c, gc);
215
216 cursor = xcb_generate_id(c);
217 xcb_render_create_cursor(c, cursor, pic, img->xhot, img->yhot);
218
219 xcb_render_free_picture(c, pic);
220 xcb_free_pixmap(c, pix);
221
222 return cursor;
223}
224
225static xcb_cursor_t
226xcb_cursor_images_load_cursor(struct weston_wm *wm, const XcursorImages *images)
227{
228 /* TODO: treat animated cursors as well */
229 if (images->nimage != 1)
230 return -1;
231
232 return xcb_cursor_image_load_cursor(wm, images->images[0]);
233}
234
235static xcb_cursor_t
236xcb_cursor_library_load_cursor(struct weston_wm *wm, const char *file)
237{
238 xcb_cursor_t cursor;
239 XcursorImages *images;
240 char *v = NULL;
241 int size = 0;
242
243 if (!file)
244 return 0;
245
246 v = getenv ("XCURSOR_SIZE");
247 if (v)
248 size = atoi(v);
249
250 if (!size)
251 size = 32;
252
253 images = XcursorLibraryLoadImages (file, NULL, size);
Tiago Vignattiac78bb12012-09-28 16:29:46 +0300254 if (!images)
255 return -1;
256
Tiago Vignatti90fada42012-07-16 12:02:08 -0400257 cursor = xcb_cursor_images_load_cursor (wm, images);
258 XcursorImagesDestroy (images);
259
260 return cursor;
261}
262
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400263void
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400264dump_property(struct weston_wm *wm,
265 xcb_atom_t property, xcb_get_property_reply_t *reply)
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400266{
267 int32_t *incr_value;
268 const char *text_value, *name;
269 xcb_atom_t *atom_value;
270 int width, len;
271 uint32_t i;
272
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400273 width = wm_log_continue("%s: ", get_atom_name(wm->conn, property));
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400274 if (reply == NULL) {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400275 wm_log_continue("(no reply)\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400276 return;
277 }
278
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400279 width += wm_log_continue("%s/%d, length %d (value_len %d): ",
280 get_atom_name(wm->conn, reply->type),
281 reply->format,
282 xcb_get_property_value_length(reply),
283 reply->value_len);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400284
285 if (reply->type == wm->atom.incr) {
286 incr_value = xcb_get_property_value(reply);
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400287 wm_log_continue("%d\n", *incr_value);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400288 } else if (reply->type == wm->atom.utf8_string ||
289 reply->type == wm->atom.string) {
290 text_value = xcb_get_property_value(reply);
291 if (reply->value_len > 40)
292 len = 40;
293 else
294 len = reply->value_len;
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400295 wm_log_continue("\"%.*s\"\n", len, text_value);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400296 } else if (reply->type == XCB_ATOM_ATOM) {
297 atom_value = xcb_get_property_value(reply);
298 for (i = 0; i < reply->value_len; i++) {
299 name = get_atom_name(wm->conn, atom_value[i]);
300 if (width + strlen(name) + 2 > 78) {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400301 wm_log_continue("\n ");
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400302 width = 4;
303 } else if (i > 0) {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400304 width += wm_log_continue(", ");
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400305 }
306
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400307 width += wm_log_continue("%s", name);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400308 }
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400309 wm_log_continue("\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400310 } else {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400311 wm_log_continue("huh?\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400312 }
313}
314
Tiago Vignatti2d129f12012-11-30 17:19:59 -0200315static void
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400316read_and_dump_property(struct weston_wm *wm,
317 xcb_window_t window, xcb_atom_t property)
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400318{
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400319 xcb_get_property_reply_t *reply;
320 xcb_get_property_cookie_t cookie;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400321
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400322 cookie = xcb_get_property(wm->conn, 0, window,
323 property, XCB_ATOM_ANY, 0, 2048);
324 reply = xcb_get_property_reply(wm->conn, cookie, NULL);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400325
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400326 dump_property(wm, property, reply);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400327
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400328 free(reply);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400329}
330
331/* We reuse some predefined, but otherwise useles atoms */
332#define TYPE_WM_PROTOCOLS XCB_ATOM_CUT_BUFFER0
333#define TYPE_MOTIF_WM_HINTS XCB_ATOM_CUT_BUFFER1
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500334#define TYPE_NET_WM_STATE XCB_ATOM_CUT_BUFFER2
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400335
336static void
337weston_wm_window_read_properties(struct weston_wm_window *window)
338{
339 struct weston_wm *wm = window->wm;
340
341#define F(field) offsetof(struct weston_wm_window, field)
342 const struct {
343 xcb_atom_t atom;
344 xcb_atom_t type;
345 int offset;
346 } props[] = {
347 { XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, F(class) },
348 { XCB_ATOM_WM_NAME, XCB_ATOM_STRING, F(name) },
349 { XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, F(transient_for) },
350 { wm->atom.wm_protocols, TYPE_WM_PROTOCOLS, F(protocols) },
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500351 { wm->atom.net_wm_state, TYPE_NET_WM_STATE },
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400352 { wm->atom.net_wm_window_type, XCB_ATOM_ATOM, F(type) },
353 { wm->atom.net_wm_name, XCB_ATOM_STRING, F(name) },
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +0300354 { wm->atom.net_wm_pid, XCB_ATOM_CARDINAL, F(pid) },
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400355 { wm->atom.motif_wm_hints, TYPE_MOTIF_WM_HINTS, 0 },
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +0300356 { wm->atom.wm_client_machine, XCB_ATOM_WM_CLIENT_MACHINE, F(machine) },
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400357 };
358#undef F
359
360 xcb_get_property_cookie_t cookie[ARRAY_LENGTH(props)];
361 xcb_get_property_reply_t *reply;
362 void *p;
363 uint32_t *xid;
364 xcb_atom_t *atom;
365 uint32_t i;
366 struct motif_wm_hints *hints;
367
368 if (!window->properties_dirty)
369 return;
370 window->properties_dirty = 0;
371
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400372 for (i = 0; i < ARRAY_LENGTH(props); i++)
373 cookie[i] = xcb_get_property(wm->conn,
374 0, /* delete */
375 window->id,
376 props[i].atom,
377 XCB_ATOM_ANY, 0, 2048);
378
Tiago Vignatti2ea74d92012-07-20 23:09:53 +0300379 window->decorate = !window->override_redirect;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400380 for (i = 0; i < ARRAY_LENGTH(props); i++) {
381 reply = xcb_get_property_reply(wm->conn, cookie[i], NULL);
382 if (!reply)
383 /* Bad window, typically */
384 continue;
385 if (reply->type == XCB_ATOM_NONE) {
386 /* No such property */
387 free(reply);
388 continue;
389 }
390
391 p = ((char *) window + props[i].offset);
392
393 switch (props[i].type) {
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +0300394 case XCB_ATOM_WM_CLIENT_MACHINE:
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400395 case XCB_ATOM_STRING:
396 /* FIXME: We're using this for both string and
397 utf8_string */
398 if (*(char **) p)
399 free(*(char **) p);
400
401 *(char **) p =
402 strndup(xcb_get_property_value(reply),
403 xcb_get_property_value_length(reply));
404 break;
405 case XCB_ATOM_WINDOW:
406 xid = xcb_get_property_value(reply);
407 *(struct weston_wm_window **) p =
408 hash_table_lookup(wm->window_hash, *xid);
409 break;
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +0300410 case XCB_ATOM_CARDINAL:
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400411 case XCB_ATOM_ATOM:
412 atom = xcb_get_property_value(reply);
413 *(xcb_atom_t *) p = *atom;
414 break;
415 case TYPE_WM_PROTOCOLS:
416 break;
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500417 case TYPE_NET_WM_STATE:
418 window->fullscreen = 0;
419 atom = xcb_get_property_value(reply);
420 for (i = 0; i < reply->value_len; i++)
421 if (atom[i] == wm->atom.net_wm_state_fullscreen)
422 window->fullscreen = 1;
423 break;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400424 case TYPE_MOTIF_WM_HINTS:
425 hints = xcb_get_property_value(reply);
426 if (hints->flags & MWM_HINTS_DECORATIONS)
427 window->decorate = hints->decorations > 0;
428 break;
429 default:
430 break;
431 }
432 free(reply);
433 }
434}
435
436static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400437weston_wm_window_get_frame_size(struct weston_wm_window *window,
438 int *width, int *height)
439{
440 struct theme *t = window->wm->theme;
441
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500442 if (window->fullscreen) {
443 *width = window->width;
444 *height = window->height;
445 } else if (window->decorate) {
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400446 *width = window->width + (t->margin + t->width) * 2;
447 *height = window->height +
448 t->margin * 2 + t->width + t->titlebar_height;
449 } else {
450 *width = window->width + t->margin * 2;
451 *height = window->height + t->margin * 2;
452 }
453}
454
455static void
456weston_wm_window_get_child_position(struct weston_wm_window *window,
457 int *x, int *y)
458{
459 struct theme *t = window->wm->theme;
460
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500461 if (window->fullscreen) {
462 *x = 0;
463 *y = 0;
464 } else if (window->decorate) {
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400465 *x = t->margin + t->width;
466 *y = t->margin + t->titlebar_height;
467 } else {
468 *x = t->margin;
469 *y = t->margin;
470 }
471}
Kristian Høgsbergeaee7842012-05-22 10:04:20 -0400472
473static void
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500474weston_wm_window_send_configure_notify(struct weston_wm_window *window)
475{
476 xcb_configure_notify_event_t configure_notify;
477 struct weston_wm *wm = window->wm;
478 int x, y;
479
480 weston_wm_window_get_child_position(window, &x, &y);
481 configure_notify.response_type = XCB_CONFIGURE_NOTIFY;
482 configure_notify.pad0 = 0;
483 configure_notify.event = window->id;
484 configure_notify.window = window->id;
485 configure_notify.above_sibling = XCB_WINDOW_NONE;
486 configure_notify.x = x;
487 configure_notify.y = y;
488 configure_notify.width = window->width;
489 configure_notify.height = window->height;
490 configure_notify.border_width = 0;
491 configure_notify.override_redirect = 0;
492 configure_notify.pad1 = 0;
493
494 xcb_send_event(wm->conn, 0, window->id,
495 XCB_EVENT_MASK_STRUCTURE_NOTIFY,
496 (char *) &configure_notify);
497}
498
499static void
Kristian Høgsbergeaee7842012-05-22 10:04:20 -0400500weston_wm_handle_configure_request(struct weston_wm *wm, xcb_generic_event_t *event)
501{
502 xcb_configure_request_event_t *configure_request =
503 (xcb_configure_request_event_t *) event;
504 struct weston_wm_window *window;
505 uint32_t mask, values[16];
506 int x, y, width, height, i = 0;
507
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400508 wm_log("XCB_CONFIGURE_REQUEST (window %d) %d,%d @ %dx%d\n",
509 configure_request->window,
510 configure_request->x, configure_request->y,
511 configure_request->width, configure_request->height);
Kristian Høgsbergeaee7842012-05-22 10:04:20 -0400512
513 window = hash_table_lookup(wm->window_hash, configure_request->window);
514
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500515 if (window->fullscreen) {
516 weston_wm_window_send_configure_notify(window);
517 return;
518 }
519
Kristian Høgsbergeaee7842012-05-22 10:04:20 -0400520 if (configure_request->value_mask & XCB_CONFIG_WINDOW_WIDTH)
521 window->width = configure_request->width;
522 if (configure_request->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
523 window->height = configure_request->height;
524
525 weston_wm_window_get_child_position(window, &x, &y);
526 values[i++] = x;
527 values[i++] = y;
528 values[i++] = window->width;
529 values[i++] = window->height;
530 values[i++] = 0;
531 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
532 XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT |
533 XCB_CONFIG_WINDOW_BORDER_WIDTH;
534 if (configure_request->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
535 values[i++] = configure_request->sibling;
536 mask |= XCB_CONFIG_WINDOW_SIBLING;
537 }
538 if (configure_request->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
539 values[i++] = configure_request->stack_mode;
540 mask |= XCB_CONFIG_WINDOW_STACK_MODE;
541 }
542
543 xcb_configure_window(wm->conn, window->id, mask, values);
544
545 weston_wm_window_get_frame_size(window, &width, &height);
546 values[0] = width;
547 values[1] = height;
548 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
549 xcb_configure_window(wm->conn, window->frame_id, mask, values);
550
551 weston_wm_window_schedule_repaint(window);
552}
553
Kristian Høgsberg00db2ee2013-07-04 02:29:32 -0400554static int
555our_resource(struct weston_wm *wm, uint32_t id)
556{
557 const xcb_setup_t *setup;
558
559 setup = xcb_get_setup(wm->conn);
560
561 return (id & ~setup->resource_id_mask) == setup->resource_id_base;
562}
563
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400564static void
565weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *event)
566{
567 xcb_configure_notify_event_t *configure_notify =
568 (xcb_configure_notify_event_t *) event;
569 struct weston_wm_window *window;
Tiago Vignattie66fcee2012-07-20 23:09:54 +0300570 int x, y;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400571
Kristian Høgsberg00db2ee2013-07-04 02:29:32 -0400572 wm_log("XCB_CONFIGURE_NOTIFY (window %d) %d,%d @ %dx%d\n",
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400573 configure_notify->window,
574 configure_notify->x, configure_notify->y,
575 configure_notify->width, configure_notify->height);
Tiago Vignattie66fcee2012-07-20 23:09:54 +0300576
Kristian Høgsberg00db2ee2013-07-04 02:29:32 -0400577 window = hash_table_lookup(wm->window_hash, configure_notify->window);
Tiago Vignattie66fcee2012-07-20 23:09:54 +0300578 weston_wm_window_get_child_position(window, &x, &y);
Kristian Høgsberg122877d2013-08-22 16:18:17 -0700579 window->x = configure_notify->x;
580 window->y = configure_notify->y;
Kristian Høgsberg1b6fed42013-08-31 00:00:57 -0700581 if (window->override_redirect) {
582 window->width = configure_notify->width;
583 window->height = configure_notify->height;
584 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400585}
586
587static void
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +0300588weston_wm_kill_client(struct wl_listener *listener, void *data)
589{
590 struct weston_surface *surface = data;
591 struct weston_wm_window *window = get_wm_window(surface);
592 char name[1024];
593
594 if (!window)
595 return;
596
597 gethostname(name, 1024);
598
599 /* this is only one heuristic to guess the PID of a client is valid,
600 * assuming it's compliant with icccm and ewmh. Non-compliants and
601 * remote applications of course fail. */
602 if (!strcmp(window->machine, name) && window->pid != 0)
603 kill(window->pid, SIGKILL);
604}
605
606static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400607weston_wm_window_activate(struct wl_listener *listener, void *data)
608{
609 struct weston_surface *surface = data;
Giulio Camuffo9f42e502013-08-13 11:42:02 +0200610 struct weston_wm_window *window = NULL;
Scott Moreau85ecac02012-05-21 15:49:14 -0600611 struct weston_wm *wm =
612 container_of(listener, struct weston_wm, activate_listener);
613 xcb_client_message_event_t client_message;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400614
Giulio Camuffo9f42e502013-08-13 11:42:02 +0200615 if (surface) {
616 window = get_wm_window(surface);
617 }
618
Scott Moreau85ecac02012-05-21 15:49:14 -0600619 if (window) {
620 client_message.response_type = XCB_CLIENT_MESSAGE;
621 client_message.format = 32;
622 client_message.window = window->id;
623 client_message.type = wm->atom.wm_protocols;
624 client_message.data.data32[0] = wm->atom.wm_take_focus;
625 client_message.data.data32[1] = XCB_TIME_CURRENT_TIME;
626
627 xcb_send_event(wm->conn, 0, window->id,
628 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
629 (char *) &client_message);
630
631 xcb_set_input_focus (wm->conn, XCB_INPUT_FOCUS_POINTER_ROOT,
632 window->id, XCB_TIME_CURRENT_TIME);
633 } else {
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400634 xcb_set_input_focus (wm->conn,
635 XCB_INPUT_FOCUS_POINTER_ROOT,
636 XCB_NONE,
637 XCB_TIME_CURRENT_TIME);
Scott Moreau85ecac02012-05-21 15:49:14 -0600638 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400639
640 if (wm->focus_window)
641 weston_wm_window_schedule_repaint(wm->focus_window);
642 wm->focus_window = window;
643 if (wm->focus_window)
644 weston_wm_window_schedule_repaint(wm->focus_window);
645}
646
Tiago Vignattifb2adba2013-06-12 15:43:21 -0300647static void
648weston_wm_window_transform(struct wl_listener *listener, void *data)
649{
650 struct weston_surface *surface = data;
651 struct weston_wm_window *window = get_wm_window(surface);
652 struct weston_wm *wm =
653 container_of(listener, struct weston_wm, transform_listener);
Tiago Vignattifb2adba2013-06-12 15:43:21 -0300654 uint32_t mask, values[2];
Tiago Vignattifb2adba2013-06-12 15:43:21 -0300655
656 if (!window || !wm)
657 return;
658
659 if (!weston_surface_is_mapped(surface))
660 return;
661
Kristian Høgsberge89a8b62013-08-22 16:20:44 -0700662 if (window->x != surface->geometry.x ||
663 window->y != surface->geometry.y) {
664 values[0] = surface->geometry.x;
665 values[1] = surface->geometry.y;
666 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
Tiago Vignattifb2adba2013-06-12 15:43:21 -0300667
Kristian Høgsberge89a8b62013-08-22 16:20:44 -0700668 xcb_configure_window(wm->conn, window->frame_id, mask, values);
669 xcb_flush(wm->conn);
670 }
Tiago Vignattifb2adba2013-06-12 15:43:21 -0300671}
672
Kristian Høgsberga6d9a5e2012-05-30 12:15:44 -0400673#define ICCCM_WITHDRAWN_STATE 0
674#define ICCCM_NORMAL_STATE 1
675#define ICCCM_ICONIC_STATE 3
676
677static void
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500678weston_wm_window_set_wm_state(struct weston_wm_window *window, int32_t state)
Kristian Høgsberga6d9a5e2012-05-30 12:15:44 -0400679{
680 struct weston_wm *wm = window->wm;
681 uint32_t property[2];
682
683 property[0] = state;
684 property[1] = XCB_WINDOW_NONE;
685
686 xcb_change_property(wm->conn,
687 XCB_PROP_MODE_REPLACE,
688 window->id,
689 wm->atom.wm_state,
690 wm->atom.wm_state,
691 32, /* format */
692 2, property);
693}
694
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400695static void
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500696weston_wm_window_set_net_wm_state(struct weston_wm_window *window)
697{
698 struct weston_wm *wm = window->wm;
699 uint32_t property[1];
700 int i;
701
702 i = 0;
703 if (window->fullscreen)
704 property[i++] = wm->atom.net_wm_state_fullscreen;
705
706 xcb_change_property(wm->conn,
707 XCB_PROP_MODE_REPLACE,
708 window->id,
709 wm->atom.net_wm_state,
710 XCB_ATOM_ATOM,
711 32, /* format */
712 i, property);
713}
714
715static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400716weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event)
717{
718 xcb_map_request_event_t *map_request =
719 (xcb_map_request_event_t *) event;
720 struct weston_wm_window *window;
Kristian Høgsbergf9187192013-05-02 13:43:24 -0400721 uint32_t values[3];
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400722 int x, y, width, height;
723
724 if (our_resource(wm, map_request->window)) {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400725 wm_log("XCB_MAP_REQUEST (window %d, ours)\n",
726 map_request->window);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400727 return;
728 }
729
730 window = hash_table_lookup(wm->window_hash, map_request->window);
731
Kristian Høgsbergbc6e1622012-05-30 09:59:56 -0400732 if (window->frame_id)
733 return;
734
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400735 weston_wm_window_read_properties(window);
736
737 weston_wm_window_get_frame_size(window, &width, &height);
738 weston_wm_window_get_child_position(window, &x, &y);
739
Kristian Høgsbergf9187192013-05-02 13:43:24 -0400740 values[0] = wm->screen->black_pixel;
741 values[1] =
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400742 XCB_EVENT_MASK_KEY_PRESS |
743 XCB_EVENT_MASK_KEY_RELEASE |
744 XCB_EVENT_MASK_BUTTON_PRESS |
745 XCB_EVENT_MASK_BUTTON_RELEASE |
Tiago Vignatti236b48d2012-07-16 12:09:19 -0400746 XCB_EVENT_MASK_POINTER_MOTION |
747 XCB_EVENT_MASK_ENTER_WINDOW |
748 XCB_EVENT_MASK_LEAVE_WINDOW |
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400749 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
Kristian Høgsberg44c20132012-05-30 10:09:21 -0400750 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
Kristian Høgsbergf9187192013-05-02 13:43:24 -0400751 values[2] = wm->colormap;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400752
753 window->frame_id = xcb_generate_id(wm->conn);
754 xcb_create_window(wm->conn,
Kristian Høgsbergf9187192013-05-02 13:43:24 -0400755 32,
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400756 window->frame_id,
757 wm->screen->root,
758 0, 0,
759 width, height,
760 0,
761 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Kristian Høgsbergf9187192013-05-02 13:43:24 -0400762 wm->visual_id,
763 XCB_CW_BORDER_PIXEL |
764 XCB_CW_EVENT_MASK |
765 XCB_CW_COLORMAP, values);
766
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400767 xcb_reparent_window(wm->conn, window->id, window->frame_id, x, y);
768
769 values[0] = 0;
770 xcb_configure_window(wm->conn, window->id,
771 XCB_CONFIG_WINDOW_BORDER_WIDTH, values);
772
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400773 wm_log("XCB_MAP_REQUEST (window %d, %p, frame %d)\n",
774 window->id, window, window->frame_id);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400775
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500776 weston_wm_window_set_wm_state(window, ICCCM_NORMAL_STATE);
777 weston_wm_window_set_net_wm_state(window);
778
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400779 xcb_map_window(wm->conn, map_request->window);
780 xcb_map_window(wm->conn, window->frame_id);
781
782 window->cairo_surface =
783 cairo_xcb_surface_create_with_xrender_format(wm->conn,
784 wm->screen,
785 window->frame_id,
Kristian Høgsbergf9187192013-05-02 13:43:24 -0400786 &wm->format_rgba,
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400787 width, height);
788
789 hash_table_insert(wm->window_hash, window->frame_id, window);
790}
791
792static void
793weston_wm_handle_map_notify(struct weston_wm *wm, xcb_generic_event_t *event)
794{
795 xcb_map_notify_event_t *map_notify = (xcb_map_notify_event_t *) event;
796
797 if (our_resource(wm, map_notify->window)) {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400798 wm_log("XCB_MAP_NOTIFY (window %d, ours)\n",
799 map_notify->window);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400800 return;
801 }
802
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400803 wm_log("XCB_MAP_NOTIFY (window %d)\n", map_notify->window);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400804}
805
806static void
Kristian Høgsberg194ea542012-05-30 10:05:41 -0400807weston_wm_handle_unmap_notify(struct weston_wm *wm, xcb_generic_event_t *event)
808{
809 xcb_unmap_notify_event_t *unmap_notify =
810 (xcb_unmap_notify_event_t *) event;
811 struct weston_wm_window *window;
812
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400813 wm_log("XCB_UNMAP_NOTIFY (window %d, event %d%s)\n",
814 unmap_notify->window,
815 unmap_notify->event,
816 our_resource(wm, unmap_notify->window) ? ", ours" : "");
Kristian Høgsberg194ea542012-05-30 10:05:41 -0400817
818 if (our_resource(wm, unmap_notify->window))
819 return;
820
MoD31700122013-06-11 19:58:55 -0500821 if (unmap_notify->response_type & SEND_EVENT_MASK)
Kristian Høgsbergd64bdf42012-05-31 10:33:43 -0400822 /* We just ignore the ICCCM 4.1.4 synthetic unmap notify
823 * as it may come in after we've destroyed the window. */
Kristian Høgsbergf197e9f2012-05-30 11:46:29 -0400824 return;
Kristian Høgsbergf197e9f2012-05-30 11:46:29 -0400825
Kristian Høgsbergd64bdf42012-05-31 10:33:43 -0400826 window = hash_table_lookup(wm->window_hash, unmap_notify->window);
Kristian Høgsberg194ea542012-05-30 10:05:41 -0400827 if (window->repaint_source)
828 wl_event_source_remove(window->repaint_source);
829 if (window->cairo_surface)
830 cairo_surface_destroy(window->cairo_surface);
831
Kristian Høgsbergbe375b32012-06-05 11:46:08 -0400832 if (window->frame_id) {
833 xcb_reparent_window(wm->conn, window->id, wm->wm_window, 0, 0);
834 xcb_destroy_window(wm->conn, window->frame_id);
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500835 weston_wm_window_set_wm_state(window, ICCCM_WITHDRAWN_STATE);
Kristian Høgsbergbe375b32012-06-05 11:46:08 -0400836 hash_table_remove(wm->window_hash, window->frame_id);
837 window->frame_id = XCB_WINDOW_NONE;
838 }
Kristian Høgsberga6d9a5e2012-05-30 12:15:44 -0400839
Kristian Høgsberg194ea542012-05-30 10:05:41 -0400840 if (wm->focus_window == window)
841 wm->focus_window = NULL;
Kristian Høgsberg194ea542012-05-30 10:05:41 -0400842 if (window->surface)
843 wl_list_remove(&window->surface_destroy_listener.link);
844 window->surface = NULL;
845}
846
847static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400848weston_wm_window_draw_decoration(void *data)
849{
850 struct weston_wm_window *window = data;
851 struct weston_wm *wm = window->wm;
852 struct theme *t = wm->theme;
853 cairo_t *cr;
854 int x, y, width, height;
855 const char *title;
856 uint32_t flags = 0;
857
858 weston_wm_window_read_properties(window);
859
860 window->repaint_source = NULL;
861
862 weston_wm_window_get_frame_size(window, &width, &height);
863 weston_wm_window_get_child_position(window, &x, &y);
864
865 cairo_xcb_surface_set_size(window->cairo_surface, width, height);
866 cr = cairo_create(window->cairo_surface);
867
Kristian Høgsbergb810eb52013-02-12 20:07:05 -0500868 if (window->fullscreen) {
869 /* nothing */
870 } else if (window->decorate) {
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400871 if (wm->focus_window == window)
872 flags |= THEME_FRAME_ACTIVE;
873
874 if (window->name)
875 title = window->name;
876 else
877 title = "untitled";
878
879 theme_render_frame(t, cr, width, height, title, flags);
880 } else {
881 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
882 cairo_set_source_rgba(cr, 0, 0, 0, 0);
883 cairo_paint(cr);
884
885 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
886 cairo_set_source_rgba(cr, 0, 0, 0, 0.45);
887 tile_mask(cr, t->shadow, 2, 2, width + 8, height + 8, 64, 64);
888 }
889
890 cairo_destroy(cr);
891
892 if (window->surface) {
Scott Moreau76d8fc82012-11-22 15:35:13 -0700893 pixman_region32_fini(&window->surface->pending.opaque);
MoD384a11a2013-06-22 11:04:21 -0500894 if(window->has_alpha) {
895 pixman_region32_init(&window->surface->pending.opaque);
896 } else {
897 /* We leave an extra pixel around the X window area to
898 * make sure we don't sample from the undefined alpha
899 * channel when filtering. */
900 pixman_region32_init_rect(&window->surface->pending.opaque,
901 x - 1, y - 1,
902 window->width + 2,
903 window->height + 2);
904 }
Pekka Paalanenc3ce7382013-03-08 14:56:49 +0200905 weston_surface_geometry_dirty(window->surface);
Kristian Høgsbergd8b617d2013-02-14 21:56:32 -0500906 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400907
Kristian Høgsbergd8b617d2013-02-14 21:56:32 -0500908 if (window->surface && !window->fullscreen) {
Kristian Høgsberg81585e92013-02-14 22:01:58 -0500909 pixman_region32_fini(&window->surface->pending.input);
Kristian Høgsbergd8b617d2013-02-14 21:56:32 -0500910 pixman_region32_init_rect(&window->surface->pending.input,
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400911 t->margin, t->margin,
912 width - 2 * t->margin,
913 height - 2 * t->margin);
914 }
915}
916
917static void
918weston_wm_window_schedule_repaint(struct weston_wm_window *window)
919{
920 struct weston_wm *wm = window->wm;
Pekka Paalanen4f9c07b2012-09-03 16:48:41 +0300921 int width, height;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400922
Kristian Høgsbergc4063f32012-07-22 15:32:45 -0400923 if (window->frame_id == XCB_WINDOW_NONE) {
924 if (window->surface != NULL) {
Pekka Paalanen4f9c07b2012-09-03 16:48:41 +0300925 weston_wm_window_get_frame_size(window, &width, &height);
Scott Moreau76d8fc82012-11-22 15:35:13 -0700926 pixman_region32_fini(&window->surface->pending.opaque);
MoD384a11a2013-06-22 11:04:21 -0500927 if(window->has_alpha) {
928 pixman_region32_init(&window->surface->pending.opaque);
929 } else {
930 pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
931 width, height);
932 }
Pekka Paalanenc3ce7382013-03-08 14:56:49 +0200933 weston_surface_geometry_dirty(window->surface);
Kristian Høgsbergc4063f32012-07-22 15:32:45 -0400934 }
935 return;
936 }
937
938 if (window->repaint_source)
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400939 return;
940
941 window->repaint_source =
942 wl_event_loop_add_idle(wm->server->loop,
943 weston_wm_window_draw_decoration,
944 window);
945}
946
947static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400948weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *event)
949{
950 xcb_property_notify_event_t *property_notify =
951 (xcb_property_notify_event_t *) event;
952 struct weston_wm_window *window;
953
954 window = hash_table_lookup(wm->window_hash, property_notify->window);
Rob Bradfordaa521bd2013-01-10 19:48:57 +0000955 if (!window)
956 return;
957
958 window->properties_dirty = 1;
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400959
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400960 wm_log("XCB_PROPERTY_NOTIFY: window %d, ", property_notify->window);
Kristian Høgsberge244cb02012-05-30 11:34:35 -0400961 if (property_notify->state == XCB_PROPERTY_DELETE)
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400962 wm_log("deleted\n");
Kristian Høgsberge244cb02012-05-30 11:34:35 -0400963 else
964 read_and_dump_property(wm, property_notify->window,
965 property_notify->atom);
Kristian Høgsberg0273b572012-05-30 09:58:02 -0400966
967 if (property_notify->atom == wm->atom.net_wm_name ||
968 property_notify->atom == XCB_ATOM_WM_NAME)
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400969 weston_wm_window_schedule_repaint(window);
Kristian Høgsberg380deee2012-05-21 17:12:41 -0400970}
971
972static void
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400973weston_wm_window_create(struct weston_wm *wm,
Tiago Vignatti771241e2012-06-04 20:01:45 +0300974 xcb_window_t id, int width, int height, int override)
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400975{
976 struct weston_wm_window *window;
977 uint32_t values[1];
MoD384a11a2013-06-22 11:04:21 -0500978 xcb_get_geometry_cookie_t geometry_cookie;
979 xcb_get_geometry_reply_t *geometry_reply;
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400980
Peter Huttererf3d62272013-08-08 11:57:05 +1000981 window = zalloc(sizeof *window);
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400982 if (window == NULL) {
Kristian Høgsberg082d58c2013-06-18 01:00:27 -0400983 wm_log("failed to allocate window\n");
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400984 return;
985 }
986
MoD384a11a2013-06-22 11:04:21 -0500987 geometry_cookie = xcb_get_geometry(wm->conn, id);
988
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400989 values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
990 xcb_change_window_attributes(wm->conn, id, XCB_CW_EVENT_MASK, values);
991
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400992 window->wm = wm;
993 window->id = id;
994 window->properties_dirty = 1;
Tiago Vignatti771241e2012-06-04 20:01:45 +0300995 window->override_redirect = override;
Kristian Høgsberg029539b2012-05-30 11:28:24 -0400996 window->width = width;
997 window->height = height;
998
MoD384a11a2013-06-22 11:04:21 -0500999 geometry_reply = xcb_get_geometry_reply(wm->conn, geometry_cookie, NULL);
1000 /* technically we should use XRender and check the visual format's
1001 alpha_mask, but checking depth is simpler and works in all known cases */
1002 if(geometry_reply != NULL)
1003 window->has_alpha = geometry_reply->depth == 32;
1004 free(geometry_reply);
1005
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001006 hash_table_insert(wm->window_hash, id, window);
1007}
1008
1009static void
1010weston_wm_window_destroy(struct weston_wm_window *window)
1011{
1012 hash_table_remove(window->wm->window_hash, window->id);
1013 free(window);
1014}
1015
1016static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001017weston_wm_handle_create_notify(struct weston_wm *wm, xcb_generic_event_t *event)
1018{
1019 xcb_create_notify_event_t *create_notify =
1020 (xcb_create_notify_event_t *) event;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001021
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001022 wm_log("XCB_CREATE_NOTIFY (window %d, width %d, height %d%s%s)\n",
1023 create_notify->window,
1024 create_notify->width, create_notify->height,
1025 create_notify->override_redirect ? ", override" : "",
1026 our_resource(wm, create_notify->window) ? ", ours" : "");
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001027
1028 if (our_resource(wm, create_notify->window))
1029 return;
1030
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001031 weston_wm_window_create(wm, create_notify->window,
Tiago Vignatti771241e2012-06-04 20:01:45 +03001032 create_notify->width, create_notify->height,
1033 create_notify->override_redirect);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001034}
1035
1036static void
1037weston_wm_handle_destroy_notify(struct weston_wm *wm, xcb_generic_event_t *event)
1038{
1039 xcb_destroy_notify_event_t *destroy_notify =
1040 (xcb_destroy_notify_event_t *) event;
1041 struct weston_wm_window *window;
1042
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001043 wm_log("XCB_DESTROY_NOTIFY, win %d, event %d%s\n",
1044 destroy_notify->window,
1045 destroy_notify->event,
1046 our_resource(wm, destroy_notify->window) ? ", ours" : "");
Kristian Høgsberg194ea542012-05-30 10:05:41 -04001047
1048 if (our_resource(wm, destroy_notify->window))
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001049 return;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001050
1051 window = hash_table_lookup(wm->window_hash, destroy_notify->window);
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001052 weston_wm_window_destroy(window);
1053}
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001054
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001055static void
1056weston_wm_handle_reparent_notify(struct weston_wm *wm, xcb_generic_event_t *event)
1057{
1058 xcb_reparent_notify_event_t *reparent_notify =
1059 (xcb_reparent_notify_event_t *) event;
1060 struct weston_wm_window *window;
Kristian Høgsbergc9571fb2012-05-29 15:35:29 -04001061
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001062 wm_log("XCB_REPARENT_NOTIFY (window %d, parent %d, event %d)\n",
1063 reparent_notify->window,
1064 reparent_notify->parent,
1065 reparent_notify->event);
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001066
1067 if (reparent_notify->parent == wm->screen->root) {
Tiago Vignatti771241e2012-06-04 20:01:45 +03001068 weston_wm_window_create(wm, reparent_notify->window, 10, 10,
1069 reparent_notify->override_redirect);
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001070 } else if (!our_resource(wm, reparent_notify->parent)) {
1071 window = hash_table_lookup(wm->window_hash,
1072 reparent_notify->window);
1073 weston_wm_window_destroy(window);
1074 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001075}
1076
Kristian Høgsberg5ba31892012-08-10 10:06:59 -04001077struct weston_seat *
1078weston_wm_pick_seat(struct weston_wm *wm)
1079{
1080 return container_of(wm->server->compositor->seat_list.next,
1081 struct weston_seat, link);
1082}
1083
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001084static void
Kristian Høgsberge68fd102012-05-22 17:09:40 -04001085weston_wm_window_handle_moveresize(struct weston_wm_window *window,
1086 xcb_client_message_event_t *client_message)
1087{
1088 static const int map[] = {
1089 THEME_LOCATION_RESIZING_TOP_LEFT,
1090 THEME_LOCATION_RESIZING_TOP,
1091 THEME_LOCATION_RESIZING_TOP_RIGHT,
1092 THEME_LOCATION_RESIZING_RIGHT,
1093 THEME_LOCATION_RESIZING_BOTTOM_RIGHT,
1094 THEME_LOCATION_RESIZING_BOTTOM,
1095 THEME_LOCATION_RESIZING_BOTTOM_LEFT,
1096 THEME_LOCATION_RESIZING_LEFT
1097 };
1098
1099 struct weston_wm *wm = window->wm;
Kristian Høgsberg5ba31892012-08-10 10:06:59 -04001100 struct weston_seat *seat = weston_wm_pick_seat(wm);
Kristian Høgsberge68fd102012-05-22 17:09:40 -04001101 int detail;
1102 struct weston_shell_interface *shell_interface =
1103 &wm->server->compositor->shell_interface;
1104
Kristian Høgsberge3148752013-05-06 23:19:49 -04001105 if (seat->pointer->button_count != 1 ||
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -04001106 seat->pointer->focus != window->surface)
Kristian Høgsberge68fd102012-05-22 17:09:40 -04001107 return;
1108
1109 detail = client_message->data.data32[2];
1110 switch (detail) {
1111 case _NET_WM_MOVERESIZE_MOVE:
1112 shell_interface->move(window->shsurf, seat);
1113 break;
1114 case _NET_WM_MOVERESIZE_SIZE_TOPLEFT:
1115 case _NET_WM_MOVERESIZE_SIZE_TOP:
1116 case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT:
1117 case _NET_WM_MOVERESIZE_SIZE_RIGHT:
1118 case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT:
1119 case _NET_WM_MOVERESIZE_SIZE_BOTTOM:
1120 case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT:
1121 case _NET_WM_MOVERESIZE_SIZE_LEFT:
1122 shell_interface->resize(window->shsurf, seat, map[detail]);
1123 break;
1124 case _NET_WM_MOVERESIZE_CANCEL:
1125 break;
1126 }
1127}
1128
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001129#define _NET_WM_STATE_REMOVE 0
1130#define _NET_WM_STATE_ADD 1
1131#define _NET_WM_STATE_TOGGLE 2
1132
1133static int
1134update_state(int action, int *state)
1135{
1136 int new_state, changed;
1137
1138 switch (action) {
1139 case _NET_WM_STATE_REMOVE:
1140 new_state = 0;
1141 break;
1142 case _NET_WM_STATE_ADD:
1143 new_state = 1;
1144 break;
1145 case _NET_WM_STATE_TOGGLE:
1146 new_state = !*state;
1147 break;
1148 default:
1149 return 0;
1150 }
1151
1152 changed = (*state != new_state);
1153 *state = new_state;
1154
1155 return changed;
1156}
1157
1158static void
1159weston_wm_window_configure(void *data);
1160
1161static void
1162weston_wm_window_handle_state(struct weston_wm_window *window,
1163 xcb_client_message_event_t *client_message)
1164{
1165 struct weston_wm *wm = window->wm;
1166 struct weston_shell_interface *shell_interface =
1167 &wm->server->compositor->shell_interface;
1168 uint32_t action, property;
1169
1170 action = client_message->data.data32[0];
1171 property = client_message->data.data32[1];
1172
1173 if (property == wm->atom.net_wm_state_fullscreen &&
1174 update_state(action, &window->fullscreen)) {
1175 weston_wm_window_set_net_wm_state(window);
1176 if (window->fullscreen) {
1177 window->saved_width = window->width;
1178 window->saved_height = window->height;
Kristian Høgsberg762b1662013-02-21 20:18:37 -05001179
1180 if (window->shsurf)
1181 shell_interface->set_fullscreen(window->shsurf,
1182 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
1183 0, NULL);
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001184 } else {
1185 shell_interface->set_toplevel(window->shsurf);
1186 window->width = window->saved_width;
1187 window->height = window->saved_height;
1188 weston_wm_window_configure(window);
1189 }
1190 }
1191}
1192
Kristian Høgsberge68fd102012-05-22 17:09:40 -04001193static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001194weston_wm_handle_client_message(struct weston_wm *wm,
1195 xcb_generic_event_t *event)
1196{
1197 xcb_client_message_event_t *client_message =
1198 (xcb_client_message_event_t *) event;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001199 struct weston_wm_window *window;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001200
1201 window = hash_table_lookup(wm->window_hash, client_message->window);
1202
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001203 wm_log("XCB_CLIENT_MESSAGE (%s %d %d %d %d %d win %d)\n",
1204 get_atom_name(wm->conn, client_message->type),
1205 client_message->data.data32[0],
1206 client_message->data.data32[1],
1207 client_message->data.data32[2],
1208 client_message->data.data32[3],
1209 client_message->data.data32[4],
1210 client_message->window);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001211
Kristian Høgsberge68fd102012-05-22 17:09:40 -04001212 if (client_message->type == wm->atom.net_wm_moveresize)
1213 weston_wm_window_handle_moveresize(window, client_message);
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001214 else if (client_message->type == wm->atom.net_wm_state)
1215 weston_wm_window_handle_state(window, client_message);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001216}
1217
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001218enum cursor_type {
1219 XWM_CURSOR_TOP,
1220 XWM_CURSOR_BOTTOM,
1221 XWM_CURSOR_LEFT,
1222 XWM_CURSOR_RIGHT,
1223 XWM_CURSOR_TOP_LEFT,
1224 XWM_CURSOR_TOP_RIGHT,
1225 XWM_CURSOR_BOTTOM_LEFT,
1226 XWM_CURSOR_BOTTOM_RIGHT,
1227 XWM_CURSOR_LEFT_PTR,
1228};
1229
1230static const char *cursors[] = {
1231 "top_side",
1232 "bottom_side",
1233 "left_side",
1234 "right_side",
1235 "top_left_corner",
1236 "top_right_corner",
1237 "bottom_left_corner",
1238 "bottom_right_corner",
1239 "left_ptr"
1240};
1241
1242static void
1243weston_wm_create_cursors(struct weston_wm *wm)
1244{
1245 int i, count = ARRAY_LENGTH(cursors);
1246
1247 wm->cursors = malloc(count * sizeof(xcb_cursor_t));
1248 for (i = 0; i < count; i++) {
1249 wm->cursors[i] =
1250 xcb_cursor_library_load_cursor(wm, cursors[i]);
1251 }
1252
1253 wm->last_cursor = -1;
1254}
1255
1256static void
1257weston_wm_destroy_cursors(struct weston_wm *wm)
1258{
1259 uint8_t i;
1260
1261 for (i = 0; i < ARRAY_LENGTH(cursors); i++)
1262 xcb_free_cursor(wm->conn, wm->cursors[i]);
1263
1264 free(wm->cursors);
1265}
1266
1267static int
1268get_cursor_for_location(struct theme *t, int width, int height, int x, int y)
1269{
Scott Moreauc6a7e4b2012-09-28 02:45:06 -06001270 int location = theme_get_location(t, x, y, width, height, 0);
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001271
1272 switch (location) {
1273 case THEME_LOCATION_RESIZING_TOP:
1274 return XWM_CURSOR_TOP;
1275 case THEME_LOCATION_RESIZING_BOTTOM:
1276 return XWM_CURSOR_BOTTOM;
1277 case THEME_LOCATION_RESIZING_LEFT:
1278 return XWM_CURSOR_LEFT;
1279 case THEME_LOCATION_RESIZING_RIGHT:
1280 return XWM_CURSOR_RIGHT;
1281 case THEME_LOCATION_RESIZING_TOP_LEFT:
1282 return XWM_CURSOR_TOP_LEFT;
1283 case THEME_LOCATION_RESIZING_TOP_RIGHT:
1284 return XWM_CURSOR_TOP_RIGHT;
1285 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
1286 return XWM_CURSOR_BOTTOM_LEFT;
1287 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
1288 return XWM_CURSOR_BOTTOM_RIGHT;
1289 case THEME_LOCATION_EXTERIOR:
1290 case THEME_LOCATION_TITLEBAR:
1291 default:
1292 return XWM_CURSOR_LEFT_PTR;
1293 }
1294}
1295
1296static void
Tiago Vignattic1903232012-07-16 12:15:37 -04001297weston_wm_window_set_cursor(struct weston_wm *wm, xcb_window_t window_id,
1298 int cursor)
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001299{
1300 uint32_t cursor_value_list;
1301
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001302 if (wm->last_cursor == cursor)
1303 return;
1304
1305 wm->last_cursor = cursor;
1306
1307 cursor_value_list = wm->cursors[cursor];
Tiago Vignattic1903232012-07-16 12:15:37 -04001308 xcb_change_window_attributes (wm->conn, window_id,
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001309 XCB_CW_CURSOR, &cursor_value_list);
1310 xcb_flush(wm->conn);
1311}
1312
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001313static void
1314weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event)
1315{
1316 xcb_button_press_event_t *button = (xcb_button_press_event_t *) event;
1317 struct weston_shell_interface *shell_interface =
1318 &wm->server->compositor->shell_interface;
Kristian Høgsberg5ba31892012-08-10 10:06:59 -04001319 struct weston_seat *seat = weston_wm_pick_seat(wm);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001320 struct weston_wm_window *window;
Kristian Høgsbergf96e6c02012-05-22 16:38:53 -04001321 enum theme_location location;
1322 struct theme *t = wm->theme;
Kristian Høgsbergc1693f22012-05-22 16:56:23 -04001323 int width, height;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001324
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001325 wm_log("XCB_BUTTON_%s (detail %d)\n",
1326 button->response_type == XCB_BUTTON_PRESS ?
1327 "PRESS" : "RELEASE", button->detail);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001328
1329 window = hash_table_lookup(wm->window_hash, button->event);
Kristian Høgsbergc1693f22012-05-22 16:56:23 -04001330 weston_wm_window_get_frame_size(window, &width, &height);
1331
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001332 if (button->response_type == XCB_BUTTON_PRESS &&
Kristian Høgsbergf96e6c02012-05-22 16:38:53 -04001333 button->detail == 1) {
1334 location = theme_get_location(t,
1335 button->event_x,
1336 button->event_y,
Scott Moreauc6a7e4b2012-09-28 02:45:06 -06001337 width, height, 0);
Kristian Høgsbergf96e6c02012-05-22 16:38:53 -04001338
1339 switch (location) {
1340 case THEME_LOCATION_TITLEBAR:
Kristian Høgsberg5ba31892012-08-10 10:06:59 -04001341 shell_interface->move(window->shsurf, seat);
Kristian Høgsbergf96e6c02012-05-22 16:38:53 -04001342 break;
Kristian Høgsbergc1693f22012-05-22 16:56:23 -04001343 case THEME_LOCATION_RESIZING_TOP:
1344 case THEME_LOCATION_RESIZING_BOTTOM:
1345 case THEME_LOCATION_RESIZING_LEFT:
1346 case THEME_LOCATION_RESIZING_RIGHT:
1347 case THEME_LOCATION_RESIZING_TOP_LEFT:
1348 case THEME_LOCATION_RESIZING_TOP_RIGHT:
1349 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
1350 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
1351 shell_interface->resize(window->shsurf,
Kristian Høgsberg5ba31892012-08-10 10:06:59 -04001352 seat, location);
Kristian Høgsbergc1693f22012-05-22 16:56:23 -04001353 break;
Kristian Høgsbergf96e6c02012-05-22 16:38:53 -04001354 default:
1355 break;
1356 }
1357 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001358}
1359
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001360static void
1361weston_wm_handle_motion(struct weston_wm *wm, xcb_generic_event_t *event)
1362{
1363 xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *) event;
1364 struct weston_wm_window *window;
1365 int cursor, width, height;
1366
1367 window = hash_table_lookup(wm->window_hash, motion->event);
Tiago Vignatti9134b772012-07-20 19:41:12 +03001368 if (!window || !window->decorate)
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001369 return;
1370
1371 weston_wm_window_get_frame_size(window, &width, &height);
1372 cursor = get_cursor_for_location(wm->theme, width, height,
1373 motion->event_x, motion->event_y);
1374
Tiago Vignattic1903232012-07-16 12:15:37 -04001375 weston_wm_window_set_cursor(wm, window->frame_id, cursor);
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001376}
1377
1378static void
1379weston_wm_handle_enter(struct weston_wm *wm, xcb_generic_event_t *event)
1380{
1381 xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *) event;
1382 struct weston_wm_window *window;
1383 int cursor, width, height;
1384
1385 window = hash_table_lookup(wm->window_hash, enter->event);
Tiago Vignatti9134b772012-07-20 19:41:12 +03001386 if (!window || !window->decorate)
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001387 return;
1388
1389 weston_wm_window_get_frame_size(window, &width, &height);
1390 cursor = get_cursor_for_location(wm->theme, width, height,
1391 enter->event_x, enter->event_y);
1392
Tiago Vignattic1903232012-07-16 12:15:37 -04001393 weston_wm_window_set_cursor(wm, window->frame_id, cursor);
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001394}
1395
1396static void
1397weston_wm_handle_leave(struct weston_wm *wm, xcb_generic_event_t *event)
1398{
1399 xcb_leave_notify_event_t *leave = (xcb_leave_notify_event_t *) event;
1400 struct weston_wm_window *window;
1401
1402 window = hash_table_lookup(wm->window_hash, leave->event);
Tiago Vignatti9134b772012-07-20 19:41:12 +03001403 if (!window || !window->decorate)
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001404 return;
1405
Tiago Vignattic1903232012-07-16 12:15:37 -04001406 weston_wm_window_set_cursor(wm, window->frame_id, XWM_CURSOR_LEFT_PTR);
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001407}
1408
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001409static int
1410weston_wm_handle_event(int fd, uint32_t mask, void *data)
1411{
1412 struct weston_wm *wm = data;
1413 xcb_generic_event_t *event;
1414 int count = 0;
1415
1416 while (event = xcb_poll_for_event(wm->conn), event != NULL) {
1417 if (weston_wm_handle_selection_event(wm, event)) {
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001418 free(event);
1419 count++;
1420 continue;
1421 }
1422
MoD31700122013-06-11 19:58:55 -05001423 switch (EVENT_TYPE(event)) {
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001424 case XCB_BUTTON_PRESS:
1425 case XCB_BUTTON_RELEASE:
1426 weston_wm_handle_button(wm, event);
1427 break;
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001428 case XCB_ENTER_NOTIFY:
1429 weston_wm_handle_enter(wm, event);
1430 break;
1431 case XCB_LEAVE_NOTIFY:
1432 weston_wm_handle_leave(wm, event);
1433 break;
1434 case XCB_MOTION_NOTIFY:
1435 weston_wm_handle_motion(wm, event);
1436 break;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001437 case XCB_CREATE_NOTIFY:
1438 weston_wm_handle_create_notify(wm, event);
1439 break;
1440 case XCB_MAP_REQUEST:
1441 weston_wm_handle_map_request(wm, event);
1442 break;
1443 case XCB_MAP_NOTIFY:
1444 weston_wm_handle_map_notify(wm, event);
1445 break;
1446 case XCB_UNMAP_NOTIFY:
Kristian Høgsberg194ea542012-05-30 10:05:41 -04001447 weston_wm_handle_unmap_notify(wm, event);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001448 break;
Kristian Høgsberg029539b2012-05-30 11:28:24 -04001449 case XCB_REPARENT_NOTIFY:
1450 weston_wm_handle_reparent_notify(wm, event);
1451 break;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001452 case XCB_CONFIGURE_REQUEST:
1453 weston_wm_handle_configure_request(wm, event);
1454 break;
1455 case XCB_CONFIGURE_NOTIFY:
1456 weston_wm_handle_configure_notify(wm, event);
1457 break;
1458 case XCB_DESTROY_NOTIFY:
1459 weston_wm_handle_destroy_notify(wm, event);
1460 break;
1461 case XCB_MAPPING_NOTIFY:
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001462 wm_log("XCB_MAPPING_NOTIFY\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001463 break;
1464 case XCB_PROPERTY_NOTIFY:
1465 weston_wm_handle_property_notify(wm, event);
1466 break;
1467 case XCB_CLIENT_MESSAGE:
1468 weston_wm_handle_client_message(wm, event);
1469 break;
1470 }
1471
1472 free(event);
1473 count++;
1474 }
1475
1476 xcb_flush(wm->conn);
1477
1478 return count;
1479}
1480
1481static void
Kristian Høgsbergf9187192013-05-02 13:43:24 -04001482weston_wm_get_visual_and_colormap(struct weston_wm *wm)
1483{
1484 xcb_depth_iterator_t d_iter;
1485 xcb_visualtype_iterator_t vt_iter;
1486 xcb_visualtype_t *visualtype;
1487
1488 d_iter = xcb_screen_allowed_depths_iterator(wm->screen);
1489 visualtype = NULL;
1490 while (d_iter.rem > 0) {
1491 if (d_iter.data->depth == 32) {
1492 vt_iter = xcb_depth_visuals_iterator(d_iter.data);
1493 visualtype = vt_iter.data;
1494 break;
1495 }
1496
1497 xcb_depth_next(&d_iter);
1498 }
1499
1500 if (visualtype == NULL) {
1501 weston_log("no 32 bit visualtype\n");
1502 return;
1503 }
1504
1505 wm->visual_id = visualtype->visual_id;
1506 wm->colormap = xcb_generate_id(wm->conn);
1507 xcb_create_colormap(wm->conn, XCB_COLORMAP_ALLOC_NONE,
1508 wm->colormap, wm->screen->root, wm->visual_id);
1509}
1510
1511static void
Tiago Vignatti9c4ff832012-11-30 17:19:57 -02001512weston_wm_get_resources(struct weston_wm *wm)
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001513{
1514
1515#define F(field) offsetof(struct weston_wm, field)
1516
1517 static const struct { const char *name; int offset; } atoms[] = {
1518 { "WM_PROTOCOLS", F(atom.wm_protocols) },
1519 { "WM_TAKE_FOCUS", F(atom.wm_take_focus) },
1520 { "WM_DELETE_WINDOW", F(atom.wm_delete_window) },
Kristian Høgsberga6d9a5e2012-05-30 12:15:44 -04001521 { "WM_STATE", F(atom.wm_state) },
Kristian Høgsberg670b5d32012-06-04 11:00:40 -04001522 { "WM_S0", F(atom.wm_s0) },
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +03001523 { "WM_CLIENT_MACHINE", F(atom.wm_client_machine) },
Kristian Høgsberg69981d92013-08-21 22:14:58 -07001524 { "_NET_WM_CM_S0", F(atom.net_wm_cm_s0) },
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001525 { "_NET_WM_NAME", F(atom.net_wm_name) },
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +03001526 { "_NET_WM_PID", F(atom.net_wm_pid) },
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001527 { "_NET_WM_ICON", F(atom.net_wm_icon) },
1528 { "_NET_WM_STATE", F(atom.net_wm_state) },
1529 { "_NET_WM_STATE_FULLSCREEN", F(atom.net_wm_state_fullscreen) },
1530 { "_NET_WM_USER_TIME", F(atom.net_wm_user_time) },
1531 { "_NET_WM_ICON_NAME", F(atom.net_wm_icon_name) },
1532 { "_NET_WM_WINDOW_TYPE", F(atom.net_wm_window_type) },
1533
1534 { "_NET_WM_WINDOW_TYPE_DESKTOP", F(atom.net_wm_window_type_desktop) },
1535 { "_NET_WM_WINDOW_TYPE_DOCK", F(atom.net_wm_window_type_dock) },
1536 { "_NET_WM_WINDOW_TYPE_TOOLBAR", F(atom.net_wm_window_type_toolbar) },
1537 { "_NET_WM_WINDOW_TYPE_MENU", F(atom.net_wm_window_type_menu) },
1538 { "_NET_WM_WINDOW_TYPE_UTILITY", F(atom.net_wm_window_type_utility) },
1539 { "_NET_WM_WINDOW_TYPE_SPLASH", F(atom.net_wm_window_type_splash) },
1540 { "_NET_WM_WINDOW_TYPE_DIALOG", F(atom.net_wm_window_type_dialog) },
Tiago Vignattibf1e8662012-06-12 14:07:49 +03001541 { "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", F(atom.net_wm_window_type_dropdown) },
1542 { "_NET_WM_WINDOW_TYPE_POPUP_MENU", F(atom.net_wm_window_type_popup) },
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001543 { "_NET_WM_WINDOW_TYPE_TOOLTIP", F(atom.net_wm_window_type_tooltip) },
1544 { "_NET_WM_WINDOW_TYPE_NOTIFICATION", F(atom.net_wm_window_type_notification) },
1545 { "_NET_WM_WINDOW_TYPE_COMBO", F(atom.net_wm_window_type_combo) },
1546 { "_NET_WM_WINDOW_TYPE_DND", F(atom.net_wm_window_type_dnd) },
1547 { "_NET_WM_WINDOW_TYPE_NORMAL", F(atom.net_wm_window_type_normal) },
1548
1549 { "_NET_WM_MOVERESIZE", F(atom.net_wm_moveresize) },
1550 { "_NET_SUPPORTING_WM_CHECK",
1551 F(atom.net_supporting_wm_check) },
1552 { "_NET_SUPPORTED", F(atom.net_supported) },
1553 { "_MOTIF_WM_HINTS", F(atom.motif_wm_hints) },
1554 { "CLIPBOARD", F(atom.clipboard) },
Kristian Høgsbergcba022a2012-06-04 10:11:45 -04001555 { "CLIPBOARD_MANAGER", F(atom.clipboard_manager) },
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001556 { "TARGETS", F(atom.targets) },
1557 { "UTF8_STRING", F(atom.utf8_string) },
1558 { "_WL_SELECTION", F(atom.wl_selection) },
1559 { "INCR", F(atom.incr) },
1560 { "TIMESTAMP", F(atom.timestamp) },
1561 { "MULTIPLE", F(atom.multiple) },
1562 { "UTF8_STRING" , F(atom.utf8_string) },
1563 { "COMPOUND_TEXT", F(atom.compound_text) },
1564 { "TEXT", F(atom.text) },
1565 { "STRING", F(atom.string) },
1566 { "text/plain;charset=utf-8", F(atom.text_plain_utf8) },
1567 { "text/plain", F(atom.text_plain) },
1568 };
1569#undef F
1570
1571 xcb_xfixes_query_version_cookie_t xfixes_cookie;
1572 xcb_xfixes_query_version_reply_t *xfixes_reply;
1573 xcb_intern_atom_cookie_t cookies[ARRAY_LENGTH(atoms)];
1574 xcb_intern_atom_reply_t *reply;
1575 xcb_render_query_pict_formats_reply_t *formats_reply;
1576 xcb_render_query_pict_formats_cookie_t formats_cookie;
1577 xcb_render_pictforminfo_t *formats;
1578 uint32_t i;
1579
1580 xcb_prefetch_extension_data (wm->conn, &xcb_xfixes_id);
1581
1582 formats_cookie = xcb_render_query_pict_formats(wm->conn);
1583
1584 for (i = 0; i < ARRAY_LENGTH(atoms); i++)
1585 cookies[i] = xcb_intern_atom (wm->conn, 0,
1586 strlen(atoms[i].name),
1587 atoms[i].name);
1588
1589 for (i = 0; i < ARRAY_LENGTH(atoms); i++) {
1590 reply = xcb_intern_atom_reply (wm->conn, cookies[i], NULL);
1591 *(xcb_atom_t *) ((char *) wm + atoms[i].offset) = reply->atom;
1592 free(reply);
1593 }
1594
1595 wm->xfixes = xcb_get_extension_data(wm->conn, &xcb_xfixes_id);
1596 if (!wm->xfixes || !wm->xfixes->present)
Martin Minarik6d118362012-06-07 18:01:59 +02001597 weston_log("xfixes not available\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001598
1599 xfixes_cookie = xcb_xfixes_query_version(wm->conn,
1600 XCB_XFIXES_MAJOR_VERSION,
1601 XCB_XFIXES_MINOR_VERSION);
1602 xfixes_reply = xcb_xfixes_query_version_reply(wm->conn,
1603 xfixes_cookie, NULL);
1604
Martin Minarik6d118362012-06-07 18:01:59 +02001605 weston_log("xfixes version: %d.%d\n",
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001606 xfixes_reply->major_version, xfixes_reply->minor_version);
1607
1608 free(xfixes_reply);
1609
1610 formats_reply = xcb_render_query_pict_formats_reply(wm->conn,
1611 formats_cookie, 0);
1612 if (formats_reply == NULL)
1613 return;
1614
1615 formats = xcb_render_query_pict_formats_formats(formats_reply);
Kristian Høgsberge89cef32012-07-16 11:57:08 -04001616 for (i = 0; i < formats_reply->num_formats; i++) {
1617 if (formats[i].direct.red_mask != 0xff &&
1618 formats[i].direct.red_shift != 16)
1619 continue;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001620 if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT &&
1621 formats[i].depth == 24)
Kristian Høgsberge89cef32012-07-16 11:57:08 -04001622 wm->format_rgb = formats[i];
1623 if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT &&
1624 formats[i].depth == 32 &&
1625 formats[i].direct.alpha_mask == 0xff &&
1626 formats[i].direct.alpha_shift == 24)
1627 wm->format_rgba = formats[i];
1628 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001629
1630 free(formats_reply);
1631}
1632
1633static void
1634weston_wm_create_wm_window(struct weston_wm *wm)
1635{
1636 static const char name[] = "Weston WM";
1637
1638 wm->wm_window = xcb_generate_id(wm->conn);
1639 xcb_create_window(wm->conn,
1640 XCB_COPY_FROM_PARENT,
1641 wm->wm_window,
1642 wm->screen->root,
1643 0, 0,
1644 10, 10,
1645 0,
1646 XCB_WINDOW_CLASS_INPUT_OUTPUT,
1647 wm->screen->root_visual,
1648 0, NULL);
1649
1650 xcb_change_property(wm->conn,
1651 XCB_PROP_MODE_REPLACE,
1652 wm->wm_window,
1653 wm->atom.net_supporting_wm_check,
1654 XCB_ATOM_WINDOW,
1655 32, /* format */
1656 1, &wm->wm_window);
1657
1658 xcb_change_property(wm->conn,
1659 XCB_PROP_MODE_REPLACE,
1660 wm->wm_window,
1661 wm->atom.net_wm_name,
1662 wm->atom.utf8_string,
1663 8, /* format */
1664 strlen(name), name);
1665
1666 xcb_change_property(wm->conn,
1667 XCB_PROP_MODE_REPLACE,
1668 wm->screen->root,
1669 wm->atom.net_supporting_wm_check,
1670 XCB_ATOM_WINDOW,
1671 32, /* format */
1672 1, &wm->wm_window);
1673
Kristian Høgsberg670b5d32012-06-04 11:00:40 -04001674 /* Claim the WM_S0 selection even though we don't suport
1675 * the --replace functionality. */
1676 xcb_set_selection_owner(wm->conn,
1677 wm->wm_window,
1678 wm->atom.wm_s0,
1679 XCB_TIME_CURRENT_TIME);
Kristian Høgsberg69981d92013-08-21 22:14:58 -07001680
1681 xcb_set_selection_owner(wm->conn,
1682 wm->wm_window,
1683 wm->atom.net_wm_cm_s0,
1684 XCB_TIME_CURRENT_TIME);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001685}
1686
1687struct weston_wm *
1688weston_wm_create(struct weston_xserver *wxs)
1689{
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001690 struct weston_wm *wm;
1691 struct wl_event_loop *loop;
1692 xcb_screen_iterator_t s;
Kristian Høgsberg4dec0112012-06-03 09:18:06 -04001693 uint32_t values[1];
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001694 int sv[2];
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001695 xcb_atom_t supported[3];
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001696
Peter Huttererf3d62272013-08-08 11:57:05 +10001697 wm = zalloc(sizeof *wm);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001698 if (wm == NULL)
1699 return NULL;
1700
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001701 wm->server = wxs;
1702 wm->window_hash = hash_table_create();
1703 if (wm->window_hash == NULL) {
1704 free(wm);
1705 return NULL;
1706 }
1707
1708 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +02001709 weston_log("socketpair failed\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001710 hash_table_destroy(wm->window_hash);
1711 free(wm);
1712 return NULL;
1713 }
1714
1715 xserver_send_client(wxs->resource, sv[1]);
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001716 wl_client_flush(wl_resource_get_client(wxs->resource));
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001717 close(sv[1]);
1718
1719 /* xcb_connect_to_fd takes ownership of the fd. */
1720 wm->conn = xcb_connect_to_fd(sv[0], NULL);
1721 if (xcb_connection_has_error(wm->conn)) {
Martin Minarik6d118362012-06-07 18:01:59 +02001722 weston_log("xcb_connect_to_fd failed\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001723 close(sv[0]);
1724 hash_table_destroy(wm->window_hash);
1725 free(wm);
1726 return NULL;
1727 }
1728
1729 s = xcb_setup_roots_iterator(xcb_get_setup(wm->conn));
1730 wm->screen = s.data;
1731
1732 loop = wl_display_get_event_loop(wxs->wl_display);
1733 wm->source =
1734 wl_event_loop_add_fd(loop, sv[0],
1735 WL_EVENT_READABLE,
1736 weston_wm_handle_event, wm);
1737 wl_event_source_check(wm->source);
1738
Tiago Vignatti9c4ff832012-11-30 17:19:57 -02001739 weston_wm_get_resources(wm);
Kristian Høgsbergf9187192013-05-02 13:43:24 -04001740 weston_wm_get_visual_and_colormap(wm);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001741
1742 values[0] =
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001743 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
1744 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
1745 XCB_EVENT_MASK_PROPERTY_CHANGE;
1746 xcb_change_window_attributes(wm->conn, wm->screen->root,
1747 XCB_CW_EVENT_MASK, values);
1748 wm->theme = theme_create();
1749
1750 weston_wm_create_wm_window(wm);
1751
1752 supported[0] = wm->atom.net_wm_moveresize;
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001753 supported[1] = wm->atom.net_wm_state;
1754 supported[2] = wm->atom.net_wm_state_fullscreen;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001755 xcb_change_property(wm->conn,
1756 XCB_PROP_MODE_REPLACE,
1757 wm->screen->root,
1758 wm->atom.net_supported,
1759 XCB_ATOM_ATOM,
1760 32, /* format */
1761 ARRAY_LENGTH(supported), supported);
1762
Kristian Høgsberg4dec0112012-06-03 09:18:06 -04001763 weston_wm_selection_init(wm);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001764
1765 xcb_flush(wm->conn);
1766
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001767 wm->activate_listener.notify = weston_wm_window_activate;
1768 wl_signal_add(&wxs->compositor->activate_signal,
1769 &wm->activate_listener);
Tiago Vignattifb2adba2013-06-12 15:43:21 -03001770 wm->transform_listener.notify = weston_wm_window_transform;
1771 wl_signal_add(&wxs->compositor->transform_signal,
1772 &wm->transform_listener);
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +03001773 wm->kill_listener.notify = weston_wm_kill_client;
1774 wl_signal_add(&wxs->compositor->kill_signal,
1775 &wm->kill_listener);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001776
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001777 weston_wm_create_cursors(wm);
Tiago Vignattic1903232012-07-16 12:15:37 -04001778 weston_wm_window_set_cursor(wm, wm->screen->root, XWM_CURSOR_LEFT_PTR);
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001779
Martin Minarik6d118362012-06-07 18:01:59 +02001780 weston_log("created wm\n");
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001781
1782 return wm;
1783}
1784
1785void
1786weston_wm_destroy(struct weston_wm *wm)
1787{
1788 /* FIXME: Free windows in hash. */
1789 hash_table_destroy(wm->window_hash);
Tiago Vignatti236b48d2012-07-16 12:09:19 -04001790 weston_wm_destroy_cursors(wm);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001791 xcb_disconnect(wm->conn);
1792 wl_event_source_remove(wm->source);
1793 wl_list_remove(&wm->selection_listener.link);
1794 wl_list_remove(&wm->activate_listener.link);
Tiago Vignatti0d20d7c2012-09-27 17:48:37 +03001795 wl_list_remove(&wm->kill_listener.link);
Louis-Francis Ratté-Bouliannedce3dac2013-07-20 05:16:45 +01001796 wl_list_remove(&wm->transform_listener.link);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001797
1798 free(wm);
1799}
1800
1801static void
1802surface_destroy(struct wl_listener *listener, void *data)
1803{
1804 struct weston_wm_window *window =
1805 container_of(listener,
1806 struct weston_wm_window, surface_destroy_listener);
1807
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001808 wm_log("surface for xid %d destroyed\n", window->id);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001809}
1810
1811static struct weston_wm_window *
1812get_wm_window(struct weston_surface *surface)
1813{
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001814 struct wl_listener *listener;
1815
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001816 listener = wl_signal_get(&surface->destroy_signal, surface_destroy);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001817 if (listener)
1818 return container_of(listener, struct weston_wm_window,
1819 surface_destroy_listener);
1820
1821 return NULL;
1822}
1823
1824static void
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001825weston_wm_window_configure(void *data)
1826{
1827 struct weston_wm_window *window = data;
1828 struct weston_wm *wm = window->wm;
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001829 uint32_t values[4];
1830 int x, y, width, height;
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001831
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001832 weston_wm_window_get_child_position(window, &x, &y);
1833 values[0] = x;
1834 values[1] = y;
1835 values[2] = window->width;
1836 values[3] = window->height;
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001837 xcb_configure_window(wm->conn,
1838 window->id,
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001839 XCB_CONFIG_WINDOW_X |
1840 XCB_CONFIG_WINDOW_Y |
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001841 XCB_CONFIG_WINDOW_WIDTH |
1842 XCB_CONFIG_WINDOW_HEIGHT,
1843 values);
1844
1845 weston_wm_window_get_frame_size(window, &width, &height);
1846 values[0] = width;
1847 values[1] = height;
1848 xcb_configure_window(wm->conn,
1849 window->frame_id,
1850 XCB_CONFIG_WINDOW_WIDTH |
1851 XCB_CONFIG_WINDOW_HEIGHT,
1852 values);
1853
1854 window->configure_source = NULL;
1855
1856 weston_wm_window_schedule_repaint(window);
1857}
1858
1859static void
1860send_configure(struct weston_surface *surface,
1861 uint32_t edges, int32_t width, int32_t height)
1862{
1863 struct weston_wm_window *window = get_wm_window(surface);
1864 struct weston_wm *wm = window->wm;
1865 struct theme *t = window->wm->theme;
Kristian Høgsbergfa514b42013-07-08 15:00:25 -04001866 int vborder, hborder;
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001867
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001868 if (window->fullscreen) {
Kristian Høgsbergfa514b42013-07-08 15:00:25 -04001869 hborder = 0;
1870 vborder = 0;
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001871 } else if (window->decorate) {
Kristian Høgsbergfa514b42013-07-08 15:00:25 -04001872 hborder = 2 * (t->margin + t->width);
1873 vborder = 2 * t->margin + t->titlebar_height + t->width;
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001874 } else {
Kristian Høgsbergfa514b42013-07-08 15:00:25 -04001875 hborder = 2 * t->margin;
1876 vborder = 2 * t->margin;
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001877 }
1878
Kristian Høgsbergfa514b42013-07-08 15:00:25 -04001879 if (width > hborder)
1880 window->width = width - hborder;
1881 else
1882 window->width = 1;
1883
1884 if (height > vborder)
1885 window->height = height - vborder;
1886 else
1887 window->height = 1;
1888
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001889 if (window->configure_source)
1890 return;
1891
1892 window->configure_source =
1893 wl_event_loop_add_idle(wm->server->loop,
1894 weston_wm_window_configure, window);
1895}
1896
1897static const struct weston_shell_client shell_client = {
1898 send_configure
1899};
1900
1901static void
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001902xserver_map_shell_surface(struct weston_wm *wm,
1903 struct weston_wm_window *window)
1904{
1905 struct weston_shell_interface *shell_interface =
1906 &wm->server->compositor->shell_interface;
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001907
1908 if (!shell_interface->create_shell_surface)
1909 return;
1910
1911 window->shsurf =
1912 shell_interface->create_shell_surface(shell_interface->shell,
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001913 window->surface,
1914 &shell_client);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001915
Kristian Høgsbergb810eb52013-02-12 20:07:05 -05001916 if (window->fullscreen) {
1917 window->saved_width = window->width;
1918 window->saved_height = window->height;
1919 shell_interface->set_fullscreen(window->shsurf,
1920 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
1921 0, NULL);
1922 return;
1923 } else if (!window->override_redirect) {
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001924 shell_interface->set_toplevel(window->shsurf);
1925 return;
Tiago Vignattifb2adba2013-06-12 15:43:21 -03001926 } else {
1927 shell_interface->set_xwayland(window->shsurf,
Kristian Høgsberg146f5ba2013-08-22 16:24:15 -07001928 window->x,
1929 window->y,
Tiago Vignattifb2adba2013-06-12 15:43:21 -03001930 WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001931 }
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001932}
1933
1934static void
1935xserver_set_window_id(struct wl_client *client, struct wl_resource *resource,
1936 struct wl_resource *surface_resource, uint32_t id)
1937{
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001938 struct weston_xserver *wxs = wl_resource_get_user_data(resource);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001939 struct weston_wm *wm = wxs->wm;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001940 struct weston_surface *surface =
1941 wl_resource_get_user_data(surface_resource);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001942 struct weston_wm_window *window;
1943
1944 if (client != wxs->client)
1945 return;
1946
1947 window = hash_table_lookup(wm->window_hash, id);
1948 if (window == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02001949 weston_log("set_window_id for unknown window %d\n", id);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001950 return;
1951 }
1952
Kristian Høgsberg082d58c2013-06-18 01:00:27 -04001953 wm_log("set_window_id %d for surface %p\n", id, surface);
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001954
1955 weston_wm_window_read_properties(window);
1956
1957 window->surface = (struct weston_surface *) surface;
1958 window->surface_destroy_listener.notify = surface_destroy;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -05001959 wl_signal_add(&surface->destroy_signal,
Kristian Høgsberg380deee2012-05-21 17:12:41 -04001960 &window->surface_destroy_listener);
1961
1962 weston_wm_window_schedule_repaint(window);
1963 xserver_map_shell_surface(wm, window);
1964}
1965
1966const struct xserver_interface xserver_implementation = {
1967 xserver_set_window_id
1968};