Greetings Chromium developers, (Please feel free to ignore this e-mail if you are not interested in Windows 7.) To celebrate the launch of Windows 7, I have written a document that describes my prototype implementation that integrates Tab Thumbnails and Aero Peek into Chromium. (My current prototype has some problems, though.)Your comments and suggestions are definitely welcome.
Sorry for sending a huge e-mail in advance. Regards, Hironori Bono E-mail: hb...@chromium.org *Tab Thumbnails and Aero Peek* Objective This document is a report of my prototype implementation that integrates two new features of Windows 7 (Tab Thumbnails and Aero Peek) into Chromium. Background Windows 7, the new operating system from Microsoft, has added some new features to its taskbar[1]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn1>: JumpList, Tab Thumbnails, Aero Peek, etc. Among these new features, Tab Thumbnails and Aero Peek are designed for improving the user experiences of TDI (Tab-Document-Interface) applications. In fact, users want for Chrome to support them and filed an issue to our buganizer (Issue 6337[2]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn2> ). * What are Tab Thumbnails and Aero Peek?* In Windows 7, an application can add (or remove) thumbnails for each application so that hovering over its taskbar button to display them as shown in Figure 1. Each thumbnail can have its own title and icon. (A thumbnail can also have its own buttons even though this example doesn’t use them.) The focused tab is shown as a high-lighted thumbnail in this thumbnail list. Figure 1 Tab Thumbnails As shown in Figure 2, hovering a mouse cursor onto a thumbnail shows the preview image of the corresponding tab, and clicking a thumbnail selects the tab, respectively. (This feature is called as Aero Peek.) Figure 2 Aero Peek Also, clicking the close button of a thumbnail (shown at the top-right corner of the focused thumbnail) closes the corresponding tab. Figure 3 Close button of a thumbnail * * Implementing Tab Thumbnails and Aero Peek Unfortunately, without using new APIs provided by Windows 7, Windows 7 just shows the thumbnail of the application window. This section provides a generic overview about implementing Tab Thumbnails and Aero Peek. (The information in this section is just the result of my investigation, and maybe incorrect.) How to add a custom thumbnail? At first, we need to add a custom thumbnail to the Tab-Thumbnail list of Windows 7. To add a custom thumbnail, we need a (tool) window[3]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn3>that receives messages from Windows 7. Windows 7 sends the following messages to notify thumbnail-specific events. So, we need to create a place-holder window that handles these events for each tab. 1. * WM_CREATE (0x0001) This message is sent when a window has been created. An application has to call DwmSetWindowAttribute() to notify Windows 7 that this window can handle WM_DWMSENDICONICTHUMBNAIL and WM_DWMSENDICONICLIVEPREVIEWBITMAP messages[4]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn4>. Also, an application needs to call ITaskbarList3::RegisterTab() to add this window to the Tab-Thumbnail list of an application[5]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn5> . 2. * WM_ACTIVATE (0x0006) This message is sent when a user clicks the thumbnail image to select its corresponding tab. 3. * WM_CLOSE (0x0010) This message is sent when a user clicks the close button of a thumbnail. An application has to call ITaskbarList3::UnregisterTab() to remove this window from the Tab-Thumbnail list before calling DestroyWindow(). 4. * WM_DWMSENDICONICTHUMBNAIL (0x0323) This message is sent when Windows 7 needs the thumbnail image of the corresponding tab. An application has to create a thumbnail bitmap (whose size is given as the LPARAM parameter of this message[6]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn6>) and send it to Windows 7 through a DwmSetIconicThumbnail() call. (Windows 7 shows a “loading” animation before sending a bitmap to Windows 7.) 5. * WM_DWMSENDICONICLIVEPREVIEWBITMAP (0x0326) This message is sent when Windows 7 needs the preview image of the corresponding tab. An application has to create a preview bitmap and send it to Windows 7 through a DwmSetIconicLivePreviewBitmap() call. How to update the thumbnail image of a tab? Windows 7 can send WM_DWMSENDICONICTHUMBNAIL messages to a place-holder window when it needs its thumbnail image. On the other hand, when an application needs to update the thumbnail image of a tab, it has to call DwmInvalidateIconicBitmaps() and let Windows 7 send a WM_DWMSENDICONICTHUMBNAIL message. It makes Windows 7 unhappy and usually returns E_FAIL to call DwmSetIconicThumbnail() directly. How to set the title of a thumbnail? Windows 7 uses GetWindowText() to retrieve the title text from a place-holder window. So, an application has to call SetWindowText() and update the title of a place-holder window. How to set the custom icon for a thumbnail? Windows 7 uses WM_GETICON messages to retrieve the icon from a place-holder window. Unlike DwmSetIconicThumbnail(), Windows does NOT create a copy of an icon retrieved through the WM_GETICON message. So, an application has to keep the HICON object while it is used by a place-holder window and delete it when it is not used any longer. *Integrating Tab Thumbnails and Aero Peek into Chromium* When we understand how to implement Tab Thumbnails and Aero Peek, we need to find the best design to integrate Tab Thumbnails and Aero Peek into Chromium. This section provides an overview about my design which integrates them into Chromium. Design Concept After some investigation, my current prototype *creates a proxy class which implements the TabStripModelObserver interface and adds it to the TabStripModel object of a browser process*. Even though I chose this design mainly because Tab Thumbnails are very similar with TabStrip[7]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn7>, this design has the following *pro et contra* (for and against). · Pros o It is easy to synchronize with TabStrip. o We don’t need to change the existing code so much (just creating the new class and add it to the observer list.) · Cons o It is hard to get some events related to a tab (e.g. scrolling a page, resizing a browser window, etc.) The major functionalities of this proxy class are listed below: · Create a place-holder window; · Maintain the list of place-holder windows; · Translate events received through the TabStripModelObserver interface to native tasks for Windows 7 (e.g. DwmSetIconicThumbnails(), DwmSetIconicLivePreviewBitmap(), etc.); · Translate window messages (e.g. WM_CLOSE, WM_ACTIVATE, etc.) received by a place-holder window to tasks of TabStripModel (or TabContents), and; · Activate (or close) the corresponding tab through a TabContentsDelegate interface. Implementation Tips How to find “the corresponding tab”? Each TabContents object has an ID, which can be retrieved through a “controller().session_id().id()” call[8]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftn8>. My implementation uses this ID to attach a place-holder window and a TabContents object. How to create the thumbnail image? Each tab (i.e. TabContents) has a BackingStore object, which has the rendering result of the tab. Fortunately, the BackingStore object has a HDC handle to keep the bitmap. So, my implementation retrieves this HDC handle from a BackingStore object and copies its image. Unfortunately, it seems Chromium does not redraw inactive tabs when we resize a browser window. Since my prototype uses the rendered results of Chromium, it updates only the thumbnail of the focused tab when we resize a browser window. Figure 4 Thumbnails when resizing a browser window How to create the preview image used by Aero Peek? A preview image used by Aero Peek has to be a complete image of an application window, i.e. it has to include images of TabStrip, omnibox, etc. On the other hand, a BackingStore object only has an image inside a tab. So, we need to create an appropriate preview image from them especially when we need a preview image of a background tab. My current prototype uses very simple approach as listed below: 1. 1. Retrieve the image of a browser window. 2. 2. Retrieve the image of a BackingStore object. 3. 3. Paste the BackingStore image onto the image of the frame window . Unfortunately, this approach also causes a problem when we resize a browser window. As I wrote above, Chromium does not redraw its background tabs when we resize a browser window. So, when my prototype creates a preview image of a background tab after we resize a browser window. It makes a broken image as shown in Figure 5. Figure 5 Preview image of a background tab when resizing a browser window My Prototype Code I have uploaded the whole code of my prototype onto Rietveld: < http://codereview.chromium.org/303033/show>. Any comments or suggestions are welcome. Challenges How to treat resize events of a browser window? The biggest problems of my current prototype are caused by my prototype that doesn’t handle resize events of a browser window. (Figure 4 may be acceptable. But, I think Figure 5 is unacceptable for many users.) The easiest solution for this problem is forcing a background tab to redraw when we need an image used for Aero Peek or Tab Thumbnails. Unfortunately, this solution probably hurts the rendering performance of Chromium. Another solution (or a workaround) is displaying a message “the preview image for the selected tab is not available” instead of showing a broken image. Any opinions or suggestions are definitely helpful. ------------------------------ [1]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref1> http://msdn.microsoft.com/en-us/library/dd378460(VS.85).aspx [2]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref2> http://crbug.com/6337 [3]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref3>When I implemented a prototype, this window must be a tool window. [4]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref4>Without calling DwmSetWindowAttribute(), Windows 7 doesn’t send the messages. [5]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref5>Without calling this function, all DwmSetIconicThumbnail() and DwmSetIconicLivePreviewBitmap() calls return E_FAIL. [6]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref6>When an application sends a larger image than this size, DwmSetIconicThumbnail() returns E_FAIL. [7]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref7>In brief, I thought “like dissolves like”. [8]<file:///C:/Users/hBono/Documents/Google/Chrome/Tab%20Thumbnails%20and%20Aero%20Peek.docx#_ftnref8>I just copied this call from “extension_tabs_module.cc”. Please correct me if I’m wrong. --~--~---------~--~----~------------~-------~--~----~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~----------~----~----~----~------~----~------~--~---