Skip to content
Permalink
Browse files
2011-04-26 Brent Fulgham <bfulgham@webkit.org>
        Reviewed by Adam Roben.

        Implement a transparent WebView under Windows.  This feature
        allows the user to create small web-based applications, similar
        to the dashboard on Mac OS X.
        https://bugs.webkit.org/show_bug.cgi?id=58300

        * Interfaces/IWebViewPrivate.idl: Add new set/get accessors to
        change the state of a WebView into a Layered Window, or back
        into a standard window.
        * Interfaces/WebKit.idl: touch to force clean build
        * WebView.cpp:
        (WebView::WebView): Set layered window state in constructor.
        (WebView::updateBackingStore): Cleanup old bitmap when finished.
        (WebView::performLayeredWindowUpdate): New method to do the work
        of calling ::UpdateLayeredWindow for the WebView with proper
        alpha blending.
        (WebView::paint): Small change to prevent accelerated compositing
        when using a layered window.  DirectX is not compatible with
        ::UpdateLayeredWindow (at least currently).
        (WebView::WebViewWndProc): Adjust main window procedure to avoid
        painting a default background on a layered window (this is handled
        by Windows during compositing), and to deal with paint messages
        properly in the layered window case.
        (WebView::active): The layered window is not a child window,
        so the active state logic is slightly different.
        (WebView::setUsesLayeredWindow): New set method for layered stated.
        When called, it will convert a WebView into a Layered Window.
        (WebView::usesLayeredWindow): Accessor
        * WebView.h:
        (WebView::setUsesLayeredWindow): Declare new accessor
        (WebView::usesLayeredWindow): Declare new accessor
2011-04-26  Brent Fulgham  <bfulgham@webkit.org>

        Reviewed by Adam Roben.

        Update WinLauncher with command-line arguments to allow the
        transparency to be tested.  Use --transparent to create a
        transparent view.  Use --desktop to have the view fill the
        desktop area of the screen.
        https://bugs.webkit.org/show_bug.cgi?id=58300

        * WinLauncher/WinLauncher.cpp:
        (usesLayeredWebView): New method to indicate that the
        program is running with layered windows (alpha-blended
        transparent windows).
        (shouldUseFullDesktop): New method to indicate that the
        program is running across the full desktop (less any
        task bars.)
        (resizeSubViews): Layered window mode doesn't have any
        winapi child windows, so this routine is exited early
        for that case.
        (subclassForLayeredWindow): Subclass the window so we can
        override its defaut message loop.
        (computeFullDesktopFrame): Convenience function to get the
        desktop region and update the frame dimensions appropriately.
        (_tWinMain): Updated to accept the new '--transparent' and
        '--desktop' arguments.
        (InitInstance): Modified to exit early for the transparent
        background case.  WebKit will construct our primary window (with
        appropriate settings) so we don't need to create one ourselves.
        (WndProc):
        (TransparentWndProc): New message loop for transparent windows,
        since they need special handling to support dragging.


Canonical link: https://commits.webkit.org/74712@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@84990 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Brent Fulgham committed Apr 27, 2011
1 parent 3e100e5 commit 653ab409a6519af1375aa25d0a20bf1e24d3f0af
Showing 7 changed files with 367 additions and 51 deletions.
@@ -1,3 +1,38 @@
2011-04-26 Brent Fulgham <bfulgham@webkit.org>

Reviewed by Adam Roben.

Implement a transparent WebView under Windows. This feature
allows the user to create small web-based applications, similar
to the dashboard on Mac OS X.
https://bugs.webkit.org/show_bug.cgi?id=58300

