ReactOS  0.4.13-dev-92-gf251225
CMenuFocusManager.cpp
Go to the documentation of this file.
1 /*
2  * Shell Menu Band
3  *
4  * Copyright 2014 David Quintana
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /*
22 This file implements the CMenuFocusManager class.
23 
24 This class manages the shell menus, by overriding the hot-tracking behaviour.
25 
26 For the shell menus, it uses a GetMessage hook,
27 where it intercepts messages directed to the menu windows.
28 
29 In order to show submenus using system popups, it also has a MessageFilter hook.
30 
31 The menu is tracked using a stack structure. When a CMenuBand wants to open a submenu,
32 it pushes the submenu band, or HMENU to track in case of system popups,
33 and when the menu has closed, it pops the same pointer or handle.
34 
35 While a shell menu is open, it overrides the menu toolbar's hottracking behaviour,
36 using its own logic to track both the active menu item, and the opened submenu's parent item.
37 
38 While a system popup is open, it tracks the mouse movements so that it can cancel the popup,
39 and switch to another submenu when the mouse goes over another item from the parent.
40 
41 */
42 #include "shellmenu.h"
43 #include <windowsx.h>
44 #include <commoncontrols.h>
45 #include <shlwapi_undoc.h>
46 
47 #include "CMenuFocusManager.h"
48 #include "CMenuToolbars.h"
49 #include "CMenuBand.h"
50 
51 #if DBG
52 # undef _ASSERT
53 # define _ASSERT(x) DbgAssert(!!(x), __FILE__, __LINE__, #x)
54 
55 bool DbgAssert(bool x, const char * filename, int line, const char * expr)
56 {
57  if (!x)
58  {
59  char szMsg[512];
60  const char *fname;
61 
62  fname = strrchr(filename, '\\');
63  if (fname == NULL)
64  {
65  fname = strrchr(filename, '/');
66  }
67 
68  if (fname == NULL)
69  fname = filename;
70  else
71  fname++;
72 
73  sprintf(szMsg, "%s:%d: Assertion failed: %s\n", fname, line, expr);
74 
75  OutputDebugStringA(szMsg);
76 
77  __debugbreak();
78  }
79  return x;
80 }
81 #else
82 # undef _ASSERT
83 # define _ASSERT(x) (!!(x))
84 #endif
85 
86 WINE_DEFAULT_DEBUG_CHANNEL(CMenuFocus);
87 
89 
90 // Gets the thread's assigned manager without refcounting
92 {
93  return reinterpret_cast<CMenuFocusManager *>(TlsGetValue(TlsIndex));
94 }
95 
96 // Obtains a manager for the thread, with refcounting
98 {
100 
101  if (!TlsIndex)
102  {
103  if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
104  return NULL;
105  }
106 
107  obj = GetManager();
108 
109  if (!obj)
110  {
111  obj = new CComObject<CMenuFocusManager>();
113  }
114 
115  obj->AddRef();
116 
117  return obj;
118 }
119 
120 // Releases a previously acquired manager, and deletes it if the refcount reaches 0
122 {
123  if (!obj->Release())
124  {
126  }
127 }
128 
130 {
131  return GetManager()->MsgFilterHook(nCode, wParam, lParam);
132 }
133 
135 {
136  return GetManager()->GetMsgHook(nCode, wParam, lParam);
137 }
138 
140 {
141  if (m_bandCount >= MAX_RECURSE)
142  return E_OUTOFMEMORY;
143 
145  m_bandStack[m_bandCount].mb = mb;
147  m_bandCount++;
148 
149  return S_OK;
150 }
151 
153 {
154  if (pType) *pType = NoEntry;
155  if (pMb) *pMb = NULL;
156  if (pHmenu) *pHmenu = NULL;
157 
158  if (m_bandCount <= 0)
159  return S_FALSE;
160 
161  m_bandCount--;
162 
163  if (pType) *pType = m_bandStack[m_bandCount].type;
164  if (*pType == TrackedMenuEntry)
165  {
166  if (pHmenu) *pHmenu = m_bandStack[m_bandCount].hmenu;
167  }
168  else
169  {
170  if (pMb) *pMb = m_bandStack[m_bandCount].mb;
171  }
172 
173  return S_OK;
174 }
175 
177  m_current(NULL),
178  m_parent(NULL),
179  m_hMsgFilterHook(NULL),
180  m_hGetMsgHook(NULL),
181  m_mouseTrackDisabled(FALSE),
182  m_captureHwnd(0),
183  m_hwndUnderMouse(NULL),
184  m_entryUnderMouse(NULL),
185  m_selectedMenu(NULL),
186  m_selectedItem(0),
187  m_selectedItemFlags(0),
188  m_movedSinceDown(FALSE),
189  m_windowAtDown(NULL),
190  m_PreviousForeground(NULL),
191  m_bandCount(0),
192  m_menuDepth(0)
193 {
194  m_ptPrev.x = 0;
195  m_ptPrev.y = 0;
197 }
198 
200 {
201 }
202 
203 // Used so that the toolbar can properly ignore mouse events, when the menu is being used with the keyboard
205 {
206  BOOL bDisable = FALSE;
207  BOOL lastDisable = FALSE;
208 
209  int i = m_bandCount;
210  while (--i >= 0)
211  {
213 
214  if (entry.type != TrackedMenuEntry)
215  {
216  HWND hwnd;
217  HRESULT hr = entry.mb->_GetTopLevelWindow(&hwnd);
218  if (FAILED_UNEXPECTEDLY(hr))
219  break;
220 
221  if (hwnd == parent)
222  {
223  lastDisable = disableThis;
224  entry.mb->_DisableMouseTrack(disableThis);
225  bDisable = TRUE;
226  }
227  else
228  {
229  lastDisable = bDisable;
230  entry.mb->_DisableMouseTrack(bDisable);
231  }
232  }
233  }
234  m_mouseTrackDisabled = lastDisable;
235 }
236 
238 {
239  if (m_captureHwnd != child)
240  {
241  if (child)
242  {
245  TRACE("Capturing %p\n", child);
246  }
247  else
248  {
251  TRACE("Capture is now off\n");
252  }
253 
254  }
255 }
256 
258 {
259  if (pentry)
260  *pentry = NULL;
261 
262  for (int i = m_bandCount; --i >= 0;)
263  {
265 
266  if (entry.type != TrackedMenuEntry)
267  {
268  HRESULT hr = entry.mb->IsWindowOwner(hWnd);
269  if (FAILED_UNEXPECTEDLY(hr))
270  return hr;
271  if (hr == S_OK)
272  {
273  if (pentry)
274  *pentry = &entry;
275  return S_OK;
276  }
277  }
278  }
279 
280  return S_FALSE;
281 }
282 
284 {
285  for (int i = m_bandCount; --i >= 0;)
286  {
288 
289  if (entry.type != TrackedMenuEntry)
290  {
291  HRESULT hr = entry.mb->IsWindowOwner(hWnd);
292  if (FAILED_UNEXPECTEDLY(hr))
293  return hr;
294  if (hr == S_OK)
295  return S_OK;
296  if (entry.mb->_IsPopup() == S_OK)
297  {
298  CComPtr<IUnknown> site;
299  CComPtr<IOleWindow> pw;
300  hr = entry.mb->GetSite(IID_PPV_ARG(IUnknown, &site));
301  if (FAILED_UNEXPECTEDLY(hr))
302  continue;
303  hr = IUnknown_QueryService(site, SID_SMenuBandParent, IID_PPV_ARG(IOleWindow, &pw));
304  if (FAILED_UNEXPECTEDLY(hr))
305  continue;
306 
307  HWND hParent;
308  if (pw->GetWindow(&hParent) == S_OK && hParent == hWnd)
309  return S_OK;
310  }
311  }
312  }
313 
314  return S_FALSE;
315 }
316 
318 {
319  HWND child;
320  int iHitTestResult = -1;
321 
322  POINT pt2 = { GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam) };
323  ClientToScreen(msg->hwnd, &pt2);
324 
325  POINT pt = msg->pt;
326 
327  // Don't do anything if another window is capturing the mouse.
328  HWND cCapture = ::GetCapture();
329  if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
330  return TRUE;
331 
333 
334  m_ptPrev = pt;
335 
337 
338  StackEntry * entry = NULL;
339  if (IsTrackedWindow(child, &entry) == S_OK)
340  {
341  TRACE("MouseMove");
342  }
343 
344  BOOL isTracking = FALSE;
345  if (entry && (entry->type == MenuBarEntry || m_current->type != TrackedMenuEntry))
346  {
348  iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
349  isTracking = entry->mb->_IsTracking();
350 
351  if (SendMessage(child, WM_USER_ISTRACKEDITEM, iHitTestResult, 0) == S_FALSE)
352  {
353  // The current tracked item has changed, notify the toolbar
354 
355  TRACE("Hot item tracking detected a change (capture=%p / cCapture=%p)...\n", m_captureHwnd, cCapture);
357  if (isTracking && iHitTestResult >= 0 && m_current->type == TrackedMenuEntry)
358  SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0);
359  PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult, MAKELPARAM(isTracking, TRUE));
361  return FALSE;
362  }
363  }
364 
365  if (m_entryUnderMouse != entry)
366  {
367  // Mouse moved away from a tracked window
368  if (m_entryUnderMouse)
369  {
371  }
372  }
373 
374  if (m_hwndUnderMouse != child)
375  {
376  if (entry)
377  {
378  // Mouse moved to a tracked window
379  if (m_current->type == MenuPopupEntry)
380  {
381  ScreenToClient(child, &pt2);
382  SendMessage(child, WM_MOUSEMOVE, msg->wParam, MAKELPARAM(pt2.x, pt2.y));
383  }
384  }
385 
388  }
389 
390  if (m_current->type == MenuPopupEntry)
391  {
394  }
395 
396  return TRUE;
397 }
398 
400 {
401  HWND child;
402  int iHitTestResult = -1;
403 
404  TRACE("ProcessMouseDown %d %d %d\n", msg->message, msg->wParam, msg->lParam);
405 
406  // Don't do anything if another window is capturing the mouse.
407  HWND cCapture = ::GetCapture();
408  if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
409  {
410  TRACE("Foreign capture active.\n");
411  return TRUE;
412  }
413 
414  POINT pt = msg->pt;
415 
417 
418  StackEntry * entry = NULL;
419  if (IsTrackedWindow(child, &entry) != S_OK)
420  {
421  TRACE("Foreign window detected.\n");
422  return TRUE;
423  }
424 
425  if (entry->type == MenuBarEntry)
426  {
427  if (entry != m_current)
428  {
429  TRACE("Menubar with popup active.\n");
430  return TRUE;
431  }
432  }
433 
434  if (entry)
435  {
437  iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
438 
439  if (iHitTestResult >= 0)
440  {
441  TRACE("MouseDown send %d\n", iHitTestResult);
442  entry->mb->_MenuBarMouseDown(child, iHitTestResult, isLButton);
443  }
444  }
445 
446  msg->message = WM_NULL;
447 
450 
451  TRACE("MouseDown end\n");
452 
453  return TRUE;
454 }
455 
457 {
458  HWND child;
459  int iHitTestResult = -1;
460 
461  TRACE("ProcessMouseUp %d %d %d\n", msg->message, msg->wParam, msg->lParam);
462 
463  // Don't do anything if another window is capturing the mouse.
464  HWND cCapture = ::GetCapture();
465  if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
466  return TRUE;
467 
468  POINT pt = msg->pt;
469 
471 
472  StackEntry * entry = NULL;
473  if (IsTrackedWindow(child, &entry) != S_OK)
474  return TRUE;
475 
476  if (entry)
477  {
479  iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
480 
481  if (iHitTestResult >= 0)
482  {
483  TRACE("MouseUp send %d\n", iHitTestResult);
484  entry->mb->_MenuBarMouseUp(child, iHitTestResult, isLButton);
485  }
486  }
487 
488  return TRUE;
489 }
490 
492 {
493  if (nCode < 0)
494  return CallNextHookEx(m_hMsgFilterHook, nCode, hookWParam, hookLParam);
495 
496  if (nCode == MSGF_MENU)
497  {
498  BOOL callNext = TRUE;
499  MSG* msg = reinterpret_cast<MSG*>(hookLParam);
500 
501  switch (msg->message)
502  {
503  case WM_LBUTTONDOWN:
504  case WM_RBUTTONDOWN:
506  {
507  POINT pt = msg->pt;
509  BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK;
510  if (hoveringMenuBar)
511  {
513  }
514  }
515  break;
516  case WM_MOUSEMOVE:
517  callNext = ProcessMouseMove(msg);
518  break;
519  case WM_INITMENUPOPUP:
520  TRACE("WM_INITMENUPOPUP %p %p\n", msg->wParam, msg->lParam);
521  m_selectedMenu = reinterpret_cast<HMENU>(msg->lParam);
522  m_selectedItem = -1;
524  break;
525  case WM_MENUSELECT:
526  TRACE("WM_MENUSELECT %p %p\n", msg->wParam, msg->lParam);
527  m_selectedMenu = reinterpret_cast<HMENU>(msg->lParam);
528  m_selectedItem = GET_X_LPARAM(msg->wParam);
529  m_selectedItemFlags = HIWORD(msg->wParam);
530  break;
531  case WM_KEYDOWN:
532  switch (msg->wParam)
533  {
534  case VK_LEFT:
536  {
538  }
539  break;
540  case VK_RIGHT:
542  {
544  }
545  break;
546  }
547  break;
548  }
549 
550  if (!callNext)
551  return 1;
552  }
553 
554  return CallNextHookEx(m_hMsgFilterHook, nCode, hookWParam, hookLParam);
555 }
556 
557 LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam)
558 {
559  BOOL isLButton = FALSE;
560  if (nCode < 0)
561  return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
562 
563  if (nCode == HC_ACTION)
564  {
565  BOOL callNext = TRUE;
566  MSG* msg = reinterpret_cast<MSG*>(hookLParam);
567  POINT pt = msg->pt;
568 
569  switch (msg->message)
570  {
571  case WM_CAPTURECHANGED:
572  if (m_captureHwnd)
573  {
574  TRACE("Capture lost.\n");
576  }
577  break;
578 
579  case WM_NCLBUTTONDOWN:
580  case WM_LBUTTONDOWN:
581  isLButton = TRUE;
582  TRACE("LB\n");
583 
585  {
586  POINT pt = msg->pt;
588  BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK;
589  if (hoveringMenuBar)
590  {
591  m_current->mb->_MenuItemSelect(MPOS_FULLCANCEL);
592  break;
593  }
594  }
595 
596  if (m_current->type == MenuPopupEntry)
597  {
599 
601  {
602  m_current->mb->_MenuItemSelect(MPOS_FULLCANCEL);
603  break;
604  }
605  }
606 
607  ProcessMouseDown(msg, isLButton);
608 
609  break;
610  case WM_NCRBUTTONUP:
611  case WM_RBUTTONUP:
612  ProcessMouseUp(msg, isLButton);
613  break;
614  case WM_NCLBUTTONUP:
615  case WM_LBUTTONUP:
616  isLButton = TRUE;
617  ProcessMouseUp(msg, isLButton);
618  break;
619  case WM_MOUSEMOVE:
620  callNext = ProcessMouseMove(msg);
621  break;
622  case WM_MOUSELEAVE:
623  callNext = ProcessMouseMove(msg);
624  //callNext = ProcessMouseLeave(msg);
625  break;
626  case WM_SYSKEYDOWN:
627  case WM_KEYDOWN:
628  if (m_current->type == MenuPopupEntry)
629  {
631  switch (msg->wParam)
632  {
633  case VK_ESCAPE:
634  case VK_MENU:
635  case VK_LMENU:
636  case VK_RMENU:
637  m_current->mb->_MenuItemSelect(MPOS_FULLCANCEL);
638  break;
639  case VK_RETURN:
640  m_current->mb->_MenuItemSelect(MPOS_EXECUTE);
641  break;
642  case VK_LEFT:
644  break;
645  case VK_RIGHT:
647  break;
648  case VK_UP:
650  break;
651  case VK_DOWN:
653  break;
654  }
655  msg->message = WM_NULL;
656  msg->lParam = 0;
657  msg->wParam = 0;
658  }
659  break;
660  }
661 
662  if (!callNext)
663  return 1;
664  }
665 
666  return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
667 }
668 
670 {
671  if (m_hGetMsgHook)
672  {
673  WARN("GETMESSAGE hook already placed!\n");
674  return S_OK;
675  }
676  if (m_hMsgFilterHook)
677  {
678  WARN("MSGFILTER hook already placed!\n");
679  return S_OK;
680  }
682  {
683  TRACE("Entering MSGFILTER hook...\n");
685  }
686  else
687  {
688  TRACE("Entering GETMESSAGE hook...\n");
690  }
691  return S_OK;
692 }
693 
695 {
696  if (m_hMsgFilterHook)
697  {
698  TRACE("Removing MSGFILTER hook...\n");
701  }
702  if (m_hGetMsgHook)
703  {
704  TRACE("Removing GETMESSAGE hook...\n");
707  }
708  return S_OK;
709 }
710 
711 // Used to update the tracking info to account for a change in the top-level menu
713 {
714  HRESULT hr;
715  StackEntry * old = m_current;
716 
717  TRACE("UpdateFocus\n");
718 
719  // Assign the new current item
720  if (m_bandCount > 0)
722  else
723  m_current = NULL;
724 
725  // Remove the menu capture if necesary
727  {
729  if (old && old->type == MenuPopupEntry && m_PreviousForeground)
730  {
733  }
734  }
735 
736  // Obtain the top-level window for the new active menu
738  {
740  if (FAILED_UNEXPECTEDLY(hr))
741  return hr;
742  }
743 
744  // Refresh the parent pointer
745  if (m_bandCount >= 2)
746  {
747  m_parent = &(m_bandStack[m_bandCount - 2]);
749  }
750  else
751  {
752  m_parent = NULL;
753  }
754 
755  // Refresh the menubar pointer, if applicable
756  if (m_bandCount >= 1 && m_bandStack[0].type == MenuBarEntry)
757  {
758  m_menuBar = &(m_bandStack[0]);
759  }
760  else
761  {
762  m_menuBar = NULL;
763  }
764 
765  // Remove the old hooks if the menu type changed, or we don't have a menu anymore
766  if (old && (!m_current || old->type != m_current->type))
767  {
769  {
771  }
772 
773  hr = RemoveHooks();
774  if (FAILED_UNEXPECTEDLY(hr))
775  return hr;
776  }
777 
778  // And place new ones if necessary
779  if (m_current && (!old || old->type != m_current->type))
780  {
781  hr = PlaceHooks();
782  if (FAILED_UNEXPECTEDLY(hr))
783  return hr;
784  }
785 
786  // Give the user a chance to move the mouse to the new menu
787  if (m_parent)
788  {
790  }
791 
793  {
794  if (m_captureHwnd == NULL)
795  {
796  // We need to restore the capture after a non-shell submenu or context menu is shown
797  StackEntry * topMenu = m_bandStack;
798  if (topMenu->type == MenuBarEntry)
799  topMenu++;
800 
801  // Get the top-level window from the top popup
802  CComPtr<IServiceProvider> bandSite;
803  CComPtr<IOleWindow> deskBar;
804  hr = topMenu->mb->GetSite(IID_PPV_ARG(IServiceProvider, &bandSite));
805  if (FAILED(hr))
806  goto NoCapture;
807  hr = bandSite->QueryService(SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &deskBar));
808  if (FAILED(hr))
809  goto NoCapture;
810 
811  CComPtr<IOleWindow> deskBarSite;
812  hr = IUnknown_GetSite(deskBar, IID_PPV_ARG(IOleWindow, &deskBarSite));
813  if (FAILED(hr))
814  goto NoCapture;
815 
816  // FIXME: Find the correct place for this
817  HWND hWndOwner;
818  hr = deskBarSite->GetWindow(&hWndOwner);
819  if (FAILED(hr))
820  goto NoCapture;
821 
823  if (m_PreviousForeground != hWndOwner)
824  ::SetForegroundWindow(hWndOwner);
825  else
827 
828  // Get the HWND of the top-level window
829  HWND hWndSite;
830  hr = deskBar->GetWindow(&hWndSite);
831  if (FAILED(hr))
832  goto NoCapture;
833  SetMenuCapture(hWndSite);
834  }
835 NoCapture:
836 
837  if (!m_parent || m_parent->type == MenuBarEntry)
838  {
839  if (old && old->type == TrackedMenuEntry)
840  {
841  // FIXME: Debugging code, probably not right
842  POINT pt2;
843  RECT rc2;
844  GetCursorPos(&pt2);
845  ScreenToClient(m_current->hwnd, &pt2);
847  if (PtInRect(&rc2, pt2))
849  else
851  }
852  }
853  }
854 
856 
857  return S_OK;
858 }
859 
860 // Begin tracking top-level menu bar (for file browser windows)
862 {
863  TRACE("PushMenuBar %p\n", mb);
864 
865  mb->AddRef();
866 
867  _ASSERT(m_bandCount == 0);
868 
870  if (FAILED_UNEXPECTEDLY(hr))
871  return hr;
872 
873  return UpdateFocus();
874 }
875 
876 // Begin tracking a shell menu popup (start menu or submenus)
878 {
879  TRACE("PushTrackedPopup %p\n", mb);
880 
881  mb->AddRef();
882 
884 
886  if (FAILED_UNEXPECTEDLY(hr))
887  return hr;
888 
889  hr = UpdateFocus();
890 
891  m_menuDepth++;
892 
894  {
895  m_parent->mb->_SetChildBand(mb);
896  mb->_SetParentBand(m_parent->mb);
897  }
898 
899  return hr;
900 }
901 
902 // Begin tracking a system popup submenu (submenu of the file browser windows)
904 {
905  TRACE("PushTrackedPopup %p\n", popup);
906 
907  _ASSERT(m_bandCount > 0);
909 
911  if (FAILED_UNEXPECTEDLY(hr))
912  return hr;
913 
914  TRACE("PushTrackedPopup %p\n", popup);
915  m_selectedMenu = popup;
916  m_selectedItem = -1;
918 
919  return UpdateFocus();
920 }
921 
922 // Stop tracking the menubar
924 {
926  CMenuBand * mbc;
927  HRESULT hr;
928 
929  TRACE("PopMenuBar %p\n", mb);
930 
932  {
934  }
935 
936  hr = PopFromArray(&type, &mbc, NULL);
937  if (FAILED_UNEXPECTEDLY(hr))
938  {
939  UpdateFocus();
940  return hr;
941  }
942 
944  if (type != MenuBarEntry)
945  return E_FAIL;
946 
947  if (!mbc)
948  return E_FAIL;
949 
950  mbc->_SetParentBand(NULL);
951 
952  mbc->Release();
953 
954  hr = UpdateFocus();
955  if (FAILED_UNEXPECTEDLY(hr))
956  return hr;
957 
958  if (m_current)
959  {
962  }
963 
964  return S_OK;
965 }
966 
967 // Stop tracking a shell menu
969 {
971  CMenuBand * mbc;
972  HRESULT hr;
973 
974  TRACE("PopMenuPopup %p\n", mb);
975 
977  {
979  }
980 
981  m_menuDepth--;
982 
983  hr = PopFromArray(&type, &mbc, NULL);
984  if (FAILED_UNEXPECTEDLY(hr))
985  {
986  UpdateFocus();
987  return hr;
988  }
989 
991  if (type != MenuPopupEntry)
992  return E_FAIL;
993 
994  if (!mbc)
995  return E_FAIL;
996 
997  mbc->_SetParentBand(NULL);
998 
999  mbc->Release();
1000 
1001  hr = UpdateFocus();
1002  if (FAILED_UNEXPECTEDLY(hr))
1003  return hr;
1004 
1005  if (m_current)
1006  {
1009  }
1010 
1011  return S_OK;
1012 }
1013 
1014 // Stop tracking a system popup submenu
1016 {
1018  HMENU hmenu;
1019  HRESULT hr;
1020 
1021  TRACE("PopTrackedPopup %p\n", popup);
1022 
1023  hr = PopFromArray(&type, NULL, &hmenu);
1024  if (FAILED_UNEXPECTEDLY(hr))
1025  {
1026  UpdateFocus();
1027  return hr;
1028  }
1029 
1031  if (type != TrackedMenuEntry)
1032  return E_FAIL;
1033 
1034  if (hmenu != popup)
1035  return E_FAIL;
1036 
1037  hr = UpdateFocus();
1038  if (FAILED_UNEXPECTEDLY(hr))
1039  return hr;
1040 
1041  return S_OK;
1042 }
#define WM_NCLBUTTONDOWN
Definition: winuser.h:1674
#define WM_NULL
Definition: winuser.h:1589
#define WM_USER_ISTRACKEDITEM
Definition: CMenuToolbars.h:25
HRESULT _BeforeCancelPopup()
Definition: CMenuBand.cpp:1101
#define GA_ROOT
Definition: winuser.h:2743
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define TB_HITTEST
Definition: commctrl.h:1240
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
HRESULT IsTrackedWindowOrParent(HWND hWnd)
#define TRUE
Definition: types.h:120
#define WH_GETMESSAGE
Definition: winuser.h:33
StackEntry * m_current
static CMenuFocusManager * AcquireManager()
StackEntry * m_parent
long y
Definition: polytest.cpp:48
HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
Definition: ordinal.c:2547
BOOL WINAPI ClientToScreen(_In_ HWND, _Inout_ LPPOINT)
#define WM_LBUTTONDOWN
Definition: winuser.h:1752
HRESULT hr
Definition: shlfolder.c:183
static HMENU hmenu
Definition: win.c:66
HRESULT PushToArray(StackEntryType type, CMenuBand *mb, HMENU hmenu)
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, PVOID *ppvSite)
Definition: CMenuBand.cpp:251
static IActiveScriptSite * site
Definition: script.c:149
long x
Definition: polytest.cpp:48
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1199
#define pt(x, y)
Definition: drawing.c:79
#define WM_INITMENUPOPUP
Definition: winuser.h:1722
#define VK_RMENU
Definition: winuser.h:2241
HRESULT PopTrackedPopup(HMENU popup)
HRESULT _GetTopLevelWindow(HWND *topLevel)
Definition: CMenuBand.cpp:874
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define WH_MSGFILTER
Definition: winuser.h:29
uint8_t entry
Definition: isohybrid.c:63
#define WARN(fmt,...)
Definition: debug.h:111
#define MAKELPARAM(l, h)
Definition: winuser.h:3915
#define WM_CAPTURECHANGED
Definition: winuser.h:1784
#define CALLBACK
Definition: compat.h:27
HWND hWnd
Definition: settings.c:17
#define GET_X_LPARAM(lp)
Definition: windowsx.h:274
#define VK_LEFT
Definition: winuser.h:2178
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
UINT_PTR WPARAM
Definition: windef.h:207
#define MSGF_MENU
Definition: winuser.h:1161
#define VK_DOWN
Definition: winuser.h:2181
HRESULT PushTrackedPopup(HMENU popup)
#define VK_MENU
Definition: winuser.h:2158
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define VK_ESCAPE
Definition: winuser.h:2168
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2635
const char * filename
Definition: ioapi.h:135
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
int32_t INT
Definition: typedefs.h:56
Definition: query.h:86
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1448
#define VK_RETURN
Definition: winuser.h:2155
static HWND child
Definition: cursoricon.c:298
WPARAM wParam
Definition: combotst.c:138
StackEntry * m_entryUnderMouse
GLsizei GLsizei GLuint * obj
Definition: glext.h:6042
#define WM_USER_CHANGETRACKEDITEM
Definition: CMenuToolbars.h:26
#define sprintf(buf, format,...)
Definition: sprintf.c:55
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT PopMenuBar(CMenuBand *mb)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define VK_UP
Definition: winuser.h:2179
HRESULT PushMenuBar(CMenuBand *mb)
unsigned int BOOL
Definition: ntddk_ex.h:94
#define WM_NCRBUTTONUP
Definition: winuser.h:1678
HRESULT _ChangeHotItem(CMenuToolbarBase *tb, INT id, DWORD dwFlags)
Definition: CMenuBand.cpp:880
HWND WINAPI GetCapture(void)
Definition: message.c:2879
#define WM_MOUSELEAVE
Definition: commctrl.h:4946
HRESULT PopMenuPopup(CMenuBand *mb)
#define WM_MENUSELECT
Definition: winuser.h:1723
#define S_FALSE
Definition: winerror.h:2357
#define HICF_MOUSE
Definition: commctrl.h:1298
HRESULT IsTrackedWindow(HWND hWnd, StackEntry **pentry=NULL)
smooth NULL
Definition: ftsmooth.c:416
#define WM_KEYDOWN
Definition: winuser.h:1691
LONG_PTR LPARAM
Definition: windef.h:208
Definition: parser.c:48
HRESULT _SetChildBand(CMenuBand *child)
Definition: CMenuBand.cpp:603
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:421
#define WM_RBUTTONDOWN
Definition: winuser.h:1755
#define PostMessage
Definition: winuser.h:5698
StackEntry * m_menuBar
LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
#define TRACE(s)
Definition: solgame.cpp:4
LRESULT ProcessMouseUp(MSG *msg, BOOL isLButton)
#define MAX_RECURSE
r parent
Definition: btrfs.c:2659
LONG HRESULT
Definition: typedefs.h:77
virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd)
Definition: CMenuBand.cpp:757
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:35
#define SetWindowsHookEx
Definition: winuser.h:5722
unsigned long DWORD
Definition: ntddk_ex.h:95
#define _ASSERT(x)
#define WM_RBUTTONUP
Definition: winuser.h:1756
ULONG AddRef()
#define MF_POPUP
Definition: winuser.h:136
HRESULT _SetParentBand(CMenuBand *parent)
Definition: CMenuBand.cpp:614
#define VK_LMENU
Definition: winuser.h:2240
LRESULT MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam)
WINE_DEFAULT_DEBUG_CHANNEL(CMenuFocus)
const DOCKBAR PVOID HWND hParent
Definition: tooldock.h:22
#define WM_CANCELMODE
Definition: winuser.h:1617
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1023
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:530
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
#define VK_RIGHT
Definition: winuser.h:2180
static LRESULT CALLBACK s_MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
HWND WINAPI SetCapture(_In_ HWND hWnd)
#define S_OK
Definition: intsafe.h:59
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
#define HC_ACTION
Definition: winuser.h:48
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_LBUTTONUP
Definition: winuser.h:1753
#define WM_MOUSEMOVE
Definition: winuser.h:1751
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
HWND WINAPI WindowFromPoint(_In_ POINT)
LRESULT ProcessMouseDown(MSG *msg, BOOL isLButton)
char mbc
static void ReleaseManager(CMenuFocusManager *obj)
#define GET_Y_LPARAM(lp)
Definition: windowsx.h:275
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1163
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define msg(x)
Definition: auth_time.c:54
static CMenuFocusManager * GetManager()
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2888
#define SendMessage
Definition: winuser.h:5709
void SetMenuCapture(HWND child)
#define WM_SYSKEYDOWN
Definition: winuser.h:1695
#define WM_NCLBUTTONUP
Definition: winuser.h:1675
#define HIWORD(l)
Definition: typedefs.h:246
static DWORD TlsIndex
BOOL WINAPI SetForegroundWindow(_In_ HWND)
HRESULT PushMenuPopup(CMenuBand *mb)
static const WCHAR rc2[]
Definition: oid.c:1216
BOOL WINAPI ScreenToClient(_In_ HWND, _Inout_ LPPOINT)
LONG_PTR LRESULT
Definition: windef.h:209
LRESULT ProcessMouseMove(MSG *msg)
StackEntry m_bandStack[MAX_RECURSE]
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
HRESULT PopFromArray(StackEntryType *pType, CMenuBand **pMb, HMENU *pHmenu)
LPARAM lParam
Definition: combotst.c:139
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
Definition: ignoredbgout.c:18
void DisableMouseTrack(HWND parent, BOOL disableThis)
HRESULT _MenuItemSelect(DWORD changeType)
Definition: CMenuBand.cpp:954