From 71c1cbc7f8011ac82ac195c6027e4094312d7403 Mon Sep 17 00:00:00 2001 From: Louis-Francis Ratté-Boulianne Date: Thu, 20 Nov 2014 22:07:12 -0500 Subject: vcl: Draw native widgets twice on black/white background to synthesize alpha Change-Id: Ic4c073360070a559855732d2de41ae9085d7d51b --- vcl/Package_opengl.mk | 1 + vcl/inc/opengl/x11/gdiimpl.hxx | 2 +- vcl/inc/openglgdiimpl.hxx | 6 + vcl/inc/unx/gtk/gtkgdi.hxx | 13 +- vcl/inc/unx/salgdi.h | 2 +- vcl/inc/unx/x11/x11gdiimpl.h | 2 +- vcl/opengl/diffTextureFragmentShader.glsl | 26 ++ vcl/opengl/gdiimpl.cxx | 47 +++ vcl/opengl/x11/gdiimpl.cxx | 38 +- vcl/unx/generic/gdi/gdiimpl.cxx | 3 +- vcl/unx/generic/gdi/gdiimpl.hxx | 2 +- vcl/unx/generic/gdi/salgdi2.cxx | 4 +- vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 626 +++++++++++++++++------------- vcl/unx/kde/salnativewidgets-kde.cxx | 2 +- 14 files changed, 481 insertions(+), 293 deletions(-) create mode 100644 vcl/opengl/diffTextureFragmentShader.glsl diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk index 4a4f30fa9d1d..d81c0ec4bd0c 100644 --- a/vcl/Package_opengl.mk +++ b/vcl/Package_opengl.mk @@ -12,6 +12,7 @@ $(eval $(call gb_Package_Package,vcl_opengl_shader,$(SRCDIR)/vcl/opengl)) $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ blendedTextureFragmentShader.glsl \ blendedTextureVertexShader.glsl \ + diffTextureFragmentShader.glsl \ convolutionFragmentShader.glsl \ linearGradientFragmentShader.glsl \ maskFragmentShader.glsl \ diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx index a2b863e3631d..d25d5d0212ca 100644 --- a/vcl/inc/opengl/x11/gdiimpl.hxx +++ b/vcl/inc/opengl/x11/gdiimpl.hxx @@ -35,7 +35,7 @@ public: virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE; void Init() SAL_OVERRIDE; bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE; - bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE; + bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE; }; #endif // INCLUDED_VCL_INC_OPENGL_X11_GDIIMPL_HXX diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 761b405dbb6d..5a7382b5e3fd 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -67,6 +67,10 @@ protected: GLuint mnTransformedMaskedSamplerUniform; GLuint mnTransformedMaskedMaskUniform; + GLuint mnDiffTextureProgram; + GLuint mnDiffTextureUniform; + GLuint mnDiffMaskUniform; + GLuint mnMaskedTextureProgram; GLuint mnMaskedSamplerUniform; GLuint mnMaskSamplerUniform; @@ -96,6 +100,7 @@ protected: bool CreateSolidProgram( void ); bool CreateTextureProgram( void ); bool CreateTransformedTextureProgram( void ); + bool CreateDiffTextureProgram( void ); bool CreateMaskedTextureProgram( void ); bool CreateBlendedTextureProgram( void ); bool CreateTransformedMaskedTextureProgram( void ); @@ -124,6 +129,7 @@ public: void DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false ); void DrawTransformedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY ); void DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false, bool pPremultiplied = false ); + void DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted = false ); void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry ); void DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, OpenGLTexture& rAlpha, const SalTwoRect& rPosAry ); void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry ); diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx index 05d763caaae8..9ce374d0db45 100644 --- a/vcl/inc/unx/gtk/gtkgdi.hxx +++ b/vcl/inc/unx/gtk/gtkgdi.hxx @@ -163,8 +163,17 @@ public: protected: typedef std::list< Rectangle > clipList; - GdkX11Pixmap* NWGetPixmapFromScreen( Rectangle srcRect ); - bool NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, Rectangle dstRect ); + GdkX11Pixmap* NWGetPixmapFromScreen( Rectangle srcRect, int nBgColor = 0 ); + bool NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask, Rectangle dstRect ); + + bool DoDrawNativeControl( GdkDrawable* pDrawable, + ControlType nType, + ControlPart nPart, + const Rectangle& aCtrlRect, + const clipList& aClip, + ControlState nState, + const ImplControlValue& aValue, + const OUString& rCaption ); bool NWPaintGTKArrow( GdkDrawable* gdkDrawable, ControlType nType, ControlPart nPart, const Rectangle& rControlRectangle, diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index 97f9d60c8dde..8ef42ba5cd12 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -284,7 +284,7 @@ public: bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ); // render a pixmap to the screen - bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ); + bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ); /* use to handle GraphicsExpose/NoExpose after XCopyArea & friends diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h index 8cd130d583a0..239d2174b45c 100644 --- a/vcl/inc/unx/x11/x11gdiimpl.h +++ b/vcl/inc/unx/x11/x11gdiimpl.h @@ -19,7 +19,7 @@ public: virtual void Init() = 0; virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0; - virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0; + virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0; }; #endif // INCLUDED_VCL_INC_UNX_X11_X11GDIIMPL_HXX diff --git a/vcl/opengl/diffTextureFragmentShader.glsl b/vcl/opengl/diffTextureFragmentShader.glsl new file mode 100644 index 000000000000..c0a982d4ee53 --- /dev/null +++ b/vcl/opengl/diffTextureFragmentShader.glsl @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/*precision mediump float;*/ +varying vec2 tex_coord; +uniform sampler2D texture; /* white background */ +uniform sampler2D mask; /* black background */ + +void main() { + float alpha; + vec4 texel0, texel1; + texel0 = texture2D(texture, tex_coord); + texel1 = texture2D(mask, tex_coord); + alpha = 1.0 - abs(texel0.r - texel1.r); + if(alpha > 0.0) + gl_FragColor = texel1 / alpha; + gl_FragColor.a = alpha; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 877db3b71ac6..54be610d558a 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -84,6 +84,9 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() , mnTransformedMaskedTransformUniform(0) , mnTransformedMaskedSamplerUniform(0) , mnTransformedMaskedMaskUniform(0) + , mnDiffTextureProgram(0) + , mnDiffTextureUniform(0) + , mnDiffMaskUniform(0) , mnMaskedTextureProgram(0) , mnMaskedSamplerUniform(0) , mnMaskSamplerUniform(0) @@ -373,6 +376,21 @@ bool OpenGLSalGraphicsImpl::CreateTransformedTextureProgram( void ) return true; } +bool OpenGLSalGraphicsImpl::CreateDiffTextureProgram( void ) +{ + mnDiffTextureProgram = OpenGLHelper::LoadShaders( "textureVertexShader", "diffTextureFragmentShader" ); + if( mnDiffTextureProgram == 0 ) + return false; + + glBindAttribLocation( mnDiffTextureProgram, GL_ATTRIB_POS, "position" ); + glBindAttribLocation( mnDiffTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" ); + mnDiffTextureUniform = glGetUniformLocation( mnDiffTextureProgram, "texture" ); + mnDiffMaskUniform = glGetUniformLocation( mnDiffTextureProgram, "mask" ); + + CHECK_GL_ERROR(); + return true; +} + bool OpenGLSalGraphicsImpl::CreateMaskedTextureProgram( void ) { mnMaskedTextureProgram = OpenGLHelper::LoadShaders( "maskedTextureVertexShader", "maskedTextureFragmentShader" ); @@ -835,6 +853,35 @@ void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const Sal glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); DrawTexture( rTexture, rPosAry, bInverted ); glDisable( GL_BLEND ); + CHECK_GL_ERROR(); +} + +void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted ) +{ + if( mnDiffTextureProgram == 0 ) + { + if( !CreateDiffTextureProgram() ) + return; + } + + glUseProgram( mnDiffTextureProgram ); + glUniform1i( mnDiffTextureUniform, 0 ); + glUniform1i( mnDiffMaskUniform, 1 ); + glActiveTexture( GL_TEXTURE0 ); + rTexture.Bind(); + glActiveTexture( GL_TEXTURE1 ); + rMask.Bind(); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + DrawTextureRect( rTexture, rPosAry, bInverted ); + glDisable( GL_BLEND ); + + glActiveTexture( GL_TEXTURE1 ); + rMask.Unbind(); + glActiveTexture( GL_TEXTURE0 ); + rTexture.Unbind(); + glUseProgram( 0 ); CHECK_GL_ERROR(); } diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx index 3385cd9da9fc..838be1bad12d 100644 --- a/vcl/opengl/x11/gdiimpl.cxx +++ b/vcl/opengl/x11/gdiimpl.cxx @@ -126,16 +126,17 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, return true; } -bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) +bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) { const int aAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, - GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None }; Display* pDisplay = mrParent.GetXDisplay(); GLXFBConfig pFbConfig; GLXPixmap pGlxPixmap; + GLXPixmap pGlxMask; SalTwoRect aPosAry; bool bInverted; @@ -148,25 +149,48 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, aPosAry.mnSrcWidth = aPosAry.mnDestWidth = pPixmap->GetWidth(); aPosAry.mnSrcHeight = aPosAry.mnDestHeight = pPixmap->GetHeight(); + PreDraw(); + //glClear( GL_COLOR_BUFFER_BIT ); + XSync( pDisplay, 0 ); pFbConfig = OpenGLHelper::GetPixmapFBConfig( pDisplay, bInverted ); pGlxPixmap = glXCreatePixmap( pDisplay, pFbConfig, pPixmap->GetPixmap(), aAttribs); + if( pMask != NULL ) + pGlxMask = glXCreatePixmap( pDisplay, pFbConfig, pMask->GetPixmap(), aAttribs); XSync( pDisplay, 0 ); - PreDraw(); + if( !pGlxPixmap ) + SAL_WARN( "vcl.opengl", "Couldn't create GLXPixmap" ); + + //TODO: lfrb: glXGetProc to get the functions OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false ); glActiveTexture( GL_TEXTURE0 ); aTexture.Bind(); - - //TODO: lfrb: glXGetProc to get the functions glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL ); + aTexture.Unbind(); + + if( pMask != NULL && pGlxMask ) + { + OpenGLTexture aMaskTexture( pMask->GetWidth(), pMask->GetHeight(), false ); + aMaskTexture.Bind(); + glXBindTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT, NULL ); + aMaskTexture.Unbind(); - DrawTexture( aTexture, aPosAry, bInverted ); + DrawTextureDiff( aTexture, aMaskTexture, aPosAry, !bInverted ); + + glXReleaseTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT ); + glXDestroyPixmap( pDisplay, pGlxMask ); + } + else + { + DrawTexture( aTexture, aPosAry, !bInverted ); + } + + CHECK_GL_ERROR(); glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT ); glXDestroyPixmap( pDisplay, pGlxPixmap ); - aTexture.Unbind(); PostDraw(); diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx index bcf8d0523abd..91c4db7b4221 100644 --- a/vcl/unx/generic/gdi/gdiimpl.cxx +++ b/vcl/unx/generic/gdi/gdiimpl.cxx @@ -185,8 +185,9 @@ bool X11SalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int n return true; } -bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) +bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* /*Mask*/, int nX, int nY ) { + // TODO: lfrb: Use the mask GC aFontGC = mrParent.GetFontGC(); // The GC can't be null, otherwise we'd have no clip region diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx index 20c995fa6a7e..675e2cdaed73 100644 --- a/vcl/unx/generic/gdi/gdiimpl.hxx +++ b/vcl/unx/generic/gdi/gdiimpl.hxx @@ -287,7 +287,7 @@ public: void Init() SAL_OVERRIDE; bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE; - bool RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE; + bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE; }; #endif diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx index b848d660447b..f1911b6e2fc5 100644 --- a/vcl/unx/generic/gdi/salgdi2.cxx +++ b/vcl/unx/generic/gdi/salgdi2.cxx @@ -89,11 +89,11 @@ bool X11SalGraphics::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) return rImpl.FillPixmapFromScreen( pPixmap, nX, nY ); } -bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, int nY ) +bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) { SAL_INFO( "vcl", "RenderPixmapToScreen" ); X11GraphicsImpl& rImpl = dynamic_cast(*mpImpl.get()); - return rImpl.RenderPixmapToScreen( pPixmap, nX, nY ); + return rImpl.RenderPixmapToScreen( pPixmap, pMask, nX, nY ); } extern "C" diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index 10cff1043e4e..46ec7b432056 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -50,6 +50,13 @@ const char* const tabPrelitDataName="libreoffice-tab-is-prelit"; bool GtkSalGraphics::bThemeChanged = true; bool GtkSalGraphics::bNeedPixmapPaint = false; +enum +{ + BG_NONE = 0, + BG_WHITE, + BG_BLACK +}; + GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow ) : X11SalGraphics(), m_pWindow( pWindow ), @@ -284,9 +291,12 @@ protected: GdkX11Pixmap::GdkX11Pixmap( int nWidth, int nHeight, int nDepth ) : X11Pixmap( nWidth, nHeight ) -, mnDepth( nDepth ) { mpGdkPixmap = gdk_pixmap_new( NULL, nWidth, nHeight, nDepth ); + mnDepth = gdk_drawable_get_depth( GDK_DRAWABLE( mpGdkPixmap ) ); + + GdkScreen *pScreen = gdk_drawable_get_screen( GDK_DRAWABLE( mpGdkPixmap ) ); + gdk_drawable_set_colormap( GDK_DRAWABLE( mpGdkPixmap ), gdk_screen_get_default_colormap( pScreen ) ); } GdkX11Pixmap::~GdkX11Pixmap() @@ -336,11 +346,12 @@ public: ControlState m_nState; Rectangle m_pixmapRect; GdkX11Pixmap* m_pixmap; + GdkX11Pixmap* m_mask; - NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0) {} + NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0), m_mask(0) {} ~NWPixmapCacheData() - { SetPixmap( NULL ); }; - void SetPixmap( GdkX11Pixmap* pPixmap ); + { SetPixmap( NULL, NULL ); }; + void SetPixmap( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ); }; class NWPixmapCache @@ -357,8 +368,8 @@ public: { delete [] pData; m_idx = 0; m_size = n; pData = new NWPixmapCacheData[m_size]; } int GetSize() const { return m_size; } - bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap ); - void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap ); + bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap** pPixmap, GdkX11Pixmap** pMask ); + void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ); void ThemeChanged(); }; @@ -375,12 +386,15 @@ public: // --- implementation --- -void NWPixmapCacheData::SetPixmap( GdkX11Pixmap* pPixmap ) +void NWPixmapCacheData::SetPixmap( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask ) { if( m_pixmap ) delete m_pixmap; + if( m_mask ) + delete m_mask; m_pixmap = pPixmap; + m_mask = pMask; } NWPixmapCache::NWPixmapCache( SalX11Screen nScreen ) @@ -403,10 +417,10 @@ void NWPixmapCache::ThemeChanged() // throw away cached pixmaps int i; for(i=0; imaNWFData.mbDDListBoxNoTextArea = true; + // use offscreen rendering when using OpenGL backend + if( OpenGLHelper::isVCLOpenGLEnabled() ) + GtkSalGraphics::bNeedPixmapPaint = true; + int nScreens = GetGtkSalData()->GetGtkDisplay()->GetXScreenCount(); gWidgetData = WidgetDataVector( nScreens ); for( int i = 0; i < nScreens; i++ ) @@ -530,10 +549,6 @@ void GtkData::initNWF( void ) if( pEnv && *pEnv ) GtkSalGraphics::bNeedPixmapPaint = true; - // use offscreen rendering when using OpenGL backend - if( OpenGLHelper::isVCLOpenGLEnabled() ) - GtkSalGraphics::bNeedPixmapPaint = true; - #if OSL_DEBUG_LEVEL > 1 std::fprintf( stderr, "GtkPlugin: using %s NWF\n", GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" ); @@ -864,8 +879,10 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, aClipRegion = aCtrlRect; clipList aClip; - GdkDrawable* gdkDrawable = GDK_DRAWABLE( GetGdkWindow() ); + int nPasses = 0; + GdkDrawable* gdkDrawable[2]; std::unique_ptr xPixmap; + std::unique_ptr xMask; Rectangle aPixmapRect; if( ( bNeedPixmapPaint ) && nType != CTRL_SCROLLBAR @@ -880,15 +897,22 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, // outside the rectangle, see e.g. checkbox aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ), Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) ); - xPixmap.reset(NWGetPixmapFromScreen(aPixmapRect)); - if (!xPixmap) + + xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) ); + xMask.reset( NWGetPixmapFromScreen( aPixmapRect, BG_BLACK ) ); + if( !xPixmap || !xMask ) return false; - gdkDrawable = xPixmap->GetGdkDrawable(); + nPasses = 2; + gdkDrawable[0] = xPixmap->GetGdkDrawable(); + gdkDrawable[1] = xMask->GetGdkDrawable(); + aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() ); aClip.push_back( aCtrlRect ); } else { + nPasses = 1; + gdkDrawable[0] = GDK_DRAWABLE( GetGdkWindow() ); RectangleVector aRectangles; aClipRegion.GetRegionRectangles(aRectangles); @@ -901,68 +925,95 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, } } - assert(gdkDrawable && "rhbz#1050162"); - if (gdkDrawable == 0) - return false; + bool returnVal = false; + SAL_INFO( "vcl.opengl", "Rendering with " << nPasses << " passe(s)" ); + + for( int i = 0; i < nPasses; ++i ) + { + assert(gdkDrawable[i] && "rhbz#1050162"); + if( gdkDrawable[i] == 0 ) + return false; - bool returnVal = false; + returnVal = DoDrawNativeControl( gdkDrawable[i], nType, nPart, aCtrlRect, aClip, + nState, aValue, rCaption ); + if( !returnVal ) + break; + } + + if( xPixmap ) + returnVal = NWRenderPixmapToScreen( xPixmap.get(), xMask.get(), aPixmapRect) && returnVal; + + return( returnVal ); +} + + +bool GtkSalGraphics::DoDrawNativeControl( + GdkDrawable* pDrawable, + ControlType nType, + ControlPart nPart, + const Rectangle& aCtrlRect, + const clipList& aClip, + ControlState nState, + const ImplControlValue& aValue, + const OUString& rCaption ) +{ if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKButton( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKButton( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKRadio( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKRadio( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKCheck( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKCheck( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_DRAW_BACKGROUND_HORZ) || (nPart==PART_DRAW_BACKGROUND_VERT)) ) { - returnVal = NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( ((nType==CTRL_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) || ((nType==CTRL_SPINBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) || ((nType==CTRL_COMBOBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) || ((nType==CTRL_LISTBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) ) { - returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKEditBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( ((nType==CTRL_MULTILINE_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) ) { - returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKEditBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( ((nType==CTRL_SPINBOX) || (nType==CTRL_SPINBUTTONS)) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_ALL_BUTTONS)) ) { - returnVal = NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType == CTRL_COMBOBOX) && ( (nPart==PART_ENTIRE_CONTROL) ||(nPart==PART_BUTTON_DOWN) ) ) { - returnVal = NWPaintGTKComboBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKComboBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( (nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || (nType==CTRL_TAB_BODY) ) { if ( nType == CTRL_TAB_BODY ) - returnVal = true; + return true; else - returnVal = NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); + return NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); } else if ( (nType==CTRL_LISTBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_WINDOW)) ) { - returnVal = NWPaintGTKListBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKListBox( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( nType== CTRL_TOOLBAR ) { - returnVal = NWPaintGTKToolbar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKToolbar( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if ( nType== CTRL_MENUBAR ) { - returnVal = NWPaintGTKMenubar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKMenubar( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_MENU_POPUP) && ( (nPart == PART_ENTIRE_CONTROL) @@ -974,55 +1025,50 @@ bool GtkSalGraphics::drawNativeControl( ControlType nType, ) ) { - returnVal = NWPaintGTKPopupMenu( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKPopupMenu( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_TOOLTIP) && (nPart == PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKTooltip( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKTooltip( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKProgress( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKProgress( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_LISTNODE) && (nPart == PART_ENTIRE_CONTROL) ) { - returnVal = NWPaintGTKListNode( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKListNode( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( (nType == CTRL_LISTNET) && (nPart == PART_ENTIRE_CONTROL) ) { // don't actually draw anything; gtk treeviews do not draw lines - returnVal = TRUE; + return TRUE; } else if( nType == CTRL_SLIDER ) { - returnVal = NWPaintGTKSlider( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKSlider( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( nType == CTRL_WINDOW_BACKGROUND ) { - returnVal = NWPaintGTKWindowBackground( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKWindowBackground( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if( nType == CTRL_FIXEDLINE ) { - returnVal = NWPaintGTKFixedLine( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKFixedLine( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } else if(nType==CTRL_FRAME) { - returnVal = NWPaintGTKFrame( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); + return NWPaintGTKFrame( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); } else if(nType==CTRL_LISTHEADER) { if(nPart == PART_BUTTON) - returnVal = NWPaintGTKListHeader( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKListHeader( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); else if(nPart == PART_ARROW) - returnVal = NWPaintGTKArrow( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); + return NWPaintGTKArrow( pDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); } - if( xPixmap ) - { - returnVal = NWRenderPixmapToScreen(xPixmap.get(), aPixmapRect) && returnVal; - } - - return( returnVal ); + return false; } /* @@ -2114,7 +2160,7 @@ bool GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart, arrowRect.GetWidth(), arrowRect.GetHeight() ); } - bool bRet = NWRenderPixmapToScreen( pixmap, pixmapRect ); + bool bRet = NWRenderPixmapToScreen( pixmap, NULL, pixmapRect ); delete pixmap; return bRet; @@ -2341,8 +2387,6 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart, const ImplControlValue& aValue, const OUString& rCaption ) { - GdkX11Pixmap * pixmap; - GdkPixmap * gdkPixmap; Rectangle pixmapRect; GtkStateType stateType; GtkShadowType shadowType; @@ -2383,56 +2427,59 @@ bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart, else pixmapRect = rControlRectangle; - pixmap = NWGetPixmapFromScreen( pixmapRect ); - if ( !pixmap ) + std::unique_ptr pixmap( NWGetPixmapFromScreen( pixmapRect, BG_WHITE ) ); + std::unique_ptr mask( NWGetPixmapFromScreen( pixmapRect, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - gdkPixmap = pixmap->GetGdkPixmap(); - // First render background - gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base", - -pixmapRect.Left(), - -pixmapRect.Top(), - pixmapRect.Right(), - pixmapRect.Bottom() ); + for( int i = 0; i < 2; ++i ) + { + GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() + : mask->GetGdkPixmap(); - upBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); - downBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); + // First render background + gtk_paint_flat_box(m_pWindow->style,gdkPixmap,GTK_STATE_NORMAL,GTK_SHADOW_NONE,NULL,m_pWindow,"base", + -pixmapRect.Left(), + -pixmapRect.Top(), + pixmapRect.Right(), + pixmapRect.Bottom() ); - if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) ) - { - // Draw an edit field for SpinBoxes and ComboBoxes - Rectangle aEditBoxRect( pixmapRect ); - aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) ); - if( Application::GetSettings().GetLayoutRTL() ) - aEditBoxRect.setX( upBtnRect.GetWidth() ); - else - aEditBoxRect.setX( 0 ); - aEditBoxRect.setY( 0 ); + upBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); + downBtnRect = NWGetSpinButtonRect( m_nXScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); - NWPaintOneEditBox( m_nXScreen, gdkPixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption ); - } + if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) ) + { + // Draw an edit field for SpinBoxes and ComboBoxes + Rectangle aEditBoxRect( pixmapRect ); + aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - upBtnRect.GetWidth(), aEditBoxRect.GetHeight() ) ); + if( Application::GetSettings().GetLayoutRTL() ) + aEditBoxRect.setX( upBtnRect.GetWidth() ); + else + aEditBoxRect.setX( 0 ); + aEditBoxRect.setY( 0 ); - NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType ); - gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL ); + NWPaintOneEditBox( m_nXScreen, gdkPixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption ); + } - if ( shadowType != GTK_SHADOW_NONE ) - { - Rectangle shadowRect( upBtnRect ); + NWSetWidgetState( gWidgetData[m_nXScreen].gSpinButtonWidget, nState, stateType ); + gtk_widget_style_get( gWidgetData[m_nXScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL ); - shadowRect.Union( downBtnRect ); - gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, NULL, - gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton", - (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()), - shadowRect.GetWidth(), shadowRect.GetHeight() ); - } + if ( shadowType != GTK_SHADOW_NONE ) + { + Rectangle shadowRect( upBtnRect ); - NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); - NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); + shadowRect.Union( downBtnRect ); + gtk_paint_box( gWidgetData[m_nXScreen].gSpinButtonWidget->style, gdkPixmap, GTK_STATE_NORMAL, shadowType, NULL, + gWidgetData[m_nXScreen].gSpinButtonWidget, "spinbutton", + (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()), + shadowRect.GetWidth(), shadowRect.GetHeight() ); + } - bool bRet = NWRenderPixmapToScreen( pixmap, pixmapRect ); - delete pixmap; + NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); + NWPaintOneSpinButton( m_nXScreen, gdkPixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); + } - return bRet; + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), pixmapRect ); } static Rectangle NWGetSpinButtonRect( SalX11Screen nScreen, @@ -2667,7 +2714,7 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart, { OSL_ASSERT( nType != CTRL_TAB_ITEM || aValue.getType() == CTRL_TAB_ITEM ); GdkX11Pixmap * pixmap; - GdkPixmap * gdkPixmap; + GdkX11Pixmap * mask; Rectangle pixmapRect; Rectangle tabRect; GtkStateType stateType; @@ -2730,83 +2777,88 @@ bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart, if( nType == CTRL_TAB_ITEM ) { - if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) ) - return NWRenderPixmapToScreen( pixmap, pixmapRect ); + if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap, &mask ) ) + return NWRenderPixmapToScreen( pixmap, mask, pixmapRect ); } else { - if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) ) - return NWRenderPixmapToScreen( pixmap, pixmapRect ); + if( aCachePage.Find( nType, nState, pixmapRect, &pixmap, &mask ) ) + return NWRenderPixmapToScreen( pixmap, mask, pixmapRect ); } - pixmap = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), - GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth() ); - gdkPixmap = pixmap->GetGdkPixmap(); + int nDepth = GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth(); + pixmap = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), nDepth ); + mask = new GdkX11Pixmap( pixmapRect.GetWidth(), pixmapRect.GetHeight(), nDepth ); GdkRectangle paintRect; paintRect.x = paintRect.y = 0; paintRect.width = pixmapRect.GetWidth(); paintRect.height = pixmapRect.GetHeight(); - gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", - -rControlRectangle.Left(), - -rControlRectangle.Top(), - pixmapRect.GetWidth()+rControlRectangle.Left(), - pixmapRect.GetHeight()+rControlRectangle.Top()); - - NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType ); - - switch( nType ) + for( int i = 0; i < 2; ++i ) { - case CTRL_TAB_BODY: - break; + GdkPixmap* gdkPixmap = (i == 0) ? pixmap->GetGdkPixmap() : mask->GetGdkPixmap(); - case CTRL_TAB_PANE: - gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, - (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 ); - break; + gtk_paint_flat_box( m_pWindow->style, gdkPixmap, GTK_STATE_NORMAL, + GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", + -rControlRectangle.Left(), + -rControlRectangle.Top(), + pixmapRect.GetWidth()+rControlRectangle.Left(), + pixmapRect.GetHeight()+rControlRectangle.Top()); - case CTRL_TAB_ITEM: + NWSetWidgetState( gWidgetData[m_nXScreen].gNotebookWidget, nState, stateType ); + + switch( nType ) { - stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE; + case CTRL_TAB_BODY: + break; - // First draw the background - gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, - GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", - -rControlRectangle.Left(), - -rControlRectangle.Top(), - pixmapRect.GetWidth()+rControlRectangle.Left(), - pixmapRect.GetHeight()+rControlRectangle.Top()); + case CTRL_TAB_PANE: + gtk_paint_box_gap( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, + (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 ); + break; - // Now the tab itself - if( nState & CTRL_STATE_ROLLOVER ) - g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast(TRUE)); + case CTRL_TAB_ITEM: + { + stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE; - gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, - (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()), - tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM ); + // First draw the background + gtk_paint_flat_box(gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, + GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", + -rControlRectangle.Left(), + -rControlRectangle.Top(), + pixmapRect.GetWidth()+rControlRectangle.Left(), + pixmapRect.GetHeight()+rControlRectangle.Top()); - g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName); + // Now the tab itself + if( nState & CTRL_STATE_ROLLOVER ) + g_object_set_data(G_OBJECT(gdkPixmap),tabPrelitDataName,reinterpret_cast(TRUE)); - if ( nState & CTRL_STATE_SELECTED ) - { - gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow, - "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 ); + gtk_paint_extension( gWidgetData[m_nXScreen].gNotebookWidget->style, gdkPixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nXScreen].gNotebookWidget, + (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()), + tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM ); + + g_object_steal_data(G_OBJECT(gdkPixmap),tabPrelitDataName); + + if ( nState & CTRL_STATE_SELECTED ) + { + gtk_paint_flat_box( m_pWindow->style, gdkPixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow, + "base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 ); + } + break; } - break; - } - default: - break; + default: + break; + } } // cache data if( nType == CTRL_TAB_ITEM ) - aCacheItems.Fill( nType, nState, pixmapRect, pixmap ); + aCacheItems.Fill( nType, nState, pixmapRect, pixmap, mask ); else - aCachePage.Fill( nType, nState, pixmapRect, pixmap ); + aCachePage.Fill( nType, nState, pixmapRect, pixmap, mask ); - bool bSuccess = NWRenderPixmapToScreen( pixmap, pixmapRect ); + bool bSuccess = NWRenderPixmapToScreen( pixmap, mask, pixmapRect ); return bSuccess; } @@ -3382,24 +3434,26 @@ bool GtkSalGraphics::NWPaintGTKListNode( break; } - GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( aRect ); - if( ! pixmap ) + std::unique_ptr pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) ); + std::unique_ptr mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable(); - gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style, - pixDrawable, - stateType, - NULL, - gWidgetData[m_nXScreen].gTreeView, - "treeview", - w/2, h/2, - eStyle ); - - bool bRet = NWRenderPixmapToScreen( pixmap, aRect ); - delete pixmap; + for( int i = 0; i < 2; ++i ) + { + GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable() + : mask->GetGdkDrawable(); + gtk_paint_expander( gWidgetData[m_nXScreen].gTreeView->style, + pixDrawable, + stateType, + NULL, + gWidgetData[m_nXScreen].gTreeView, + "treeview", + w/2, h/2, + eStyle ); + } - return bRet; + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), aRect ); } bool GtkSalGraphics::NWPaintGTKProgress( @@ -3418,57 +3472,60 @@ bool GtkSalGraphics::NWPaintGTKProgress( long nProgressWidth = rValue.getNumericVal(); - GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) ); - if( ! pixmap ) + Rectangle aRect( Point( 0, 0 ), Size( w, h ) ); + std::unique_ptr pixmap( NWGetPixmapFromScreen( aRect, BG_WHITE ) ); + std::unique_ptr mask( NWGetPixmapFromScreen( aRect, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable(); - - // paint background - gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable, - GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", - -rControlRectangle.Left(),-rControlRectangle.Top(), - rControlRectangle.Left()+w,rControlRectangle.Top()+h); - - gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style, - pixDrawable, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, - NULL, - gWidgetData[m_nXScreen].gProgressBar, - "trough", - 0, 0, w, h ); - if( nProgressWidth > 0 ) - { - // paint progress - if( Application::GetSettings().GetLayoutRTL() ) - { - gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, - pixDrawable, - GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - NULL, - gWidgetData[m_nXScreen].gProgressBar, - "bar", - w-nProgressWidth, 0, nProgressWidth, h - ); - } - else + for( int i = 0; i < 2; ++i ) + { + GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable() + : mask->GetGdkDrawable(); + + // paint background + gtk_paint_flat_box(gWidgetData[m_nXScreen].gProgressBar->style, pixDrawable, + GTK_STATE_NORMAL, GTK_SHADOW_NONE, NULL, m_pWindow, "base", + -rControlRectangle.Left(),-rControlRectangle.Top(), + rControlRectangle.Left()+w,rControlRectangle.Top()+h); + + gtk_paint_flat_box( gWidgetData[m_nXScreen].gProgressBar->style, + pixDrawable, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + NULL, + gWidgetData[m_nXScreen].gProgressBar, + "trough", + 0, 0, w, h ); + if( nProgressWidth > 0 ) { - gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, - pixDrawable, - GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - NULL, - gWidgetData[m_nXScreen].gProgressBar, - "bar", - 0, 0, nProgressWidth, h - ); + // paint progress + if( Application::GetSettings().GetLayoutRTL() ) + { + gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, + pixDrawable, + GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, + NULL, + gWidgetData[m_nXScreen].gProgressBar, + "bar", + w-nProgressWidth, 0, nProgressWidth, h + ); + } + else + { + gtk_paint_box( gWidgetData[m_nXScreen].gProgressBar->style, + pixDrawable, + GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, + NULL, + gWidgetData[m_nXScreen].gProgressBar, + "bar", + 0, 0, nProgressWidth, h + ); + } } } - bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); - delete pixmap; - - return bRet; + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), rControlRectangle ); } bool GtkSalGraphics::NWPaintGTKSlider( @@ -3488,75 +3545,78 @@ bool GtkSalGraphics::NWPaintGTKSlider( const SliderValue* pVal = static_cast(&rValue); - GdkX11Pixmap* pixmap = NWGetPixmapFromScreen( rControlRectangle ); - if( ! pixmap ) + std::unique_ptr pixmap( NWGetPixmapFromScreen( rControlRectangle, BG_WHITE ) ); + std::unique_ptr mask( NWGetPixmapFromScreen( rControlRectangle, BG_BLACK ) ); + if( !pixmap || !mask ) return false; - GdkDrawable* const &pixDrawable = pixmap->GetGdkDrawable(); - GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA) - ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale) - : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale); - const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale"; - GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; - gint slider_width = 10; - gint slider_length = 10; - gint trough_border = 0; - gtk_widget_style_get( pWidget, - "slider-width", &slider_width, - "slider-length", &slider_length, - "trough-border", &trough_border, - NULL); - - GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; - if( nPart == PART_TRACK_HORZ_AREA ) - { - gtk_paint_box( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_IN, - NULL, - pWidget, - "trough", - 0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border); - gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); - gtk_paint_slider( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_OUT, - NULL, - pWidget, - pDetail, - x, (h-slider_width)/2, - slider_length, slider_width, - eOri ); - } - else + for( int i = 0; i < 2; ++i ) { - gtk_paint_box( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_IN, - NULL, - pWidget, - "trough", - (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h); - gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); - gtk_paint_slider( pWidget->style, - pixDrawable, - eState, - GTK_SHADOW_OUT, - NULL, - pWidget, - pDetail, - (w-slider_width)/2, y, - slider_width, slider_length, - eOri ); - } - - bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); - delete pixmap; + GdkDrawable* const &pixDrawable = (i == 0) ? pixmap->GetGdkDrawable() + : mask->GetGdkDrawable(); - return bRet; + GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA) + ? GTK_WIDGET(gWidgetData[m_nXScreen].gHScale) + : GTK_WIDGET(gWidgetData[m_nXScreen].gVScale); + const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale"; + GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; + gint slider_width = 10; + gint slider_length = 10; + gint trough_border = 0; + gtk_widget_style_get( pWidget, + "slider-width", &slider_width, + "slider-length", &slider_length, + "trough-border", &trough_border, + NULL); + + GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; + if( nPart == PART_TRACK_HORZ_AREA ) + { + gtk_paint_box( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_IN, + NULL, + pWidget, + "trough", + 0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border); + gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); + gtk_paint_slider( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_OUT, + NULL, + pWidget, + pDetail, + x, (h-slider_width)/2, + slider_length, slider_width, + eOri ); + } + else + { + gtk_paint_box( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_IN, + NULL, + pWidget, + "trough", + (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h); + gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); + gtk_paint_slider( pWidget->style, + pixDrawable, + eState, + GTK_SHADOW_OUT, + NULL, + pWidget, + pDetail, + (w-slider_width)/2, y, + slider_width, slider_length, + eOri ); + } + } + + return NWRenderPixmapToScreen( pixmap.get(), mask.get(), rControlRectangle ); } static int getFrameWidth(GtkWidget* widget) @@ -4128,12 +4188,26 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings ) * Create a GdkPixmap filled with the contents of an area of an Xlib window ************************************************************************/ -GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect ) +GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect, int nBgColor ) { GdkX11Pixmap* pPixmap; + int nDepth = GetGenericData()->GetSalDisplay()->GetVisual( m_nXScreen ).GetDepth(); +; + + pPixmap = new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), nDepth ); + + if( nBgColor != BG_NONE ) + { + cairo_t *cr = gdk_cairo_create( pPixmap->GetGdkDrawable() ); + if( nBgColor == BG_BLACK) + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); + else + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy(cr); + } - pPixmap = new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), 24 ); - FillPixmapFromScreen( pPixmap, srcRect.Left(), srcRect.Top() ); return pPixmap; } @@ -4141,9 +4215,9 @@ GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect ) * Copy an alpha pixmap to screen using a gc with clipping ************************************************************************/ -bool GtkSalGraphics::NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, Rectangle dstRect ) +bool GtkSalGraphics::NWRenderPixmapToScreen( GdkX11Pixmap* pPixmap, GdkX11Pixmap* pMask, Rectangle dstRect ) { - return RenderPixmapToScreen( pPixmap, dstRect.Left(), dstRect.Top() ); + return RenderPixmapToScreen( pPixmap, pMask, dstRect.Left(), dstRect.Top() ); } /************************************************************************ diff --git a/vcl/unx/kde/salnativewidgets-kde.cxx b/vcl/unx/kde/salnativewidgets-kde.cxx index b849c5377f7b..0a7fca90227e 100644 --- a/vcl/unx/kde/salnativewidgets-kde.cxx +++ b/vcl/unx/kde/salnativewidgets-kde.cxx @@ -853,7 +853,7 @@ bool WidgetPainter::drawStyledWidget( QWidget *pWidget, return false; // Bitblt it to the screen - pGraphics->RenderPixmapToScreen( &xPixmap, qWidgetPos.x(), qWidgetPos.y() ); + pGraphics->RenderPixmapToScreen( &xPixmap, NULL, qWidgetPos.x(), qWidgetPos.y() ); // Restore widget's position pWidget->move( qWidgetPos ); -- cgit v1.2.3