mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 04:08:31 +00:00
winewayland: Clip huge window surfaces to the virtual screen rect.
This commit is contained in:
parent
98c669b1c2
commit
970c3f9d42
|
@ -236,6 +236,7 @@ void wayland_output_use_xdg_extension(struct wayland_output *output);
|
|||
* Wayland surface
|
||||
*/
|
||||
|
||||
BOOL get_surface_rect(const RECT *visible_rect, RECT *surface_rect);
|
||||
struct wayland_surface *wayland_surface_create(HWND hwnd);
|
||||
void wayland_surface_destroy(struct wayland_surface *surface);
|
||||
void wayland_surface_make_toplevel(struct wayland_surface *surface);
|
||||
|
@ -272,7 +273,7 @@ void wayland_shm_buffer_unref(struct wayland_shm_buffer *shm_buffer);
|
|||
* Wayland window surface
|
||||
*/
|
||||
|
||||
void wayland_window_surface_update_wayland_surface(struct window_surface *surface,
|
||||
void wayland_window_surface_update_wayland_surface(struct window_surface *surface, const RECT *visible_rect,
|
||||
struct wayland_surface *wayland_surface);
|
||||
void wayland_window_flush(HWND hwnd);
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ static void wayland_win_data_destroy(struct wayland_win_data *data)
|
|||
|
||||
if (data->window_surface)
|
||||
{
|
||||
wayland_window_surface_update_wayland_surface(data->window_surface, NULL);
|
||||
wayland_window_surface_update_wayland_surface(data->window_surface, NULL, NULL);
|
||||
window_surface_release(data->window_surface);
|
||||
}
|
||||
if (data->wayland_surface) wayland_surface_destroy(data->wayland_surface);
|
||||
|
@ -200,20 +200,20 @@ static void reapply_cursor_clipping(void)
|
|||
NtUserSetThreadDpiAwarenessContext(context);
|
||||
}
|
||||
|
||||
static void wayland_win_data_update_wayland_surface(struct wayland_win_data *data)
|
||||
static void wayland_win_data_update_wayland_surface(struct wayland_win_data *data, const RECT *visible_rect)
|
||||
{
|
||||
struct wayland_surface *surface = data->wayland_surface;
|
||||
HWND parent = NtUserGetAncestor(data->hwnd, GA_PARENT);
|
||||
BOOL visible, xdg_visible;
|
||||
WCHAR text[1024];
|
||||
|
||||
TRACE("hwnd=%p\n", data->hwnd);
|
||||
TRACE("hwnd=%p, rect=%s\n", data->hwnd, wine_dbgstr_rect(visible_rect));
|
||||
|
||||
/* We don't want wayland surfaces for child windows. */
|
||||
if (parent != NtUserGetDesktopWindow() && parent != 0)
|
||||
{
|
||||
if (data->window_surface)
|
||||
wayland_window_surface_update_wayland_surface(data->window_surface, NULL);
|
||||
wayland_window_surface_update_wayland_surface(data->window_surface, NULL, NULL);
|
||||
if (surface) wayland_surface_destroy(surface);
|
||||
surface = NULL;
|
||||
goto out;
|
||||
|
@ -251,7 +251,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
|
|||
pthread_mutex_unlock(&surface->mutex);
|
||||
|
||||
if (data->window_surface)
|
||||
wayland_window_surface_update_wayland_surface(data->window_surface, surface);
|
||||
wayland_window_surface_update_wayland_surface(data->window_surface, visible_rect, surface);
|
||||
|
||||
/* Size/position changes affect the effective pointer constraint, so update
|
||||
* it as needed. */
|
||||
|
@ -432,6 +432,7 @@ BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rec
|
|||
struct wayland_win_data *data = wayland_win_data_get(hwnd);
|
||||
HWND parent;
|
||||
BOOL visible, ret = FALSE;
|
||||
RECT surface_rect;
|
||||
|
||||
TRACE("hwnd %p window %s client %s visible %s flags %08x\n",
|
||||
hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect),
|
||||
|
@ -445,6 +446,7 @@ BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rec
|
|||
!(swp_flags & SWP_HIDEWINDOW);
|
||||
|
||||
if ((parent && parent != NtUserGetDesktopWindow()) || !visible) goto done; /* use default surface */
|
||||
if (!get_surface_rect( visible_rect, &surface_rect )) goto done; /* use default surface */
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
|
@ -484,7 +486,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
|
|||
if (data->window_surface) window_surface_release(data->window_surface);
|
||||
data->window_surface = surface;
|
||||
|
||||
wayland_win_data_update_wayland_surface(data);
|
||||
wayland_win_data_update_wayland_surface(data, visible_rect);
|
||||
if (data->wayland_surface) wayland_win_data_update_wayland_state(data);
|
||||
|
||||
wayland_win_data_release(data);
|
||||
|
|
|
@ -283,8 +283,8 @@ static void copy_pixel_region(char *src_pixels, RECT *src_rect,
|
|||
if (!intersect_rect(&rc, rgn_rect, src_rect)) continue;
|
||||
if (!intersect_rect(&rc, &rc, dst_rect)) continue;
|
||||
|
||||
src = src_pixels + rc.top * src_stride + rc.left * bpp;
|
||||
dst = dst_pixels + rc.top * dst_stride + rc.left * bpp;
|
||||
src = src_pixels + (rc.top - src_rect->top) * src_stride + (rc.left - src_rect->left) * bpp;
|
||||
dst = dst_pixels + (rc.top - dst_rect->top) * dst_stride + (rc.left - dst_rect->left) * bpp;
|
||||
width_bytes = (rc.right - rc.left) * bpp;
|
||||
height = rc.bottom - rc.top;
|
||||
|
||||
|
@ -346,7 +346,8 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface,
|
|||
goto done;
|
||||
}
|
||||
|
||||
surface_damage_region = NtGdiCreateRectRgn(dirty->left, dirty->top, dirty->right, dirty->bottom);
|
||||
surface_damage_region = NtGdiCreateRectRgn(rect->left + dirty->left, rect->top + dirty->top,
|
||||
rect->left + dirty->right, rect->top + dirty->bottom);
|
||||
if (!surface_damage_region)
|
||||
{
|
||||
ERR("failed to create surface damage region\n");
|
||||
|
@ -486,7 +487,7 @@ failed:
|
|||
/***********************************************************************
|
||||
* wayland_window_surface_update_wayland_surface
|
||||
*/
|
||||
void wayland_window_surface_update_wayland_surface(struct window_surface *window_surface,
|
||||
void wayland_window_surface_update_wayland_surface(struct window_surface *window_surface, const RECT *visible_rect,
|
||||
struct wayland_surface *wayland_surface)
|
||||
{
|
||||
struct wayland_window_surface *wws;
|
||||
|
@ -497,27 +498,51 @@ void wayland_window_surface_update_wayland_surface(struct window_surface *window
|
|||
wws = wayland_window_surface_cast(window_surface);
|
||||
window_surface_lock(window_surface);
|
||||
|
||||
TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws, window_surface->hwnd, wayland_surface);
|
||||
TRACE("surface=%p hwnd=%p visible_rect=%s wayland_surface=%p\n", wws, window_surface->hwnd,
|
||||
wine_dbgstr_rect(visible_rect), wayland_surface);
|
||||
|
||||
wws->wayland_surface = wayland_surface;
|
||||
|
||||
/* We only need a buffer queue if we have a surface to commit to. */
|
||||
if (wws->wayland_surface && !wws->wayland_buffer_queue)
|
||||
{
|
||||
wws->wayland_buffer_queue =
|
||||
wayland_buffer_queue_create(wws->info.bmiHeader.biWidth,
|
||||
abs(wws->info.bmiHeader.biHeight));
|
||||
}
|
||||
else if (!wws->wayland_surface && wws->wayland_buffer_queue)
|
||||
if (wws->wayland_buffer_queue)
|
||||
{
|
||||
wayland_buffer_queue_destroy(wws->wayland_buffer_queue);
|
||||
wws->wayland_buffer_queue = NULL;
|
||||
}
|
||||
|
||||
/* We only need a buffer queue if we have a surface to commit to. */
|
||||
if (wws->wayland_surface)
|
||||
{
|
||||
wws->wayland_buffer_queue =
|
||||
wayland_buffer_queue_create(visible_rect->right - visible_rect->left,
|
||||
visible_rect->bottom - visible_rect->top);
|
||||
}
|
||||
|
||||
window_surface_unlock(window_surface);
|
||||
}
|
||||
|
||||
|
||||
BOOL get_surface_rect(const RECT *visible_rect, RECT *surface_rect)
|
||||
{
|
||||
RECT virtual_rect = NtUserGetVirtualScreenRect();
|
||||
|
||||
*surface_rect = *visible_rect;
|
||||
|
||||
/* crop surfaces which are larger than the virtual screen rect, some applications create huge windows */
|
||||
if ((surface_rect->right - surface_rect->left > virtual_rect.right - virtual_rect.left ||
|
||||
surface_rect->bottom - surface_rect->top > virtual_rect.bottom - virtual_rect.top) &&
|
||||
!intersect_rect( surface_rect, surface_rect, &virtual_rect ))
|
||||
return FALSE;
|
||||
OffsetRect(surface_rect, -visible_rect->left, -visible_rect->top);
|
||||
|
||||
/* round the surface coordinates to avoid re-creating them too often on resize */
|
||||
surface_rect->left &= ~127;
|
||||
surface_rect->top &= ~127;
|
||||
surface_rect->right = max(surface_rect->left + 128, (surface_rect->right + 127) & ~127);
|
||||
surface_rect->bottom = max(surface_rect->top + 128, (surface_rect->bottom + 127) & ~127);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WAYLAND_CreateWindowSurface
|
||||
*/
|
||||
|
@ -529,14 +554,12 @@ BOOL WAYLAND_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_
|
|||
TRACE("hwnd %p, swp_flags %08x, visible %s, surface %p\n", hwnd, swp_flags, wine_dbgstr_rect(visible_rect), surface);
|
||||
|
||||
if (!(data = wayland_win_data_get(hwnd))) return TRUE; /* use default surface */
|
||||
if (!get_surface_rect( visible_rect, &surface_rect )) goto done; /* use default surface */
|
||||
|
||||
/* Release the dummy surface wine provides for toplevels. */
|
||||
if (*surface) window_surface_release(*surface);
|
||||
*surface = NULL;
|
||||
|
||||
surface_rect = *visible_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))
|
||||
|
|
Loading…
Reference in a new issue