* Interfaces/IWebViewPrivate.idl: Add new set/get accessors to
change the state of a WebView into a Layered Window, or back
into a standard window.
* Interfaces/WebKit.idl: touch to force clean build
* WebView.cpp:
(WebView::WebView): Set layered window state in constructor.
(WebView::updateBackingStore): Cleanup old bitmap when finished.
(WebView::performLayeredWindowUpdate): New method to do the work
of calling ::UpdateLayeredWindow for the WebView with proper
alpha blending.
(WebView::paint): Small change to prevent accelerated compositing
when using a layered window. DirectX is not compatible with
::UpdateLayeredWindow (at least currently).
(WebView::WebViewWndProc): Adjust main window procedure to avoid
painting a default background on a layered window (this is handled
by Windows during compositing), and to deal with paint messages
properly in the layered window case.
(WebView::active): The layered window is not a child window,
so the active state logic is slightly different.
(WebView::setUsesLayeredWindow): New set method for layered stated.
When called, it will convert a WebView into a Layered Window.
(WebView::usesLayeredWindow): Accessor
* WebView.h:
(WebView::setUsesLayeredWindow): Declare new accessor
(WebView::usesLayeredWindow): Declare new accessor

2011-04-21 Ryosuke Niwa <rniwa@webkit.org>

Windows build fix.
@@ -153,6 +153,9 @@ interface IWebViewPrivate : IUnknown
HRESULT setTransparent([in] BOOL transparent);
HRESULT transparent([out, retval] BOOL* transparent);

HRESULT setUsesLayeredWindow([in] BOOL usesLayeredWindow);
HRESULT usesLayeredWindow([out, retval] BOOL* usesLayeredWindow);

HRESULT setAlwaysUsesComplexTextCodePath([in] BOOL complex);
HRESULT alwaysUsesComplexTextCodePath([out, retval] BOOL* complex);

@@ -301,3 +301,4 @@ library WebKit
[default] interface IWebUserContentURLPattern;
}
}

