[Libreoffice-commits] .: Branch 'libreoffice-3-4' - 7 commits - vcl/unx

Lubos Lunak llunak at kemper.freedesktop.org
Fri Apr 8 13:01:39 PDT 2011


 vcl/unx/kde4/KDESalFrame.cxx    |    1 
 vcl/unx/kde4/KDESalGraphics.cxx |  235 +++++++++++++++++++++++++---------------
 vcl/unx/kde4/KDESalGraphics.hxx |    1 
 3 files changed, 152 insertions(+), 85 deletions(-)

New commits:
commit 3638e82b039c071dbc3908a8977cb909ef71c07b
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 21:55:54 2011 +0200

    better fix for KDE4 popup painting covering popup frame

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index 8e9aad8..7fefe8f 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -264,6 +264,9 @@ sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
                                         const ImplControlValue& value,
                                         const OUString& )
 {
+    if( lastPopupRect.isValid() && ( type != CTRL_MENU_POPUP || part != PART_MENU_ITEM ))
+        lastPopupRect = QRect();
+
     // put not implemented types here
     if (type == CTRL_SPINBUTTONS)
     {
@@ -323,15 +326,21 @@ sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
     }
     else if (type == CTRL_MENU_POPUP)
     {
+        OSL_ASSERT( part == PART_MENU_ITEM ? lastPopupRect.isValid() : !lastPopupRect.isValid());
         if( part == PART_MENU_ITEM )
         {
             QStyleOptionMenuItem option;
-            // this is painted after popup frame, so highlight would be painted
-            // over popup border
-            int fw = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
-            clipRegion = new QRegion( widgetRect.adjusted( fw, fw, -fw, -fw ));
             draw( QStyle::CE_MenuItem, &option, m_image,
                   vclStateValue2StateFlag(nControlState, value) );
+            // HACK: LO core first paints the entire popup and only then it paints menu items,
+            // but QMenu::paintEvent() paints popup frame after all items. That means highlighted
+            // items here would paint the highlight over the frame border. Since calls to PART_MENU_ITEM
+            // are always preceded by calls to PART_ENTIRE_CONTROL, just remember the size for the whole
+            // popup (otherwise not possible to get here) and draw the border afterwards.
+            QRect framerect( lastPopupRect.topLeft() - widgetRect.topLeft(),
+                widgetRect.size().expandedTo( lastPopupRect.size()));
+            QStyleOptionFrame frame;
+            draw( QStyle::PE_FrameMenu, &frame, m_image, vclStateValue2StateFlag( nControlState, value ), framerect );
         }
         else if( part == PART_MENU_SEPARATOR )
         {
@@ -346,7 +355,7 @@ sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
             QPoint center = rect.center();
             rect.setHeight( size.height());
             rect.moveCenter( center );
-            // don't paint over popup frame border
+            // don't paint over popup frame border (like the hack above, but here it can be simpler)
             int fw = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
             clipRegion = new QRegion( rect.translated( widgetRect.topLeft()).adjusted( fw, 0, -fw, 0 ));
             draw( QStyle::CE_MenuItem, &option, m_image,
@@ -375,8 +384,8 @@ sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
             QStyleOptionMenuItem option;
             draw( QStyle::PE_PanelMenu, &option, m_image, vclStateValue2StateFlag( nControlState, value ));
             QStyleOptionFrame frame;
-            frame.lineWidth = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
             draw( QStyle::PE_FrameMenu, &frame, m_image, vclStateValue2StateFlag( nControlState, value ));
+            lastPopupRect = widgetRect;
         }
         else
             returnVal = false;
diff --git a/vcl/unx/kde4/KDESalGraphics.hxx b/vcl/unx/kde4/KDESalGraphics.hxx
index 55697e4..e1ec6ba 100644
--- a/vcl/unx/kde4/KDESalGraphics.hxx
+++ b/vcl/unx/kde4/KDESalGraphics.hxx
@@ -40,6 +40,7 @@
 class KDESalGraphics : public X11SalGraphics
 {
     QImage* m_image;
+    QRect lastPopupRect;
 
     public:
         KDESalGraphics();
commit b2d1508fd2dfd22113b343914cb382be092fd628
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 21:43:11 2011 +0200

    rework KDE4 popup menu drawing to avoid various glitches

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index e0f736b..8e9aad8 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -160,10 +160,10 @@ sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType type, ControlPart
 /// helper drawing methods
 namespace 
 {
-    void draw( QStyle::ControlElement element, QStyleOption* option, QImage* image, QStyle::State state )
+    void draw( QStyle::ControlElement element, QStyleOption* option, QImage* image, QStyle::State state, QRect rect = QRect())
     {
         option->state |= state;
-        option->rect = image->rect();
+        option->rect = !rect.isNull() ? rect : image->rect();
         
         QPainter painter(image);
         kapp->style()->drawControl(element, option, &painter);
@@ -323,43 +323,63 @@ sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
     }
     else if (type == CTRL_MENU_POPUP)
     {
-        if (part == PART_MENU_ITEM)
+        if( part == PART_MENU_ITEM )
         {
             QStyleOptionMenuItem option;
-            draw( QStyle::CE_MenuItem, &option, m_image, 
+            // this is painted after popup frame, so highlight would be painted
+            // over popup border
+            int fw = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
+            clipRegion = new QRegion( widgetRect.adjusted( fw, fw, -fw, -fw ));
+            draw( QStyle::CE_MenuItem, &option, m_image,
                   vclStateValue2StateFlag(nControlState, value) );
         }
-        else if (part == PART_MENU_ITEM_CHECK_MARK)
+        else if( part == PART_MENU_SEPARATOR )
         {
-            m_image->fill(Qt::transparent);
-            if(nControlState & CTRL_STATE_PRESSED) // at least Oxygen paints always as checked
-            {
-                QStyleOptionButton option;
-                draw( QStyle::PE_IndicatorMenuCheckMark, &option, m_image,
-                      vclStateValue2StateFlag(nControlState, value));
-            }
+            QStyleOptionMenuItem option;
+            option.menuItemType = QStyleOptionMenuItem::Separator;
+            // Painting the whole menu item area results in different background
+            // with at least Plastique style, so clip only to the separator itself
+            // (QSize( 2, 2 ) is hardcoded in Qt)
+            option.rect = m_image->rect();
+            QSize size = kapp->style()->sizeFromContents( QStyle::CT_MenuItem, &option, QSize( 2, 2 ));
+            QRect rect = m_image->rect();
+            QPoint center = rect.center();
+            rect.setHeight( size.height());
+            rect.moveCenter( center );
+            // don't paint over popup frame border
+            int fw = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
+            clipRegion = new QRegion( rect.translated( widgetRect.topLeft()).adjusted( fw, 0, -fw, 0 ));
+            draw( QStyle::CE_MenuItem, &option, m_image,
+                  vclStateValue2StateFlag(nControlState, value), rect );
         }
-        else if (part == PART_MENU_ITEM_RADIO_MARK)
+        else if( part == PART_MENU_ITEM_CHECK_MARK || part == PART_MENU_ITEM_RADIO_MARK )
         {
-            m_image->fill(Qt::transparent);
-            QStyleOptionButton option;
-            // we get always passed BUTTONVALUE_DONTKNOW in 'value', and the checked
-            // state is actually CTRL_STATE_PRESSED
-            QStyle::State set = ( nControlState & CTRL_STATE_PRESSED ) ? QStyle::State_On : QStyle::State_Off;
-            draw( QStyle::PE_IndicatorRadioButton, &option, m_image,
-                  vclStateValue2StateFlag(nControlState, value) | set );
+            QStyleOptionMenuItem option;
+            option.checkType = ( part == PART_MENU_ITEM_CHECK_MARK )
+                ? QStyleOptionMenuItem::NonExclusive : QStyleOptionMenuItem::Exclusive;
+            option.checked = ( nControlState & CTRL_STATE_PRESSED );
+            // widgetRect is now the rectangle for the checkbox/radiobutton itself, but Qt
+            // paints the whole menu item, so translate position (and it'll be clipped);
+            // it is also necessary to fill the background transparently first, as this
+            // is painted after menuitem highlight, otherwise there would be a grey area
+            const MenupopupValue* menuVal = static_cast<const MenupopupValue*>(&value);
+            QRect menuItemRect( region2QRect( menuVal->maItemRect ));
+            QRect rect( menuItemRect.topLeft() - widgetRect.topLeft(),
+                widgetRect.size().expandedTo( menuItemRect.size()));
+            m_image->fill( Qt::transparent );
+            draw( QStyle::CE_MenuItem, &option, m_image,
+                  vclStateValue2StateFlag(nControlState, value), rect );
         }
-        else
+        else if( part == PART_ENTIRE_CONTROL )
         {
-            #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
-            QStyleOptionFrameV3 option;
-            option.frameShape = QFrame::StyledPanel;
-            #else
-            QStyleOptionFrameV2 option;
-            #endif
-            draw( QStyle::PE_FrameMenu, &option, m_image, 
-                  vclStateValue2StateFlag(nControlState, value) );
+            QStyleOptionMenuItem option;
+            draw( QStyle::PE_PanelMenu, &option, m_image, vclStateValue2StateFlag( nControlState, value ));
+            QStyleOptionFrame frame;
+            frame.lineWidth = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
+            draw( QStyle::PE_FrameMenu, &frame, m_image, vclStateValue2StateFlag( nControlState, value ));
         }
+        else
+            returnVal = false;
     }
     else if ( (type == CTRL_TOOLBAR) && (part == PART_BUTTON) )
     {
commit c15593ad44e736f55b26f5c117b07fd86be65178
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 18:19:19 2011 +0200

    kde4 size of menu radio/checkboxes

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index 92af333..e0f736b 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -810,16 +810,8 @@ sal_Bool KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart p
             break;
         }
         case CTRL_MENU_POPUP:
-            //just limit the widget of the menu items
-            //OO isn't very flexible in all reguards with the menu
-            //so we do the best we can
-            if (part == PART_MENU_ITEM_CHECK_MARK)
-            {
-                contentRect.setWidth(contentRect.height());
-                retVal = true;
-            }
-            else if (part == PART_MENU_ITEM_RADIO_MARK)
-            {
+            if (part == PART_MENU_ITEM_CHECK_MARK || part == PART_MENU_ITEM_RADIO_MARK)
+            { // core uses this to detect radio/checkbox sizes, so just set a square
                 contentRect.setWidth(contentRect.height());
                 retVal = true;
             }
commit 9a389766e67f8832381238d6c6f3dbb26ffdd660
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 17:55:14 2011 +0200

    implement CTRL_PROGRESS for KDE4

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index ebe939a..92af333 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -146,12 +146,13 @@ sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType type, ControlPart
     if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA) )
         return true;
     
+    if ( (type == CTRL_PROGRESS)    && (part == PART_ENTIRE_CONTROL) ) return true;
+
     return false;
     
     if ( (type == CTRL_TAB_ITEM) && (part == PART_ENTIRE_CONTROL) ) return true;
     if ( (type == CTRL_TAB_PANE) && (part == PART_ENTIRE_CONTROL) ) return true;
     // no CTRL_TAB_BODY for KDE
-    if ( (type == CTRL_PROGRESS)    && (part == PART_ENTIRE_CONTROL) ) return true;
         
     return false;
 }
@@ -568,6 +569,18 @@ sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
         
         draw( QStyle::CC_Slider, &option, m_image, vclStateValue2StateFlag(nControlState, value) );
     }
+    else if( type == CTRL_PROGRESS && part == PART_ENTIRE_CONTROL )
+    {
+        QStyleOptionProgressBarV2 option;
+        option.minimum = 0;
+        option.maximum = widgetRect.width();
+        option.progress = value.getNumericVal();
+        option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
+        option.state = vclStateValue2StateFlag( nControlState, value );
+
+        draw( QStyle::CE_ProgressBar, &option, m_image,
+              vclStateValue2StateFlag(nControlState, value) );
+    }
     else
     {
         returnVal = false;
commit f38caab61313a7a18bf5c9215273f4c15c8ef68c
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 17:17:15 2011 +0200

    define minimal scrollbar slider size for KDE4

diff --git a/vcl/unx/kde4/KDESalFrame.cxx b/vcl/unx/kde4/KDESalFrame.cxx
index 3d34957..ab6bf1a 100644
--- a/vcl/unx/kde4/KDESalFrame.cxx
+++ b/vcl/unx/kde4/KDESalFrame.cxx
@@ -345,6 +345,7 @@ void KDESalFrame::UpdateSettings( AllSettings& rSettings )
     
     // Scroll bar size
     style.SetScrollBarSize( kapp->style()->pixelMetric( QStyle::PM_ScrollBarExtent ) );
+    style.SetMinThumbSize( kapp->style()->pixelMetric( QStyle::PM_ScrollBarSliderMin ));
     
     rSettings.SetStyleSettings( style );
 }
commit 5a27f468b350f81becd088b565c3bc8ed3a6d824
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 16:30:34 2011 +0200

    provide scrollbar track area, to fix detection of KDE4 scrollbar areas

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index d3f8965..ebe939a 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -862,6 +862,35 @@ sal_Bool KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart p
             }
             break;
         }
+        case CTRL_SCROLLBAR:
+        {
+            // core can't handle 3-button scrollbars well, so we fix that in hitTestNativeControl(),
+            // for the rest also provide the track area (i.e. area not taken by buttons)
+            if( part == PART_TRACK_VERT_AREA || part == PART_TRACK_HORZ_AREA )
+            {
+                QStyleOptionSlider option;
+                OSL_ASSERT( val.getType() == CTRL_SCROLLBAR );
+                const ScrollbarValue* sbVal = static_cast<const ScrollbarValue *>(&val);
+                option.orientation = ( part == PART_TRACK_HORZ_AREA ) ? Qt::Horizontal : Qt::Vertical;
+                option.minimum = sbVal->mnMin;
+                option.maximum = sbVal->mnMax;
+                option.sliderValue = sbVal->mnCur;
+                option.sliderPosition = sbVal->mnCur;
+                option.pageStep = sbVal->mnVisibleSize;
+                // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
+                // widget and screen coordinates the same. QStyle functions should use screen
+                // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
+                // and sometimes uses widget coordinates.
+                QRect rect = contentRect;
+                rect.moveTo( 0, 0 );
+                option.rect = rect;
+                rect = kapp->style()->subControlRect( QStyle::CC_ScrollBar, &option,
+                    QStyle::SC_ScrollBarGroove );
+                rect.translate( contentRect.topLeft()); // reverse the workaround above
+                contentRect = boundingRect = rect;
+                retVal = true;
+            }
+        }
         default:
             break;
     }
