From 69a5b343d16ae3c719ba41b56c82a8324f345b60 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Thu, 9 Jun 2011 20:00:43 +0000 Subject: [PATCH] [Win32k] - Fix hot tracking but does not clear it properly. See bug 6257. - Ported NC_HandleNCHitTest from wine, will sync User32 later. svn path=/trunk/; revision=52163 --- .../subsystems/win32/win32k/include/window.h | 16 ++ .../subsystems/win32/win32k/ntuser/defwnd.c | 202 ++++++++++++++++++ .../subsystems/win32/win32k/ntuser/msgqueue.c | 52 +++-- 3 files changed, 258 insertions(+), 12 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/window.h b/reactos/subsystems/win32/win32k/include/window.h index 44e6a8c86db..6b5d2f25898 100644 --- a/reactos/subsystems/win32/win32k/include/window.h +++ b/reactos/subsystems/win32/win32k/include/window.h @@ -28,6 +28,21 @@ BOOL FASTCALL UserUpdateUiState(PWND Wnd, WPARAM wParam); #define HAS_THINFRAME(Style, ExStyle) \ (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP)))) +#define HAS_BIGFRAME(style,exStyle) \ + (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \ + ((exStyle) & WS_EX_DLGMODALFRAME)) + +#define HAS_STATICOUTERFRAME(style,exStyle) \ + (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \ + WS_EX_STATICEDGE) + +#define HAS_ANYFRAME(style,exStyle) \ + (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \ + ((exStyle) & WS_EX_DLGMODALFRAME) || \ + !((style) & (WS_CHILD | WS_POPUP))) + +#define HAS_MENU(pWnd,style) ((((style) & (WS_CHILD | WS_POPUP)) != WS_CHILD) && pWnd->IDMenu) + #define IntIsDesktopWindow(WndObj) \ (WndObj->spwndParent == NULL) @@ -112,5 +127,6 @@ PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRI WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL); BOOL FASTCALL IntEnableWindow(HWND,BOOL); +DWORD FASTCALL GetNCHitEx(PWND pWnd, POINT pt); /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/defwnd.c b/reactos/subsystems/win32/win32k/ntuser/defwnd.c index 1b1d051e224..470df873eaf 100644 --- a/reactos/subsystems/win32/win32k/ntuser/defwnd.c +++ b/reactos/subsystems/win32/win32k/ntuser/defwnd.c @@ -215,5 +215,207 @@ IntDefWindowProc( return lResult; } +static HICON NC_IconForWindow( PWND pWnd ) +{ + HICON hIcon = 0; + + if (!pWnd->pcls || pWnd->fnid == FNID_DESKTOP) return hIcon; + if (!hIcon) hIcon = pWnd->pcls->hIconSm; + if (!hIcon) hIcon = pWnd->pcls->hIcon; + + if (!hIcon && pWnd->style & DS_MODALFRAME) + { // Fake it out for now, we use it as a test. + hIcon = (HICON)1; + /* FIXME: Need to setup Registry System Cursor & Icons via Callbacks at init time! */ + if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small + if (!hIcon) hIcon = gpsi->hIcoWindows; // Reg size. + } + return hIcon; +} + +DWORD FASTCALL +GetNCHitEx(PWND pWnd, POINT pt) +{ + RECT rcWindow, rcClient; + DWORD Style, ExStyle; + + if (!pWnd) return HTNOWHERE; + + rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0; + rcWindow.right = pWnd->rcWindow.right; + rcWindow.bottom = pWnd->rcWindow.bottom; + rcClient.right = pWnd->rcClient.right; + rcClient.bottom = pWnd->rcClient.bottom; + + if (!IntPtInRect(&rcWindow, pt)) return HTNOWHERE; + + Style = pWnd->style; + ExStyle = pWnd->ExStyle; + + if (Style & WS_MINIMIZE) return HTCAPTION; + + if (IntPtInRect( &rcClient, pt )) return HTCLIENT; + + /* Check borders */ + if (HAS_THICKFRAME( Style, ExStyle )) + { + RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) ); + if (!IntPtInRect(&rcWindow, pt)) + { + /* Check top sizing border */ + if (pt.y < rcWindow.top) + { + if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT; + if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT; + return HTTOP; + } + /* Check bottom sizing border */ + if (pt.y >= rcWindow.bottom) + { + if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT; + if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT; + return HTBOTTOM; + } + /* Check left sizing border */ + if (pt.x < rcWindow.left) + { + if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT; + if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT; + return HTLEFT; + } + /* Check right sizing border */ + if (pt.x >= rcWindow.right) + { + if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT; + if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT; + return HTRIGHT; + } + } + } + else /* No thick frame */ + { + if (HAS_DLGFRAME( Style, ExStyle )) + RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME)); + else if (HAS_THINFRAME( Style, ExStyle )) + RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER)); + if (!IntPtInRect( &rcWindow, pt )) return HTBORDER; + } + + /* Check caption */ + + if ((Style & WS_CAPTION) == WS_CAPTION) + { + if (ExStyle & WS_EX_TOOLWINDOW) + rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1; + else + rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1; + if (!IntPtInRect( &rcWindow, pt )) + { + BOOL min_or_max_box = (Style & WS_MAXIMIZEBOX) || + (Style & WS_MINIMIZEBOX); + if (ExStyle & WS_EX_LAYOUTRTL) + { + /* Check system menu */ + if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd)) + { + rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1; + if (pt.x > rcWindow.right) return HTSYSMENU; + } + + /* Check close button */ + if (Style & WS_SYSMENU) + { + rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION); + if (pt.x < rcWindow.left) return HTCLOSE; + } + + /* Check maximize box */ + /* In win95 there is automatically a Maximize button when there is a minimize one*/ + if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) + { + rcWindow.left += UserGetSystemMetrics(SM_CXSIZE); + if (pt.x < rcWindow.left) return HTMAXBUTTON; + } + + /* Check minimize box */ + if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) + { + rcWindow.left += UserGetSystemMetrics(SM_CXSIZE); + if (pt.x < rcWindow.left) return HTMINBUTTON; + } + } + else + { + /* Check system menu */ + if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd)) + { + rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1; + if (pt.x < rcWindow.left) return HTSYSMENU; + } + + /* Check close button */ + if (Style & WS_SYSMENU) + { + rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION); + if (pt.x > rcWindow.right) return HTCLOSE; + } + + /* Check maximize box */ + /* In win95 there is automatically a Maximize button when there is a minimize one*/ + if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) + { + rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE); + if (pt.x > rcWindow.right) return HTMAXBUTTON; + } + + /* Check minimize box */ + if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) + { + rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE); + if (pt.x > rcWindow.right) return HTMINBUTTON; + } + } + return HTCAPTION; + } + } + + /* Check menu bar */ + + if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) && + (pt.x >= rcClient.left) && (pt.x < rcClient.right)) + return HTMENU; + + /* Check vertical scroll bar */ + + if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR; + if (Style & WS_VSCROLL) + { + if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) + rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL); + else + rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL); + if (IntPtInRect( &rcClient, pt )) return HTVSCROLL; + } + + /* Check horizontal scroll bar */ + + if (Style & WS_HSCROLL) + { + rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL); + if (IntPtInRect( &rcClient, pt )) + { + /* Check size box */ + if ((Style & WS_VSCROLL) && + ((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) || + (((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL))))) + return HTSIZE; + return HTHSCROLL; + } + } + + /* Has to return HTNOWHERE if nothing was found + Could happen when a window has a customized non client area */ + return HTNOWHERE; +} /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c index b19608f0af7..1246d70c9f1 100644 --- a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c @@ -43,6 +43,39 @@ MsqInitializeImpl(VOID) return(STATUS_SUCCESS); } +PWND FASTCALL +IntChildrenWindowFromPoint(PWND pWndTop, INT x, INT y) +{ + PWND pWnd, pWndChild; + + if (!(pWndTop->style & WS_VISIBLE)) return NULL; + if ((pWndTop->style & WS_DISABLED)) return NULL; + if (!IntPtInWindow(pWndTop, x, y)) return NULL; + + if (x - pWndTop->rcClient.left < pWndTop->rcClient.right && + y - pWndTop->rcClient.top < pWndTop->rcClient.bottom ) + { + for (pWnd = pWndTop->spwndChild; + pWnd != NULL; + pWnd = pWnd->spwndNext) + { + if (pWnd->state2 & WNDS2_INDESTROY || pWnd->state & WNDS_DESTROYED ) + { + DPRINT("The Window is in DESTROY!\n"); + continue; + } + + pWndChild = IntChildrenWindowFromPoint(pWnd, x, y); + + if (pWndChild) + { + return pWndChild; + } + } + } + return pWndTop; +} + PWND FASTCALL IntTopLevelWindowFromPoint(INT x, INT y) { @@ -503,22 +536,17 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook if (Msg->hwnd != NULL) { pwnd = UserGetWindowObject(Msg->hwnd); - if ((pwnd->style & WS_VISIBLE) && - IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y)) - { - pDesk->htEx = HTCLIENT; - pDesk->spwndTrack = pwnd; - } } else { pwnd = IntTopLevelWindowFromPoint(Msg->pt.x, Msg->pt.y); - if (pwnd) - { - Msg->hwnd = pwnd->head.h; - pDesk->htEx = HTCLIENT; - pDesk->spwndTrack = pwnd; - } + if (pwnd) Msg->hwnd = pwnd->head.h; + } + + if (pwnd) + { + pDesk->spwndTrack = IntChildrenWindowFromPoint(pwnd, Msg->pt.x, Msg->pt.y); + pDesk->htEx = GetNCHitEx(pDesk->spwndTrack, Msg->pt); } hdcScreen = IntGetScreenDC();