mirror of
https://github.com/reactos/reactos.git
synced 2024-12-03 08:23: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,
|
_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 (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:
|
// 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);
|
||||||
|
@ -1443,7 +1443,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Let's go Ghost!\n");
|
TRACE("Let's go Ghost!\n");
|
||||||
IntGoGhost(Window, TRUE);
|
IntMakeHungWindowGhosted(hWnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Window->state & WNDS_DESTROYED)
|
if (Window->state & WNDS_DESTROYED)
|
||||||
|
@ -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 New Issue
Block a user