@@ -894,7 +923,8 @@ sal_Bool KDESalGraphics::hitTestNativeControl( ControlType nType, ControlPart nP
     {
         if( nPart != PART_BUTTON_UP && nPart != PART_BUTTON_DOWN
             && nPart != PART_BUTTON_LEFT && nPart != PART_BUTTON_RIGHT )
-        { // we adjust only for buttons (because some scrollbars have 3 buttons)
+        { // we adjust only for buttons (because some scrollbars have 3 buttons,
+          // and LO core doesn't handle such scrollbars well)
             return FALSE;
         }
         rIsInside = FALSE;
commit 4a9a7743d0aa9d5372f3e1debc4ae46336f8315c
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Apr 8 15:15:49 2011 +0200

    move hitTestNativeControl() to be next to getNativeControlRegion()

diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
index 6cf466d..d3f8965 100644
--- a/vcl/unx/kde4/KDESalGraphics.cxx
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -156,51 +156,6 @@ sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType type, ControlPart
     return false;
 }
 
-/** Test whether the position is in the native widget.
-    If the return value is TRUE, bIsInside contains information whether
-    aPos was or was not inside the native widget specified by the
-    nType/nPart combination.
-*/
-sal_Bool KDESalGraphics::hitTestNativeControl( ControlType nType, ControlPart nPart,
-                                           const Rectangle& rControlRegion, const Point& rPos,
-                                           sal_Bool& rIsInside )
-{
-    if ( nType == CTRL_SCROLLBAR )
-    {
-        if( nPart != PART_BUTTON_UP && nPart != PART_BUTTON_DOWN
-            && nPart != PART_BUTTON_LEFT && nPart != PART_BUTTON_RIGHT )
-        { // we adjust only for buttons (because some scrollbars have 3 buttons)
-            return FALSE;
-        }
-        rIsInside = FALSE;
-        bool bHorizontal = ( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT );
-        QRect rect = region2QRect( rControlRegion );
-        QPoint pos( rPos.X(), rPos.Y());
-        // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
-        // widget and screen coordinates the same. QStyle functions should use screen
-        // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
-        // and sometimes uses widget coordinates.
-        pos -= rect.topLeft();
-        rect.moveTo( 0, 0 );
-        QStyleOptionSlider options;
-        options.orientation = bHorizontal ? Qt::Horizontal : Qt::Vertical;
-        options.rect = rect;
-        // some random sensible values, since we call this code only for scrollbar buttons,
-        // the slider position does not exactly matter
-        options.maximum = 10;
-        options.minimum = 0;
-        options.sliderPosition = options.sliderValue = 4;
-        options.pageStep = 2;
-        QStyle::SubControl control = kapp->style()->hitTestComplexControl( QStyle::CC_ScrollBar, &options, pos );
-        if( nPart == PART_BUTTON_UP || nPart == PART_BUTTON_LEFT )
-            rIsInside = ( control == QStyle::SC_ScrollBarSubLine );
-        else // DOWN, RIGHT
-            rIsInside = ( control == QStyle::SC_ScrollBarAddLine );
-        return TRUE;
-    }
-    return FALSE;
-}
-
 /// helper drawing methods
 namespace 
 {
@@ -926,4 +881,50 @@ sal_Bool KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart p
     return retVal;
 }
 
+/** Test whether the position is in the native widget.
+    If the return value is TRUE, bIsInside contains information whether
+    aPos was or was not inside the native widget specified by the
+    nType/nPart combination.
+*/
+sal_Bool KDESalGraphics::hitTestNativeControl( ControlType nType, ControlPart nPart,
+                                           const Rectangle& rControlRegion, const Point& rPos,
+                                           sal_Bool& rIsInside )
+{
+    if ( nType == CTRL_SCROLLBAR )
+    {
+        if( nPart != PART_BUTTON_UP && nPart != PART_BUTTON_DOWN
+            && nPart != PART_BUTTON_LEFT && nPart != PART_BUTTON_RIGHT )
+        { // we adjust only for buttons (because some scrollbars have 3 buttons)
+            return FALSE;
+        }
+        rIsInside = FALSE;
+        bool bHorizontal = ( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT );
+        QRect rect = region2QRect( rControlRegion );
+        QPoint pos( rPos.X(), rPos.Y());
+        // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
+        // widget and screen coordinates the same. QStyle functions should use screen
+        // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
+        // and sometimes uses widget coordinates.
+        pos -= rect.topLeft();
+        rect.moveTo( 0, 0 );
+        QStyleOptionSlider options;
+        options.orientation = bHorizontal ? Qt::Horizontal : Qt::Vertical;
+        options.rect = rect;
+        // some random sensible values, since we call this code only for scrollbar buttons,
+        // the slider position does not exactly matter
+        options.maximum = 10;
+        options.minimum = 0;
+        options.sliderPosition = options.sliderValue = 4;
+        options.pageStep = 2;
+        QStyle::SubControl control = kapp->style()->hitTestComplexControl( QStyle::CC_ScrollBar, &options, pos );
+        if( nPart == PART_BUTTON_UP || nPart == PART_BUTTON_LEFT )
+            rIsInside = ( control == QStyle::SC_ScrollBarSubLine );
+        else // DOWN, RIGHT
+            rIsInside = ( control == QStyle::SC_ScrollBarAddLine );
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list