mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NTUSER] Implement NtUserAssociateInputContext (#4334)
- Add IntReAllocatePoolWithTag function in window.c. - Define WINDOWLIST structure in "window.h". - Add IntBuildHwndList and IntFreeHwndList helper functions in window.c. - Add IntAssociateInputContext and IntAssociateInputContextEx helper functions in ime.c. - Implement NtUserAssociateInputContext function. CORE-11700
This commit is contained in:
parent
bf16435303
commit
f2c3167db3
4 changed files with 259 additions and 7 deletions
|
@ -577,11 +577,10 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC, DWORD, DWORD, LPIMEMENUITEMINFOW, LPIMEMEN
|
|||
#define IME_REGWORD_STYLE_USER_FIRST 0x80000000
|
||||
#define IME_REGWORD_STYLE_USER_LAST 0xFFFFFFFF
|
||||
|
||||
|
||||
/* dwFlags for ImmAssociateContextEx */
|
||||
#define IACE_CHILDREN 0x0001
|
||||
#define IACE_DEFAULT 0x0010
|
||||
#define IACE_IGNORENOCONTEXT 0x0020
|
||||
#define IACE_CHILDREN 0x0001
|
||||
#define IACE_DEFAULT 0x0010
|
||||
#define IACE_IGNORENOCONTEXT 0x0020
|
||||
|
||||
/* dwFlags for ImmGetImeMenuItems */
|
||||
#define IGIMIF_RIGHTMENU 0x0001
|
||||
|
|
|
@ -695,12 +695,97 @@ Quit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
HIMC FASTCALL IntAssociateInputContext(PWND pWnd, PIMC pImc)
|
||||
{
|
||||
HIMC hOldImc = pWnd->hImc;
|
||||
pWnd->hImc = (pImc ? UserHMGetHandle(pImc) : NULL);
|
||||
return hOldImc;
|
||||
}
|
||||
|
||||
DWORD FASTCALL IntAssociateInputContextEx(PWND pWnd, PIMC pIMC, DWORD dwFlags)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
PWINDOWLIST pwl;
|
||||
BOOL bIgnoreNullImc = (dwFlags & IACE_IGNORENOCONTEXT);
|
||||
PTHREADINFO pti = pWnd->head.pti;
|
||||
PWND pwndTarget, pwndFocus = pti->MessageQueue->spwndFocus;
|
||||
HWND *phwnd;
|
||||
HIMC hIMC;
|
||||
|
||||
if (dwFlags & IACE_DEFAULT)
|
||||
{
|
||||
pIMC = pti->spDefaultImc;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pIMC && pti != pIMC->head.pti)
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (pWnd->head.pti->ppi != GetW32ThreadInfo()->ppi ||
|
||||
(pIMC && pIMC->head.rpdesk != pWnd->head.rpdesk))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ((dwFlags & IACE_CHILDREN) && pWnd->spwndChild)
|
||||
{
|
||||
pwl = IntBuildHwndList(pWnd->spwndChild, IACE_CHILDREN | IACE_LIST, pti);
|
||||
if (pwl)
|
||||
{
|
||||
for (phwnd = pwl->ahwnd; *phwnd != HWND_TERMINATOR; ++phwnd)
|
||||
{
|
||||
pwndTarget = ValidateHwndNoErr(*phwnd);
|
||||
if (!pwndTarget)
|
||||
continue;
|
||||
|
||||
hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
|
||||
if (pwndTarget->hImc == hIMC || (bIgnoreNullImc && !pwndTarget->hImc))
|
||||
continue;
|
||||
|
||||
IntAssociateInputContext(pwndTarget, pIMC);
|
||||
if (pwndTarget == pwndFocus)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
IntFreeHwndList(pwl);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bIgnoreNullImc || pWnd->hImc)
|
||||
{
|
||||
hIMC = (pIMC ? UserHMGetHandle(pIMC) : NULL);
|
||||
if (pWnd->hImc != hIMC)
|
||||
{
|
||||
IntAssociateInputContext(pWnd, pIMC);
|
||||
if (pWnd == pwndFocus)
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
NtUserAssociateInputContext(HWND hWnd, HIMC hIMC, DWORD dwFlags)
|
||||
{
|
||||
STUB
|
||||
return 0;
|
||||
DWORD ret = 2;
|
||||
PWND pWnd;
|
||||
PIMC pIMC;
|
||||
|
||||
UserEnterExclusive();
|
||||
|
||||
pWnd = ValidateHwndNoErr(hWnd);
|
||||
if (!pWnd || !IS_IMM_MODE())
|
||||
goto Quit;
|
||||
|
||||
pIMC = (hIMC ? UserGetObjectNoErr(gHandleTable, hIMC, TYPE_INPUTCONTEXT) : NULL);
|
||||
ret = IntAssociateInputContextEx(pWnd, pIMC, dwFlags);
|
||||
|
||||
Quit:
|
||||
UserLeave();
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL FASTCALL UserUpdateInputContext(PIMC pIMC, DWORD dwType, DWORD_PTR dwValue)
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
* PROJECT: ReactOS Win32k subsystem
|
||||
* PURPOSE: Windows
|
||||
* FILE: win32ss/user/ntuser/window.c
|
||||
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#include <win32k.h>
|
||||
|
@ -11,8 +12,28 @@ DBG_DEFAULT_CHANNEL(UserWnd);
|
|||
|
||||
INT gNestedWindowLimit = 50;
|
||||
|
||||
PWINDOWLIST gpwlList = NULL;
|
||||
PWINDOWLIST gpwlCache = NULL;
|
||||
|
||||
/* HELPER FUNCTIONS ***********************************************************/
|
||||
|
||||
PVOID FASTCALL
|
||||
IntReAllocatePoolWithTag(
|
||||
POOL_TYPE PoolType,
|
||||
PVOID pOld,
|
||||
SIZE_T cbOld,
|
||||
SIZE_T cbNew,
|
||||
ULONG Tag)
|
||||
{
|
||||
PVOID pNew = ExAllocatePoolWithTag(PoolType, cbNew, Tag);
|
||||
if (!pNew)
|
||||
return NULL;
|
||||
|
||||
RtlCopyMemory(pNew, pOld, min(cbOld, cbNew));
|
||||
ExFreePoolWithTag(pOld, Tag);
|
||||
return pNew;
|
||||
}
|
||||
|
||||
BOOL FASTCALL UserUpdateUiState(PWND Wnd, WPARAM wParam)
|
||||
{
|
||||
WORD Action = LOWORD(wParam);
|
||||
|
@ -1320,6 +1341,133 @@ IntUnlinkWindow(PWND Wnd)
|
|||
Wnd->spwndPrev = Wnd->spwndNext = NULL;
|
||||
}
|
||||
|
||||
BOOL FASTCALL IntGrowHwndList(PWINDOWLIST *ppwl)
|
||||
{
|
||||
PWINDOWLIST pwlOld, pwlNew;
|
||||
SIZE_T ibOld, ibNew;
|
||||
|
||||
#define GROW_COUNT 8
|
||||
pwlOld = *ppwl;
|
||||
ibOld = (LPBYTE)pwlOld->phwndLast - (LPBYTE)pwlOld;
|
||||
ibNew = ibOld + GROW_COUNT * sizeof(HWND);
|
||||
#undef GROW_COUNT
|
||||
pwlNew = IntReAllocatePoolWithTag(PagedPool, pwlOld, ibOld, ibNew, USERTAG_WINDOWLIST);
|
||||
if (!pwlNew)
|
||||
return FALSE;
|
||||
|
||||
pwlNew->phwndLast = (HWND *)((LPBYTE)pwlNew + ibOld);
|
||||
pwlNew->phwndEnd = (HWND *)((LPBYTE)pwlNew + ibNew);
|
||||
*ppwl = pwlNew;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PWINDOWLIST FASTCALL IntPopulateHwndList(PWINDOWLIST pwl, PWND pwnd, DWORD dwFlags)
|
||||
{
|
||||
ASSERT(!WL_IS_BAD(pwl));
|
||||
|
||||
for (; pwnd; pwnd = pwnd->spwndNext)
|
||||
{
|
||||
if (!pwl->pti || pwl->pti == pwnd->head.pti)
|
||||
{
|
||||
*(pwl->phwndLast) = UserHMGetHandle(pwnd);
|
||||
++(pwl->phwndLast);
|
||||
|
||||
if (pwl->phwndLast == pwl->phwndEnd && !IntGrowHwndList(&pwl))
|
||||
break;
|
||||
}
|
||||
|
||||
if ((dwFlags & IACE_CHILDREN) && pwnd->spwndChild)
|
||||
{
|
||||
pwl = IntPopulateHwndList(pwl, pwnd->spwndChild, IACE_CHILDREN | IACE_LIST);
|
||||
if (WL_IS_BAD(pwl))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(dwFlags & IACE_LIST))
|
||||
break;
|
||||
}
|
||||
|
||||
return pwl;
|
||||
}
|
||||
|
||||
PWINDOWLIST FASTCALL IntBuildHwndList(PWND pwnd, DWORD dwFlags, PTHREADINFO pti)
|
||||
{
|
||||
PWINDOWLIST pwl;
|
||||
DWORD cbWL;
|
||||
|
||||
if (gpwlCache)
|
||||
{
|
||||
pwl = gpwlCache;
|
||||
gpwlCache = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
#define INITIAL_COUNT 32
|
||||
cbWL = sizeof(WINDOWLIST) + (INITIAL_COUNT - 1) * sizeof(HWND);
|
||||
pwl = ExAllocatePoolWithTag(PagedPool, cbWL, USERTAG_WINDOWLIST);
|
||||
if (!pwl)
|
||||
return NULL;
|
||||
|
||||
pwl->phwndEnd = &pwl->ahwnd[INITIAL_COUNT];
|
||||
#undef INITIAL_COUNT
|
||||
}
|
||||
|
||||
pwl->pti = pti;
|
||||
pwl->phwndLast = pwl->ahwnd;
|
||||
pwl = IntPopulateHwndList(pwl, pwnd, dwFlags);
|
||||
if (WL_IS_BAD(pwl))
|
||||
{
|
||||
ExFreePoolWithTag(pwl, USERTAG_WINDOWLIST);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*(pwl->phwndLast) = HWND_TERMINATOR;
|
||||
|
||||
if (dwFlags & 0x8)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
||||
pwl->pti = GetW32ThreadInfo();
|
||||
pwl->pNextList = gpwlList;
|
||||
gpwlList = pwl;
|
||||
|
||||
return pwl;
|
||||
}
|
||||
|
||||
VOID FASTCALL IntFreeHwndList(PWINDOWLIST pwlTarget)
|
||||
{
|
||||
PWINDOWLIST pwl, *ppwl;
|
||||
|
||||
for (ppwl = &gpwlList; *ppwl; ppwl = &(*ppwl)->pNextList)
|
||||
{
|
||||
if (*ppwl != pwlTarget)
|
||||
continue;
|
||||
|
||||
*ppwl = pwlTarget->pNextList;
|
||||
|
||||
if (gpwlCache)
|
||||
{
|
||||
if (WL_CAPACITY(pwlTarget) > WL_CAPACITY(gpwlCache))
|
||||
{
|
||||
pwl = gpwlCache;
|
||||
gpwlCache = pwlTarget;
|
||||
ExFreePoolWithTag(pwl, USERTAG_WINDOWLIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExFreePoolWithTag(pwlTarget, USERTAG_WINDOWLIST);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpwlCache = pwlTarget;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,4 +79,24 @@ LONG_PTR FASTCALL co_UserSetWindowLongPtr(HWND, DWORD, LONG_PTR, BOOL);
|
|||
HWND FASTCALL IntGetWindow(HWND,UINT);
|
||||
LRESULT co_UserFreeWindow(PWND,PPROCESSINFO,PTHREADINFO,BOOLEAN);
|
||||
|
||||
#define HWND_TERMINATOR ((HWND)(ULONG_PTR)1)
|
||||
|
||||
typedef struct tagWINDOWLIST
|
||||
{
|
||||
struct tagWINDOWLIST *pNextList;
|
||||
HWND *phwndLast;
|
||||
HWND *phwndEnd;
|
||||
PTHREADINFO pti;
|
||||
HWND ahwnd[ANYSIZE_ARRAY]; /* Terminated by HWND_TERMINATOR */
|
||||
} WINDOWLIST, *PWINDOWLIST;
|
||||
|
||||
#define WL_IS_BAD(pwl) ((pwl)->phwndEnd <= (pwl)->phwndLast)
|
||||
#define WL_CAPACITY(pwl) ((pwl)->phwndEnd - &((pwl)->ahwnd[0]))
|
||||
|
||||
PWINDOWLIST FASTCALL IntBuildHwndList(PWND pwnd, DWORD dwFlags, PTHREADINFO pti);
|
||||
VOID FASTCALL IntFreeHwndList(PWINDOWLIST pwlTarget);
|
||||
|
||||
/* Undocumented dwFlags for IntBuildHwndList */
|
||||
#define IACE_LIST 0x0002
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue