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 {
|
enum nsContentType {
|
||||||
eContentTypeInherit = -1,
|
eContentTypeInherit = -1,
|
||||||
eContentTypeUI = 0, // eContentTypeUI must equal 0
|
eContentTypeUI = 0, // eContentTypeUI must equal 0
|
||||||
eContentTypeContent = 1 // eContentTypeUI must equal 1
|
eContentTypeContent = 1 // eContentTypeContent must equal 1
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nsTopLevelWidgetZPlacement { // for PlaceBehind()
|
enum nsTopLevelWidgetZPlacement { // for PlaceBehind()
|
||||||
|
@ -134,6 +134,9 @@ static const char *kMozHeapDumpMessageString = "MOZ_HeapDump";
|
|||||||
#define SPI_GETWHEELSCROLLLINES 104
|
#define SPI_GETWHEELSCROLLLINES 104
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MOZ_XUL
|
||||||
|
|
||||||
#ifndef AC_SRC_ALPHA
|
#ifndef AC_SRC_ALPHA
|
||||||
#define AC_SRC_ALPHA 0x01
|
#define AC_SRC_ALPHA 0x01
|
||||||
#endif
|
#endif
|
||||||
@ -147,6 +150,27 @@ static const char *kMozHeapDumpMessageString = "MOZ_HeapDump";
|
|||||||
#endif
|
#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?
|
// Pick some random timer ID. Is there a better way?
|
||||||
#define NS_FLASH_TIMER_ID 0x011231984
|
#define NS_FLASH_TIMER_ID 0x011231984
|
||||||
|
|
||||||
@ -779,8 +803,10 @@ nsWindow::nsWindow() : nsBaseWidget()
|
|||||||
mHas3DBorder = PR_FALSE;
|
mHas3DBorder = PR_FALSE;
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
mIsTranslucent = PR_FALSE;
|
mIsTranslucent = PR_FALSE;
|
||||||
mMemoryBitmap = NULL;
|
mIsTopTranslucent = PR_FALSE;
|
||||||
mMemoryDC = NULL;
|
w2k.mMemoryBitmap = NULL;
|
||||||
|
w2k.mMemoryDC = NULL;
|
||||||
|
w9x.mPerformingSetWindowRgn = PR_FALSE;
|
||||||
mAlphaMask = nsnull;
|
mAlphaMask = nsnull;
|
||||||
#endif
|
#endif
|
||||||
mWindowType = eWindowType_child;
|
mWindowType = eWindowType_child;
|
||||||
@ -1655,12 +1681,9 @@ NS_METHOD nsWindow::Destroy()
|
|||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (mIsTranslucent)
|
if (mIsTranslucent)
|
||||||
{
|
{
|
||||||
::DeleteDC(mMemoryDC);
|
SetupTranslucentWindowMemoryBitmap(PR_FALSE);
|
||||||
::DeleteObject(mMemoryBitmap);
|
|
||||||
delete [] mAlphaMask;
|
|
||||||
|
|
||||||
mMemoryDC = NULL;
|
delete [] mAlphaMask;
|
||||||
mMemoryBitmap = NULL;
|
|
||||||
mAlphaMask = nsnull;
|
mAlphaMask = nsnull;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1701,19 +1724,23 @@ NS_IMETHODIMP nsWindow::SetParent(nsIWidget *aNewParent)
|
|||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
nsIWidget* nsWindow::GetParent(void)
|
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
|
// 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
|
// owned by the topmost widget, because a child window can be embedded inside
|
||||||
// a HWND which is not associated with a nsIWidget.
|
// a HWND which is not associated with a nsIWidget.
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
/* If this widget has already been destroyed, pretend we have no parent.
|
// If this widget has already been destroyed, pretend we have no parent.
|
||||||
This corresponds to code in Destroy which removes the destroyed
|
// This corresponds to code in Destroy which removes the destroyed
|
||||||
widget from its parent's child list. */
|
// widget from its parent's child list.
|
||||||
if (mIsDestroying || mOnDestroyCalled)
|
if (mIsDestroying || mOnDestroyCalled)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
|
|
||||||
|
|
||||||
nsWindow* widget = nsnull;
|
nsWindow* widget = nsnull;
|
||||||
if (mWnd) {
|
if (mWnd) {
|
||||||
HWND parent = ::GetParent(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 tempStyle = nsToolkit::mGetWindowLong(hwnd, GWL_STYLE);
|
||||||
DWORD tempExStyle = nsToolkit::mGetWindowLong(hwnd, GWL_EXSTYLE);
|
DWORD tempExStyle = nsToolkit::mGetWindowLong(hwnd, GWL_EXSTYLE);
|
||||||
|
|
||||||
style = WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
|
style = tempStyle & ~(WS_CAPTION | WS_THICKFRAME);
|
||||||
exStyle = tempExStyle & WS_EX_LAYERED;
|
exStyle = tempExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE |
|
||||||
|
WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||||
if (tempExStyle & WS_EX_LAYERED) style = 0;
|
|
||||||
|
|
||||||
mOldStyle = tempStyle;
|
mOldStyle = tempStyle;
|
||||||
mOldExStyle = tempExStyle;
|
mOldExStyle = tempExStyle;
|
||||||
@ -2591,8 +2617,8 @@ NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
|
|||||||
#endif // NS_DEBUG
|
#endif // NS_DEBUG
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (mIsTranslucent)
|
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||||
OnPaint(mMemoryDC);
|
OnPaint(w2k.mMemoryDC);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -2624,8 +2650,8 @@ NS_METHOD nsWindow::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
|
|||||||
#endif // NS_DEBUG
|
#endif // NS_DEBUG
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (mIsTranslucent)
|
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||||
OnPaint(mMemoryDC);
|
OnPaint(w2k.mMemoryDC);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -2651,8 +2677,8 @@ nsWindow::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
|
|||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
if (mWnd) {
|
if (mWnd) {
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (mIsTranslucent)
|
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||||
OnPaint(mMemoryDC);
|
OnPaint(w2k.mMemoryDC);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -2688,7 +2714,7 @@ NS_IMETHODIMP nsWindow::Update()
|
|||||||
if (mWnd)
|
if (mWnd)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (mIsTranslucent)
|
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||||
{
|
{
|
||||||
// rv = UpdateTranslucentWindow();
|
// rv = UpdateTranslucentWindow();
|
||||||
} else
|
} else
|
||||||
@ -2715,7 +2741,8 @@ void* nsWindow::GetNativeData(PRUint32 aDataType)
|
|||||||
case NS_NATIVE_GRAPHIC:
|
case NS_NATIVE_GRAPHIC:
|
||||||
// XXX: This is sleezy!! Remember to Release the DC after using it!
|
// XXX: This is sleezy!! Remember to Release the DC after using it!
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
return (void*)(!mIsTranslucent) ? ::GetDC(mWnd) : mMemoryDC;
|
return (void*)(mIsTranslucent && IsAlphaTranslucencySupported()) ?
|
||||||
|
w2k.mMemoryDC : ::GetDC(mWnd);
|
||||||
#else
|
#else
|
||||||
return (void*)::GetDC(mWnd);
|
return (void*)::GetDC(mWnd);
|
||||||
#endif
|
#endif
|
||||||
@ -2734,7 +2761,7 @@ void nsWindow::FreeNativeData(void * data, PRUint32 aDataType)
|
|||||||
{
|
{
|
||||||
case NS_NATIVE_GRAPHIC:
|
case NS_NATIVE_GRAPHIC:
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (!mIsTranslucent)
|
if (!(mIsTranslucent && IsAlphaTranslucencySupported()))
|
||||||
::ReleaseDC(mWnd, (HDC)data);
|
::ReleaseDC(mWnd, (HDC)data);
|
||||||
#else
|
#else
|
||||||
::ReleaseDC(mWnd, (HDC)data);
|
::ReleaseDC(mWnd, (HDC)data);
|
||||||
@ -4228,6 +4255,14 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
|
|||||||
|
|
||||||
case WM_WINDOWPOSCHANGED:
|
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;
|
WINDOWPOS *wp = (LPWINDOWPOS)lParam;
|
||||||
|
|
||||||
// We only care about a resize, so filter out things like z-order
|
// 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));
|
HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps));
|
||||||
RECT paintRect;
|
RECT paintRect;
|
||||||
|
|
||||||
|
#ifdef MOZ_XUL
|
||||||
|
if (aDC || mIsTranslucent) {
|
||||||
|
#else
|
||||||
if (aDC) {
|
if (aDC) {
|
||||||
|
#endif
|
||||||
::GetClientRect(mWnd, &paintRect);
|
::GetClientRect(mWnd, &paintRect);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -5093,7 +5133,7 @@ PRBool nsWindow::OnPaint(HDC aDC)
|
|||||||
event.renderingContext->DestroyDrawingSurface(surf);
|
event.renderingContext->DestroyDrawingSurface(surf);
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (mIsTranslucent)
|
if (mIsTranslucent && IsAlphaTranslucencySupported())
|
||||||
{
|
{
|
||||||
// Data from offscreen drawing surface was copied to memory bitmap of transparent
|
// 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
|
// 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
|
#ifdef MOZ_XUL
|
||||||
|
|
||||||
typedef BOOL WINAPI UpdateLayeredWindowProc (HWND hWnd, HDC hdcDst, POINT *pptDst,
|
nsWindow* nsWindow::GetTopLevelWindow()
|
||||||
SIZE *psize, HDC hdcSrc, POINT *pptSrc,
|
|
||||||
COLORREF crKey, BLENDFUNCTION *pblend,
|
|
||||||
DWORD dwFlags);
|
|
||||||
|
|
||||||
|
|
||||||
static UpdateLayeredWindowProc* pUpdateLayeredWindow = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static PRBool IsTranslucencySupported()
|
|
||||||
{
|
{
|
||||||
static PRBool firstTime = PR_TRUE;
|
nsWindow* curWindow = this;
|
||||||
|
NS_ADDREF(curWindow);
|
||||||
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);
|
|
||||||
|
|
||||||
while (PR_TRUE)
|
while (PR_TRUE)
|
||||||
{
|
{
|
||||||
if (mIsTopWidgetWindow)
|
nsWindow* parentWindow = curWindow->GetParent(PR_TRUE);
|
||||||
return curWidget;
|
|
||||||
|
|
||||||
nsIWidget* parentWidget = curWidget->GetParent();
|
|
||||||
|
|
||||||
if (parentWidget)
|
if (parentWindow)
|
||||||
{
|
{
|
||||||
NS_RELEASE(curWidget);
|
NS_RELEASE(curWindow);
|
||||||
curWidget = parentWidget;
|
curWindow = parentWindow;
|
||||||
} else
|
} else
|
||||||
return curWidget;
|
return curWindow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7236,15 +7247,15 @@ void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight)
|
|||||||
|
|
||||||
for (PRInt32 cy = 0 ; cy < copyHeight ; cy++)
|
for (PRInt32 cy = 0 ; cy < copyHeight ; cy++)
|
||||||
{
|
{
|
||||||
memcpy (pDest, pSrc, copyWidth);
|
memcpy(pDest, pSrc, copyWidth);
|
||||||
memset (pDest + copyWidth, 255, growWidth);
|
memset(pDest + copyWidth, 255, growWidth);
|
||||||
pSrc += mBounds.width;
|
pSrc += mBounds.width;
|
||||||
pDest += aNewWidth;
|
pDest += aNewWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PRInt32 gy = 0 ; gy < growHeight ; gy++)
|
for (PRInt32 gy = 0 ; gy < growHeight ; gy++)
|
||||||
{
|
{
|
||||||
memset (pDest, 255, aNewWidth);
|
memset(pDest, 255, aNewWidth);
|
||||||
pDest += aNewWidth;
|
pDest += aNewWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7255,38 +7266,34 @@ void nsWindow::ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight)
|
|||||||
mAlphaMask = pBits;
|
mAlphaMask = pBits;
|
||||||
|
|
||||||
|
|
||||||
// resize the memory bitmap
|
if (IsAlphaTranslucencySupported())
|
||||||
HDC hScreenDC = ::GetDC(NULL);
|
|
||||||
mMemoryBitmap = ::CreateCompatibleBitmap(hScreenDC, aNewWidth, aNewHeight);
|
|
||||||
|
|
||||||
if (mMemoryBitmap)
|
|
||||||
{
|
{
|
||||||
HGDIOBJ oldBitmap = ::SelectObject(mMemoryDC, mMemoryBitmap);
|
// resize the memory bitmap
|
||||||
::DeleteObject(oldBitmap);
|
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)
|
NS_IMETHODIMP nsWindow::GetWindowTranslucency(PRBool& aTranslucent)
|
||||||
{
|
{
|
||||||
if (IsTranslucencySupported())
|
nsWindow* topWindow = GetTopLevelWindow();
|
||||||
{
|
aTranslucent = topWindow->GetWindowTranslucencyInner();
|
||||||
nsWindow* topWindow = (nsWindow*)GetTopLevelWidget();
|
NS_RELEASE(topWindow);
|
||||||
aTranslucent = topWindow->GetWindowTranslucencyInner();
|
|
||||||
NS_RELEASE(topWindow);
|
|
||||||
} else
|
|
||||||
aTranslucent = PR_FALSE;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsWindow::SetWindowTranslucency(PRBool aTranslucent)
|
NS_IMETHODIMP nsWindow::SetWindowTranslucency(PRBool aTranslucent)
|
||||||
{
|
{
|
||||||
if (!IsTranslucencySupported())
|
nsWindow* topWindow = GetTopLevelWindow();
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
nsWindow* topWindow = (nsWindow*)GetTopLevelWidget();
|
|
||||||
nsresult rv = topWindow->SetWindowTranslucencyInner(aTranslucent);
|
nsresult rv = topWindow->SetWindowTranslucencyInner(aTranslucent);
|
||||||
NS_RELEASE(topWindow);
|
NS_RELEASE(topWindow);
|
||||||
|
|
||||||
@ -7295,10 +7302,7 @@ NS_IMETHODIMP nsWindow::SetWindowTranslucency(PRBool aTranslucent)
|
|||||||
|
|
||||||
NS_IMETHODIMP nsWindow::UpdateTranslucentWindowAlpha(const nsRect& aRect, PRUint8* aAlphas)
|
NS_IMETHODIMP nsWindow::UpdateTranslucentWindowAlpha(const nsRect& aRect, PRUint8* aAlphas)
|
||||||
{
|
{
|
||||||
if (!IsTranslucencySupported())
|
nsWindow* topWindow = GetTopLevelWindow();
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
nsWindow* topWindow = (nsWindow*)GetTopLevelWidget();
|
|
||||||
topWindow->UpdateTranslucentWindowAlphaInner(aRect, aAlphas);
|
topWindow->UpdateTranslucentWindowAlphaInner(aRect, aAlphas);
|
||||||
NS_RELEASE(topWindow);
|
NS_RELEASE(topWindow);
|
||||||
|
|
||||||
@ -7311,8 +7315,9 @@ nsresult nsWindow::SetWindowTranslucencyInner(PRBool aTranslucent)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
HWND hWnd = GetTopLevelHWND(mWnd);
|
HWND hWnd = GetTopLevelHWND(mWnd);
|
||||||
|
nsWindow* topWindow = GetNSWindowPtr(hWnd);
|
||||||
|
|
||||||
if (!GetNSWindowPtr(hWnd))
|
if (!topWindow)
|
||||||
{
|
{
|
||||||
NS_WARNING("Trying to use transparent chrome in an embedded context");
|
NS_WARNING("Trying to use transparent chrome in an embedded context");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
@ -7326,7 +7331,9 @@ nsresult nsWindow::SetWindowTranslucencyInner(PRBool aTranslucent)
|
|||||||
~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
~(WS_CAPTION | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
||||||
exStyle = nsToolkit::mGetWindowLong(hWnd, GWL_EXSTYLE) &
|
exStyle = nsToolkit::mGetWindowLong(hWnd, GWL_EXSTYLE) &
|
||||||
~(WS_EX_DLGMODALFRAME | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
~(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
|
} else
|
||||||
{
|
{
|
||||||
style = WindowStyle();
|
style = WindowStyle();
|
||||||
@ -7335,48 +7342,65 @@ nsresult nsWindow::SetWindowTranslucencyInner(PRBool aTranslucent)
|
|||||||
nsToolkit::mSetWindowLong(hWnd, GWL_STYLE, style);
|
nsToolkit::mSetWindowLong(hWnd, GWL_STYLE, style);
|
||||||
nsToolkit::mSetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
|
nsToolkit::mSetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
|
||||||
|
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
|
||||||
mIsTranslucent = aTranslucent;
|
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)
|
if (aTranslucent)
|
||||||
{
|
{
|
||||||
HDC hScreenDC = ::GetDC(NULL);
|
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;
|
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);
|
::ReleaseDC(NULL, hScreenDC);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
::DeleteDC(mMemoryDC);
|
::DeleteDC(w2k.mMemoryDC);
|
||||||
::DeleteObject(mMemoryBitmap);
|
::DeleteObject(w2k.mMemoryBitmap);
|
||||||
delete [] mAlphaMask;
|
|
||||||
|
|
||||||
mMemoryDC = NULL;
|
w2k.mMemoryDC = NULL;
|
||||||
mMemoryBitmap = NULL;
|
w2k.mMemoryBitmap = NULL;
|
||||||
mAlphaMask = nsnull;
|
|
||||||
|
|
||||||
rv = NS_OK;
|
rv = NS_OK;
|
||||||
}
|
}
|
||||||
@ -7391,22 +7415,55 @@ void nsWindow::UpdateTranslucentWindowAlphaInner(const nsRect& aRect, PRUint8* a
|
|||||||
aRect.XMost() <= mBounds.width && aRect.YMost() <= mBounds.height,
|
aRect.XMost() <= mBounds.width && aRect.YMost() <= mBounds.height,
|
||||||
"Rect is out of window bounds");
|
"Rect is out of window bounds");
|
||||||
|
|
||||||
|
PRBool transparencyMaskChanged = PR_FALSE;
|
||||||
|
|
||||||
if (!aRect.IsEmpty())
|
if (!aRect.IsEmpty())
|
||||||
{
|
{
|
||||||
PRUint8* pSrc = aAlphas;
|
PRBool skipMaskChangeCheck = IsAlphaTranslucencySupported();
|
||||||
PRUint8* pDest = mAlphaMask + aRect.y * mBounds.width + aRect.x;
|
PRUint8* pSrcRow = aAlphas;
|
||||||
|
PRUint8* pDestRow = mAlphaMask + aRect.y * mBounds.width + aRect.x;
|
||||||
|
|
||||||
for (PRInt32 y = 0 ; y < aRect.height ; y++)
|
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;
|
for (PRInt32 x = 0 ; x < aRect.width ; x++)
|
||||||
pDest += mBounds.width;
|
{
|
||||||
|
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
|
if (IsAlphaTranslucencySupported())
|
||||||
// bits from offscreen drawing surface are copied back to memory bitmap.
|
{
|
||||||
|
// 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()
|
nsresult nsWindow::UpdateTranslucentWindow()
|
||||||
@ -7439,7 +7496,7 @@ nsresult nsWindow::UpdateTranslucentWindow()
|
|||||||
|
|
||||||
if (pBits)
|
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)
|
if (lines == mBounds.height)
|
||||||
{
|
{
|
||||||
@ -7458,7 +7515,7 @@ nsresult nsWindow::UpdateTranslucentWindow()
|
|||||||
pAlpha++;
|
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;
|
delete [] pBits;
|
||||||
@ -7490,4 +7547,121 @@ nsresult nsWindow::UpdateTranslucentWindow()
|
|||||||
return rv;
|
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
|
#endif
|
||||||
|
@ -351,9 +351,11 @@ private:
|
|||||||
nsresult SetWindowTranslucencyInner(PRBool aTransparent);
|
nsresult SetWindowTranslucencyInner(PRBool aTransparent);
|
||||||
PRBool GetWindowTranslucencyInner() { return mIsTranslucent; }
|
PRBool GetWindowTranslucencyInner() { return mIsTranslucent; }
|
||||||
void UpdateTranslucentWindowAlphaInner(const nsRect& aRect, PRUint8* aAlphas);
|
void UpdateTranslucentWindowAlphaInner(const nsRect& aRect, PRUint8* aAlphas);
|
||||||
nsIWidget* GetTopLevelWidget();
|
nsWindow* GetTopLevelWindow();
|
||||||
void ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight);
|
void ResizeTranslucentWindow(PRInt32 aNewWidth, PRInt32 aNewHeight);
|
||||||
nsresult UpdateTranslucentWindow();
|
nsresult UpdateTranslucentWindow();
|
||||||
|
nsresult SetupTranslucentWindowMemoryBitmap(PRBool aTranslucent);
|
||||||
|
void SetWindowRegionToAlphaMask();
|
||||||
public:
|
public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -406,8 +408,9 @@ protected:
|
|||||||
|
|
||||||
static PRBool EventIsInsideWindow(UINT Msg, nsWindow* aWindow);
|
static PRBool EventIsInsideWindow(UINT Msg, nsWindow* aWindow);
|
||||||
|
|
||||||
static nsWindow * GetNSWindowPtr(HWND aWnd);
|
static nsWindow* GetNSWindowPtr(HWND aWnd);
|
||||||
static BOOL SetNSWindowPtr(HWND aWnd, nsWindow * ptr);
|
static BOOL SetNSWindowPtr(HWND aWnd, nsWindow * ptr);
|
||||||
|
nsWindow* GetParent(PRBool aStopOnFirstTopLevel);
|
||||||
|
|
||||||
void DispatchPendingEvents();
|
void DispatchPendingEvents();
|
||||||
virtual PRBool ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *aRetValue);
|
virtual PRBool ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *aRetValue);
|
||||||
@ -517,10 +520,23 @@ protected:
|
|||||||
HBRUSH mBrush;
|
HBRUSH mBrush;
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
HBITMAP mMemoryBitmap;
|
union
|
||||||
HDC mMemoryDC;
|
{
|
||||||
|
// 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;
|
PRUint8* mAlphaMask;
|
||||||
PRPackedBool mIsTranslucent;
|
PRPackedBool mIsTranslucent;
|
||||||
|
PRPackedBool mIsTopTranslucent; // Topmost window itself or any of it's child windows has tranlucency enabled
|
||||||
#endif
|
#endif
|
||||||
PRPackedBool mIsTopWidgetWindow;
|
PRPackedBool mIsTopWidgetWindow;
|
||||||
PRPackedBool mHas3DBorder;
|
PRPackedBool mHas3DBorder;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user