mirror of
https://github.com/reactos/reactos.git
synced 2024-06-25 23:41:35 +00:00
CORE-11944
This commit is contained in:
parent
99b055a506
commit
f469acacec
20
win32ss/include/ghostwnd.h
Normal file
20
win32ss/include/ghostwnd.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS header
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Ghost window
|
||||||
|
* COPYRIGHT: Copyright 2018 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
|
*/
|
||||||
|
#ifndef REACTOS_GHOST_WND_INCLUDED
|
||||||
|
#define REACTOS_GHOST_WND_INCLUDED
|
||||||
|
|
||||||
|
#define GHOSTCLASSNAME L"Ghost"
|
||||||
|
#define GHOST_PROP L"GhostProp"
|
||||||
|
|
||||||
|
typedef struct GHOST_DATA
|
||||||
|
{
|
||||||
|
HWND hwndTarget;
|
||||||
|
HBITMAP hbm32bpp;
|
||||||
|
BOOL bDestroyTarget;
|
||||||
|
} GHOST_DATA;
|
||||||
|
|
||||||
|
#endif
|
|
@ -66,4 +66,12 @@ ProbeAndCaptureUnicodeStringOrAtom(
|
||||||
_Out_ _When_(return>=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut,
|
_Out_ _When_(return>=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut,
|
||||||
__in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe);
|
__in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe);
|
||||||
|
|
||||||
|
BOOL FASTCALL LookupFnIdToiCls(int FnId, int *iCls);
|
||||||
|
|
||||||
|
INT
|
||||||
|
UserGetClassName(IN PCLS Class,
|
||||||
|
IN OUT PUNICODE_STRING ClassName,
|
||||||
|
IN RTL_ATOM Atom,
|
||||||
|
IN BOOL Ansi);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,23 +1,178 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS user32.dll
|
* PROJECT: ReactOS user32.dll
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: Ghost window handling
|
* PURPOSE: Window ghosting feature
|
||||||
* COPYRIGHT: Copyright 2018 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
* COPYRIGHT: Copyright 2018 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <win32k.h>
|
#include <win32k.h>
|
||||||
|
#include "ghostwnd.h"
|
||||||
|
|
||||||
BOOL FASTCALL IntGoGhost(PWND Window, BOOL bGo)
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
static UNICODE_STRING GhostClass = RTL_CONSTANT_STRING(GHOSTCLASSNAME);
|
||||||
|
static UNICODE_STRING GhostProp = RTL_CONSTANT_STRING(GHOST_PROP);
|
||||||
|
|
||||||
|
BOOL FASTCALL IntIsGhostWindow(PWND Window)
|
||||||
{
|
{
|
||||||
|
BOOLEAN Ret = FALSE;
|
||||||
|
UNICODE_STRING ClassName;
|
||||||
|
INT iCls, Len;
|
||||||
|
RTL_ATOM Atom = 0;
|
||||||
|
|
||||||
|
if (!Window)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (Window->fnid && !(Window->fnid & FNID_DESTROY))
|
||||||
|
{
|
||||||
|
if (LookupFnIdToiCls(Window->fnid, &iCls))
|
||||||
|
{
|
||||||
|
Atom = gpsi->atomSysClass[iCls];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check class name
|
||||||
|
RtlInitUnicodeString(&ClassName, NULL);
|
||||||
|
Len = UserGetClassName(Window->pcls, &ClassName, Atom, FALSE);
|
||||||
|
if (Len > 0)
|
||||||
|
{
|
||||||
|
Ret = RtlEqualUnicodeString(&ClassName, &GhostClass, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("Unable to get class name\n");
|
||||||
|
}
|
||||||
|
RtlFreeUnicodeString(&ClassName);
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND FASTCALL IntGhostWindowFromHungWindow(PWND pHungWnd)
|
||||||
|
{
|
||||||
|
RTL_ATOM Atom;
|
||||||
|
HWND hwndGhost;
|
||||||
|
|
||||||
|
if (!IntGetAtomFromStringOrAtom(&GhostProp, &Atom))
|
||||||
|
ASSERT(FALSE);
|
||||||
|
|
||||||
|
hwndGhost = UserGetProp(pHungWnd, Atom, TRUE);
|
||||||
|
if (hwndGhost)
|
||||||
|
{
|
||||||
|
if (ValidateHwndNoErr(hwndGhost))
|
||||||
|
return hwndGhost;
|
||||||
|
|
||||||
|
DPRINT("Not a window\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND FASTCALL UserGhostWindowFromHungWindow(HWND hwndHung)
|
||||||
|
{
|
||||||
|
PWND pHungWnd = ValidateHwndNoErr(hwndHung);
|
||||||
|
if (!pHungWnd)
|
||||||
|
{
|
||||||
|
DPRINT("Not a window\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return IntGhostWindowFromHungWindow(pHungWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND FASTCALL IntHungWindowFromGhostWindow(PWND pGhostWnd)
|
||||||
|
{
|
||||||
|
const GHOST_DATA *UserData;
|
||||||
|
HWND hwndTarget;
|
||||||
|
|
||||||
|
if (!IntIsGhostWindow(pGhostWnd))
|
||||||
|
{
|
||||||
|
DPRINT("Not a ghost window\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserData = (const GHOST_DATA *)pGhostWnd->dwUserData;
|
||||||
|
if (UserData)
|
||||||
|
{
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(UserData, sizeof(GHOST_DATA), 1);
|
||||||
|
hwndTarget = UserData->hwndTarget;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
DPRINT1("Exception!\n");
|
||||||
|
hwndTarget = NULL;
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("No user data\n");
|
||||||
|
hwndTarget = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hwndTarget)
|
||||||
|
{
|
||||||
|
if (ValidateHwndNoErr(hwndTarget))
|
||||||
|
return hwndTarget;
|
||||||
|
|
||||||
|
DPRINT1("Not a window\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND FASTCALL UserHungWindowFromGhostWindow(HWND hwndGhost)
|
||||||
|
{
|
||||||
|
PWND pGhostWnd = ValidateHwndNoErr(hwndGhost);
|
||||||
|
return IntHungWindowFromGhostWindow(pGhostWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung)
|
||||||
|
{
|
||||||
|
PWND pHungWnd = ValidateHwndNoErr(hwndHung);
|
||||||
|
if (!pHungWnd)
|
||||||
|
{
|
||||||
|
DPRINT1("Not a window\n");
|
||||||
|
return FALSE; // not a window
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MsqIsHung(pHungWnd->head.pti))
|
||||||
|
{
|
||||||
|
DPRINT1("Not hung window\n");
|
||||||
|
return FALSE; // not hung window
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pHungWnd->style & WS_VISIBLE))
|
||||||
|
return FALSE; // invisible
|
||||||
|
|
||||||
|
if (pHungWnd->style & WS_CHILD)
|
||||||
|
return FALSE; // child
|
||||||
|
|
||||||
|
if (IntIsGhostWindow(pHungWnd))
|
||||||
|
{
|
||||||
|
DPRINT1("IntIsGhostWindow\n");
|
||||||
|
return FALSE; // ghost window cannot be ghosted
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IntGhostWindowFromHungWindow(pHungWnd))
|
||||||
|
{
|
||||||
|
DPRINT("Already ghosting\n");
|
||||||
|
return FALSE; // already ghosting
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// 1. Create a thread.
|
// 1. Create a thread.
|
||||||
// 2. Create a ghost window in the thread.
|
// 2. Create a ghost window in the thread.
|
||||||
// 3. Do message loop in the thread
|
// 3. Do message loop in the thread
|
||||||
static int bWarnedOnce = 0;
|
|
||||||
if (!bWarnedOnce)
|
|
||||||
{
|
{
|
||||||
bWarnedOnce++;
|
static int bWarnedOnce = 0;
|
||||||
STUB;
|
if (!bWarnedOnce)
|
||||||
|
{
|
||||||
|
bWarnedOnce++;
|
||||||
|
STUB;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
BOOL FASTCALL IntGoGhost(PWND Window, BOOL bGo);
|
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung);
|
||||||
|
|
|
@ -1441,9 +1441,6 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
|
||||||
/* FIXME: Set a LastError? */
|
/* FIXME: Set a LastError? */
|
||||||
RETURN( FALSE);
|
RETURN( FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Let's go Ghost!\n");
|
|
||||||
IntGoGhost(Window, TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Window->state & WNDS_DESTROYED)
|
if (Window->state & WNDS_DESTROYED)
|
||||||
|
@ -1471,6 +1468,11 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
|
||||||
|
|
||||||
if (Status == STATUS_TIMEOUT)
|
if (Status == STATUS_TIMEOUT)
|
||||||
{
|
{
|
||||||
|
if (MsqIsHung(ptiSendTo))
|
||||||
|
{
|
||||||
|
TRACE("Let's go Ghost!\n");
|
||||||
|
IntMakeHungWindowGhosted(hWnd);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* MSDN says:
|
* MSDN says:
|
||||||
* Microsoft Windows 2000: If GetLastError returns zero, then the function
|
* Microsoft Windows 2000: If GetLastError returns zero, then the function
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
|
|
||||||
#include <user32.h>
|
#include <user32.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
#include "ghostwnd.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ghost);
|
WINE_DEFAULT_DEBUG_CHANNEL(ghost);
|
||||||
|
|
||||||
#define GHOST_TIMER_ID 0xFACEDEAD
|
#define GHOST_TIMER_ID 0xFACEDEAD
|
||||||
#define GHOST_INTERVAL 1000 // one second
|
#define GHOST_INTERVAL 1000 // one second
|
||||||
#define GHOST_PROP L"GhostProp"
|
|
||||||
|
|
||||||
const struct builtin_class_descr GHOST_builtin_class =
|
const struct builtin_class_descr GHOST_builtin_class =
|
||||||
{
|
{
|
||||||
|
@ -105,13 +105,6 @@ IntMakeGhostImage(HBITMAP hbm)
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
typedef struct GHOST_DATA
|
|
||||||
{
|
|
||||||
HWND hwndTarget;
|
|
||||||
HBITMAP hbm32bpp;
|
|
||||||
BOOL bDestroyTarget;
|
|
||||||
} GHOST_DATA;
|
|
||||||
|
|
||||||
static GHOST_DATA *
|
static GHOST_DATA *
|
||||||
Ghost_GetData(HWND hwnd)
|
Ghost_GetData(HWND hwnd)
|
||||||
{
|
{
|
||||||
|
@ -188,9 +181,9 @@ Ghost_OnCreate(HWND hwnd, CREATESTRUCTW *lpcs)
|
||||||
|
|
||||||
// get the target
|
// get the target
|
||||||
hwndTarget = (HWND)lpcs->lpCreateParams;
|
hwndTarget = (HWND)lpcs->lpCreateParams;
|
||||||
if (!IsWindowVisible(hwndTarget) || // invisible?
|
if (!IsWindowVisible(hwndTarget) || // invisible?
|
||||||
GetParent(hwndTarget) || // child?
|
(GetWindowLongPtrW(hwndTarget, GWL_STYLE) & WS_CHILD) || // child?
|
||||||
!IsHungAppWindow(hwndTarget)) // not hung?
|
!IsHungAppWindow(hwndTarget)) // not hung?
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue