diff --git a/mozilla/gfx/src/xlib/Makefile.in b/mozilla/gfx/src/xlib/Makefile.in index 27ed26ad1c7..6d24cb160e7 100644 --- a/mozilla/gfx/src/xlib/Makefile.in +++ b/mozilla/gfx/src/xlib/Makefile.in @@ -45,8 +45,17 @@ CPPSRCS = \ nsScreenXlib.cpp \ nsScreenManagerXlib.cpp \ nsPrintOptionsXlib.cpp \ + nsGCCache.cpp \ $(NULL) +ifdef HAVE_XIE +CSRCS += XIE.c +endif + +CSRCS += scale.c + +EXPORTS = nsGCCache.h + include $(topsrcdir)/config/rules.mk ifndef MOZ_MONOLITHIC_TOOLKIT @@ -57,10 +66,16 @@ EXTRA_DSO_LDOPTS += $(TK_LIBS) CXXFLAGS += $(TK_CFLAGS) endif +ifdef HAVE_XIE +DEFINES += -DHAVE_XIE +GFX_XIE_LIBS += $(MOZ_XIE_LIBS) +endif + EXTRA_DSO_LDOPTS += \ $(NSPR_LIBS) \ -lxpcom \ -lgkgfx \ + $(GFX_XIE_LIBS) \ $(NULL) DEFINES += -D_IMPL_NS_GFXNONXP diff --git a/mozilla/gfx/src/xlib/nsDeviceContextXlib.cpp b/mozilla/gfx/src/xlib/nsDeviceContextXlib.cpp index 841655323bb..44a8eedc305 100644 --- a/mozilla/gfx/src/xlib/nsDeviceContextXlib.cpp +++ b/mozilla/gfx/src/xlib/nsDeviceContextXlib.cpp @@ -36,6 +36,7 @@ #include "nsFontMetricsXlib.h" #include "xlibrgb.h" +#include "X11/Xatom.h" #include "nsDeviceContextSpecXlib.h" @@ -49,8 +50,14 @@ static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); static NS_DEFINE_IID(kDeviceContextIID, NS_IDEVICE_CONTEXT_IID); +#define XLIB_DEFAULT_FONT1 "-*-helvetica-medium-r-*-*-*-140-*-*-*-*-iso8859-1" +#define XLIB_DEFAULT_FONT2 "-*-fixed-medium-r-*-*-*-120-*-*-*-*-*-*" + static PRLogModuleInfo *DeviceContextXlibLM = PR_NewLogModule("DeviceContextXlib"); +/* global default font handle */ +static XFontStruct *mDefaultFont = nsnull; + nsDeviceContextXlib::nsDeviceContextXlib() : DeviceContextImpl() { @@ -93,6 +100,11 @@ NS_IMETHODIMP nsDeviceContextXlib::Init(nsNativeWidget aNativeWidget) mVisual = xlib_rgb_get_visual(); mDepth = xlib_rgb_get_depth(); + if (!mDefaultFont) + mDefaultFont = XLoadQueryFont(mDisplay, XLIB_DEFAULT_FONT1); + + if (!mDefaultFont) + mDefaultFont = XLoadQueryFont(mDisplay, XLIB_DEFAULT_FONT2); #ifdef DEBUG static PRBool once = PR_TRUE; @@ -171,12 +183,7 @@ NS_IMETHODIMP nsDeviceContextXlib::CreateRenderingContext(nsIRenderingContext *& NS_ADDREF(context); surface = new nsDrawingSurfaceXlib(); if (nsnull != surface) { - - GC gc = XCreateGC(mDisplay, - (Drawable) mWidget, - 0, - NULL); - + xGC *gc = new xGC(mDisplay,(Drawable) mWidget, 0, NULL); rv = surface->Init(mDisplay, mScreen, mVisual, @@ -292,15 +299,65 @@ NS_IMETHODIMP nsDeviceContextXlib::GetSystemAttribute(nsSystemAttrID anID, Syste //--------- // Fonts //--------- - case eSystemAttr_Font_Caption: + case eSystemAttr_Font_Caption: // css2 case eSystemAttr_Font_Icon: case eSystemAttr_Font_Menu: case eSystemAttr_Font_MessageBox: case eSystemAttr_Font_SmallCaption: case eSystemAttr_Font_StatusBar: - case eSystemAttr_Font_Tooltips: + case eSystemAttr_Font_Window: // css3 + case eSystemAttr_Font_Document: + case eSystemAttr_Font_Workspace: + case eSystemAttr_Font_Desktop: + case eSystemAttr_Font_Info: + case eSystemAttr_Font_Dialog: + case eSystemAttr_Font_Button: + case eSystemAttr_Font_PullDownMenu: + case eSystemAttr_Font_List: + case eSystemAttr_Font_Field: + case eSystemAttr_Font_Tooltips: // moz case eSystemAttr_Font_Widget: - status = NS_ERROR_FAILURE; + aInfo->mFont->style = NS_FONT_STYLE_NORMAL; + aInfo->mFont->weight = NS_FONT_WEIGHT_NORMAL; + aInfo->mFont->decorations = NS_FONT_DECORATION_NONE; + + + if (!mDefaultFont) + return NS_ERROR_FAILURE; + else + { + char *fontName = (char *)NULL; + unsigned long pr = 0; + + ::XGetFontProperty(mDefaultFont, XA_FULL_NAME, &pr); + if(pr) + { + fontName = XGetAtomName(mDisplay, pr); + aInfo->mFont->name.AssignWithConversion(fontName); + ::XFree(fontName); + } + + pr = 0; + ::XGetFontProperty(mDefaultFont, XA_WEIGHT, &pr); + if ( pr > 10 ) + aInfo->mFont->weight = NS_FONT_WEIGHT_BOLD; + + pr = 0; + Atom pixelSizeAtom = ::XInternAtom(mDisplay, "PIXEL_SIZE", 0); + ::XGetFontProperty(mDefaultFont, pixelSizeAtom, &pr); + if( pr ) + aInfo->mFont->size = NSIntPixelsToTwips(pr, mPixelsToTwips); + + pr = 0; + ::XGetFontProperty(mDefaultFont, XA_ITALIC_ANGLE, &pr ); + if( pr ) + aInfo->mFont->style = NS_FONT_STYLE_ITALIC; + + pr = 0; + ::XGetFontProperty(mDefaultFont, XA_UNDERLINE_THICKNESS, &pr); + if( pr ) + aInfo->mFont->decorations = NS_FONT_DECORATION_UNDERLINE; + } break; } // switch diff --git a/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.cpp b/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.cpp index 5fdef11e03a..d6889bf3efe 100644 --- a/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.cpp +++ b/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.cpp @@ -23,6 +23,7 @@ #include "nsDrawingSurfaceXlib.h" #include "prlog.h" +#include "nsGCCache.h" #include "xlibrgb.h" // for xlib_rgb_get_visual_info #include // for XVisualInfo. @@ -42,7 +43,7 @@ nsDrawingSurfaceXlib::nsDrawingSurfaceXlib() mScreen = nsnull; mVisual = nsnull; mDepth = 0; - mGC = 0; + mGC = nsnull; // set up lock info mLocked = PR_FALSE; mLockX = 0; @@ -91,8 +92,10 @@ nsDrawingSurfaceXlib::~nsDrawingSurfaceXlib() } // We are freeing the GC here now [See nsWidget::CreateGC()] - if (mGC) - XFreeGC(mDisplay, mGC); + if(mGC) { + mGC->Release(); + mGC = nsnull; + } } NS_IMPL_QUERY_INTERFACE(nsDrawingSurfaceXlib, kIDrawingSurfaceIID) @@ -105,7 +108,7 @@ nsDrawingSurfaceXlib::Init(Display * aDisplay, Visual * aVisual, int aDepth, Drawable aDrawable, - GC aGC) + xGC *aGC) { PR_LOG(DrawingSurfaceXlibLM, PR_LOG_DEBUG, ("nsDrawingSurfaceXlib::Init()\n")); @@ -113,14 +116,12 @@ nsDrawingSurfaceXlib::Init(Display * aDisplay, mScreen = aScreen; mVisual = aVisual; mDepth = aDepth; - // We Ignore the GC we are given, cos it is bad. [See nsWidget::CreateGC()] -#if 0 - mGC = aGC; -#endif mDrawable = aDrawable; - // Create a new GC - mGC = XCreateGC(mDisplay, mDrawable, 0, NULL); + if (mGC) + mGC->Release(); + mGC = aGC; + mGC->AddRef(); mIsOffscreen = PR_FALSE; return NS_OK; @@ -131,7 +132,7 @@ nsDrawingSurfaceXlib::Init (Display * aDisplay, Screen * aScreen, Visual * aVisual, int aDepth, - GC aGC, + xGC * aGC, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aFlags) @@ -140,15 +141,15 @@ nsDrawingSurfaceXlib::Init (Display * aDisplay, mScreen = aScreen; mVisual = aVisual; mDepth = aDepth; - // We Ignore the GC we are given, cos it is bad. [See nsWidget::Create()] -#if 0 - mGC = aGC; -#endif - mWidth = aWidth; mHeight = aHeight; mLockFlags = aFlags; + if(mGC) + mGC->Release(); + mGC = aGC; + mGC->AddRef(); + mIsOffscreen = PR_TRUE; mDrawable = XCreatePixmap(mDisplay, @@ -156,9 +157,6 @@ nsDrawingSurfaceXlib::Init (Display * aDisplay, mWidth, mHeight, mDepth); - // Create a new GC - mGC = XCreateGC(mDisplay, mDrawable, 0, NULL); - return NS_OK; } @@ -213,7 +211,7 @@ nsDrawingSurfaceXlib::Unlock(void) // If the lock was not read only, put the bits back on the pixmap if (!(mLockFlags & NS_LOCK_SURFACE_READ_ONLY)) { - XPutImage(mDisplay, mDrawable, mGC, mImage, + XPutImage(mDisplay, mDrawable, *mGC, mImage, 0, 0, mLockX, mLockY, mLockWidth, mLockHeight); } diff --git a/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.h b/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.h index 1849b40f966..6191be56f8b 100644 --- a/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.h +++ b/mozilla/gfx/src/xlib/nsDrawingSurfaceXlib.h @@ -24,6 +24,7 @@ #define nsDrawingSurfaceXlib_h__ #include "nsIDrawingSurface.h" +#include "nsGCCache.h" #include #include #include @@ -50,31 +51,31 @@ public: Visual * aVisual, int aDepth, Drawable aDrawable, - GC aGC); + xGC * aGC); NS_IMETHOD Init (Display * aDisplay, Screen * aScreen, Visual * aVisual, int aDepth, - GC aGC, + xGC * aGC, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aFlags); - GC GetGC(void) { return mGC; } Drawable GetDrawable(void) { return (mDrawable); } Display * GetDisplay() { return mDisplay; } Screen * GetScreen() { return mScreen; } Visual * GetVisual() { return mVisual; } int GetDepth() { return mDepth; } int GetScreenNumber() { return XScreenNumberOfScreen(mScreen); } + xGC * GetGC() { mGC->AddRef(); return mGC; } private: Display * mDisplay; Screen * mScreen; Visual * mVisual; int mDepth; - GC mGC; + xGC * mGC; Drawable mDrawable; XImage * mImage; nsPixelFormat mPixFormat; diff --git a/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp b/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp index 5f3f75cabc2..20fd737a532 100644 --- a/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp +++ b/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp @@ -49,7 +49,7 @@ #undef USER_DEFINED #define USER_DEFINED "x-user-def" -#define NOISY_FONTS 1 +// #define NOISY_FONTS 1 // these are in the widget set @@ -1477,6 +1477,7 @@ SetUpFontCharSetInfo(nsFontCharSetInfo* aSelf) } } } +#ifdef NOISY_FONTS else fprintf(stderr, "=== nsICharRepresentable %s failed\n", aSelf->mCharSet); } @@ -1485,6 +1486,10 @@ SetUpFontCharSetInfo(nsFontCharSetInfo* aSelf) } else fprintf(stderr, "=== GetCharsetAtom2 %s failed\n", aSelf->mCharSet); +#else + } + } +#endif } #undef DEBUG_DUMP_TREE @@ -1723,7 +1728,7 @@ nsFontXlibNormal::GetWidth(const PRUnichar* aString, PRUint32 aLength) if ((mFont->min_byte1 == 0) && (mFont->max_byte1 == 0)) return XTextWidth(mFont, (char*) buf, len); else - return XTextWidth16(mFont, buf, len); + return XTextWidth16(mFont, buf, len / 2); } int @@ -1743,23 +1748,39 @@ nsFontXlibNormal::DrawString(nsRenderingContextXlib* aContext, int len = mCharSetInfo->Convert(mCharSetInfo, mFont, aString, aLength, (char*) buf, sizeof(buf)); + xGC *gc = aContext->GetGC(); if ((mFont->min_byte1 == 0) && (mFont->max_byte1 == 0)) { XDrawString(aSurface->GetDisplay(), aSurface->GetDrawable(), - aSurface->GetGC(), + *gc, aX, aY + mBaselineAdjust, (char *)buf, len); + gc->Release(); return XTextWidth(mFont, (char*) buf, len); } else { + /* XXX is this the right way to do it? Can I get GCCache to give me a + * new GC? */ + GC copyGC; + XGCValues values; + memset(&values, 0, sizeof(XGCValues)); + + XGetGCValues(aSurface->GetDisplay(), *gc, + GCForeground | GCBackground, &values); + values.font = mFont->fid; + copyGC = XCreateGC(aSurface->GetDisplay(), aSurface->GetDrawable(), + GCForeground | GCBackground | GCFont, &values); + + /* note the length must be divided by 2 for X*16 functions */ XDrawString16(aSurface->GetDisplay(), aSurface->GetDrawable(), - aSurface->GetGC(), - aX, aY + mBaselineAdjust, buf, len); - - return XTextWidth16(mFont, buf, len); + copyGC, + aX, aY + mBaselineAdjust, buf, len / 2); + XFreeGC(aSurface->GetDisplay(), copyGC); + gc->Release(); + return XTextWidth16(mFont, buf, len / 2); } } @@ -2016,11 +2037,13 @@ nsFontXlibUserDefined::DrawString(nsRenderingContextXlib* aContext, char buf[1024]; PRUint32 len = Convert(aString, aLength, buf, sizeof(buf)); + xGC *gc = aContext->GetGC(); XDrawString(aSurface->GetDisplay(), aSurface->GetDrawable(), - aSurface->GetGC(), + *gc, aX, aY + mBaselineAdjust, (char *)buf, len); + gc->Release(); return XTextWidth(mFont, buf, len); } @@ -2104,7 +2127,7 @@ nsFontMetricsXlib::PickASizeAndLoad(nsFontStretch* aStretch, { PRInt32 i; PRInt32 n = aStretch->mScaledFonts.Count(); - nsFontXlib* p; + nsFontXlib* p = nsnull; for (i=0; i < n; i++) { @@ -3061,7 +3084,7 @@ nsFontMetricsXlib::FindLocalFont(PRUnichar aChar) if (mFontIsGeneric[mFontsIndex]) return nsnull; - nsCString* familyName = mFonts.CStringAt(mFontsIndex++); + nsCString* familyName = mFonts.CStringAt(mFontsIndex); /* * Count Hyphens @@ -3102,6 +3125,7 @@ nsFontMetricsXlib::FindLocalFont(PRUnichar aChar) if (font && font->SupportsChar(aChar)) return font; } + mFontsIndex++; } return nsnull; diff --git a/mozilla/gfx/src/xlib/nsGfxFactoryXlib.cpp b/mozilla/gfx/src/xlib/nsGfxFactoryXlib.cpp index 9bd7d759016..ec3fbe30159 100644 --- a/mozilla/gfx/src/xlib/nsGfxFactoryXlib.cpp +++ b/mozilla/gfx/src/xlib/nsGfxFactoryXlib.cpp @@ -64,7 +64,7 @@ static nsresult nsScriptableRegionConstructor(nsISupports *aOuter, REFNSIID aIID { nsresult rv; - nsIScriptableRegion *inst; + nsIScriptableRegion *inst = nsnull; if ( NULL == aResult ) { @@ -190,5 +190,10 @@ static nsModuleComponentInfo components[] = nsScreenManagerXlibConstructor } }; -NS_IMPL_NSGETMODULE(nsGfxXlibModule, components) +PR_STATIC_CALLBACK(void) +nsGfxXlibModuleDtor(nsIModule *self) +{ + nsRenderingContextXlib::Shutdown(); +} +NS_IMPL_NSGETMODULE_WITH_DTOR("nsGfxXlibModule", components, nsGfxXlibModuleDtor) diff --git a/mozilla/gfx/src/xlib/nsImageXlib.cpp b/mozilla/gfx/src/xlib/nsImageXlib.cpp index 2a573e84c37..336daeadb1d 100644 --- a/mozilla/gfx/src/xlib/nsImageXlib.cpp +++ b/mozilla/gfx/src/xlib/nsImageXlib.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:ts=2:sw=2:et * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -23,13 +24,25 @@ #include "nsImageXlib.h" #include "nsDrawingSurfaceXlib.h" +#include "nsDeviceContextXlib.h" +#include "nsRenderingContextXlib.h" #include "xlibrgb.h" #include "prlog.h" +#include "drawers.h" #define IsFlagSet(a,b) ((a) & (b)) static PRLogModuleInfo *ImageXlibLM = PR_NewLogModule("ImageXlib"); +/* XXX we are simply creating a GC and setting its function to Copy. + we shouldn't be doing this every time this method is called. this creates + way more trips to the server than we should be doing so we are creating a + static one. +*/ +static GC s1bitGC = 0; +static GC sXbitGC = 0; + + nsImageXlib::nsImageXlib() { PR_LOG(ImageXlibLM, PR_LOG_DEBUG, ("nsImageXlib::nsImageXlib()\n")); @@ -48,10 +61,9 @@ nsImageXlib::nsImageXlib() mAlphaRowBytes = 0; mAlphaWidth = 0; mAlphaHeight = 0; - mLocation.x = 0; - mLocation.y = 0; + mAlphaValid = PR_FALSE; mDisplay = nsnull; - mConvertedBits = nsnull; + mGC = nsnull; mNaturalWidth = 0; mNaturalHeight = 0; @@ -94,17 +106,38 @@ nsImageXlib::~nsImageXlib() XFreePixmap(mDisplay, mImagePixmap); } + + if(mGC) + { + XFreeGC(mDisplay, mGC); + mGC=nsnull; + } + if(sXbitGC && mDisplay) // Sometimes mDisplay is null, let orhers free + { + XFreeGC(mDisplay, sXbitGC); + sXbitGC=nsnull; + } + if(s1bitGC && mDisplay) // Sometimes mDisplay is null, let orhers free + { + XFreeGC(mDisplay, s1bitGC); + s1bitGC=nsnull; + } + } -NS_IMPL_ISUPPORTS1(nsImageXlib, nsIImage) +NS_IMPL_ISUPPORTS1(nsImageXlib, nsIImage); nsresult nsImageXlib::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements) { + if ((aWidth == 0) || (aHeight == 0)) + return NS_ERROR_FAILURE; + if (nsnull != mImageBits) { delete[] mImageBits; mImageBits = nsnull; } + if (nsnull != mAlphaBits) { delete[] mAlphaBits; mAlphaBits = nsnull;; @@ -123,8 +156,7 @@ nsresult nsImageXlib::Init(PRInt32 aWidth, PRInt32 aHeight, mImagePixmap = nsnull; } - if (24 == aDepth) - { + if (24 == aDepth) { mNumBytesPixel = 3; } else { NS_ASSERTION(PR_FALSE, "unexpected image depth"); @@ -141,8 +173,7 @@ nsresult nsImageXlib::Init(PRInt32 aWidth, PRInt32 aHeight, mImageBits = (PRUint8*)new PRUint8[mSizeImage]; - switch(aMaskRequirements) - { + switch(aMaskRequirements) { case nsMaskRequirements_kNoMask: mAlphaBits = nsnull; mAlphaWidth = 0; @@ -257,17 +288,137 @@ void nsImageXlib::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect) { - if (nsImageUpdateFlags_kBitsChanged & aFlags) { - if (mAlphaPixmap != nsnull) { - XFreePixmap(mDisplay, mAlphaPixmap); - mAlphaPixmap = nsnull; + /* this does not do what I think it should do, so comment out for now */ + + // check if the image has an all-opaque 8-bit alpha mask + if ((mAlphaDepth==8) && !mAlphaValid) { + unsigned bottom, left, right; + bottom = aUpdateRect->y + aUpdateRect->height; + left = aUpdateRect->x; + right = left + aUpdateRect->width; + for (unsigned y=aUpdateRect->y; (yx, aUpdateRect->y, + aUpdateRect->width, aUpdateRect->height, + XLIB_RGB_DITHER_MAX, + mImageBits + mRowBytes * aUpdateRect->y + 3 * aUpdateRect->x, + mRowBytes, + aUpdateRect->x, aUpdateRect->y); + } + mFlags = aFlags; // this should be 0'd out by Draw() +} + +NS_IMETHODIMP +nsImageXlib::DrawScaled(nsIRenderingContext &aContext, + nsDrawingSurface aSurface, + PRInt32 aSX, PRInt32 aSY, + PRInt32 aSWidth, PRInt32 aSHeight, + PRInt32 aDX, PRInt32 aDY, + PRInt32 aDWidth, PRInt32 aDHeight) +{ + + PRInt32 origSHeight = aSHeight, origDHeight = aDHeight; + PRInt32 origSWidth = aSWidth, origDWidth = aDWidth; + + if (aSWidth < 0 || aDWidth < 0 || aSHeight < 0 || aDHeight < 0) + return NS_ERROR_FAILURE; + + if (0 == aSWidth || 0 == aDWidth || 0 == aSHeight || 0 == aDHeight) + return NS_OK; + + // limit the size of the blit to the amount of the image read in + if (aSX + aSWidth > mDecodedX2) { + aDWidth -= ((aSX + aSWidth - mDecodedX2)*origDWidth)/origSWidth; + aSWidth -= (aSX + aSWidth) - mDecodedX2; + } + if (aSX < mDecodedX1) { + aDX += ((mDecodedX1 - aSX)*origDWidth)/origSWidth; + aSX = mDecodedX1; + } + + if (aSY + aSHeight > mDecodedY2) { + aDHeight -= ((aSY + aSHeight - mDecodedY2)*origDHeight)/origSHeight; + aSHeight -= (aSY + aSHeight) - mDecodedY2; + } + if (aSY < mDecodedY1) { + aDY += ((mDecodedY1 - aSY)*origDHeight)/origSHeight; + aSY = mDecodedY1; + } + + if ((aDWidth <= 0 || aDHeight <= 0) || (aSWidth <= 0 || aSHeight <= 0)) + return NS_OK; + + nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; + xGC *gc = ((nsRenderingContextXlib&)aContext).GetGC(); + + if (mAlphaDepth == 1) + CreateAlphaBitmap(mWidth, mHeight); + + if ((mAlphaDepth == 8) && mAlphaValid) { + NS_WARNING("can't do 8bit alpha stretched images currently\n"); + /* TODO: stretch alpha, stretch source, composite */ + /* DrawComposited(aContext, aSurface, aSX, aSY, aDX, aDY, aSWidth, aSHeight); */ + gc->Release(); + return NS_OK; + } + + PRBool succeeded = PR_FALSE; + +#ifdef HAVE_XIE + /* Draw with XIE */ + succeeded = DrawScaledImageXIE(mDisplay, drawing->GetDrawable(), + *gc, + mImagePixmap, + mAlphaPixmap, + mWidth, mHeight, + aSX, aSY, + aSWidth, aSHeight, + aDX, aDY, + aDWidth, aDHeight); +#endif + + if (!succeeded) { + /* the last resort */ + succeeded = DrawScaledImageNN(mDisplay, + drawing->GetDrawable(), + *gc, + mImagePixmap, + mAlphaPixmap, + mWidth, mHeight, + aSX, aSY, + aSWidth, aSHeight, + aDX, aDY, + aDWidth, aDHeight); + } + + gc->Release(); + + mFlags = 0; + return NS_OK; } // Draw the bitmap, this method has a source and destination coordinates @@ -279,18 +430,86 @@ nsImageXlib::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, if (aSurface == nsnull) return NS_ERROR_FAILURE; - nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; + if (aSWidth != aDWidth || aSHeight != aDHeight) { + return DrawScaled(aContext, aSurface, aSX, aSY, aSWidth, aSHeight, + aDX, aDY, aDWidth, aDHeight); + } + if (aSWidth <= 0 || aDWidth <= 0 || aSHeight <= 0 || aDHeight <= 0) { + NS_ASSERTION(aSWidth > 0 && aDWidth > 0 && aSHeight > 0 && aDHeight > 0, + "You can't draw an image with a 0 width or height!"); + return NS_OK; + } + + // limit the size of the blit to the amount of the image read in + PRInt32 j = aSX + aSWidth; + PRInt32 z; + if (j > mDecodedX2) { + z = j - mDecodedX2; + aDWidth -= z; + aSWidth -= z; + } + if (aSX < mDecodedX1) { + aDX += mDecodedX1 - aSX; + aSX = mDecodedX1; + } + + j = aSY + aSHeight; + if (j > mDecodedY2) { + z = j - mDecodedY2; + aDHeight -= z; + aSHeight -= z; + } + if (aSY < mDecodedY1) { + aDY += mDecodedY1 - aSY; + aSY = mDecodedY1; + } + + if (aDWidth <= 0 || aDHeight <= 0 || aSWidth <= 0 || aSHeight <= 0) + return NS_OK; + + if ((mAlphaDepth == 8) && mAlphaValid) { + DrawComposited(aContext, aSurface, aSX, aSY, aDX, aDY, aSWidth, aSHeight); + return NS_OK; + } + + nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; if (mDisplay == nsnull) mDisplay = drawing->GetDisplay(); - xlib_draw_rgb_image(drawing->GetDrawable(), - drawing->GetGC(), - aDX, aDY, aDWidth, aDHeight, - XLIB_RGB_DITHER_MAX, - mImageBits + mRowBytes * aSY + 3 * aDX, - mRowBytes); + if (mAlphaDepth == 1) + CreateAlphaBitmap(mWidth, mHeight); + + GC copyGC; + xGC *gc = ((nsRenderingContextXlib&)aContext).GetGC(); + + if (mAlphaPixmap) { + if (mGC) { /* reuse GC */ + copyGC = mGC; + SetupGCForAlpha(copyGC, aDX - aSX, aDY - aSY); + } else { /* make a new one */ + /* this repeats things done in SetupGCForAlpha */ + XGCValues xvalues; + memset(&xvalues, 0, sizeof(XGCValues)); + unsigned long xvalues_mask = 0; + xvalues.clip_x_origin = aDX - aSX; + xvalues.clip_y_origin = aDY - aSY; + if (IsFlagSet(nsImageUpdateFlags_kBitsChanged, mFlags)) { + xvalues_mask = GCClipXOrigin | GCClipYOrigin | GCClipMask; + xvalues.clip_mask = mAlphaPixmap; + } + mGC = XCreateGC(mDisplay, drawing->GetDrawable(), xvalues_mask , &xvalues); + copyGC = mGC; + } + } else { /* !mAlphaPixmap */ + copyGC = *gc; + } + + XCopyArea(mDisplay, mImagePixmap, drawing->GetDrawable(), + copyGC, aSX, aSY, aSWidth, aDWidth, aDX, aDY); + + gc->Release(); return NS_OK; } @@ -470,7 +689,6 @@ nsImageXlib::DrawCompositedGeneral(PRBool isLSB, PRBool flipBytes, XImage *ximage, unsigned char *readData) { Visual *visual = xlib_rgb_get_visual(); - Colormap colormap = xlib_rgb_get_cmap(); unsigned char *target = readData; @@ -533,7 +751,7 @@ nsImageXlib::DrawCompositedGeneral(PRBool isLSB, PRBool flipBytes, unsigned char *ptr = (unsigned char *)ximage->data + row*ximage->bytes_per_line; for (int col=0; colwidth; col++) { - unsigned pix; + unsigned pix = 0; switch (ximage->bits_per_pixel) { case 1: pix = (*ptr>>(col%8))&1; @@ -591,14 +809,12 @@ nsImageXlib::DrawCompositedGeneral(PRBool isLSB, PRBool flipBytes, void nsImageXlib::DrawComposited(nsIRenderingContext &aContext, nsDrawingSurface aSurface, - PRInt32 aX, PRInt32 aY, + PRInt32 aSX, PRInt32 aSY, + PRInt32 aDX, PRInt32 aDY, PRInt32 aWidth, PRInt32 aHeight) { - if ((aWidth != mWidth) || (aHeight != mHeight)) - { - aWidth = mWidth; - aHeight = mHeight; - } + if ((aWidth==0) || (aHeight==0)) + return; nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; Visual *visual = xlib_rgb_get_visual(); @@ -606,35 +822,30 @@ nsImageXlib::DrawComposited(nsIRenderingContext &aContext, Display *dpy = drawing->GetDisplay(); Drawable drawable = drawing->GetDrawable(); - // I hate clipping too :) + // I hate clipping... too! PRUint32 surfaceWidth, surfaceHeight; drawing->GetDimensions(&surfaceWidth, &surfaceHeight); int readX, readY; unsigned readWidth, readHeight, destX, destY; - readX = aX; readY = aY; - destX = 0; destY = 0; - if ((aY>=(int)surfaceHeight) || (aX>=(int)surfaceWidth) || - (aY+aHeight<=0) || (aX+aWidth<=0)) - { - // this should never happen if the layout engine is sane, - // as it means we are trying to draw an image which is outside - // the drawing surface. - + if ((aDY >= (int)surfaceHeight) || (aDX >= (int)surfaceWidth) || + (aDY + aHeight <= 0) || (aDX + aWidth <= 0)) { + // This should never happen if the layout engine is sane, + // as it means we're trying to draw an image which is outside + // the drawing surface. Bulletproof gfx for now... return; } - if (aX<0) { - readX = 0; readWidth = aWidth+aX; destX = -aX; + if (aDX < 0) { + readX = 0; readWidth = aWidth + aDX; destX = aSX - aDX; } else { - readX = aX; readWidth = aWidth; destX = 0; + readX = aDX; readWidth = aWidth; destX = aSX; } - - if (aY<0) { - readY = 0; readHeight = aHeight+aY; destY = -aY; + if (aDY < 0) { + readY = 0; readHeight = aHeight + aDY; destY = aSY - aDY; } else { - readY = aY; readHeight = aHeight; destY = 0; + readY = aDY; readHeight = aHeight; destY = aSY; } if (readX+readWidth > surfaceWidth) @@ -642,13 +853,26 @@ nsImageXlib::DrawComposited(nsIRenderingContext &aContext, if (readY+readHeight > surfaceHeight) readHeight = surfaceHeight-readY; + if ((readHeight <= 0) || (readWidth <= 0)) + return; + + // fprintf(stderr, "aX=%d aY=%d, aWidth=%u aHeight=%u\n", aX, aY, aWidth, aHeight); + // fprintf(stderr, "surfaceWidth=%u surfaceHeight=%u\n", surfaceWidth, surfaceHeight); + // fprintf(stderr, "readX=%u readY=%u readWidth=%u readHeight=%u destX=%u destY=%u\n\n", + // readX, readY, readWidth, readHeight, destX, destY); + XImage *ximage = XGetImage(dpy, drawable, readX, readY, readWidth, readHeight, AllPlanes, ZPixmap); + + NS_ASSERTION((ximage != NULL), "XGetImage() failed"); + if (!ximage) + return; + unsigned char *readData = new unsigned char[3*readWidth*readHeight]; PRBool isLSB; - unsigned test = 1; + unsigned int test = 1; isLSB = (((char *)&test)[0]) ? 1 : 0; PRBool flipBytes = @@ -668,107 +892,117 @@ nsImageXlib::DrawComposited(nsIRenderingContext &aContext, DrawComposited24(isLSB, flipBytes, destX, destY, readWidth, readHeight, ximage, readData); else if ((ximage->bits_per_pixel==16) && - (xlib_get_prec_from_mask(visual->red_mask) == 6) && - (xlib_get_prec_from_mask(visual->green_mask) == 6) && - (xlib_get_prec_from_mask(visual->blue_mask) == 6)) + ((xlib_get_prec_from_mask(visual->red_mask) == 5) || (xlib_get_prec_from_mask(visual->red_mask) == 6)) && + ((xlib_get_prec_from_mask(visual->green_mask) == 5) || (xlib_get_prec_from_mask(visual->green_mask) == 6)) && + ((xlib_get_prec_from_mask(visual->blue_mask) == 5) || (xlib_get_prec_from_mask(visual->blue_mask) == 6))) DrawComposited16(isLSB, flipBytes, destX, destY, readWidth, readHeight, ximage, readData); else DrawCompositedGeneral(isLSB, flipBytes, destX, destY, readWidth, readHeight, ximage, readData); - GC imageGC; - imageGC = XCreateGC(dpy, drawing->GetDrawable(), 0, NULL); - xlib_draw_rgb_image(drawing->GetDrawable(), - imageGC, + xGC *imageGC = ((nsRenderingContextXlib&)aContext).GetGC(); + xlib_draw_rgb_image(drawing->GetDrawable(), *imageGC, readX, readY, readWidth, readHeight, XLIB_RGB_DITHER_MAX, readData, 3*readWidth); - XFreeGC(dpy, imageGC); + XDestroyImage(ximage); + imageGC->Release(); delete[] readData; + mFlags = 0; } -void nsImageXlib::CreateAlphaBitmap(PRInt32 aWidth, PRInt32 aHeight, - nsDrawingSurface aSurface) +void nsImageXlib::CreateAlphaBitmap(PRInt32 aWidth, PRInt32 aHeight) { XImage *x_image = nsnull; - Display *dpy = nsnull; - Visual *visual = nsnull; - GC gc; XGCValues gcv; - nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; - if (mDisplay == nsnull) - mDisplay = drawing->GetDisplay(); + mDisplay = xlib_rgb_get_display(); - // Create gc clip-mask on demand - if (mAlphaBits != nsnull) - { - if (mAlphaPixmap == nsnull) - { - mAlphaPixmap = XCreatePixmap(mDisplay, - RootWindow(mDisplay, drawing->GetScreenNumber()), - aWidth, aHeight, 1); - } + /* Create gc clip-mask on demand */ + if (mAlphaBits && IsFlagSet(nsImageUpdateFlags_kBitsChanged, mFlags)) { - dpy = mDisplay; - visual = drawing->GetVisual(); + if (!mAlphaPixmap) + mAlphaPixmap = XCreatePixmap(mDisplay, DefaultRootWindow(mDisplay), + aWidth, aHeight, 1); - x_image = XCreateImage(dpy, visual, 1, XYPixmap, 0, (char *)mAlphaBits, - aWidth, aHeight, 32, mAlphaRowBytes); + // Make an image out of the alpha-bits created by the image library + x_image = XCreateImage(mDisplay, xlib_rgb_get_visual(), + 1, /* visual depth...1 for bitmaps */ + XYPixmap, + 0, /* x offset, XXX fix this */ + (char *)mAlphaBits, /* cast away our sign. */ + aWidth, + aHeight, + 32, /* bitmap pad */ + mAlphaRowBytes); /* bytes per line */ x_image->bits_per_pixel=1; - x_image->bitmap_bit_order = MSBFirst; - x_image->byte_order = MSBFirst; + /* Image library always places pixels left-to-right MSB to LSB */ + x_image->bitmap_bit_order = MSBFirst; + + /* This definition doesn't depend on client byte ordering + because the image library ensures that the bytes in + bitmask data are arranged left to right on the screen, + low to high address in memory. */ + x_image->byte_order = MSBFirst; +#if defined(IS_LITTLE_ENDIAN) + // no, it's still MSB XXX check on this!! + // x_image->byte_order = LSBFirst; +#elif defined (IS_BIG_ENDIAN) + x_image->byte_order = MSBFirst; +#else +#error ERROR! Endianness is unknown; +#endif + + /* Copy the XImage to mAlphaPixmap */ + if (!s1bitGC) { memset(&gcv, 0, sizeof(XGCValues)); gcv.function = GXcopy; - gc = XCreateGC(dpy, mAlphaPixmap, GCFunction, &gcv); - XPutImage(dpy, mAlphaPixmap, - gc, - x_image, - 0,0,0,0, - aWidth, aHeight); - XFreeGC(dpy, gc); + s1bitGC = XCreateGC(mDisplay, mAlphaPixmap, GCFunction, &gcv); + } - // done with the temp image - x_image->data = 0; //Don't free the IL_Pixmap's bits + XPutImage(mDisplay, mAlphaPixmap, s1bitGC, x_image, 0, 0, 0, 0, + aWidth, aHeight); + + /* Now we are done with the temporary image */ + x_image->data = 0; /* Don't free the IL_Pixmap's bits. */ XDestroyImage(x_image); } } -void nsImageXlib::CreateOffscreenPixmap(PRInt32 aWidth, PRInt32 aHeight, - nsDrawingSurface aDrawing) +void nsImageXlib::CreateOffscreenPixmap(PRInt32 aWidth, PRInt32 aHeight) { - if (mImagePixmap == nsnull) - { - nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aDrawing; + if (mImagePixmap == nsnull) { if (mDisplay == nsnull) - mDisplay = drawing->GetDisplay(); + mDisplay = xlib_rgb_get_display(); - mImagePixmap = XCreatePixmap(mDisplay, - RootWindow(mDisplay, drawing->GetScreenNumber()), - aWidth, - aHeight, - drawing->GetDepth()); - XSetClipOrigin(mDisplay, drawing->GetGC(), 0, 0); - XSetClipMask(mDisplay, drawing->GetGC(), None); + mImagePixmap = XCreatePixmap(mDisplay, DefaultRootWindow(mDisplay), + aWidth, aHeight, + xlib_rgb_get_depth()); } } -void nsImageXlib::DrawImageOffscreen(PRInt32 validX, PRInt32 validY, - PRInt32 validWidth, PRInt32 validHeight, - nsDrawingSurface aDrawing) +void nsImageXlib::DrawImageOffscreen(PRInt32 aSX, PRInt32 aSY, + PRInt32 aWidth, PRInt32 aHeight) { - nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aDrawing; - - xlib_draw_rgb_image(mImagePixmap, - drawing->GetGC(), - validX, validY, validWidth, validHeight, + if (IsFlagSet(nsImageUpdateFlags_kBitsChanged, mFlags)) { + printf("draw_image_off_screen: %p\n", this); + if (!sXbitGC) { + printf("no sXbit gc\n"); + XGCValues gcv; + gcv.function = GXcopy; + sXbitGC = XCreateGC(mDisplay, DefaultRootWindow(mDisplay), + GCFunction, &gcv); + } + xlib_draw_rgb_image(mImagePixmap, sXbitGC, + aSX, aSY, aWidth, aHeight, XLIB_RGB_DITHER_MAX, mImageBits, mRowBytes); } +} void nsImageXlib::SetupGCForAlpha(GC aGC, PRInt32 aX, PRInt32 aY) { @@ -779,9 +1013,13 @@ void nsImageXlib::SetupGCForAlpha(GC aGC, PRInt32 aX, PRInt32 aY) unsigned long xvalues_mask = 0; xvalues.clip_x_origin = aX; xvalues.clip_y_origin = aY; - xvalues.clip_mask = mAlphaPixmap; - xvalues_mask = GCClipXOrigin | GCClipYOrigin | GCClipMask; + xvalues_mask = GCClipXOrigin | GCClipYOrigin; + xvalues.function = GXcopy; + if (IsFlagSet(nsImageUpdateFlags_kBitsChanged, mFlags)) { + xvalues.clip_mask = mAlphaPixmap; + xvalues_mask |= GCClipMask; + } XChangeGC(mDisplay, aGC, xvalues_mask, &xvalues); } } @@ -796,14 +1034,13 @@ nsImageXlib::Draw(nsIRenderingContext &aContext, if (aSurface == nsnull) return NS_ERROR_FAILURE; - if (mAlphaDepth == 8) - { - DrawComposited(aContext, aSurface, aX, aY, aWidth, aHeight); + if ((mAlphaDepth == 8) && mAlphaValid) { + DrawComposited(aContext, aSurface, 0, 0, aX, aY, aWidth, aHeight); return NS_OK; } - if ((aWidth != mWidth) || (aHeight != mHeight)) - { + // XXX it is said that this is temporary code + if ((aWidth != mWidth) || (aHeight != mHeight)) { aWidth = mWidth; aHeight = mHeight; } @@ -834,29 +1071,40 @@ nsImageXlib::Draw(nsIRenderingContext &aContext, validX = mDecodedX1; } - CreateAlphaBitmap(validWidth, validHeight, aSurface); - - CreateOffscreenPixmap(validWidth, validHeight, aSurface); - DrawImageOffscreen(validX, validY, validWidth, validHeight, aSurface); + CreateAlphaBitmap(aWidth, aHeight); GC copyGC; - if (mAlphaPixmap) - { - copyGC = XCreateGC(mDisplay, drawing->GetDrawable(), 0, NULL); - XCopyGC(mDisplay, drawing->GetGC(), 0xffffffff, copyGC); + xGC *gc = ((nsRenderingContextXlib&)aContext).GetGC(); + + if (mAlphaPixmap) { + if (mGC) { /* reuse GC */ + copyGC = mGC; SetupGCForAlpha(copyGC, aX, aY); - } else - { - copyGC = drawing->GetGC(); + } else { /* make a new one */ + /* this repeats things done in SetupGCForAlpha */ + XGCValues xvalues; + memset(&xvalues, 0, sizeof(XGCValues)); + unsigned long xvalues_mask = 0; + xvalues.clip_x_origin = aX; + xvalues.clip_y_origin = aY; + if (IsFlagSet(nsImageUpdateFlags_kBitsChanged, mFlags)) { + xvalues_mask = GCClipXOrigin | GCClipYOrigin | GCClipMask; + xvalues.clip_mask = mAlphaPixmap; + } + mGC = XCreateGC(mDisplay, drawing->GetDrawable(), xvalues_mask , &xvalues); + copyGC = mGC; + } + } else { /* !mAlphaPixmap */ + copyGC = *gc; } XCopyArea(mDisplay, mImagePixmap, drawing->GetDrawable(), copyGC, validX, validY, validWidth, validHeight, - aX, aY); + validX + aX, validY + aY); + + gc->Release(); - if (mAlphaPixmap) - XFreeGC(mDisplay, copyGC); mFlags = 0; return NS_OK; } @@ -876,9 +1124,13 @@ void nsImageXlib::TilePixmap(Pixmap src, Pixmap dest, PRInt32 aSXOffset, valuesMask = GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle; gc = XCreateGC(mDisplay, src, valuesMask, &values); - if (useClip) - { - // FIXME: set the clipping area here + if (useClip) { + XRectangle xrectangle; + xrectangle.x = clipRect.x; + xrectangle.y = clipRect.y; + xrectangle.width = clipRect.width; + xrectangle.height = clipRect.height; + XSetClipRectangles(mDisplay, gc, 0, 0, &xrectangle, 1, Unsorted); } XFillRectangle(mDisplay, dest, gc, destRect.x, destRect.y, @@ -892,15 +1144,109 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext, nsRect &aSrcRect, nsRect &aTileRect) { + nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; + PRBool partial = PR_FALSE; + PRInt32 - aY0 = aTileRect.y, + validX = 0, + validY = 0, + validWidth = mWidth, + validHeight = mHeight; + + // limit the image rectangle to the size of the image data which + // has been validated. + if (mDecodedY2 < mHeight) { + validHeight = mDecodedY2 - mDecodedY1; + partial = PR_TRUE; + } + if (mDecodedX2 < mWidth) { + validWidth = mDecodedX2 - mDecodedX1; + partial = PR_TRUE; + } + if (mDecodedY1 > 0) { + validHeight -= mDecodedY1; + validY = mDecodedY1; + partial = PR_TRUE; + } + if (mDecodedX1 > 0) { + validWidth -= mDecodedX1; + validX = mDecodedX1; + partial = PR_TRUE; + } + + if (partial || + (drawing->GetDepth() == 8) || + ((mAlphaDepth == 8) && mAlphaValid)) { +#ifdef DEBUG_TILING + printf("Warning: using slow tiling\n"); +#endif + PRInt32 aY0 = aTileRect.y, aX0 = aTileRect.x, aY1 = aTileRect.y + aTileRect.height, aX1 = aTileRect.x + aTileRect.width; for (PRInt32 y = aY0; y < aY1; y+=aSrcRect.height) for (PRInt32 x = aX0; x < aX1; x+=aSrcRect.width) - Draw(aContext, aSurface, x, y, aSrcRect.width, aSrcRect.height); + Draw(aContext,aSurface,x,y, + PR_MIN(aSrcRect.width, aX1-x), + PR_MIN(aSrcRect.height, aY1-y)); + + return NS_OK; + } + + /* draw the tile offscreen */ + CreateOffscreenPixmap(mWidth, mHeight); + /* XXX Why? DrawImageOffscreen(0, 0, validWidth, validHeight); */ + + if (mAlphaDepth == 1) { + Pixmap tileImg; + Pixmap tileMask; + + CreateAlphaBitmap(validWidth, validHeight); + + nsRect tmpRect(0,0,aTileRect.width, aTileRect.height); + + tileImg = XCreatePixmap(mDisplay, mImagePixmap, + aTileRect.width, aTileRect.height, + mDepth); + + TilePixmap(mImagePixmap, tileImg, 0, 0, tmpRect, tmpRect, PR_FALSE); + + // tile alpha mask + tileMask = XCreatePixmap(mDisplay, mAlphaPixmap, + aTileRect.width, aTileRect.height, mAlphaDepth); + + TilePixmap(mAlphaPixmap, tileMask, 0, 0, tmpRect, tmpRect, PR_FALSE); + + GC fgc; + XGCValues values; + unsigned long valuesMask; + + memset(&values, 0, sizeof(XGCValues)); + values.clip_mask = tileMask; + values.clip_x_origin = aTileRect.x; + values.clip_y_origin = aTileRect.y; + valuesMask = GCClipXOrigin | GCClipYOrigin | GCClipMask; + fgc = XCreateGC(mDisplay, drawing->GetDrawable(), valuesMask, &values); + + // and copy it back + XCopyArea(mDisplay, tileImg, drawing->GetDrawable(), + fgc, 0,0, + aTileRect.width, aTileRect.height, + aTileRect.x, aTileRect.y); + + XFreePixmap(mDisplay, tileImg); + XFreePixmap(mDisplay, tileMask); + XFreeGC(mDisplay, fgc); + + } else { + // In the non-alpha case, ??? can tile for us + + nsRect clipRect; + PRBool isValid; + aContext.GetClipRect(clipRect, isValid); + TilePixmap(mImagePixmap, drawing->GetDrawable(), aTileRect.x, aTileRect.y, aTileRect, clipRect, PR_TRUE); + } return NS_OK; } @@ -910,10 +1256,11 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext, const nsRect &aTileRect) { nsDrawingSurfaceXlib *drawing = (nsDrawingSurfaceXlib*)aSurface; - if (mDisplay == nsnull) mDisplay = drawing->GetDisplay(); + PRBool partial = PR_FALSE; + PRInt32 validX = 0, validY = 0, @@ -921,23 +1268,26 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext, validHeight = mHeight; // limit the image rectangle to the size of the image data which - // has been validated. - if ((mDecodedY2 < mHeight)) { + if (mDecodedY2 < mHeight) { validHeight = mDecodedY2 - mDecodedY1; + partial = PR_TRUE; } - if ((mDecodedX2 < mWidth)) { + if (mDecodedX2 < mWidth) { validWidth = mDecodedX2 - mDecodedX1; + partial = PR_TRUE; } - if ((mDecodedY1 > 0)) { + if (mDecodedY1 > 0) { validHeight -= mDecodedY1; validY = mDecodedY1; + partial = PR_TRUE; } - if ((mDecodedX1 > 0)) { + if (mDecodedX1 > 0) { validWidth -= mDecodedX1; validX = mDecodedX1; + partial = PR_TRUE; } - if (mAlphaDepth == 8) { + if (partial || ((mAlphaDepth == 8) && mAlphaValid)) { PRInt32 aY0 = aTileRect.y - aSYOffset, aX0 = aTileRect.x - aSXOffset, aY1 = aTileRect.y + aTileRect.height, @@ -958,15 +1308,15 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext, return NS_OK; } - CreateOffscreenPixmap(validWidth, validHeight, aSurface); - DrawImageOffscreen(validX, validY, validWidth, validHeight, aSurface); + CreateOffscreenPixmap(mWidth, mHeight); + /* XXX Why? DrawImageOffscreen(validX, validY, validWidth, validHeight); */ if (mAlphaDepth == 1) { Pixmap tileImg; Pixmap tileMask; - CreateAlphaBitmap(validWidth, validHeight, aSurface); + CreateAlphaBitmap(validWidth, validHeight); nsRect tmpRect(0,0,aTileRect.width, aTileRect.height); @@ -1001,8 +1351,9 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext, XFreePixmap(mDisplay, tileImg); XFreePixmap(mDisplay, tileMask); XFreeGC(mDisplay, fgc); - } else - { + + } else { + nsRect clipRect; PRBool isValid; @@ -1048,6 +1399,17 @@ nsImageXlib::SetDecodedRect(PRInt32 x1, PRInt32 y1, PRInt32 x2, PRInt32 y2) mDecodedY1 = y1; mDecodedX2 = x2; mDecodedY2 = y2; + + // check if the image has an all-opaque 8-bit alpha mask + if ((mAlphaDepth==8) && !mAlphaValid) { + for (int y=mDecodedY1; ymImagePixmap) - dest->CreateOffscreenPixmap(dest->mWidth, dest->mHeight, drawing); + dest->CreateOffscreenPixmap(dest->mWidth, dest->mHeight); if (!dest->mImagePixmap || !mImagePixmap) return NS_ERROR_FAILURE; if (!mDisplay) - mDisplay = drawing->GetDisplay(); + mDisplay = xlib_rgb_get_display(); + GC gc = XCreateGC(mDisplay, dest->mImagePixmap, 0, NULL); if (mAlphaDepth == 1) - CreateAlphaBitmap(mWidth, mHeight, drawing); + CreateAlphaBitmap(mWidth, mHeight); - if (mAlphaPixmap) { + if (mAlphaPixmap) SetupGCForAlpha(gc, 0, 0); - } XCopyArea(dest->mDisplay, mImagePixmap, dest->mImagePixmap, gc, 0, 0, mWidth, mHeight, aDX, aDY); @@ -1089,9 +1445,5 @@ NS_IMETHODIMP nsImageXlib::DrawToImage(nsIImage* aDstImage, XFreeGC(mDisplay, gc); return NS_OK; -#else - NS_NOTREACHED("nsImageXlib::DrawToImage not yet implemented"); - return NS_ERROR_FAILURE; -#endif } #endif // USE_IMG2 diff --git a/mozilla/gfx/src/xlib/nsImageXlib.h b/mozilla/gfx/src/xlib/nsImageXlib.h index f07df192f53..5304116dcf1 100644 --- a/mozilla/gfx/src/xlib/nsImageXlib.h +++ b/mozilla/gfx/src/xlib/nsImageXlib.h @@ -25,11 +25,12 @@ #define nsImageXlib_h__ #include "nsIImage.h" +#include "nsGCCache.h" #include "X11/Xlib.h" #include "X11/Xutil.h" #include "X11/Xos.h" -class nsDrawingSurfaceXlib; +// class nsDrawingSurfaceXlib; class nsImageXlib : public nsIImage { public: @@ -122,6 +123,10 @@ private: void ComputePaletteSize(PRIntn nBitCount); private: + NS_IMETHODIMP DrawScaled(nsIRenderingContext &aContext, nsDrawingSurface aSurface, + PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, + PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight); + static unsigned scaled6[1<<6]; static unsigned scaled5[1<<5]; @@ -143,18 +148,16 @@ private: XImage *ximage, unsigned char *readData); inline void DrawComposited(nsIRenderingContext &aContext, nsDrawingSurface aSurface, - PRInt32 aX, PRInt32 aY, + PRInt32 aSX, PRInt32 aSY, + PRInt32 aDX, PRInt32 aDY, PRInt32 aWidth, PRInt32 aHeight); inline void TilePixmap(Pixmap src, Pixmap dest, PRInt32 aSXOffset, PRInt32 aSYOffset, const nsRect &destRect, const nsRect &clipRect, PRBool useClip); - inline void CreateAlphaBitmap(PRInt32 aWidth, PRInt32 aHeight, - nsDrawingSurface aSurface); - inline void CreateOffscreenPixmap(PRInt32 aWidth, PRInt32 aHeight, - nsDrawingSurface aSurface); - inline void DrawImageOffscreen(PRInt32 validX, PRInt32 validY, - PRInt32 validWidth, PRInt32 validHeight, - nsDrawingSurface aSurface); + inline void CreateAlphaBitmap(PRInt32 aWidth, PRInt32 aHeight); + inline void CreateOffscreenPixmap(PRInt32 aWidth, PRInt32 aHeight); + inline void DrawImageOffscreen(PRInt32 aSX, PRInt32 aSY, + PRInt32 aWidth, PRInt32 aHeight); inline void SetupGCForAlpha(GC aGC, PRInt32 aX, PRInt32 aY); PRInt32 mWidth; @@ -162,7 +165,9 @@ private: PRInt32 mDepth; // bits per pixel PRInt32 mRowBytes; PRUint8 *mImageBits; - PRUint8 *mConvertedBits; + GC mGC; + + //PRUint8 *mConvertedBits; PRInt32 mSizeImage; PRBool mIsTopToBottom; @@ -183,7 +188,7 @@ private: PRInt16 mAlphaRowBytes; // alpha bytes per row PRInt16 mAlphaWidth; // alpha layer width PRInt16 mAlphaHeight; // alpha layer height - nsPoint mLocation; // alpha mask location + PRPackedBool mAlphaValid; Pixmap mImagePixmap; Display *mDisplay; diff --git a/mozilla/gfx/src/xlib/nsRenderingContextXlib.cpp b/mozilla/gfx/src/xlib/nsRenderingContextXlib.cpp index 64c7d94e6cc..255c3285ba0 100644 --- a/mozilla/gfx/src/xlib/nsRenderingContextXlib.cpp +++ b/mozilla/gfx/src/xlib/nsRenderingContextXlib.cpp @@ -21,6 +21,7 @@ * Peter Hartshorn * Ken Faulkner * Tony Tsui + * Tomi Leppikangas */ #include "nsRenderingContextXlib.h" @@ -29,11 +30,14 @@ #include "xlibrgb.h" #include "prprf.h" #include "prmem.h" +#include "nsGCCache.h" NS_IMPL_THREADSAFE_ISUPPORTS1(nsRenderingContextXlib, nsIRenderingContext) static PRLogModuleInfo * RenderingContextXlibLM = PR_NewLogModule("RenderingContextXlib"); +static nsGCCache *gcCache = nsnull; + class GraphicsState { public: @@ -83,6 +87,9 @@ nsRenderingContextXlib::nsRenderingContextXlib() mScreen = nsnull; mVisual = nsnull; mDepth = 0; + mGC = nsnull; + + mFunction = GXcopy; PushState(); } @@ -102,11 +109,15 @@ nsRenderingContextXlib::~nsRenderingContextXlib() delete mStateCache; mStateCache = nsnull; } + if (mTranMatrix) delete mTranMatrix; NS_IF_RELEASE(mOffscreenSurface); NS_IF_RELEASE(mFontMetrics); NS_IF_RELEASE(mContext); + + if(nsnull != mGC) + mGC->Release(); } NS_IMETHODIMP @@ -126,14 +137,15 @@ nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsIWidget *aWindow) mRenderingSurface = (nsDrawingSurfaceXlib *)new nsDrawingSurfaceXlib(); if (mRenderingSurface) { + Drawable win = (Drawable)aWindow->GetNativeData(NS_NATIVE_WINDOW); - GC gc = (GC)aWindow->GetNativeData(NS_NATIVE_GRAPHIC); + xGC *gc = (xGC*)aWindow->GetNativeData(NS_NATIVE_GRAPHIC); mRenderingSurface->Init(mDisplay, mScreen, mVisual, mDepth, - win, + (PRUint32)win, gc); mOffscreenSurface = mRenderingSurface; @@ -142,6 +154,13 @@ nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsIWidget *aWindow) return (CommonInit()); } +/*static*/ nsresult +nsRenderingContextXlib::Shutdown() +{ + delete gcCache; + return NS_OK; +} + NS_IMETHODIMP nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsDrawingSurface aSurface) { @@ -330,12 +349,6 @@ nsRenderingContextXlib::PopState(PRBool &aClipState) if (mFontMetrics != state->mFontMetrics) SetFont(state->mFontMetrics); - if (mRenderingSurface && mClipRegion) { - Region region; - mClipRegion->GetNativeRegion((void *&)region); - XSetRegion(mDisplay, mRenderingSurface->GetGC(), region); - } - if (state->mColor != mCurrentColor) SetColor(state->mColor); if (state->mLineStyle != mCurrentLineStyle) @@ -351,6 +364,50 @@ nsRenderingContextXlib::PopState(PRBool &aClipState) return NS_OK; } +void nsRenderingContextXlib::UpdateGC() +{ + XGCValues values; + unsigned long valuesMask; + + if (mGC) + mGC->Release(); + + memset(&values, 0, sizeof(XGCValues)); + + unsigned long color; + + color = xlib_rgb_xpixel_from_rgb (NS_RGB(NS_GET_B(mCurrentColor), + NS_GET_G(mCurrentColor), + NS_GET_R(mCurrentColor))); + + values.foreground =color; + valuesMask = GCForeground; + + if (mCurrentFont) { + valuesMask |= GCFont; + values.font = mCurrentFont->fid; + } + + values.line_style = mLineStyle; + valuesMask |= GCLineStyle; + + values.function = mFunction; + valuesMask |= GCFunction; + + Region rgn = 0; + if (mClipRegion) { + mClipRegion->GetNativeRegion((void*&)rgn); + } + + if (!gcCache) { + gcCache = new nsGCCache(); + if (!gcCache) return; + } + + mGC = gcCache->GetGC(mDisplay, mRenderingSurface->GetDrawable(), + valuesMask, &values, + rgn); +} NS_IMETHODIMP nsRenderingContextXlib::IsVisibleRect(const nsRect& aRect, PRBool &aVisible) @@ -384,9 +441,6 @@ nsRenderingContextXlib::SetClipRect(const nsRect& aRect, nsClipCombine aCombine, } aClipState = mClipRegion->IsEmpty(); - mClipRegion->GetNativeRegion((void*&)rgn); - XSetRegion(mDisplay, mRenderingSurface->GetGC(), rgn); - return NS_OK; } @@ -428,8 +482,6 @@ nsRenderingContextXlib::SetClipRegion(const nsIRegion& aRegion, nsClipCombine aC } aClipState = mClipRegion->IsEmpty(); - mClipRegion->GetNativeRegion((void*&)rgn); - XSetRegion(mDisplay, mRenderingSurface->GetGC(),rgn); return NS_OK; } @@ -461,36 +513,28 @@ nsRenderingContextXlib::SetLineStyle(nsLineStyle aLineStyle) { PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetLineStyle()\n")); if (aLineStyle != mCurrentLineStyle) { + /* XXX this isnt done in gtk, copy from there when ready switch(aLineStyle) { case nsLineStyle_kSolid: - XSetLineAttributes(mDisplay, mRenderingSurface->GetGC(), - 1, // width - LineSolid, // line style - CapNotLast,// cap style - JoinMiter);// join style + mLineStyle = LineSolid; + mDashes = 0; break; case nsLineStyle_kDashed: - { static char dashed[2] = {4,4}; - XSetDashes(mDisplay, mRenderingSurface->GetGC(), - 0, dashed, 2); - } + mDashList = dashed; + mDashes = 2; break; - case nsLineStyle_kDotted: - { static char dotted[2] = {3,1}; - XSetDashes(mDisplay, mRenderingSurface->GetGC(), - 0, dotted, 2); - } + mDashList = dotted; + mDashes = 2; break; - default: break; } - + */ mCurrentLineStyle = aLineStyle ; } return NS_OK; @@ -512,9 +556,7 @@ nsRenderingContextXlib::SetColor(nscolor aColor) return NS_ERROR_FAILURE; mCurrentColor = aColor; - xlib_rgb_gc_set_foreground(mRenderingSurface->GetGC(), NS_RGB(NS_GET_B(aColor), - NS_GET_G(aColor), - NS_GET_R(aColor))); + PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("Setting color to %d %d %d\n", NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor))); return NS_OK; } @@ -550,7 +592,6 @@ nsRenderingContextXlib::SetFont(nsIFontMetrics *aFontMetrics) nsFontHandle fontHandle; mFontMetrics->GetFontHandle(fontHandle); mCurrentFont = (XFontStruct *)fontHandle; - XSetFont(mDisplay, mRenderingSurface->GetGC(), mCurrentFont->fid); } return NS_OK; } @@ -601,12 +642,13 @@ nsRenderingContextXlib::CreateDrawingSurface(nsRect *aBounds, PRUint32 aSurfFlag if (surf) { NS_ADDREF(surf); - + if (!mGC) + UpdateGC(); surf->Init(mDisplay, mScreen, mVisual, mDepth, - mRenderingSurface->GetGC(), + mGC, aBounds->width, aBounds->height, aSurfFlags); @@ -650,8 +692,10 @@ nsRenderingContextXlib::DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord diffY = (diffY>0?1:-1); } + UpdateGC(); + ::XDrawLine(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), aX0, aY0, aX1 - diffX, aY1 - diffY); + *mGC, aX0, aY0, aX1 - diffX, aY1 - diffY); return NS_OK; } @@ -678,8 +722,9 @@ nsRenderingContextXlib::DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoo diffY = (diffY>0?1:-1); } + UpdateGC(); ::XDrawLine(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), aX0, aY0, aX1 - diffX, aY1 - diffY); + *mGC, aX0, aY0, aX1 - diffX, aY1 - diffY); return NS_OK; } @@ -704,9 +749,10 @@ nsRenderingContextXlib::DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints mTranMatrix->TransformCoord((PRInt32*)&thispoint->x,(PRInt32*)&thispoint->y); } + UpdateGC(); ::XDrawLines(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, xpoints, aNumPoints, CoordModeOrigin); PR_Free((void *)xpoints); @@ -738,13 +784,19 @@ nsRenderingContextXlib::DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord mTranMatrix->TransformCoord(&x,&y,&w,&h); + // After the transform, if the numbers are huge, chop them, because + // they're going to be converted from 32 bit to 16 bit. + // It's all way off the screen anyway. + ConditionRect(x,y,w,h); + // Don't draw empty rectangles; also, w/h are adjusted down by one // so that the right number of pixels are drawn. if (w && h) { + UpdateGC(); ::XDrawRectangle(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x, y, w - 1, @@ -775,11 +827,18 @@ nsRenderingContextXlib::FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord h = aHeight; mTranMatrix->TransformCoord(&x,&y,&w,&h); + + // After the transform, if the numbers are huge, chop them, because + // they're going to be converted from 32 bit to 16 bit. + // It's all way off the screen anyway. + ConditionRect(x,y,w,h); + PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("About to fill window 0x%lxd with rect %d %d %d %d\n", mRenderingSurface->GetDrawable(), x, y, w, h)); + UpdateGC(); ::XFillRectangle(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x,y,w,h); return NS_OK; @@ -806,23 +865,24 @@ nsRenderingContextXlib :: InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nsc mTranMatrix->TransformCoord(&x,&y,&w,&h); - // Set XOR drawing mode - ::XSetFunction(mDisplay, - mRenderingSurface->GetGC(), - GXxor); + // After the transform, if the numbers are huge, chop them, because + // they're going to be converted from 32 bit to 16 bit. + // It's all way off the screen anyway. + ConditionRect(x,y,w,h); + mFunction = GXxor; + + UpdateGC(); + ::XFillRectangle(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x, y, w, h); - // Back to normal copy drawing mode - ::XSetFunction(mDisplay, - mRenderingSurface->GetGC(), - GXcopy); + mFunction = GXcopy; return NS_OK; } @@ -847,9 +907,10 @@ nsRenderingContextXlib::DrawPolygon(const nsPoint aPoints[], PRInt32 aNumPoints) mTranMatrix->TransformCoord((PRInt32*)&thispoint->x,(PRInt32*)&thispoint->y); } + UpdateGC(); ::XDrawLines(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, xpoints, aNumPoints, CoordModeOrigin); PR_Free((void *)xpoints); @@ -880,9 +941,10 @@ nsRenderingContextXlib::FillPolygon(const nsPoint aPoints[], PRInt32 aNumPoints) thispoint->y = y; } + UpdateGC(); ::XFillPolygon(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, xpoints, aNumPoints, Convex, CoordModeOrigin); PR_Free((void *)xpoints); @@ -913,9 +975,10 @@ nsRenderingContextXlib::DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nsco mTranMatrix->TransformCoord(&x,&y,&w,&h); + UpdateGC(); ::XDrawArc(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x,y,w,h, 0, 360 * 64); return NS_OK; @@ -944,9 +1007,11 @@ nsRenderingContextXlib::FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nsco mTranMatrix->TransformCoord(&x,&y,&w,&h); + UpdateGC(); + ::XFillArc(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x,y,w,h, 0, 360 * 64); return NS_OK; @@ -977,9 +1042,10 @@ nsRenderingContextXlib::DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord mTranMatrix->TransformCoord(&x,&y,&w,&h); + UpdateGC(); ::XDrawArc(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x,y,w,h, NSToIntRound(aStartAngle * 64.0f), NSToIntRound(aEndAngle * 64.0f)); @@ -1011,9 +1077,10 @@ nsRenderingContextXlib::FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord mTranMatrix->TransformCoord(&x,&y,&w,&h); + UpdateGC(); ::XFillArc(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x,y,w,h, NSToIntRound(aStartAngle * 64.0f), NSToIntRound(aEndAngle * 64.0f)); @@ -1156,6 +1223,8 @@ nsRenderingContextXlib::DrawString(const char *aString, PRUint32 aLength, y += aY; } + UpdateGC(); + if (nsnull != aSpacing) { // Render the string, one character at a time... const char* end = aString + aLength; @@ -1164,9 +1233,9 @@ nsRenderingContextXlib::DrawString(const char *aString, PRUint32 aLength, nscoord xx = x; nscoord yy = y; mTranMatrix->TransformCoord(&xx, &yy); - XDrawString(mDisplay, + ::XDrawString(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, xx, yy, &ch, 1); x += *aSpacing++; } @@ -1175,7 +1244,7 @@ nsRenderingContextXlib::DrawString(const char *aString, PRUint32 aLength, mTranMatrix->TransformCoord(&x, &y); XDrawString(mDisplay, mRenderingSurface->GetDrawable(), - mRenderingSurface->GetGC(), + *mGC, x, y, aString, aLength); } } @@ -1267,6 +1336,7 @@ FoundFont: if (aSpacing) { const PRUnichar* str = &aString[start]; const PRUnichar* end = &aString[i]; + UpdateGC(); while (str < end) { x = aX; y = aY; @@ -1277,6 +1347,7 @@ FoundFont: } } else { + UpdateGC(); prevFont->DrawString(this, mRenderingSurface, x, y, &aString[start], i - start); x += prevFont->GetWidth(&aString[start], i -start); @@ -1292,6 +1363,7 @@ FoundFont: } if (prevFont) { + UpdateGC(); if (aSpacing) { const PRUnichar* str = &aString[start]; const PRUnichar* end = &aString[i]; @@ -1358,6 +1430,7 @@ nsRenderingContextXlib::DrawImage(nsIImage *aImage, const nsRect& aRect) nsRect tr; tr = aRect; mTranMatrix->TransformCoord(&tr.x, &tr.y, &tr.width, &tr.height); + UpdateGC(); return aImage->Draw(*this, mRenderingSurface, tr.x, tr.y, tr.width, tr.height); } @@ -1377,6 +1450,7 @@ nsRenderingContextXlib::DrawImage(nsIImage *aImage, const nsRect& aSRect, const dr = aDRect; mTranMatrix->TransformCoord(&dr.x, &dr.y, &dr.width, &dr.height); + UpdateGC(); return aImage->Draw(*this, mRenderingSurface, sr.x, sr.y, @@ -1454,10 +1528,12 @@ nsRenderingContextXlib::CopyOffScreenBits(nsDrawingSurface aSrcSurf, PRInt32 aSr //XXX flags are unused. that would seem to mean that there is //inefficiency somewhere... MMP + UpdateGC(); + XCopyArea(mDisplay, ((nsDrawingSurfaceXlib *)aSrcSurf)->GetDrawable(), destsurf->GetDrawable(), - ((nsDrawingSurfaceXlib *)aSrcSurf)->GetGC(), + *mGC, srcX, srcY, drect.width, drect.height, drect.x, drect.y); diff --git a/mozilla/gfx/src/xlib/nsRenderingContextXlib.h b/mozilla/gfx/src/xlib/nsRenderingContextXlib.h index a565b7706f9..8e69a370cad 100644 --- a/mozilla/gfx/src/xlib/nsRenderingContextXlib.h +++ b/mozilla/gfx/src/xlib/nsRenderingContextXlib.h @@ -41,6 +41,9 @@ #include "nsDrawingSurfaceXlib.h" #include "nsRegionXlib.h" #include "nsCOMPtr.h" +#include "nsGCCache.h" +#include +#include class GraphicsState; @@ -49,6 +52,7 @@ class nsRenderingContextXlib : public nsRenderingContextImpl public: nsRenderingContextXlib(); virtual ~nsRenderingContextXlib(); + static nsresult Shutdown(); // release statics NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW @@ -197,7 +201,10 @@ class nsRenderingContextXlib : public nsRenderingContextImpl // this is a common init function for both of the init functions. nsresult CommonInit(void); + xGC *GetGC() { mGC->AddRef(); return mGC; } + private: + void UpdateGC(); nsDrawingSurfaceXlib *mOffscreenSurface; nsDrawingSurfaceXlib *mRenderingSurface; nsIDeviceContext *mContext; @@ -214,6 +221,32 @@ private: nsVoidArray *mStateCache; XFontStruct *mCurrentFont; nsLineStyle mCurrentLineStyle; + xGC *mGC; + int mFunction; + int mLineStyle; + char *mDashList; + int mDashes; + + // ConditionRect is used to fix coordinate overflow problems for + // rectangles after they are transformed to screen coordinates + void ConditionRect(nscoord &x, nscoord &y, nscoord &w, nscoord &h) { + if ( y < -32766 ) { + y = -32766; + } + + if ( y + h > 32766 ) { + h = 32766 - y; + } + + if ( x < -32766 ) { + x = -32766; + } + + if ( x + w > 32766 ) { + w = 32766 - x; + } + } + }; #endif diff --git a/mozilla/widget/src/xlib/nsAppShell.cpp b/mozilla/widget/src/xlib/nsAppShell.cpp index 66eef8374a8..f1d01aa43d4 100644 --- a/mozilla/widget/src/xlib/nsAppShell.cpp +++ b/mozilla/widget/src/xlib/nsAppShell.cpp @@ -1,5 +1,6 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* +/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- + * vim:ts=2:et:sw=2 + * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of @@ -31,6 +32,7 @@ #include #include #include +#include #include "nsWindow.h" #include "nsWidget.h" @@ -295,6 +297,18 @@ NS_METHOD nsAppShell::Create(int* bac, char ** bav) break; } + /* setup locale */ + if (!setlocale (LC_ALL,"")) + NS_WARNING("locale not supported by C library"); + + if (!XSupportsLocale ()) { + NS_WARNING("locale not supported by Xlib, locale set to C"); + setlocale (LC_ALL, "C"); + } + + if (!XSetLocaleModifiers ("")) + NS_WARNING("can not set locale modifiers"); + // Open the display if (mDisplay == nsnull) { mDisplay = XOpenDisplay(displayName); @@ -304,12 +318,10 @@ NS_METHOD nsAppShell::Create(int* bac, char ** bav) // Requires XSynchronize(mDisplay, True); To stop X buffering. Use this // to make debugging easier. KenF - if (mDisplay == NULL) - { + if (mDisplay == NULL) { fprintf(stderr, "%s: Cannot connect to X server %s\n", argv[0], XDisplayName(displayName)); - exit(1); } @@ -728,7 +740,9 @@ nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget) eventType = NS_MOUSE_MIDDLE_BUTTON_DOWN; break; case 3: - eventType = NS_MOUSE_RIGHT_BUTTON_DOWN; + /* look back into this in case anything actually needs a + * NS_MOUSE_RIGHT_BUTTON_DOWN */ + eventType = NS_CONTEXTMENU; break; case 4: case 5: @@ -797,9 +811,8 @@ nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget) } } - if (currentlyDragging && !mDragging) { + if (currentlyDragging && !mDragging) HandleDragDropEvent(event, aWidget); - } mevent.message = eventType; mevent.eventStructType = NS_MOUSE_EVENT; @@ -812,7 +825,6 @@ nsAppShell::HandleButtonEvent(XEvent *event, nsWidget *aWidget) void nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget) { - PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Expose event for window 0x%lx %d %d %d %d\n", event->xany.window, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height)); @@ -830,23 +842,17 @@ nsAppShell::HandleExposeEvent(XEvent *event, nsWidget *aWidget) } while (txe.xexpose.count>0); } - - nsPaintEvent pevent; pevent.message = NS_PAINT; pevent.widget = aWidget; pevent.eventStructType = NS_PAINT_EVENT; pevent.rect = dirtyRect; - // XXX fix this pevent.time = 0; - //pevent.time = PR_Now(); - //pevent.region = nsnull; NS_ADDREF(aWidget); aWidget->OnPaint(pevent); NS_RELEASE(aWidget); delete pevent.rect; - } void diff --git a/mozilla/widget/src/xlib/nsScrollBar.cpp b/mozilla/widget/src/xlib/nsScrollBar.cpp index d16db6fedd0..d9bb321b99d 100644 --- a/mozilla/widget/src/xlib/nsScrollBar.cpp +++ b/mozilla/widget/src/xlib/nsScrollBar.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:ts=2:et:sw=2: * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -18,15 +19,20 @@ * Rights Reserved. * * Contributor(s): + * tim copperfield + * */ #include "nsScrollBar.h" #include "nsGfxCIID.h" - #include "xlibrgb.h" -NS_IMPL_ADDREF(nsScrollbar) -NS_IMPL_RELEASE(nsScrollbar) +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define NS_SCROLLBAR_MIN 8 + +NS_IMPL_ADDREF_INHERITED(nsScrollbar, nsWidget) +NS_IMPL_RELEASE_INHERITED(nsScrollbar, nsWidget) +NS_IMPL_QUERY_INTERFACE2(nsScrollbar, nsIScrollbar, nsIWidget) PRLogModuleInfo *XlibScrollbarLM = PR_NewLogModule("XlibScrollbar"); @@ -36,6 +42,8 @@ nsScrollbar::nsScrollbar(PRBool aIsVertical) : nsWidget(), nsIScrollbar() mMaxRange = 0; mPosition = 0; mThumbSize = 0; + mXScale = 0.0; + mYScale = 0.0; mLineIncrement = 1; mIsVertical = aIsVertical; mBackground = NS_RGB(100,100,100); @@ -49,9 +57,65 @@ nsScrollbar::~nsScrollbar() { } -NS_INTERFACE_MAP_BEGIN(nsScrollbar) - NS_INTERFACE_MAP_ENTRY(nsIScrollbar) -NS_INTERFACE_MAP_END_INHERITING(nsWidget) +/* Create scrollbar widget */ +void nsScrollbar::CreateNative(Window aParent, nsRect aRect) +{ + XSetWindowAttributes attr; + unsigned long attr_mask; + + // on a window resize, we don't want to window contents to + // be discarded... + attr.bit_gravity = NorthWestGravity; + // make sure that we listen for events + attr.event_mask = StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | VisibilityChangeMask; + // set the default background color and border to that awful gray + attr.background_pixel = mBackgroundPixel; + attr.border_pixel = mBorderPixel; + // set the colormap + attr.colormap = xlib_rgb_get_cmap(); + // here's what's in the struct + attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel; + // check to see if there was actually a colormap. + if (attr.colormap) + attr_mask |= CWColormap; + + CreateNativeWindow(aParent, mBounds, attr, attr_mask); + // set up the scrolling bar. + attr.event_mask = Button1MotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | VisibilityChangeMask; + attr.background_pixel = xlib_rgb_xpixel_from_rgb(NS_RGB(192,192,192)); + attr.border_pixel = xlib_rgb_xpixel_from_rgb(NS_RGB(100,100,100)); + // set up the size + CalcBarBounds(); + mBar = XCreateWindow(mDisplay, + mBaseWindow, + mBarBounds.x, mBarBounds.y, + mBarBounds.width, mBarBounds.height, + 2, // border width + mDepth, + InputOutput, + mVisual, + attr_mask, + &attr); + AddWindowCallback(mBar, this); + PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::CreateNative created window 0x%lx with bar 0x%lx\n", + mBaseWindow, mBar)); +} + +void nsScrollbar::DestroyNative(void) +{ + // override since we have two native widgets + if (mBar) { + DestroyNativeChildren(mDisplay, mBar); + + XDestroyWindow(mDisplay, mBar); + DeleteWindowCallback(mBar); + mBar = 0; + } + if (mBaseWindow) { + nsWidget::DestroyNative(); + mBaseWindow = 0; + } +} NS_METHOD nsScrollbar::SetMaxRange(PRUint32 aEndRange) { @@ -74,8 +138,7 @@ NS_METHOD nsScrollbar::SetPosition(PRUint32 aPos) { PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::SetPosition()\n")); PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("Scroll to %d\n", aPos)); -// mPosition = (PRUint32)((float)aPos / (float)mRequestedSize.height * (float)mMaxRange); - mPosition = aPos; + mPosition = CLAMP(aPos, 0, mMaxRange); CalcBarBounds(); LayoutBar(); return NS_OK; @@ -155,6 +218,9 @@ PRBool nsScrollbar::OnScroll(PRUint32 scrollCode, int cPos) result = PrevPage(); break; case NS_SCROLLBAR_POS: + if (mIsVertical == PR_TRUE) + result = SetPosition(cPos); + else result = SetPosition(cPos); break; default: @@ -178,105 +244,40 @@ PRBool nsScrollbar::OnResize(nsSizeEvent &event) PRBool nsScrollbar::DispatchMouseEvent(nsMouseEvent &aEvent) { - PRBool result; + PRInt32 real; PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::DispatchMouseEvent\n")); - // check to see if this was on the main window. + /* that calculation is kind of screwed, but better than the original */ switch (aEvent.message) { case NS_MOUSE_MIDDLE_BUTTON_DOWN: if (mIsVertical == PR_TRUE) { - OnScroll(NS_SCROLLBAR_POS, aEvent.point.y); + real = (PRInt32)((float)(PR_MAX(0, aEvent.point.y - ((PRInt32)PR_MAX((mThumbSize * mYScale), NS_SCROLLBAR_MIN) / 2))) / mYScale); + OnScroll(NS_SCROLLBAR_POS, real); + } else { + real = (PRInt32)((float)(PR_MAX(0, aEvent.point.x - ((PRInt32)PR_MAX((mThumbSize * mXScale), NS_SCROLLBAR_MIN) / 2))) / mXScale); + OnScroll(NS_SCROLLBAR_POS, real); } - else { - OnScroll(NS_SCROLLBAR_POS, aEvent.point.x); - } break; + case NS_MOUSE_LEFT_BUTTON_DOWN: if (mIsVertical == PR_TRUE) { - if (aEvent.point.y < mBarBounds.y) { + if (aEvent.point.y < mBarBounds.y) OnScroll(NS_SCROLLBAR_PAGE_PREV, 0); - } - else if (aEvent.point.y > mBarBounds.height) { + else if (aEvent.point.y > (mBarBounds.y + mBarBounds.height)) + OnScroll(NS_SCROLLBAR_PAGE_NEXT, 0); + } else { /* !vertical */ + if (aEvent.point.x < mBarBounds.x) + OnScroll(NS_SCROLLBAR_PAGE_PREV, 0); + else if (aEvent.point.x > (mBarBounds.x + mBarBounds.width)) OnScroll(NS_SCROLLBAR_PAGE_NEXT, 0); } - } - else { - if (aEvent.point.x < mBarBounds.x) { - OnScroll(NS_SCROLLBAR_PAGE_PREV, 0); - } - else if (aEvent.point.x > mBarBounds.width) { - OnScroll(NS_SCROLLBAR_PAGE_NEXT, 0); - } - } break; default: break; - } - result = PR_FALSE; - return result; } - - -void nsScrollbar::CreateNative(Window aParent, nsRect aRect) -{ - XSetWindowAttributes attr; - unsigned long attr_mask; - - // on a window resize, we don't want to window contents to - // be discarded... - attr.bit_gravity = SouthEastGravity; - // make sure that we listen for events - attr.event_mask = StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | VisibilityChangeMask; - // set the default background color and border to that awful gray - attr.background_pixel = mBackgroundPixel; - attr.border_pixel = mBorderPixel; - // set the colormap - attr.colormap = xlib_rgb_get_cmap(); - // here's what's in the struct - attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel; - // check to see if there was actually a colormap. - if (attr.colormap) - attr_mask |= CWColormap; - - CreateNativeWindow(aParent, mBounds, attr, attr_mask); - CreateGC(); - // set up the scrolling bar. - attr.event_mask = Button1MotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | VisibilityChangeMask; - attr.background_pixel = xlib_rgb_xpixel_from_rgb(NS_RGB(192,192,192)); - attr.border_pixel = xlib_rgb_xpixel_from_rgb(NS_RGB(100,100,100)); - // set up the size - CalcBarBounds(); - mBar = XCreateWindow(mDisplay, - mBaseWindow, - mBarBounds.x, mBarBounds.y, - mBarBounds.width, mBarBounds.height, - 2, // border width - mDepth, - InputOutput, - mVisual, - attr_mask, - &attr); - AddWindowCallback(mBar, this); - PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::CreateNative created window 0x%lx with bar 0x%lx\n", - mBaseWindow, mBar)); -} - -void nsScrollbar::DestroyNative() -{ - // override since we have two native widgets - if (mBar) { - DestroyNativeChildren(mDisplay, mBar); - - XDestroyWindow(mDisplay, mBar); - DeleteWindowCallback(mBar); - mBar = 0; + return SendEvent(NS_SCROLLBAR_POS); } - if (mBaseWindow) { - nsWidget::DestroyNative(); - mBaseWindow = 0; - } -} NS_IMETHODIMP nsScrollbar::Show(PRBool bState) { @@ -329,21 +330,7 @@ nsresult nsScrollbar::NextPage(void) mPosition = max; PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("nsScrollbar::NextPage(): new position is %d\n", mPosition)); - // send the event - if (mEventCallback) { - nsScrollbarEvent sevent; - sevent.message = NS_SCROLLBAR_POS; - sevent.widget = (nsWidget *)this; - sevent.eventStructType = NS_SCROLLBAR_EVENT; - sevent.position = (mPosition); - sevent.point.x = 0; - sevent.point.y = 0; - // send the event - result = ConvertStatus((*mEventCallback) (&sevent)); - // the gtk code indicates that the callback can - // modify the position. how odd. - mPosition = sevent.position; - } + result = SendEvent(NS_SCROLLBAR_POS); CalcBarBounds(); LayoutBar(); return result; @@ -352,27 +339,14 @@ nsresult nsScrollbar::NextPage(void) nsresult nsScrollbar::PrevPage(void) { nsresult result = PR_FALSE; + // check to make sure we don't go backwards if (mThumbSize > mPosition) { mPosition = 0; - } - else { + } else { mPosition -= mThumbSize; } - - // send the event - if (mEventCallback) { - nsScrollbarEvent sevent; - sevent.message = NS_SCROLLBAR_POS; - sevent.widget = (nsWidget *)this; - sevent.eventStructType = NS_SCROLLBAR_EVENT; - sevent.position = (mPosition); - // send the event - result = ConvertStatus((*mEventCallback) (&sevent)); - // the gtk code indicates that the callback can - // modify the position. how odd. - mPosition = sevent.position; - } + result = SendEvent(NS_SCROLLBAR_POS); CalcBarBounds(); LayoutBar(); return result; @@ -380,47 +354,46 @@ nsresult nsScrollbar::PrevPage(void) void nsScrollbar::CalcBarBounds(void) { - float bar_start; - float bar_end; + PRUint32 bar_start; + PRUint32 bar_end; if (mMaxRange == 0) { bar_start = 0; bar_end = 0; - PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: max range is zero.\n")); - + mXScale = 0.0; + mYScale = 0.0; + } else { + if (mIsVertical == PR_TRUE) { + mYScale = (float)mRequestedSize.height / (float)mMaxRange; + bar_start = (PRUint32)((float)mPosition * mYScale); + bar_end = (PRUint32)((float)mThumbSize * mYScale); + bar_start = CLAMP(bar_start, 0, (PRUint32)(mRequestedSize.height)); + } else { + mXScale = (float)mRequestedSize.width / (float)mMaxRange; + bar_start = (PRUint32)((float)mPosition * mXScale); + bar_end = (PRUint32)((float)mThumbSize * mXScale); + bar_start = CLAMP(bar_start, 0, (PRUint32)(mRequestedSize.width)); } - else { - - PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: position: %d max: %d thumb: %d\n", - mPosition, mMaxRange, mThumbSize)); - bar_start = (float)mPosition / (float)mMaxRange; - bar_end = (float)mThumbSize / (float)mMaxRange; - PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: start: %f end: %f\n", bar_start, bar_end)); - } + bar_end = PR_MAX(bar_end, NS_SCROLLBAR_MIN); if (mIsVertical == PR_TRUE) { mBarBounds.x = 0; - mBarBounds.y = (int)(bar_start * mRequestedSize.height); - mBarBounds.width = mRequestedSize.width; - mBarBounds.height = (int)(bar_end * mRequestedSize.height); - } - else { - mBarBounds.x = (int)(bar_start * mRequestedSize.width); + mBarBounds.y = bar_start; + mBarBounds.width = mRequestedSize.width - 4; + mBarBounds.height = bar_end; + } else { + mBarBounds.x = bar_start; mBarBounds.y = 0; - mBarBounds.width = (int)(bar_end * mRequestedSize.width); - mBarBounds.height = mRequestedSize.height; + mBarBounds.width = bar_end; + mBarBounds.height = mRequestedSize.height - 4; } - if (mBarBounds.height == 0) { + + if (mBarBounds.height == 0) mBarBounds.height = 1; - } - if (mBarBounds.width == 0) { - mBarBounds.width = 1; - } - PR_LOG(XlibScrollbarLM, PR_LOG_DEBUG, ("CalcBarBounds: bar is (%s) %d %d %d %d\n", - ((mIsVertical == PR_TRUE) ? "vertical" : "horizontal" ), - mBarBounds.x, mBarBounds.y, mBarBounds.width, mBarBounds.height)); + if (mBarBounds.width == 0) + mBarBounds.width = 1; } void nsScrollbar::LayoutBar(void) @@ -434,3 +407,22 @@ NS_IMETHODIMP nsScrollbar::Move(PRInt32 aX, PRInt32 aY) { return nsWidget::Move(aX, aY); } + +PRBool nsScrollbar::SendEvent(PRUint32 message) +{ + PRBool result = PR_FALSE; + // send the event + if (mEventCallback) { + nsScrollbarEvent sevent; + sevent.message = message; + sevent.widget = (nsWidget *)this; + sevent.eventStructType = NS_SCROLLBAR_EVENT; + sevent.position = (mPosition); + // send the event + result = ConvertStatus((*mEventCallback) (&sevent)); + // the gtk code indicates that the callback can + // modify the position. how odd. + mPosition = sevent.position; + } + return result; +} diff --git a/mozilla/widget/src/xlib/nsScrollBar.h b/mozilla/widget/src/xlib/nsScrollBar.h index b7452ef6a32..c5aac34c65e 100644 --- a/mozilla/widget/src/xlib/nsScrollBar.h +++ b/mozilla/widget/src/xlib/nsScrollBar.h @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:ts=2:et:sw=2 * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -68,6 +69,7 @@ public: PRBool OnScroll(PRUint32 scrollCode, int cPos); void CreateNative(Window aParent, nsRect aRect); + PRBool SendEvent(PRUint32 message); private: void CalcBarBounds(void); @@ -77,6 +79,8 @@ private: PRUint32 mMaxRange; PRUint32 mPosition; PRUint32 mThumbSize; + float mXScale; + float mYScale; PRUint32 mLineIncrement; PRBool mIsVertical; nsIRenderingContext *mRenderingContext; diff --git a/mozilla/widget/src/xlib/nsToolkit.cpp b/mozilla/widget/src/xlib/nsToolkit.cpp index 178a4798d38..e51de327ae1 100644 --- a/mozilla/widget/src/xlib/nsToolkit.cpp +++ b/mozilla/widget/src/xlib/nsToolkit.cpp @@ -23,6 +23,7 @@ #include "nsToolkit.h" #include "nsGUIEvent.h" #include "plevent.h" +#include "nsGCCache.h" // Static Thread Local Storage index of the toolkit object associated with // a given thread... @@ -32,15 +33,34 @@ static PRUintn gToolkitTLSIndex = 0; nsToolkit::nsToolkit() { NS_INIT_REFCNT(); + mGC = NULL; } nsToolkit::~nsToolkit() { + if(mGC) + mGC->Release(); } NS_DEFINE_IID(kIToolkitIID, NS_ITOOLKIT_IID); NS_IMPL_ISUPPORTS(nsToolkit,kIToolkitIID); +void nsToolkit::CreateSharedGC(Display *display, Drawable d) +{ + if (mGC) + return; + mGC = new xGC(display, d, 0, NULL); + mGC->AddRef(); // this is for us +} + +xGC *nsToolkit::GetSharedGC(Display *display, Drawable d) +{ + if(!mGC) + CreateSharedGC(display, d); + + return mGC; +} + NS_METHOD nsToolkit::Init(PRThread *aThread) { return NS_OK; @@ -66,14 +86,27 @@ NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult) { toolkit = (nsIToolkit*)PR_GetThreadPrivate(gToolkitTLSIndex); - // Create a new toolkit for this thread - if (!toolkit) - { - fprintf(stderr, "Creating a new nsIToolkit!\n"); + // + // Create a new toolkit for this thread... + // + if (!toolkit) { + toolkit = new nsToolkit(); + + if (!toolkit) { + rv = NS_ERROR_OUT_OF_MEMORY; + } else { + NS_ADDREF(toolkit); + toolkit->Init(PR_GetCurrentThread()); + // + // The reference stored in the TLS is weak. It is removed in the + // nsToolkit destructor... + // + PR_SetThreadPrivate(gToolkitTLSIndex, (void*)toolkit); } - else - fprintf(stderr, "No need to create a new nsIToolkit!\n"); + } else { + NS_ADDREF(toolkit); + } + *aResult = toolkit; } - return NS_OK; } diff --git a/mozilla/widget/src/xlib/nsToolkit.h b/mozilla/widget/src/xlib/nsToolkit.h index 22d8a27bd20..5e66f710d16 100644 --- a/mozilla/widget/src/xlib/nsToolkit.h +++ b/mozilla/widget/src/xlib/nsToolkit.h @@ -24,6 +24,7 @@ #define nsToolkit_h__ #include "nsIToolkit.h" +#include "nsGCCache.h" #include #include @@ -38,6 +39,9 @@ struct MethodInfo; class nsToolkit : public nsIToolkit { +private: + void CreateSharedGC(Display *display, Drawable d); + xGC *mGC; public: nsToolkit(); @@ -45,6 +49,7 @@ public: NS_DECL_ISUPPORTS NS_IMETHOD Init(PRThread *aThread); + xGC *GetSharedGC(Display *display, Drawable d); }; diff --git a/mozilla/widget/src/xlib/nsWidget.cpp b/mozilla/widget/src/xlib/nsWidget.cpp index 3c379452fbf..522b8976e9d 100644 --- a/mozilla/widget/src/xlib/nsWidget.cpp +++ b/mozilla/widget/src/xlib/nsWidget.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:ts=2:et:sw=2 * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -37,8 +38,10 @@ #include "nsIEventListener.h" #include "nsIMenuListener.h" #include "nsIMouseListener.h" +#include "nsIRollupListener.h" #include "nsGfxCIID.h" #include "nsIMenuRollup.h" +#include "nsToolkit.h" #include "xlibrgb.h" @@ -73,8 +76,7 @@ Window nsWidget::mFocusWindow = 0; // For popup handling nsCOMPtr nsWidget::gRollupListener; -//nsWeakPtr nsWidget::gRollupWidget; -nsCOMPtr nsWidget::gRollupWidget; +nsWeakPtr nsWidget::gRollupWidget; PRBool nsWidget::gRollupConsumeRollupEvent = PR_FALSE; class nsWindowKey : public nsHashKey { @@ -116,7 +118,6 @@ nsWidget::nsWidget() // : nsBaseWidget() mBackgroundPixel = xlib_rgb_xpixel_from_rgb(mBackground); mBackground = NS_RGB(192, 192, 192); mBorderPixel = xlib_rgb_xpixel_from_rgb(mBorderRGB); - mGC = 0; mParentWidget = nsnull; mName.AssignWithConversion("unnamed"); mIsShown = PR_FALSE; @@ -189,12 +190,6 @@ nsWidget::DestroyNative() // with dangling references. DestroyNativeChildren(mDisplay, mBaseWindow); - // This is handled in nsDrawingSurfaceXlib for now -#if 0 - if (mGC) - XFreeGC(mDisplay, mGC); -#endif - XDestroyWindow(mDisplay, mBaseWindow); DeleteWindowCallback(mBaseWindow); } @@ -217,9 +212,9 @@ NS_IMETHODIMP nsWidget::Create(nsIWidget *aParent, //mParentWidget = aParent; //NS_IF_ADDREF(mParentWidget); // KenF FIXME - return(StandardWidgetCreate(aParent, aRect, aHandleEventFunction, + return StandardWidgetCreate(aParent, aRect, aHandleEventFunction, aContext, aAppShell, aToolkit, aInitData, - nsnull)); + nsnull); } NS_IMETHODIMP nsWidget::Create(nsNativeWidget aParent, @@ -291,11 +286,9 @@ nsWidget::StandardWidgetCreate(nsIWidget *aParent, attr.bit_gravity = NorthWestGravity; attr.event_mask = GetEventMask(); - attr.background_pixel = mBackgroundPixel; - attr.border_pixel = mBorderPixel; attr.colormap = xlib_rgb_get_cmap(); - attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel; + attr_mask = CWBitGravity | CWEventMask; if (attr.colormap) attr_mask |= CWColormap; @@ -386,10 +379,16 @@ NS_IMETHODIMP nsWidget::ConstrainPosition(PRInt32 *aX, PRInt32 *aY) NS_IMETHODIMP nsWidget::Move(PRInt32 aX, PRInt32 aY) { - + //printf("nsWidget::Move aX=%i, aY=%i\n", aX, aY); PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Move(x, y)\n")); PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Moving window 0x%lx to %d, %d\n", mBaseWindow, aX, aY)); + if((aX == mBounds.x) && (aY == mBounds.y) && !mIsToplevel) { + //printf("discard this move\n"); + return NS_OK; + } + + mBounds.x = aX; mBounds.y = aY; @@ -433,6 +432,7 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) { + //printf("nsWidget::Resize aWidth=%i, Height=%i\n",aWidth, aHeight); PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Resize(width, height)\n")); if (aWidth <= 0) { @@ -444,6 +444,7 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** height is %d, fixing.\n", aHeight)); aHeight = 1; } + PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Resizing window 0x%lx to %d, %d\n", mBaseWindow, aWidth, aHeight)); mRequestedSize.width = mBounds.width = aWidth; mRequestedSize.height = mBounds.height = aHeight; @@ -477,6 +478,7 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aX, PRInt32 aHeight, PRBool aRepaint) { + //printf("nsWidget::Resize aX=%i, aY=%i, aWidth=%i, aHeight=%i\n", aX, aY, aWidth, aHeight); PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Resize(x, y, width, height)\n")); if (aWidth <= 0) { @@ -584,7 +586,8 @@ void * nsWidget::GetNativeData(PRUint32 aDataType) break; case NS_NATIVE_GRAPHIC: // XXX implement this... - return (void *)mGC; + NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC"); + return (void *)NS_STATIC_CAST(nsToolkit*,mToolkit)->GetSharedGC(mDisplay, mBaseWindow); break; default: fprintf(stderr, "nsWidget::GetNativeData(%d) called with crap value.\n", @@ -636,29 +639,10 @@ NS_IMETHODIMP nsWidget::Show(PRBool bState) PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("state is %d\n", bState)); if (bState) { - if (mIsToplevel) { - PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Someone just used the show method on the toplevel window.\n")); - } - if (mParentWidget) { - ((nsWidget *)mParentWidget)->WidgetShow(this); - // Fix Popups appearing behind mozilla window. TonyT - XRaiseWindow(mDisplay, mBaseWindow); - } - else { - if (mBaseWindow) { - PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Mapping window 0x%lx...\n", mBaseWindow)); Map(); - } - } - mIsShown = PR_TRUE; - } - else { - if (mBaseWindow) { - PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Unmapping window 0x%lx...\n", mBaseWindow)); + } else { Unmap(); } - mIsShown = PR_FALSE; - } return NS_OK; } @@ -702,6 +686,8 @@ NS_IMETHODIMP nsWidget::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) return NS_OK; } +NS_IMPL_ISUPPORTS_INHERITED(nsWidget, nsBaseWidget, nsISupportsWeakReference) + NS_IMETHODIMP nsWidget::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect) { @@ -815,11 +801,9 @@ void nsWidget::CreateNative(Window aParent, nsRect aRect) attr.bit_gravity = NorthWestGravity; attr.event_mask = GetEventMask(); - attr.background_pixel = mBackgroundPixel; - attr.border_pixel = mBorderPixel; attr.colormap = xlib_rgb_get_cmap(); - attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel ; + attr_mask = CWBitGravity | CWEventMask; if (attr.colormap) attr_mask |= CWColormap; @@ -986,13 +970,16 @@ nsWidget::OnPaint(nsPaintEvent &event) return result; } -PRBool nsWidget::IsMouseInWindow(nsIWidget* inWidget, PRInt32 inMouseX, PRInt32 inMouseY){ +PRBool nsWidget::IsMouseInWindow(Window window, PRInt32 inMouseX, PRInt32 inMouseY){ XWindowAttributes inWindowAttributes; + /* sometimes we get NULL window */ + if (!window) + return PR_FALSE; + // Get the origin (top left corner) coordinate and size - Window currentPopupWindow = (Window)inWidget->GetNativeData(NS_NATIVE_WINDOW); - if (XGetWindowAttributes(mDisplay, currentPopupWindow, &inWindowAttributes) == 0){ + if (XGetWindowAttributes(mDisplay, window, &inWindowAttributes) == 0) { fprintf(stderr, "Failed calling XGetWindowAttributes in nsWidget::IsMouseInWindow"); return PR_FALSE; } @@ -1033,21 +1020,20 @@ PRBool nsWidget::IsMouseInWindow(nsIWidget* inWidget, PRInt32 inMouseX, PRInt32 // // Deal with rollup of popups (xpmenus, etc) // -PRBool nsWidget::HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ){ +PRBool nsWidget::HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ) +{ PRBool retVal = PR_FALSE; PRBool rollup = PR_FALSE; // The gRollupListener and gRollupWidget are both set to nsnull when a popup is no // longer visible - // Use non weak reference until implemented - //nsCOMPtr rollupWidget = do_QueryReferent(gRollupWidget); - //nsCOMPtr rollupWidget = gRollupWidget; + nsCOMPtr rollupWidget = do_QueryReferent(gRollupWidget); - - if (gRollupWidget && gRollupListener){ + if (rollupWidget && gRollupListener) { + Window currentPopup = (Window)rollupWidget->GetNativeData(NS_NATIVE_WINDOW); - if (!IsMouseInWindow(gRollupWidget, inMouseX, inMouseY)){ + if (!IsMouseInWindow(currentPopup, inMouseX, inMouseY)) { rollup = PR_TRUE; nsCOMPtr menuRollup ( do_QueryInterface(gRollupListener) ); if ( menuRollup ) { @@ -1061,7 +1047,8 @@ PRBool nsWidget::HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ){ widgetChain->GetElementAt ( i, getter_AddRefs(genericWidget) ); nsCOMPtr widget ( do_QueryInterface(genericWidget) ); if ( widget ) { - if ( IsMouseInWindow(widget, inMouseX, inMouseY) ) { + Window currWindow = (Window)widget->GetNativeData(NS_NATIVE_WINDOW); + if ( IsMouseInWindow(currWindow, inMouseX, inMouseY) ) { rollup = PR_FALSE; break; } @@ -1070,11 +1057,9 @@ PRBool nsWidget::HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ){ } } } - } if (rollup){ - //fprintf(stderr, "Calling gRollupListener->Rollup()\n"); gRollupListener->Rollup(); retVal = PR_TRUE; } @@ -1212,6 +1197,7 @@ PRBool nsWidget::DispatchKeyEvent(nsKeyEvent & aKeyEvent) #undef TRACE_EVENTS_MOTION #undef TRACE_EVENTS_PAINT #undef TRACE_EVENTS_CROSSING +#undef DEBUG #ifdef DEBUG void @@ -1302,14 +1288,6 @@ PRBool nsWidget::ConvertStatus(nsEventStatus aStatus) return(PR_FALSE); } -void nsWidget::CreateGC(void) -{ - // This is handled in nsDrawingSurfaceXlib, for now -#if 0 - mGC = XCreateGC(mDisplay, mBaseWindow, 0, NULL); -#endif -} - void nsWidget::WidgetPut(nsWidget *aWidget) { diff --git a/mozilla/widget/src/xlib/nsWidget.h b/mozilla/widget/src/xlib/nsWidget.h index 2cc75587db7..9a940c00efe 100644 --- a/mozilla/widget/src/xlib/nsWidget.h +++ b/mozilla/widget/src/xlib/nsWidget.h @@ -31,6 +31,7 @@ #include #include "nsBaseWidget.h" +#include "nsWeakReference.h" #include "nsHashtable.h" #include "prlog.h" #include "nsIRegion.h" @@ -41,12 +42,14 @@ #define XLIB_WIDGET_NOISY #endif -class nsWidget : public nsBaseWidget +class nsWidget : public nsBaseWidget, public nsSupportsWeakReference { public: nsWidget(); virtual ~nsWidget(); + NS_DECL_ISUPPORTS_INHERITED + NS_IMETHOD Create(nsIWidget *aParent, const nsRect &aRect, EVENT_CALLBACK aHandleEventFunction, @@ -156,9 +159,10 @@ public: void *CheckParent(long ThisWindow); // Deal with rollup for popups - PRBool IsMouseInWindow(nsIWidget* inWidget, PRInt32 inMouseX, PRInt32 inMouseY); + PRBool IsMouseInWindow(Window window, PRInt32 inMouseX, PRInt32 inMouseY); PRBool HandlePopup( PRInt32 inMouseX, PRInt32 inMouseY); + void WidgetShow (nsWidget *aWidget); protected: nsCOMPtr mUpdateArea; @@ -171,7 +175,6 @@ protected: virtual void CreateNative(Window aParent, nsRect aRect); virtual void DestroyNative(); static void DestroyNativeChildren(Display *aDisplay, Window aWindow); - void CreateGC(void); void Map(void); void Unmap(void); @@ -192,11 +195,11 @@ protected: void WidgetMove (nsWidget *aWidget); void WidgetMoveResize (nsWidget *aWidget); void WidgetResize (nsWidget *aWidget); - void WidgetShow (nsWidget *aWidget); // check to see whether or not a rect will intersect with the current scrolled area PRBool WidgetVisible (nsRect &aBounds); PRBool mIsShown; + PRBool mShown; int mVisibility; // this is an int because that's the way X likes it PRUint32 mPreferredWidth; PRUint32 mPreferredHeight; @@ -213,11 +216,12 @@ protected: unsigned long mBackgroundPixel; PRUint32 mBorderRGB; unsigned long mBorderPixel; - GC mGC; // until we get gc pooling working... + // GC mGC; // until we get gc pooling working... nsString mName; // name of the type of widget PRBool mIsToplevel; nsRect mRequestedSize; PRBool mMapped; + PRBool mLastGrabFailed; static Window mFocusWindow; @@ -232,8 +236,7 @@ protected: // Variables for infomation about the current popup window and its listener static nsCOMPtr gRollupListener; - static nsCOMPtr gRollupWidget; - //static nsWeakPtr gRollupWidget; + static nsWeakPtr gRollupWidget; static PRBool gRollupConsumeRollupEvent; }; diff --git a/mozilla/widget/src/xlib/nsWindow.cpp b/mozilla/widget/src/xlib/nsWindow.cpp index 128a89f74d8..17e934ecc7f 100644 --- a/mozilla/widget/src/xlib/nsWindow.cpp +++ b/mozilla/widget/src/xlib/nsWindow.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:ts=2:et:sw=2 * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -28,6 +29,11 @@ #include "xlibrgb.h" +/* for window title unicode->locale conversion */ +#include "nsICharsetConverterManager.h" +#include "nsIPlatformCharset.h" +#include "nsIServiceManager.h" + #include "nsFileSpec.h" // for nsAutoCString #define ABS(i) ( i<0 ? 0-i : i ) @@ -176,6 +182,7 @@ nsWindow::UnqueueDraw () } /////////////////////////////////////////////////////////////////// +NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsWidget) /////////////////////////////////////////////////////////////////// nsWindow::nsWindow() : nsWidget() @@ -190,6 +197,8 @@ nsWindow::nsWindow() : nsWidget() // FIXME KenF mIsUpdating = PR_FALSE; mBlockFocusEvents = PR_FALSE; + mLastGrabFailed = PR_TRUE; + mIsTooSmall = PR_FALSE; // FIXME New on M17 merge. mWindowType = eWindowType_child; @@ -234,10 +243,49 @@ PRBool nsWindow::OnExpose(nsPaintEvent &event) return result; } +NS_IMETHODIMP nsWindow::Show(PRBool bState) +{ + // don't show if we are too small + if (mIsTooSmall) + return NS_OK; + + if (bState) { + if (mIsToplevel) { + PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Someone just used the show method on the toplevel window.\n")); + } + + if (mParentWidget) { + ((nsWidget *)mParentWidget)->WidgetShow(this); + // Fix Popups appearing behind mozilla window. TonyT + XRaiseWindow(mDisplay, mBaseWindow); + } else { + if (mBaseWindow) { + PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Mapping window 0x%lx...\n", mBaseWindow)); + Map(); + } + } + + mIsShown = PR_TRUE; + if (sGrabWindow == this && mLastGrabFailed) { + /* re-grab things like popup menus - the window isn't mapped when + * the first grab occurs */ + NativeGrab(PR_TRUE); + } + } else { + if (mBaseWindow) { + PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Unmapping window 0x%lx...\n", mBaseWindow)); + Unmap(); + } + mIsShown = PR_FALSE; + } + return NS_OK; +} + // Function that does native grab. void nsWindow::NativeGrab(PRBool aGrab) { Cursor newCursor = XCreateFontCursor(mDisplay, XC_right_ptr); + mLastGrabFailed = PR_FALSE; if (aGrab) { @@ -249,17 +297,15 @@ void nsWindow::NativeGrab(PRBool aGrab) (Window)0, newCursor, CurrentTime); if (retval != GrabSuccess) - fprintf(stderr, "Grab pointer failed!\n"); + mLastGrabFailed = PR_TRUE; retval = XGrabKeyboard(mDisplay, mBaseWindow, PR_TRUE, GrabModeAsync, GrabModeAsync, CurrentTime); if (retval != GrabSuccess) - fprintf(stderr, "Grab keyboard failed!\n"); + mLastGrabFailed = PR_TRUE; - } - else - { + } else { XUngrabPointer(mDisplay, CurrentTime); XUngrabKeyboard(mDisplay, CurrentTime); } @@ -272,29 +318,17 @@ void nsWindow::NativeGrab(PRBool aGrab) NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent) -{ - if (aDoCapture) { + if (aDoCapture) { NativeGrab(PR_TRUE); sIsGrabbing = PR_TRUE; sGrabWindow = this; - //fprintf(stderr, "Received listener from generated popup\n"); - gRollupListener = aListener; - - // Get assertion error: - // ###!!! ASSERTION: Did you know you were calling |NS_GetWeakReference()| on - // something that doesn't support weak references?: 'factoryPtr', file - // nsWeakReference.cpp, line 55 - //gRollupWidget = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWidget*,this))); - gRollupWidget = NS_STATIC_CAST(nsIWidget*,this); - - // GTK does not seem to use this but other window toolkits do gRollupConsumeRollupEvent = PR_TRUE; - //} + gRollupListener = aListener; + gRollupWidget = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWidget*, this))); }else{ - // Release Grab if (sGrabWindow == this) sGrabWindow = NULL; @@ -377,6 +411,34 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) { + //printf("nsWindow::Resize aWidth=%i aHeight=%i\n", aWidth,aHeight); + PRBool NeedToShow = PR_FALSE; + /* PRInt32 sizeHeight = aHeight; + PRInt32 sizeWidth = aWidth; */ + + mBounds.width = aWidth; + mBounds.height = aHeight; + + // code to keep the window from showing before it has been moved or resized + + // if we are resized to 1x1 or less, we will hide the window. Show(TRUE) will be ignored until a + // larger resize has happened + if (aWidth <= 1 || aHeight <= 1) + { + aWidth = 1; + aHeight = 1; + mIsTooSmall = PR_TRUE; + Show(PR_FALSE); + } + else + { + if (mIsTooSmall) + { + // if we are not shown, we don't want to force a show here, so check and see if Show(TRUE) has been called + NeedToShow = mShown; + mIsTooSmall = PR_FALSE; + } + } nsWidget::Resize(aWidth, aHeight, aRepaint); nsSizeEvent sevent; @@ -393,6 +455,13 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, OnResize(sevent); Release(); delete sevent.windowSize; + + if (NeedToShow) + Show(PR_TRUE); + + if (aRepaint) + Invalidate(PR_FALSE); + return NS_OK; } @@ -407,6 +476,7 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aX, PRInt32 aHeight, PRBool aRepaint) { + //printf("nsWindow::Resize aX=%i, aY=%i, aWidth=%i, aHeight=%i\n", aX,aY,aWidth,aHeight); nsWidget::Resize(aX, aY, aWidth, aHeight, aRepaint); @@ -427,43 +497,6 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aX, return NS_OK; } - - -#if 0 -void nsWindow::CreateNative(Window aParent, nsRect aRect) -{ - XSetWindowAttributes attr; - unsigned long attr_mask; - - // on a window resize, we don't want to window contents to - // be discarded... - attr.bit_gravity = NorthWestGravity; - // make sure that we listen for events - attr.event_mask = StructureNotifyMask | - ExposureMask | - ButtonPressMask | - ButtonReleaseMask | - PointerMotionMask | - KeyPressMask | - KeyReleaseMask | - VisibilityChangeMask; - // set the default background color and border to that awful gray - attr.background_pixel = mBackgroundPixel; - attr.border_pixel = mBorderPixel; - // set the colormap - attr.colormap = xlib_rgb_get_cmap(); - // here's what's in the struct - attr_mask = CWBitGravity | CWEventMask | CWBackPixel | CWBorderPixel; - // check to see if there was actually a colormap. - if (attr.colormap) - attr_mask |= CWColormap; - - CreateNativeWindow(aParent, mBounds, attr, attr_mask); - CreateGC(); - -} -#endif - /* virtual */ long nsWindow::GetEventMask() { @@ -587,7 +620,7 @@ NS_IMETHODIMP nsWindow::Update() nsISupports* child; if (NS_SUCCEEDED(children->CurrentItem(&child))) { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*,child); + nsWindow *childWindow = NS_STATIC_CAST(nsWindow*, NS_STATIC_CAST(nsIWidget*, child)); NS_RELEASE(child); childWindow->Update(); @@ -604,10 +637,9 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) if (mIsUpdating) UnqueueDraw(); - PRInt32 srcX, srcY, destX, destY, width, height; + PRInt32 srcX = 0, srcY = 0, destX = 0, destY = 0, width = 0, height = 0; nsRect aRect; GC gc; - gc = XCreateGC(mDisplay, mBaseWindow, 0, NULL); if (aDx < 0 || aDy < 0) @@ -669,7 +701,7 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) nsISupports* child; if (NS_SUCCEEDED(children->CurrentItem(&child))) { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*,child); + nsWindow *childWindow = NS_STATIC_CAST(nsWindow*, NS_STATIC_CAST(nsIWidget*, child)); NS_RELEASE(child); nsRect bounds; @@ -724,6 +756,61 @@ NS_IMETHODIMP nsWindow::SetTitle(const nsString& aTitle) if(!mBaseWindow) return NS_ERROR_FAILURE; + nsresult rv; + char *platformText; + PRInt32 platformLen; + + nsCOMPtr encoder; + /* get the charset */ + nsAutoString platformCharset; + nsCOMPtr platformCharsetService = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + rv = platformCharsetService->GetCharset(kPlatformCharsetSel_Menu, platformCharset); + + if (NS_FAILED(rv)) + platformCharset.AssignWithConversion("ISO-8859-1"); + + /* get the encoder */ + NS_WITH_SERVICE(nsICharsetConverterManager, ccm, NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); + rv = ccm->GetUnicodeEncoder(&platformCharset, getter_AddRefs(encoder)); + + /* Estimate out length and allocate the buffer based on a worst-case estimate, then do + the conversion. */ + PRInt32 len = (PRInt32)aTitle.Length(); + encoder->GetMaxLength(aTitle.GetUnicode(), len, &platformLen); + if (platformLen) { + platformText = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(platformLen + sizeof(char))); + if (platformText) { + rv = encoder->Convert(aTitle.GetUnicode(), &len, platformText, &platformLen); + (platformText)[platformLen] = '\0'; // null terminate. Convert() doesn't do it for us + } + } // if valid length + + if (platformLen > 0) { + int status = 0; + XTextProperty prop; + + /* Use XStdICCTextStyle for 41786(a.k.a TWM sucks) and 43108(JA text title) */ + prop.value = 0; + status = XmbTextListToTextProperty(mDisplay, &platformText, 1, + XStdICCTextStyle, &prop); + + if (status == Success) { + XSetWMProperties(mDisplay, mBaseWindow, + &prop, &prop, NULL, 0, NULL, NULL, NULL); + if (prop.value) + XFree(prop.value); + + nsMemory::Free(platformText); + return NS_OK; + } else { // status != Success + if (prop.value) + XFree(prop.value); + nsMemory::Free(platformText); + } + } + + /* if the stuff above failed, replace multibyte with .... */ XStoreName(mDisplay, mBaseWindow, (const char *) nsAutoCString(aTitle)); return NS_OK; diff --git a/mozilla/widget/src/xlib/nsWindow.h b/mozilla/widget/src/xlib/nsWindow.h index c8146766141..f8d1e20f5fb 100644 --- a/mozilla/widget/src/xlib/nsWindow.h +++ b/mozilla/widget/src/xlib/nsWindow.h @@ -70,6 +70,9 @@ class nsWindow : public nsWidget public: nsWindow(); ~nsWindow(); + + NS_DECL_ISUPPORTS_INHERITED + static void UpdateIdle (void *data); NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, PRBool aDoCapture, @@ -83,6 +86,7 @@ class nsWindow : public nsWidget NS_IMETHOD ScrollRect(nsRect &aSrcRect, PRInt32 aDx, PRInt32 aDy); NS_IMETHOD SetTitle(const nsString& aTitle); + NS_IMETHOD Show(PRBool aShow); NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, @@ -108,6 +112,7 @@ protected: void UnqueueDraw(); PRBool mIsUpdating; PRBool mBlockFocusEvents; + PRBool mIsTooSmall; static PRBool sIsGrabbing; static nsWindow *sGrabWindow;