1 /*
2  * Copyright © 2011-2014 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of the
9  * copyright holders not be used in advertising or publicity
10  * pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no
12  * representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  */
25 
26 #include "xwayland.h"
27 
28 #include <stdio.h>
29 
30 #include <X11/Xatom.h>
31 #include <selection.h>
32 #include <micmap.h>
33 #include <misyncshm.h>
34 #include <compositeext.h>
35 #include <compint.h>
36 #include <glx_extinit.h>
37 #include <os.h>
38 #include <xserver_poll.h>
39 #include <propertyst.h>
40 
41 #ifdef XF86VIDMODE
42 #include <X11/extensions/xf86vmproto.h>
43 extern _X_EXPORT Bool noXFree86VidModeExtension;
44 #endif
45 
46 #ifdef XWL_HAS_GLAMOR
47 #include <glamor.h>
48 #endif
49 
50 void
ddxGiveUp(enum ExitCode error)51 ddxGiveUp(enum ExitCode error)
52 {
53 }
54 
55 void
AbortDDX(enum ExitCode error)56 AbortDDX(enum ExitCode error)
57 {
58     ddxGiveUp(error);
59 }
60 
61 void
OsVendorInit(void)62 OsVendorInit(void)
63 {
64     if (serverGeneration == 1)
65         ForceClockId(CLOCK_MONOTONIC);
66 }
67 
68 void
OsVendorFatalError(const char * f,va_list args)69 OsVendorFatalError(const char *f, va_list args)
70 {
71 }
72 
73 #if defined(DDXBEFORERESET)
74 void
ddxBeforeReset(void)75 ddxBeforeReset(void)
76 {
77     return;
78 }
79 #endif
80 
81 #if INPUTTHREAD
82 /** This function is called in Xserver/os/inputthread.c when starting
83     the input thread. */
84 void
ddxInputThreadInit(void)85 ddxInputThreadInit(void)
86 {
87 }
88 #endif
89 
90 #define DEFAULT_DPI 96
91 
92  _X_NORETURN
93 static void _X_ATTRIBUTE_PRINTF(1, 2)
xwl_give_up(const char * f,...)94 xwl_give_up(const char *f, ...)
95 {
96     va_list args;
97 
98     va_start(args, f);
99     VErrorFSigSafe(f, args);
100     va_end(args);
101 
102     CloseWellKnownConnections();
103     OsCleanup(TRUE);
104     fflush(stderr);
105     exit(1);
106 }
107 
108 void
ddxUseMsg(void)109 ddxUseMsg(void)
110 {
111     ErrorF("-rootless              run rootless, requires wm support\n");
112     ErrorF("-wm fd                 create X client for wm on given fd\n");
113     ErrorF("-listen fd             add give fd as a listen socket\n");
114     ErrorF("-eglstream             use eglstream backend for nvidia GPUs\n");
115 }
116 
117 int
ddxProcessArgument(int argc,char * argv[],int i)118 ddxProcessArgument(int argc, char *argv[], int i)
119 {
120     if (strcmp(argv[i], "-rootless") == 0) {
121         return 1;
122     }
123     else if (strcmp(argv[i], "-listen") == 0) {
124         NoListenAll = TRUE;
125         return 2;
126     }
127     else if (strcmp(argv[i], "-wm") == 0) {
128         return 2;
129     }
130     else if (strcmp(argv[i], "-shm") == 0) {
131         return 1;
132     }
133     else if (strcmp(argv[i], "-eglstream") == 0) {
134         return 1;
135     }
136 
137     return 0;
138 }
139 
140 static DevPrivateKeyRec xwl_window_private_key;
141 static DevPrivateKeyRec xwl_screen_private_key;
142 static DevPrivateKeyRec xwl_pixmap_private_key;
143 static DevPrivateKeyRec xwl_damage_private_key;
144 
145 static struct xwl_window *
xwl_window_get(WindowPtr window)146 xwl_window_get(WindowPtr window)
147 {
148     return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
149 }
150 
151 struct xwl_screen *
xwl_screen_get(ScreenPtr screen)152 xwl_screen_get(ScreenPtr screen)
153 {
154     return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
155 }
156 
157 static void
xwl_window_set_allow_commits(struct xwl_window * xwl_window,Bool allow,const char * debug_msg)158 xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
159                              const char *debug_msg)
160 {
161     xwl_window->allow_commits = allow;
162     DebugF("xwayland: win %d allow_commits = %d (%s)\n",
163            xwl_window->window->drawable.id, allow, debug_msg);
164 }
165 
166 static void
xwl_window_set_allow_commits_from_property(struct xwl_window * xwl_window,PropertyPtr prop)167 xwl_window_set_allow_commits_from_property(struct xwl_window *xwl_window,
168                                            PropertyPtr prop)
169 {
170     static Bool warned = FALSE;
171     CARD32 *propdata;
172 
173     if (prop->propertyName != xwl_window->xwl_screen->allow_commits_prop)
174         FatalError("Xwayland internal error: prop mismatch in %s.\n", __func__);
175 
176     if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) {
177         /* Not properly set, so fall back to safe and glitchy */
178         xwl_window_set_allow_commits(xwl_window, TRUE, "WM fault");
179 
180         if (!warned) {
181             LogMessageVerb(X_WARNING, 0, "Window manager is misusing property %s.\n",
182                            NameForAtom(prop->propertyName));
183             warned = TRUE;
184         }
185         return;
186     }
187 
188     propdata = prop->data;
189     xwl_window_set_allow_commits(xwl_window, !!propdata[0], "from property");
190 }
191 
192 static void
xwl_window_property_allow_commits(struct xwl_window * xwl_window,PropertyStateRec * propstate)193 xwl_window_property_allow_commits(struct xwl_window *xwl_window,
194                                   PropertyStateRec *propstate)
195 {
196     switch (propstate->state) {
197     case PropertyNewValue:
198         xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop);
199         break;
200 
201     case PropertyDelete:
202         xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted");
203         break;
204 
205     default:
206         break;
207     }
208 }
209 
210 static void
xwl_property_callback(CallbackListPtr * pcbl,void * closure,void * calldata)211 xwl_property_callback(CallbackListPtr *pcbl, void *closure,
212                       void *calldata)
213 {
214     ScreenPtr screen = closure;
215     PropertyStateRec *rec = calldata;
216     struct xwl_screen *xwl_screen;
217     struct xwl_window *xwl_window;
218 
219     if (rec->win->drawable.pScreen != screen)
220         return;
221 
222     xwl_window = xwl_window_get(rec->win);
223     if (!xwl_window)
224         return;
225 
226     xwl_screen = xwl_screen_get(screen);
227 
228     if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
229         xwl_window_property_allow_commits(xwl_window, rec);
230 }
231 
232 static Bool
xwl_close_screen(ScreenPtr screen)233 xwl_close_screen(ScreenPtr screen)
234 {
235     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
236     struct xwl_output *xwl_output, *next_xwl_output;
237     struct xwl_seat *xwl_seat, *next_xwl_seat;
238 
239     DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
240 
241     xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
242                                   &xwl_screen->output_list, link)
243         xwl_output_destroy(xwl_output);
244 
245     xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
246                                   &xwl_screen->seat_list, link)
247         xwl_seat_destroy(xwl_seat);
248 
249     xwl_screen_release_tablet_manager(xwl_screen);
250 
251     RemoveNotifyFd(xwl_screen->wayland_fd);
252 
253     wl_display_disconnect(xwl_screen->display);
254 
255     screen->CloseScreen = xwl_screen->CloseScreen;
256     free(xwl_screen);
257 
258     return screen->CloseScreen(screen);
259 }
260 
261 struct xwl_window *
xwl_window_from_window(WindowPtr window)262 xwl_window_from_window(WindowPtr window)
263 {
264     struct xwl_window *xwl_window;
265 
266     while (window) {
267         xwl_window = xwl_window_get(window);
268         if (xwl_window)
269             return xwl_window;
270 
271         window = window->parent;
272     }
273 
274     return NULL;
275 }
276 
277 static struct xwl_seat *
xwl_screen_get_default_seat(struct xwl_screen * xwl_screen)278 xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
279 {
280     if (xorg_list_is_empty(&xwl_screen->seat_list))
281         return NULL;
282 
283     return container_of(xwl_screen->seat_list.prev,
284                         struct xwl_seat,
285                         link);
286 }
287 
288 static void
xwl_cursor_warped_to(DeviceIntPtr device,ScreenPtr screen,ClientPtr client,WindowPtr window,SpritePtr sprite,int x,int y)289 xwl_cursor_warped_to(DeviceIntPtr device,
290                      ScreenPtr screen,
291                      ClientPtr client,
292                      WindowPtr window,
293                      SpritePtr sprite,
294                      int x, int y)
295 {
296     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
297     struct xwl_seat *xwl_seat = device->public.devicePrivate;
298     struct xwl_window *xwl_window;
299     WindowPtr focus;
300 
301     if (!xwl_seat)
302         xwl_seat = xwl_screen_get_default_seat(xwl_screen);
303 
304     if (!window)
305         window = XYToWindow(sprite, x, y);
306 
307     xwl_window = xwl_window_from_window(window);
308     if (!xwl_window && xwl_seat->focus_window) {
309         focus = xwl_seat->focus_window->window;
310 
311         /* Warps on non wl_surface backed Windows are only allowed
312          * as long as the pointer stays within the focus window.
313          */
314         if (x >= focus->drawable.x &&
315             y >= focus->drawable.y &&
316             x < focus->drawable.x + focus->drawable.width &&
317             y < focus->drawable.y + focus->drawable.height) {
318             if (!window) {
319                 DebugF("Warp relative to pointer, assuming pointer focus\n");
320                 xwl_window = xwl_seat->focus_window;
321             } else if (window == screen->root) {
322                 DebugF("Warp on root window, assuming pointer focus\n");
323                 xwl_window = xwl_seat->focus_window;
324             }
325         }
326     }
327     if (!xwl_window)
328         return;
329 
330     xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y);
331 }
332 
333 static void
xwl_cursor_confined_to(DeviceIntPtr device,ScreenPtr screen,WindowPtr window)334 xwl_cursor_confined_to(DeviceIntPtr device,
335                        ScreenPtr screen,
336                        WindowPtr window)
337 {
338     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
339     struct xwl_seat *xwl_seat = device->public.devicePrivate;
340     struct xwl_window *xwl_window;
341 
342     if (!xwl_seat)
343         xwl_seat = xwl_screen_get_default_seat(xwl_screen);
344 
345     /* xwl_seat hasn't been setup yet, don't do anything just yet */
346     if (!xwl_seat)
347         return;
348 
349     if (window == screen->root) {
350         xwl_seat_unconfine_pointer(xwl_seat);
351         return;
352     }
353 
354     xwl_window = xwl_window_from_window(window);
355     if (!xwl_window && xwl_seat->focus_window) {
356         /* Allow confining on InputOnly windows, but only if the geometry
357          * is the same than the focus window.
358          */
359         if (window->drawable.class == InputOnly) {
360             DebugF("Confine on InputOnly window, assuming pointer focus\n");
361             xwl_window = xwl_seat->focus_window;
362         }
363     }
364     if (!xwl_window)
365         return;
366 
367     xwl_seat_confine_pointer(xwl_seat, xwl_window);
368 }
369 
370 static void
damage_report(DamagePtr pDamage,RegionPtr pRegion,void * data)371 damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
372 {
373     WindowPtr window = data;
374     struct xwl_window *xwl_window = xwl_window_get(window);
375     struct xwl_screen *xwl_screen;
376 
377     if (!xwl_window)
378         return;
379 
380     xwl_screen = xwl_window->xwl_screen;
381 
382 #ifdef GLAMOR_HAS_GBM
383     if (xwl_window->present_flipped) {
384         /* This damage is from a Present flip, which already committed a new
385          * buffer for the surface, so we don't need to do anything in response
386          */
387         RegionEmpty(DamageRegion(pDamage));
388         xorg_list_del(&xwl_window->link_damage);
389         xwl_window->present_flipped = FALSE;
390         return;
391     }
392 #endif
393 
394     xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
395 }
396 
397 static void
damage_destroy(DamagePtr pDamage,void * data)398 damage_destroy(DamagePtr pDamage, void *data)
399 {
400 }
401 
402 static Bool
register_damage(WindowPtr window)403 register_damage(WindowPtr window)
404 {
405     DamagePtr damage;
406 
407     damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
408                           FALSE, window->drawable.pScreen, window);
409     if (damage == NULL) {
410         ErrorF("Failed creating damage\n");
411         return FALSE;
412     }
413 
414     DamageRegister(&window->drawable, damage);
415     DamageSetReportAfterOp(damage, TRUE);
416 
417     dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);
418 
419     return TRUE;
420 }
421 
422 static void
unregister_damage(WindowPtr window)423 unregister_damage(WindowPtr window)
424 {
425     DamagePtr damage;
426 
427     damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
428     if (!damage)
429         return;
430 
431     DamageUnregister(damage);
432     DamageDestroy(damage);
433 
434     dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL);
435 }
436 
437 static DamagePtr
window_get_damage(WindowPtr window)438 window_get_damage(WindowPtr window)
439 {
440     return dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
441 }
442 
443 static void
shell_surface_ping(void * data,struct wl_shell_surface * shell_surface,uint32_t serial)444 shell_surface_ping(void *data,
445                    struct wl_shell_surface *shell_surface, uint32_t serial)
446 {
447     wl_shell_surface_pong(shell_surface, serial);
448 }
449 
450 static void
shell_surface_configure(void * data,struct wl_shell_surface * wl_shell_surface,uint32_t edges,int32_t width,int32_t height)451 shell_surface_configure(void *data,
452                         struct wl_shell_surface *wl_shell_surface,
453                         uint32_t edges, int32_t width, int32_t height)
454 {
455 }
456 
457 static void
shell_surface_popup_done(void * data,struct wl_shell_surface * wl_shell_surface)458 shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
459 {
460 }
461 
462 static const struct wl_shell_surface_listener shell_surface_listener = {
463     shell_surface_ping,
464     shell_surface_configure,
465     shell_surface_popup_done
466 };
467 
468 void
xwl_pixmap_set_private(PixmapPtr pixmap,struct xwl_pixmap * xwl_pixmap)469 xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap)
470 {
471     dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap);
472 }
473 
474 struct xwl_pixmap *
xwl_pixmap_get(PixmapPtr pixmap)475 xwl_pixmap_get(PixmapPtr pixmap)
476 {
477     return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
478 }
479 
480 static void
xwl_window_init_allow_commits(struct xwl_window * xwl_window)481 xwl_window_init_allow_commits(struct xwl_window *xwl_window)
482 {
483     PropertyPtr prop = NULL;
484     int ret;
485 
486     ret = dixLookupProperty(&prop, xwl_window->window,
487                             xwl_window->xwl_screen->allow_commits_prop,
488                             serverClient, DixReadAccess);
489     if (ret == Success && prop)
490         xwl_window_set_allow_commits_from_property(xwl_window, prop);
491     else
492         xwl_window_set_allow_commits(xwl_window, TRUE, "no property");
493 }
494 
495 static void
send_surface_id_event(struct xwl_window * xwl_window)496 send_surface_id_event(struct xwl_window *xwl_window)
497 {
498     static const char atom_name[] = "WL_SURFACE_ID";
499     static Atom type_atom;
500     DeviceIntPtr dev;
501     xEvent e;
502 
503     if (type_atom == None)
504         type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
505 
506     e.u.u.type = ClientMessage;
507     e.u.u.detail = 32;
508     e.u.clientMessage.window = xwl_window->window->drawable.id;
509     e.u.clientMessage.u.l.type = type_atom;
510     e.u.clientMessage.u.l.longs0 =
511         wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
512     e.u.clientMessage.u.l.longs1 = 0;
513     e.u.clientMessage.u.l.longs2 = 0;
514     e.u.clientMessage.u.l.longs3 = 0;
515     e.u.clientMessage.u.l.longs4 = 0;
516 
517     dev = PickPointer(serverClient);
518     DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root,
519                           &e, 1, SubstructureRedirectMask, NullGrab);
520 }
521 
522 static Bool
ensure_surface_for_window(WindowPtr window)523 ensure_surface_for_window(WindowPtr window)
524 {
525     ScreenPtr screen = window->drawable.pScreen;
526     struct xwl_screen *xwl_screen;
527     struct xwl_window *xwl_window;
528     struct wl_region *region;
529 
530     if (xwl_window_from_window(window))
531         return TRUE;
532 
533     xwl_screen = xwl_screen_get(screen);
534 
535     if (xwl_screen->rootless) {
536         if (window->redirectDraw != RedirectDrawManual)
537             return TRUE;
538     }
539     else {
540         if (window->parent)
541             return TRUE;
542     }
543 
544     xwl_window = calloc(1, sizeof *xwl_window);
545     if (xwl_window == NULL)
546         return FALSE;
547 
548     xwl_window->xwl_screen = xwl_screen;
549     xwl_window->window = window;
550     xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
551     if (xwl_window->surface == NULL) {
552         ErrorF("wl_display_create_surface failed\n");
553         goto err;
554     }
555 
556     if (!xwl_screen->rootless) {
557         xwl_window->shell_surface =
558             wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface);
559         if (xwl_window->shell_surface == NULL) {
560             ErrorF("Failed creating shell surface\n");
561             goto err_surf;
562         }
563 
564         wl_shell_surface_add_listener(xwl_window->shell_surface,
565                                       &shell_surface_listener, xwl_window);
566 
567         wl_shell_surface_set_toplevel(xwl_window->shell_surface);
568 
569         region = wl_compositor_create_region(xwl_screen->compositor);
570         if (region == NULL) {
571             ErrorF("Failed creating region\n");
572             goto err_surf;
573         }
574 
575         wl_region_add(region, 0, 0,
576                       window->drawable.width, window->drawable.height);
577         wl_surface_set_opaque_region(xwl_window->surface, region);
578         wl_region_destroy(region);
579     }
580 
581     wl_display_flush(xwl_screen->display);
582 
583     send_surface_id_event(xwl_window);
584 
585     wl_surface_set_user_data(xwl_window->surface, xwl_window);
586 
587     compRedirectWindow(serverClient, window, CompositeRedirectManual);
588 
589     dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
590     xorg_list_init(&xwl_window->link_damage);
591 
592 #ifdef GLAMOR_HAS_GBM
593     xorg_list_init(&xwl_window->frame_callback_list);
594 #endif
595 
596     xwl_window_init_allow_commits(xwl_window);
597 
598     return TRUE;
599 
600 err_surf:
601     if (xwl_window->shell_surface)
602         wl_shell_surface_destroy(xwl_window->shell_surface);
603     wl_surface_destroy(xwl_window->surface);
604 err:
605     free(xwl_window);
606     return FALSE;
607 }
608 
609 static Bool
xwl_realize_window(WindowPtr window)610 xwl_realize_window(WindowPtr window)
611 {
612     ScreenPtr screen = window->drawable.pScreen;
613     struct xwl_screen *xwl_screen;
614     Bool ret;
615 
616     xwl_screen = xwl_screen_get(screen);
617 
618     screen->RealizeWindow = xwl_screen->RealizeWindow;
619     ret = (*screen->RealizeWindow) (window);
620     xwl_screen->RealizeWindow = screen->RealizeWindow;
621     screen->RealizeWindow = xwl_realize_window;
622 
623     if (!ret)
624         return FALSE;
625 
626     if (xwl_screen->rootless && !window->parent) {
627         BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
628 
629         RegionReset(&window->winSize, &box);
630         RegionNull(&window->clipList);
631         RegionNull(&window->borderClip);
632     }
633 
634     if (xwl_screen->rootless ?
635         (window->drawable.class == InputOutput &&
636          window->parent == window->drawable.pScreen->root) :
637         !window->parent) {
638         if (!register_damage(window))
639             return FALSE;
640     }
641 
642     return ensure_surface_for_window(window);
643 }
644 
645 static Bool
xwl_unrealize_window(WindowPtr window)646 xwl_unrealize_window(WindowPtr window)
647 {
648     ScreenPtr screen = window->drawable.pScreen;
649     struct xwl_screen *xwl_screen;
650     struct xwl_window *xwl_window;
651     struct xwl_seat *xwl_seat;
652     Bool ret;
653 
654     xwl_screen = xwl_screen_get(screen);
655 
656     xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
657         if (xwl_seat->focus_window && xwl_seat->focus_window->window == window)
658             xwl_seat->focus_window = NULL;
659         if (xwl_seat->tablet_focus_window && xwl_seat->tablet_focus_window->window == window)
660             xwl_seat->tablet_focus_window = NULL;
661         if (xwl_seat->last_xwindow == window)
662             xwl_seat->last_xwindow = NullWindow;
663         if (xwl_seat->cursor_confinement_window &&
664             xwl_seat->cursor_confinement_window->window == window)
665             xwl_seat_unconfine_pointer(xwl_seat);
666         if (xwl_seat->pointer_warp_emulator &&
667             xwl_seat->pointer_warp_emulator->locked_window &&
668             xwl_seat->pointer_warp_emulator->locked_window->window == window)
669             xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
670         xwl_seat_clear_touch(xwl_seat, window);
671     }
672 
673     compUnredirectWindow(serverClient, window, CompositeRedirectManual);
674 
675     screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
676     ret = (*screen->UnrealizeWindow) (window);
677     xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
678     screen->UnrealizeWindow = xwl_unrealize_window;
679 
680     xwl_window = xwl_window_get(window);
681     if (!xwl_window)
682         return ret;
683 
684     wl_surface_destroy(xwl_window->surface);
685     xorg_list_del(&xwl_window->link_damage);
686     unregister_damage(window);
687 
688     if (xwl_window->frame_callback)
689         wl_callback_destroy(xwl_window->frame_callback);
690 
691 #ifdef GLAMOR_HAS_GBM
692     if (xwl_screen->present) {
693         struct xwl_present_window *xwl_present_window, *tmp;
694 
695         xorg_list_for_each_entry_safe(xwl_present_window, tmp,
696                                       &xwl_window->frame_callback_list,
697                                       frame_callback_list) {
698             xwl_present_unrealize_window(xwl_present_window);
699         }
700     }
701 #endif
702 
703     free(xwl_window);
704     dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
705 
706     return ret;
707 }
708 
709 static Bool
xwl_save_screen(ScreenPtr pScreen,int on)710 xwl_save_screen(ScreenPtr pScreen, int on)
711 {
712     return TRUE;
713 }
714 
715 static void
xwl_set_window_pixmap(WindowPtr window,PixmapPtr pixmap)716 xwl_set_window_pixmap(WindowPtr window,
717                       PixmapPtr pixmap)
718 {
719     ScreenPtr screen = window->drawable.pScreen;
720     struct xwl_screen *xwl_screen;
721 
722     xwl_screen = xwl_screen_get(screen);
723 
724     screen->SetWindowPixmap = xwl_screen->SetWindowPixmap;
725     (*screen->SetWindowPixmap) (window, pixmap);
726     xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
727     screen->SetWindowPixmap = xwl_set_window_pixmap;
728 
729     if (!RegionNotEmpty(&window->winSize))
730         return;
731 
732     ensure_surface_for_window(window);
733 }
734 
735 static void
frame_callback(void * data,struct wl_callback * callback,uint32_t time)736 frame_callback(void *data,
737                struct wl_callback *callback,
738                uint32_t time)
739 {
740     struct xwl_window *xwl_window = data;
741 
742     wl_callback_destroy (xwl_window->frame_callback);
743     xwl_window->frame_callback = NULL;
744 
745 #ifdef GLAMOR_HAS_GBM
746     if (xwl_window->xwl_screen->present) {
747         struct xwl_present_window *xwl_present_window, *tmp;
748 
749         xorg_list_for_each_entry_safe(xwl_present_window, tmp,
750                                       &xwl_window->frame_callback_list,
751                                       frame_callback_list) {
752             xwl_present_frame_callback(xwl_present_window);
753         }
754     }
755 #endif
756 }
757 
758 static const struct wl_callback_listener frame_listener = {
759     frame_callback
760 };
761 
762 void
xwl_window_create_frame_callback(struct xwl_window * xwl_window)763 xwl_window_create_frame_callback(struct xwl_window *xwl_window)
764 {
765     xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
766     wl_callback_add_listener(xwl_window->frame_callback, &frame_listener,
767                              xwl_window);
768 }
769 
770 static Bool
xwl_destroy_window(WindowPtr window)771 xwl_destroy_window(WindowPtr window)
772 {
773     ScreenPtr screen = window->drawable.pScreen;
774     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
775     Bool ret;
776 
777 #ifdef GLAMOR_HAS_GBM
778     if (xwl_screen->present)
779         xwl_present_cleanup(window);
780 #endif
781 
782     screen->DestroyWindow = xwl_screen->DestroyWindow;
783 
784     if (screen->DestroyWindow)
785         ret = screen->DestroyWindow (window);
786     else
787         ret = TRUE;
788 
789     xwl_screen->DestroyWindow = screen->DestroyWindow;
790     screen->DestroyWindow = xwl_destroy_window;
791 
792     return ret;
793 }
794 
795 static void
xwl_window_post_damage(struct xwl_window * xwl_window)796 xwl_window_post_damage(struct xwl_window *xwl_window)
797 {
798     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
799     RegionPtr region;
800     BoxPtr box;
801     struct wl_buffer *buffer;
802     PixmapPtr pixmap;
803     int i;
804 
805     assert(!xwl_window->frame_callback);
806 
807     region = DamageRegion(window_get_damage(xwl_window->window));
808     pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
809 
810 #ifdef XWL_HAS_GLAMOR
811     if (xwl_screen->glamor)
812         buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap,
813                                                  NULL);
814     else
815 #endif
816         buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
817 
818 #ifdef XWL_HAS_GLAMOR
819     if (xwl_screen->glamor)
820         xwl_glamor_post_damage(xwl_window, pixmap, region);
821 #endif
822 
823     wl_surface_attach(xwl_window->surface, buffer, 0, 0);
824 
825     /* Arbitrary limit to try to avoid flooding the Wayland
826      * connection. If we flood it too much anyway, this could
827      * abort in libwayland-client.
828      */
829     if (RegionNumRects(region) > 256) {
830         box = RegionExtents(region);
831         wl_surface_damage(xwl_window->surface, box->x1, box->y1,
832                           box->x2 - box->x1, box->y2 - box->y1);
833     } else {
834         box = RegionRects(region);
835         for (i = 0; i < RegionNumRects(region); i++, box++)
836             wl_surface_damage(xwl_window->surface, box->x1, box->y1,
837                               box->x2 - box->x1, box->y2 - box->y1);
838     }
839 
840     xwl_window_create_frame_callback(xwl_window);
841     DamageEmpty(window_get_damage(xwl_window->window));
842 }
843 
844 static void
xwl_screen_post_damage(struct xwl_screen * xwl_screen)845 xwl_screen_post_damage(struct xwl_screen *xwl_screen)
846 {
847     struct xwl_window *xwl_window, *next_xwl_window;
848     struct xorg_list commit_window_list;
849 
850     xorg_list_init(&commit_window_list);
851 
852     xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
853                                   &xwl_screen->damage_window_list, link_damage) {
854         /* If we're waiting on a frame callback from the server,
855          * don't attach a new buffer. */
856         if (xwl_window->frame_callback)
857             continue;
858 
859         if (!xwl_window->allow_commits)
860             continue;
861 
862 #ifdef XWL_HAS_GLAMOR
863         if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
864             continue;
865 #endif
866 
867         xwl_window_post_damage(xwl_window);
868         xorg_list_del(&xwl_window->link_damage);
869         xorg_list_append(&xwl_window->link_damage, &commit_window_list);
870     }
871 
872     if (xorg_list_is_empty(&commit_window_list))
873         return;
874 
875 #ifdef XWL_HAS_GLAMOR
876     if (xwl_screen->glamor &&
877         xwl_screen->egl_backend == &xwl_screen->gbm_backend) {
878         glamor_block_handler(xwl_screen->screen);
879     }
880 #endif
881 
882     xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
883                                   &commit_window_list, link_damage) {
884         wl_surface_commit(xwl_window->surface);
885         xorg_list_del(&xwl_window->link_damage);
886     }
887 }
888 
889 static void
registry_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)890 registry_global(void *data, struct wl_registry *registry, uint32_t id,
891                 const char *interface, uint32_t version)
892 {
893     struct xwl_screen *xwl_screen = data;
894 
895     if (strcmp(interface, "wl_compositor") == 0) {
896         xwl_screen->compositor =
897             wl_registry_bind(registry, id, &wl_compositor_interface, 1);
898     }
899     else if (strcmp(interface, "wl_shm") == 0) {
900         xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
901     }
902     else if (strcmp(interface, "wl_shell") == 0) {
903         xwl_screen->shell =
904             wl_registry_bind(registry, id, &wl_shell_interface, 1);
905     }
906     else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
907         if (xwl_output_create(xwl_screen, id))
908             xwl_screen->expecting_event++;
909     }
910     else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
911         xwl_screen->xdg_output_manager =
912             wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, 1);
913         xwl_screen_init_xdg_output(xwl_screen);
914     }
915 #ifdef XWL_HAS_GLAMOR
916     else if (xwl_screen->glamor) {
917         xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
918                                     version);
919     }
920 #endif
921 }
922 
923 static void
global_remove(void * data,struct wl_registry * registry,uint32_t name)924 global_remove(void *data, struct wl_registry *registry, uint32_t name)
925 {
926     struct xwl_screen *xwl_screen = data;
927     struct xwl_output *xwl_output, *tmp_xwl_output;
928 
929     xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
930                                   &xwl_screen->output_list, link) {
931         if (xwl_output->server_output_id == name) {
932             xwl_output_remove(xwl_output);
933             break;
934         }
935     }
936 }
937 
938 static const struct wl_registry_listener registry_listener = {
939     registry_global,
940     global_remove
941 };
942 
943 static void
xwl_read_events(struct xwl_screen * xwl_screen)944 xwl_read_events (struct xwl_screen *xwl_screen)
945 {
946     int ret;
947 
948     if (xwl_screen->wait_flush)
949         return;
950 
951     ret = wl_display_read_events(xwl_screen->display);
952     if (ret == -1)
953         xwl_give_up("failed to read Wayland events: %s\n", strerror(errno));
954 
955     xwl_screen->prepare_read = 0;
956 
957     ret = wl_display_dispatch_pending(xwl_screen->display);
958     if (ret == -1)
959         xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno));
960 }
961 
962 static int
xwl_display_pollout(struct xwl_screen * xwl_screen,int timeout)963 xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout)
964 {
965     struct pollfd poll_fd;
966 
967     poll_fd.fd = wl_display_get_fd(xwl_screen->display);
968     poll_fd.events = POLLOUT;
969 
970     return xserver_poll(&poll_fd, 1, timeout);
971 }
972 
973 static void
xwl_dispatch_events(struct xwl_screen * xwl_screen)974 xwl_dispatch_events (struct xwl_screen *xwl_screen)
975 {
976     int ret = 0;
977     int ready;
978 
979     if (xwl_screen->wait_flush)
980         goto pollout;
981 
982     while (xwl_screen->prepare_read == 0 &&
983            wl_display_prepare_read(xwl_screen->display) == -1) {
984         ret = wl_display_dispatch_pending(xwl_screen->display);
985         if (ret == -1)
986             xwl_give_up("failed to dispatch Wayland events: %s\n",
987                        strerror(errno));
988     }
989 
990     xwl_screen->prepare_read = 1;
991 
992 pollout:
993     ready = xwl_display_pollout(xwl_screen, 5);
994     if (ready == -1 && errno != EINTR)
995         xwl_give_up("error polling on XWayland fd: %s\n", strerror(errno));
996 
997     if (ready > 0)
998         ret = wl_display_flush(xwl_screen->display);
999 
1000     if (ret == -1 && errno != EAGAIN)
1001         xwl_give_up("failed to write to XWayland fd: %s\n", strerror(errno));
1002 
1003     xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
1004 }
1005 
1006 static void
socket_handler(int fd,int ready,void * data)1007 socket_handler(int fd, int ready, void *data)
1008 {
1009     struct xwl_screen *xwl_screen = data;
1010 
1011     xwl_read_events (xwl_screen);
1012 }
1013 
1014 static void
wakeup_handler(void * data,int err)1015 wakeup_handler(void *data, int err)
1016 {
1017 }
1018 
1019 static void
block_handler(void * data,void * timeout)1020 block_handler(void *data, void *timeout)
1021 {
1022     struct xwl_screen *xwl_screen = data;
1023 
1024     xwl_screen_post_damage(xwl_screen);
1025     xwl_dispatch_events (xwl_screen);
1026 }
1027 
1028 void
xwl_sync_events(struct xwl_screen * xwl_screen)1029 xwl_sync_events (struct xwl_screen *xwl_screen)
1030 {
1031     xwl_dispatch_events (xwl_screen);
1032     xwl_read_events (xwl_screen);
1033 }
1034 
1035 void
xwl_screen_roundtrip(struct xwl_screen * xwl_screen)1036 xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
1037 {
1038     int ret;
1039 
1040     ret = wl_display_roundtrip(xwl_screen->display);
1041     while (ret >= 0 && xwl_screen->expecting_event)
1042         ret = wl_display_roundtrip(xwl_screen->display);
1043 
1044     if (ret < 0)
1045         xwl_give_up("could not connect to wayland server\n");
1046 }
1047 
1048 static CARD32
add_client_fd(OsTimerPtr timer,CARD32 time,void * arg)1049 add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
1050 {
1051     struct xwl_screen *xwl_screen = arg;
1052 
1053     if (!AddClientOnOpenFD(xwl_screen->wm_fd))
1054         FatalError("Failed to add wm client\n");
1055 
1056     TimerFree(timer);
1057 
1058     return 0;
1059 }
1060 
1061 static void
listen_on_fds(struct xwl_screen * xwl_screen)1062 listen_on_fds(struct xwl_screen *xwl_screen)
1063 {
1064     int i;
1065 
1066     for (i = 0; i < xwl_screen->listen_fd_count; i++)
1067         ListenOnOpenFD(xwl_screen->listen_fds[i], FALSE);
1068 }
1069 
1070 static void
wm_selection_callback(CallbackListPtr * p,void * data,void * arg)1071 wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
1072 {
1073     SelectionInfoRec *info = arg;
1074     struct xwl_screen *xwl_screen = data;
1075     static const char atom_name[] = "WM_S0";
1076     static Atom atom_wm_s0;
1077 
1078     if (atom_wm_s0 == None)
1079         atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
1080     if (info->selection->selection != atom_wm_s0 ||
1081         info->kind != SelectionSetOwner)
1082         return;
1083 
1084     listen_on_fds(xwl_screen);
1085 
1086     DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
1087 }
1088 
1089 static Bool
xwl_screen_init(ScreenPtr pScreen,int argc,char ** argv)1090 xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
1091 {
1092     static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
1093     struct xwl_screen *xwl_screen;
1094     Pixel red_mask, blue_mask, green_mask;
1095     int ret, bpc, green_bpc, i;
1096     Bool use_eglstreams = FALSE;
1097 
1098     xwl_screen = calloc(1, sizeof *xwl_screen);
1099     if (xwl_screen == NULL)
1100         return FALSE;
1101     xwl_screen->wm_fd = -1;
1102 
1103     if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
1104         return FALSE;
1105     if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
1106         return FALSE;
1107     if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
1108         return FALSE;
1109     if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0))
1110         return FALSE;
1111 
1112     dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
1113     xwl_screen->screen = pScreen;
1114 
1115 #ifdef XWL_HAS_GLAMOR
1116     xwl_screen->glamor = 1;
1117 #endif
1118 
1119     for (i = 1; i < argc; i++) {
1120         if (strcmp(argv[i], "-rootless") == 0) {
1121             xwl_screen->rootless = 1;
1122 
1123             /* Disable the XSS extension on Xwayland rootless.
1124              *
1125              * Xwayland is just a Wayland client, no X11 screensaver
1126              * should be expected to work reliably on Xwayland rootless.
1127              */
1128 #ifdef SCREENSAVER
1129             noScreenSaverExtension = TRUE;
1130 #endif
1131             ScreenSaverTime = 0;
1132             ScreenSaverInterval = 0;
1133             defaultScreenSaverTime = 0;
1134             defaultScreenSaverInterval = 0;
1135         }
1136         else if (strcmp(argv[i], "-wm") == 0) {
1137             xwl_screen->wm_fd = atoi(argv[i + 1]);
1138             i++;
1139             TimerSet(NULL, 0, 1, add_client_fd, xwl_screen);
1140         }
1141         else if (strcmp(argv[i], "-listen") == 0) {
1142             if (xwl_screen->listen_fd_count ==
1143                 ARRAY_SIZE(xwl_screen->listen_fds))
1144                 FatalError("Too many -listen arguments given, max is %zu\n",
1145                            ARRAY_SIZE(xwl_screen->listen_fds));
1146 
1147             xwl_screen->listen_fds[xwl_screen->listen_fd_count++] =
1148                 atoi(argv[i + 1]);
1149             i++;
1150         }
1151         else if (strcmp(argv[i], "-shm") == 0) {
1152             xwl_screen->glamor = 0;
1153         }
1154         else if (strcmp(argv[i], "-eglstream") == 0) {
1155 #ifdef XWL_HAS_EGLSTREAM
1156             use_eglstreams = TRUE;
1157 #else
1158             ErrorF("xwayland glamor: this build does not have EGLStream support\n");
1159 #endif
1160         }
1161     }
1162 
1163 #ifdef XWL_HAS_GLAMOR
1164     if (xwl_screen->glamor)
1165         xwl_glamor_init_backends(xwl_screen, use_eglstreams);
1166 #endif
1167 
1168     /* In rootless mode, we don't have any screen storage, and the only
1169      * rendering should be to redirected mode. */
1170     if (xwl_screen->rootless)
1171         xwl_screen->root_clip_mode = ROOT_CLIP_INPUT_ONLY;
1172     else
1173         xwl_screen->root_clip_mode = ROOT_CLIP_FULL;
1174 
1175     if (xwl_screen->listen_fd_count > 0) {
1176         if (xwl_screen->wm_fd >= 0)
1177             AddCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
1178         else
1179             listen_on_fds(xwl_screen);
1180     }
1181 
1182     xorg_list_init(&xwl_screen->output_list);
1183     xorg_list_init(&xwl_screen->seat_list);
1184     xorg_list_init(&xwl_screen->damage_window_list);
1185     xwl_screen->depth = 24;
1186 
1187     if (!monitorResolution)
1188         monitorResolution = DEFAULT_DPI;
1189 
1190     xwl_screen->display = wl_display_connect(NULL);
1191     if (xwl_screen->display == NULL) {
1192         ErrorF("could not connect to wayland server\n");
1193         return FALSE;
1194     }
1195 
1196     if (!xwl_screen_init_output(xwl_screen))
1197         return FALSE;
1198 
1199     xwl_screen->expecting_event = 0;
1200     xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
1201     wl_registry_add_listener(xwl_screen->registry,
1202                              &registry_listener, xwl_screen);
1203     xwl_screen_roundtrip(xwl_screen);
1204 
1205     if (!xwl_screen->rootless && !xwl_screen->shell) {
1206         ErrorF("missing wl_shell protocol\n");
1207         return FALSE;
1208     }
1209 
1210     bpc = xwl_screen->depth / 3;
1211     green_bpc = xwl_screen->depth - 2 * bpc;
1212     blue_mask = (1 << bpc) - 1;
1213     green_mask = ((1 << green_bpc) - 1) << bpc;
1214     red_mask = blue_mask << (green_bpc + bpc);
1215 
1216     miSetVisualTypesAndMasks(xwl_screen->depth,
1217                              ((1 << TrueColor) | (1 << DirectColor)),
1218                              green_bpc, TrueColor,
1219                              red_mask, green_mask, blue_mask);
1220 
1221     miSetPixmapDepths();
1222 
1223     ret = fbScreenInit(pScreen, NULL,
1224                        xwl_screen->width, xwl_screen->height,
1225                        monitorResolution, monitorResolution, 0,
1226                        BitsPerPixel(xwl_screen->depth));
1227     if (!ret)
1228         return FALSE;
1229 
1230     fbPictureInit(pScreen, 0, 0);
1231 
1232 #ifdef HAVE_XSHMFENCE
1233     if (!miSyncShmScreenInit(pScreen))
1234         return FALSE;
1235 #endif
1236 
1237     xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
1238     SetNotifyFd(xwl_screen->wayland_fd, socket_handler, X_NOTIFY_READ, xwl_screen);
1239     RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
1240 
1241     pScreen->SaveScreen = xwl_save_screen;
1242 
1243     pScreen->blackPixel = 0;
1244     pScreen->whitePixel = 1;
1245 
1246     ret = fbCreateDefColormap(pScreen);
1247 
1248     if (!xwl_screen_init_cursor(xwl_screen))
1249         return FALSE;
1250 
1251 #ifdef XWL_HAS_GLAMOR
1252     if (xwl_screen->glamor) {
1253         xwl_glamor_select_backend(xwl_screen, use_eglstreams);
1254 
1255         if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
1256            ErrorF("Failed to initialize glamor, falling back to sw\n");
1257            xwl_screen->glamor = 0;
1258         }
1259     }
1260 
1261     if (xwl_screen->glamor && xwl_screen->rootless)
1262         xwl_screen->present = xwl_present_init(pScreen);
1263 #endif
1264 
1265     if (!xwl_screen->glamor) {
1266         xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
1267         pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
1268         pScreen->CreatePixmap = xwl_shm_create_pixmap;
1269         pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
1270     }
1271 
1272     xwl_screen->RealizeWindow = pScreen->RealizeWindow;
1273     pScreen->RealizeWindow = xwl_realize_window;
1274 
1275     xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
1276     pScreen->UnrealizeWindow = xwl_unrealize_window;
1277 
1278     xwl_screen->DestroyWindow = pScreen->DestroyWindow;
1279     pScreen->DestroyWindow = xwl_destroy_window;
1280 
1281     xwl_screen->CloseScreen = pScreen->CloseScreen;
1282     pScreen->CloseScreen = xwl_close_screen;
1283 
1284     if (xwl_screen->rootless) {
1285         xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
1286         pScreen->SetWindowPixmap = xwl_set_window_pixmap;
1287     }
1288 
1289     pScreen->CursorWarpedTo = xwl_cursor_warped_to;
1290     pScreen->CursorConfinedTo = xwl_cursor_confined_to;
1291 
1292     xwl_screen->allow_commits_prop = MakeAtom(allow_commits,
1293                                               strlen(allow_commits),
1294                                               TRUE);
1295     if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
1296         return FALSE;
1297 
1298     AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
1299 
1300     xwl_screen_roundtrip(xwl_screen);
1301 
1302     return ret;
1303 }
1304 
1305 _X_NORETURN
1306 static void _X_ATTRIBUTE_PRINTF(1, 0)
xwl_log_handler(const char * format,va_list args)1307 xwl_log_handler(const char *format, va_list args)
1308 {
1309     char msg[256];
1310 
1311     vsnprintf(msg, sizeof msg, format, args);
1312     FatalError("%s", msg);
1313 }
1314 
1315 static const ExtensionModule xwayland_extensions[] = {
1316 #ifdef XF86VIDMODE
1317     { xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
1318 #endif
1319 };
1320 
1321 void
InitOutput(ScreenInfo * screen_info,int argc,char ** argv)1322 InitOutput(ScreenInfo * screen_info, int argc, char **argv)
1323 {
1324     int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
1325     int bpp[] =    { 1, 8, 8, 16, 16, 32, 32 };
1326     int i;
1327 
1328     for (i = 0; i < ARRAY_SIZE(depths); i++) {
1329         screen_info->formats[i].depth = depths[i];
1330         screen_info->formats[i].bitsPerPixel = bpp[i];
1331         screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
1332     }
1333 
1334     screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
1335     screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1336     screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
1337     screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
1338     screen_info->numPixmapFormats = ARRAY_SIZE(depths);
1339 
1340     if (serverGeneration == 1)
1341         LoadExtensionList(xwayland_extensions,
1342                           ARRAY_SIZE(xwayland_extensions), FALSE);
1343 
1344     /* Cast away warning from missing printf annotation for
1345      * wl_log_func_t.  Wayland 1.5 will have the annotation, so we can
1346      * remove the cast and require that when it's released. */
1347     wl_log_set_handler_client((void *) xwl_log_handler);
1348 
1349     if (AddScreen(xwl_screen_init, argc, argv) == -1) {
1350         FatalError("Couldn't add screen\n");
1351     }
1352 
1353     xorgGlxCreateVendor();
1354 
1355     LocalAccessScopeUser();
1356 }
1357