4 * Copyright 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
30 #include "waylanddrv.h"
31 #include "wine/debug.h"
32 #include "wine/server.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv
);
36 static void xdg_surface_handle_configure(void *data
, struct xdg_surface
*xdg_surface
,
39 struct wayland_surface
*surface
;
40 BOOL initial_configure
= FALSE
;
43 TRACE("serial=%u\n", serial
);
45 if (!(surface
= wayland_surface_lock_hwnd(hwnd
))) return;
47 /* Handle this event only if wayland_surface is still associated with
48 * the target xdg_surface. */
49 if (surface
->xdg_surface
== xdg_surface
)
51 /* If we have a previously requested config, we have already sent a
52 * WM_WAYLAND_CONFIGURE which hasn't been handled yet. In that case,
53 * avoid sending another message to reduce message queue traffic. */
54 BOOL should_post
= surface
->requested
.serial
== 0;
55 initial_configure
= surface
->current
.serial
== 0;
56 surface
->pending
.serial
= serial
;
57 surface
->requested
= surface
->pending
;
58 memset(&surface
->pending
, 0, sizeof(surface
->pending
));
59 if (should_post
) NtUserPostMessage(hwnd
, WM_WAYLAND_CONFIGURE
, 0, 0);
62 pthread_mutex_unlock(&surface
->mutex
);
64 /* Flush the window surface in case there is content that we weren't
65 * able to flush before due to the lack of the initial configure. */
66 if (initial_configure
) wayland_window_flush(hwnd
);
69 static const struct xdg_surface_listener xdg_surface_listener
=
71 xdg_surface_handle_configure
74 static void xdg_toplevel_handle_configure(void *data
,
75 struct xdg_toplevel
*xdg_toplevel
,
76 int32_t width
, int32_t height
,
77 struct wl_array
*states
)
79 struct wayland_surface
*surface
;
82 enum wayland_surface_config_state config_state
= 0;
84 wl_array_for_each(state
, states
)
88 case XDG_TOPLEVEL_STATE_MAXIMIZED
:
89 config_state
|= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED
;
91 case XDG_TOPLEVEL_STATE_RESIZING
:
92 config_state
|= WAYLAND_SURFACE_CONFIG_STATE_RESIZING
;
94 case XDG_TOPLEVEL_STATE_TILED_LEFT
:
95 case XDG_TOPLEVEL_STATE_TILED_RIGHT
:
96 case XDG_TOPLEVEL_STATE_TILED_TOP
:
97 case XDG_TOPLEVEL_STATE_TILED_BOTTOM
:
98 config_state
|= WAYLAND_SURFACE_CONFIG_STATE_TILED
;
100 case XDG_TOPLEVEL_STATE_FULLSCREEN
:
101 config_state
|= WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN
;
108 TRACE("hwnd=%p %dx%d,%#x\n", hwnd
, width
, height
, config_state
);
110 if (!(surface
= wayland_surface_lock_hwnd(hwnd
))) return;
112 if (surface
->xdg_toplevel
== xdg_toplevel
)
114 surface
->pending
.width
= width
;
115 surface
->pending
.height
= height
;
116 surface
->pending
.state
= config_state
;
119 pthread_mutex_unlock(&surface
->mutex
);
122 static void xdg_toplevel_handle_close(void *data
, struct xdg_toplevel
*xdg_toplevel
)
124 NtUserPostMessage((HWND
)data
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
127 static const struct xdg_toplevel_listener xdg_toplevel_listener
=
129 xdg_toplevel_handle_configure
,
130 xdg_toplevel_handle_close
133 /**********************************************************************
134 * wayland_surface_create
136 * Creates a role-less wayland surface.
138 struct wayland_surface
*wayland_surface_create(HWND hwnd
)
140 struct wayland_surface
*surface
;
142 surface
= calloc(1, sizeof(*surface
));
145 ERR("Failed to allocate space for Wayland surface\n");
149 TRACE("surface=%p\n", surface
);
151 pthread_mutex_init(&surface
->mutex
, NULL
);
153 surface
->hwnd
= hwnd
;
154 surface
->wl_surface
= wl_compositor_create_surface(process_wayland
.wl_compositor
);
155 if (!surface
->wl_surface
)
157 ERR("Failed to create wl_surface Wayland surface\n");
160 wl_surface_set_user_data(surface
->wl_surface
, hwnd
);
162 if (process_wayland
.wp_viewporter
)
164 surface
->wp_viewport
=
165 wp_viewporter_get_viewport(process_wayland
.wp_viewporter
,
166 surface
->wl_surface
);
169 surface
->window
.scale
= 1.0;
174 if (surface
) wayland_surface_destroy(surface
);
178 /**********************************************************************
179 * wayland_surface_destroy
181 * Destroys a wayland surface.
183 void wayland_surface_destroy(struct wayland_surface
*surface
)
185 pthread_mutex_lock(&process_wayland
.pointer
.mutex
);
186 if (process_wayland
.pointer
.focused_hwnd
== surface
->hwnd
)
188 process_wayland
.pointer
.focused_hwnd
= NULL
;
189 process_wayland
.pointer
.enter_serial
= 0;
191 pthread_mutex_unlock(&process_wayland
.pointer
.mutex
);
193 pthread_mutex_lock(&process_wayland
.keyboard
.mutex
);
194 if (process_wayland
.keyboard
.focused_hwnd
== surface
->hwnd
)
195 process_wayland
.keyboard
.focused_hwnd
= NULL
;
196 pthread_mutex_unlock(&process_wayland
.keyboard
.mutex
);
198 pthread_mutex_lock(&surface
->mutex
);
200 if (surface
->wp_viewport
)
202 wp_viewport_destroy(surface
->wp_viewport
);
203 surface
->wp_viewport
= NULL
;
206 if (surface
->xdg_toplevel
)
208 xdg_toplevel_destroy(surface
->xdg_toplevel
);
209 surface
->xdg_toplevel
= NULL
;
212 if (surface
->xdg_surface
)
214 xdg_surface_destroy(surface
->xdg_surface
);
215 surface
->xdg_surface
= NULL
;
218 if (surface
->wl_surface
)
220 wl_surface_destroy(surface
->wl_surface
);
221 surface
->wl_surface
= NULL
;
224 pthread_mutex_unlock(&surface
->mutex
);
226 if (surface
->latest_window_buffer
)
227 wayland_shm_buffer_unref(surface
->latest_window_buffer
);
229 wl_display_flush(process_wayland
.wl_display
);
231 pthread_mutex_destroy(&surface
->mutex
);
236 /**********************************************************************
237 * wayland_surface_make_toplevel
239 * Gives the toplevel role to a plain wayland surface.
241 void wayland_surface_make_toplevel(struct wayland_surface
*surface
)
243 TRACE("surface=%p\n", surface
);
245 surface
->xdg_surface
=
246 xdg_wm_base_get_xdg_surface(process_wayland
.xdg_wm_base
, surface
->wl_surface
);
247 if (!surface
->xdg_surface
) goto err
;
248 xdg_surface_add_listener(surface
->xdg_surface
, &xdg_surface_listener
, surface
->hwnd
);
250 surface
->xdg_toplevel
= xdg_surface_get_toplevel(surface
->xdg_surface
);
251 if (!surface
->xdg_toplevel
) goto err
;
252 xdg_toplevel_add_listener(surface
->xdg_toplevel
, &xdg_toplevel_listener
, surface
->hwnd
);
254 wl_surface_commit(surface
->wl_surface
);
255 wl_display_flush(process_wayland
.wl_display
);
260 wayland_surface_clear_role(surface
);
261 ERR("Failed to assign toplevel role to wayland surface\n");
264 /**********************************************************************
265 * wayland_surface_clear_role
267 * Clears the role related Wayland objects of a Wayland surface, making it a
268 * plain surface again. We can later assign the same role (but not a
269 * different one!) to the surface.
271 void wayland_surface_clear_role(struct wayland_surface
*surface
)
273 TRACE("surface=%p\n", surface
);
275 if (surface
->xdg_toplevel
)
277 xdg_toplevel_destroy(surface
->xdg_toplevel
);
278 surface
->xdg_toplevel
= NULL
;
281 if (surface
->xdg_surface
)
283 xdg_surface_destroy(surface
->xdg_surface
);
284 surface
->xdg_surface
= NULL
;
287 memset(&surface
->pending
, 0, sizeof(surface
->pending
));
288 memset(&surface
->requested
, 0, sizeof(surface
->requested
));
289 memset(&surface
->processing
, 0, sizeof(surface
->processing
));
290 memset(&surface
->current
, 0, sizeof(surface
->current
));
292 /* Ensure no buffer is attached, otherwise future role assignments may fail. */
293 wl_surface_attach(surface
->wl_surface
, NULL
, 0, 0);
294 wl_surface_commit(surface
->wl_surface
);
296 wl_display_flush(process_wayland
.wl_display
);
299 /**********************************************************************
300 * wayland_surface_attach_shm
302 * Attaches a SHM buffer to a wayland surface.
304 * The buffer is marked as unavailable until committed and subsequently
305 * released by the compositor.
307 void wayland_surface_attach_shm(struct wayland_surface
*surface
,
308 struct wayland_shm_buffer
*shm_buffer
,
309 HRGN surface_damage_region
)
311 RGNDATA
*surface_damage
;
313 TRACE("surface=%p shm_buffer=%p (%dx%d)\n",
314 surface
, shm_buffer
, shm_buffer
->width
, shm_buffer
->height
);
316 shm_buffer
->busy
= TRUE
;
317 wayland_shm_buffer_ref(shm_buffer
);
319 wl_surface_attach(surface
->wl_surface
, shm_buffer
->wl_buffer
, 0, 0);
321 /* Add surface damage, i.e., which parts of the surface have changed since
322 * the last surface commit. Note that this is different from the buffer
324 surface_damage
= get_region_data(surface_damage_region
);
327 RECT
*rgn_rect
= (RECT
*)surface_damage
->Buffer
;
328 RECT
*rgn_rect_end
= rgn_rect
+ surface_damage
->rdh
.nCount
;
330 for (;rgn_rect
< rgn_rect_end
; rgn_rect
++)
332 wl_surface_damage_buffer(surface
->wl_surface
,
333 rgn_rect
->left
, rgn_rect
->top
,
334 rgn_rect
->right
- rgn_rect
->left
,
335 rgn_rect
->bottom
- rgn_rect
->top
);
337 free(surface_damage
);
341 /**********************************************************************
342 * wayland_surface_config_is_compatible
344 * Checks whether a wayland_surface_config object is compatible with the
345 * the provided arguments.
347 BOOL
wayland_surface_config_is_compatible(struct wayland_surface_config
*conf
,
348 int width
, int height
,
349 enum wayland_surface_config_state state
)
351 static enum wayland_surface_config_state mask
=
352 WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED
;
354 /* We require the same state. */
355 if ((state
& mask
) != (conf
->state
& mask
)) return FALSE
;
357 /* The maximized state requires the configured size. During surface
358 * reconfiguration we can use surface geometry to provide smaller areas
359 * from larger sizes, so only smaller sizes are incompatible. */
360 if ((conf
->state
& WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED
) &&
361 (width
< conf
->width
|| height
< conf
->height
))
366 /* The fullscreen state requires a size smaller or equal to the configured
367 * size. If we have a larger size, we can use surface geometry during
368 * surface reconfiguration to provide the smaller size, so we are always
369 * compatible with a fullscreen state. */
374 /**********************************************************************
375 * wayland_surface_get_rect_in_monitor
377 * Gets the largest rectangle within a surface's window (in window coordinates)
378 * that is visible in a monitor.
380 static void wayland_surface_get_rect_in_monitor(struct wayland_surface
*surface
,
386 mi
.cbSize
= sizeof(mi
);
387 if (!(hmonitor
= NtUserMonitorFromRect(&surface
->window
.rect
, 0)) ||
388 !NtUserGetMonitorInfo(hmonitor
, (MONITORINFO
*)&mi
))
394 intersect_rect(rect
, &mi
.rcMonitor
, &surface
->window
.rect
);
395 OffsetRect(rect
, -surface
->window
.rect
.left
, -surface
->window
.rect
.top
);
398 /**********************************************************************
399 * wayland_surface_reconfigure_geometry
401 * Sets the xdg_surface geometry
403 static void wayland_surface_reconfigure_geometry(struct wayland_surface
*surface
,
404 int width
, int height
)
408 /* If the window size is bigger than the current state accepts, use the
409 * largest visible (from Windows' perspective) subregion of the window. */
410 if ((surface
->current
.state
& (WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED
|
411 WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN
)) &&
412 (width
> surface
->current
.width
|| height
> surface
->current
.height
))
414 wayland_surface_get_rect_in_monitor(surface
, &rect
);
416 wayland_surface_coords_from_window(surface
, rect
.left
, rect
.top
,
417 (int *)&rect
.left
, (int *)&rect
.top
);
418 wayland_surface_coords_from_window(surface
, rect
.right
, rect
.bottom
,
419 (int *)&rect
.right
, (int *)&rect
.bottom
);
421 /* If the window rect in the monitor is smaller than required,
422 * fall back to an appropriately sized rect at the top-left. */
423 if ((surface
->current
.state
& WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED
) &&
424 (rect
.right
- rect
.left
< surface
->current
.width
||
425 rect
.bottom
- rect
.top
< surface
->current
.height
))
427 SetRect(&rect
, 0, 0, surface
->current
.width
, surface
->current
.height
);
431 rect
.right
= min(rect
.right
, rect
.left
+ surface
->current
.width
);
432 rect
.bottom
= min(rect
.bottom
, rect
.top
+ surface
->current
.height
);
434 TRACE("Window is too large for Wayland state, using subregion\n");
438 SetRect(&rect
, 0, 0, width
, height
);
441 TRACE("hwnd=%p geometry=%s\n", surface
->hwnd
, wine_dbgstr_rect(&rect
));
443 if (!IsRectEmpty(&rect
))
445 xdg_surface_set_window_geometry(surface
->xdg_surface
,
447 rect
.right
- rect
.left
,
448 rect
.bottom
- rect
.top
);
452 /**********************************************************************
453 * wayland_surface_reconfigure_size
455 * Sets the surface size with viewporter
457 static void wayland_surface_reconfigure_size(struct wayland_surface
*surface
,
458 int width
, int height
)
460 TRACE("hwnd=%p size=%dx%d\n", surface
->hwnd
, width
, height
);
462 if (surface
->wp_viewport
)
464 if (width
!= 0 && height
!= 0)
465 wp_viewport_set_destination(surface
->wp_viewport
, width
, height
);
467 wp_viewport_set_destination(surface
->wp_viewport
, -1, -1);
471 /**********************************************************************
472 * wayland_surface_reconfigure_client
474 * Reconfigures the subsurface covering the client area.
476 static void wayland_surface_reconfigure_client(struct wayland_surface
*surface
)
478 struct wayland_window_config
*window
= &surface
->window
;
479 int client_x
, client_y
, x
, y
;
480 int client_width
, client_height
, width
, height
;
482 if (!surface
->client
) return;
484 /* The offset of the client area origin relatively to the window origin. */
485 client_x
= window
->client_rect
.left
- window
->rect
.left
;
486 client_y
= window
->client_rect
.top
- window
->rect
.top
;
488 client_width
= window
->client_rect
.right
- window
->client_rect
.left
;
489 client_height
= window
->client_rect
.bottom
- window
->client_rect
.top
;
491 wayland_surface_coords_from_window(surface
, client_x
, client_y
, &x
, &y
);
492 wayland_surface_coords_from_window(surface
, client_width
, client_height
,
495 TRACE("hwnd=%p subsurface=%d,%d+%dx%d\n", surface
->hwnd
, x
, y
, width
, height
);
497 wl_subsurface_set_position(surface
->client
->wl_subsurface
, x
, y
);
499 if (surface
->client
->wp_viewport
)
501 if (width
!= 0 && height
!= 0)
503 wp_viewport_set_destination(surface
->client
->wp_viewport
,
508 /* We can't have a 0x0 destination, use 1x1 instead. */
509 wp_viewport_set_destination(surface
->client
->wp_viewport
, 1, 1);
513 wl_surface_commit(surface
->client
->wl_surface
);
516 /**********************************************************************
517 * wayland_surface_reconfigure
519 * Reconfigures the wayland surface as needed to match the latest requested
522 BOOL
wayland_surface_reconfigure(struct wayland_surface
*surface
)
524 struct wayland_window_config
*window
= &surface
->window
;
525 int win_width
, win_height
, width
, height
;
527 if (!surface
->xdg_toplevel
) return TRUE
;
529 win_width
= surface
->window
.rect
.right
- surface
->window
.rect
.left
;
530 win_height
= surface
->window
.rect
.bottom
- surface
->window
.rect
.top
;
532 wayland_surface_coords_from_window(surface
, win_width
, win_height
,
535 TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n",
536 surface
->hwnd
, win_width
, win_height
, window
->state
,
537 surface
->processing
.width
, surface
->processing
.height
,
538 surface
->processing
.state
, surface
->current
.width
,
539 surface
->current
.height
, surface
->current
.state
);
541 /* Acknowledge any compatible processed config. */
542 if (surface
->processing
.serial
&& surface
->processing
.processed
&&
543 wayland_surface_config_is_compatible(&surface
->processing
,
547 surface
->current
= surface
->processing
;
548 memset(&surface
->processing
, 0, sizeof(surface
->processing
));
549 xdg_surface_ack_configure(surface
->xdg_surface
, surface
->current
.serial
);
551 /* If this is the initial configure, and we have a compatible requested
552 * config, use that, in order to draw windows that don't go through the
553 * message loop (e.g., some splash screens). */
554 else if (!surface
->current
.serial
&& surface
->requested
.serial
&&
555 wayland_surface_config_is_compatible(&surface
->requested
,
559 surface
->current
= surface
->requested
;
560 memset(&surface
->requested
, 0, sizeof(surface
->requested
));
561 xdg_surface_ack_configure(surface
->xdg_surface
, surface
->current
.serial
);
563 else if (!surface
->current
.serial
||
564 !wayland_surface_config_is_compatible(&surface
->current
,
571 wayland_surface_reconfigure_geometry(surface
, width
, height
);
572 wayland_surface_reconfigure_size(surface
, width
, height
);
573 wayland_surface_reconfigure_client(surface
);
578 /**********************************************************************
579 * wayland_shm_buffer_ref
581 * Increases the reference count of a SHM buffer.
583 void wayland_shm_buffer_ref(struct wayland_shm_buffer
*shm_buffer
)
585 InterlockedIncrement(&shm_buffer
->ref
);
588 /**********************************************************************
589 * wayland_shm_buffer_unref
591 * Decreases the reference count of a SHM buffer (and may destroy it).
593 void wayland_shm_buffer_unref(struct wayland_shm_buffer
*shm_buffer
)
595 if (InterlockedDecrement(&shm_buffer
->ref
) > 0) return;
597 TRACE("destroying %p map=%p\n", shm_buffer
, shm_buffer
->map_data
);
599 if (shm_buffer
->wl_buffer
)
600 wl_buffer_destroy(shm_buffer
->wl_buffer
);
601 if (shm_buffer
->map_data
)
602 NtUnmapViewOfSection(GetCurrentProcess(), shm_buffer
->map_data
);
603 if (shm_buffer
->damage_region
)
604 NtGdiDeleteObjectApp(shm_buffer
->damage_region
);
609 /**********************************************************************
610 * wayland_shm_buffer_create
612 * Creates a SHM buffer with the specified width, height and format.
614 struct wayland_shm_buffer
*wayland_shm_buffer_create(int width
, int height
,
615 enum wl_shm_format format
)
617 struct wayland_shm_buffer
*shm_buffer
= NULL
;
620 SIZE_T view_size
= 0;
621 LARGE_INTEGER section_size
;
623 struct wl_shm_pool
*pool
;
626 stride
= width
* WINEWAYLAND_BYTES_PER_PIXEL
;
627 size
= stride
* height
;
630 ERR("Invalid shm_buffer size %dx%d\n", width
, height
);
634 shm_buffer
= calloc(1, sizeof(*shm_buffer
));
637 ERR("Failed to allocate space for SHM buffer\n");
641 TRACE("%p %dx%d format=%d size=%d\n", shm_buffer
, width
, height
, format
, size
);
644 shm_buffer
->width
= width
;
645 shm_buffer
->height
= height
;
646 shm_buffer
->map_size
= size
;
648 shm_buffer
->damage_region
= NtGdiCreateRectRgn(0, 0, width
, height
);
649 if (!shm_buffer
->damage_region
)
651 ERR("Failed to create buffer damage region\n");
655 section_size
.QuadPart
= size
;
656 status
= NtCreateSection(&handle
,
657 GENERIC_READ
| SECTION_MAP_READ
| SECTION_MAP_WRITE
,
658 NULL
, §ion_size
, PAGE_READWRITE
, SEC_COMMIT
, 0);
661 ERR("Failed to create SHM section status=0x%lx\n", (long)status
);
665 status
= NtMapViewOfSection(handle
, GetCurrentProcess(),
666 (PVOID
)&shm_buffer
->map_data
, 0, 0, NULL
,
667 &view_size
, ViewUnmap
, 0, PAGE_READWRITE
);
670 shm_buffer
->map_data
= NULL
;
671 ERR("Failed to create map SHM handle status=0x%lx\n", (long)status
);
675 status
= wine_server_handle_to_fd(handle
, FILE_READ_DATA
, &fd
, NULL
);
678 ERR("Failed to get fd from SHM handle status=0x%lx\n", (long)status
);
682 pool
= wl_shm_create_pool(process_wayland
.wl_shm
, fd
, size
);
685 ERR("Failed to create SHM pool fd=%d size=%d\n", fd
, size
);
688 shm_buffer
->wl_buffer
= wl_shm_pool_create_buffer(pool
, 0, width
, height
,
690 wl_shm_pool_destroy(pool
);
691 if (!shm_buffer
->wl_buffer
)
693 ERR("Failed to create SHM buffer %dx%d\n", width
, height
);
700 TRACE("=> map=%p\n", shm_buffer
->map_data
);
705 if (fd
>= 0) close(fd
);
706 if (handle
) NtClose(handle
);
707 if (shm_buffer
) wayland_shm_buffer_unref(shm_buffer
);
711 /**********************************************************************
712 * wayland_surface_coords_from_window
714 * Converts the window (logical) coordinates to wayland surface-local coordinates.
716 void wayland_surface_coords_from_window(struct wayland_surface
*surface
,
717 int window_x
, int window_y
,
718 int *surface_x
, int *surface_y
)
720 *surface_x
= round(window_x
/ surface
->window
.scale
);
721 *surface_y
= round(window_y
/ surface
->window
.scale
);
724 /**********************************************************************
725 * wayland_surface_coords_to_window
727 * Converts the surface-local coordinates to window (logical) coordinates.
729 void wayland_surface_coords_to_window(struct wayland_surface
*surface
,
730 double surface_x
, double surface_y
,
731 int *window_x
, int *window_y
)
733 *window_x
= round(surface_x
* surface
->window
.scale
);
734 *window_y
= round(surface_y
* surface
->window
.scale
);
737 /**********************************************************************
738 * wayland_client_surface_release
740 BOOL
wayland_client_surface_release(struct wayland_client_surface
*client
)
742 if (InterlockedDecrement(&client
->ref
)) return FALSE
;
744 if (client
->wp_viewport
)
745 wp_viewport_destroy(client
->wp_viewport
);
746 if (client
->wl_subsurface
)
747 wl_subsurface_destroy(client
->wl_subsurface
);
748 if (client
->wl_surface
)
749 wl_surface_destroy(client
->wl_surface
);
756 /**********************************************************************
757 * wayland_surface_get_client
759 struct wayland_client_surface
*wayland_surface_get_client(struct wayland_surface
*surface
)
761 struct wl_region
*empty_region
;
765 InterlockedIncrement(&surface
->client
->ref
);
766 return surface
->client
;
769 surface
->client
= calloc(1, sizeof(*surface
->client
));
770 if (!surface
->client
)
772 ERR("Failed to allocate space for client surface\n");
776 surface
->client
->ref
= 1;
778 surface
->client
->wl_surface
=
779 wl_compositor_create_surface(process_wayland
.wl_compositor
);
780 if (!surface
->client
->wl_surface
)
782 ERR("Failed to create client wl_surface\n");
785 wl_surface_set_user_data(surface
->client
->wl_surface
, surface
->hwnd
);
787 /* Let parent handle all pointer events. */
788 empty_region
= wl_compositor_create_region(process_wayland
.wl_compositor
);
791 ERR("Failed to create wl_region\n");
794 wl_surface_set_input_region(surface
->client
->wl_surface
, empty_region
);
795 wl_region_destroy(empty_region
);
797 surface
->client
->wl_subsurface
=
798 wl_subcompositor_get_subsurface(process_wayland
.wl_subcompositor
,
799 surface
->client
->wl_surface
,
800 surface
->wl_surface
);
801 if (!surface
->client
->wl_subsurface
)
803 ERR("Failed to create client wl_subsurface\n");
807 if (process_wayland
.wp_viewporter
)
809 surface
->client
->wp_viewport
=
810 wp_viewporter_get_viewport(process_wayland
.wp_viewporter
,
811 surface
->client
->wl_surface
);
814 wayland_surface_reconfigure_client(surface
);
816 return surface
->client
;
821 wayland_client_surface_release(surface
->client
);
822 surface
->client
= NULL
;