mirror of
https://github.com/reactos/reactos.git
synced 2024-12-01 23:43:32 +08:00
parent
acef266bc6
commit
1adefd180c
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,
|
||||
__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 */
|
||||
|
@ -1,23 +1,178 @@
|
||||
/*
|
||||
* PROJECT: ReactOS user32.dll
|
||||
* 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)
|
||||
*/
|
||||
|
||||
#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 (IntIsGhostWindow(pHungWnd))
|
||||
{
|
||||
DPRINT1("IntIsGhostWindow\n");
|
||||
return FALSE; // ghost window cannot be ghosted
|
||||
}
|
||||
|
||||
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 (IntGhostWindowFromHungWindow(pHungWnd))
|
||||
{
|
||||
DPRINT("Already ghosting\n");
|
||||
return FALSE; // already ghosting
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// 1. Create a thread.
|
||||
// 2. Create a ghost window in the thread.
|
||||
// 3. Do message loop in the thread
|
||||
static int bWarnedOnce = 0;
|
||||
if (!bWarnedOnce)
|
||||
{
|
||||
bWarnedOnce++;
|
||||
STUB;
|
||||
static int bWarnedOnce = 0;
|
||||
if (!bWarnedOnce)
|
||||
{
|
||||
bWarnedOnce++;
|
||||
STUB;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
BOOL FASTCALL IntGoGhost(PWND Window, BOOL bGo);
|
||||
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung);
|
||||
|
@ -1443,7 +1443,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
|
||||
}
|
||||
|
||||
TRACE("Let's go Ghost!\n");
|
||||
IntGoGhost(Window, TRUE);
|
||||
IntMakeHungWindowGhosted(hWnd);
|
||||
}
|
||||
|
||||
if (Window->state & WNDS_DESTROYED)
|
||||
|
@ -7,12 +7,12 @@
|
||||
|
||||
#include <user32.h>
|
||||
#include <strsafe.h>
|
||||
#include "ghostwnd.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ghost);
|
||||
|
||||
#define GHOST_TIMER_ID 0xFACEDEAD
|
||||
#define GHOST_INTERVAL 1000 // one second
|
||||
#define GHOST_PROP L"GhostProp"
|
||||
|
||||
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 *
|
||||
Ghost_GetData(HWND hwnd)
|
||||
{
|
||||
@ -188,9 +181,9 @@ Ghost_OnCreate(HWND hwnd, CREATESTRUCTW *lpcs)
|
||||
|
||||
// get the target
|
||||
hwndTarget = (HWND)lpcs->lpCreateParams;
|
||||
if (!IsWindowVisible(hwndTarget) || // invisible?
|
||||
GetParent(hwndTarget) || // child?
|
||||
!IsHungAppWindow(hwndTarget)) // not hung?
|
||||
if (!IsWindowVisible(hwndTarget) || // invisible?
|
||||
(GetWindowLongPtrW(hwndTarget, GWL_STYLE) & WS_CHILD) || // child?
|
||||
!IsHungAppWindow(hwndTarget)) // not hung?
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user