@@ -1,5 +1,7 @@
/*
* Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple, Inc. All rights reserved.
* Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
* Copyright (C) 2011 Brent Fulgham. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -358,6 +360,7 @@ WebView::WebView()
#endif
, m_nextDisplayIsSynchronous(false)
, m_lastSetCursor(0)
, m_usesLayeredWindow(false)
{
JSC::initializeThreading();
WTF::initializeMainThread();
@@ -949,10 +952,11 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore

HDC windowDC = 0;
HDC bitmapDC = dc;
HGDIOBJ oldBitmap = 0;
if (!dc) {
windowDC = ::GetDC(m_viewWindow);
bitmapDC = ::CreateCompatibleDC(windowDC);
::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
oldBitmap = ::SelectObject(bitmapDC, m_backingStoreBitmap->handle());
}

if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
@@ -982,19 +986,43 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore
}

if (!dc) {
::SelectObject(bitmapDC, oldBitmap);
::DeleteDC(bitmapDC);
::ReleaseDC(m_viewWindow, windowDC);
}

GdiFlush();
}

void WebView::performLayeredWindowUpdate()
{
HDC hdcScreen = ::GetDC(m_viewWindow);
OwnPtr<HDC> hdcMem = adoptPtr(::CreateCompatibleDC(hdcScreen));
HBITMAP hbmOld = static_cast<HBITMAP>(::SelectObject(hdcMem.get(), m_backingStoreBitmap->handle()));

BITMAP bmpInfo;
::GetObject(m_backingStoreBitmap->handle(), sizeof(bmpInfo), &bmpInfo);
SIZE windowSize = { bmpInfo.bmWidth, bmpInfo.bmHeight };

BLENDFUNCTION blendFunction;
blendFunction.BlendOp = AC_SRC_OVER;
blendFunction.BlendFlags = 0;
blendFunction.SourceConstantAlpha = 0xFF;
blendFunction.AlphaFormat = AC_SRC_ALPHA;

POINT layerPos = { 0, 0 };
::UpdateLayeredWindow(m_viewWindow, hdcScreen, 0, &windowSize, hdcMem.get(), &layerPos, 0, &blendFunction, ULW_ALPHA);

::SelectObject(hdcMem.get(), hbmOld);
::ReleaseDC(0, hdcScreen);
}

void WebView::paint(HDC dc, LPARAM options)
{
LOCAL_GDI_COUNTER(0, __FUNCTION__);

#if USE(ACCELERATED_COMPOSITING)
if (isAcceleratedCompositing()) {
if (isAcceleratedCompositing() && !usesLayeredWindow()) {
m_layerTreeHost->flushPendingLayerChangesNow();
// Flushing might have taken us out of compositing mode.
if (isAcceleratedCompositing()) {
@@ -2097,8 +2125,17 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam,
switch (message) {
case WM_PAINT: {
webView->paint(0, 0);
if (webView->usesLayeredWindow())
webView->performLayeredWindowUpdate();
break;
}
case WM_ERASEBKGND:
if (webView->usesLayeredWindow()) {
// Don't perform a background erase for transparent views.
handled = true;
lResult = 1;
}
break;
case WM_PRINTCLIENT:
webView->paint((HDC)wParam, lParam);
break;
@@ -3314,6 +3351,9 @@ HRESULT STDMETHODCALLTYPE WebView::searchFor(
bool WebView::active()
{
HWND activeWindow = GetActiveWindow();
if (usesLayeredWindow() && activeWindow == m_viewWindow)
return true;

return (activeWindow && m_topLevelParent == findTopLevelParent(activeWindow));
}

@@ -5788,6 +5828,84 @@ HRESULT STDMETHODCALLTYPE WebView::transparent(BOOL* transparent)
return S_OK;
}

static bool setWindowStyle(HWND window, int index, LONG_PTR newValue)
{
// According to MSDN, if the last value of the flag we are setting was zero,
// then SetWindowLongPtr returns zero, even though the call succeeded. So,
// we have to clear the error state, then check the last error after
// setting the value to see if it actually was a failure.
::SetLastError(0);
return ::SetWindowLongPtr(window, index, newValue) || !::GetLastError();
}

HRESULT WebView::setUsesLayeredWindow(BOOL usesLayeredWindow)
{
if (m_usesLayeredWindow == !!usesLayeredWindow)
return S_OK;

if (!m_viewWindow)
return E_FAIL;

RECT rect;
::GetWindowRect(m_viewWindow, &rect);

LONG_PTR origExStyle = ::GetWindowLongPtr(m_viewWindow, GWL_EXSTYLE);
LONG_PTR origStyle = ::GetWindowLongPtr(m_viewWindow, GWL_STYLE);

// The logic here has to account for the way SetParent works.
// According to MSDN, to go from a child window to a popup window,
// you must clear the child bit after setting the parent to 0.
// On the other hand, to go from a popup window to a child, you
// must clear the popup state before setting the parent.
if (usesLayeredWindow) {
LONG_PTR newExStyle = origExStyle | WS_EX_LAYERED;
LONG_PTR newStyle = (origStyle & ~(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)) | WS_POPUP;

HWND origParent = ::SetParent(m_viewWindow, 0);

if (!setWindowStyle(m_viewWindow, GWL_STYLE, newStyle)) {
::SetParent(m_viewWindow, origParent);
return E_FAIL;
}

if (!setWindowStyle(m_viewWindow, GWL_EXSTYLE, newExStyle)) {
setWindowStyle(m_viewWindow, GWL_STYLE, origStyle);
::SetParent(m_viewWindow, origParent);
return E_FAIL;
}
} else {
LONG_PTR newExStyle = origExStyle & ~WS_EX_LAYERED;
LONG_PTR newStyle = (origStyle & ~WS_POPUP) | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

if (!setWindowStyle(m_viewWindow, GWL_EXSTYLE, newExStyle))
return E_FAIL;

if (!setWindowStyle(m_viewWindow, GWL_STYLE, newStyle)) {
setWindowStyle(m_viewWindow, GWL_EXSTYLE, origExStyle);
return E_FAIL;
}

::SetParent(m_viewWindow, m_hostWindow ? m_hostWindow : HWND_MESSAGE);
}

// MSDN indicates that SetWindowLongPtr doesn't take effect for some settings until a
// SetWindowPos is called.
::SetWindowPos(m_viewWindow, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);

m_usesLayeredWindow = usesLayeredWindow;
return S_OK;
}

HRESULT WebView::usesLayeredWindow(BOOL* usesLayeredWindow)
{
if (!usesLayeredWindow)
return E_POINTER;

*usesLayeredWindow = this->usesLayeredWindow() ? TRUE : FALSE;
return S_OK;
}

HRESULT STDMETHODCALLTYPE WebView::setCookieEnabled(BOOL enable)
{
if (!m_page)
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
* Copyright (C) 2011 Brent Fulgham. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -123,7 +125,7 @@ class WebView
/* [in] */ RECT frame,
/* [in] */ BSTR frameName,
/* [in] */ BSTR groupName);

