Author: dquintana
Date: Sat Mar 15 21:38:15 2014
New Revision: 62509
URL:
http://svn.reactos.org/svn/reactos?rev=62509&view=rev
Log:
[RSHELL]
* Fix keyboard navigation and hottracking behaviour. One glitch remains where quickly
moving the mouse to a parent's toolbar item, and returning to the submenu before it
closes, won't restore the parent's hot item to the one with the submenu.
Modified:
branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
branches/shell-experiments/base/shell/rshell/CMenuBand.h
branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp
branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp
branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h
branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp
branches/shell-experiments/base/shell/rshell/CMenuToolbars.h
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuBand.cpp [iso-8859-1] Sat Mar 15
21:38:15 2014
@@ -345,6 +345,35 @@
hr = _CallCB(SMC_INITMENU, 0, 0);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
+ }
+
+ CComPtr<IObjectWithSite> ows;
+ if (SUCCEEDED(m_subMenuParent->QueryInterface(IID_PPV_ARG(IObjectWithSite,
&ows))))
+ {
+ CComPtr<IServiceProvider> sp;
+ if (SUCCEEDED(ows->GetSite(IID_PPV_ARG(IServiceProvider, &sp))))
+ {
+ CComPtr<IDeskBar> db0;
+ if (SUCCEEDED(sp->QueryInterface(IID_PPV_ARG(IDeskBar, &db0))))
+ {
+ CComPtr<IUnknown> unk0;
+ if (SUCCEEDED(db0->GetClient(&unk0)))
+ {
+ CComPtr<IDeskBar> db;
+ if (SUCCEEDED(IUnknown_QueryService(unk0, SID_SMenuBandChild,
IID_PPV_ARG(IDeskBar, &db))))
+ {
+ CComPtr<IDeskBar> db1;
+ if (SUCCEEDED(IUnknown_QueryService(m_site, SID_SMenuBandParent,
IID_PPV_ARG(IDeskBar, &db1))))
+ {
+ if (fShow)
+ db->SetClient(db1);
+ else
+ db->SetClient(NULL);
+ }
+ }
+ }
+ }
+ }
}
if (m_dwFlags & SMINIT_VERTICAL)
@@ -494,8 +523,11 @@
HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
{
- UNIMPLEMENTED;
- return S_OK;
+ if (m_subMenuChild)
+ m_subMenuChild = NULL;
+ if (!punkClient)
+ return S_OK;
+ return punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
}
HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
@@ -673,6 +705,10 @@
HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
{
+ if (m_subMenuChild && id == -1)
+ {
+ return S_FALSE;
+ }
m_hotBar = tb;
m_hotItem = id;
if (m_staticToolbar) m_staticToolbar->OnHotItemChanged(tb, id);
@@ -779,7 +815,6 @@
}
if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item);
if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item);
- m_subMenuChild = popup;
if (popup)
{
if (m_subMenuParent)
@@ -792,6 +827,15 @@
return S_OK;
}
+HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable)
+{
+ if (m_staticToolbar)
+ m_staticToolbar->DisableMouseTrack(bDisable);
+ if (m_SFToolbar)
+ m_SFToolbar->DisableMouseTrack(bDisable);
+ return S_OK;
+}
+
HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
{
UNIMPLEMENTED;
Modified: branches/shell-experiments/base/shell/rshell/CMenuBand.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuBand.h [iso-8859-1] Sat Mar 15
21:38:15 2014
@@ -176,6 +176,7 @@
HRESULT _OnHotItemChanged(CMenuToolbarBase * tb, INT id);
HRESULT _MenuItemHotTrack(DWORD changeType);
HRESULT _OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude,
CMenuToolbarBase * toolbar, INT item);
+ HRESULT _DisableMouseTrack(BOOL bDisable);
BOOL UseBigIcons()
{
Modified: branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuDeskBar.cpp [iso-8859-1] Sat Mar 15
21:38:15 2014
@@ -607,8 +607,6 @@
LRESULT CMenuDeskBar::_OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
&bHandled)
{
- DbgPrint("BaseBar %08p (de)activated (%08x, %08x).\n", m_hWnd, wParam,
lParam);
-
// BUG in ReactOS: WM_ACTIVATE/WA_INACTIVE makes no sense with lParam==hWnd
if (LOWORD(wParam) != 0 || reinterpret_cast<HWND>(lParam) == m_hWnd)
{
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.cpp [iso-8859-1] Sat
Mar 15 21:38:15 2014
@@ -115,13 +115,76 @@
CMenuFocusManager::CMenuFocusManager() :
m_currentBand(NULL),
m_currentFocus(NULL),
- m_bandCount(0)
+ m_bandCount(0),
+ m_mouseTrackDisabled(FALSE),
+ m_lastMoveFlags(0),
+ m_lastMovePos(0)
{
m_threadId = GetCurrentThreadId();
}
CMenuFocusManager::~CMenuFocusManager()
{
+}
+
+void CMenuFocusManager::DisableMouseTrack(HWND enableTo, BOOL disableThis)
+{
+ BOOL bDisable = FALSE;
+
+ int i = m_bandCount;
+ while (--i >= 0)
+ {
+ CMenuBand * band = m_bandStack[i];
+
+ HWND hwnd;
+ HRESULT hr = band->_GetTopLevelWindow(&hwnd);
+ if (FAILED_UNEXPECTEDLY(hr))
+ break;
+
+ if (hwnd == enableTo)
+ {
+ band->_DisableMouseTrack(disableThis);
+ bDisable = TRUE;
+ }
+ else
+ {
+ band->_DisableMouseTrack(bDisable);
+ }
+ }
+
+ if (m_mouseTrackDisabled == bDisable)
+ {
+ if (bDisable)
+ {
+ SetCapture(m_currentFocus);
+ }
+ else
+ ReleaseCapture();
+
+ m_mouseTrackDisabled = bDisable;
+ }
+}
+
+HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd)
+{
+ if (hWnd == m_currentFocus)
+ return S_OK;
+
+ int i = m_bandCount - 1;
+ while (--i >= 0)
+ {
+ CMenuBand * band = m_bandStack[i];
+
+ HWND hwnd;
+ HRESULT hr = band->_GetTopLevelWindow(&hwnd);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ if (hwnd == hWnd)
+ return S_OK;
+ }
+
+ return S_FALSE;
}
LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
@@ -129,6 +192,8 @@
if (nCode < 0)
return CallNextHookEx(m_hHook, nCode, wParam, lParam);
+ DWORD pos = GetMessagePos();
+
if (nCode == HC_ACTION)
{
BOOL callNext = TRUE;
@@ -138,10 +203,33 @@
switch (msg->message)
{
+ case WM_ACTIVATE: // does not trigger
+ ActivationChange(msg->hwnd);
case WM_CLOSE:
+ break;
+ case WM_MOUSEMOVE:
+ if (m_lastMoveFlags != wParam || m_lastMovePos != pos)
+ {
+ m_lastMoveFlags = wParam;
+ m_lastMovePos = pos;
+
+ POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) };
+
+ HWND window = WindowFromPoint(pt);
+
+ if (IsTrackedWindow(window) == S_OK)
+ {
+ DisableMouseTrack(window, FALSE);
+ }
+ else
+ {
+ DisableMouseTrack(NULL, FALSE);
+ }
+ }
break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
+ DisableMouseTrack(m_currentFocus, TRUE);
switch (msg->wParam)
{
case VK_MENU:
@@ -193,6 +281,36 @@
return S_OK;
}
+HRESULT CMenuFocusManager::ActivationChange(HWND newHwnd)
+{
+ HRESULT hr;
+ CMenuBand * newBand = NULL;
+
+ CMenuBand * band;
+ PeekArray(&band);
+
+ while (m_bandCount >= 0)
+ {
+ HWND hwnd;
+ hr = band->_GetTopLevelWindow(&hwnd);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ if (hwnd == newHwnd)
+ {
+ newBand = band;
+ break;
+ }
+ else
+ {
+ PopFromArray(NULL);
+ PeekArray(&band);
+ }
+ }
+
+ return UpdateFocus(newBand);
+}
+
HRESULT CMenuFocusManager::UpdateFocus(CMenuBand * newBand)
{
HRESULT hr;
@@ -217,6 +335,11 @@
return hr;
}
+ CHAR title[1024];
+ GetWindowTextA(newFocus, title, 1024);
+
+ DbgPrint("Focus is now at %08p, hwnd=%08x, title='%s'.
m_bandCount=%d\n", newBand, newFocus, title, m_bandCount);
+
m_currentFocus = newFocus;
m_currentBand = newBand;
@@ -239,14 +362,33 @@
CMenuBand * mbc;
HRESULT hr;
- hr = PopFromArray(&mbc);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
-
- if (mb != mbc)
+ HWND newFocus;
+ hr = mb->_GetTopLevelWindow(&newFocus);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ DbgPrint("Trying to pop %08p, hwnd=%08x\n", mb, newFocus);
+
+ do {
+ hr = PopFromArray(&mbc);
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ mbc = NULL;
+ return hr;
+ }
+ }
+ while (mbc && mb != mbc);
+
+ hr = PeekArray(&mb);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ hr = UpdateFocus(mb);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ if (!mbc)
return E_FAIL;
- hr = PeekArray(&mbc);
-
- return UpdateFocus(mbc);
-}
+ return S_OK;
+}
Modified: branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuFocusManager.h [iso-8859-1] Sat Mar
15 21:38:15 2014
@@ -43,6 +43,9 @@
HWND m_currentFocus;
HHOOK m_hHook;
DWORD m_threadId;
+ BOOL m_mouseTrackDisabled;
+ WPARAM m_lastMoveFlags;
+ LPARAM m_lastMovePos;
// TODO: make dynamic
#define MAX_RECURSE 20
@@ -64,10 +67,14 @@
BEGIN_COM_MAP(CMenuFocusManager)
END_COM_MAP()
+private:
LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam);
HRESULT PlaceHooks(HWND window);
HRESULT RemoveHooks(HWND window);
HRESULT UpdateFocus(CMenuBand * newBand);
+ HRESULT ActivationChange(HWND newHwnd);
+ void DisableMouseTrack(HWND enableTo, BOOL disableThis);
+ HRESULT IsTrackedWindow(HWND hWnd);
public:
HRESULT PushMenu(CMenuBand * mb);
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1]
(original)
+++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.cpp [iso-8859-1] Sat Mar 15
21:38:15 2014
@@ -40,6 +40,12 @@
#define TIMERID_HOTTRACK 1
#define SUBCLASS_ID_MENUBAND 1
+HRESULT CMenuToolbarBase::DisableMouseTrack(BOOL bDisable)
+{
+ m_disableMouseTrack = bDisable;
+ return S_OK;
+}
+
HRESULT CMenuToolbarBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LRESULT *theResult)
{
NMHDR * hdr;
@@ -82,7 +88,7 @@
return OnCommand(wParam, 0, theResult);
case TBN_HOTITEMCHANGE:
- return OnHotItemChange(reinterpret_cast<LPNMTBHOTITEM>(hdr));
+ return OnHotItemChange(reinterpret_cast<LPNMTBHOTITEM>(hdr),
theResult);
case NM_RCLICK:
return OnContextMenu(reinterpret_cast<LPNMMOUSE>(hdr));
@@ -183,7 +189,8 @@
CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) :
m_hwnd(NULL),
m_useFlatMenus(FALSE),
- m_SubclassOld(NULL),
+ m_SubclassOld(NULL),
+ m_disableMouseTrack(FALSE),
m_menuBand(menuBand),
m_hwndToolbar(NULL),
m_dwMenuFlags(0),
@@ -417,18 +424,34 @@
return m_SubclassOld(hWnd, uMsg, wParam, lParam);
}
-HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot)
-{
+HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult)
+{
+ if (m_disableMouseTrack && hot->dwFlags & HICF_MOUSE)
+ {
+ *theResult = 1;
+ return S_OK;
+ }
+
if (hot->dwFlags & HICF_LEAVING)
{
KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
- m_hotItem = -1;
- m_menuBand->_OnHotItemChanged(NULL, -1);
- m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
+
+ if (m_menuBand->_OnHotItemChanged(NULL, -1) == S_FALSE)
+ {
+ *theResult = 1;
+ return S_OK;
+ }
+ else
+ {
+ m_hotItem = -1;
+ m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
+ return S_OK;
+ }
}
else if (m_hotItem != hot->idNew)
{
- if (m_toolbarFlags & SMINIT_VERTICAL)
+ if (hot->dwFlags & HICF_MOUSE &&
+ m_toolbarFlags & SMINIT_VERTICAL)
{
DWORD elapsed = 0;
SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
@@ -438,6 +461,7 @@
m_hotItem = hot->idNew;
m_menuBand->_OnHotItemChanged(this, m_hotItem);
m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
+ return S_OK;
}
return S_OK;
}
@@ -693,11 +717,9 @@
if (btn.dwData)
{
- m_hotItem = btn.idCommand;
- if (prev != m_hotItem)
+ if (prev != btn.idCommand)
{
SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
- return m_menuBand->_OnHotItemChanged(this, m_hotItem);
}
return S_OK;
}
@@ -713,11 +735,9 @@
}
}
- m_hotItem = -1;
- if (prev != m_hotItem)
+ if (prev != -1)
{
SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0);
- m_menuBand->_OnHotItemChanged(NULL, -1);
}
return S_FALSE;
}
Modified: branches/shell-experiments/base/shell/rshell/CMenuToolbars.h
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/base/shell/rs…
==============================================================================
--- branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] (original)
+++ branches/shell-experiments/base/shell/rshell/CMenuToolbars.h [iso-8859-1] Sat Mar 15
21:38:15 2014
@@ -29,6 +29,7 @@
HFONT m_marlett;
BOOL m_useFlatMenus;
WNDPROC m_SubclassOld;
+ BOOL m_disableMouseTrack;
protected:
CMenuBand * m_menuBand;
@@ -67,12 +68,14 @@
HRESULT DoContextMenu(IContextMenu* contextMenu);
HRESULT ChangeHotItem(DWORD changeType);
- HRESULT OnHotItemChange(const NMTBHOTITEM * hot);
+ HRESULT OnHotItemChange(const NMTBHOTITEM * hot, LRESULT * theResult);
HRESULT GetIdealSize(SIZE& size);
HRESULT SetPosSize(int x, int y, int cx, int cy);
void InvalidateDraw();
+
+ HRESULT DisableMouseTrack(BOOL bDisable);
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE) = 0;
virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0;