2 * Wayland core handling
4 * Copyright (c) 2020 Alexandros Frantzis for Collabora Ltd
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "waylanddrv.h"
29 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv
);
35 struct wayland process_wayland
=
37 .output_list
= {&process_wayland
.output_list
, &process_wayland
.output_list
},
38 .output_mutex
= PTHREAD_MUTEX_INITIALIZER
41 /**********************************************************************
42 * xdg_wm_base handling
45 static void xdg_wm_base_handle_ping(void *data
, struct xdg_wm_base
*shell
,
48 xdg_wm_base_pong(shell
, serial
);
51 static const struct xdg_wm_base_listener xdg_wm_base_listener
=
53 xdg_wm_base_handle_ping
56 /**********************************************************************
60 static void registry_handle_global(void *data
, struct wl_registry
*registry
,
61 uint32_t id
, const char *interface
,
64 TRACE("interface=%s version=%u id=%u\n", interface
, version
, id
);
66 if (strcmp(interface
, "wl_output") == 0)
68 if (!wayland_output_create(id
, version
))
69 ERR("Failed to create wayland_output for global id=%u\n", id
);
71 else if (strcmp(interface
, "zxdg_output_manager_v1") == 0)
73 struct wayland_output
*output
;
75 process_wayland
.zxdg_output_manager_v1
=
76 wl_registry_bind(registry
, id
, &zxdg_output_manager_v1_interface
,
77 version
< 3 ? version
: 3);
79 /* Add zxdg_output_v1 to existing outputs. */
80 wl_list_for_each(output
, &process_wayland
.output_list
, link
)
81 wayland_output_use_xdg_extension(output
);
83 else if (strcmp(interface
, "wl_compositor") == 0)
85 process_wayland
.wl_compositor
=
86 wl_registry_bind(registry
, id
, &wl_compositor_interface
, 4);
88 else if (strcmp(interface
, "xdg_wm_base") == 0)
90 /* Bind version 2 so that compositors (e.g., sway) can properly send tiled
91 * states, instead of falling back to (ab)using the maximized state. */
92 process_wayland
.xdg_wm_base
=
93 wl_registry_bind(registry
, id
, &xdg_wm_base_interface
,
94 version
< 2 ? version
: 2);
95 xdg_wm_base_add_listener(process_wayland
.xdg_wm_base
, &xdg_wm_base_listener
, NULL
);
97 else if (strcmp(interface
, "wl_shm") == 0)
99 process_wayland
.wl_shm
= wl_registry_bind(registry
, id
, &wl_shm_interface
, 1);
103 static void registry_handle_global_remove(void *data
, struct wl_registry
*registry
,
106 struct wayland_output
*output
, *tmp
;
108 TRACE("id=%u\n", id
);
110 wl_list_for_each_safe(output
, tmp
, &process_wayland
.output_list
, link
)
112 if (output
->global_id
== id
)
114 TRACE("removing output->name=%s\n", output
->current
.name
);
115 wayland_output_destroy(output
);
121 static const struct wl_registry_listener registry_listener
= {
122 registry_handle_global
,
123 registry_handle_global_remove
126 /**********************************************************************
127 * wayland_process_init
129 * Initialise the per process wayland objects.
132 BOOL
wayland_process_init(void)
134 struct wl_display
*wl_display_wrapper
;
136 process_wayland
.wl_display
= wl_display_connect(NULL
);
137 if (!process_wayland
.wl_display
)
140 TRACE("wl_display=%p\n", process_wayland
.wl_display
);
142 if (!(process_wayland
.wl_event_queue
= wl_display_create_queue(process_wayland
.wl_display
)))
144 ERR("Failed to create event queue\n");
148 if (!(wl_display_wrapper
= wl_proxy_create_wrapper(process_wayland
.wl_display
)))
150 ERR("Failed to create proxy wrapper for wl_display\n");
153 wl_proxy_set_queue((struct wl_proxy
*) wl_display_wrapper
,
154 process_wayland
.wl_event_queue
);
156 process_wayland
.wl_registry
= wl_display_get_registry(wl_display_wrapper
);
157 wl_proxy_wrapper_destroy(wl_display_wrapper
);
158 if (!process_wayland
.wl_registry
)
160 ERR("Failed to get to wayland registry\n");
164 /* Populate registry */
165 wl_registry_add_listener(process_wayland
.wl_registry
, ®istry_listener
, NULL
);
167 /* We need two roundtrips. One to get and bind globals, one to handle all
168 * initial events produced from registering the globals. */
169 wl_display_roundtrip_queue(process_wayland
.wl_display
, process_wayland
.wl_event_queue
);
170 wl_display_roundtrip_queue(process_wayland
.wl_display
, process_wayland
.wl_event_queue
);
172 /* Check for required protocol globals. */
173 if (!process_wayland
.wl_compositor
)
175 ERR("Wayland compositor doesn't support wl_compositor\n");
178 if (!process_wayland
.xdg_wm_base
)
180 ERR("Wayland compositor doesn't support xdg_wm_base\n");
183 if (!process_wayland
.wl_shm
)
185 ERR("Wayland compositor doesn't support wl_shm\n");
189 wayland_init_display_devices(FALSE
);
191 process_wayland
.initialized
= TRUE
;