1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-08 20:06:18 +00:00

winewayland.drv: Introduce window_surface for Wayland.

This commit is contained in:
Alexandros Frantzis 2023-05-05 11:20:10 +03:00 committed by Alexandre Julliard
parent a7ec328fa8
commit d53cb7206d
4 changed files with 229 additions and 1 deletions

View File

@ -12,5 +12,6 @@ SOURCES = \
wayland_surface.c \
waylanddrv_main.c \
window.c \
window_surface.c \
xdg-output-unstable-v1.xml \
xdg-shell.xml

View File

@ -126,6 +126,12 @@ void wayland_surface_destroy(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_make_toplevel(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_clear_role(struct wayland_surface *surface) DECLSPEC_HIDDEN;
/**********************************************************************
* Wayland window surface
*/
struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect) DECLSPEC_HIDDEN;
/**********************************************************************
* USER driver functions
*/

View File

@ -41,6 +41,8 @@ struct wayland_win_data
HWND hwnd;
/* wayland surface (if any) for this window */
struct wayland_surface *wayland_surface;
/* wine window_surface backing this window */
struct window_surface *window_surface;
};
static int wayland_win_data_cmp_rb(const void *key,
@ -105,6 +107,7 @@ static void wayland_win_data_destroy(struct wayland_win_data *data)
pthread_mutex_unlock(&win_data_mutex);
if (data->window_surface) window_surface_release(data->window_surface);
if (data->wayland_surface) wayland_surface_destroy(data->wayland_surface);
free(data);
}
@ -201,6 +204,9 @@ BOOL WAYLAND_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
RECT *visible_rect, struct window_surface **surface)
{
struct wayland_win_data *data = wayland_win_data_get(hwnd);
HWND parent;
BOOL visible;
RECT surface_rect;
TRACE("hwnd %p window %s client %s visible %s after %p flags %08x\n",
hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
@ -208,8 +214,35 @@ BOOL WAYLAND_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags,
if (!data && !(data = wayland_win_data_create(hwnd))) return TRUE;
wayland_win_data_release(data);
/* Release the dummy surface wine provides for toplevels. */
if (*surface) window_surface_release(*surface);
*surface = NULL;
parent = NtUserGetAncestor(hwnd, GA_PARENT);
visible = ((NtUserGetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE) ||
(swp_flags & SWP_SHOWWINDOW)) &&
!(swp_flags & SWP_HIDEWINDOW);
/* Check if we don't want a dedicated window surface. */
if ((parent && parent != NtUserGetDesktopWindow()) || !visible) goto done;
surface_rect = *window_rect;
OffsetRect(&surface_rect, -surface_rect.left, -surface_rect.top);
/* Check if we can reuse our current window surface. */
if (data->window_surface &&
EqualRect(&data->window_surface->rect, &surface_rect))
{
window_surface_add_ref(data->window_surface);
*surface = data->window_surface;
TRACE("reusing surface %p\n", *surface);
goto done;
}
*surface = wayland_window_surface_create(data->hwnd, &surface_rect);
done:
wayland_win_data_release(data);
return TRUE;
}
@ -229,6 +262,10 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
if (!data) return;
if (surface) window_surface_add_ref(surface);
if (data->window_surface) window_surface_release(data->window_surface);
data->window_surface = surface;
wayland_win_data_update_wayland_surface(data);
wayland_win_data_release(data);

View File

@ -0,0 +1,184 @@
/*
* Wayland window surface implementation
*
* Copyright 2020 Alexandros Frantzis for Collabora Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#if 0
#pragma makedep unix
#endif
#include "config.h"
#include <limits.h>
#include <stdlib.h>
#include "waylanddrv.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
struct wayland_window_surface
{
struct window_surface header;
HWND hwnd;
RECT bounds;
void *bits;
pthread_mutex_t mutex;
BITMAPINFO info;
};
static struct wayland_window_surface *wayland_window_surface_cast(
struct window_surface *window_surface)
{
return (struct wayland_window_surface *)window_surface;
}
static inline void reset_bounds(RECT *bounds)
{
bounds->left = bounds->top = INT_MAX;
bounds->right = bounds->bottom = INT_MIN;
}
/***********************************************************************
* wayland_window_surface_lock
*/
static void wayland_window_surface_lock(struct window_surface *window_surface)
{
struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface);
pthread_mutex_lock(&wws->mutex);
}
/***********************************************************************
* wayland_window_surface_unlock
*/
static void wayland_window_surface_unlock(struct window_surface *window_surface)
{
struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface);
pthread_mutex_unlock(&wws->mutex);
}
/***********************************************************************
* wayland_window_surface_get_bitmap_info
*/
static void *wayland_window_surface_get_bitmap_info(struct window_surface *window_surface,
BITMAPINFO *info)
{
struct wayland_window_surface *surface = wayland_window_surface_cast(window_surface);
/* We don't store any additional information at the end of our BITMAPINFO, so
* just copy the structure itself. */
memcpy(info, &surface->info, sizeof(*info));
return surface->bits;
}
/***********************************************************************
* wayland_window_surface_get_bounds
*/
static RECT *wayland_window_surface_get_bounds(struct window_surface *window_surface)
{
struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface);
return &wws->bounds;
}
/***********************************************************************
* wayland_window_surface_set_region
*/
static void wayland_window_surface_set_region(struct window_surface *window_surface,
HRGN region)
{
/* TODO */
}
/***********************************************************************
* wayland_window_surface_flush
*/
static void wayland_window_surface_flush(struct window_surface *window_surface)
{
/* TODO */
}
/***********************************************************************
* wayland_window_surface_destroy
*/
static void wayland_window_surface_destroy(struct window_surface *window_surface)
{
struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface);
TRACE("surface=%p\n", wws);
pthread_mutex_destroy(&wws->mutex);
free(wws->bits);
free(wws);
}
static const struct window_surface_funcs wayland_window_surface_funcs =
{
wayland_window_surface_lock,
wayland_window_surface_unlock,
wayland_window_surface_get_bitmap_info,
wayland_window_surface_get_bounds,
wayland_window_surface_set_region,
wayland_window_surface_flush,
wayland_window_surface_destroy
};
/***********************************************************************
* wayland_window_surface_create
*/
struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect)
{
struct wayland_window_surface *wws;
int width = rect->right - rect->left;
int height = rect->bottom - rect->top;
pthread_mutexattr_t mutexattr;
TRACE("hwnd %p rect %s\n", hwnd, wine_dbgstr_rect(rect));
wws = calloc(1, sizeof(*wws));
if (!wws) return NULL;
wws->info.bmiHeader.biSize = sizeof(wws->info.bmiHeader);
wws->info.bmiHeader.biClrUsed = 0;
wws->info.bmiHeader.biBitCount = 32;
wws->info.bmiHeader.biCompression = BI_RGB;
wws->info.bmiHeader.biWidth = width;
wws->info.bmiHeader.biHeight = -height; /* top-down */
wws->info.bmiHeader.biPlanes = 1;
wws->info.bmiHeader.biSizeImage = width * height * 4;
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&wws->mutex, &mutexattr);
pthread_mutexattr_destroy(&mutexattr);
wws->header.funcs = &wayland_window_surface_funcs;
wws->header.rect = *rect;
wws->header.ref = 1;
wws->hwnd = hwnd;
reset_bounds(&wws->bounds);
if (!(wws->bits = malloc(wws->info.bmiHeader.biSizeImage)))
goto failed;
TRACE("created %p hwnd %p %s bits [%p,%p)\n", wws, hwnd, wine_dbgstr_rect(rect),
wws->bits, (char *)wws->bits + wws->info.bmiHeader.biSizeImage);
return &wws->header;
failed:
wayland_window_surface_destroy(&wws->header);
return NULL;
}