[RSHELL]
[reactos.git] / base / shell / rshell / CMenuFocusManager.cpp
index 9bc1b7d..36ef3d0 100644 (file)
@@ -160,6 +160,9 @@ CMenuFocusManager::CMenuFocusManager() :
     m_selectedMenu(NULL),
     m_selectedItem(0),
     m_selectedItemFlags(0),
+    m_isLButtonDown(FALSE),
+    m_movedSinceDown(FALSE),
+    m_windowAtDown(NULL),
     m_bandCount(0)
 {
     m_ptPrev.x = 0;
@@ -302,15 +305,21 @@ LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg)
     if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
         return TRUE;
 
+
+    m_movedSinceDown = TRUE;
+
     m_ptPrev = pt;
 
     child = WindowFromPoint(pt);
 
     StackEntry * entry = NULL;
-    IsTrackedWindow(child, &entry);
+    if (IsTrackedWindow(child, &entry) == S_OK)
+    {
+        TRACE("MouseMove %d\n", m_isLButtonDown);
+    }
 
     BOOL isTracking = FALSE;
-    if (entry)
+    if (entry && (entry->type == MenuBarEntry || m_current->type != TrackedMenuEntry))
     {
         ScreenToClient(child, &pt);
         iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
@@ -320,7 +329,7 @@ LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg)
         {
             TRACE("Hot item tracking detected a change (capture=%p / cCapture=%p)...\n", m_captureHwnd, cCapture);
             DisableMouseTrack(NULL, FALSE);
-            if (isTracking && iHitTestResult>=0 && m_current->type == TrackedMenuEntry)
+            if (isTracking && iHitTestResult >= 0 && m_current->type == TrackedMenuEntry)
                 SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0);
             PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult, MAKELPARAM(isTracking, TRUE));
             if (m_current->type == TrackedMenuEntry)
@@ -364,6 +373,94 @@ LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg)
     return TRUE;
 }
 
