mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[NTUSER] Destroy the default IME window (#4462)
- Add IntFindNonImeRelatedWndOfSameThread, IntImeCanDestroyDefIMEforChild, and IntImeCanDestroyDefIME helper functions. - Do assignment unlock spwndDefaultIme at co_UserFreeWindow. - Destroy the default IME window of the specified window if necessary at co_UserDestroyWindow. CORE-11700
This commit is contained in:
parent
944b942eb2
commit
4bcf23d1de
|
@ -21,15 +21,6 @@ DBG_DEFAULT_CHANNEL(UserMisc);
|
||||||
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
||||||
#define LANGID_NEUTRAL MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
|
#define LANGID_NEUTRAL MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
|
||||||
|
|
||||||
// The IME-like windows are the IME windows and the IME UI windows.
|
|
||||||
// The IME window's class name is "IME".
|
|
||||||
// The IME UI window behaves the User Interface of IME for the user.
|
|
||||||
#define IS_WND_IMELIKE(pwnd) \
|
|
||||||
(((pwnd)->pcls->style & CS_IME) || \
|
|
||||||
((pwnd)->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]))
|
|
||||||
#define IS_WND_MENU(pWnd) \
|
|
||||||
((pWnd)->pcls->atomClassName == gpsi->atomSysClass[ICLS_MENU])
|
|
||||||
|
|
||||||
// The special virtual keys for Japanese: Used for key states.
|
// The special virtual keys for Japanese: Used for key states.
|
||||||
// https://www.kthree.co.jp/kihelp/index.html?page=app/vkey&type=html
|
// https://www.kthree.co.jp/kihelp/index.html?page=app/vkey&type=html
|
||||||
#define VK_DBE_ALPHANUMERIC 0xF0
|
#define VK_DBE_ALPHANUMERIC 0xF0
|
||||||
|
@ -1820,4 +1811,192 @@ Quit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Searchs a non-IME-related window of the same thread of pwndTarget,
|
||||||
|
// other than pwndTarget, around pwndParent. Returns TRUE if found.
|
||||||
|
//
|
||||||
|
// Win: IsChildSameThread
|
||||||
|
BOOL IntFindNonImeRelatedWndOfSameThread(PWND pwndParent, PWND pwndTarget)
|
||||||
|
{
|
||||||
|
PWND pwnd, pwndOwner, pwndNode;
|
||||||
|
PTHREADINFO ptiTarget = pwndTarget->head.pti;
|
||||||
|
|
||||||
|
// For all the children of pwndParent, ...
|
||||||
|
for (pwnd = pwndParent->spwndChild; pwnd; pwnd = pwnd->spwndNext)
|
||||||
|
{
|
||||||
|
if (pwnd == pwndTarget || pwnd->head.pti != ptiTarget || IS_WND_MENU(pwnd))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!IS_WND_CHILD(pwnd))
|
||||||
|
{
|
||||||
|
// Check if any IME-like owner.
|
||||||
|
BOOL bFound1 = FALSE;
|
||||||
|
for (pwndOwner = pwnd; pwndOwner; pwndOwner = pwndOwner->spwndOwner)
|
||||||
|
{
|
||||||
|
if (IS_WND_IMELIKE(pwndOwner))
|
||||||
|
{
|
||||||
|
bFound1 = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bFound1)
|
||||||
|
continue; // Skip if any IME-like owner.
|
||||||
|
}
|
||||||
|
|
||||||
|
pwndNode = pwnd;
|
||||||
|
|
||||||
|
if (IS_WND_CHILD(pwndNode))
|
||||||
|
{
|
||||||
|
// Check if any same-thread IME-like ancestor.
|
||||||
|
BOOL bFound2 = FALSE;
|
||||||
|
for (; IS_WND_CHILD(pwndNode); pwndNode = pwndNode->spwndParent)
|
||||||
|
{
|
||||||
|
if (pwndNode->head.pti != ptiTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (IS_WND_IMELIKE(pwndNode))
|
||||||
|
{
|
||||||
|
bFound2 = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bFound2)
|
||||||
|
continue;
|
||||||
|
// Now, pwndNode is non-child or non-same-thread window.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_WND_CHILD(pwndNode)) // pwndNode is non-child
|
||||||
|
{
|
||||||
|
// Check if any same-thread IME-like owner.
|
||||||
|
BOOL bFound3 = FALSE;
|
||||||
|
for (; pwndNode; pwndNode = pwndNode->spwndOwner)
|
||||||
|
{
|
||||||
|
if (pwndNode->head.pti != ptiTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (IS_WND_IMELIKE(pwndNode))
|
||||||
|
{
|
||||||
|
bFound3 = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bFound3)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we destroy the default IME window for the target child window?
|
||||||
|
// Win: ImeCanDestroyDefIMEforChild
|
||||||
|
BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget)
|
||||||
|
{
|
||||||
|
PWND pwndNode;
|
||||||
|
PIMEUI pimeui;
|
||||||
|
IMEUI SafeImeUI;
|
||||||
|
|
||||||
|
pimeui = ((PIMEWND)pImeWnd)->pimeui;
|
||||||
|
if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Check IMEUI.fChildThreadDef
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(pimeui, sizeof(IMEUI), 1);
|
||||||
|
SafeImeUI = *pimeui;
|
||||||
|
if (!SafeImeUI.fChildThreadDef)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
// The parent of pwndTarget is NULL or of the same thread of pwndTarget?
|
||||||
|
if (pwndTarget->spwndParent == NULL ||
|
||||||
|
pwndTarget->head.pti == pwndTarget->spwndParent->head.pti)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndParent)
|
||||||
|
{
|
||||||
|
if (pwndNode == pwndNode->head.rpdesk->pDeskInfo->spwnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (IntFindNonImeRelatedWndOfSameThread(pwndNode->spwndParent, pwndTarget))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we destroy the default IME window for the non-child target window?
|
||||||
|
// If so, this function sets spwndOwner to NULL.
|
||||||
|
// Win: ImeCanDestroyDefIME
|
||||||
|
BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget)
|
||||||
|
{
|
||||||
|
PWND pwndNode;
|
||||||
|
PIMEUI pimeui;
|
||||||
|
IMEUI SafeImeUI;
|
||||||
|
|
||||||
|
pimeui = ((PIMEWND)pImeWnd)->pimeui;
|
||||||
|
if (!pimeui || (LONG_PTR)pimeui == (LONG_PTR)-1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Check IMEUI.fDestroy
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(pimeui, sizeof(IMEUI), 1);
|
||||||
|
SafeImeUI = *pimeui;
|
||||||
|
if (SafeImeUI.fDestroy)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
// Any ancestor of pImeWnd is pwndTarget?
|
||||||
|
if (pImeWnd->spwndOwner)
|
||||||
|
{
|
||||||
|
for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndOwner)
|
||||||
|
{
|
||||||
|
if (pwndNode == pwndTarget)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pwndNode)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any ancestor of pwndTarget is IME-like?
|
||||||
|
for (pwndNode = pwndTarget; pwndNode; pwndNode = pwndNode->spwndOwner)
|
||||||
|
{
|
||||||
|
if (IS_WND_IMELIKE(pwndNode))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the ordering and top-mode status
|
||||||
|
IntImeSetFutureOwner(pImeWnd, pwndTarget);
|
||||||
|
for (pwndNode = pImeWnd->spwndOwner; pwndNode; pwndNode = pwndNode->spwndNext)
|
||||||
|
{
|
||||||
|
if (pwndNode == pImeWnd)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pwndNode == pImeWnd)
|
||||||
|
IntImeCheckTopmost(pImeWnd);
|
||||||
|
|
||||||
|
// Is the owner of pImeWnd NULL or pwndTarget?
|
||||||
|
if (pImeWnd->spwndOwner && pwndTarget != pImeWnd->spwndOwner)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pImeWnd->spwndOwner = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -658,6 +658,9 @@ LRESULT co_UserFreeWindow(PWND Window,
|
||||||
ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
|
ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_IMM_MODE() && Window == ThreadData->spwndDefaultIme)
|
||||||
|
UserAssignmentUnlock((PVOID*)&(ThreadData->spwndDefaultIme));
|
||||||
|
|
||||||
/* Fixes dialog test_focus breakage due to r66237. */
|
/* Fixes dialog test_focus breakage due to r66237. */
|
||||||
if (ThreadData->MessageQueue->spwndFocus == Window)
|
if (ThreadData->MessageQueue->spwndFocus == Window)
|
||||||
ThreadData->MessageQueue->spwndFocus = NULL;
|
ThreadData->MessageQueue->spwndFocus = NULL;
|
||||||
|
@ -2762,7 +2765,7 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
|
||||||
TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
|
TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
|
||||||
|
|
||||||
/* Check for owner thread */
|
/* Check for owner thread */
|
||||||
if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
|
if (Window->head.pti != ti)
|
||||||
{
|
{
|
||||||
/* Check if we are destroying the desktop window */
|
/* Check if we are destroying the desktop window */
|
||||||
if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
|
if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
|
||||||
|
@ -2918,6 +2921,22 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
|
||||||
/* Send destroy messages */
|
/* Send destroy messages */
|
||||||
IntSendDestroyMsg(UserHMGetHandle(Window));
|
IntSendDestroyMsg(UserHMGetHandle(Window));
|
||||||
|
|
||||||
|
// Destroy the default IME window if necessary
|
||||||
|
if (IS_IMM_MODE() && !(ti->TIF_flags & TIF_INCLEANUP) &&
|
||||||
|
ti->spwndDefaultIme && !IS_WND_IMELIKE(Window) && !(Window->state & WNDS_DESTROYED))
|
||||||
|
{
|
||||||
|
if (IS_WND_CHILD(Window))
|
||||||
|
{
|
||||||
|
if (IntImeCanDestroyDefIMEforChild(ti->spwndDefaultIme, Window))
|
||||||
|
co_UserDestroyWindow(ti->spwndDefaultIme);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IntImeCanDestroyDefIME(ti->spwndDefaultIme, Window))
|
||||||
|
co_UserDestroyWindow(ti->spwndDefaultIme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!IntIsWindow(UserHMGetHandle(Window)))
|
if (!IntIsWindow(UserHMGetHandle(Window)))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -102,4 +102,17 @@ VOID FASTCALL IntFreeHwndList(PWINDOWLIST pwlTarget);
|
||||||
/* Undocumented dwFlags for IntBuildHwndList */
|
/* Undocumented dwFlags for IntBuildHwndList */
|
||||||
#define IACE_LIST 0x0002
|
#define IACE_LIST 0x0002
|
||||||
|
|
||||||
|
#define IS_WND_CHILD(pWnd) ((pWnd)->style & WS_CHILD)
|
||||||
|
#define IS_WND_MENU(pWnd) ((pWnd)->pcls->atomClassName == gpsi->atomSysClass[ICLS_MENU])
|
||||||
|
|
||||||
|
// The IME-like windows are the IME windows and the IME UI windows.
|
||||||
|
// The IME window's class name is "IME".
|
||||||
|
// The IME UI window behaves the User Interface of IME for the user.
|
||||||
|
#define IS_WND_IMELIKE(pWnd) \
|
||||||
|
(((pWnd)->pcls->style & CS_IME) || \
|
||||||
|
((pWnd)->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]))
|
||||||
|
|
||||||
|
BOOL FASTCALL IntImeCanDestroyDefIMEforChild(PWND pImeWnd, PWND pwndTarget);
|
||||||
|
BOOL FASTCALL IntImeCanDestroyDefIME(PWND pImeWnd, PWND pwndTarget);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue