multi-threaded message loop issue with F1 key

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

multi-threaded message loop issue with F1 key

Postby nickb » Wed Dec 06, 2017 4:52 am

Hi,

I'm on Windows embedding CEF3 into an MFC application. I'm trying to understand what happens with the setting 'multi_threaded_message_loop' is set to true. We've been using CEF for a while like this without problems - until now.

When the user hits F1 in a CEF window, we want to display a dialog showing help. This is where problems start. For a regular MFC window there are no problems, the dialog displays and everything works as expected. When the user hits F1 from an CEF window (in this case embedded in an MFC framewnd), the dialog displays fine, but I can no longer interact with it; the application just hangs and nothing responds.

The call stacks are slightly different.

For the MFC window, the response to the F1 key occurs during the PumpMessage phase:
... large call stack ...
mfc140d.dll!AfxInternalPumpMessage() Line 181 C++ Symbols loaded.
mfc140d.dll!CWinThread::PumpMessage() Line 900 C++ Symbols loaded.
mfc140d.dll!CWinThread::Run() Line 629 C++ Symbols loaded.
mfc140d.dll!CWinApp::Run() Line 787 C++ Symbols loaded.
mfc140d.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 47 C++ Symbols loaded.
MyApp.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 26 C++ Symbols loaded.

For the CEF embedded window, it gets trapped in the PeekMessage phase:
... large call stack ...
ntdll.dll!_KiUserCallbackDispatcher@12() Unknown Symbols loaded.
user32.dll!PeekMessageA() Unknown Symbols loaded.
mfc140d.dll!CWinThread::Run() Line 617 C++ Symbols loaded.
mfc140d.dll!CWinApp::Run() Line 787 C++ Symbols loaded.
mfc140d.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 47 C++ Symbols loaded.
MyApp.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 26 C++ Symbols loaded.

So my question is does anyone know why? If I set 'multi_threaded_message_loop' to false and add implement CefDoMessageLoopWork in PumpMessage, then it works the same as the regular MFC application, but setting this flag to false is not recommended and I certainly see performance issues in doing so (for example, redrawing during a resize no longer works). I'm curious as to why PeekMessage should result in my window receiving the F1 key directly.

If anyone could shed any light on this, greatly appreciated.

Regards

Nick
nickb
Techie
 
Posts: 13
Joined: Mon Oct 08, 2012 6:41 am

Re: multi-threaded message loop issue with F1 key

Postby magreenblatt » Wed Dec 06, 2017 11:19 am

nickb wrote:When the user hits F1 from an CEF window (in this case embedded in an MFC framewnd), the dialog displays fine, but I can no longer interact with it; the application just hangs and nothing responds.

How are you handling the F1 keypress from the CEF window? How are you displaying the MFC dialog?
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: multi-threaded message loop issue with F1 key

Postby nickb » Thu Dec 07, 2017 4:55 am

Hi Marshall, thanks for your help.

We're calling 'help' through MFC's standard way. The dialog can simply be a message box (AfxMessageBox, for example).

A bit more call stack might help.

PumpMessage (working) version has extra calls:

