1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #define _SV_SALNATIVEWIDGETS_KDE_CXX
28 #include <shell/kde_headers.h>
29 
30 #include <unx/salunx.h>
31 #include <unx/saldata.hxx>
32 #include <unx/saldisp.hxx>
33 #include <unx/salgdi.h>
34 #include <unx/pspgraphics.h>
35 #include <unx/kde/kdedata.hxx>
36 
37 #include <vcl/settings.hxx>
38 #include <rtl/ustrbuf.hxx>
39 
40 
41 using namespace ::rtl;
42 
43 /** Cached native widgets.
44 
45     A class which caches and paints the native widgets.
46 */
47 class WidgetPainter
48 {
49     protected:
50 	/** Cached push button.
51 
52 	    It is necessary for the QStyle::drawControl(). The buttons are created
53 	    on demand and they are still hidden (no QWidget::show() is called).
54 	*/
55 	QPushButton  *m_pPushButton;
56 
57 	/** Cached radio button.
58 
59 	    @see m_pPushButton
60 	*/
61 	QRadioButton *m_pRadioButton;
62 
63 	/** Cached check box.
64 
65 	    @see m_pPushButton
66 	*/
67 	QCheckBox    *m_pCheckBox;
68 
69 	/** Cached combo box.
70 
71 	    @see m_pPushButton
72 	*/
73 	QComboBox    *m_pComboBox;
74 
75 	/** Cached editable combo box.
76 
77 	    Needed, because some styles do not like dynamic changes
78 	    (QComboBox::setEditable()).
79 
80 	    @see m_pPushButton
81 	*/
82 	QComboBox    *m_pEditableComboBox;
83 
84 	/** Cached line edit box.
85 
86 	    @see m_pPushButton
87 	*/
88 	QLineEdit    *m_pLineEdit;
89 
90 	/** Cached spin box.
91 
92 	    @see m_pPushButton
93 	*/
94 	QSpinWidget  *m_pSpinWidget;
95 
96 	/** Cached spin box'es line edit.
97 
98 	    @see m_pPushButton
99 	*/
100 	QLineEdit    *m_pSpinEdit;
101 
102 	/** Cached tab.
103 
104 	    Left, middle, right tab and a tab which is alone.
105 
106 	    @see m_pPushButton
107 	*/
108 	QTab         *m_pTabLeft, *m_pTabMiddle, *m_pTabRight, *m_pTabAlone;
109 
110 	/** Cached tab bar's parent widget.
111 
112 	    Needed, because the Qt windows style checks for the availability
113 	    of tab bar's parent. We cannot use m_pTabWidget, because
114 	    TabWidget::setTabBar() and TabWidget::tabBar() methods are
115 	    protected.
116 
117 	    @see m_pPushButton, m_pTabWidget
118 	*/
119 	QWidget      *m_pTabBarParent;
120 
121 	/** Cached tab bar widget.
122 
123 	    @see m_pPushButton
124 	*/
125 	QTabBar      *m_pTabBar;
126 
127 	/** Cached tab widget.
128 
129 	    We need it to draw the tab page. It cannot be used to draw the
130 	    tabs themselves, because the drawing has to be tweaked a little
131 	    due to not enough information from VCL.
132 
133 	    @see m_pPushButton, m_pTabBarParent
134 	*/
135 	QTabWidget   *m_pTabWidget;
136 
137 	/** Cached list view.
138 
139 	    @see m_pPushButton
140 	*/
141 	QListView    *m_pListView;
142 
143 	/** Cached scroll bar.
144 
145 	    @see m_pPushButton
146 	*/
147 	QScrollBar   *m_pScrollBar;
148 
149     /** Cached dock area. Needed for proper functionality of tool bars.
150 
151       @see m_pPushButton
152       */
153     QMainWindow  *m_pMainWindow;
154 
155     /** Cached tool bar.
156 
157       @see m_pPushButton
158     */
159     QToolBar     *m_pToolBarHoriz, *m_pToolBarVert;
160 
161     /** Cached tool button.
162 
163       @see m_pPushButton
164     */
165     QToolButton  *m_pToolButton;
166 
167     /** Cached menu bar.
168 
169       @see m_pPushButton
170     */
171     QMenuBar     *m_pMenuBar;
172 
173     /** Identifiers of menu bar items.
174      */
175     int           m_nMenuBarEnabledItem, m_nMenuBarDisabledItem;
176 
177     /** Cached popup menu.
178 
179       @see m_pPushButton
180     */
181     QPopupMenu   *m_pPopupMenu;
182 
183     /** Identifiers of popup menu items.
184      */
185     int           m_nPopupMenuEnabledItem, m_nPopupMenuDisabledItem;
186 
187     /** cached progress bar
188       */
189     QProgressBar *m_pProgressBar;
190 
191 	// TODO other widgets
192 
193     public:
194 	/** Implicit constructor.
195 
196 	    It creates an empty WidgetPainter with all the cached widgets initialized
197 	    to NULL. The widgets are created on demand and they are still hidden
198 	    (no QWidget::show()), because they are needed just as a parameter for
199 	    QStyle::drawControl().
200 
201 	    @see m_pPushButton
202 	*/
203 	WidgetPainter( void );
204 
205 	/** Destructor.
206 
207 	    Destruct all the cached widgets.
208 	*/
209 	virtual ~WidgetPainter( void );
210 
211 	/** Paints the specified widget to the X window.
212 
213 	    Use X calls to bitblt (bit block transfer) the widget qWidget to
214 	    the window specified by drawable with the style defined by nStyle.
215 
216 	    @param qWidget
217 	    A pointer to the cached widget.
218 
219 	    @param nState
220 	    The state of the control (focused, on/off, ...)
221 
222 	    @param aValue
223 	    The value (true/false, ...)
224 
225 	    @param dpy
226 	    The display to be used by the X calls.
227 
228 	    @param drawable
229 	    The destination X window.
230 
231 	    @param gc
232 	    The graphics context.
233 	*/
234         sal_Bool drawStyledWidget( QWidget *pWidget,
235                 ControlState nState, const ImplControlValue& aValue,
236                 Display *dpy, XLIB_Window drawable, int nScreen, int nDepth, GC gc,
237                 ControlPart nPart = PART_ENTIRE_CONTROL );
238 
239 	/** 'Get' method for push button.
240 
241 	    The method returns the cached push button. It is constructed if it
242 	    does not exist. It has NULL as a parent and it stays hidden, but it
243 	    is necessary for the drawStyledWidget() method.
244 
245 	    @return valid push button.
246 	*/
247 	QPushButton  *pushButton( const Rectangle& rControlRegion, sal_Bool bDefault );
248 
249 	/** 'Get' method for radio button.
250 
251 	    @see pushButton()
252 	*/
253 	QRadioButton *radioButton( const Rectangle& rControlRegion );
254 
255 	/** 'Get' method for check box.
256 
257 	    @see pushButton()
258 	*/
259 	QCheckBox    *checkBox( const Rectangle& rControlRegion );
260 
261 	/** 'Get' method for combo box.
262 
263 	    It returns m_pComboBox or m_pEditableComboBox according to
264 	    bEditable.
265 
266 	    @see pushButton(), m_pEditableComboBox
267 	*/
268 	QComboBox    *comboBox( const Rectangle& rControlRegion, sal_Bool bEditable );
269 
270 	/** 'Get' method for line edit box.
271 
272 	    @see pushButton()
273 	*/
274 	QLineEdit    *lineEdit( const Rectangle& rControlRegion );
275 
276 	/** 'Get' method for spin box.
277 
278 	    @see pushButton()
279 	*/
280 	QSpinWidget  *spinWidget( const Rectangle& rControlRegion );
281 
282 	/** 'Get' method for tab bar.
283 
284 	    @see pushButton()
285 	*/
286 	QTabBar      *tabBar( const Rectangle& rControlRegion );
287 
288 	/** 'Get' method for tab widget.
289 
290 	    @see pushButton()
291 	*/
292 	QTabWidget   *tabWidget( const Rectangle& rControlRegion );
293 
294 	/** 'Get' method for list view.
295 
296 	    @see pushButton()
297 	*/
298 	QListView    *listView( const Rectangle& rControlRegion );
299 
300 	/** 'Get' method for scroll bar.
301 
302 	    @see pushButton()
303 	*/
304 	QScrollBar   *scrollBar( const Rectangle& rControlRegion,
305 		sal_Bool bHorizontal, const ImplControlValue& aValue );
306 
307     /** 'Get' method for tool bar.
308 
309       @see pushButton()
310     */
311     QToolBar     *toolBar( const Rectangle& rControlRegion, sal_Bool bHorizontal );
312 
313     /** 'Get' method for tool button.
314 
315       @see pushButton()
316     */
317     QToolButton  *toolButton( const Rectangle& rControlRegion );
318 
319     /** 'Get' method for menu bar.
320 
321       @see pushButton()
322     */
323     QMenuBar     *menuBar( const Rectangle& rControlRegion );
324 
325     /** 'Get' method for popup menu.
326 
327       @see pushButton()
328     */
329     QPopupMenu   *popupMenu( const Rectangle& rControlRegion );
330 
331     /** 'Get' method for progress bar
332 
333       @see pushButton()
334     */
335     QProgressBar *progressBar( const Rectangle& rControlRegion );
336 
337 	// TODO other widgets
338 
339     protected:
340 	/** Style conversion function.
341 
342 	    Conversion function between VCL ControlState together with
343 	    ImplControlValue and Qt state flags.
344 
345 	    @param nState
346 	    State of the widget (default, focused, ...) as defined in Native
347 	    Widget Framework.
348 
349 	    @param aValue
350 	    Value held by the widget (on, off, ...)
351 	*/
352 	QStyle::SFlags vclStateValue2SFlags( ControlState nState, const ImplControlValue& aValue );
353 
354     public:
355 	/** Convert VCL Rectangle to QRect.
356 
357 	    @param rControlRegion
358 	    The region to convert.
359 
360 	    @return
361 	    The bounding box of the region.
362 	*/
363 	static QRect region2QRect( const Rectangle& rControlRegion );
364 };
365 
WidgetPainter(void)366 WidgetPainter::WidgetPainter( void )
367     : m_pPushButton( NULL ),
368       m_pRadioButton( NULL ),
369       m_pCheckBox( NULL ),
370       m_pComboBox( NULL ),
371       m_pEditableComboBox( NULL ),
372       m_pLineEdit( NULL ),
373       m_pSpinWidget( NULL ),
374       m_pSpinEdit( NULL ),
375       m_pTabLeft( NULL ),
376       m_pTabMiddle( NULL ),
377       m_pTabRight( NULL ),
378       m_pTabAlone( NULL ),
379       m_pTabBarParent( NULL ),
380       m_pTabBar( NULL ),
381       m_pTabWidget( NULL ),
382       m_pListView( NULL ),
383       m_pScrollBar( NULL ),
384       m_pMainWindow( NULL ),
385       m_pToolBarHoriz( NULL ),
386       m_pToolBarVert( NULL ),
387       m_pToolButton( NULL ),
388       m_pMenuBar( NULL ),
389       m_pPopupMenu( NULL ),
390       m_pProgressBar( NULL )
391 {
392 }
393 
~WidgetPainter(void)394 WidgetPainter::~WidgetPainter( void )
395 {
396     delete m_pPushButton, m_pPushButton = NULL;
397     delete m_pRadioButton, m_pRadioButton = NULL;
398     delete m_pCheckBox, m_pCheckBox = NULL;
399     delete m_pComboBox, m_pComboBox = NULL;
400     delete m_pEditableComboBox, m_pEditableComboBox = NULL;
401     delete m_pLineEdit, m_pLineEdit = NULL;
402     delete m_pSpinWidget, m_pSpinWidget = NULL;
403     m_pSpinEdit = NULL; // Deleted in m_pSpinWidget's destructor
404     delete m_pTabAlone, m_pTabAlone = NULL;
405     delete m_pTabBarParent, m_pTabBarParent = NULL;
406     m_pTabBar = NULL;    // Deleted in m_pTabBarParent's destructor
407     m_pTabLeft = NULL;
408     m_pTabMiddle = NULL;
409     m_pTabRight = NULL;
410     delete m_pTabWidget, m_pTabWidget = NULL;
411     delete m_pListView, m_pListView = NULL;
412     delete m_pScrollBar, m_pScrollBar = NULL;
413     delete m_pToolBarHoriz, m_pToolBarHoriz = NULL;
414     delete m_pToolBarVert, m_pToolBarVert = NULL;
415     delete m_pMainWindow, m_pMainWindow = NULL;
416     delete m_pToolButton, m_pToolButton = NULL;
417     delete m_pMenuBar, m_pMenuBar = NULL;
418     delete m_pPopupMenu, m_pPopupMenu = NULL;
419     delete m_pProgressBar, m_pProgressBar = NULL;
420 }
421 
drawStyledWidget(QWidget * pWidget,ControlState nState,const ImplControlValue & aValue,Display * dpy,XLIB_Window drawable,int nScreen,int nDepth,GC gc,ControlPart nPart)422 sal_Bool WidgetPainter::drawStyledWidget( QWidget *pWidget,
423 	ControlState nState, const ImplControlValue& aValue,
424         Display *dpy, XLIB_Window drawable, int nScreen, int nDepth, GC gc,
425         ControlPart nPart )
426 {
427     if ( !pWidget )
428 	return sal_False;
429 
430     // Normalize the widget
431     QPoint   qWidgetPos( pWidget->pos() );
432     pWidget->move( 0, 0 );
433 
434     // Enable/disable the widget
435     pWidget->setEnabled( nState & CTRL_STATE_ENABLED );
436 
437     // Create pixmap to paint to
438     QPixmap  qPixmap( pWidget->width(), pWidget->height() );
439     QPainter qPainter( &qPixmap );
440     QRect    qRect( 0, 0, pWidget->width(), pWidget->height() );
441 
442     // Use the background of the widget
443     qPixmap.fill( pWidget, QPoint(0, 0) );
444 
445     // Convert the flags
446     QStyle::SFlags nStyle = vclStateValue2SFlags( nState, aValue );
447 
448     // Store the widget class
449     const char *pClassName = pWidget->className();
450 
451     // Draw the widget to the pixmap
452     if ( strcmp( "QPushButton", pClassName ) == 0 )
453     {
454 	// Workaround for the Platinum style.
455 	// Platinum takes the state directly from the widget, not from SFlags.
456 	QPushButton *pPushButton = static_cast<QPushButton *>( pWidget->qt_cast( "QPushButton" ) );
457 	if ( pPushButton )
458 	{
459 	    pPushButton->setDown   ( nStyle & QStyle::Style_Down );
460 	    pPushButton->setOn     ( nStyle & QStyle::Style_On );
461 	    pPushButton->setEnabled( nStyle & QStyle::Style_Enabled );
462 	}
463 
464 	kapp->style().drawControl( QStyle::CE_PushButton,
465 		&qPainter, pWidget, qRect,
466 		pWidget->colorGroup(), nStyle );
467     }
468     else if ( strcmp( "QRadioButton", pClassName ) == 0 )
469     {
470 	// Bitblt from the screen, because the radio buttons are usually not
471 	// rectangular, and there could be a bitmap under them
472 	GC aTmpGC = XCreateGC( dpy, qPixmap.handle(), 0, NULL );
473     X11SalGraphics::CopyScreenArea( dpy,
474                               drawable, nScreen, nDepth,
475                               qPixmap.handle(), qPixmap.x11Screen(), qPixmap.x11Depth(),
476                               aTmpGC,
477                               qWidgetPos.x(), qWidgetPos.y(), qRect.width(), qRect.height(),
478                               0, 0 );
479 	XFreeGC( dpy, aTmpGC );
480 
481 	kapp->style().drawControl( QStyle::CE_RadioButton,
482 		&qPainter, pWidget, qRect,
483 		pWidget->colorGroup(), nStyle );
484     }
485     else if ( strcmp( "QCheckBox", pClassName ) == 0 )
486     {
487 	kapp->style().drawControl( QStyle::CE_CheckBox,
488 		&qPainter, pWidget, qRect,
489 		pWidget->colorGroup(), nStyle );
490     }
491     else if ( strcmp( "QComboBox", pClassName ) == 0 )
492     {
493 	kapp->style().drawComplexControl( QStyle::CC_ComboBox,
494 		&qPainter, pWidget, qRect,
495 		pWidget->colorGroup(), nStyle );
496 
497 	// Editable combo box uses the background of the associated edit box
498 	QComboBox *pComboBox = static_cast<QComboBox *>( pWidget->qt_cast( "QComboBox" ) );
499 	if ( pComboBox && pComboBox->editable() && pComboBox->lineEdit() )
500 	{
501 	    QColorGroup::ColorRole eColorRole = ( pComboBox->isEnabled() )?
502 		QColorGroup::Base: QColorGroup::Background;
503 	    qPainter.fillRect(
504 		    kapp->style().querySubControlMetrics( QStyle::CC_ComboBox,
505 			pComboBox, QStyle::SC_ComboBoxEditField ),
506 		    pComboBox->lineEdit()->colorGroup().brush( eColorRole ) );
507 	}
508     }
509     else if ( strcmp( "QLineEdit", pClassName ) == 0 )
510     {
511 	kapp->style().drawPrimitive( QStyle::PE_PanelLineEdit,
512 		&qPainter, qRect,
513 		pWidget->colorGroup(), nStyle | QStyle::Style_Sunken );
514     }
515     else if ( strcmp( "QSpinWidget", pClassName ) == 0 )
516     {
517 	const SpinbuttonValue* pValue = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue*>(&aValue) : NULL;
518 
519 	// Is any of the buttons pressed?
520 	QStyle::SCFlags eActive = QStyle::SC_None;
521 	if ( pValue )
522 	{
523 	    if ( pValue->mnUpperState & CTRL_STATE_PRESSED )
524 		eActive = QStyle::SC_SpinWidgetUp;
525 	    else if ( pValue->mnLowerState & CTRL_STATE_PRESSED )
526 		eActive = QStyle::SC_SpinWidgetDown;
527 
528 	    // Update the enable/disable state of the widget
529 	    if ( ( nState & CTRL_STATE_ENABLED ) ||
530 		    ( pValue->mnUpperState & CTRL_STATE_ENABLED ) ||
531 		    ( pValue->mnLowerState & CTRL_STATE_ENABLED ) )
532 	    {
533 		pWidget->setEnabled( true );
534 		nStyle |= QStyle::Style_Enabled;
535 	    }
536 	    else
537 		pWidget->setEnabled( false );
538 
539 	    // Mouse-over effect
540 	    if ( (pValue->mnUpperState & CTRL_STATE_ROLLOVER) ||
541 		    (pValue->mnLowerState & CTRL_STATE_ROLLOVER) )
542 		nStyle |= QStyle::Style_MouseOver;
543 	}
544 
545 	// Spin widget uses the background of the associated edit box
546 	QSpinWidget *pSpinWidget = static_cast<QSpinWidget *>( pWidget->qt_cast( "QSpinWidget" ) );
547 	if ( pSpinWidget && pSpinWidget->editWidget() )
548 	{
549 	    QColorGroup::ColorRole eColorRole = ( pSpinWidget->isEnabled() )?
550 		QColorGroup::Base: QColorGroup::Background;
551 	    qPainter.fillRect(
552 		    kapp->style().querySubControlMetrics( QStyle::CC_SpinWidget,
553 			pSpinWidget, QStyle::SC_SpinWidgetEditField ),
554 		    pSpinWidget->editWidget()->colorGroup().brush( eColorRole ) );
555 	}
556 
557 	// Adjust the frame (needed for Motif Plus style)
558 	QRect qFrameRect = kapp->style().querySubControlMetrics( QStyle::CC_SpinWidget,
559 		pWidget, QStyle::SC_SpinWidgetFrame );
560 
561 	kapp->style().drawComplexControl( QStyle::CC_SpinWidget,
562 		&qPainter, pWidget, qFrameRect,
563 		pWidget->colorGroup(), nStyle,
564 		QStyle::SC_All, eActive );
565     }
566     else if ( strcmp( "QTabBar", pClassName ) == 0 )
567     {
568 	const TabitemValue *pValue = static_cast<const TabitemValue *> ( &aValue );
569 
570 	QTab *pTab = NULL;
571 	if ( pValue )
572 	{
573 	    if ( ( pValue->isFirst() || pValue->isLeftAligned() ) && ( pValue->isLast() || pValue->isRightAligned() ) )
574 		pTab = m_pTabAlone;
575 	    else if ( pValue->isFirst() || pValue->isLeftAligned() )
576 		pTab = m_pTabLeft;
577 	    else if ( pValue->isLast() || pValue->isRightAligned() )
578 		pTab = m_pTabRight;
579 	    else
580 		pTab = m_pTabMiddle;
581 	}
582 	if ( !pTab )
583 	    return sal_False;
584 
585 	pTab->setRect( qRect );
586 
587 	kapp->style().drawControl( QStyle::CE_TabBarTab,
588 		&qPainter, pWidget, qRect,
589 		pWidget->colorGroup(), nStyle,
590 		QStyleOption( pTab ) );
591     }
592     else if ( strcmp( "QTabWidget", pClassName ) == 0 )
593     {
594 	kapp->style().drawPrimitive( QStyle::PE_PanelTabWidget,
595 		&qPainter, qRect,
596 		pWidget->colorGroup(), nStyle );
597     }
598     else if ( strcmp( "QListView", pClassName ) == 0 )
599     {
600 	kapp->style().drawPrimitive( QStyle::PE_Panel,
601 		&qPainter, qRect,
602 		pWidget->colorGroup(), nStyle | QStyle::Style_Sunken );
603     }
604     else if ( strcmp( "QScrollBar", pClassName ) == 0 )
605     {
606 	const ScrollbarValue* pScrollbarVal = (aValue.getType() == CTRL_SCROLLBAR) ? static_cast<const ScrollbarValue*>(&aValue) : NULL;
607 
608 	QStyle::SCFlags eActive = QStyle::SC_None;
609 	if ( pValue )
610 	{
611 	    // Workaround for Style_MouseOver-aware themes.
612 	    // Quite ugly, but I do not know about a better solution.
613 	    const char *pStyleName = kapp->style().className();
614 	    if ( strcmp( "QMotifPlusStyle", pStyleName ) == 0 )
615 	    {
616 		nStyle |= QStyle::Style_MouseOver;
617 		if ( pValue->mnThumbState & CTRL_STATE_ROLLOVER )
618 		    eActive = QStyle::SC_ScrollBarSlider;
619 	    }
620 	    else if ( strcmp( "QSGIStyle", pStyleName ) == 0 )
621 	    {
622 		nStyle |= QStyle::Style_MouseOver;
623 		if ( pValue->mnButton1State & CTRL_STATE_ROLLOVER )
624 		    eActive = QStyle::SC_ScrollBarSubLine;
625 		else if ( pValue->mnButton2State & CTRL_STATE_ROLLOVER )
626 		    eActive = QStyle::SC_ScrollBarAddLine;
627 		else if ( pValue->mnThumbState & CTRL_STATE_ROLLOVER )
628 		    eActive = QStyle::SC_ScrollBarSlider;
629 	    }
630 
631 	    if ( pValue->mnButton1State & CTRL_STATE_PRESSED )
632 		eActive = QStyle::SC_ScrollBarSubLine;
633 	    else if ( pValue->mnButton2State & CTRL_STATE_PRESSED )
634 		eActive = QStyle::SC_ScrollBarAddLine;
635 	    else if ( pValue->mnThumbState & CTRL_STATE_PRESSED )
636 		eActive = QStyle::SC_ScrollBarSlider;
637 	    else if ( pValue->mnPage1State & CTRL_STATE_PRESSED )
638 		eActive = QStyle::SC_ScrollBarSubPage;
639 	    else if ( pValue->mnPage2State & CTRL_STATE_PRESSED )
640 		eActive = QStyle::SC_ScrollBarAddPage;
641 
642 	    // Update the enable/disable state of the widget
643 	    if ( ( nState & CTRL_STATE_ENABLED ) ||
644 		    ( pValue->mnButton1State & CTRL_STATE_ENABLED ) ||
645 		    ( pValue->mnButton2State & CTRL_STATE_ENABLED ) ||
646 		    ( pValue->mnThumbState & CTRL_STATE_ENABLED ) ||
647 		    ( pValue->mnPage1State & CTRL_STATE_ENABLED ) ||
648 		    ( pValue->mnPage2State & CTRL_STATE_ENABLED ) )
649 	    {
650 		pWidget->setEnabled( true );
651 		nStyle |= QStyle::Style_Enabled;
652 	    }
653 	    else
654 		pWidget->setEnabled( false );
655 	}
656 
657 	// Is it a horizontal scroll bar?
658 	QScrollBar *pScrollBar = static_cast<QScrollBar *> ( pWidget->qt_cast( "QScrollBar" ) );
659 	QStyle::StyleFlags eHoriz = QStyle::Style_Default;
660 	if ( pScrollBar && pScrollBar->orientation() == Qt::Horizontal )
661 	    eHoriz = QStyle::Style_Horizontal;
662 
663 	kapp->style().drawComplexControl( QStyle::CC_ScrollBar,
664 		&qPainter, pWidget, qRect,
665 		pWidget->colorGroup(), nStyle | eHoriz,
666 		QStyle::SC_All, eActive );
667     }
668     else if ( strcmp( "QToolBar", pClassName ) == 0 )
669     {
670         QToolBar *pToolBar = static_cast< QToolBar * >( pWidget->qt_cast( "QToolBar" ) );
671         bool bIsHorizontal = false;
672         if ( pToolBar && pToolBar->orientation() == Qt::Horizontal )
673         {
674             nStyle |= QStyle::Style_Horizontal;
675             bIsHorizontal = true;
676         }
677 
678         kapp->style().drawControl( QStyle::CE_DockWindowEmptyArea,
679                 &qPainter, pWidget, qRect,
680                 pWidget->colorGroup(), nStyle );
681 
682         kapp->style().drawPrimitive( QStyle::PE_PanelDockWindow,
683                 &qPainter, qRect, pWidget->colorGroup(), nStyle );
684 
685         if ( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
686         {
687             const ToolbarValue *pValue = static_cast< const ToolbarValue * >( &aValue );
688 
689             QRect qThumbRect = region2QRect( pValue->maGripRect );
690             qThumbRect.moveBy( -qWidgetPos.x(), -qWidgetPos.y() );
691             if ( bIsHorizontal )
692                 qThumbRect.addCoords( 0, 2, 0, -3 );    // make the thumb a bit nicer
693             else
694                 qThumbRect.addCoords( 2, 0, -3, 0 );    // make the thumb a bit nicer
695 
696             if ( kapp->style().inherits( "HighColorStyle" ) ||
697                  kapp->style().inherits( "HighContrastStyle" ) ||
698                  kapp->style().inherits( "KeramikStyle" ) ||
699                  kapp->style().inherits( "KThemeStyle" ) ||
700                  kapp->style().inherits( "ThinKeramikStyle" ) )
701             {
702                 // Workaround for the workaround in KStyle::drawPrimitive()
703                 KStyle *pStyle = static_cast< KStyle * >( &kapp->style() );
704                 pStyle->drawKStylePrimitive( KStyle::KPE_ToolBarHandle,
705                         &qPainter, pToolBar, qThumbRect,
706                         pWidget->colorGroup(), nStyle );
707             }
708             else
709                 kapp->style().drawPrimitive( QStyle::PE_DockWindowHandle,
710                         &qPainter, qThumbRect, pWidget->colorGroup(), nStyle );
711         }
712     }
713     else if ( strcmp( "QToolButton", pClassName ) == 0 )
714     {
715         if( (nStyle & QStyle::Style_MouseOver) )
716             nStyle &= ~QStyle::Style_Off;
717         kapp->style().drawComplexControl( QStyle::CC_ToolButton,
718                 &qPainter, pWidget, qRect,
719                 pWidget->colorGroup(), nStyle,
720                 QStyle::SC_ToolButton );
721     }
722     else if ( strcmp( "QMenuBar", pClassName ) == 0 )
723     {
724         if ( nPart == PART_ENTIRE_CONTROL )
725         {
726             kapp->style().drawControl( QStyle::CE_MenuBarEmptyArea,
727                     &qPainter, pWidget, qRect,
728                     pWidget->colorGroup(), nStyle );
729         }
730         else if ( nPart == PART_MENU_ITEM )
731         {
732             int nMenuItem = ( nStyle & QStyle::Style_Enabled )? m_nMenuBarEnabledItem: m_nMenuBarDisabledItem;
733             QMenuItem *pMenuItem = static_cast<QMenuBar*>( pWidget )->findItem( nMenuItem );
734 
735             if ( nStyle & QStyle::Style_Selected )
736                 nStyle |= QStyle::Style_Active | QStyle::Style_Down | QStyle::Style_HasFocus;
737 
738             kapp->style().drawControl( QStyle::CE_MenuBarItem,
739                     &qPainter, pWidget, qRect,
740                     pWidget->colorGroup(), nStyle,
741                     QStyleOption( pMenuItem ) );
742         }
743     }
744     else if ( strcmp( "QPopupMenu", pClassName ) == 0 )
745     {
746         int nMenuItem = ( nStyle & QStyle::Style_Enabled )? m_nPopupMenuEnabledItem: m_nPopupMenuDisabledItem;
747         QMenuItem *pMenuItem = static_cast<QPopupMenu*>( pWidget )->findItem( nMenuItem );
748 
749         if ( nStyle & QStyle::Style_Selected )
750             nStyle |= QStyle::Style_Active;
751 
752         kapp->style().drawControl( QStyle::CE_PopupMenuItem,
753                 &qPainter, pWidget, qRect,
754                 pWidget->colorGroup(), nStyle,
755                 QStyleOption( pMenuItem, 0, 0 ) );
756     }
757     else if ( strcmp( "QProgressBar", pClassName ) == 0 )
758     {
759         long nProgressWidth = aValue.getNumericVal();
760         QProgressBar* pProgress = static_cast<QProgressBar*>(pWidget);
761         pProgress->setProgress( nProgressWidth, qRect.width() );
762 
763         kapp->style().drawControl( QStyle::CE_ProgressBarGroove,
764             &qPainter, pWidget, qRect,
765             pWidget->colorGroup(), nStyle );
766         kapp->style().drawControl( QStyle::CE_ProgressBarContents,
767             &qPainter, pWidget, qRect,
768             pWidget->colorGroup(), nStyle );
769     }
770     else
771 	return sal_False;
772 
773     // Bitblt it to the screen
774     X11SalGraphics::CopyScreenArea( dpy,
775 	                          qPixmap.handle(), qPixmap.x11Screen(), qPixmap.x11Depth(),
776                               drawable, nScreen, nDepth,
777                               gc,
778                               0, 0, qRect.width(), qRect.height(),
779                               qWidgetPos.x(), qWidgetPos.y() );
780 
781     // Restore widget's position
782     pWidget->move( qWidgetPos );
783 
784     return sal_True;
785 }
786 
pushButton(const Rectangle & rControlRegion,sal_Bool bDefault)787 QPushButton *WidgetPainter::pushButton( const Rectangle& rControlRegion,
788 	sal_Bool bDefault )
789 {
790     if ( !m_pPushButton )
791 	m_pPushButton = new QPushButton( NULL, "push_button" );
792 
793     QRect qRect = region2QRect( rControlRegion );
794 
795     // Workaround for broken styles which do not add
796     // QStyle::PM_ButtonDefaultIndicator to the size of the default button
797     // (for example Keramik)
798     // FIXME Fix Keramik style to be consistent with Qt built-in styles. Aargh!
799     if ( bDefault )
800     {
801 	QSize qContentsSize( 50, 50 );
802 	m_pPushButton->setDefault( false );
803 	QSize qNormalSize = kapp->style().sizeFromContents( QStyle::CT_PushButton,
804 		m_pPushButton, qContentsSize );
805 	m_pPushButton->setDefault( true );
806 	QSize qDefSize = kapp->style().sizeFromContents( QStyle::CT_PushButton,
807 		m_pPushButton, qContentsSize );
808 
809 	int nIndicatorSize = kapp->style().pixelMetric(
810 		QStyle::PM_ButtonDefaultIndicator, m_pPushButton );
811 	if ( qNormalSize.width() == qDefSize.width() )
812 	    qRect.addCoords( nIndicatorSize, 0, -nIndicatorSize, 0 );
813 	if ( qNormalSize.height() == qDefSize.height() )
814 	    qRect.addCoords( 0, nIndicatorSize, 0, -nIndicatorSize );
815     }
816 
817     m_pPushButton->move( qRect.topLeft() );
818     m_pPushButton->resize( qRect.size() );
819     m_pPushButton->setDefault( bDefault );
820 
821     return m_pPushButton;
822 }
823 
radioButton(const Rectangle & rControlRegion)824 QRadioButton *WidgetPainter::radioButton( const Rectangle& rControlRegion )
825 {
826     if ( !m_pRadioButton )
827 	m_pRadioButton = new QRadioButton( NULL, "radio_button" );
828 
829     QRect qRect = region2QRect( rControlRegion );
830 
831     // Workaround for broken themes which do not honor the given size.
832     // Quite ugly, but I do not know about a better solution.
833     const char *pStyleName = kapp->style().className();
834     if ( strcmp( "KThemeStyle", pStyleName ) == 0 )
835     {
836 	QRect qOldRect( qRect );
837 
838 	qRect.setWidth( kapp->style().pixelMetric(
839 		QStyle::PM_ExclusiveIndicatorWidth, m_pRadioButton ) );
840 	qRect.setHeight( kapp->style().pixelMetric(
841 		QStyle::PM_ExclusiveIndicatorHeight, m_pRadioButton ) );
842 
843 	qRect.moveBy( ( qOldRect.width() - qRect.width() ) / 2,
844 		( qOldRect.height() - qRect.height() ) / 2 );
845     }
846 
847     m_pRadioButton->move( qRect.topLeft() );
848     m_pRadioButton->resize( qRect.size() );
849 
850     return m_pRadioButton;
851 }
852 
checkBox(const Rectangle & rControlRegion)853 QCheckBox *WidgetPainter::checkBox( const Rectangle& rControlRegion )
854 {
855     if ( !m_pCheckBox )
856 	m_pCheckBox = new QCheckBox( NULL, "check_box" );
857 
858     QRect qRect = region2QRect( rControlRegion );
859 
860     // Workaround for broken themes which do not honor the given size.
861     // Quite ugly, but I do not know about a better solution.
862     const char *pStyleName = kapp->style().className();
863     if ( strcmp( "KThemeStyle", pStyleName ) == 0 )
864     {
865 	QRect qOldRect( qRect );
866 
867 	qRect.setWidth( kapp->style().pixelMetric(
868 		QStyle::PM_IndicatorWidth, m_pCheckBox ) );
869 	qRect.setHeight( kapp->style().pixelMetric(
870 		QStyle::PM_IndicatorHeight, m_pCheckBox ) );
871 
872 	qRect.moveBy( ( qOldRect.width() - qRect.width() ) / 2,
873 		( qOldRect.height() - qRect.height() ) / 2 );
874     }
875 
876     m_pCheckBox->move( qRect.topLeft() );
877     m_pCheckBox->resize( qRect.size() );
878 
879     return m_pCheckBox;
880 }
881 
comboBox(const Rectangle & rControlRegion,sal_Bool bEditable)882 QComboBox *WidgetPainter::comboBox( const Rectangle& rControlRegion,
883 	sal_Bool bEditable )
884 {
885     QComboBox *pComboBox = NULL;
886     if ( bEditable )
887     {
888 	if ( !m_pEditableComboBox )
889 	    m_pEditableComboBox = new QComboBox( true, NULL, "combo_box_edit" );
890 	pComboBox = m_pEditableComboBox;
891     }
892     else
893     {
894 	if ( !m_pComboBox )
895 	    m_pComboBox = new QComboBox( false, NULL, "combo_box" );
896 	pComboBox = m_pComboBox;
897     }
898 
899     QRect qRect = region2QRect( rControlRegion );
900 
901     pComboBox->move( qRect.topLeft() );
902     pComboBox->resize( qRect.size() );
903 
904     return pComboBox;
905 }
906 
lineEdit(const Rectangle & rControlRegion)907 QLineEdit *WidgetPainter::lineEdit( const Rectangle& rControlRegion )
908 {
909     if ( !m_pLineEdit )
910 	m_pLineEdit = new QLineEdit( NULL, "line_edit" );
911 
912     QRect qRect = region2QRect( rControlRegion );
913 
914     m_pLineEdit->move( qRect.topLeft() );
915     m_pLineEdit->resize( qRect.size() );
916 
917     return m_pLineEdit;
918 }
919 
spinWidget(const Rectangle & rControlRegion)920 QSpinWidget *WidgetPainter::spinWidget( const Rectangle& rControlRegion )
921 {
922     if ( !m_pSpinWidget )
923     {
924 	m_pSpinWidget = new QSpinWidget( NULL, "spin_widget" );
925 
926 	m_pSpinEdit = new QLineEdit( NULL, "line_edit_spin" );
927 	m_pSpinWidget->setEditWidget( m_pSpinEdit );
928     }
929 
930     QRect qRect = region2QRect( rControlRegion );
931 
932     m_pSpinWidget->move( qRect.topLeft() );
933     m_pSpinWidget->resize( qRect.size() );
934     m_pSpinWidget->arrange();
935 
936     return m_pSpinWidget;
937 }
938 
tabBar(const Rectangle & rControlRegion)939 QTabBar *WidgetPainter::tabBar( const Rectangle& rControlRegion )
940 {
941     if ( !m_pTabBar )
942     {
943 	if ( !m_pTabBarParent )
944 	    m_pTabBarParent = new QWidget( NULL, "tab_bar_parent" );
945 
946 	m_pTabBar = new QTabBar( m_pTabBarParent, "tab_bar" );
947 
948 	m_pTabLeft = new QTab();
949 	m_pTabMiddle = new QTab();
950 	m_pTabRight = new QTab();
951 	m_pTabAlone = new QTab();
952 
953 	m_pTabBar->addTab( m_pTabLeft );
954 	m_pTabBar->addTab( m_pTabMiddle );
955 	m_pTabBar->addTab( m_pTabRight );
956     }
957 
958     QRect qRect = region2QRect( rControlRegion );
959 
960     m_pTabBar->move( qRect.topLeft() );
961     m_pTabBar->resize( qRect.size() );
962 
963     m_pTabBar->setShape( QTabBar::RoundedAbove );
964 
965     return m_pTabBar;
966 }
967 
tabWidget(const Rectangle & rControlRegion)968 QTabWidget *WidgetPainter::tabWidget( const Rectangle& rControlRegion )
969 {
970     if ( !m_pTabWidget )
971 	m_pTabWidget = new QTabWidget( NULL, "tab_widget" );
972 
973     QRect qRect = region2QRect( rControlRegion );
974     --qRect.rTop();
975 
976     m_pTabWidget->move( qRect.topLeft() );
977     m_pTabWidget->resize( qRect.size() );
978 
979     return m_pTabWidget;
980 }
981 
listView(const Rectangle & rControlRegion)982 QListView *WidgetPainter::listView( const Rectangle& rControlRegion )
983 {
984     if ( !m_pListView )
985 	m_pListView = new QListView( NULL, "list_view" );
986 
987     QRect qRect = region2QRect( rControlRegion );
988 
989     m_pListView->move( qRect.topLeft() );
990     m_pListView->resize( qRect.size() );
991 
992     return m_pListView;
993 }
994 
scrollBar(const Rectangle & rControlRegion,sal_Bool bHorizontal,const ImplControlValue & aValue)995 QScrollBar *WidgetPainter::scrollBar( const Rectangle& rControlRegion,
996 	sal_Bool bHorizontal, const ImplControlValue& aValue )
997 {
998     if ( !m_pScrollBar )
999     {
1000 	m_pScrollBar = new QScrollBar( NULL, "scroll_bar" );
1001 	m_pScrollBar->setTracking( false );
1002 	m_pScrollBar->setLineStep( 1 );
1003     }
1004 
1005     QRect qRect = region2QRect( rControlRegion );
1006 
1007     m_pScrollBar->move( qRect.topLeft() );
1008     m_pScrollBar->resize( qRect.size() );
1009     m_pScrollBar->setOrientation( bHorizontal? Qt::Horizontal: Qt::Vertical );
1010 
1011     const ScrollbarValue* pScrollbarVal = (aValue.getType() == CTRL_SCROLLBAR) ? static_cast<const ScrollbarValue*>(&aValue) : NULL;
1012     if ( pValue )
1013     {
1014 	m_pScrollBar->setMinValue( pValue->mnMin );
1015 	m_pScrollBar->setMaxValue( pValue->mnMax - pValue->mnVisibleSize );
1016 	m_pScrollBar->setValue( pValue->mnCur );
1017 	m_pScrollBar->setPageStep( pValue->mnVisibleSize );
1018     }
1019 
1020     return m_pScrollBar;
1021 }
1022 
toolBar(const Rectangle & rControlRegion,sal_Bool bHorizontal)1023 QToolBar *WidgetPainter::toolBar( const Rectangle& rControlRegion, sal_Bool bHorizontal )
1024 {
1025     if ( !m_pMainWindow )
1026         m_pMainWindow = new QMainWindow( NULL, "main_window" );
1027 
1028     QToolBar *pToolBar;
1029     if ( bHorizontal )
1030     {
1031         if ( !m_pToolBarHoriz )
1032         {
1033             m_pToolBarHoriz = new QToolBar( m_pMainWindow, "tool_bar_horiz" );
1034             m_pMainWindow->moveDockWindow( m_pToolBarHoriz, Qt::DockTop );
1035         }
1036         pToolBar = m_pToolBarHoriz;
1037     }
1038     else
1039     {
1040         if ( !m_pToolBarVert )
1041         {
1042             m_pToolBarVert = new QToolBar( m_pMainWindow, "tool_bar_horiz" );
1043             m_pMainWindow->moveDockWindow( m_pToolBarVert, Qt::DockLeft );
1044         }
1045         pToolBar = m_pToolBarVert;
1046     }
1047 
1048     QRect qRect = region2QRect( rControlRegion );
1049 
1050     pToolBar->move( qRect.topLeft() );
1051     pToolBar->resize( qRect.size() );
1052 
1053     return pToolBar;
1054 }
1055 
toolButton(const Rectangle & rControlRegion)1056 QToolButton *WidgetPainter::toolButton( const Rectangle& rControlRegion)
1057 {
1058     if ( !m_pToolButton )
1059 	m_pToolButton = new QToolButton( NULL, "tool_button" );
1060 
1061     QRect qRect = region2QRect( rControlRegion );
1062 
1063     m_pToolButton->move( qRect.topLeft() );
1064     m_pToolButton->resize( qRect.size() );
1065 
1066     return m_pToolButton;
1067 }
1068 
menuBar(const Rectangle & rControlRegion)1069 QMenuBar *WidgetPainter::menuBar( const Rectangle& rControlRegion)
1070 {
1071     if ( !m_pMenuBar )
1072     {
1073         m_pMenuBar = new QMenuBar( NULL, "menu_bar" );
1074 
1075         m_nMenuBarEnabledItem = m_pMenuBar->insertItem( "" );
1076         m_nMenuBarDisabledItem = m_pMenuBar->insertItem( "" );
1077 
1078         m_pMenuBar->setItemEnabled( m_nMenuBarEnabledItem, true );
1079         m_pMenuBar->setItemEnabled( m_nMenuBarDisabledItem, false );
1080     }
1081 
1082     QRect qRect = region2QRect( rControlRegion );
1083 
1084     m_pMenuBar->move( qRect.topLeft() );
1085     m_pMenuBar->resize( qRect.size() );
1086 
1087     return m_pMenuBar;
1088 }
1089 
popupMenu(const Rectangle & rControlRegion)1090 QPopupMenu *WidgetPainter::popupMenu( const Rectangle& rControlRegion)
1091 {
1092     if ( !m_pPopupMenu )
1093     {
1094         m_pPopupMenu = new QPopupMenu( NULL, "popup_menu" );
1095 
1096         m_nPopupMenuEnabledItem = m_pPopupMenu->insertItem( "" );
1097         m_nPopupMenuDisabledItem = m_pPopupMenu->insertItem( "" );
1098 
1099         m_pPopupMenu->setItemEnabled( m_nPopupMenuEnabledItem, true );
1100         m_pPopupMenu->setItemEnabled( m_nPopupMenuDisabledItem, false );
1101     }
1102 
1103     QRect qRect = region2QRect( rControlRegion );
1104 
1105     m_pPopupMenu->move( qRect.topLeft() );
1106     m_pPopupMenu->resize( qRect.size() );
1107 
1108     return m_pPopupMenu;
1109 }
1110 
progressBar(const Rectangle & rControlRegion)1111 QProgressBar *WidgetPainter::progressBar( const Rectangle& rControlRegion )
1112 {
1113     if ( !m_pProgressBar )
1114 	m_pProgressBar = new QProgressBar( NULL, "progress_bar" );
1115 
1116     QRect qRect = region2QRect( rControlRegion );
1117 
1118     m_pProgressBar->move( qRect.topLeft() );
1119     m_pProgressBar->resize( qRect.size() );
1120 
1121     return m_pProgressBar;
1122 }
1123 
vclStateValue2SFlags(ControlState nState,const ImplControlValue & aValue)1124 QStyle::SFlags WidgetPainter::vclStateValue2SFlags( ControlState nState,
1125 	const ImplControlValue& aValue )
1126 {
1127     QStyle::SFlags nStyle =
1128 	( (nState & CTRL_STATE_DEFAULT)?  QStyle::Style_ButtonDefault: QStyle::Style_Default ) |
1129 	( (nState & CTRL_STATE_ENABLED)?  QStyle::Style_Enabled:       QStyle::Style_Default ) |
1130 	( (nState & CTRL_STATE_FOCUSED)?  QStyle::Style_HasFocus:      QStyle::Style_Default ) |
1131 	( (nState & CTRL_STATE_PRESSED)?  QStyle::Style_Down:          QStyle::Style_Raised )  |
1132 	( (nState & CTRL_STATE_SELECTED)? QStyle::Style_Selected :     QStyle::Style_Default ) |
1133 	( (nState & CTRL_STATE_ROLLOVER)? QStyle::Style_MouseOver:     QStyle::Style_Default );
1134 	//TODO ( (nState & CTRL_STATE_HIDDEN)?   QStyle::Style_: QStyle::Style_Default ) |
1135 
1136     switch ( aValue.getTristateVal() )
1137     {
1138 	case BUTTONVALUE_ON:    nStyle |= QStyle::Style_On;       break;
1139 	case BUTTONVALUE_OFF:   nStyle |= QStyle::Style_Off;      break;
1140 	case BUTTONVALUE_MIXED: nStyle |= QStyle::Style_NoChange; break;
1141     default: break;
1142     }
1143 
1144     return nStyle;
1145 }
1146 
region2QRect(const Rectangle & rControlRegion)1147 QRect WidgetPainter::region2QRect( const Rectangle& rControlRegion )
1148 {
1149     return QRect( QPoint( rControlRegion.Left(), rControlRegion.Top() ),
1150                   QPoint( rControlRegion.Right(), rControlRegion.Bottom() ) );
1151 }
1152 
1153 /** Instance of WidgetPainter.
1154 
1155     It is used to paint the widgets requested by NWF.
1156 */
1157 static WidgetPainter *pWidgetPainter;
1158 
1159 class KDESalGraphics : public X11SalGraphics
1160 {
1161   public:
KDESalGraphics()1162 	KDESalGraphics() {}
~KDESalGraphics()1163 	virtual ~KDESalGraphics() {}
1164 	virtual sal_Bool IsNativeControlSupported( ControlType nType, ControlPart nPart );
1165 	virtual sal_Bool hitTestNativeControl( ControlType nType, ControlPart nPart,
1166 									   const Rectangle& rControlRegion, const Point& aPos,
1167 									   sal_Bool& rIsInside );
1168 	virtual sal_Bool drawNativeControl( ControlType nType, ControlPart nPart,
1169 									const Rectangle& rControlRegion, ControlState nState,
1170 									const ImplControlValue& aValue,
1171 									const OUString& aCaption );
1172 	virtual sal_Bool drawNativeControlText( ControlType nType, ControlPart nPart,
1173 										const Rectangle& rControlRegion, ControlState nState,
1174 										const ImplControlValue& aValue,
1175 										const OUString& aCaption );
1176 	virtual sal_Bool getNativeControlRegion( ControlType nType, ControlPart nPart,
1177 										 const Rectangle& rControlRegion, ControlState nState,
1178 										 const ImplControlValue& aValue,
1179 										 const OUString& aCaption,
1180 										 Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion );
1181 };
1182 
1183 /** What widgets can be drawn the native way.
1184 
1185     @param nType
1186     Type of the widget.
1187 
1188     @param nPart
1189     Specification of the widget's part if it consists of more than one.
1190 
1191     @return sal_True if the platform supports native drawing of the widget nType
1192     defined by nPart.
1193 */
IsNativeControlSupported(ControlType nType,ControlPart nPart)1194 sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
1195 {
1196     return
1197 	( (nType == CTRL_PUSHBUTTON)  && (nPart == PART_ENTIRE_CONTROL) ) ||
1198 	( (nType == CTRL_RADIOBUTTON) && (nPart == PART_ENTIRE_CONTROL) ) ||
1199 	( (nType == CTRL_CHECKBOX)    && (nPart == PART_ENTIRE_CONTROL) ) ||
1200 	( (nType == CTRL_COMBOBOX)    && (nPart == PART_ENTIRE_CONTROL || nPart == HAS_BACKGROUND_TEXTURE) ) ||
1201 	( (nType == CTRL_EDITBOX)     && (nPart == PART_ENTIRE_CONTROL || nPart == HAS_BACKGROUND_TEXTURE) ) ||
1202 	( (nType == CTRL_LISTBOX)     && (nPart == PART_ENTIRE_CONTROL || nPart == PART_WINDOW || nPart == HAS_BACKGROUND_TEXTURE ) ) ||
1203 	( (nType == CTRL_SPINBOX)     && (nPart == PART_ENTIRE_CONTROL || nPart == HAS_BACKGROUND_TEXTURE) ) ||
1204 	// no CTRL_SPINBUTTONS for KDE
1205 	( (nType == CTRL_TAB_ITEM)    && (nPart == PART_ENTIRE_CONTROL) ) ||
1206 	( (nType == CTRL_TAB_PANE)    && (nPart == PART_ENTIRE_CONTROL) ) ||
1207 	// no CTRL_TAB_BODY for KDE
1208 	( (nType == CTRL_SCROLLBAR)   && (nPart == PART_ENTIRE_CONTROL || nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT) ) ||
1209 	( (nType == CTRL_SCROLLBAR)   && (nPart == HAS_THREE_BUTTONS) ) || // TODO small optimization is possible here: return this only if the style really has 3 buttons
1210 	// CTRL_GROUPBOX not supported
1211 	// CTRL_FIXEDLINE not supported
1212 	// CTRL_FIXEDBORDER not supported
1213     ( (nType == CTRL_TOOLBAR)     && (nPart == PART_ENTIRE_CONTROL ||
1214                                       nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ||
1215                                       nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ||
1216                                       nPart == PART_BUTTON) ) ||
1217     ( (nType == CTRL_MENUBAR)     && (nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM) ) ||
1218     ( (nType == CTRL_MENU_POPUP)  && (nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM) ) ||
1219 	( (nType == CTRL_PROGRESS)    && (nPart == PART_ENTIRE_CONTROL) )
1220         ;
1221 }
1222 
1223 
1224 /** Test whether the position is in the native widget.
1225 
1226     If the return value is sal_True, bIsInside contains information whether
1227     aPos was or was not inside the native widget specified by the
1228     nType/nPart combination.
1229 */
hitTestNativeControl(ControlType nType,ControlPart nPart,const Rectangle & rControlRegion,const Point & rPos,sal_Bool & rIsInside)1230 sal_Bool KDESalGraphics::hitTestNativeControl( ControlType nType, ControlPart nPart,
1231 										   const Rectangle& rControlRegion, const Point& rPos,
1232 										   sal_Bool& rIsInside )
1233 {
1234     if ( nType == CTRL_SCROLLBAR )
1235     {
1236     // make position relative to rControlRegion
1237     Point aPos = rPos - rControlRegion.TopLeft();
1238 	rIsInside = sal_False;
1239 
1240 	sal_Bool bHorizontal = ( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT );
1241 
1242 	QScrollBar *pScrollBar = pWidgetPainter->scrollBar( rControlRegion,
1243 		bHorizontal, ImplControlValue() );
1244 	QRect qRectSubLine = kapp->style().querySubControlMetrics(
1245 		QStyle::CC_ScrollBar, pScrollBar, QStyle::SC_ScrollBarSubLine );
1246 	QRect qRectAddLine = kapp->style().querySubControlMetrics(
1247 		QStyle::CC_ScrollBar, pScrollBar, QStyle::SC_ScrollBarAddLine );
1248 
1249 	// There are 2 buttons on the right/bottom side of the scrollbar
1250 	sal_Bool bTwoSubButtons = sal_False;
1251 
1252 	// It is a Platinum style scroll bar
1253 	sal_Bool bPlatinumStyle = sal_False;
1254 
1255 	// Workaround for Platinum and 3 button style scroll bars.
1256 	// It makes the right/down button bigger.
1257 	if ( bHorizontal )
1258 	{
1259 	    qRectAddLine.setLeft( kapp->style().querySubControlMetrics(
1260 			QStyle::CC_ScrollBar, pScrollBar,
1261 			QStyle::SC_ScrollBarAddPage ).right() + 1 );
1262 	    if ( qRectAddLine.width() > qRectSubLine.width() )
1263 		bTwoSubButtons = sal_True;
1264 	    if ( qRectSubLine.left() > kapp->style().querySubControlMetrics( QStyle::CC_ScrollBar, pScrollBar, QStyle::SC_ScrollBarSubPage ).left() )
1265 		bPlatinumStyle = sal_True;
1266 	}
1267 	else
1268 	{
1269 	    qRectAddLine.setTop( kapp->style().querySubControlMetrics(
1270 			QStyle::CC_ScrollBar, pScrollBar,
1271 			QStyle::SC_ScrollBarAddPage ).bottom() + 1 );
1272 	    if ( qRectAddLine.height() > qRectSubLine.height() )
1273 		bTwoSubButtons = sal_True;
1274 	    if ( qRectSubLine.top() > kapp->style().querySubControlMetrics( QStyle::CC_ScrollBar, pScrollBar, QStyle::SC_ScrollBarSubPage ).top() )
1275 		bPlatinumStyle = sal_True;
1276 	}
1277 
1278 	switch ( nPart )
1279 	{
1280 	    case PART_BUTTON_LEFT:
1281 		if ( !bPlatinumStyle && qRectSubLine.contains( aPos.getX(), aPos.getY() ) )
1282 		    rIsInside = sal_True;
1283 		else if ( bTwoSubButtons )
1284 		{
1285 		    qRectAddLine.setWidth( qRectAddLine.width() / 2 );
1286 		    rIsInside = qRectAddLine.contains( aPos.getX(), aPos.getY() );
1287 		}
1288 		break;
1289 
1290 	    case PART_BUTTON_UP:
1291 		if ( !bPlatinumStyle && qRectSubLine.contains( aPos.getX(), aPos.getY() ) )
1292 		    rIsInside = sal_True;
1293 		else if ( bTwoSubButtons )
1294 		{
1295 		    qRectAddLine.setHeight( qRectAddLine.height() / 2 );
1296 		    rIsInside = qRectAddLine.contains( aPos.getX(), aPos.getY() );
1297 		}
1298 		break;
1299 
1300 	    case PART_BUTTON_RIGHT:
1301 		if ( bTwoSubButtons )
1302 		    qRectAddLine.setLeft( qRectAddLine.left() + qRectAddLine.width() / 2 );
1303 
1304 		rIsInside = qRectAddLine.contains( aPos.getX(), aPos.getY() );
1305 		break;
1306 
1307 	    case PART_BUTTON_DOWN:
1308 		if ( bTwoSubButtons )
1309 		    qRectAddLine.setTop( qRectAddLine.top() + qRectAddLine.height() / 2 );
1310 
1311 		rIsInside = qRectAddLine.contains( aPos.getX(), aPos.getY() );
1312 		break;
1313 
1314         // cases PART_TRACK_HORZ_AREA and PART_TRACK_VERT_AREA
1315         default:
1316         return sal_False;
1317 	}
1318 
1319 	return sal_True;
1320     }
1321 
1322     return sal_False;
1323 }
1324 
1325 
1326 /** Draw the requested control described by nPart/nState.
1327 
1328     @param rControlRegion
1329     The bounding region of the complete control in VCL frame coordinates.
1330 
1331     @param aValue
1332     An optional value (tristate/numerical/string).
1333 
1334     @param aCaption
1335     A caption or title string (like button text etc.)
1336 */
drawNativeControl(ControlType nType,ControlPart nPart,const Rectangle & rControlRegion,ControlState nState,const ImplControlValue & aValue,const OUString &)1337 sal_Bool KDESalGraphics::drawNativeControl( ControlType nType, ControlPart nPart,
1338 										const Rectangle& rControlRegion, ControlState nState,
1339 										const ImplControlValue& aValue,
1340 										const OUString& )
1341 {
1342     sal_Bool bReturn = sal_False;
1343 
1344     Display *dpy = GetXDisplay();
1345     XLIB_Window drawable = GetDrawable();
1346     GC gc = SelectPen(); //SelectFont(); // GC with current clipping region set
1347 
1348     if ( (nType == CTRL_PUSHBUTTON) && (nPart == PART_ENTIRE_CONTROL) )
1349     {
1350 	bReturn = pWidgetPainter->drawStyledWidget(
1351 		pWidgetPainter->pushButton( rControlRegion, (nState & CTRL_STATE_DEFAULT) ),
1352 		nState, aValue,
1353 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1354     }
1355     else if ( (nType == CTRL_RADIOBUTTON) && (nPart == PART_ENTIRE_CONTROL) )
1356     {
1357 	bReturn = pWidgetPainter->drawStyledWidget(
1358 		pWidgetPainter->radioButton( rControlRegion ),
1359 		nState, aValue,
1360 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1361     }
1362     else if ( (nType == CTRL_CHECKBOX) && (nPart == PART_ENTIRE_CONTROL) )
1363     {
1364 	bReturn = pWidgetPainter->drawStyledWidget(
1365 		pWidgetPainter->checkBox( rControlRegion ),
1366 		nState, aValue,
1367 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1368     }
1369     else if ( (nType == CTRL_COMBOBOX) && (nPart == PART_ENTIRE_CONTROL) )
1370     {
1371 	bReturn = pWidgetPainter->drawStyledWidget(
1372 		pWidgetPainter->comboBox( rControlRegion, sal_True ),
1373 		nState, aValue,
1374 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1375     }
1376     else if ( (nType == CTRL_EDITBOX) && (nPart == PART_ENTIRE_CONTROL) )
1377     {
1378 	bReturn = pWidgetPainter->drawStyledWidget(
1379 		pWidgetPainter->lineEdit( rControlRegion ),
1380 		nState, aValue,
1381 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1382     }
1383     else if ( (nType == CTRL_LISTBOX) && (nPart == PART_ENTIRE_CONTROL) )
1384     {
1385 	bReturn = pWidgetPainter->drawStyledWidget(
1386 		pWidgetPainter->comboBox( rControlRegion, sal_False ),
1387 		nState, aValue,
1388 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1389     }
1390     else if ( (nType == CTRL_LISTBOX) && (nPart == PART_WINDOW) )
1391     {
1392 	bReturn = pWidgetPainter->drawStyledWidget(
1393 		pWidgetPainter->listView( rControlRegion ),
1394 		nState, aValue,
1395 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1396     }
1397     else if ( (nType == CTRL_SPINBOX) && (nPart == PART_ENTIRE_CONTROL) )
1398     {
1399 	bReturn = pWidgetPainter->drawStyledWidget(
1400 		pWidgetPainter->spinWidget( rControlRegion ),
1401 		nState, aValue,
1402 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1403     }
1404     else if ( (nType==CTRL_TAB_ITEM) && (nPart == PART_ENTIRE_CONTROL) )
1405     {
1406 	bReturn = pWidgetPainter->drawStyledWidget(
1407 		pWidgetPainter->tabBar( rControlRegion ),
1408 		nState, aValue,
1409 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1410     }
1411     else if ( (nType==CTRL_TAB_PANE) && (nPart == PART_ENTIRE_CONTROL) )
1412     {
1413 	bReturn = pWidgetPainter->drawStyledWidget(
1414 		pWidgetPainter->tabWidget( rControlRegion ),
1415 		nState, aValue,
1416 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1417     }
1418     else if ( (nType == CTRL_SCROLLBAR) && (nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT) )
1419     {
1420 	bReturn = pWidgetPainter->drawStyledWidget(
1421 		pWidgetPainter->scrollBar( rControlRegion, nPart == PART_DRAW_BACKGROUND_HORZ, aValue ),
1422 		nState, aValue,
1423 		dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1424     }
1425     else if ( (nType == CTRL_TOOLBAR) && (nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT || nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
1426     {
1427         bReturn = pWidgetPainter->drawStyledWidget(
1428                 pWidgetPainter->toolBar( rControlRegion, nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_THUMB_VERT ),
1429                 nState, aValue,
1430                 dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc, nPart );
1431     }
1432     else if ( (nType == CTRL_TOOLBAR) && (nPart == PART_BUTTON) )
1433     {
1434         bReturn = pWidgetPainter->drawStyledWidget(
1435                 pWidgetPainter->toolButton( rControlRegion ),
1436                 nState, aValue,
1437                 dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc, nPart );
1438     }
1439     else if ( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM) )
1440     {
1441         bReturn = pWidgetPainter->drawStyledWidget(
1442                 pWidgetPainter->menuBar( rControlRegion ),
1443                 nState, aValue,
1444                 dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc, nPart );
1445     }
1446     else if ( (nType == CTRL_MENU_POPUP) && (nPart == PART_ENTIRE_CONTROL || nPart == PART_MENU_ITEM) )
1447     {
1448         bReturn = pWidgetPainter->drawStyledWidget(
1449                 pWidgetPainter->popupMenu( rControlRegion ),
1450                 nState, aValue,
1451                 dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1452     }
1453     else if ( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) )
1454     {
1455         bReturn = pWidgetPainter->drawStyledWidget(
1456                 pWidgetPainter->progressBar( rControlRegion ),
1457                 nState, aValue,
1458                 dpy, drawable, GetScreenNumber(), GetVisual().GetDepth(), gc );
1459     }
1460 
1461     return bReturn;
1462 }
1463 
1464 
1465 /** Draw text on the widget.
1466 
1467     OPTIONAL. Draws the requested text for the control described by nPart/nState.
1468     Used if text is not drawn by DrawNativeControl().
1469 
1470     @param rControlRegion
1471     The bounding region of the complete control in VCL frame coordinates.
1472 
1473     @param aValue
1474     An optional value (tristate/numerical/string)
1475 
1476     @param aCaption
1477     A caption or title string (like button text etc.)
1478 */
drawNativeControlText(ControlType,ControlPart,const Rectangle &,ControlState,const ImplControlValue &,const OUString &)1479 sal_Bool KDESalGraphics::drawNativeControlText( ControlType, ControlPart,
1480 											const Rectangle&, ControlState,
1481 											const ImplControlValue&,
1482 											const OUString& )
1483 {
1484     return sal_False;
1485 }
1486 
1487 /** Check if the bounding regions match.
1488 
1489     If the return value is sal_True, rNativeBoundingRegion
1490     contains the true bounding region covered by the control
1491     including any adornment, while rNativeContentRegion contains the area
1492     within the control that can be safely drawn into without drawing over
1493     the borders of the control.
1494 
1495     @param rControlRegion
1496     The bounding region of the control in VCL frame coordinates.
1497 
1498     @param aValue
1499     An optional value (tristate/numerical/string)
1500 
1501     @param aCaption
1502     A caption or title string (like button text etc.)
1503 */
getNativeControlRegion(ControlType nType,ControlPart nPart,const Rectangle & rControlRegion,ControlState nState,const ImplControlValue &,const OUString &,Rectangle & rNativeBoundingRegion,Rectangle & rNativeContentRegion)1504 sal_Bool KDESalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart,
1505 											 const Rectangle& rControlRegion, ControlState nState,
1506 											 const ImplControlValue&,
1507 											 const OUString&,
1508 											 Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion )
1509 {
1510     sal_Bool bReturn = sal_False;
1511     QRect qBoundingRect = WidgetPainter::region2QRect( rControlRegion );
1512     QRect qRect;
1513 
1514     QWidget *pWidget = NULL;
1515     switch ( nType )
1516     {
1517 	// Metrics of the push button
1518 	case CTRL_PUSHBUTTON:
1519 	    pWidget = pWidgetPainter->pushButton( rControlRegion, ( nState & CTRL_STATE_DEFAULT ) );
1520 
1521 	    switch ( nPart )
1522 	    {
1523 		case PART_ENTIRE_CONTROL:
1524 		    qRect = qBoundingRect;
1525 
1526 		    if ( nState & CTRL_STATE_DEFAULT )
1527 		    {
1528 			int nIndicatorSize = kapp->style().pixelMetric(
1529 				QStyle::PM_ButtonDefaultIndicator, pWidget );
1530 			qBoundingRect.addCoords( -nIndicatorSize, -nIndicatorSize,
1531 				nIndicatorSize, nIndicatorSize );
1532 			bReturn = sal_True;
1533 		    }
1534 		    break;
1535 	    }
1536 	    break;
1537 
1538         // Metrics of the radio button
1539         case CTRL_RADIOBUTTON:
1540             pWidget = pWidgetPainter->radioButton( rControlRegion );
1541 
1542             if ( nPart == PART_ENTIRE_CONTROL )
1543             {
1544                 qRect.setWidth( kapp->style().pixelMetric( QStyle::PM_ExclusiveIndicatorWidth, pWidget ) );
1545                 qRect.setHeight( kapp->style().pixelMetric( QStyle::PM_ExclusiveIndicatorHeight, pWidget ) );
1546 
1547                 bReturn = sal_True;
1548             }
1549             break;
1550 
1551         // Metrics of the check box
1552         case CTRL_CHECKBOX:
1553             pWidget = pWidgetPainter->checkBox( rControlRegion );
1554 
1555             if ( nPart == PART_ENTIRE_CONTROL )
1556             {
1557                 qRect.setWidth( kapp->style().pixelMetric( QStyle::PM_IndicatorWidth, pWidget ) );
1558                 qRect.setHeight( kapp->style().pixelMetric( QStyle::PM_IndicatorHeight, pWidget ) );
1559 
1560                 bReturn = sal_True;
1561             }
1562             break;
1563 
1564 	// Metrics of the combo box
1565 	case CTRL_COMBOBOX:
1566 	case CTRL_LISTBOX:
1567 	    pWidget = pWidgetPainter->comboBox( rControlRegion, ( nType == CTRL_COMBOBOX ) );
1568 	    switch ( nPart )
1569 	    {
1570 		case PART_BUTTON_DOWN:
1571 		    qRect = kapp->style().querySubControlMetrics(
1572 			    QStyle::CC_ComboBox, pWidget, QStyle::SC_ComboBoxArrow );
1573 		    qRect.setLeft( kapp->style().querySubControlMetrics(
1574 			    QStyle::CC_ComboBox, pWidget,
1575 			    QStyle::SC_ComboBoxEditField ).right() + 1 );
1576             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1577 		    bReturn = sal_True;
1578 		    break;
1579 
1580 		case PART_SUB_EDIT:
1581 		    qRect = kapp->style().querySubControlMetrics(
1582 			    QStyle::CC_ComboBox, pWidget, QStyle::SC_ComboBoxEditField );
1583             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1584 		    bReturn = sal_True;
1585 		    break;
1586 	    }
1587 	    break;
1588 
1589 	// Metrics of the spin box
1590 	case CTRL_SPINBOX:
1591 	    pWidget = pWidgetPainter->spinWidget( rControlRegion );
1592 	    switch ( nPart )
1593 	    {
1594 		case PART_BUTTON_UP:
1595 		    qRect = kapp->style().querySubControlMetrics(
1596 			    QStyle::CC_SpinWidget, pWidget, QStyle::SC_SpinWidgetUp );
1597 		    bReturn = sal_True;
1598             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1599 		    break;
1600 
1601 		case PART_BUTTON_DOWN:
1602 		    qRect = kapp->style().querySubControlMetrics(
1603 			    QStyle::CC_SpinWidget, pWidget, QStyle::SC_SpinWidgetDown );
1604 		    bReturn = sal_True;
1605             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1606 		    break;
1607 
1608         case PART_SUB_EDIT:
1609 		    qRect = kapp->style().querySubControlMetrics(
1610 			    QStyle::CC_SpinWidget, pWidget, QStyle::SC_SpinWidgetEditField );
1611             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1612 		    bReturn = sal_True;
1613 		    break;
1614 	    }
1615 	    break;
1616 
1617 	// Metrics of the scroll bar
1618 	case CTRL_SCROLLBAR:
1619 	    pWidget = pWidgetPainter->scrollBar( rControlRegion,
1620 		    ( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT ),
1621 		    ImplControlValue() );
1622 	    switch ( nPart )
1623 	    {
1624 		case PART_BUTTON_LEFT:
1625 		case PART_BUTTON_UP:
1626 		    qRect = kapp->style().querySubControlMetrics(
1627 			    QStyle::CC_ScrollBar, pWidget, QStyle::SC_ScrollBarSubLine );
1628 
1629 		    // Workaround for Platinum style scroll bars. It makes the
1630 		    // left/up button invisible.
1631 		    if ( nPart == PART_BUTTON_LEFT )
1632 		    {
1633 			if ( qRect.left() > kapp->style().querySubControlMetrics(
1634 				    QStyle::CC_ScrollBar, pWidget,
1635 				    QStyle::SC_ScrollBarSubPage ).left() )
1636 			{
1637 			    qRect.setLeft( 0 );
1638 			    qRect.setRight( 0 );
1639 			}
1640 		    }
1641 		    else
1642 		    {
1643 			if ( qRect.top() > kapp->style().querySubControlMetrics(
1644 				    QStyle::CC_ScrollBar, pWidget,
1645 				    QStyle::SC_ScrollBarSubPage ).top() )
1646 			{
1647 			    qRect.setTop( 0 );
1648 			    qRect.setBottom( 0 );
1649 			}
1650 		    }
1651 
1652             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1653 
1654 		    bReturn = sal_True;
1655 		    break;
1656 
1657 		case PART_BUTTON_RIGHT:
1658 		case PART_BUTTON_DOWN:
1659 		    qRect = kapp->style().querySubControlMetrics(
1660 			    QStyle::CC_ScrollBar, pWidget, QStyle::SC_ScrollBarAddLine );
1661 
1662 		    // Workaround for Platinum and 3 button style scroll bars.
1663 		    // It makes the right/down button bigger.
1664 		    if ( nPart == PART_BUTTON_RIGHT )
1665 			qRect.setLeft( kapp->style().querySubControlMetrics(
1666 				    QStyle::CC_ScrollBar, pWidget,
1667 				    QStyle::SC_ScrollBarAddPage ).right() + 1 );
1668 		    else
1669 			qRect.setTop( kapp->style().querySubControlMetrics(
1670 				    QStyle::CC_ScrollBar, pWidget,
1671 				    QStyle::SC_ScrollBarAddPage ).bottom() + 1 );
1672 
1673             qRect.moveBy( qBoundingRect.left(), qBoundingRect.top() );
1674 
1675 		    bReturn = sal_True;
1676 		    break;
1677 	    }
1678             break;
1679     }
1680 
1681     // Fill rNativeBoundingRegion and rNativeContentRegion
1682     if ( bReturn )
1683     {
1684 	// Bounding region
1685 	Point aBPoint( qBoundingRect.x(), qBoundingRect.y() );
1686 	Size aBSize( qBoundingRect.width(), qBoundingRect.height() );
1687 	rNativeBoundingRegion = Rectangle( aBPoint, aBSize );
1688 
1689 	// Region of the content
1690 	Point aPoint( qRect.x(), qRect.y() );
1691 	Size  aSize( qRect.width(), qRect.height() );
1692 	rNativeContentRegion = Rectangle( aPoint, aSize );
1693     }
1694 
1695     return bReturn;
1696 }
1697 
1698 // -----------------------------------------------------------------------
1699 // KDESalFrame implementation
1700 // -----------------------------------------------------------------------
1701 
KDESalFrame(SalFrame * pParent,sal_uLong nStyle)1702 KDESalFrame::KDESalFrame( SalFrame* pParent, sal_uLong nStyle ) :
1703     X11SalFrame( pParent, nStyle )
1704 {
1705 }
1706 
Show(sal_Bool bVisible,sal_Bool bNoActivate)1707 void KDESalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
1708 {
1709     if ( !GetParent() && ! (GetStyle() & SAL_FRAME_STYLE_INTRO) )
1710     {
1711         KDEXLib* pXLib = static_cast<KDEXLib*>(GetDisplay()->GetXLib());
1712         pXLib->doStartup();
1713     }
1714     X11SalFrame::Show( bVisible, bNoActivate );
1715 }
1716 
1717 /** Helper function to convert colors.
1718 */
toColor(const QColor & rColor)1719 static Color toColor( const QColor &rColor )
1720 {
1721     return Color( rColor.red(), rColor.green(), rColor.blue() );
1722 }
1723 
1724 /** Helper function to read untranslated text entry from KConfig configuration repository.
1725 */
readEntryUntranslated(KConfig * pConfig,const char * pKey)1726 static OUString readEntryUntranslated( KConfig *pConfig, const char *pKey )
1727 {
1728     return OUString::createFromAscii( pConfig->readEntryUntranslated( pKey ).ascii() );
1729 }
1730 
1731 /** Helper function to read color from KConfig configuration repository.
1732 */
readColor(KConfig * pConfig,const char * pKey)1733 static Color readColor( KConfig *pConfig, const char *pKey )
1734 {
1735     return toColor( pConfig->readColorEntry( pKey ) );
1736 }
1737 
1738 /** Helper function to add information to Font from QFont.
1739 
1740     Mostly grabbed from the Gtk+ vclplug (salnativewidgets-gtk.cxx).
1741 */
toFont(const QFont & rQFont,const::com::sun::star::lang::Locale & rLocale)1742 static Font toFont( const QFont &rQFont, const ::com::sun::star::lang::Locale& rLocale )
1743 {
1744     psp::FastPrintFontInfo aInfo;
1745     QFontInfo qFontInfo( rQFont );
1746 
1747     // set family name
1748     aInfo.m_aFamilyName = String( rQFont.family().utf8(), RTL_TEXTENCODING_UTF8 );
1749 
1750     // set italic
1751     aInfo.m_eItalic = ( qFontInfo.italic()? psp::italic::Italic: psp::italic::Upright );
1752 
1753     // set weight
1754     int nWeight = qFontInfo.weight();
1755     if ( nWeight <= QFont::Light )
1756         aInfo.m_eWeight = psp::weight::Light;
1757     else if ( nWeight <= QFont::Normal )
1758         aInfo.m_eWeight = psp::weight::Normal;
1759     else if ( nWeight <= QFont::DemiBold )
1760         aInfo.m_eWeight = psp::weight::SemiBold;
1761     else if ( nWeight <= QFont::Bold )
1762         aInfo.m_eWeight = psp::weight::Bold;
1763     else
1764         aInfo.m_eWeight = psp::weight::UltraBold;
1765 
1766     // set width
1767     int nStretch = rQFont.stretch();
1768     if ( nStretch <= QFont::UltraCondensed )
1769         aInfo.m_eWidth = psp::width::UltraCondensed;
1770     else if ( nStretch <= QFont::ExtraCondensed )
1771         aInfo.m_eWidth = psp::width::ExtraCondensed;
1772     else if ( nStretch <= QFont::Condensed )
1773         aInfo.m_eWidth = psp::width::Condensed;
1774     else if ( nStretch <= QFont::SemiCondensed )
1775         aInfo.m_eWidth = psp::width::SemiCondensed;
1776     else if ( nStretch <= QFont::Unstretched )
1777         aInfo.m_eWidth = psp::width::Normal;
1778     else if ( nStretch <= QFont::SemiExpanded )
1779         aInfo.m_eWidth = psp::width::SemiExpanded;
1780     else if ( nStretch <= QFont::Expanded )
1781         aInfo.m_eWidth = psp::width::Expanded;
1782     else if ( nStretch <= QFont::ExtraExpanded )
1783         aInfo.m_eWidth = psp::width::ExtraExpanded;
1784     else
1785         aInfo.m_eWidth = psp::width::UltraExpanded;
1786 
1787 #if OSL_DEBUG_LEVEL > 1
1788     fprintf( stderr, "font name BEFORE system match: \"%s\"\n", OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1789 #endif
1790 
1791     // match font to e.g. resolve "Sans"
1792     psp::PrintFontManager::get().matchFont( aInfo, rLocale );
1793 
1794 #if OSL_DEBUG_LEVEL > 1
1795     fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
1796              aInfo.m_nID != 0 ? "succeeded" : "failed",
1797              OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1798 #endif
1799 
1800     // font height
1801     int nPointHeight = qFontInfo.pointSize();
1802     if ( nPointHeight <= 0 )
1803         nPointHeight = rQFont.pointSize();
1804 
1805     // Create the font
1806     Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
1807     if( aInfo.m_eWeight != psp::weight::Unknown )
1808         aFont.SetWeight( PspGraphics::ToFontWeight( aInfo.m_eWeight ) );
1809     if( aInfo.m_eWidth != psp::width::Unknown )
1810         aFont.SetWidthType( PspGraphics::ToFontWidth( aInfo.m_eWidth ) );
1811     if( aInfo.m_eItalic != psp::italic::Unknown )
1812         aFont.SetItalic( PspGraphics::ToFontItalic( aInfo.m_eItalic ) );
1813     if( aInfo.m_ePitch != psp::pitch::Unknown )
1814         aFont.SetPitch( PspGraphics::ToFontPitch( aInfo.m_ePitch ) );
1815 
1816     return aFont;
1817 }
1818 
1819 /** Implementation of KDE integration's main method.
1820 */
UpdateSettings(AllSettings & rSettings)1821 void KDESalFrame::UpdateSettings( AllSettings& rSettings )
1822 {
1823     StyleSettings aStyleSettings( rSettings.GetStyleSettings() );
1824 	bool bSetTitleFont = false;
1825 
1826     // WM settings
1827     KConfig *pConfig = KGlobal::config();
1828     if ( pConfig )
1829     {
1830         pConfig->setGroup( "WM" );
1831         const char *pKey;
1832 
1833         pKey = "activeBackground";
1834         if ( pConfig->hasKey( pKey ) )
1835             aStyleSettings.SetActiveColor( readColor( pConfig, pKey ) );
1836 
1837         pKey = "activeBlend";
1838         if ( pConfig->hasKey( pKey ) )
1839             aStyleSettings.SetActiveColor2( readColor( pConfig, pKey ) );
1840 
1841         pKey = "inactiveBackground";
1842         if ( pConfig->hasKey( pKey ) )
1843             aStyleSettings.SetDeactiveColor( readColor( pConfig, pKey ) );
1844 
1845         pKey = "inactiveBlend";
1846         if ( pConfig->hasKey( pKey ) )
1847             aStyleSettings.SetDeactiveColor2( readColor( pConfig, pKey ) );
1848 
1849         pKey = "inactiveForeground";
1850         if ( pConfig->hasKey( pKey ) )
1851             aStyleSettings.SetDeactiveTextColor( readColor( pConfig, pKey ) );
1852 
1853         pKey = "activeForeground";
1854         if ( pConfig->hasKey( pKey ) )
1855             aStyleSettings.SetActiveTextColor( readColor( pConfig, pKey ) );
1856 
1857         pKey = "titleFont";
1858         if ( pConfig->hasKey( pKey ) )
1859         {
1860             Font aFont = toFont( pConfig->readFontEntry( pKey ), rSettings.GetUILocale() );
1861             aStyleSettings.SetTitleFont( aFont );
1862 			bSetTitleFont = true;
1863         }
1864 
1865         pConfig->setGroup( "Icons" );
1866 
1867         pKey = "Theme";
1868         if ( pConfig->hasKey( pKey ) )
1869             aStyleSettings.SetPreferredSymbolsStyleName( readEntryUntranslated( pConfig, pKey ) );
1870     }
1871 
1872     // General settings
1873     QColorGroup qColorGroup = kapp->palette().active();
1874 
1875     Color aFore = toColor( qColorGroup.foreground() );
1876     Color aBack = toColor( qColorGroup.background() );
1877     Color aText = toColor( qColorGroup.text() );
1878     Color aBase = toColor( qColorGroup.base() );
1879 
1880     // Foreground
1881     aStyleSettings.SetRadioCheckTextColor( aFore );
1882     aStyleSettings.SetLabelTextColor( aFore );
1883     aStyleSettings.SetInfoTextColor( aFore );
1884     aStyleSettings.SetDialogTextColor( aFore );
1885     aStyleSettings.SetGroupTextColor( aFore );
1886 
1887     // Text
1888     aStyleSettings.SetFieldTextColor( aText );
1889     aStyleSettings.SetFieldRolloverTextColor( aText );
1890     aStyleSettings.SetWindowTextColor( aText );
1891     aStyleSettings.SetHelpTextColor( aText );
1892 
1893     // Base
1894     aStyleSettings.SetFieldColor( aBase );
1895     aStyleSettings.SetHelpColor( aBase );
1896     aStyleSettings.SetWindowColor( aBase );
1897     aStyleSettings.SetActiveTabColor( aBase );
1898 
1899     // Buttons
1900     aStyleSettings.SetButtonTextColor( toColor( qColorGroup.buttonText() ) );
1901     aStyleSettings.SetButtonRolloverTextColor( toColor( qColorGroup.buttonText() ) );
1902 
1903     // Disable color
1904     aStyleSettings.SetDisableColor( toColor( qColorGroup.mid() ) );
1905 
1906     // Workspace
1907     aStyleSettings.SetWorkspaceColor( toColor( qColorGroup.mid() ) );
1908 
1909     // Background
1910     aStyleSettings.Set3DColors( aBack );
1911     aStyleSettings.SetFaceColor( aBack );
1912     aStyleSettings.SetInactiveTabColor( aBack );
1913     aStyleSettings.SetDialogColor( aBack );
1914     if( aBack == COL_LIGHTGRAY )
1915         aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
1916     else
1917     {
1918         Color aColor2 = aStyleSettings.GetLightColor();
1919         aStyleSettings.
1920             SetCheckedColor( Color( (sal_uInt8)(((sal_uInt16)aBack.GetRed()+(sal_uInt16)aColor2.GetRed())/2),
1921                         (sal_uInt8)(((sal_uInt16)aBack.GetGreen()+(sal_uInt16)aColor2.GetGreen())/2),
1922                         (sal_uInt8)(((sal_uInt16)aBack.GetBlue()+(sal_uInt16)aColor2.GetBlue())/2)
1923                         ) );
1924     }
1925 
1926     // Selection
1927     aStyleSettings.SetHighlightColor( toColor( qColorGroup.highlight() ) );
1928     aStyleSettings.SetHighlightTextColor( toColor( qColorGroup.highlightedText() ) );
1929 
1930     // Font
1931     Font aFont = toFont( kapp->font(), rSettings.GetUILocale() );
1932 
1933     aStyleSettings.SetAppFont( aFont );
1934     aStyleSettings.SetHelpFont( aFont );
1935 	if( !bSetTitleFont )
1936 		aStyleSettings.SetTitleFont( aFont );
1937 	aStyleSettings.SetFloatTitleFont( aFont );
1938     aStyleSettings.SetMenuFont( aFont ); // will be changed according to pMenuBar
1939     aStyleSettings.SetToolFont( aFont ); // will be changed according to pToolBar
1940     aStyleSettings.SetLabelFont( aFont );
1941     aStyleSettings.SetInfoFont( aFont );
1942     aStyleSettings.SetRadioCheckFont( aFont );
1943     aStyleSettings.SetPushButtonFont( aFont );
1944     aStyleSettings.SetFieldFont( aFont );
1945     aStyleSettings.SetIconFont( aFont );
1946     aStyleSettings.SetGroupFont( aFont );
1947     int flash_time = QApplication::cursorFlashTime();
1948     aStyleSettings.SetCursorBlinkTime( flash_time != 0 ? flash_time/2 : STYLE_CURSOR_NOBLINKTIME );
1949 
1950     KMainWindow qMainWindow;
1951     qMainWindow.createGUI( "/dev/null" ); // hack
1952 
1953     // Menu
1954     aStyleSettings.SetSkipDisabledInMenus( sal_True );
1955     KMenuBar *pMenuBar = qMainWindow.menuBar();
1956     if ( pMenuBar )
1957     {
1958         // Color
1959         QColorGroup qMenuCG = pMenuBar->colorGroup();
1960 
1961         // Menu text and background color, theme specific
1962         Color aMenuFore = toColor( qMenuCG.foreground() );
1963         Color aMenuBack = toColor( qMenuCG.background() );
1964         if ( kapp->style().inherits( "LightStyleV2" ) ||
1965              kapp->style().inherits( "LightStyleV3" ) ||
1966              ( kapp->style().inherits( "QMotifStyle" ) && !kapp->style().inherits( "QSGIStyle" ) ) ||
1967              kapp->style().inherits( "QWindowsStyle" ) )
1968         {
1969             aMenuFore = toColor( qMenuCG.buttonText() );
1970             aMenuBack = toColor( qMenuCG.button() );
1971         }
1972 
1973         aStyleSettings.SetMenuTextColor( aMenuFore );
1974         aStyleSettings.SetMenuBarTextColor( aMenuFore );
1975         aStyleSettings.SetMenuColor( aMenuBack );
1976         aStyleSettings.SetMenuBarColor( aMenuBack );
1977 
1978         aStyleSettings.SetMenuHighlightColor( toColor ( qMenuCG.highlight() ) );
1979 
1980         // Menu items higlight text color, theme specific
1981         if ( kapp->style().inherits( "HighContrastStyle" ) ||
1982              kapp->style().inherits( "KeramikStyle" ) ||
1983              kapp->style().inherits( "QWindowsStyle" ) ||
1984              kapp->style().inherits( "ThinKeramikStyle" ) ||
1985              kapp->style().inherits( "PlastikStyle" ) )
1986         {
1987             aStyleSettings.SetMenuHighlightTextColor( toColor ( qMenuCG.highlightedText() ) );
1988         }
1989         else
1990             aStyleSettings.SetMenuHighlightTextColor( aMenuFore );
1991 
1992         // set special menubar higlight text color
1993         if ( kapp->style().inherits( "HighContrastStyle" ) )
1994             ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = toColor( qMenuCG.highlightedText() );
1995         else
1996             ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = aMenuFore;
1997 
1998         // Font
1999         aFont = toFont( pMenuBar->font(), rSettings.GetUILocale() );
2000         aStyleSettings.SetMenuFont( aFont );
2001     }
2002 
2003     // Tool bar
2004     KToolBar *pToolBar = qMainWindow.toolBar();
2005     if ( pToolBar )
2006     {
2007         aFont = toFont( pToolBar->font(), rSettings.GetUILocale() );
2008         aStyleSettings.SetToolFont( aFont );
2009     }
2010 
2011     // Scroll bar size
2012     aStyleSettings.SetScrollBarSize( kapp->style().pixelMetric( QStyle::PM_ScrollBarExtent ) );
2013 
2014     rSettings.SetStyleSettings( aStyleSettings );
2015 }
2016 
GetGraphics()2017 SalGraphics* KDESalFrame::GetGraphics()
2018 {
2019     if( GetWindow() )
2020     {
2021         for( int i = 0; i < nMaxGraphics; i++ )
2022         {
2023             if( ! m_aGraphics[i].bInUse )
2024             {
2025                 m_aGraphics[i].bInUse = true;
2026                 if( ! m_aGraphics[i].pGraphics )
2027                 {
2028                     m_aGraphics[i].pGraphics = new KDESalGraphics();
2029                     m_aGraphics[i].pGraphics->Init( this, GetWindow(), GetScreenNumber() );
2030                 }
2031                 return m_aGraphics[i].pGraphics;
2032             }
2033         }
2034     }
2035 
2036     return NULL;
2037 }
2038 
ReleaseGraphics(SalGraphics * pGraphics)2039 void KDESalFrame::ReleaseGraphics( SalGraphics *pGraphics )
2040 {
2041     for( int i = 0; i < nMaxGraphics; i++ )
2042     {
2043         if( m_aGraphics[i].pGraphics == pGraphics )
2044         {
2045             m_aGraphics[i].bInUse = false;
2046             break;
2047         }
2048     }
2049 }
2050 
updateGraphics(bool bClear)2051 void KDESalFrame::updateGraphics( bool bClear )
2052 {
2053     Drawable aDrawable = bClear ? None : GetWindow();
2054     for( int i = 0; i < nMaxGraphics; i++ )
2055     {
2056         if( m_aGraphics[i].bInUse )
2057             m_aGraphics[i].pGraphics->SetDrawable( aDrawable, GetScreenNumber() );
2058     }
2059 }
2060 
~KDESalFrame()2061 KDESalFrame::~KDESalFrame()
2062 {
2063 }
2064 
~GraphicsHolder()2065 KDESalFrame::GraphicsHolder::~GraphicsHolder()
2066 {
2067 	delete pGraphics;
2068 }
2069 
2070 // -----------------------------------------------------------------------
2071 // KDESalInstance implementation
2072 // -----------------------------------------------------------------------
2073 
2074 SalFrame *
CreateFrame(SalFrame * pParent,sal_uLong nStyle)2075 KDESalInstance::CreateFrame( SalFrame *pParent, sal_uLong nStyle )
2076 {
2077 	return new KDESalFrame( pParent, nStyle );
2078 }
2079 
2080 // -----------------------------------------------------------------------
2081 // KDESalData pieces
2082 // -----------------------------------------------------------------------
2083 
2084 // Create the widget painter so we have some control over
2085 // the destruction sequence, so Qt doesn't die in action.
2086 
initNWF()2087 void KDEData::initNWF()
2088 {
2089     ImplSVData *pSVData = ImplGetSVData();
2090     // draw toolbars on separate lines
2091     pSVData->maNWFData.mbDockingAreaSeparateTB = true;
2092 
2093     pWidgetPainter = new WidgetPainter();
2094 }
2095 
deInitNWF()2096 void KDEData::deInitNWF()
2097 {
2098     delete pWidgetPainter;
2099     pWidgetPainter = NULL;
2100 
2101     // We have to destroy the style early
2102     kapp->setStyle( NULL );
2103 }
2104