+LRESULT CMenuFocusManager::ProcessMouseDown(MSG* msg)
+{
+    HWND child;
+    int iHitTestResult = -1;
+
+    TRACE("ProcessMouseDown %d %d %d\n", msg->message, msg->wParam, msg->lParam);
+
+    // Don't do anything if another window is capturing the mouse.
+    HWND cCapture = ::GetCapture();
+    if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
+        return TRUE;
+
+
+    POINT pt = msg->pt;
+
+    child = WindowFromPoint(pt);
+
+    StackEntry * entry = NULL;
+    if (IsTrackedWindow(child, &entry) != S_OK)
+        return TRUE;
+
+    TRACE("MouseDown %d\n", m_isLButtonDown);
+
+    if (entry)
+    {
+        ScreenToClient(child, &pt);
+        iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
+
+        if (iHitTestResult >= 0)
+        {
+            TRACE("MouseDown send %d\n", iHitTestResult);
+            entry->mb->_MenuBarMouseDown(child, iHitTestResult);
+        }
+    }
+
+    msg->message = WM_NULL;
+
+    m_isLButtonDown = TRUE;
+    m_movedSinceDown = FALSE;
+    m_windowAtDown = child;
+
+    TRACE("MouseDown end %d\n", m_isLButtonDown);
+
+    return TRUE;
+}
+
+LRESULT CMenuFocusManager::ProcessMouseUp(MSG* msg)
+{
+    HWND child;
+    int iHitTestResult = -1;
+
+    TRACE("ProcessMouseUp %d %d %d\n", msg->message, msg->wParam, msg->lParam);
+
+    // Don't do anything if another window is capturing the mouse.
+    HWND cCapture = ::GetCapture();
+    if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
+        return TRUE;
+
+    if (!m_isLButtonDown)
+        return TRUE;
+
+    m_isLButtonDown = FALSE;
+
+    POINT pt = msg->pt;
+
+    child = WindowFromPoint(pt);
+
+    StackEntry * entry = NULL;
+    if (IsTrackedWindow(child, &entry) != S_OK)
+        return TRUE;
+
+    TRACE("MouseUp %d\n", m_isLButtonDown);
+
+    if (entry)
+    {
+        ScreenToClient(child, &pt);
+        iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
+
+        if (iHitTestResult >= 0)
+        {
+            TRACE("MouseUp send %d\n", iHitTestResult);
+            entry->mb->_MenuBarMouseUp(child, iHitTestResult);
+        }
+    }
+
+    return TRUE;
+}
+
 LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam)
 {
     if (nCode < 0)
@@ -378,6 +475,8 @@ LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM ho
         {
         case WM_NCLBUTTONDOWN:
         case WM_LBUTTONDOWN:
+        case WM_NCRBUTTONDOWN:
+        case WM_RBUTTONDOWN:
             if (m_menuBar)
             {
                 POINT pt = msg->pt;
@@ -386,9 +485,23 @@ LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM ho
                 if (hoveringMenuBar)
                 {
                     m_menuBar->mb->_DisableMouseTrack(TRUE);
+                    if (m_current->type == TrackedMenuEntry)
+                    {
+                        SendMessage(m_parent->hwnd, WM_CANCELMODE, 0, 0);
+                        msg->message = WM_NULL;
+                    }
                 }
             }
             break;
+        case WM_NCLBUTTONUP:
+        case WM_LBUTTONUP:
+        case WM_NCRBUTTONUP:
+        case WM_RBUTTONUP:
+            if (m_current && m_current->type != TrackedMenuEntry)
+            {
+                msg->message = WM_NULL;
+            }
+            break;
         case WM_MOUSEMOVE:
             callNext = ProcessMouseMove(msg);
             break;
@@ -432,6 +545,7 @@ LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM ho
 
 LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam)
 {
+    BOOL isLButton = FALSE;
     if (nCode < 0)
         return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
     
@@ -445,6 +559,11 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookL
         {
         case WM_NCLBUTTONDOWN:
         case WM_LBUTTONDOWN:
+            isLButton = TRUE;
+
+            // fallthrough;
+        case WM_NCRBUTTONDOWN:
+        case WM_RBUTTONDOWN:
             if (m_current->type == MenuPopupEntry)
             {
                 HWND child = WindowFromPoint(pt);
@@ -453,8 +572,18 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookL
                 {
                     SetCapture(NULL);
                     m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL);
+                    break;
                 }
             }
+            
+            if (isLButton)
+            {
+                ProcessMouseDown(msg);
+            }
+            break;
+        case WM_NCLBUTTONUP:
+        case WM_LBUTTONUP:
+            ProcessMouseUp(msg);
             break;
         case WM_MOUSEMOVE:
             callNext = ProcessMouseMove(msg);
@@ -508,6 +637,16 @@ LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookL
 
 HRESULT CMenuFocusManager::PlaceHooks()
 {
+    if (m_hMsgFilterHook)
+    {
+        WARN("GETMESSAGE hook already placed!\n");
+        return S_OK;
+    }
+    if (m_hMsgFilterHook)
+    {
+        WARN("MSGFILTER hook already placed!\n");
+        return S_OK;
+    }
     if (m_current->type == TrackedMenuEntry)
     {
         TRACE("Entering MSGFILTER hook...\n");
@@ -538,6 +677,8 @@ HRESULT CMenuFocusManager::UpdateFocus()
     HRESULT hr;
     StackEntry * old = m_current;
 
+    TRACE("UpdateFocus\n");
+
     if (old)
         SetCapture(NULL);
 
@@ -624,6 +765,10 @@ HRESULT CMenuFocusManager::UpdateFocus()
 
 HRESULT CMenuFocusManager::PushMenuBar(CMenuBand * mb)
 {
+    DbgPrint("PushMenuBar %p\n", mb);
+
+    mb->AddRef();
+
     _ASSERT(m_bandCount == 0);
 
     HRESULT hr = PushToArray(MenuBarEntry, mb, NULL);
@@ -635,6 +780,10 @@ HRESULT CMenuFocusManager::PushMenuBar(CMenuBand * mb)
 
 HRESULT CMenuFocusManager::PushMenuPopup(CMenuBand * mb)
 {
+    DbgPrint("PushTrackedPopup %p\n", mb);
+
+    mb->AddRef();
+
     _ASSERT(!m_current || m_current->type != TrackedMenuEntry);
 
     HRESULT hr = PushToArray(MenuPopupEntry, mb, NULL);
@@ -654,6 +803,8 @@ HRESULT CMenuFocusManager::PushMenuPopup(CMenuBand * mb)
 
 HRESULT CMenuFocusManager::PushTrackedPopup(HMENU popup)
 {
+    DbgPrint("PushTrackedPopup %p\n", popup);
+
     _ASSERT(m_bandCount > 0);
     _ASSERT(!m_current || m_current->type != TrackedMenuEntry);
 
@@ -661,7 +812,7 @@ HRESULT CMenuFocusManager::PushTrackedPopup(HMENU popup)
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
-    TRACE("PushTrackedPopup %p\n", popup);
+    DbgPrint("PushTrackedPopup %p\n", popup);
     m_selectedMenu = popup;
     m_selectedItem = -1;
     m_selectedItemFlags = 0;
@@ -675,6 +826,13 @@ HRESULT CMenuFocusManager::PopMenuBar(CMenuBand * mb)
     CMenuBand * mbc;
     HRESULT hr;
 
+    DbgPrint("PopMenuBar %p\n", mb);
+
+    if (m_current == m_entryUnderMouse)
+    {
+        m_entryUnderMouse = NULL;
+    }
+
     hr = PopFromArray(&type, &mbc, NULL);
     if (FAILED_UNEXPECTEDLY(hr))
     {
@@ -691,6 +849,8 @@ HRESULT CMenuFocusManager::PopMenuBar(CMenuBand * mb)
 
     mbc->_SetParentBand(NULL);
 
+    mbc->Release();
+
     hr = UpdateFocus();
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
@@ -710,6 +870,13 @@ HRESULT CMenuFocusManager::PopMenuPopup(CMenuBand * mb)
     CMenuBand * mbc;
     HRESULT hr;
 
+    DbgPrint("PopMenuPopup %p\n", mb);
+
+    if (m_current == m_entryUnderMouse)
+    {
+        m_entryUnderMouse = NULL;
+    }
+
     hr = PopFromArray(&type, &mbc, NULL);
     if (FAILED_UNEXPECTEDLY(hr))
     {
@@ -726,6 +893,8 @@ HRESULT CMenuFocusManager::PopMenuPopup(CMenuBand * mb)
 
     mbc->_SetParentBand(NULL);
 
+    mbc->Release();
+
     hr = UpdateFocus();
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
@@ -745,6 +914,8 @@ HRESULT CMenuFocusManager::PopTrackedPopup(HMENU popup)
     HMENU hmenu;
     HRESULT hr;
 
+    DbgPrint("PopTrackedPopup %p\n", popup);
+
     hr = PopFromArray(&type, NULL, &hmenu);
     if (FAILED_UNEXPECTEDLY(hr))
     {