virtual HRESULT STDMETHODCALLTYPE setUIDelegate(
/* [in] */ IWebUIDelegate *d);

@@ -823,6 +825,9 @@ class WebView
virtual HRESULT STDMETHODCALLTYPE setMinimumTimerInterval(
/* [in] */ double);

virtual HRESULT STDMETHODCALLTYPE setUsesLayeredWindow(BOOL);
virtual HRESULT STDMETHODCALLTYPE usesLayeredWindow(BOOL*);

// WebView
bool shouldUseEmbeddedView(const WTF::String& mimeType) const;

@@ -859,6 +864,7 @@ class WebView
bool didClose() const { return m_didClose; }

bool transparent() const { return m_transparent; }
bool usesLayeredWindow() const { return m_usesLayeredWindow; }

bool onIMEStartComposition();
bool onIMEComposition(LPARAM);
@@ -947,6 +953,8 @@ class WebView
void paintIntoBackingStore(WebCore::FrameView*, HDC bitmapDC, const WebCore::IntRect& dirtyRect, WindowsToPaint);
void updateBackingStore(WebCore::FrameView*, HDC = 0, bool backingStoreCompletelyDirty = false, WindowsToPaint = PaintWebViewOnly);

void performLayeredWindowUpdate();

WebCore::DragOperation keyStateToDragOperation(DWORD grfKeyState) const;

// FIXME: This variable is part of a workaround. The drop effect (pdwEffect) passed to Drop is incorrect.
@@ -1077,6 +1085,7 @@ class WebView
#endif

bool m_nextDisplayIsSynchronous;
bool m_usesLayeredWindow;

HCURSOR m_lastSetCursor;

@@ -1,3 +1,36 @@
2011-04-26 Brent Fulgham <bfulgham@webkit.org>

Reviewed by Adam Roben.

Update WinLauncher with command-line arguments to allow the
transparency to be tested. Use --transparent to create a
transparent view. Use --desktop to have the view fill the
desktop area of the screen.
https://bugs.webkit.org/show_bug.cgi?id=58300

* WinLauncher/WinLauncher.cpp:
(usesLayeredWebView): New method to indicate that the
program is running with layered windows (alpha-blended
transparent windows).
(shouldUseFullDesktop): New method to indicate that the
program is running across the full desktop (less any
task bars.)
(resizeSubViews): Layered window mode doesn't have any
winapi child windows, so this routine is exited early
for that case.
(subclassForLayeredWindow): Subclass the window so we can
override its defaut message loop.
(computeFullDesktopFrame): Convenience function to get the
desktop region and update the frame dimensions appropriately.
(_tWinMain): Updated to accept the new '--transparent' and
'--desktop' arguments.
(InitInstance): Modified to exit early for the transparent
background case. WebKit will construct our primary window (with
appropriate settings) so we don't need to create one ourselves.
(WndProc):
(TransparentWndProc): New message loop for transparent windows,
since they need special handling to support dragging.

2011-04-26 Alexandre MAzari <amazari@igalia.com>

Reviewed by Xan Lopez.

0 comments on commit 653ab40

Please sign in to comment.