mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 12:07:52 +00:00
Fix for bug 264708: Single-bit transparency not supported on Win98
Patch by Dainis Jonitis r=emaijala sr=roc
This commit is contained in:
parent
57f7000a49
commit
d46f71b538
@ -209,7 +209,7 @@ enum nsCursor { ///(normal cursor, usually rendered as an arrow)
|
||||
enum nsContentType {
|
||||
eContentTypeInherit = -1,
|
||||
eContentTypeUI = 0, // eContentTypeUI must equal 0
|
||||
eContentTypeContent = 1 // eContentTypeUI must equal 1
|
||||
eContentTypeContent = 1 // eContentTypeContent must equal 1
|
||||
};
|
||||
|
||||
enum nsTopLevelWidgetZPlacement { // for PlaceBehind()
|
||||
|
@ -134,6 +134,9 @@ static const char *kMozHeapDumpMessageString = "MOZ_HeapDump";
|
||||
#define SPI_GETWHEELSCROLLLINES 104
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
|
||||
#ifndef AC_SRC_ALPHA
|
||||
#define AC_SRC_ALPHA 0x01
|
||||
#endif
|
||||
@ -147,6 +150,27 @@ static const char *kMozHeapDumpMessageString = "MOZ_HeapDump";
|
||||
#endif
|
||||
|
||||
|
||||
typedef BOOL WINAPI UpdateLayeredWindowProc (HWND hWnd, HDC hdcDst, POINT *pptDst,
|
||||
SIZE *psize, HDC hdcSrc, POINT *pptSrc,
|
||||
COLORREF crKey, BLENDFUNCTION *pblend,
|
||||
DWORD dwFlags);
|
||||
|
||||
|
||||
static UpdateLayeredWindowProc* GetUpdateLayeredWindowProc()
|
||||
{
|
||||
HMODULE user32 = ::GetModuleHandle("user32.dll");
|
||||
|
||||
return NS_REINTERPRET_CAST(UpdateLayeredWindowProc*,
|
||||
(user32) ? ::GetProcAddress(user32, "UpdateLayeredWindow") : nsnull);
|
||||
}
|
||||
|
||||
static UpdateLayeredWindowProc* pUpdateLayeredWindow = GetUpdateLayeredWindowProc();
|
||||
|
||||
static inline PRBool IsAlphaTranslucencySupported() { return pUpdateLayeredWindow != nsnull; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Pick some random timer ID. Is there a better way?
|
||||
#define NS_FLASH_TIMER_ID 0x011231984
|
||||
|
||||
@ -779,8 +803,10 @@ nsWindow::nsWindow() : nsBaseWidget()
|
||||
mHas3DBorder = PR_FALSE;
|
||||
#ifdef MOZ_XUL
|
||||
mIsTranslucent = PR_FALSE;
|
||||
mMemoryBitmap = NULL;
|
||||
mMemoryDC = NULL;
|
||||
mIsTopTranslucent = PR_FALSE;
|
||||
w2k.mMemoryBitmap = NULL;
|
||||
w2k.mMemoryDC = NULL;
|
||||
w9x.mPerformingSetWindowRgn = PR_FALSE;
|
||||
mAlphaMask = nsnull;
|
||||
#endif
|
||||
mWindowType = eWindowType_child;
|
||||
@ -1655,12 +1681,9 @@ NS_METHOD nsWindow::Destroy()
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTranslucent)
|
||||
{
|
||||
::DeleteDC(mMemoryDC);
|
||||
::DeleteObject(mMemoryBitmap);
|
||||
delete [] mAlphaMask;
|
||||
SetupTranslucentWindowMemoryBitmap(PR_FALSE);
|
||||
|
||||
mMemoryDC = NULL;
|
||||
mMemoryBitmap = NULL;
|
||||
delete [] mAlphaMask;
|
||||
mAlphaMask = nsnull;
|
||||
}
|
||||
#endif
|
||||
@ -1701,19 +1724,23 @@ NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent)
|
||||
//-------------------------------------------------------------------------
|
||||
nsIWidget* nsWindow::GetParent(void)
|
||||
{
|
||||
if (mIsTopWidgetWindow) {
|
||||
return GetParent(PR_TRUE);
|
||||
}
|
||||
|
||||
nsWindow* nsWindow::GetParent(PRBool aStopOnFirstTopLevel)
|
||||
{
|
||||
if (mIsTopWidgetWindow && aStopOnFirstTopLevel) {
|
||||
// Must use a flag instead of mWindowType to tell if the window is the
|
||||
// owned by the topmost widget, because a child window can be embedded inside
|
||||
// a HWND which is not associated with a nsIWidget.
|
||||
return nsnull;
|
||||
}
|
||||
/* If this widget has already been destroyed, pretend we have no parent.
|
||||
This corresponds to code in Destroy which removes the destroyed
|
||||
widget from its parent's child list. */
|
||||
// If this widget has already been destroyed, pretend we have no parent.
|
||||
// This corresponds to code in Destroy which removes the destroyed
|
||||
// widget from its parent's child list.
|
||||
if (mIsDestroying || mOnDestroyCalled)
|
||||
return nsnull;
|
||||
|
||||
|
||||
nsWindow* widget = nsnull;
|
||||
if (mWnd) {
|
||||
HWND parent = ::GetParent(mWnd);
|
||||
@ -1731,7 +1758,7 @@ nsIWidget* nsWindow::GetParent(void)
|
||||
}
|
||||
}
|
||||
|
||||
return (nsIWidget*)widget;
|
||||
return widget;
|
||||
}
|
||||
|
||||
|
||||
@ -2535,10 +2562,9 @@ NS_IMETHODIMP nsWindow::HideWindowChrome(PRBool aShouldHide)
|
||||
DWORD tempStyle = nsToolkit::mGetWindowLong(hwnd, GWL_STYLE);
|
||||
DWORD tempExStyle = nsToolkit::mGetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
|
||||
style = WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
|
||||
exStyle = tempExStyle & WS_EX_LAYERED;
|
||||
|
||||
if (tempExStyle & WS_EX_LAYERED) style = 0;
|
||||
style = tempStyle & ~(WS_CAPTION | WS_THICKFRAME);
|
||||
exStyle = tempExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE |
|
||||
WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
|
||||
mOldStyle = tempStyle;
|
||||
mOldExStyle = tempExStyle;
|
||||
@ -2591,8 +2617,8 @@ NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
|
||||
#endif // NS_DEBUG
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTranslucent)
|
||||
OnPaint(mMemoryDC);
|
||||
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||
OnPaint(w2k.mMemoryDC);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@ -2624,8 +2650,8 @@ NS_METHOD nsWindow::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
|
||||
#endif // NS_DEBUG
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTranslucent)
|
||||
OnPaint(mMemoryDC);
|
||||
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||
OnPaint(w2k.mMemoryDC);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@ -2651,8 +2677,8 @@ nsWindow::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
|
||||
nsresult rv = NS_OK;
|
||||
if (mWnd) {
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTranslucent)
|
||||
OnPaint(mMemoryDC);
|
||||
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||
OnPaint(w2k.mMemoryDC);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@ -2688,7 +2714,7 @@ NS_IMETHODIMP nsWindow::Update()
|
||||
if (mWnd)
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTranslucent)
|
||||
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||
{
|
||||
// rv = UpdateTranslucentWindow();
|
||||
} else
|
||||
@ -2715,7 +2741,8 @@ void* nsWindow::GetNativeData(PRUint32 aDataType)
|
||||
case NS_NATIVE_GRAPHIC:
|
||||
// XXX: This is sleezy!! Remember to Release the DC after using it!
|
||||
#ifdef MOZ_XUL
|
||||
return (void*)(!mIsTranslucent) ? ::GetDC(mWnd) : mMemoryDC;
|
||||
return (void*)(mIsTranslucent && IsAlphaTranslucencySupported()) ?
|
||||
w2k.mMemoryDC : ::GetDC(mWnd);
|
||||
#else
|
||||
return (void*)::GetDC(mWnd);
|
||||
#endif
|
||||
@ -2734,7 +2761,7 @@ void nsWindow::FreeNativeData(void * data, PRUint32 aDataType)
|
||||
{
|
||||
case NS_NATIVE_GRAPHIC:
|
||||
#ifdef MOZ_XUL
|
||||
if (!mIsTranslucent)
|
||||
if (!(mIsTranslucent && IsAlphaTranslucencySupported()))
|
||||
::ReleaseDC(mWnd, (HDC)data);
|
||||
#else
|
||||
::ReleaseDC(mWnd, (HDC)data);
|
||||
@ -4228,6 +4255,14 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
||||
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTopTranslucent && !IsAlphaTranslucencySupported() && w9x.mPerformingSetWindowRgn)
|
||||
{
|
||||
result = PR_FALSE; // Ignore events generated by SetWindowRgn
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
WINDOWPOS *wp = (LPWINDOWPOS)lParam;
|
||||
|
||||
// We only care about a resize, so filter out things like z-order
|
||||
@ -5043,7 +5078,12 @@ PRBool nsWindow::OnPaint(HDC aDC)
|
||||
|
||||
HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps));
|
||||
RECT paintRect;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
if (aDC || mIsTranslucent) {
|
||||
#else
|
||||
if (aDC) {
|
||||
#endif
|
||||
::GetClientRect(mWnd, &paintRect);
|
||||
}
|
||||
else {
|
||||
@ -5093,7 +5133,7 @@ PRBool nsWindow::OnPaint(HDC aDC)
|
||||
event.renderingContext->DestroyDrawingSurface(surf);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
if (mIsTranslucent)
|
||||
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||
{
|
||||
// Data from offscreen drawing surface was copied to memory bitmap of transparent
|
||||
// bitmap. Now it can be read from memory bitmap to apply alpha channel and after
|
||||
@ -7147,50 +7187,21 @@ STDMETHODIMP_(LRESULT) nsWindow::LresultFromObject(REFIID riid, WPARAM wParam, L
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
|
||||
typedef BOOL WINAPI UpdateLayeredWindowProc (HWND hWnd, HDC hdcDst, POINT *pptDst,
|
||||
SIZE *psize, HDC hdcSrc, POINT *pptSrc,
|
||||
COLORREF crKey, BLENDFUNCTION *pblend,
|
||||
DWORD dwFlags);
|
||||
|
||||
|
||||
static UpdateLayeredWindowProc* pUpdateLayeredWindow = NULL;
|
||||
|
||||
|
||||
static PRBool IsTranslucencySupported()
|
||||
nsWindow* nsWindow::GetTopLevelWindow()
|
||||
{
|
||||
static PRBool firstTime = PR_TRUE;
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
firstTime = PR_FALSE;
|
||||
|
||||
HMODULE user32 = ::GetModuleHandle("user32.dll");
|
||||
|
||||
if (user32)
|
||||
pUpdateLayeredWindow = (UpdateLayeredWindowProc*)::GetProcAddress(user32, "UpdateLayeredWindow");
|
||||
}
|
||||
|
||||
return pUpdateLayeredWindow != NULL;
|
||||
}
|
||||
|
||||
nsIWidget* nsWindow::GetTopLevelWidget()
|
||||
{
|
||||
nsIWidget* curWidget = this;
|
||||
NS_ADDREF(curWidget);
|
||||
nsWindow* curWindow = this;
|
||||
NS_ADDREF(curWindow);
|
||||
|
||||
while (PR_TRUE)
|
||||
{
|
||||
if (mIsTopWidgetWindow)
|
||||
return curWidget;
|
||||
|
||||
nsIWidget* parentWidget = curWidget->GetParent();
|
||||
nsWindow* parentWindow = curWindow->GetParent(PR_TRUE);
|
||||
|
||||
if (parentWidget)
|
||||
if (parentWindow)
|
||||
{
|
||||
NS_RELEASE(curWidget);
|
||||
curWidget = parentWidget;
|
||||
NS_RELEASE(curWindow);
|
||||
curWindow = parentWindow;
|
||||
} else
|
||||
return curWidget;
|
||||
return curWindow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7236,15 +7247,15 @@ void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight)
|
||||
|
||||
for (PRInt32 cy = 0 ; cy < copyHeight ; cy++)
|
||||
{
|
||||
memcpy (pDest, pSrc, copyWidth);
|
||||
memset (pDest + copyWidth, 255, growWidth);
|
||||
memcpy(pDest, pSrc, copyWidth);
|
||||
memset(pDest + copyWidth, 255, growWidth);
|
||||
pSrc += mBounds.width;
|
||||
pDest += aNewWidth;
|
||||
}
|
||||
|
||||
for (PRInt32 gy = 0 ; gy < growHeight ; gy++)
|
||||
{
|
||||
memset (pDest, 255, aNewWidth);
|
||||
memset(pDest, 255, aNewWidth);
|
||||
pDest += aNewWidth;
|
||||
}
|
||||
}
|
||||
@ -7255,38 +7266,34 @@ void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight)
|
||||
mAlphaMask = pBits;
|
||||
|
||||
|
||||
// resize the memory bitmap
|
||||
HDC hScreenDC = ::GetDC(NULL);
|
||||
mMemoryBitmap = ::CreateCompatibleBitmap(hScreenDC, aNewWidth, aNewHeight);
|
||||
|
||||
if (mMemoryBitmap)
|
||||
if (IsAlphaTranslucencySupported())
|
||||
{
|
||||
HGDIOBJ oldBitmap = ::SelectObject(mMemoryDC, mMemoryBitmap);
|
||||
::DeleteObject(oldBitmap);
|
||||
}
|
||||
// resize the memory bitmap
|
||||
HDC hScreenDC = ::GetDC(NULL);
|
||||
w2k.mMemoryBitmap = ::CreateCompatibleBitmap(hScreenDC, aNewWidth, aNewHeight);
|
||||
|
||||
::ReleaseDC(NULL, hScreenDC);
|
||||
if (w2k.mMemoryBitmap)
|
||||
{
|
||||
HGDIOBJ oldBitmap = ::SelectObject(w2k.mMemoryDC, w2k.mMemoryBitmap);
|
||||
::DeleteObject(oldBitmap);
|
||||
}
|
||||
|
||||
::ReleaseDC(NULL, hScreenDC);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsWindow::GetWindowTranslucency(PRBool& aTranslucent)
|
||||
{
|
||||
if (IsTranslucencySupported())
|
||||
{
|
||||
nsWindow* topWindow = (nsWindow*)GetTopLevelWidget();
|
||||
aTranslucent = topWindow->GetWindowTranslucencyInner();
|
||||
NS_RELEASE(topWindow);
|
||||
} else
|
||||
aTranslucent = PR_FALSE;
|
||||
nsWindow* topWindow = GetTopLevelWindow();
|
||||
aTranslucent = topWindow->GetWindowTranslucencyInner();
|
||||
NS_RELEASE(topWindow);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsWindow::SetWindowTranslucency(PRBool aTranslucent)
|
||||
{
|
||||
if (!IsTranslucencySupported())
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
nsWindow* topWindow = (nsWindow*)GetTopLevelWidget();
|
||||
nsWindow* topWindow = GetTopLevelWindow();
|
||||
nsresult rv = topWindow->SetWindowTranslucencyInner(aTranslucent);
|
||||
NS_RELEASE(topWindow);
|
||||
|
||||
@ -7295,10 +7302,7 @@ NS_IMETHODIMP nsWindow::SetWindowTranslucency(PRBool aTranslucent)
|
||||
|
||||
NS_IMETHODIMP nsWindow::UpdateTranslucentWindowAlpha(const nsRect& aRect, PRUint8* aAlphas)
|
||||
{
|
||||
if (!IsTranslucencySupported())
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
nsWindow* topWindow = (nsWindow*)GetTopLevelWidget();
|
||||
nsWindow* topWindow = GetTopLevelWindow();
|
||||
topWindow->UpdateTranslucentWindowAlphaInner(aRect, aAlphas);
|
||||
NS_RELEASE(topWindow);
|
||||
|
||||
@ -7311,8 +7315,9 @@ nsresult nsWindow::SetWindowTranslucencyInner(PRBool aTranslucent)
|
||||
return NS_OK;
|
||||
|
||||
HWND hWnd = GetTopLevelHWND(mWnd);
|
||||
nsWindow* topWindow = GetNSWindowPtr(hWnd);
|
||||
|
||||
if (!GetNSWindowPtr(hWnd))
|
||||
if (!topWindow)
|
||||
{
|
||||
NS_WARNING("Trying to use transparent chrome in an embedded context");
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -7326,7 +7331,9 @@ nsresult nsWindow::SetWindowTranslucencyInner(PRBool aTranslucent)
|
||||
~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
||||
exStyle = nsToolkit::mGetWindowLong(hWnd, GWL_EXSTYLE) &
|
||||
~(WS_EX_DLGMODALFRAME | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
exStyle |= WS_EX_LAYERED;
|
||||
|
||||
if (IsAlphaTranslucencySupported())
|
||||
exStyle |= WS_EX_LAYERED;
|
||||
} else
|
||||
{
|
||||
style = WindowStyle();
|
||||
@ -7335,48 +7342,65 @@ nsresult nsWindow::SetWindowTranslucencyInner(PRBool aTranslucent)
|
||||
nsToolkit::mSetWindowLong(hWnd, GWL_STYLE, style);
|
||||
nsToolkit::mSetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
mIsTranslucent = aTranslucent;
|
||||
topWindow->mIsTopTranslucent = aTranslucent;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (IsAlphaTranslucencySupported())
|
||||
rv = SetupTranslucentWindowMemoryBitmap(aTranslucent);
|
||||
|
||||
if (aTranslucent)
|
||||
{
|
||||
if (!mBounds.IsEmpty())
|
||||
{
|
||||
PRInt32 alphaBytes = mBounds.width * mBounds.height;
|
||||
mAlphaMask = new PRUint8 [alphaBytes];
|
||||
|
||||
if (mAlphaMask)
|
||||
memset(mAlphaMask, 255, alphaBytes);
|
||||
else
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
} else
|
||||
mAlphaMask = nsnull;
|
||||
} else
|
||||
{
|
||||
delete [] mAlphaMask;
|
||||
mAlphaMask = nsnull;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsWindow::SetupTranslucentWindowMemoryBitmap(PRBool aTranslucent)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (aTranslucent)
|
||||
{
|
||||
HDC hScreenDC = ::GetDC(NULL);
|
||||
mMemoryDC = ::CreateCompatibleDC(hScreenDC);
|
||||
w2k.mMemoryDC = ::CreateCompatibleDC(hScreenDC);
|
||||
|
||||
if (mMemoryDC)
|
||||
if (w2k.mMemoryDC)
|
||||
{
|
||||
mMemoryBitmap = ::CreateCompatibleBitmap(hScreenDC, mBounds.width, mBounds.height);
|
||||
w2k.mMemoryBitmap = ::CreateCompatibleBitmap(hScreenDC, mBounds.width, mBounds.height);
|
||||
|
||||
if (mMemoryBitmap)
|
||||
if (w2k.mMemoryBitmap)
|
||||
{
|
||||
::SelectObject(mMemoryDC, mMemoryBitmap);
|
||||
::SelectObject(w2k.mMemoryDC, w2k.mMemoryBitmap);
|
||||
|
||||
rv = NS_OK;
|
||||
|
||||
if (!mBounds.IsEmpty())
|
||||
{
|
||||
PRInt32 alphaBytes = mBounds.width * mBounds.height;
|
||||
mAlphaMask = new PRUint8 [alphaBytes];
|
||||
|
||||
if (mAlphaMask)
|
||||
memset (mAlphaMask, 255, alphaBytes);
|
||||
else
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
} else
|
||||
mAlphaMask = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
::ReleaseDC(NULL, hScreenDC);
|
||||
} else
|
||||
{
|
||||
::DeleteDC(mMemoryDC);
|
||||
::DeleteObject(mMemoryBitmap);
|
||||
delete [] mAlphaMask;
|
||||
::DeleteDC(w2k.mMemoryDC);
|
||||
::DeleteObject(w2k.mMemoryBitmap);
|
||||
|
||||
mMemoryDC = NULL;
|
||||
mMemoryBitmap = NULL;
|
||||
mAlphaMask = nsnull;
|
||||
w2k.mMemoryDC = NULL;
|
||||
w2k.mMemoryBitmap = NULL;
|
||||
|
||||
rv = NS_OK;
|
||||
}
|
||||
@ -7391,22 +7415,55 @@ void nsWindow::UpdateTranslucentWindowAlphaInner(const nsRect& aRect, PRUint8* a
|
||||
aRect.XMost() <= mBounds.width && aRect.YMost() <= mBounds.height,
|
||||
"Rect is out of window bounds");
|
||||
|
||||
PRBool transparencyMaskChanged = PR_FALSE;
|
||||
|
||||
if (!aRect.IsEmpty())
|
||||
{
|
||||
PRUint8* pSrc = aAlphas;
|
||||
PRUint8* pDest = mAlphaMask + aRect.y * mBounds.width + aRect.x;
|
||||
PRBool skipMaskChangeCheck = IsAlphaTranslucencySupported();
|
||||
PRUint8* pSrcRow = aAlphas;
|
||||
PRUint8* pDestRow = mAlphaMask + aRect.y * mBounds.width + aRect.x;
|
||||
|
||||
for (PRInt32 y = 0 ; y < aRect.height ; y++)
|
||||
{
|
||||
memcpy (pDest, pSrc, aRect.width);
|
||||
if (skipMaskChangeCheck)
|
||||
memcpy(pDestRow, pSrcRow, aRect.width);
|
||||
else
|
||||
{
|
||||
PRUint8* pSrc = pSrcRow;
|
||||
PRUint8* pDest = pDestRow;
|
||||
|
||||
pSrc += aRect.width;
|
||||
pDest += mBounds.width;
|
||||
for (PRInt32 x = 0 ; x < aRect.width ; x++)
|
||||
{
|
||||
if (!*pDest != !*pSrc)
|
||||
{
|
||||
transparencyMaskChanged = PR_TRUE;
|
||||
skipMaskChangeCheck = PR_TRUE;
|
||||
}
|
||||
|
||||
*pDest++ = *pSrc++;
|
||||
}
|
||||
}
|
||||
|
||||
pSrcRow += aRect.width;
|
||||
pDestRow += mBounds.width;
|
||||
}
|
||||
}
|
||||
|
||||
// The real screen update is performed in OnPaint() handler only after rendered
|
||||
// bits from offscreen drawing surface are copied back to memory bitmap.
|
||||
if (IsAlphaTranslucencySupported())
|
||||
{
|
||||
// Windows 2000 and newer versions support layered windows which allow to implement
|
||||
// full 256 level alpha translucency.
|
||||
// The real screen update is performed in OnPaint() handler only after rendered
|
||||
// bits from offscreen drawing surface are copied back to memory bitmap.
|
||||
} else
|
||||
{
|
||||
// Older Windows versions do not have native support for 256 level alpha translucency.
|
||||
// By use of complex shaped window regions we can achieve the effect of 1-bit
|
||||
// transparency map.
|
||||
|
||||
if (transparencyMaskChanged)
|
||||
SetWindowRegionToAlphaMask();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsWindow::UpdateTranslucentWindow()
|
||||
@ -7439,7 +7496,7 @@ nsresult nsWindow::UpdateTranslucentWindow()
|
||||
|
||||
if (pBits)
|
||||
{
|
||||
int lines = ::GetDIBits(mMemoryDC, mMemoryBitmap, 0, mBounds.height, pBits, &bi, DIB_RGB_COLORS);
|
||||
int lines = ::GetDIBits(w2k.mMemoryDC, w2k.mMemoryBitmap, 0, mBounds.height, pBits, &bi, DIB_RGB_COLORS);
|
||||
|
||||
if (lines == mBounds.height)
|
||||
{
|
||||
@ -7458,7 +7515,7 @@ nsresult nsWindow::UpdateTranslucentWindow()
|
||||
pAlpha++;
|
||||
}
|
||||
|
||||
lines = ::SetDIBits (hMemoryDC, hAlphaBitmap, 0, mBounds.height, pBits, &bi, DIB_RGB_COLORS);
|
||||
lines = ::SetDIBits(hMemoryDC, hAlphaBitmap, 0, mBounds.height, pBits, &bi, DIB_RGB_COLORS);
|
||||
}
|
||||
|
||||
delete [] pBits;
|
||||
@ -7490,4 +7547,121 @@ nsresult nsWindow::UpdateTranslucentWindow()
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsWindow::SetWindowRegionToAlphaMask()
|
||||
{
|
||||
PRInt32 minX = PR_INT32_MAX, maxX = PR_INT32_MIN;
|
||||
PRInt32 minY = PR_INT32_MAX, maxY = PR_INT32_MIN;
|
||||
PRUint8* pPixel = mAlphaMask;
|
||||
|
||||
// Convert all non-zero alpha pixels to be completely opaque (255).
|
||||
// Find minimal bounding rectangle that contains all opaque pixels.
|
||||
for (PRInt32 y = 0 ; y < mBounds.height ; y++)
|
||||
{
|
||||
PRBool lineEmpty = PR_TRUE;
|
||||
|
||||
for (PRInt32 x = 0 ; x < mBounds.width ; x++)
|
||||
{
|
||||
if (*pPixel)
|
||||
{
|
||||
*pPixel = 255;
|
||||
lineEmpty = PR_FALSE;
|
||||
|
||||
if (x < minX) minX = x;
|
||||
if (x > maxX) maxX = x;
|
||||
}
|
||||
|
||||
pPixel++;
|
||||
}
|
||||
|
||||
if (!lineEmpty)
|
||||
{
|
||||
if (y < minY) minY = y;
|
||||
if (y > maxY) maxY = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRGN hrgnOpacityMask = ::CreateRectRgn(0, 0, 0, 0);
|
||||
|
||||
if (maxY >= minY)
|
||||
{
|
||||
HRGN hrgnRectBlock = ::CreateRectRgn(0, 0, 0, 0);
|
||||
|
||||
for (PRInt32 seqY1 = minY ; seqY1 <= maxY ; seqY1++)
|
||||
{
|
||||
PRUint8* pRow = mAlphaMask + seqY1 * mBounds.width;
|
||||
|
||||
for (PRInt32 seqX1 = minX ; seqX1 <= maxX ; seqX1++)
|
||||
{
|
||||
if (pRow [seqX1] == 255) // Found first opaque pixel of possibly larger block
|
||||
{
|
||||
// Get max sequence of continuous opaque pixels on it's right side.
|
||||
PRInt32 seqX2 = seqX1;
|
||||
PRInt32 sx, sy;
|
||||
|
||||
for (sx = seqX1 ; sx <= maxX && pRow [sx] == 255 ; sx++)
|
||||
{
|
||||
seqX2 = sx;
|
||||
pRow [seqX2] = 1; // Mark pixel as already handled
|
||||
}
|
||||
|
||||
// Look if found pixel sequence can be combined with exactly same one on next line
|
||||
PRInt32 seqY2 = seqY1;
|
||||
PRUint8* pNextRow = pRow + mBounds.width;
|
||||
|
||||
for (sy = seqY1 + 1 ; sy <= maxY ; sy++)
|
||||
{
|
||||
// Check if line starts and ends right below the original pixel sequence
|
||||
if (pNextRow [seqX1] != 255 ||
|
||||
pNextRow [seqX2] != 255 ||
|
||||
(seqX1 > minX && pNextRow [seqX1 - 1]) ||
|
||||
(seqX2 < maxX && pNextRow [seqX2 + 1]))
|
||||
break;
|
||||
|
||||
// Check if line is continuously opaque and thus exactly same to previous sequence
|
||||
PRBool sequenceContinuous = PR_TRUE;
|
||||
|
||||
for (sx = seqX1 + 1 ; sx < seqX2 ; sx++)
|
||||
if (pNextRow [sx] != 255)
|
||||
{
|
||||
sequenceContinuous = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sequenceContinuous)
|
||||
break;
|
||||
|
||||
seqY2 = sy; // Include this sequence in block
|
||||
memset(pNextRow + seqX1, 1, seqX2 - seqX1 + 1); // and mark it as handled
|
||||
|
||||
pNextRow += mBounds.width;
|
||||
}
|
||||
|
||||
|
||||
// Continuous opaque region of maximal size found
|
||||
::SetRectRgn(hrgnRectBlock, seqX1, seqY1, seqX2 + 1, seqY2 + 1);
|
||||
::CombineRgn(hrgnOpacityMask, hrgnRectBlock, hrgnOpacityMask, RGN_OR);
|
||||
|
||||
|
||||
if (seqX1 == minX && seqX2 == maxX) // Whole row opaque
|
||||
{
|
||||
seqY1 = seqY2; // Next sequences can start only below this block
|
||||
break;
|
||||
} else
|
||||
seqX1 = seqX2; // Next sequence on same row can only be on right side of this block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::DeleteObject(hrgnRectBlock);
|
||||
}
|
||||
|
||||
HWND hWnd = GetTopLevelHWND(mWnd);
|
||||
nsWindow* topWindow = GetNSWindowPtr(hWnd);
|
||||
|
||||
topWindow->w9x.mPerformingSetWindowRgn = PR_TRUE;
|
||||
::SetWindowRgn(hWnd, hrgnOpacityMask, TRUE); // Now system owns this region
|
||||
topWindow->w9x.mPerformingSetWindowRgn = PR_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -351,9 +351,11 @@ private:
|
||||
nsresult SetWindowTranslucencyInner(PRBool aTransparent);
|
||||
PRBool GetWindowTranslucencyInner() { return mIsTranslucent; }
|
||||
void UpdateTranslucentWindowAlphaInner(const nsRect& aRect, PRUint8* aAlphas);
|
||||
nsIWidget* GetTopLevelWidget();
|
||||
nsWindow* GetTopLevelWindow();
|
||||
void ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight);
|
||||
nsresult UpdateTranslucentWindow();
|
||||
nsresult SetupTranslucentWindowMemoryBitmap(PRBool aTranslucent);
|
||||
void SetWindowRegionToAlphaMask();
|
||||
public:
|
||||
#endif
|
||||
|
||||
@ -406,8 +408,9 @@ protected:
|
||||
|
||||
static PRBool EventIsInsideWindow(UINT Msg, nsWindow* aWindow);
|
||||
|
||||
static nsWindow * GetNSWindowPtr(HWND aWnd);
|
||||
static nsWindow* GetNSWindowPtr(HWND aWnd);
|
||||
static BOOL SetNSWindowPtr(HWND aWnd, nsWindow * ptr);
|
||||
nsWindow* GetParent(PRBool aStopOnFirstTopLevel);
|
||||
|
||||
void DispatchPendingEvents();
|
||||
virtual PRBool ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *aRetValue);
|
||||
@ -517,10 +520,23 @@ protected:
|
||||
HBRUSH mBrush;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
HBITMAP mMemoryBitmap;
|
||||
HDC mMemoryDC;
|
||||
union
|
||||
{
|
||||
// Windows 2000 and newer use layered windows to support full 256 level alpha translucency
|
||||
struct
|
||||
{
|
||||
HDC mMemoryDC;
|
||||
HBITMAP mMemoryBitmap;
|
||||
} w2k;
|
||||
// Windows NT and 9x use complex shaped window regions to support 1-bit transparency masks
|
||||
struct
|
||||
{
|
||||
PRPackedBool mPerformingSetWindowRgn;
|
||||
} w9x;
|
||||
};
|
||||
PRUint8* mAlphaMask;
|
||||
PRPackedBool mIsTranslucent;
|
||||
PRPackedBool mIsTopTranslucent; // Topmost window itself or any of it's child windows has tranlucency enabled
|
||||
#endif
|
||||
PRPackedBool mIsTopWidgetWindow;
|
||||
PRPackedBool mHas3DBorder;
|
||||
|
Loading…
x
Reference in New Issue
Block a user