A colleague and I were looking at an interesting bug today. For a little while I've been working on some new frames for the Chromium browser window. These frames are based on the CustomFrameWindow/Window ChromeViews classes that we use to contain much of the UI. Anyway the frames handle various windows non-client messages to implement Chromium's custom looking UI while still using the standard window styles expected of a resizable top level frame window, so that other system level window management functionality works properly (and window management add-ins like SplitView work better too).
One issue preventing the frames from being turned on on the trunk is an annoying flicker in the title bar when switching tabs (or loading a page, or doing just about anything that causes painting to happen near the top of the window). It wasn't happening in an easily reproducible fashion, however it nearly always happened after using the browser for a while. You'd switch tabs and it looked like Windows was trying to paint the standard windows title bar. Then our custom code would kick in and paint our window contents, which would result in an ugly flash.
After trying some elementary logging and poking around in our WM_NCPAINT handling, we looked at the message log sent to each window as the tab was switched, and compared that against the message log sent to a window using the old frames.
The new frames received this string of messages:
S WM_COMMAND wNotifyCode:0400 wID:36648 hwndCtl:073C0244 [wParam:04008F28 lParam:073C0244]
R WM_COMMAND lResult:00000000
S WM_ERASEBKGND hdc:9D0164EB [wParam:9D0164EB lParam:00000000]
R WM_ERASEBKGND fErased:True [lResult:00000001]
S WM_SETTEXT lpsz:0012E8B8 ("Netvibes (200) - Chromium") [wParam:00000000 lParam:0012E8B8]
S message:0x00AE [Unknown] wParam:00000008 lParam:00000000
S WM_GETTEXT cchTextMax:510 lpszText:0012D730 [wParam:000001FE lParam:0012D730]
R WM_GETTEXT cchCopied:25 lpszText:0012D730 ("N") [lResult:00000019]
R message:0x00AE [Unknown] lResult:00000000
The first WM_COMMAND is the Ctrl+PageUp sent to the window when I switched to the previous tab. Then comes the background erase message WM_ERASEBKGND. At this point code in BrowserView2 updates the native window title using WM_SETTEXT. This is done so that the Windows Taskbar title is in sync with the newly selected tab. Then things get interesting.
We receive an "[Unknown]" message 0x00AE, which wraps a WM_GETTEXT message. This message is not sent to the window using the old frames. I theorize that the WM_GETTEXT is being called from some Windows routine that's painting the native titlebar. Since this is all asynchronous that explains the flashing.
A quick Google search reveals that in fact yes, this mystery message 0x00AE is the cause of the problem. Under the hood it maps to WM_NCUAHDRAWCAPTION, which is not #defined in winuser.h. It has a sibling 0x00AF (which apparently maps to WM_NCUAHDRAWFRAME). The forums I found discussing this message all suggest that if you are drawing a custom frame (as we are with Chromium), then you must handle these messages to prevent DefWindowProc from doing it (and trying to paint the caption).
I have applied this change now to HWNDViewContainer and CustomFrameWindow, and things are going smoothly! I'm hoping that the code in ChromeViews will be a good reference for others wanting to build custom window frames on Windows, since the pathway here is far from clear. I may do another post later on describing all the things that need to be done, but in the mean time you can just look at the code in custom_frame_window.cc/h and go from there. At the very least, we are another step closer to turning on --magic_browzR by default!
« Google Chrome & Chromium | Main | Writing a Custom Window Frame »
Could you please shed some light as to why Google refused to follow commong CUA user interface guidelines?.
Using few screen space is one thing, not displaying a File, Edit, View... etc menus when one presses a know key combination (say Alt-F) is another.
I refuse to use Chrome until a proper user interface is available, even if it disappears when not in use.
Thoughts? Comments? Expletives? ;)
FC