diff --git a/gfx/thebes/public/gfxOS2Surface.h b/gfx/thebes/public/gfxOS2Surface.h index b12f2bcc7625..6bc1058db830 100644 --- a/gfx/thebes/public/gfxOS2Surface.h +++ b/gfx/thebes/public/gfxOS2Surface.h @@ -47,8 +47,6 @@ class THEBES_API gfxOS2Surface : public gfxASurface { public: - // constructor to create a cairo surface using an existing PS - gfxOS2Surface(HPS aPS, const gfxIntSize& aSize); // constructor used to create a memory surface of given size gfxOS2Surface(const gfxIntSize& aSize, gfxASurface::gfxImageFormat aImageFormat); @@ -56,11 +54,20 @@ public: gfxOS2Surface(HWND aWnd); virtual ~gfxOS2Surface(); + // Special functions that only make sense for the OS/2 port of cairo: + + // Update the cairo surface. + // While gfxOS2Surface keeps track of the presentation handle itself, + // use the one from WinBeginPaint() here. + void Refresh(RECTL *aRect, HPS aPS); + + // Reset the cairo surface to the given size. + int Resize(const gfxIntSize& aSize); + HPS GetPS() { return mPS; } gfxIntSize GetSize() { return mSize; } private: - PRBool mOwnsPS; PRBool mHasWnd; // indicates if created through the HWND constructor HDC mDC; // memory device context HPS mPS; // presentation space connected to window or memory device diff --git a/gfx/thebes/src/gfxOS2Surface.cpp b/gfx/thebes/src/gfxOS2Surface.cpp index bd21c8358a23..3a4c9ee69789 100644 --- a/gfx/thebes/src/gfxOS2Surface.cpp +++ b/gfx/thebes/src/gfxOS2Surface.cpp @@ -43,28 +43,9 @@ * class gfxOS2Surface **********************************************************************/ -gfxOS2Surface::gfxOS2Surface(HPS aPS, const gfxIntSize& aSize) - : mOwnsPS(PR_FALSE), mHasWnd(PR_FALSE), mDC(nsnull), mPS(aPS), mBitmap(nsnull), mSize(aSize) -{ -#ifdef DEBUG_thebes_2 - printf("gfxOS2Surface[%#x]::gfxOS2Surface(HPS=%#x, Size=%dx%d)\n", (unsigned int)this, - (unsigned int)mPS, aSize.width, aSize.height); -#endif - - // create the cairo surface on the passed PS - cairo_surface_t *surf = cairo_os2_surface_create(mPS, mSize.width, mSize.height); -#ifdef DEBUG_thebes_2 - printf(" type(%#x)=%d (ID=%#x, h/w=%d/%d)\n", (unsigned int)surf, - cairo_surface_get_type(surf), (unsigned int)mPS, mSize.width, mSize.height); -#endif - // XXX for now uncomment the mark_dirty function, see bug 371505 - //cairo_surface_mark_dirty(surf); - Init(surf); -} - gfxOS2Surface::gfxOS2Surface(const gfxIntSize& aSize, gfxASurface::gfxImageFormat aImageFormat) - : mOwnsPS(PR_TRUE), mHasWnd(PR_FALSE), mSize(aSize) + : mHasWnd(PR_FALSE), mSize(aSize) { #ifdef DEBUG_thebes_2 printf("gfxOS2Surface[%#x]::gfxOS2Surface(Size=%dx%d, %d)\n", (unsigned int)this, @@ -105,13 +86,18 @@ gfxOS2Surface::gfxOS2Surface(const gfxIntSize& aSize, printf(" type(%#x)=%d (ID=%#x, h/w=%d/%d)\n", (unsigned int)surf, cairo_surface_get_type(surf), (unsigned int)mPS, mSize.width, mSize.height); #endif - // XXX for now uncomment the mark_dirty function, see bug 371505 - //cairo_surface_mark_dirty(surf); + // Normally, OS/2 cairo surfaces have to be forced to redraw completely + // by calling cairo_surface_mark_dirty(surf), but Mozilla paints them in + // full, so that is not necessary here. + + // manual refresh is done from nsWindow::OnPaint + cairo_os2_surface_set_manual_window_refresh(surf, 1); + Init(surf); } gfxOS2Surface::gfxOS2Surface(HWND aWnd) - : mOwnsPS(PR_TRUE), mHasWnd(PR_TRUE), mDC(nsnull), mBitmap(nsnull) + : mHasWnd(PR_TRUE), mDC(nsnull), mBitmap(nsnull) { #ifdef DEBUG_thebes_2 printf("gfxOS2Surface[%#x]::gfxOS2Surface(HWND=%#x)\n", (unsigned int)this, @@ -131,10 +117,15 @@ gfxOS2Surface::gfxOS2Surface(HWND aWnd) printf(" type(%#x)=%d (ID=%#x, h/w=%d/%d)\n", (unsigned int)surf, cairo_surface_get_type(surf), (unsigned int)mPS, mSize.width, mSize.height); #endif + // Normally, OS/2 cairo surfaces have to be forced to redraw completely + // by calling cairo_surface_mark_dirty(surf), but Mozilla paints them in + // full, so that is not necessary here. + // record the window handle in the cairo surface, so that refresh works cairo_os2_surface_set_hwnd(surf, aWnd); - // XXX for now uncomment the mark_dirty function, see bug 371505 - //cairo_surface_mark_dirty(surf); + // manual refresh is done from nsWindow::OnPaint + cairo_os2_surface_set_manual_window_refresh(surf, 1); + Init(surf); } @@ -149,7 +140,7 @@ gfxOS2Surface::~gfxOS2Surface() // hand were created on memory device contexts with the GPI functions, so // use those to clean up stuff. if (mHasWnd) { - if (mOwnsPS && mPS) { + if (mPS) { WinReleasePS(mPS); } } else { @@ -157,7 +148,7 @@ gfxOS2Surface::~gfxOS2Surface() GpiSetBitmap(mPS, NULL); GpiDeleteBitmap(mBitmap); } - if (mOwnsPS && mPS) { + if (mPS) { GpiDestroyPS(mPS); } if (mDC) { @@ -165,3 +156,25 @@ gfxOS2Surface::~gfxOS2Surface() } } } + +void gfxOS2Surface::Refresh(RECTL *aRect, HPS aPS) +{ +#ifdef DEBUG_thebes_2 + printf("gfxOS2Surface[%#x]::Refresh(x=%ld,%ld/y=%ld,%ld, HPS=%#x), mPS=%#x\n", + (unsigned int)this, + aRect->xLeft, aRect->xRight, aRect->yBottom, aRect->yTop, + (unsigned int)aPS, (unsigned int)mPS); +#endif + cairo_os2_surface_refresh_window(CairoSurface(), aPS, aRect); +} + +int gfxOS2Surface::Resize(const gfxIntSize& aSize) +{ +#ifdef DEBUG_thebes_2 + printf("gfxOS2Surface[%#x]::Resize(%dx%d)\n", (unsigned int)this, + aSize.width, aSize.height); +#endif + mSize = aSize; // record the new size + // hardcode mutex timeout to 50ms for now + return cairo_os2_surface_set_size(CairoSurface(), mSize.width, mSize.height, 50); +} diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index e133709a4fa6..56af5edb2852 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -1125,9 +1125,6 @@ NS_METHOD nsWindow::Destroy() CaptureRollupEvents(nsnull, PR_FALSE, PR_TRUE); } - // Destroy thebes surface now, XXX do we need this at all?? - mThebesSurface = nsnull; - if (mWnd) { HWND hwndBeingDestroyed = mFrameWnd ? mFrameWnd : mWnd; DEBUGFOCUS(Destroy); @@ -3165,16 +3162,7 @@ PRBool nsWindow::OnPaint() (PRInt32)mWnd); #endif // NS_DEBUG - // Thebes code version, adapted from windows/nsWindow.cpp - // XXX as a preliminary solution for repaint problems of cairo-os2 - // builds, repaint the whole window for each paint event - // see Bug 371505 - SWP swp; - WinQueryWindowPos(mWnd, &swp); - nsRefPtr targetSurface = - new gfxOS2Surface(hPS, gfxIntSize(swp.cx, swp.cy)); - //new gfxOS2Surface(hPS, gfxIntSize(rect.width, rect.height)); - nsRefPtr thebesContext = new gfxContext(targetSurface); + nsRefPtr thebesContext = new gfxContext(mThebesSurface); nsCOMPtr context; nsresult rv = mContext->CreateRenderingContextInstance(*getter_AddRefs(context)); @@ -3190,7 +3178,15 @@ PRBool nsWindow::OnPaint() } event.renderingContext = context; - rc = DispatchWindowEvent(&event, eventStatus); + // try to dispatch a few times, 10 should be more than enough, in tests + // we get something at the second try at the latest + for (int i = 0; i < 10; i++) { + rc = DispatchWindowEvent(&event, eventStatus); + if (rc) { + // this was handled, so we can stop trying + break; + } + } event.renderingContext = nsnull; if (rc) { @@ -3200,7 +3196,9 @@ PRBool nsWindow::OnPaint() thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE); thebesContext->Paint(); } + NS_RELEASE(event.widget); } // if (mEventCallback) + mThebesSurface->Refresh(&rcl, hPS); } // if (!WinIsRectEmpty(0, &rcl)) WinEndPaint(hPS); @@ -3243,6 +3241,16 @@ PRBool nsWindow::OnResize(PRInt32 aX, PRInt32 aY) { mBounds.width = aX; mBounds.height = aY; + + // resize the thebes surface to the new size + if (!mThebesSurface) { + // So we need to create a thebes surface for this window. + // (This is necessary for the first resize of a window.) + mThebesSurface = new gfxOS2Surface(mWnd); + } + + mThebesSurface->Resize(gfxIntSize(aX, aY)); + return DispatchResizeEvent( aX, aY); }