mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-04 20:17:38 +00:00
winewayland.drv: Handle window foreground state on keyboard focus.
Borrow the concept of "managed" windows from WineX11 and use it to decide whether a window should become the foreground window when receiving the Wayland keyboard focus.
This commit is contained in:
parent
57a391b85b
commit
7841182172
|
@ -698,6 +698,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
|
|||
struct wl_array *keys)
|
||||
{
|
||||
struct wayland_keyboard *keyboard = &process_wayland.keyboard;
|
||||
struct wayland_surface *surface;
|
||||
HWND hwnd;
|
||||
|
||||
if (!wl_surface) return;
|
||||
|
@ -713,6 +714,12 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
|
|||
|
||||
NtUserPostMessage(keyboard->focused_hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/,
|
||||
(LPARAM)keyboard_hkl);
|
||||
|
||||
if ((surface = wayland_surface_lock_hwnd(hwnd)))
|
||||
{
|
||||
if (surface->window.managed) NtUserSetForegroundWindow(hwnd);
|
||||
pthread_mutex_unlock(&surface->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
|
||||
|
|
|
@ -167,6 +167,7 @@ struct wayland_window_config
|
|||
/* The scale (i.e., normalized dpi) the window is rendering at. */
|
||||
double scale;
|
||||
BOOL visible;
|
||||
BOOL managed;
|
||||
};
|
||||
|
||||
struct wayland_client_surface
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
|
||||
#include "waylanddrv.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
@ -47,6 +50,7 @@ struct wayland_win_data
|
|||
RECT window_rect;
|
||||
/* USER client rectangle relative to win32 parent window client area */
|
||||
RECT client_rect;
|
||||
BOOL managed;
|
||||
};
|
||||
|
||||
static int wayland_win_data_cmp_rb(const void *key,
|
||||
|
@ -182,6 +186,7 @@ static void wayland_win_data_get_config(struct wayland_win_data *data,
|
|||
conf->state = window_state;
|
||||
conf->scale = NtUserGetDpiForWindow(data->hwnd) / 96.0;
|
||||
conf->visible = (style & WS_VISIBLE) == WS_VISIBLE;
|
||||
conf->managed = data->managed;
|
||||
}
|
||||
|
||||
static void wayland_win_data_update_wayland_surface(struct wayland_win_data *data)
|
||||
|
@ -287,6 +292,99 @@ out:
|
|||
wl_display_flush(process_wayland.wl_display);
|
||||
}
|
||||
|
||||
static BOOL is_managed(HWND hwnd)
|
||||
{
|
||||
struct wayland_win_data *data = wayland_win_data_get(hwnd);
|
||||
BOOL ret = data && data->managed;
|
||||
if (data) wayland_win_data_release(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HWND *build_hwnd_list(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HWND *list;
|
||||
ULONG count = 128;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(list = malloc(count * sizeof(*list)))) return NULL;
|
||||
status = NtUserBuildHwndList(0, 0, 0, 0, 0, count, list, &count);
|
||||
if (!status) return list;
|
||||
free(list);
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL has_owned_popups(HWND hwnd)
|
||||
{
|
||||
HWND *list;
|
||||
UINT i;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!(list = build_hwnd_list())) return FALSE;
|
||||
|
||||
for (i = 0; list[i] != HWND_BOTTOM; i++)
|
||||
{
|
||||
if (list[i] == hwnd) break; /* popups are always above owner */
|
||||
if (NtUserGetWindowRelative(list[i], GW_OWNER) != hwnd) continue;
|
||||
if ((ret = is_managed(list[i]))) break;
|
||||
}
|
||||
|
||||
free(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline HWND get_active_window(void)
|
||||
{
|
||||
GUITHREADINFO info;
|
||||
info.cbSize = sizeof(info);
|
||||
return NtUserGetGUIThreadInfo(GetCurrentThreadId(), &info) ? info.hwndActive : 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* is_window_managed
|
||||
*
|
||||
* Check if a given window should be managed
|
||||
*/
|
||||
static BOOL is_window_managed(HWND hwnd, UINT swp_flags, const RECT *window_rect)
|
||||
{
|
||||
DWORD style, ex_style;
|
||||
|
||||
/* child windows are not managed */
|
||||
style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
|
||||
if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) return FALSE;
|
||||
/* activated windows are managed */
|
||||
if (!(swp_flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) return TRUE;
|
||||
if (hwnd == get_active_window()) return TRUE;
|
||||
/* windows with caption are managed */
|
||||
if ((style & WS_CAPTION) == WS_CAPTION) return TRUE;
|
||||
/* windows with thick frame are managed */
|
||||
if (style & WS_THICKFRAME) return TRUE;
|
||||
if (style & WS_POPUP)
|
||||
{
|
||||
HMONITOR hmon;
|
||||
MONITORINFO mi;
|
||||
|
||||
/* popup with sysmenu == caption are managed */
|
||||
if (style & WS_SYSMENU) return TRUE;
|
||||
/* full-screen popup windows are managed */
|
||||
hmon = NtUserMonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
|
||||
mi.cbSize = sizeof(mi);
|
||||
NtUserGetMonitorInfo(hmon, &mi);
|
||||
if (window_rect->left <= mi.rcWork.left && window_rect->right >= mi.rcWork.right &&
|
||||
window_rect->top <= mi.rcWork.top && window_rect->bottom >= mi.rcWork.bottom)
|
||||
return TRUE;
|
||||
}
|
||||
/* application windows are managed */
|
||||
ex_style = NtUserGetWindowLongW(hwnd, GWL_EXSTYLE);
|
||||
if (ex_style & WS_EX_APPWINDOW) return TRUE;
|
||||
/* windows that own popups are managed */
|
||||
if (has_owned_popups(hwnd)) return TRUE;
|
||||
/* default: not managed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WAYLAND_DestroyWindow
|
||||
*/
|
||||
|
@ -369,6 +467,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
|
|||
|
||||
data->window_rect = *window_rect;
|
||||
data->client_rect = *client_rect;
|
||||
data->managed = is_window_managed(hwnd, swp_flags, window_rect);
|
||||
|
||||
if (surface) window_surface_add_ref(surface);
|
||||
if (data->window_surface) window_surface_release(data->window_surface);
|
||||
|
|
Loading…
Reference in a new issue