r=blizzard, sr=kin@netscape.com, a=asa for drivers
XLIB only - Checkin for timecop@network.email.ne.jp - adding gc-cache to xlib port
This commit is contained in:
mkaply%us.ibm.com 2001-06-15 19:11:03 +00:00
parent 6ecd046893
commit 2fe8c52474
19 changed files with 1255 additions and 576 deletions

View File

@ -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

View File

@ -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

View File

@ -23,6 +23,7 @@
#include "nsDrawingSurfaceXlib.h"
#include "prlog.h"
#include "nsGCCache.h"
#include "xlibrgb.h" // for xlib_rgb_get_visual_info
#include <X11/Xutil.h> // 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);
}

View File

@ -24,6 +24,7 @@
#define nsDrawingSurfaceXlib_h__
#include "nsIDrawingSurface.h"
#include "nsGCCache.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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; (y<bottom) && !mAlphaValid; y++) {
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + left;
for (unsigned x=left; x<right; x++) {
if (*(alpha++)!=255) {
mAlphaValid=PR_TRUE;
break;
}
if (mImagePixmap != nsnull) {
XFreePixmap(mDisplay, mImagePixmap);
mImagePixmap = nsnull;
}
}
}
mFlags = aFlags;
if (mAlphaValid && mImagePixmap) {
XFreePixmap(mDisplay, mImagePixmap);
mImagePixmap = 0;
}
if (!mAlphaValid) {
CreateOffscreenPixmap(mWidth, mHeight);
if (!sXbitGC) {
XGCValues gcv;
memset(&gcv, 0, sizeof(XGCValues));
gcv.function = GXcopy;
sXbitGC = XCreateGC(mDisplay, mImagePixmap, GCFunction, &gcv);
}
xlib_draw_rgb_image_dithalign(mImagePixmap, sXbitGC,
aUpdateRect->x, 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; col<ximage->width; 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; y<mDecodedY2; y++) {
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + mDecodedX1;
for (int x=mDecodedX1; x<mDecodedX2; x++)
if (*(alpha++)!=255) {
mAlphaValid=PR_TRUE;
}
}
}
return NS_OK;
}
@ -1056,32 +1418,26 @@ NS_IMETHODIMP nsImageXlib::DrawToImage(nsIImage* aDstImage,
nscoord aDX, nscoord aDY,
nscoord aDWidth, nscoord aDHeight)
{
#if 0
// XXX This is a copy of the GTK version, partially converted for
// the xlib port. I can't figure out how to finish it.
nsImageXlib *dest = NS_STATIC_CAST(nsImageXlib *, aDstImage);
if (!dest)
return NS_ERROR_FAILURE;
nsDrawingSurfaceXlib *drawing = /* XXX What should this be!?!?! */ nsnull;
NS_ENSURE_TRUE(drawing, NS_ERROR_FAILURE);
if (!dest->mImagePixmap)
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

View File

@ -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;

View File

@ -21,6 +21,7 @@
* Peter Hartshorn <peter@igelaus.com.au>
* Ken Faulkner <faulkner@igelaus.com.au>
* Tony Tsui <tony@igelaus.com.au>
* Tomi Leppikangas <tomi.leppikangas@oulu.fi>
*/
#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);

View File

@ -41,6 +41,9 @@
#include "nsDrawingSurfaceXlib.h"
#include "nsRegionXlib.h"
#include "nsCOMPtr.h"
#include "nsGCCache.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
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

View File

@ -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 <errno.h>
#include <X11/keysym.h>
#include <X11/keysymdef.h>
#include <X11/Xlocale.h>
#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

View File

@ -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 <timecop@japan.co.jp>
*
*/
#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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -24,6 +24,7 @@
#define nsToolkit_h__
#include "nsIToolkit.h"
#include "nsGCCache.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -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);
};

View File

@ -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<nsIRollupListener> nsWidget::gRollupListener;
//nsWeakPtr nsWidget::gRollupWidget;
nsCOMPtr<nsIWidget> 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<nsIWidget> rollupWidget = do_QueryReferent(gRollupWidget);
//nsCOMPtr<nsIWidget> rollupWidget = gRollupWidget;
nsCOMPtr<nsIWidget> 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<nsIMenuRollup> menuRollup ( do_QueryInterface(gRollupListener) );
if ( menuRollup ) {
@ -1061,7 +1047,8 @@ PRBool nsWidget::HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ){
widgetChain->GetElementAt ( i, getter_AddRefs(genericWidget) );
nsCOMPtr<nsIWidget> 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)
{

View File

@ -31,6 +31,7 @@
#include <X11/Xos.h>
#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<nsIRegion> 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<nsIRollupListener> gRollupListener;
static nsCOMPtr<nsIWidget> gRollupWidget;
//static nsWeakPtr gRollupWidget;
static nsWeakPtr gRollupWidget;
static PRBool gRollupConsumeRollupEvent;
};

View File

@ -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<nsIUnicodeEncoder> encoder;
/* get the charset */
nsAutoString platformCharset;
nsCOMPtr <nsIPlatformCharset> 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;

View File

@ -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;