... large call stack omitted ...
mfc140d.dll!CWnd::OnHelpInfo(tagHELPINFO * __formal) Line 3627 C++ Symbols loaded.
mfc140d.dll!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult) Line 2343 C++ Symbols loaded.
mfc140d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 2099 C++ Symbols loaded.
mfc140d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 265 C++ Symbols loaded.
mfc140d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 418 C++ Symbols loaded.
mfc140d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 299 C++ Symbols loaded.
user32.dll!__InternalCallWinProc@20() Unknown Symbols loaded.
user32.dll!UserCallWinProcCheckWow() Unknown Symbols loaded.
user32.dll!DispatchClientMessage() Unknown Symbols loaded.
user32.dll!___fnINLPHELPINFOSTRUCT@4() Unknown Symbols loaded.
ntdll.dll!_KiUserCallbackDispatcher@12() Unknown Symbols loaded.
... additional calls
user32.dll!RealDefWindowProcA() Unknown Symbols loaded.
user32.dll!DefWindowProcA() Unknown Symbols loaded.
user32.dll!__InternalCallWinProc@20() Unknown Symbols loaded.
user32.dll!UserCallWinProcCheckWow() Unknown Symbols loaded.
user32.dll!CallWindowProcA() Unknown Symbols loaded.
mfc140d.dll!CWnd::DefWindowProcA(unsigned int nMsg, unsigned int wParam, long lParam) Line 1100 C++ Symbols loaded.
mfc140d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 2100 C++ Symbols loaded.
mfc140d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 265 C++ Symbols loaded.
mfc140d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 418 C++ Symbols loaded.
mfc140d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 299 C++ Symbols loaded.
user32.dll!__InternalCallWinProc@20() Unknown Symbols loaded.
user32.dll!UserCallWinProcCheckWow() Unknown Symbols loaded.
user32.dll!DispatchMessageWorker() Unknown Symbols loaded.
user32.dll!_DispatchMessageA@4() Unknown Symbols loaded.
mfc140d.dll!AfxInternalPumpMessage() Line 181 C++ Symbols loaded.
...end of additional calls
mfc140d.dll!CWinThread::PumpMessage() Line 900 C++ Symbols loaded.
MyApp.exe!MyApp::PumpMessage() Line 3366 C++ Symbols loaded.
mfc140d.dll!CWinThread::Run() Line 629 C++ Symbols loaded

PeekMessage is shorter:
mfc140d.dll!CWnd::OnHelpInfo(tagHELPINFO * __formal) Line 3627 C++ Symbols loaded.
mfc140d.dll!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult) Line 2343 C++ Symbols loaded.
mfc140d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 2099 C++ Symbols loaded.
mfc140d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 265 C++ Symbols loaded.
mfc140d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 418 C++ Symbols loaded.
mfc140d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 299 C++ Symbols loaded.
user32.dll!__InternalCallWinProc@20() Unknown Symbols loaded.
user32.dll!UserCallWinProcCheckWow() Unknown Symbols loaded.
user32.dll!DispatchClientMessage() Unknown Symbols loaded.
user32.dll!___fnINLPHELPINFOSTRUCT@4() Unknown Symbols loaded.
ntdll.dll!_KiUserCallbackDispatcher@12() Unknown Symbols loaded.
user32.dll!PeekMessageA() Unknown Symbols loaded.
mfc140d.dll!CWinThread::Run() Line 617 C++ Symbols loaded.

Other than that, the call stacks are identical (about 100 calls above this!).

I'm trying to understand how PeekMessage results in calling the Windows WndProc when I don't think it should. What does CEF do that enables that to happen? Nowhere in this call stack is there a mention of libcef etc, so why on the CEF window only does this message get percolated in the PeekMessage rather than the PumpMessage?

Regards

Nick

-NIck
nickb
Techie
 
Posts: 13
Joined: Mon Oct 08, 2012 6:41 am

Re: multi-threaded message loop issue with F1 key

Postby nickb » Thu Dec 14, 2017 12:16 pm

So, I ended up with a fix to this by subclassing the browser window and overriding OnHelpInfo with a PostMessage instead of the default SendMessage, something like below:

Code: Select all
BEGIN_MESSAGE_MAP(CefBrowser, CWnd)
   ON_WM_HELPINFO()
END_MESSAGE_MAP()

BOOL CefBrowser::OnHelpInfo(HELPINFO* /*pHelpInfo*/)
{
   if (m_pMainFrame != NULL &&
      GetKeyState(VK_SHIFT) >= 0 &&
      GetKeyState(VK_CONTROL) >= 0 &&
      GetKeyState(VK_MENU) >= 0)
   {
      m_pMainFrame->PostMessage(WM_COMMAND, ID_HELP); // default implementation will do a send message here.
      return TRUE;
   }
   return Default() != 0;
}
nickb
Techie
 
Posts: 13
Joined: Mon Oct 08, 2012 6:41 am

Re: multi-threaded message loop issue with F1 key

Postby magreenblatt » Thu Dec 14, 2017 1:08 pm

That makes sense. SendMessage will block the sending thread until the receiving thread processes the message.
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 44 guests