1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include "vcl/svapp.hxx"
32 
33 #include "unx/gtk/gtkframe.hxx"
34 #include "unx/gtk/gtkdata.hxx"
35 #include "unx/gtk/gtkinst.hxx"
36 #include "unx/gtk/gtkgdi.hxx"
37 
38 #include "unx/pspgraphics.h"
39 #include "unx/saldata.hxx"
40 #include "unx/saldisp.hxx"
41 
42 #include <cstdio>
43 #include <cmath>
44 #include <vector>
45 #include <algorithm>
46 #include <hash_map>
47 
48 typedef struct _cairo_font_options cairo_font_options_t;
49 
50 // initialize statics
51 sal_Bool GtkSalGraphics::bThemeChanged = sal_True;
52 sal_Bool GtkSalGraphics::bNeedPixmapPaint = sal_False;
53 sal_Bool GtkSalGraphics::bGlobalNeedPixmapPaint = sal_False;
54 sal_Bool GtkSalGraphics::bToolbarGripWorkaround = sal_False;
55 sal_Bool GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround = sal_False;
56 
57 GtkSalGraphics::~GtkSalGraphics()
58 {
59 }
60 
61 
62 using namespace rtl;
63 
64 /*************************************
65  * Cached native widget objects
66  *************************************/
67 class NWPixmapCacheList;
68 class NWPixmapCache;
69 struct NWFWidgetData
70 {
71     GtkWidget *	gCacheWindow;
72     GtkWidget *	gDumbContainer;
73 
74     GtkWidget *	gBtnWidget;
75     GtkWidget *	gRadioWidget;
76     GtkWidget *	gRadioWidgetSibling;
77     GtkWidget *	gCheckWidget;
78     GtkWidget *	gScrollHorizWidget;
79     GtkWidget *	gScrollVertWidget;
80     GtkWidget *	gArrowWidget;
81     GtkWidget *	gDropdownWidget;
82     GtkWidget *	gEditBoxWidget;
83     GtkWidget *	gSpinButtonWidget;
84     GtkWidget *	gNotebookWidget;
85     GtkWidget *	gOptionMenuWidget;
86     GtkWidget *	gComboWidget;
87     GtkWidget *	gScrolledWindowWidget;
88     GtkWidget *  gToolbarWidget;
89     GtkWidget *  gToolbarButtonWidget;
90     GtkWidget *  gToolbarToggleWidget;
91     GtkWidget *  gHandleBoxWidget;
92     GtkWidget *  gMenubarWidget;
93     GtkWidget *  gMenuItemMenubarWidget;
94     GtkWidget *  gMenuWidget;
95     GtkWidget *  gMenuItemMenuWidget;
96     GtkWidget *  gMenuItemCheckMenuWidget;
97     GtkWidget *  gMenuItemRadioMenuWidget;
98     GtkWidget *  gImageMenuItem;
99     GtkWidget *  gTooltipPopup;
100     GtkWidget *  gProgressBar;
101     GtkWidget *  gTreeView;
102     GtkWidget *  gHScale;
103     GtkWidget *  gVScale;
104 
105     NWPixmapCacheList* gNWPixmapCacheList;
106     NWPixmapCache* gCacheTabItems;
107     NWPixmapCache* gCacheTabPages;
108 
109     NWFWidgetData() :
110         gCacheWindow( NULL ),
111         gDumbContainer( NULL ),
112         gBtnWidget( NULL ),
113         gRadioWidget( NULL ),
114         gRadioWidgetSibling( NULL ),
115         gCheckWidget( NULL ),
116         gScrollHorizWidget( NULL ),
117         gScrollVertWidget( NULL ),
118         gArrowWidget( NULL ),
119         gDropdownWidget( NULL ),
120         gEditBoxWidget( NULL ),
121         gSpinButtonWidget( NULL ),
122         gNotebookWidget( NULL ),
123         gOptionMenuWidget( NULL ),
124         gComboWidget( NULL ),
125         gScrolledWindowWidget( NULL ),
126         gToolbarWidget( NULL ),
127         gToolbarButtonWidget( NULL ),
128         gToolbarToggleWidget( NULL ),
129         gHandleBoxWidget( NULL ),
130         gMenubarWidget( NULL ),
131         gMenuItemMenubarWidget( NULL ),
132         gMenuWidget( NULL ),
133         gMenuItemMenuWidget( NULL ),
134         gMenuItemCheckMenuWidget( NULL ),
135         gMenuItemRadioMenuWidget( NULL ),
136         gImageMenuItem( NULL ),
137         gTooltipPopup( NULL ),
138         gProgressBar( NULL ),
139         gTreeView( NULL ),
140         gHScale( NULL ),
141         gVScale( NULL ),
142         gNWPixmapCacheList( NULL ),
143         gCacheTabItems( NULL ),
144         gCacheTabPages( NULL )
145     {}
146 };
147 
148 // Keep a hash table of Widgets->default flags so that we can
149 // easily and quickly reset each to a default state before using
150 // them
151 static std::hash_map<long, guint>	gWidgetDefaultFlags;
152 static std::vector<NWFWidgetData>   gWidgetData;
153 
154 static const GtkBorder aDefDefBorder		= { 1, 1, 1, 1 };
155 
156 // Some GTK defaults
157 #define MIN_ARROW_SIZE					11
158 #define BTN_CHILD_SPACING				1
159 #define MIN_SPIN_ARROW_WIDTH				6
160 
161 
162 static void NWEnsureGTKRadio			( int nScreen );
163 static void NWEnsureGTKButton			( int nScreen );
164 static void NWEnsureGTKCheck			( int nScreen );
165 static void NWEnsureGTKScrollbars		( int nScreen );
166 static void NWEnsureGTKArrow			( int nScreen );
167 static void NWEnsureGTKEditBox			( int nScreen );
168 static void NWEnsureGTKSpinButton		( int nScreen );
169 static void NWEnsureGTKNotebook			( int nScreen );
170 static void NWEnsureGTKOptionMenu		( int nScreen );
171 static void NWEnsureGTKCombo			( int nScreen );
172 static void NWEnsureGTKScrolledWindow	( int nScreen );
173 static void NWEnsureGTKToolbar			( int nScreen );
174 static void NWEnsureGTKMenubar          ( int nScreen );
175 static void NWEnsureGTKMenu             ( int nScreen );
176 static void NWEnsureGTKTooltip          ( int nScreen );
177 static void NWEnsureGTKProgressBar      ( int nScreen );
178 static void NWEnsureGTKTreeView         ( int nScreen );
179 static void NWEnsureGTKSlider           ( int nScreen );
180 
181 static void NWConvertVCLStateToGTKState( ControlState nVCLState, GtkStateType* nGTKState, GtkShadowType* nGTKShadow );
182 static void NWAddWidgetToCacheWindow( GtkWidget* widget, int nScreen );
183 static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState );
184 
185 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow );
186 
187 /*
188  * Individual helper functions
189  *
190  */
191 
192 //---
193 static Rectangle NWGetButtonArea( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
194 								const ImplControlValue& aValue, const OUString& rCaption );
195 
196 //---
197 static Rectangle NWGetEditBoxPixmapRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
198 							const ImplControlValue& aValue, const OUString& rCaption );
199 
200 static void NWPaintOneEditBox( int nScreen, GdkDrawable * gdkDrawable, GdkRectangle *gdkRect,
201                                ControlType nType, ControlPart nPart, Rectangle aEditBoxRect,
202                                ControlState nState, const ImplControlValue& aValue,
203                                const OUString& rCaption );
204 
205 //---
206 static Rectangle NWGetSpinButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
207 							const ImplControlValue& aValue, const OUString& rCaption );
208 
209 static void NWPaintOneSpinButton( int nScreen, GdkPixmap * pixmap, ControlType nType, ControlPart nPart, Rectangle aAreaRect,
210 							ControlState nState, const ImplControlValue& aValue,
211 							const OUString& rCaption );
212 //---
213 static Rectangle NWGetComboBoxButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
214 							const ImplControlValue& aValue, const OUString& rCaption );
215 
216 //---
217 static Rectangle NWGetListBoxButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
218 							const ImplControlValue& aValue, const OUString& rCaption );
219 
220 static Rectangle NWGetListBoxIndicatorRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
221 							const ImplControlValue& aValue, const OUString& rCaption );
222 
223 static Rectangle NWGetToolbarRect( int nScreen,
224                                    ControlType nType,
225                                    ControlPart nPart,
226                                    Rectangle aAreaRect,
227                                    ControlState nState,
228                                    const ImplControlValue& aValue,
229                                    const OUString& rCaption );
230 //---
231 
232 static Rectangle NWGetScrollButtonRect(	int nScreen, ControlPart nPart, Rectangle aAreaRect );
233 //---
234 
235 /*********************************************************
236  * PixmapCache
237  *********************************************************/
238 
239 // as some native widget drawing operations are pretty slow
240 // with certain themes (eg tabpages)
241 // this cache can be used to cache the corresponding pixmap
242 // see NWPaintGTKTabItem
243 
244 class NWPixmapCacheData
245 {
246 public:
247     ControlType m_nType;
248     ControlState m_nState;
249     Rectangle   m_pixmapRect;
250     GdkPixmap*  m_pixmap;
251 
252     NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0) {}
253     ~NWPixmapCacheData()
254         { SetPixmap( NULL ); };
255     void SetPixmap( GdkPixmap* pPixmap );
256 };
257 
258 class NWPixmapCache
259 {
260     int m_size;
261     int m_idx;
262     int m_screen;
263     NWPixmapCacheData* pData;
264 public:
265     NWPixmapCache( int nScreen );
266     ~NWPixmapCache();
267 
268     void SetSize( int n)
269         { delete [] pData; m_idx = 0; m_size = n; pData = new NWPixmapCacheData[m_size]; }
270     int GetSize() { return m_size; }
271 
272     sal_Bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap** pPixmap );
273     void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap* pPixmap );
274 
275     void ThemeChanged();
276 };
277 
278 class NWPixmapCacheList
279 {
280 public:
281     ::std::vector< NWPixmapCache* > mCaches;
282 
283     void AddCache( NWPixmapCache *pCache );
284     void RemoveCache( NWPixmapCache *pCache );
285     void ThemeChanged();
286 };
287 
288 // --- implementation ---
289 
290 void NWPixmapCacheData::SetPixmap( GdkPixmap* pPixmap )
291 {
292     if( m_pixmap )
293         g_object_unref( m_pixmap );
294 
295     m_pixmap = pPixmap;
296 
297     if( m_pixmap )
298         g_object_ref( m_pixmap );
299 }
300 
301 
302 NWPixmapCache::NWPixmapCache( int nScreen )
303 {
304     m_idx = 0;
305     m_size = 0;
306     m_screen = nScreen;
307     pData = NULL;
308     if( gWidgetData[m_screen].gNWPixmapCacheList )
309         gWidgetData[m_screen].gNWPixmapCacheList->AddCache(this);
310 }
311 NWPixmapCache::~NWPixmapCache()
312 {
313     if( gWidgetData[m_screen].gNWPixmapCacheList )
314         gWidgetData[m_screen].gNWPixmapCacheList->RemoveCache(this);
315     delete[] pData;
316 }
317 void NWPixmapCache::ThemeChanged()
318 {
319     // throw away cached pixmaps
320     int i;
321     for(i=0; i<m_size; i++)
322         pData[i].SetPixmap( NULL );
323 }
324 
325 sal_Bool  NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap** pPixmap )
326 {
327     aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag
328     int i;
329     for(i=0; i<m_size; i++)
330     {
331         if( pData[i].m_nType == aType &&
332             pData[i].m_nState == aState &&
333             pData[i].m_pixmapRect.GetWidth() == r_pixmapRect.GetWidth() &&
334             pData[i].m_pixmapRect.GetHeight() == r_pixmapRect.GetHeight() &&
335             pData[i].m_pixmap != NULL )
336         {
337             *pPixmap = pData[i].m_pixmap;
338             return sal_True;
339         }
340     }
341     return sal_False;
342 }
343 
344 void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap* pPixmap )
345 {
346     if( !(aState & CTRL_CACHING_ALLOWED) )
347         return;
348 
349     aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag
350     m_idx = (m_idx+1) % m_size; // just wrap
351     pData[m_idx].m_nType = aType;
352     pData[m_idx].m_nState = aState;
353     pData[m_idx].m_pixmapRect = r_pixmapRect;
354     pData[m_idx].SetPixmap( pPixmap );
355 }
356 
357 
358 void NWPixmapCacheList::AddCache( NWPixmapCache* pCache )
359 {
360     mCaches.push_back( pCache );
361 }
362 void NWPixmapCacheList::RemoveCache( NWPixmapCache* pCache )
363 {
364     ::std::vector< NWPixmapCache* >::iterator p;
365     p = ::std::find( mCaches.begin(), mCaches.end(), pCache );
366     if( p != mCaches.end() )
367         mCaches.erase( p );
368 }
369 void NWPixmapCacheList::ThemeChanged( )
370 {
371     ::std::vector< NWPixmapCache* >::iterator p = mCaches.begin();
372     while( p != mCaches.end() )
373     {
374         (*p)->ThemeChanged();
375         p++;
376     }
377 }
378 
379 
380 /*********************************************************
381  * Make border manipulation easier
382  *********************************************************/
383 inline void NW_gtk_border_set_from_border( GtkBorder& aDst, const GtkBorder * pSrc )
384 {
385 	aDst.left		= pSrc->left;
386 	aDst.top		= pSrc->top;
387 	aDst.right	= pSrc->right;
388 	aDst.bottom	= pSrc->bottom;
389 }
390 
391 
392 /*********************************************************
393  * Initialize GTK and local stuff
394  *********************************************************/
395 void GtkData::initNWF( void )
396 {
397     ImplSVData* pSVData = ImplGetSVData();
398 
399     // draw no border for popup menus (NWF draws its own)
400     pSVData->maNWFData.mbFlatMenu = true;
401 
402     // draw separate buttons for toolbox dropdown items
403     pSVData->maNWFData.mbToolboxDropDownSeparate = true;
404 
405     // small extra border around menu items
406     pSVData->maNWFData.mnMenuFormatExtraBorder = 1;
407 
408     // draw toolbars in separate lines
409     pSVData->maNWFData.mbDockingAreaSeparateTB = true;
410 
411     // open first menu on F10
412     pSVData->maNWFData.mbOpenMenuOnF10 = true;
413 
414     // omit GetNativeControl while painting (see brdwin.cxx)
415     pSVData->maNWFData.mbCanDrawWidgetAnySize = true;
416 
417     int nScreens = GetX11SalData()->GetDisplay()->GetScreenCount();
418     gWidgetData = std::vector<NWFWidgetData>( nScreens );
419     for( int i = 0; i < nScreens; i++ )
420         gWidgetData[i].gNWPixmapCacheList = new NWPixmapCacheList;
421 
422 
423     if( SalGetDesktopEnvironment().equalsAscii( "KDE" ) )
424     {
425         // #i97196# ensure a widget exists and the style engine was loaded
426         NWEnsureGTKButton( 0 );
427         if( g_type_from_name( "QtEngineStyle" ) )
428         {
429             // KDE 3.3 invented a bug in the qt<->gtk theme engine
430             // that makes direct rendering impossible: they totally
431             // ignore the clip rectangle passed to the paint methods
432             GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true;
433         }
434     }
435     static const char* pEnv = getenv( "SAL_GTK_USE_PIXMAPPAINT" );
436     if( pEnv && *pEnv )
437         GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true;
438 
439     #if OSL_DEBUG_LEVEL > 1
440     std::fprintf( stderr, "GtkPlugin: using %s NWF\n",
441              GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" );
442     #endif
443 }
444 
445 
446 /*********************************************************
447  * Release GTK and local stuff
448  *********************************************************/
449 void GtkData::deInitNWF( void )
450 {
451 
452     for( unsigned int i = 0; i < gWidgetData.size(); i++ )
453     {
454         // free up global widgets
455         // gtk_widget_destroy will in turn destroy the child hierarchy
456         // so only destroy disjunct hierachies
457         if( gWidgetData[i].gCacheWindow )
458             gtk_widget_destroy( gWidgetData[i].gCacheWindow );
459         if( gWidgetData[i].gMenuWidget )
460             gtk_widget_destroy( gWidgetData[i].gMenuWidget );
461         if( gWidgetData[i].gTooltipPopup )
462             gtk_widget_destroy( gWidgetData[i].gTooltipPopup );
463         delete gWidgetData[i].gCacheTabPages;
464         gWidgetData[i].gCacheTabPages = NULL;
465         delete gWidgetData[i].gCacheTabItems;
466         gWidgetData[i].gCacheTabItems = NULL;
467         delete gWidgetData[i].gNWPixmapCacheList;
468         gWidgetData[i].gNWPixmapCacheList = NULL;
469     }
470 }
471 
472 
473 /**********************************************************
474  * track clip region
475  **********************************************************/
476 void GtkSalGraphics::ResetClipRegion()
477 {
478     m_aClipRegion.SetNull();
479     X11SalGraphics::ResetClipRegion();
480 }
481 
482 bool GtkSalGraphics::setClipRegion( const Region& i_rClip )
483 {
484     m_aClipRegion = i_rClip;
485     bool bRet = X11SalGraphics::setClipRegion( m_aClipRegion );
486     if( m_aClipRegion.IsEmpty() )
487         m_aClipRegion.SetNull();
488     return bRet;
489 }
490 
491 void GtkSalGraphics::copyBits( const SalTwoRect* pPosAry,
492                                SalGraphics* pSrcGraphics )
493 {
494     GtkSalFrame* pFrame = GetGtkFrame();
495     XLIB_Window aWin = None;
496     if( pFrame && m_pWindow )
497     {
498         /* #i64117# some themes set the background pixmap VERY frequently */
499         GdkWindow* pWin = GTK_WIDGET(m_pWindow)->window;
500         if( pWin )
501         {
502             aWin = GDK_WINDOW_XWINDOW(pWin);
503             if( aWin != None )
504                 XSetWindowBackgroundPixmap( pFrame->getDisplay()->GetDisplay(),
505                                             aWin,
506                                             None );
507         }
508     }
509     X11SalGraphics::copyBits( pPosAry, pSrcGraphics );
510     if( pFrame && pFrame->getBackgroundPixmap() != None )
511         XSetWindowBackgroundPixmap( pFrame->getDisplay()->GetDisplay(),
512                                     aWin,
513                                     pFrame->getBackgroundPixmap() );
514 }
515 
516 /*
517  * IsNativeControlSupported()
518  *
519  *  Returns sal_True if the platform supports native
520  *  drawing of the control defined by nPart
521  */
522 sal_Bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
523 {
524 	if (
525 		((nType==CTRL_PUSHBUTTON)  && (nPart==PART_ENTIRE_CONTROL)) 	||
526  		((nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL))		||
527 		((nType==CTRL_CHECKBOX)    && (nPart==PART_ENTIRE_CONTROL))		||
528 		((nType==CTRL_SCROLLBAR) &&
529 				(  (nPart==PART_DRAW_BACKGROUND_HORZ)
530 				|| (nPart==PART_DRAW_BACKGROUND_VERT)
531 				|| (nPart==PART_ENTIRE_CONTROL)
532                 || (nPart==HAS_THREE_BUTTONS) )  				)	||
533 		((nType==CTRL_EDITBOX) &&
534 				(  (nPart==PART_ENTIRE_CONTROL)
535 				|| (nPart==HAS_BACKGROUND_TEXTURE) ) 			)	||
536 		((nType==CTRL_MULTILINE_EDITBOX) &&
537 				(  (nPart==PART_ENTIRE_CONTROL)
538 				|| (nPart==HAS_BACKGROUND_TEXTURE) ) 			)	||
539 		((nType==CTRL_SPINBOX) &&
540 				(  (nPart==PART_ENTIRE_CONTROL)
541 				|| (nPart==PART_ALL_BUTTONS)
542 				|| (nPart==HAS_BACKGROUND_TEXTURE) )			)	||
543 		((nType==CTRL_SPINBUTTONS) &&
544 				(  (nPart==PART_ENTIRE_CONTROL)
545 				|| (nPart==PART_ALL_BUTTONS)	)				)	||
546 		((nType==CTRL_COMBOBOX) &&
547 				(  (nPart==PART_ENTIRE_CONTROL)
548 				|| (nPart==HAS_BACKGROUND_TEXTURE)	)			)	||
549 		(((nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) ||
550 		  (nType==CTRL_TAB_BODY) || (nType==CTRL_FIXEDBORDER)) &&
551 				(  (nPart==PART_ENTIRE_CONTROL)
552 				|| (nPart==PART_TABS_DRAW_RTL) )				)	||
553 		((nType==CTRL_LISTBOX) &&
554 				(  (nPart==PART_ENTIRE_CONTROL)
555 				|| (nPart==PART_WINDOW)
556 				|| (nPart==HAS_BACKGROUND_TEXTURE) )			)   ||
557         ((nType == CTRL_TOOLBAR) &&
558          		(	(nPart==PART_ENTIRE_CONTROL)
559                 ||  (nPart==PART_DRAW_BACKGROUND_HORZ)
560                 ||  (nPart==PART_DRAW_BACKGROUND_VERT)
561                 ||  (nPart==PART_THUMB_HORZ)
562                 ||  (nPart==PART_THUMB_VERT)
563                 ||  (nPart==PART_BUTTON)
564                 )
565                                                                 )   ||
566         ((nType == CTRL_MENUBAR) &&
567                 (   (nPart==PART_ENTIRE_CONTROL) )              )   ||
568         ((nType == CTRL_TOOLTIP) &&
569                 (   (nPart==PART_ENTIRE_CONTROL) )              )   ||
570         ((nType == CTRL_MENU_POPUP) &&
571                 (   (nPart==PART_ENTIRE_CONTROL)
572                 ||  (nPart==PART_MENU_ITEM)
573                 ||  (nPart==PART_MENU_ITEM_CHECK_MARK)
574                 ||  (nPart==PART_MENU_ITEM_RADIO_MARK)
575                 )
576                                                                 )   ||
577         ((nType == CTRL_PROGRESS) &&
578                 (   (nPart == PART_ENTIRE_CONTROL) )
579                 )                                                   ||
580         ((nType == CTRL_LISTNODE || nType == CTRL_LISTNET) &&
581                 (   (nPart == PART_ENTIRE_CONTROL) )
582                 )                                                   ||
583         ((nType == CTRL_SLIDER) &&
584                 (   (nPart == PART_TRACK_HORZ_AREA)
585                 ||  (nPart == PART_TRACK_VERT_AREA)
586                 )
587         )
588         )
589 		return( sal_True );
590 
591 	return( sal_False );
592 }
593 
594 
595 /*
596  * HitTestNativeControl()
597  *
598  *  bIsInside is set to sal_True if aPos is contained within the
599  *  given part of the control, whose bounding region is
600  *  given by rControlRegion (in VCL frame coordinates).
601  *
602  *  returns whether bIsInside was really set.
603  */
604 sal_Bool GtkSalGraphics::hitTestNativeControl( ControlType		nType,
605 								ControlPart		nPart,
606 								const Rectangle&		rControlRegion,
607 								const Point&		aPos,
608 								sal_Bool&			rIsInside )
609 {
610     if ( ( nType == CTRL_SCROLLBAR ) &&
611          ( ( nPart == PART_BUTTON_UP ) ||
612            ( nPart == PART_BUTTON_DOWN ) ||
613            ( nPart == PART_BUTTON_LEFT ) ||
614            ( nPart == PART_BUTTON_RIGHT ) ) )
615     {
616         NWEnsureGTKScrollbars( m_nScreen );
617 
618         // Grab some button style attributes
619         gboolean has_forward;
620         gboolean has_forward2;
621         gboolean has_backward;
622         gboolean has_backward2;
623 
624 	    gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward,
625 									    "has-secondary-forward-stepper", &has_forward2,
626 									    "has-backward-stepper", &has_backward,
627 	   								    "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
628         Rectangle aForward;
629         Rectangle aBackward;
630 
631         rIsInside = sal_False;
632 
633         ControlPart nCounterPart = 0;
634         if ( nPart == PART_BUTTON_UP )
635             nCounterPart = PART_BUTTON_DOWN;
636         else if ( nPart == PART_BUTTON_DOWN )
637             nCounterPart = PART_BUTTON_UP;
638         else if ( nPart == PART_BUTTON_LEFT )
639             nCounterPart = PART_BUTTON_RIGHT;
640         else if ( nPart == PART_BUTTON_RIGHT )
641             nCounterPart = PART_BUTTON_LEFT;
642 
643         aBackward = NWGetScrollButtonRect( m_nScreen, nPart, rControlRegion );
644         aForward = NWGetScrollButtonRect( m_nScreen, nCounterPart, rControlRegion );
645 
646         if ( has_backward && has_forward2 )
647         {
648             Size aSize( aBackward.GetSize() );
649             if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
650                 aSize.setHeight( aBackward.GetHeight() / 2 );
651             else
652                 aSize.setWidth( aBackward.GetWidth() / 2 );
653             aBackward.SetSize( aSize );
654 
655             if ( nPart == PART_BUTTON_DOWN )
656                 aBackward.Move( 0, aBackward.GetHeight() / 2 );
657             else if ( nPart == PART_BUTTON_RIGHT )
658                 aBackward.Move( aBackward.GetWidth() / 2, 0 );
659         }
660 
661         if ( has_backward2 && has_forward )
662         {
663             Size aSize( aForward.GetSize() );
664             if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
665                 aSize.setHeight( aForward.GetHeight() / 2 );
666             else
667                 aSize.setWidth( aForward.GetWidth() / 2 );
668             aForward.SetSize( aSize );
669 
670             if ( nPart == PART_BUTTON_DOWN )
671                 aForward.Move( 0, aForward.GetHeight() / 2 );
672             else if ( nPart == PART_BUTTON_RIGHT )
673                 aForward.Move( aForward.GetWidth() / 2, 0 );
674         }
675 
676         if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_LEFT ) )
677         {
678             if ( has_backward )
679                 rIsInside |= aBackward.IsInside( aPos );
680             if ( has_backward2 )
681                 rIsInside |= aForward.IsInside( aPos );
682         }
683         else
684         {
685             if ( has_forward )
686                 rIsInside |= aBackward.IsInside( aPos );
687             if ( has_forward2 )
688                 rIsInside |= aForward.IsInside( aPos );
689         }
690         return ( sal_True );
691     }
692 
693     if( IsNativeControlSupported(nType, nPart) )
694 	{
695 		rIsInside = rControlRegion.IsInside( aPos );
696 		return( sal_True );
697 	}
698 	else
699 	{
700 		return( sal_False );
701 	}
702 }
703 
704 
705 /*
706  * DrawNativeControl()
707  *
708  *  Draws the requested control described by nPart/nState.
709  *
710  *  rControlRegion:	The bounding region of the complete control in VCL frame coordinates.
711  *  aValue:  		An optional value (tristate/numerical/string)
712  *  rCaption:  	A caption or title string (like button text etc)
713  */
714 sal_Bool GtkSalGraphics::drawNativeControl(	ControlType nType,
715 							ControlPart nPart,
716 							const Rectangle& rControlRegion,
717 							ControlState nState,
718 							const ImplControlValue& aValue,
719 							const OUString& rCaption )
720 {
721 	sal_Bool			returnVal = sal_False;
722 	// get a GC with current clipping region set
723     GetFontGC();
724 
725 
726     // theme changed ?
727     if( GtkSalGraphics::bThemeChanged )
728     {
729         // invalidate caches
730         for( unsigned int i = 0; i < gWidgetData.size(); i++ )
731             if( gWidgetData[i].gNWPixmapCacheList )
732                 gWidgetData[i].gNWPixmapCacheList->ThemeChanged();
733         GtkSalGraphics::bThemeChanged = sal_False;
734     }
735 
736     Rectangle aCtrlRect( rControlRegion );
737     Region aClipRegion( m_aClipRegion );
738     if( aClipRegion.IsNull() )
739         aClipRegion = aCtrlRect;
740 
741     clipList aClip;
742     GdkDrawable* gdkDrawable = GDK_DRAWABLE( GetGdkWindow() );
743     GdkPixmap* pixmap = NULL;
744     Rectangle aPixmapRect;
745     if( ( bNeedPixmapPaint )
746         && nType != CTRL_SCROLLBAR
747         && nType != CTRL_SPINBOX
748         && nType != CTRL_TAB_ITEM
749         && nType != CTRL_TAB_PANE
750         && nType != CTRL_PROGRESS
751         && ! (bToolbarGripWorkaround && nType == CTRL_TOOLBAR && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
752         )
753     {
754         // make pixmap a little larger since some themes draw decoration
755         // outside the rectangle, see e.g. checkbox
756         aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
757                                  Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
758         pixmap = NWGetPixmapFromScreen( aPixmapRect );
759         if( ! pixmap )
760             return sal_False;
761         gdkDrawable = GDK_DRAWABLE( pixmap );
762         aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() );
763         aClip.push_back( aCtrlRect );
764     }
765     else
766     {
767         RegionHandle aHdl = aClipRegion.BeginEnumRects();
768         Rectangle aPaintRect;
769         while( aClipRegion.GetNextEnumRect( aHdl, aPaintRect ) )
770         {
771             aPaintRect = aCtrlRect.GetIntersection( aPaintRect );
772             if( aPaintRect.IsEmpty() )
773                 continue;
774             aClip.push_back( aPaintRect );
775         }
776         aClipRegion.EndEnumRects( aHdl );
777     }
778 
779     if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
780     {
781         returnVal = NWPaintGTKButton( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
782     }
783     else if ( (nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
784     {
785         returnVal = NWPaintGTKRadio( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
786     }
787     else if ( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) )
788     {
789         returnVal = NWPaintGTKCheck( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
790     }
791     else if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_DRAW_BACKGROUND_HORZ) || (nPart==PART_DRAW_BACKGROUND_VERT)) )
792     {
793         returnVal = NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
794     }
795     else if ( ((nType==CTRL_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) )
796         || ((nType==CTRL_SPINBOX) && (nPart==HAS_BACKGROUND_TEXTURE))
797     || ((nType==CTRL_COMBOBOX) && (nPart==HAS_BACKGROUND_TEXTURE))
798     || ((nType==CTRL_LISTBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) )
799     {
800         returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
801     }
802     else if ( ((nType==CTRL_MULTILINE_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) )
803     {
804         returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
805     }
806     else if ( ((nType==CTRL_SPINBOX) || (nType==CTRL_SPINBUTTONS))
807         && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_ALL_BUTTONS)) )
808     {
809         returnVal = NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
810     }
811     else if ( (nType == CTRL_COMBOBOX) &&
812         ( (nPart==PART_ENTIRE_CONTROL)
813         ||(nPart==PART_BUTTON_DOWN)
814         ) )
815     {
816         returnVal = NWPaintGTKComboBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
817     }
818     else if ( (nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || (nType==CTRL_TAB_BODY) || (nType==CTRL_FIXEDBORDER) )
819     {
820         if ( nType == CTRL_TAB_BODY )
821             returnVal = sal_True;
822         else
823             returnVal = NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption);
824     }
825     else if ( (nType==CTRL_LISTBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_WINDOW)) )
826     {
827         returnVal = NWPaintGTKListBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
828     }
829     else if ( (nType== CTRL_TOOLBAR) )
830     {
831         returnVal = NWPaintGTKToolbar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
832     }
833     else if ( (nType== CTRL_MENUBAR) )
834     {
835         returnVal = NWPaintGTKMenubar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
836     }
837     else if(    (nType == CTRL_MENU_POPUP)
838         && (  (nPart == PART_ENTIRE_CONTROL)
839     || (nPart == PART_MENU_ITEM)
840     || (nPart == PART_MENU_ITEM_CHECK_MARK)
841     || (nPart == PART_MENU_ITEM_RADIO_MARK)
842     )
843     )
844     {
845         returnVal = NWPaintGTKPopupMenu( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
846     }
847     else if( (nType == CTRL_TOOLTIP) && (nPart == PART_ENTIRE_CONTROL) )
848     {
849         returnVal = NWPaintGTKTooltip( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
850     }
851     else if( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) )
852     {
853         returnVal = NWPaintGTKProgress( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
854     }
855     else if( (nType == CTRL_LISTNODE) && (nPart == PART_ENTIRE_CONTROL) )
856     {
857         returnVal = NWPaintGTKListNode( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
858     }
859     else if( (nType == CTRL_LISTNET) && (nPart == PART_ENTIRE_CONTROL) )
860     {
861         // don't actually draw anything; gtk treeviews do not draw lines
862         returnVal = true;
863     }
864     else if( (nType == CTRL_SLIDER) )
865     {
866         returnVal = NWPaintGTKSlider( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption );
867     }
868 
869     if( pixmap )
870     {
871         returnVal = NWRenderPixmapToScreen( pixmap, aPixmapRect ) && returnVal;
872         g_object_unref( pixmap );
873     }
874 
875 	return( returnVal );
876 }
877 
878 /*
879  * DrawNativeControlText()
880  *
881  *  OPTIONAL.  Draws the requested text for the control described by nPart/nState.
882  *     Used if text not drawn by DrawNativeControl().
883  *
884  *  rControlRegion:	The bounding region of the complete control in VCL frame coordinates.
885  *  aValue:  		An optional value (tristate/numerical/string)
886  *  rCaption:  	A caption or title string (like button text etc)
887  */
888 sal_Bool GtkSalGraphics::drawNativeControlText(	ControlType,
889 								ControlPart,
890 								const Rectangle&,
891 								ControlState,
892 								const ImplControlValue&,
893 								const OUString& )
894 {
895 	return( sal_False );
896 }
897 
898 
899 /*
900  * GetNativeControlRegion()
901  *
902  *  If the return value is sal_True, rNativeBoundingRegion
903  *  contains the true bounding region covered by the control
904  *  including any adornment, while rNativeContentRegion contains the area
905  *  within the control that can be safely drawn into without drawing over
906  *  the borders of the control.
907  *
908  *  rControlRegion:	The bounding region of the control in VCL frame coordinates.
909  *  aValue:		An optional value (tristate/numerical/string)
910  *  rCaption:		A caption or title string (like button text etc)
911  */
912 sal_Bool GtkSalGraphics::getNativeControlRegion(  ControlType nType,
913 								ControlPart nPart,
914 								const Rectangle& rControlRegion,
915 								ControlState nState,
916 								const ImplControlValue& aValue,
917 								const OUString& rCaption,
918 								Rectangle &rNativeBoundingRegion,
919 								Rectangle &rNativeContentRegion )
920 {
921 	sal_Bool returnVal = sal_False;
922 
923     if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL)
924         && (rControlRegion.GetWidth() > 16)
925     && (rControlRegion.GetHeight() > 16) )
926     {
927         rNativeBoundingRegion = NWGetButtonArea( m_nScreen, nType, nPart, rControlRegion,
928         nState, aValue, rCaption );
929         rNativeContentRegion = rControlRegion;
930 
931         returnVal = sal_True;
932     }
933     if ( (nType==CTRL_COMBOBOX) && ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
934     {
935         rNativeBoundingRegion = NWGetComboBoxButtonRect( m_nScreen, nType, nPart, rControlRegion, nState,
936         aValue, rCaption );
937         rNativeContentRegion = rNativeBoundingRegion;
938 
939         returnVal = sal_True;
940     }
941     if ( (nType==CTRL_SPINBOX) && ((nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
942     {
943 
944         rNativeBoundingRegion = NWGetSpinButtonRect( m_nScreen, nType, nPart, rControlRegion, nState,
945         aValue, rCaption );
946         rNativeContentRegion = rNativeBoundingRegion;
947 
948         returnVal = sal_True;
949     }
950     if ( (nType==CTRL_LISTBOX) && ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
951     {
952         rNativeBoundingRegion = NWGetListBoxButtonRect( m_nScreen, nType, nPart, rControlRegion, nState,
953         aValue, rCaption );
954         rNativeContentRegion = rNativeBoundingRegion;
955 
956         returnVal = sal_True;
957     }
958     if ( (nType==CTRL_TOOLBAR) &&
959         ((nPart==PART_DRAW_BACKGROUND_HORZ)	||
960         (nPart==PART_DRAW_BACKGROUND_VERT)	||
961         (nPart==PART_THUMB_HORZ)			||
962         (nPart==PART_THUMB_VERT)            ||
963         (nPart==PART_BUTTON)
964         ))
965     {
966         rNativeBoundingRegion = NWGetToolbarRect( m_nScreen, nType, nPart, rControlRegion, nState, aValue, rCaption );
967         rNativeContentRegion = rNativeBoundingRegion;
968         returnVal = sal_True;
969     }
970     if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_BUTTON_LEFT) || (nPart==PART_BUTTON_RIGHT) ||
971         (nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN)  ) )
972     {
973         rNativeBoundingRegion = NWGetScrollButtonRect( m_nScreen, nPart, rControlRegion );
974         rNativeContentRegion = rNativeBoundingRegion;
975 
976         returnVal = sal_True;
977     }
978     if( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL) )
979     {
980         NWEnsureGTKMenubar( m_nScreen );
981         GtkRequisition aReq;
982         gtk_widget_size_request( gWidgetData[m_nScreen].gMenubarWidget, &aReq );
983         Rectangle aMenuBarRect = rControlRegion;
984         aMenuBarRect = Rectangle( aMenuBarRect.TopLeft(),
985                                   Size( aMenuBarRect.GetWidth(), aReq.height+1 ) );
986         rNativeBoundingRegion = aMenuBarRect;
987         rNativeContentRegion = rNativeBoundingRegion;
988         returnVal = sal_True;
989     }
990     if( (nType == CTRL_MENU_POPUP) )
991     {
992         if( (nPart == PART_MENU_ITEM_CHECK_MARK) ||
993             (nPart == PART_MENU_ITEM_RADIO_MARK) )
994         {
995             NWEnsureGTKMenu( m_nScreen );
996 
997             gint indicator_size = 0;
998             GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ?
999                                  gWidgetData[m_nScreen].gMenuItemCheckMenuWidget : gWidgetData[m_nScreen].gMenuItemRadioMenuWidget;
1000             gtk_widget_style_get( pWidget,
1001                                   "indicator_size", &indicator_size,
1002                                   (char *)NULL );
1003             rNativeBoundingRegion = rControlRegion;
1004             Rectangle aIndicatorRect( Point( 0,
1005                                              (rControlRegion.GetHeight()-indicator_size)/2),
1006                                       Size( indicator_size, indicator_size ) );
1007             rNativeContentRegion = aIndicatorRect;
1008             returnVal = sal_True;
1009         }
1010     }
1011     if( (nType == CTRL_RADIOBUTTON || nType == CTRL_CHECKBOX) )
1012     {
1013         NWEnsureGTKRadio( m_nScreen );
1014         NWEnsureGTKCheck( m_nScreen );
1015         GtkWidget* widget = (nType == CTRL_RADIOBUTTON) ? gWidgetData[m_nScreen].gRadioWidget : gWidgetData[m_nScreen].gCheckWidget;
1016         gint indicator_size, indicator_spacing;
1017         gtk_widget_style_get( widget,
1018                               "indicator_size", &indicator_size,
1019                               "indicator_spacing", &indicator_spacing,
1020                               (char *)NULL);
1021         indicator_size += 2*indicator_spacing; // guess overpaint of theme
1022         rNativeBoundingRegion = rControlRegion;
1023         Rectangle aIndicatorRect( Point( 0,
1024                                          (rControlRegion.GetHeight()-indicator_size)/2),
1025                                   Size( indicator_size, indicator_size ) );
1026         rNativeContentRegion = aIndicatorRect;
1027         returnVal = sal_True;
1028     }
1029     if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL )
1030     {
1031         NWEnsureGTKEditBox( m_nScreen );
1032         GtkWidget* widget = gWidgetData[m_nScreen].gEditBoxWidget;
1033         GtkRequisition aReq;
1034         gtk_widget_size_request( widget, &aReq );
1035         Rectangle aEditRect = rControlRegion;
1036         long nHeight = (aEditRect.GetHeight() > aReq.height+1) ? aEditRect.GetHeight() : aReq.height+1;
1037         aEditRect = Rectangle( aEditRect.TopLeft(),
1038                                Size( aEditRect.GetWidth(), nHeight ) );
1039         rNativeBoundingRegion = aEditRect;
1040         rNativeContentRegion = rNativeBoundingRegion;
1041         returnVal = sal_True;
1042     }
1043     if( (nType == CTRL_SLIDER) && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
1044     {
1045         NWEnsureGTKSlider( m_nScreen );
1046         GtkWidget* widget = (nPart == PART_THUMB_HORZ) ? gWidgetData[m_nScreen].gHScale : gWidgetData[m_nScreen].gVScale;
1047         gint slider_length = 10;
1048         gint slider_width = 10;
1049         gtk_widget_style_get( widget,
1050                               "slider-width", &slider_width,
1051                               "slider-length", &slider_length,
1052                               (char *)NULL);
1053         Rectangle aRect( rControlRegion );
1054         if( nPart == PART_THUMB_HORZ )
1055         {
1056             aRect.Right() = aRect.Left() + slider_length - 1;
1057             aRect.Bottom() = aRect.Top() + slider_width - 1;
1058         }
1059         else
1060         {
1061             aRect.Bottom() = aRect.Top() + slider_length - 1;
1062             aRect.Right() = aRect.Left() + slider_width - 1;
1063         }
1064         rNativeBoundingRegion = rNativeContentRegion = aRect;
1065         returnVal = sal_True;
1066     }
1067 
1068 	return( returnVal );
1069 }
1070 
1071 
1072 /************************************************************************
1073  * Individual control drawing functions
1074  ************************************************************************/
1075 sal_Bool GtkSalGraphics::NWPaintGTKButton(
1076             GdkDrawable* gdkDrawable,
1077             ControlType, ControlPart,
1078 			const Rectangle& rControlRectangle,
1079             const clipList& rClipList,
1080             ControlState nState, const ImplControlValue&,
1081 			const OUString& )
1082 {
1083 	GtkStateType	stateType;
1084 	GtkShadowType	shadowType;
1085 	gboolean		interiorFocus;
1086 	gint			focusWidth;
1087 	gint			focusPad;
1088 	sal_Bool			bDrawFocus = sal_True;
1089 	gint			x, y, w, h;
1090 	GtkBorder		aDefBorder;
1091 	GtkBorder*		pBorder;
1092     GdkRectangle	clipRect;
1093 
1094 	NWEnsureGTKButton( m_nScreen );
1095 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1096 
1097 	x = rControlRectangle.Left();
1098     y = rControlRectangle.Top();
1099 	w = rControlRectangle.GetWidth();
1100 	h = rControlRectangle.GetHeight();
1101 
1102 	// Grab some button style attributes
1103 	gtk_widget_style_get( gWidgetData[m_nScreen].gBtnWidget,	"focus-line-width",	&focusWidth,
1104 								"focus-padding", 	&focusPad,
1105 					 			"interior_focus",	&interiorFocus,
1106 								"default_border",	&pBorder,
1107 								(char *)NULL );
1108 
1109 	// Make sure the border values exist, otherwise use some defaults
1110 	if ( pBorder )
1111 	{
1112 		NW_gtk_border_set_from_border( aDefBorder, pBorder );
1113 		gtk_border_free( pBorder );
1114 	}
1115 	else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder );
1116 
1117 	// If the button is too small, don't ever draw focus or grab more space
1118 	if ( (w < 16) || (h < 16) )
1119 		bDrawFocus = sal_False;
1120 
1121 	NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
1122 
1123     gint xi = x, yi = y, wi = w, hi = h;
1124 	if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus )
1125 	{
1126 		xi += aDefBorder.left;
1127 		yi += aDefBorder.top;
1128 		wi -= aDefBorder.left + aDefBorder.right;
1129 		hi -= aDefBorder.top + aDefBorder.bottom;
1130 	}
1131 
1132 	if ( !interiorFocus && bDrawFocus )
1133 	{
1134 		xi += focusWidth + focusPad;
1135 		yi += focusWidth + focusPad;
1136 		wi -= 2 * (focusWidth + focusPad);
1137 		hi -= 2 * (focusWidth + focusPad);
1138 	}
1139 
1140     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it)
1141     {
1142         clipRect.x = it->Left();
1143         clipRect.y = it->Top();
1144         clipRect.width = it->GetWidth();
1145         clipRect.height = it->GetHeight();
1146 
1147         // Buttons must paint opaque since some themes have alpha-channel enabled buttons
1148         gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
1149                             &clipRect, m_pWindow, "base", x, y, w, h );
1150 
1151         if ( (nState & CTRL_STATE_DEFAULT) && (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief == GTK_RELIEF_NORMAL) )
1152         {
1153             gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
1154                            &clipRect, gWidgetData[m_nScreen].gBtnWidget, "buttondefault", x, y, w, h );
1155         }
1156 
1157         if ( (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief != GTK_RELIEF_NONE)
1158             || (nState & CTRL_STATE_PRESSED)
1159 		    || (nState & CTRL_STATE_ROLLOVER) )
1160         {
1161             gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, shadowType,
1162                            &clipRect, gWidgetData[m_nScreen].gBtnWidget, "button", xi, yi, wi, hi );
1163         }
1164     }
1165 #if 0 // VCL draws focus rects
1166 	// Draw focus rect
1167 	if ( (nState & CTRL_STATE_FOCUSED) && (nState & CTRL_STATE_ENABLED) && bDrawFocus )
1168 	{
1169 		if (interiorFocus)
1170 		{
1171 			x += gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad;
1172 			y += gWidgetData[m_nScreen].gBtnWidget->style->ythickness + focusPad;
1173 			w -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad);
1174 			h -=  2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad);
1175 		}
1176 		else
1177 		{
1178 			x -= focusWidth + focusPad;
1179 			y -= focusWidth + focusPad;
1180 			w += 2 * (focusWidth + focusPad);
1181 			h += 2 * (focusWidth + focusPad);
1182 		}
1183 		if ( !interiorFocus )
1184 			gtk_paint_focus( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, &clipRect,
1185                              gWidgetData[m_nScreen].gBtnWidget, "button", x, y, w, h );
1186 	}
1187 #endif
1188 
1189 	return( sal_True );
1190 }
1191 
1192 static Rectangle NWGetButtonArea( int nScreen,
1193                                   ControlType, ControlPart, Rectangle aAreaRect, ControlState nState,
1194 							      const ImplControlValue&, const OUString& )
1195 {
1196 	gboolean		interiorFocus;
1197 	gint			focusWidth;
1198 	gint			focusPad;
1199 	GtkBorder		aDefBorder;
1200 	GtkBorder *	pBorder;
1201 	sal_Bool			bDrawFocus = sal_True;
1202 	Rectangle		aRect;
1203 	gint			x, y, w, h;
1204 
1205 	NWEnsureGTKButton( nScreen );
1206 	gtk_widget_style_get( gWidgetData[nScreen].gBtnWidget,
1207                             	"focus-line-width",	&focusWidth,
1208 								"focus-padding", 	&focusPad,
1209 					 			"interior_focus",	&interiorFocus,
1210 								"default_border",	&pBorder,
1211 								(char *)NULL );
1212 
1213 	// Make sure the border values exist, otherwise use some defaults
1214 	if ( pBorder )
1215 	{
1216 		NW_gtk_border_set_from_border( aDefBorder, pBorder );
1217 		gtk_border_free( pBorder );
1218 	}
1219 	else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder );
1220 
1221 	x = aAreaRect.Left();
1222 	y = aAreaRect.Top();
1223 	w = aAreaRect.GetWidth();
1224 	h = aAreaRect.GetHeight();
1225 
1226 	// If the button is too small, don't ever draw focus or grab more space
1227 	if ( (w < 16) || (h < 16) )
1228 		bDrawFocus = sal_False;
1229 
1230 	if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus )
1231 	{
1232 		x -= aDefBorder.left;
1233 		y -= aDefBorder.top;
1234 		w += aDefBorder.left + aDefBorder.right;
1235 		h += aDefBorder.top + aDefBorder.bottom;
1236 	}
1237 
1238     aRect = Rectangle( Point( x, y ), Size( w, h ) );
1239 
1240 	return( aRect );
1241 }
1242 
1243 //-------------------------------------
1244 
1245 sal_Bool GtkSalGraphics::NWPaintGTKRadio( GdkDrawable* gdkDrawable,
1246                                       ControlType, ControlPart,
1247                                       const Rectangle& rControlRectangle,
1248                                       const clipList& rClipList,
1249                                       ControlState nState,
1250                                       const ImplControlValue& aValue,
1251                                       const OUString& )
1252 {
1253 	GtkStateType	stateType;
1254 	GtkShadowType	shadowType;
1255 	sal_Bool			isChecked = (aValue.getTristateVal()==BUTTONVALUE_ON);
1256     gint            x, y;
1257     GdkRectangle	clipRect;
1258 
1259 	NWEnsureGTKButton( m_nScreen );
1260 	NWEnsureGTKRadio( m_nScreen );
1261 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1262 
1263     gint indicator_size;
1264     gtk_widget_style_get( gWidgetData[m_nScreen].gRadioWidget, "indicator_size", &indicator_size, (char *)NULL);
1265 
1266     x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2;
1267     y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2;
1268 
1269 	// Set the shadow based on if checked or not so we get a freakin checkmark.
1270 	shadowType = isChecked ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
1271 	NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidget, nState, stateType );
1272 	NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidgetSibling, nState, stateType );
1273 
1274 	// GTK enforces radio groups, so that if we don't have 2 buttons in the group,
1275 	// the single button will always be active.  So we have to have 2 buttons.
1276 
1277     // #i59666# set the members directly where we should use
1278     // gtk_toggle_button_set_active. reason: there are animated themes
1279     // which are in active state only after a while leading to painting
1280     // intermediate states between active/inactive. Let's hope that
1281     // GtkToggleButtone stays binary compatible.
1282 	if (!isChecked)
1283 		GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidgetSibling)->active = sal_True;
1284 	GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidget)->active = isChecked;
1285 
1286     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
1287     {
1288         clipRect.x = it->Left();
1289         clipRect.y = it->Top();
1290         clipRect.width = it->GetWidth();
1291         clipRect.height = it->GetHeight();
1292 
1293         gtk_paint_option( gWidgetData[m_nScreen].gRadioWidget->style, gdkDrawable, stateType, shadowType,
1294                           &clipRect, gWidgetData[m_nScreen].gRadioWidget, "radiobutton",
1295                           x, y, indicator_size, indicator_size );
1296     }
1297 
1298 	return( sal_True );
1299 }
1300 
1301 //-------------------------------------
1302 
1303 sal_Bool GtkSalGraphics::NWPaintGTKCheck( GdkDrawable* gdkDrawable,
1304                                       ControlType, ControlPart,
1305                                       const Rectangle& rControlRectangle,
1306                                       const clipList& rClipList,
1307                                       ControlState nState,
1308                                       const ImplControlValue& aValue,
1309                                       const OUString& )
1310 {
1311 	GtkStateType	stateType;
1312 	GtkShadowType	shadowType;
1313 	bool			isChecked = (aValue.getTristateVal() == BUTTONVALUE_ON);
1314 	bool            isInconsistent = (aValue.getTristateVal() == BUTTONVALUE_MIXED);
1315     GdkRectangle	clipRect;
1316     gint			x,y;
1317 
1318 	NWEnsureGTKButton( m_nScreen );
1319 	NWEnsureGTKCheck( m_nScreen );
1320 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1321 
1322     gint indicator_size;
1323     gtk_widget_style_get( gWidgetData[m_nScreen].gCheckWidget, "indicator_size", &indicator_size, (char *)NULL);
1324 
1325     x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2;
1326     y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2;
1327 
1328 	// Set the shadow based on if checked or not so we get a checkmark.
1329 	shadowType = isChecked ? GTK_SHADOW_IN : isInconsistent ? GTK_SHADOW_ETCHED_IN : GTK_SHADOW_OUT;
1330 	NWSetWidgetState( gWidgetData[m_nScreen].gCheckWidget, nState, stateType );
1331 	GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gCheckWidget)->active = isChecked;
1332 
1333     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
1334     {
1335         clipRect.x = it->Left();
1336         clipRect.y = it->Top();
1337         clipRect.width = it->GetWidth();
1338         clipRect.height = it->GetHeight();
1339 
1340         gtk_paint_check( gWidgetData[m_nScreen].gCheckWidget->style, gdkDrawable, stateType, shadowType,
1341                          &clipRect, gWidgetData[m_nScreen].gCheckWidget, "checkbutton",
1342                          x, y, indicator_size, indicator_size );
1343     }
1344 
1345 	return( sal_True );
1346 }
1347 
1348 //-------------------------------------
1349 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow )
1350 {
1351 	// Size the arrow appropriately
1352     Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
1353     rArrow.SetSize( aSize );
1354 
1355 	rArrow.SetPos( Point(
1356         rButton.Left() + ( rButton.GetWidth()  - rArrow.GetWidth()  ) / 2,
1357         rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
1358         ) );
1359 }
1360 
1361 sal_Bool GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart,
1362                                           const Rectangle& rControlRectangle,
1363                                           const clipList&,
1364                                           ControlState nState,
1365                                           const ImplControlValue& aValue,
1366                                           const OUString& )
1367 {
1368     OSL_ASSERT( aValue.getType() == CTRL_SCROLLBAR );
1369 	const ScrollbarValue* pScrollbarVal = static_cast<const ScrollbarValue *>(&aValue);
1370     GdkPixmap*      pixmap = NULL;
1371 	Rectangle		pixmapRect, scrollbarRect;
1372 	GtkStateType	stateType;
1373 	GtkShadowType	shadowType;
1374 	GtkScrollbar *	scrollbarWidget;
1375 	GtkStyle *	style;
1376 	GtkAdjustment* scrollbarValues = NULL;
1377 	GtkOrientation	scrollbarOrientation;
1378 	Rectangle		thumbRect = pScrollbarVal->maThumbRect;
1379 	Rectangle		button11BoundRect = pScrollbarVal->maButton1Rect;   // backward
1380 	Rectangle		button22BoundRect = pScrollbarVal->maButton2Rect;   // forward
1381 	Rectangle		button12BoundRect = pScrollbarVal->maButton1Rect;   // secondary forward
1382 	Rectangle		button21BoundRect = pScrollbarVal->maButton2Rect;   // secondary backward
1383 	GtkArrowType	button1Type;                                        // backward
1384 	GtkArrowType	button2Type;                                        // forward
1385 	gchar *		scrollbarTagH = (gchar *) "hscrollbar";
1386 	gchar *		scrollbarTagV = (gchar *) "vscrollbar";
1387 	gchar *		scrollbarTag = NULL;
1388 	Rectangle		arrowRect;
1389 	gint			slider_width = 0;
1390 	gint			stepper_size = 0;
1391 	gint			stepper_spacing = 0;
1392 	gint			trough_border = 0;
1393 	gint			min_slider_length = 0;
1394 	gint			vShim = 0;
1395 	gint			hShim = 0;
1396 	gint			x,y,w,h;
1397 
1398     // make controlvalue rectangles relative to area
1399     thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1400     button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1401     button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1402     button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1403     button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1404 
1405 	NWEnsureGTKButton( m_nScreen );
1406 	NWEnsureGTKScrollbars( m_nScreen );
1407 	NWEnsureGTKArrow( m_nScreen );
1408 
1409 	// Find the overall bounding rect of the control
1410 	pixmapRect = rControlRectangle;
1411     pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 1,
1412                               pixmapRect.GetHeight() + 1 ) );
1413 	scrollbarRect = pixmapRect;
1414 
1415 	if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) )
1416 		return( sal_True );
1417 
1418 	// Grab some button style attributes
1419 	gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget,
1420                                       "slider_width", &slider_width,
1421 									  "stepper_size", &stepper_size,
1422 									  "trough_border", &trough_border,
1423 									  "stepper_spacing", &stepper_spacing,
1424 									  "min_slider_length", &min_slider_length, (char *)NULL );
1425     gboolean has_forward;
1426     gboolean has_forward2;
1427     gboolean has_backward;
1428     gboolean has_backward2;
1429 
1430 	gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward,
1431 									  "has-secondary-forward-stepper", &has_forward2,
1432 									  "has-backward-stepper", &has_backward,
1433 	   								  "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
1434 	gint magic = trough_border ? 1 : 0;
1435     gint nFirst = 0;
1436 
1437     if ( has_backward )  nFirst  += 1;
1438     if ( has_forward2 )  nFirst  += 1;
1439 
1440 	if ( nPart == PART_DRAW_BACKGROUND_HORZ )
1441 	{
1442 		unsigned int sliderHeight = slider_width + (trough_border * 2);
1443 		vShim = (pixmapRect.GetHeight() - sliderHeight) / 2;
1444 
1445 		scrollbarRect.Move( 0, vShim );
1446 		scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), sliderHeight ) );
1447 
1448 		scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollHorizWidget );
1449 		scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
1450 		scrollbarTag = scrollbarTagH;
1451 		button1Type = GTK_ARROW_LEFT;
1452 		button2Type = GTK_ARROW_RIGHT;
1453 
1454         if ( has_backward )
1455         {
1456             button12BoundRect.Move( stepper_size - trough_border,
1457                                     (scrollbarRect.GetHeight() - slider_width) / 2 );
1458         }
1459 
1460         button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 );
1461         button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
1462         button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
1463 
1464         if ( has_backward2 )
1465         {
1466             button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
1467             button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
1468         }
1469         else
1470         {
1471             button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
1472         }
1473 
1474         button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
1475         button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
1476 
1477 		thumbRect.Bottom() = thumbRect.Top() + slider_width - 1;
1478 		// Make sure the thumb is at least the default width (so we don't get tiny thumbs),
1479 		// but if the VCL gives us a size smaller than the theme's default thumb size,
1480 		// honor the VCL size
1481 #if 0
1482 		if ( (thumbRect.GetWidth() < min_slider_length)
1483 			&& ((scrollbarRect.GetWidth()-button1BoundRect.GetWidth()-button2BoundRect.GetWidth()) > min_slider_length) )
1484 			thumbRect.SetSize( Size( min_slider_length, thumbRect.GetHeight() ) );
1485 #endif
1486 
1487         thumbRect.Right() += magic;
1488 		// Center vertically in the track
1489 		thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
1490 	}
1491 	else
1492 	{
1493 		unsigned int sliderWidth = slider_width + (trough_border * 2);
1494 		hShim = (pixmapRect.GetWidth() - sliderWidth) / 2;
1495 
1496 		scrollbarRect.Move( hShim, 0 );
1497 		scrollbarRect.SetSize( Size( sliderWidth, scrollbarRect.GetHeight() ) );
1498 
1499 		scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollVertWidget );
1500 		scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
1501 		scrollbarTag = scrollbarTagV;
1502 		button1Type = GTK_ARROW_UP;
1503 		button2Type = GTK_ARROW_DOWN;
1504 
1505         if ( has_backward )
1506         {
1507             button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
1508                                     stepper_size + trough_border );
1509         }
1510         button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border );
1511         button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
1512 		button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
1513 
1514         if ( has_backward2 )
1515         {
1516             button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 );
1517             button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
1518         }
1519         else
1520         {
1521             button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
1522         }
1523 
1524         button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
1525         button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
1526 
1527 		thumbRect.Right() = thumbRect.Left() + slider_width - 1;
1528 #if 0
1529 		// Make sure the thumb is at least the default width (so we don't get tiny thumbs),
1530 		// but if the VCL gives us a size smaller than the theme's default thumb size,
1531 		// honor the VCL size
1532 		if ( (thumbRect.GetHeight() < min_slider_length)
1533 			&& ((scrollbarRect.GetHeight()-button1BoundRect.GetHeight()-button2BoundRect.GetHeight()) > min_slider_length) )
1534 			thumbRect.SetSize( Size( thumbRect.GetWidth(), min_slider_length ) );
1535 #endif
1536 
1537         thumbRect.Bottom() += magic;
1538 		// Center horizontally in the track
1539 		thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
1540 	}
1541 
1542     sal_Bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
1543 
1544 	scrollbarValues = gtk_range_get_adjustment( GTK_RANGE(scrollbarWidget) );
1545 	if ( scrollbarValues == NULL )
1546 		scrollbarValues = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
1547 	if ( nPart == PART_DRAW_BACKGROUND_HORZ )
1548 	{
1549 		scrollbarValues->lower = pScrollbarVal->mnMin;
1550 		scrollbarValues->upper = pScrollbarVal->mnMax;
1551 		scrollbarValues->value = pScrollbarVal->mnCur;
1552 		scrollbarValues->page_size = scrollbarRect.GetWidth() / 2;
1553 	}
1554 	else
1555 	{
1556 		scrollbarValues->lower = pScrollbarVal->mnMin;
1557 		scrollbarValues->upper = pScrollbarVal->mnMax;
1558 		scrollbarValues->value = pScrollbarVal->mnCur;
1559 		scrollbarValues->page_size = scrollbarRect.GetHeight() / 2;
1560 	}
1561 	gtk_adjustment_changed( scrollbarValues );
1562 
1563     // as multiple paints are required for the scrollbar
1564     // painting them directly to the window flickers
1565     pixmap = NWGetPixmapFromScreen( pixmapRect );
1566     if( ! pixmap )
1567         return sal_False;
1568     x = y = 0;
1569 
1570     w = pixmapRect.GetWidth();
1571     h = pixmapRect.GetHeight();
1572 
1573     GdkDrawable* const &gdkDrawable = GDK_DRAWABLE( pixmap );
1574     GdkRectangle* gdkRect = NULL;
1575 
1576 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1577 	NWSetWidgetState( GTK_WIDGET(scrollbarWidget), nState, stateType );
1578 	NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
1579 	style = GTK_WIDGET( scrollbarWidget )->style;
1580 
1581 	// ----------------- TROUGH
1582 	gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable,
1583                         GTK_STATE_NORMAL, GTK_SHADOW_NONE, gdkRect,
1584                         m_pWindow, "base", x, y,
1585                         w, h );
1586 	gtk_paint_box( style, gdkDrawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN,
1587                    gdkRect, GTK_WIDGET(scrollbarWidget), "trough",
1588                    x, y,
1589                    scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
1590 
1591 	if ( nState & CTRL_STATE_FOCUSED )
1592 	{
1593 		gtk_paint_focus( style, gdkDrawable, GTK_STATE_ACTIVE,
1594                          gdkRect, GTK_WIDGET(scrollbarWidget), "trough",
1595                          x, y,
1596                          scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
1597 	}
1598 
1599 	// ----------------- THUMB
1600     if ( has_slider )
1601     {
1602 	    NWConvertVCLStateToGTKState( pScrollbarVal->mnThumbState, &stateType, &shadowType );
1603 	    if ( pScrollbarVal->mnThumbState & CTRL_STATE_PRESSED )  stateType = GTK_STATE_PRELIGHT;
1604 	    gtk_paint_slider( style, gdkDrawable, stateType, GTK_SHADOW_OUT,
1605                         gdkRect, GTK_WIDGET(scrollbarWidget), "slider",
1606                         x+hShim+thumbRect.Left(), y+vShim+thumbRect.Top(),
1607                         thumbRect.GetWidth(), thumbRect.GetHeight(), scrollbarOrientation );
1608     }
1609 	// ----------------- BUTTON 1 //
1610 	if ( has_backward )
1611 	{
1612         NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType );
1613         if ( stateType == GTK_STATE_INSENSITIVE )	stateType = GTK_STATE_NORMAL;
1614         gtk_paint_box( style, gdkDrawable, stateType, shadowType,
1615                        gdkRect, GTK_WIDGET(scrollbarWidget), "stepper",
1616                        x+hShim+button11BoundRect.Left(), y+vShim+button11BoundRect.Top(),
1617                        button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
1618         // ----------------- ARROW 1
1619     	NWCalcArrowRect( button11BoundRect, arrowRect );
1620     	gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1621                          gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, sal_True,
1622                          x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1623                          arrowRect.GetWidth(), arrowRect.GetHeight() );
1624     }
1625 	if ( has_forward2 )
1626 	{
1627         NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType );
1628         if ( stateType == GTK_STATE_INSENSITIVE )	stateType = GTK_STATE_NORMAL;
1629         gtk_paint_box( style, gdkDrawable, stateType, shadowType,
1630                        gdkRect, GTK_WIDGET(scrollbarWidget), "stepper",
1631                        x+hShim+button12BoundRect.Left(), y+vShim+button12BoundRect.Top(),
1632                        button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
1633         // ----------------- ARROW 1
1634     	NWCalcArrowRect( button12BoundRect, arrowRect );
1635     	gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1636                          gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, sal_True,
1637                          x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1638                          arrowRect.GetWidth(), arrowRect.GetHeight() );
1639     }
1640 	// ----------------- BUTTON 2
1641     if ( has_backward2 )
1642     {
1643         NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType );
1644         if ( stateType == GTK_STATE_INSENSITIVE )	stateType = GTK_STATE_NORMAL;
1645         gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect,
1646                        GTK_WIDGET(scrollbarWidget), "stepper",
1647                        x+hShim+button21BoundRect.Left(), y+vShim+button21BoundRect.Top(),
1648                        button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
1649     	// ----------------- ARROW 2
1650     	NWCalcArrowRect( button21BoundRect, arrowRect );
1651         gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1652                          gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, sal_True,
1653                          x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1654                          arrowRect.GetWidth(), arrowRect.GetHeight() );
1655     }
1656     if ( has_forward )
1657     {
1658         NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType );
1659         if ( stateType == GTK_STATE_INSENSITIVE )	stateType = GTK_STATE_NORMAL;
1660         gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect,
1661                        GTK_WIDGET(scrollbarWidget), "stepper",
1662                        x+hShim+button22BoundRect.Left(), y+vShim+button22BoundRect.Top(),
1663                        button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
1664     	// ----------------- ARROW 2
1665     	NWCalcArrowRect( button22BoundRect, arrowRect );
1666         gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1667                          gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, sal_True,
1668                          x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1669                          arrowRect.GetWidth(), arrowRect.GetHeight() );
1670     }
1671 
1672     if( !NWRenderPixmapToScreen(pixmap, pixmapRect) )
1673     {
1674         g_object_unref( pixmap );
1675         return( sal_False );
1676     }
1677     g_object_unref( pixmap );
1678 
1679 	return( sal_True );
1680 }
1681 
1682 //---
1683 
1684 static Rectangle NWGetScrollButtonRect(	int nScreen, ControlPart nPart, Rectangle aAreaRect )
1685 {
1686     gint slider_width;
1687     gint stepper_size;
1688     gint stepper_spacing;
1689     gint trough_border;
1690 
1691     NWEnsureGTKScrollbars( nScreen );
1692 
1693 	// Grab some button style attributes
1694 	gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget,
1695                                       "slider-width", &slider_width,
1696 									  "stepper-size", &stepper_size,
1697 									  "trough-border", &trough_border,
1698 	   								  "stepper-spacing", &stepper_spacing, (char *)NULL );
1699 
1700     gboolean has_forward;
1701     gboolean has_forward2;
1702     gboolean has_backward;
1703     gboolean has_backward2;
1704 
1705 	gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget,
1706                                       "has-forward-stepper", &has_forward,
1707 									  "has-secondary-forward-stepper", &has_forward2,
1708 									  "has-backward-stepper", &has_backward,
1709 	   								  "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
1710 	gint       buttonWidth;
1711 	gint       buttonHeight;
1712 	Rectangle  buttonRect;
1713 
1714     gint nFirst = 0;
1715     gint nSecond = 0;
1716 
1717     if ( has_forward )   nSecond += 1;
1718     if ( has_forward2 )  nFirst  += 1;
1719     if ( has_backward )  nFirst  += 1;
1720     if ( has_backward2 ) nSecond += 1;
1721 
1722     if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
1723     {
1724         buttonWidth = slider_width + 2 * trough_border;
1725         buttonHeight = stepper_size + trough_border + stepper_spacing;
1726     }
1727     else
1728     {
1729         buttonWidth = stepper_size + trough_border + stepper_spacing;
1730         buttonHeight = slider_width + 2 * trough_border;
1731     }
1732 
1733     if ( nPart == PART_BUTTON_UP )
1734     {
1735         buttonHeight *= nFirst;
1736         buttonHeight -= 1;
1737         buttonRect.setX( aAreaRect.Left() );
1738         buttonRect.setY( aAreaRect.Top() );
1739     }
1740     else if ( nPart == PART_BUTTON_LEFT )
1741     {
1742         buttonWidth *= nFirst;
1743         buttonWidth -= 1;
1744         buttonRect.setX( aAreaRect.Left() );
1745         buttonRect.setY( aAreaRect.Top() );
1746     }
1747     else if ( nPart == PART_BUTTON_DOWN )
1748     {
1749         buttonHeight *= nSecond;
1750         buttonRect.setX( aAreaRect.Left() );
1751         buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight );
1752     }
1753     else if ( nPart == PART_BUTTON_RIGHT )
1754     {
1755         buttonWidth *= nSecond;
1756         buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth );
1757         buttonRect.setY( aAreaRect.Top() );
1758     }
1759 
1760     buttonRect.SetSize( Size( buttonWidth, buttonHeight ) );
1761 
1762 	return( buttonRect );
1763 }
1764 
1765 //-------------------------------------
1766 
1767 sal_Bool GtkSalGraphics::NWPaintGTKEditBox( GdkDrawable* gdkDrawable,
1768                                         ControlType nType, ControlPart nPart,
1769                                         const Rectangle& rControlRectangle,
1770                                         const clipList& rClipList,
1771                                         ControlState nState,
1772                                         const ImplControlValue& aValue,
1773                                         const OUString& rCaption )
1774 {
1775 	Rectangle		pixmapRect;
1776     GdkRectangle    clipRect;
1777 
1778 	// Find the overall bounding rect of the buttons's drawing area,
1779 	// plus its actual draw rect excluding adornment
1780 	pixmapRect = NWGetEditBoxPixmapRect( m_nScreen, nType, nPart, rControlRectangle,
1781 					                     nState, aValue, rCaption );
1782     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
1783     {
1784         clipRect.x = it->Left();
1785         clipRect.y = it->Top();
1786         clipRect.width = it->GetWidth();
1787         clipRect.height = it->GetHeight();
1788 
1789         NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, pixmapRect, nState, aValue, rCaption );
1790     }
1791 
1792 	return( sal_True );
1793 }
1794 
1795 
1796 /* Take interior/exterior focus into account and return
1797  * the bounding rectangle of the edit box including
1798  * any focus requirements.
1799  */
1800 static Rectangle NWGetEditBoxPixmapRect(int nScreen,
1801                                         ControlType,
1802 								        ControlPart,
1803                                         Rectangle aAreaRect,
1804                                         ControlState,
1805                                         const ImplControlValue&,
1806                                         const OUString& )
1807 {
1808 	Rectangle		pixmapRect = aAreaRect;
1809 	gboolean		interiorFocus;
1810 	gint			focusWidth;
1811 
1812 	NWEnsureGTKEditBox( nScreen );
1813 
1814 	// Grab some entry style attributes
1815 	gtk_widget_style_get( gWidgetData[nScreen].gEditBoxWidget,
1816                                 	"focus-line-width",	&focusWidth,
1817 					 				"interior-focus",	&interiorFocus, (char *)NULL );
1818 
1819 	if ( !interiorFocus )
1820 	{
1821 		pixmapRect.Move( -(focusWidth), -(focusWidth) );
1822         pixmapRect.SetSize( Size( pixmapRect.GetWidth() + (2*(focusWidth)),
1823                                   pixmapRect.GetHeight() + (2*(focusWidth)) ) );
1824 	}
1825 
1826 	return( pixmapRect );
1827 }
1828 
1829 
1830 /* Paint a GTK Entry widget into the specified GdkPixmap.
1831  * All coordinates should be local to the Pixmap, NOT
1832  * screen/window coordinates.
1833  */
1834 static void NWPaintOneEditBox(	int nScreen,
1835                                 GdkDrawable * gdkDrawable,
1836                                 GdkRectangle *	gdkRect,
1837                                 ControlType			nType,
1838                                 ControlPart,
1839                                 Rectangle				aEditBoxRect,
1840                                 ControlState			nState,
1841                                 const ImplControlValue&,
1842                                 const OUString& )
1843 {
1844 	GtkStateType	stateType;
1845 	GtkShadowType	shadowType;
1846 	GtkWidget      *widget;
1847 
1848 	NWEnsureGTKButton( nScreen );
1849 	NWEnsureGTKEditBox( nScreen );
1850 	NWEnsureGTKSpinButton( nScreen );
1851 	NWEnsureGTKCombo( nScreen );
1852 	NWEnsureGTKScrolledWindow( nScreen );
1853 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1854 
1855     /* border's shadowType for gtk entries is always GTK_SHADOW_IN (see gtkentry.c)
1856     shadowType = GTK_SHADOW_IN;
1857     */
1858 
1859 	switch ( nType )
1860 	{
1861 		case CTRL_SPINBOX:
1862 			widget = gWidgetData[nScreen].gSpinButtonWidget;
1863 			break;
1864 
1865         case CTRL_MULTILINE_EDITBOX:
1866             widget = gWidgetData[nScreen].gScrolledWindowWidget;
1867             break;
1868 		case CTRL_COMBOBOX:
1869 			widget = GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry;
1870 			break;
1871 
1872 		default:
1873 			widget = gWidgetData[nScreen].gEditBoxWidget;
1874 			break;
1875 	}
1876 
1877 	if ( stateType == GTK_STATE_PRELIGHT )
1878 		stateType = GTK_STATE_NORMAL;
1879 
1880 	// Blueprint needs to paint entry_bg with a Button widget, not an Entry widget to get
1881 	// a nice white (or whatever default color) background
1882     GtkWidget* pBGWidget = widget;
1883     if( GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround )
1884     {
1885         NWSetWidgetState( gWidgetData[nScreen].gBtnWidget, nState, stateType );
1886         pBGWidget = gWidgetData[nScreen].gBtnWidget;
1887     }
1888 	NWSetWidgetState( widget, nState, stateType );
1889 
1890 	gtk_paint_flat_box( pBGWidget->style, gdkDrawable, stateType, GTK_SHADOW_NONE,
1891                         gdkRect, pBGWidget, "entry_bg",
1892                         aEditBoxRect.Left(), aEditBoxRect.Top(),
1893                         aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
1894 	gtk_paint_shadow( widget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
1895                       gdkRect, widget, "entry",
1896                       aEditBoxRect.Left(), aEditBoxRect.Top(),
1897                       aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
1898 
1899 }
1900 
1901 
1902 
1903 //-------------------------------------
1904 
1905 sal_Bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart,
1906                                         const Rectangle& rControlRectangle,
1907                                         const clipList&,
1908                                         ControlState nState,
1909                                         const ImplControlValue& aValue,
1910                                         const OUString& rCaption )
1911 {
1912 	GdkPixmap	*		pixmap;
1913 	Rectangle			pixmapRect;
1914 	GtkStateType		stateType;
1915 	GtkShadowType		shadowType;
1916 	const SpinbuttonValue *	pSpinVal = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue *>(&aValue) : NULL;
1917 	Rectangle			upBtnRect;
1918 	ControlPart		upBtnPart = PART_BUTTON_UP;
1919 	ControlState		upBtnState = CTRL_STATE_ENABLED;
1920 	Rectangle			downBtnRect;
1921 	ControlPart		downBtnPart = PART_BUTTON_DOWN;
1922 	ControlState		downBtnState = CTRL_STATE_ENABLED;
1923 
1924 	NWEnsureGTKButton( m_nScreen );
1925 	NWEnsureGTKSpinButton( m_nScreen );
1926 	NWEnsureGTKArrow( m_nScreen );
1927 
1928 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1929 
1930 	if ( pSpinVal )
1931 	{
1932 		upBtnPart = pSpinVal->mnUpperPart;
1933 		upBtnState = pSpinVal->mnUpperState;
1934 
1935 		downBtnPart = pSpinVal->mnLowerPart;
1936 		downBtnState = pSpinVal->mnLowerState;
1937 	}
1938 
1939 	// CTRL_SPINBUTTONS pass their area in pSpinVal, not in rControlRectangle
1940 	if ( nType == CTRL_SPINBUTTONS )
1941 	{
1942 		if ( !pSpinVal )
1943 		{
1944             std::fprintf( stderr, "Tried to draw CTRL_SPINBUTTONS, but the SpinButtons data structure didn't exist!\n" );
1945 			return( false );
1946 		}
1947 		pixmapRect = pSpinVal->maUpperRect;
1948 		pixmapRect.Union( pSpinVal->maLowerRect );
1949 	}
1950 	else
1951 		pixmapRect = rControlRectangle;
1952 
1953 
1954 	pixmap = NWGetPixmapFromScreen( pixmapRect );
1955 	if ( !pixmap )
1956 		return( sal_False );
1957 
1958 	upBtnRect = NWGetSpinButtonRect( m_nScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
1959 	downBtnRect = NWGetSpinButtonRect( m_nScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
1960 
1961 	if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) )
1962 	{
1963 		// Draw an edit field for SpinBoxes and ComboBoxes
1964 		Rectangle aEditBoxRect( pixmapRect );
1965 		aEditBoxRect.SetSize( Size( upBtnRect.Left() - pixmapRect.Left(), aEditBoxRect.GetHeight() ) );
1966 		aEditBoxRect.setX( 0 );
1967 		aEditBoxRect.setY( 0 );
1968 
1969 		NWPaintOneEditBox( m_nScreen, pixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption );
1970 	}
1971 
1972 	NWSetWidgetState( gWidgetData[m_nScreen].gSpinButtonWidget, nState, stateType );
1973 	gtk_widget_style_get( gWidgetData[m_nScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL );
1974 
1975 	if ( shadowType != GTK_SHADOW_NONE )
1976 	{
1977 		Rectangle		shadowRect( upBtnRect );
1978 
1979 		shadowRect.Union( downBtnRect );
1980 		gtk_paint_box( gWidgetData[m_nScreen].gSpinButtonWidget->style, pixmap, GTK_STATE_NORMAL, shadowType, NULL,
1981 			gWidgetData[m_nScreen].gSpinButtonWidget, "spinbutton",
1982 			(shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()),
1983 			shadowRect.GetWidth(), shadowRect.GetHeight() );
1984 	}
1985 
1986 	NWPaintOneSpinButton( m_nScreen, pixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption );
1987 	NWPaintOneSpinButton( m_nScreen, pixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption );
1988 
1989 	if( !NWRenderPixmapToScreen(pixmap, pixmapRect) )
1990 	{
1991 		g_object_unref( pixmap );
1992 		return( sal_False );
1993 	}
1994 
1995 	g_object_unref( pixmap );
1996 	return( sal_True );
1997 }
1998 
1999 //---
2000 
2001 static Rectangle NWGetSpinButtonRect( int nScreen,
2002                                       ControlType,
2003 								      ControlPart			nPart,
2004                                       Rectangle 			aAreaRect,
2005                                       ControlState,
2006                                       const ImplControlValue&,
2007                                       const OUString& )
2008 {
2009 	gint			buttonSize;
2010 	Rectangle		buttonRect;
2011 
2012 	NWEnsureGTKSpinButton( nScreen );
2013 
2014 	buttonSize = MAX( PANGO_PIXELS( pango_font_description_get_size(GTK_WIDGET(gWidgetData[nScreen].gSpinButtonWidget)->style->font_desc) ),
2015 				   MIN_SPIN_ARROW_WIDTH );
2016 	buttonSize -= buttonSize % 2 - 1; /* force odd */
2017 	buttonRect.SetSize( Size( buttonSize + 2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness,
2018                               buttonRect.GetHeight() ) );
2019 	buttonRect.setX( aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()) );
2020 	if ( nPart == PART_BUTTON_UP )
2021 	{
2022 		buttonRect.setY( aAreaRect.Top() );
2023 		buttonRect.Bottom() = buttonRect.Top() + (aAreaRect.GetHeight() / 2);
2024 	}
2025 	else if( nPart == PART_BUTTON_DOWN )
2026 	{
2027 		buttonRect.setY( aAreaRect.Top() + (aAreaRect.GetHeight() / 2) );
2028 		buttonRect.Bottom() = aAreaRect.Bottom(); // cover area completely
2029 	}
2030     else
2031     {
2032         buttonRect.Right()  = buttonRect.Left()-1;
2033         buttonRect.Left()   = aAreaRect.Left();
2034         buttonRect.Top()    = aAreaRect.Top();
2035         buttonRect.Bottom() = aAreaRect.Bottom();
2036     }
2037 
2038 	return( buttonRect );
2039 }
2040 
2041 //---
2042 
2043 static void NWPaintOneSpinButton( int nScreen,
2044                                   GdkPixmap*			pixmap,
2045                                   ControlType			nType,
2046                                   ControlPart			nPart,
2047                                   Rectangle				aAreaRect,
2048                                   ControlState			nState,
2049                                   const ImplControlValue&	aValue,
2050                                   const OUString&				rCaption )
2051 {
2052 	Rectangle			buttonRect;
2053 	GtkStateType		stateType;
2054 	GtkShadowType		shadowType;
2055 	Rectangle			arrowRect;
2056 	gint				arrowSize;
2057 
2058 	NWEnsureGTKSpinButton( nScreen );
2059 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2060 
2061 	buttonRect = NWGetSpinButtonRect( nScreen, nType, nPart, aAreaRect, nState, aValue, rCaption );
2062 
2063 	NWSetWidgetState( gWidgetData[nScreen].gSpinButtonWidget, nState, stateType );
2064 	gtk_paint_box( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, shadowType, NULL, gWidgetData[nScreen].gSpinButtonWidget,
2065 			(nPart == PART_BUTTON_UP) ? "spinbutton_up" : "spinbutton_down",
2066 			(buttonRect.Left() - aAreaRect.Left()), (buttonRect.Top() - aAreaRect.Top()),
2067 			buttonRect.GetWidth(), buttonRect.GetHeight() );
2068 
2069 	arrowSize = (buttonRect.GetWidth() - (2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness)) - 4;
2070 	arrowSize -= arrowSize % 2 - 1; /* force odd */
2071     arrowRect.SetSize( Size( arrowSize, arrowSize ) );
2072 	arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
2073 	if ( nPart == PART_BUTTON_UP )
2074 		arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 + 1);
2075 	else
2076 		arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 - 1);
2077 
2078 	gtk_paint_arrow( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[nScreen].gSpinButtonWidget,
2079 			"spinbutton", (nPart == PART_BUTTON_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN, sal_True,
2080 			(arrowRect.Left() - aAreaRect.Left()), (arrowRect.Top() - aAreaRect.Top()),
2081 			arrowRect.GetWidth(), arrowRect.GetHeight() );
2082 }
2083 
2084 
2085 //-------------------------------------
2086 
2087 sal_Bool GtkSalGraphics::NWPaintGTKComboBox( GdkDrawable* gdkDrawable,
2088                                          ControlType nType, ControlPart nPart,
2089                                          const Rectangle& rControlRectangle,
2090                                          const clipList& rClipList,
2091                                          ControlState nState,
2092                                          const ImplControlValue& aValue,
2093                                          const OUString& rCaption )
2094 {
2095 	Rectangle		pixmapRect;
2096 	Rectangle		buttonRect;
2097 	GtkStateType	stateType;
2098 	GtkShadowType	shadowType;
2099 	Rectangle		arrowRect;
2100     gint			x,y;
2101     GdkRectangle	clipRect;
2102 
2103 	NWEnsureGTKButton( m_nScreen );
2104 	NWEnsureGTKArrow( m_nScreen );
2105 	NWEnsureGTKCombo( m_nScreen );
2106 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2107 
2108 	// Find the overall bounding rect of the buttons's drawing area,
2109 	// plus its actual draw rect excluding adornment
2110 	pixmapRect = rControlRectangle;
2111     x = rControlRectangle.Left();
2112     y = rControlRectangle.Top();
2113 
2114 	NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
2115 	NWSetWidgetState( gWidgetData[m_nScreen].gComboWidget, nState, stateType );
2116 	NWSetWidgetState( gWidgetData[m_nScreen].gArrowWidget, nState, stateType );
2117 
2118     buttonRect = NWGetComboBoxButtonRect( m_nScreen, nType, PART_BUTTON_DOWN, pixmapRect, nState, aValue, rCaption );
2119     if( nPart == PART_BUTTON_DOWN )
2120         buttonRect.Left() += 1;
2121 
2122 	Rectangle		aEditBoxRect( pixmapRect );
2123 	aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
2124 
2125     #define ARROW_EXTENT		0.7
2126 	arrowRect.SetSize( Size( (gint)(MIN_ARROW_SIZE * ARROW_EXTENT),
2127 	                         (gint)(MIN_ARROW_SIZE * ARROW_EXTENT) ) );
2128 	arrowRect.SetPos( Point( buttonRect.Left() + (gint)((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
2129                              buttonRect.Top() + (gint)((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
2130 
2131     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2132     {
2133         clipRect.x = it->Left();
2134         clipRect.y = it->Top();
2135         clipRect.width = it->GetWidth();
2136         clipRect.height = it->GetHeight();
2137 
2138         if( nPart == PART_ENTIRE_CONTROL )
2139             NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, aEditBoxRect,
2140                                nState, aValue, rCaption );
2141 
2142         // Buttons must paint opaque since some themes have alpha-channel enabled buttons
2143         gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
2144                             &clipRect, m_pWindow, "base",
2145                             x+(buttonRect.Left() - pixmapRect.Left()),
2146                             y+(buttonRect.Top() - pixmapRect.Top()),
2147                             buttonRect.GetWidth(), buttonRect.GetHeight() );
2148         gtk_paint_box( GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button->style, gdkDrawable, stateType, shadowType,
2149                        &clipRect, GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button, "button",
2150                        x+(buttonRect.Left() - pixmapRect.Left()),
2151                        y+(buttonRect.Top() - pixmapRect.Top()),
2152                        buttonRect.GetWidth(), buttonRect.GetHeight() );
2153 
2154         gtk_paint_arrow( gWidgetData[m_nScreen].gArrowWidget->style, gdkDrawable, stateType, shadowType,
2155                          &clipRect, gWidgetData[m_nScreen].gArrowWidget, "arrow", GTK_ARROW_DOWN, sal_True,
2156                          x+(arrowRect.Left() - pixmapRect.Left()), y+(arrowRect.Top() - pixmapRect.Top()),
2157                          arrowRect.GetWidth(), arrowRect.GetHeight() );
2158     }
2159 
2160 	return( sal_True );
2161 }
2162 
2163 //----
2164 
2165 static Rectangle NWGetComboBoxButtonRect( int nScreen,
2166                                           ControlType,
2167 									      ControlPart nPart,
2168                                           Rectangle				aAreaRect,
2169                                           ControlState,
2170                                           const ImplControlValue&,
2171                                           const OUString& )
2172 {
2173 	Rectangle	aButtonRect;
2174 	gint		nArrowWidth;
2175     gint        nButtonWidth;
2176 	gint		nFocusWidth;
2177 	gint		nFocusPad;
2178 
2179 	NWEnsureGTKArrow( nScreen );
2180 
2181 	// Grab some button style attributes
2182 	gtk_widget_style_get( gWidgetData[nScreen].gDropdownWidget,
2183                                   	"focus-line-width",	&nFocusWidth,
2184 									"focus-padding", 	&nFocusPad, (char *)NULL );
2185 
2186 	nArrowWidth = MIN_ARROW_SIZE + (GTK_MISC(gWidgetData[nScreen].gArrowWidget)->xpad * 2);
2187     nButtonWidth = nArrowWidth +
2188                    ((BTN_CHILD_SPACING + gWidgetData[nScreen].gDropdownWidget->style->xthickness) * 2)
2189 				   + (2 * (nFocusWidth+nFocusPad));
2190     if( nPart == PART_BUTTON_DOWN )
2191     {
2192         aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
2193         aButtonRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth,
2194                                    aAreaRect.Top() ) );
2195     }
2196     else if( nPart == PART_SUB_EDIT )
2197     {
2198         NWEnsureGTKCombo( nScreen );
2199 
2200         gint adjust_x = GTK_CONTAINER(gWidgetData[nScreen].gComboWidget)->border_width +
2201                         nFocusWidth +
2202                         nFocusPad;
2203         gint adjust_y = adjust_x + gWidgetData[nScreen].gComboWidget->style->ythickness;
2204         adjust_x     += gWidgetData[nScreen].gComboWidget->style->xthickness;
2205         aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - 2 * adjust_x,
2206                                    aAreaRect.GetHeight() - 2 * adjust_y ) );
2207         Point aEditPos = aAreaRect.TopLeft();
2208         aEditPos.X() += adjust_x;
2209         aEditPos.Y() += adjust_y;
2210         aButtonRect.SetPos( aEditPos );
2211     }
2212 
2213 	return( aButtonRect );
2214 }
2215 
2216 //-------------------------------------
2217 
2218 
2219 
2220 sal_Bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
2221                                         const Rectangle& rControlRectangle,
2222                                         const clipList&,
2223                                         ControlState nState,
2224                                         const ImplControlValue& aValue,
2225                                         const OUString& )
2226 {
2227     OSL_ASSERT( nType != CTRL_TAB_ITEM || aValue.getType() == CTRL_TAB_ITEM );
2228 	GdkPixmap *	pixmap;
2229 	Rectangle		pixmapRect;
2230 	Rectangle		tabRect;
2231 	GtkStateType	stateType;
2232 	GtkShadowType	shadowType;
2233     if( ! gWidgetData[ m_nScreen ].gCacheTabItems )
2234     {
2235         gWidgetData[ m_nScreen ].gCacheTabItems = new NWPixmapCache( m_nScreen );
2236         gWidgetData[ m_nScreen ].gCacheTabPages = new NWPixmapCache( m_nScreen );
2237     }
2238     NWPixmapCache& aCacheItems = *gWidgetData[ m_nScreen ].gCacheTabItems;
2239     NWPixmapCache& aCachePage = *gWidgetData[ m_nScreen ].gCacheTabPages;
2240 
2241     if( !aCacheItems.GetSize() )
2242         aCacheItems.SetSize( 20 );
2243     if( !aCachePage.GetSize() )
2244         aCachePage.SetSize( 1 );
2245 
2246 	if ( (nType == CTRL_TAB_ITEM) && (aValue.getType() != CTRL_TAB_ITEM) )
2247 	{
2248 		return( false );
2249 	}
2250 
2251 	NWEnsureGTKButton( m_nScreen );
2252 	NWEnsureGTKNotebook( m_nScreen );
2253 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2254 
2255 	// Find the overall bounding rect of the buttons's drawing area,
2256 	// plus its actual draw rect excluding adornment
2257 	pixmapRect = rControlRectangle;
2258 	if ( nType == CTRL_TAB_ITEM )
2259 	{
2260         const TabitemValue *	pTabitemValue = static_cast<const TabitemValue *>(&aValue);
2261 		if ( !pTabitemValue->isFirst() )
2262 		{
2263 			// GTK+ tabs overlap on the right edge (the top tab obscures the
2264 			// left edge of the tab right "below" it, so adjust the rectangle
2265 			// to draw tabs slightly large so the overlap happens
2266 			pixmapRect.Move( -2, 0 );
2267 			pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, pixmapRect.GetHeight() ) );
2268 		}
2269 		if ( nState & CTRL_STATE_SELECTED )
2270 		{
2271 			// In GTK+, the selected tab is 2px taller than all other tabs
2272 			pixmapRect.Move( 0, -2 );
2273 			pixmapRect.Bottom() += 2;
2274 			tabRect = pixmapRect;
2275 			// Only draw over 1 pixel of the tab pane that this tab is drawn on top of.
2276 			tabRect.Bottom() -= 1;
2277 		}
2278 		else
2279 			tabRect = pixmapRect;
2280 
2281 		// Allow the tab to draw a right border if needed
2282 		tabRect.Right() -= 1;
2283 
2284         // #129732# avoid degenerate cases which might lead to crashes
2285         if( tabRect.GetWidth() <= 1 || tabRect.GetHeight() <= 1 )
2286             return false;
2287 	}
2288 
2289     if( nType == CTRL_TAB_ITEM )
2290     {
2291         if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) )
2292             return NWRenderPixmapToScreen( pixmap, pixmapRect );
2293     }
2294     else
2295     {
2296         if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) )
2297             return NWRenderPixmapToScreen( pixmap, pixmapRect );
2298     }
2299 
2300 
2301 //	gtk_widget_set_state( gWidgetData[m_nScreen].gNotebookWidget, stateType );
2302 
2303     pixmap = gdk_pixmap_new( NULL, pixmapRect.GetWidth(), pixmapRect.GetHeight(),
2304                              GetX11SalData()->GetDisplay()->GetVisual( m_nScreen ).GetDepth() );
2305     GdkRectangle paintRect;
2306     paintRect.x = paintRect.y = 0;
2307     paintRect.width = pixmapRect.GetWidth();
2308     paintRect.height = pixmapRect.GetHeight();
2309 
2310     gtk_paint_flat_box( m_pWindow->style, pixmap, GTK_STATE_NORMAL,
2311 		                GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", 0, 0, -1, -1);
2312 
2313 	NWSetWidgetState( gWidgetData[m_nScreen].gNotebookWidget, nState, stateType );
2314 
2315 	switch( nType )
2316 	{
2317 		case CTRL_TAB_BODY:
2318 			break;
2319 
2320 		case CTRL_FIXEDBORDER:
2321 		case CTRL_TAB_PANE:
2322 			gtk_paint_box_gap( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget,
2323 				(char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 );
2324 			break;
2325 
2326 		case CTRL_TAB_ITEM:
2327 			stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE;
2328 
2329 			gtk_paint_extension( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget,
2330 				(char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()),
2331 				tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM );
2332 
2333 			if ( nState & CTRL_STATE_SELECTED )
2334 			{
2335 				gtk_paint_flat_box( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow,
2336 					(char *)"base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 );
2337 			}
2338 			break;
2339 
2340 		default:
2341 			break;
2342 	}
2343 
2344 	// Crux seems to think it can make the pane without a left edge
2345 	if ( nType == CTRL_FIXEDBORDER )
2346 		pixmapRect.Move( 1, 0 );
2347 
2348     // cache data
2349     if( nType == CTRL_TAB_ITEM )
2350         aCacheItems.Fill( nType, nState, pixmapRect, pixmap );
2351     else
2352         aCachePage.Fill( nType, nState, pixmapRect, pixmap );
2353 
2354 	sal_Bool bSuccess = NWRenderPixmapToScreen(pixmap, pixmapRect);
2355 	g_object_unref( pixmap );
2356 	return bSuccess;
2357 }
2358 
2359 //-------------------------------------
2360 
2361 sal_Bool GtkSalGraphics::NWPaintGTKListBox( GdkDrawable* gdkDrawable,
2362                                         ControlType nType, ControlPart nPart,
2363                                         const Rectangle& rControlRectangle,
2364                                         const clipList& rClipList,
2365                                         ControlState nState,
2366                                         const ImplControlValue& aValue,
2367                                         const OUString& rCaption )
2368 {
2369 	Rectangle		pixmapRect;
2370 	Rectangle		widgetRect;
2371 	Rectangle		aIndicatorRect;
2372 	GtkStateType	stateType;
2373 	GtkShadowType	shadowType;
2374 	gint			bInteriorFocus;
2375 	gint			nFocusLineWidth;
2376 	gint			nFocusPadding;
2377     gint			x,y;
2378     GdkRectangle    clipRect;
2379 
2380 	NWEnsureGTKButton( m_nScreen );
2381 	NWEnsureGTKOptionMenu( m_nScreen );
2382 	NWEnsureGTKScrolledWindow( m_nScreen );
2383 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2384 
2385 	// Find the overall bounding rect of the buttons's drawing area,
2386 	// plus its actual draw rect excluding adornment
2387 	pixmapRect = rControlRectangle;
2388 	if ( nPart == PART_WINDOW )
2389 	{
2390 		// Make the widget a _bit_ bigger
2391 		pixmapRect.SetPos( Point( pixmapRect.Left() - 1,
2392                                   pixmapRect.Top() - 1 ) );
2393 		pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2,
2394 		                          pixmapRect.GetHeight() + 2 ) );
2395 	}
2396 
2397 	widgetRect = pixmapRect;
2398     x = pixmapRect.Left();
2399     y = pixmapRect.Top();
2400 
2401     // set up references to correct drawable and cliprect
2402 	NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
2403 	NWSetWidgetState( gWidgetData[m_nScreen].gOptionMenuWidget, nState, stateType );
2404 	NWSetWidgetState( gWidgetData[m_nScreen].gScrolledWindowWidget, nState, stateType );
2405 
2406 	if ( nPart != PART_WINDOW )
2407 	{
2408 		gtk_widget_style_get( gWidgetData[m_nScreen].gOptionMenuWidget,
2409 			"interior_focus",	&bInteriorFocus,
2410 			"focus_line_width",	&nFocusLineWidth,
2411 			"focus_padding",	&nFocusPadding,
2412 			(char *)NULL);
2413     }
2414 
2415     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2416     {
2417         clipRect.x = it->Left();
2418         clipRect.y = it->Top();
2419         clipRect.width = it->GetWidth();
2420         clipRect.height = it->GetHeight();
2421 
2422         if ( nPart != PART_WINDOW )
2423         {
2424             // Listboxes must paint opaque since some themes have alpha-channel enabled bodies
2425             gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
2426                                 &clipRect, m_pWindow, "base", x, y,
2427                                 pixmapRect.GetWidth(), pixmapRect.GetHeight() );
2428             gtk_paint_box( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect,
2429                            gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenu",
2430                            x+(widgetRect.Left() - pixmapRect.Left()),
2431                            y+(widgetRect.Top() - pixmapRect.Top()),
2432                            widgetRect.GetWidth(), widgetRect.GetHeight() );
2433             aIndicatorRect = NWGetListBoxIndicatorRect( m_nScreen, nType, nPart, widgetRect, nState,
2434                                                         aValue, rCaption );
2435             gtk_paint_tab( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect,
2436                            gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenutab",
2437                            x+(aIndicatorRect.Left() - pixmapRect.Left()),
2438                            y+(aIndicatorRect.Top() - pixmapRect.Top()),
2439                            aIndicatorRect.GetWidth(), aIndicatorRect.GetHeight() );
2440         }
2441         else
2442         {
2443             shadowType = GTK_SHADOW_IN;
2444 
2445             gtk_paint_shadow( gWidgetData[m_nScreen].gScrolledWindowWidget->style, gdkDrawable, GTK_STATE_NORMAL, shadowType,
2446                 &clipRect, gWidgetData[m_nScreen].gScrolledWindowWidget, "scrolled_window",
2447                 x+(widgetRect.Left() - pixmapRect.Left()), y+(widgetRect.Top() - pixmapRect.Top()),
2448                 widgetRect.GetWidth(), widgetRect.GetHeight() );
2449         }
2450     }
2451 
2452 	return( sal_True );
2453 }
2454 
2455 sal_Bool GtkSalGraphics::NWPaintGTKToolbar(
2456             GdkDrawable* gdkDrawable,
2457             ControlType, ControlPart nPart,
2458 			const Rectangle& rControlRectangle,
2459             const clipList& rClipList,
2460             ControlState nState, const ImplControlValue& aValue,
2461 			const OUString& )
2462 {
2463 	GtkStateType	stateType;
2464 	GtkShadowType	shadowType;
2465 	gint			x, y, w, h;
2466     gint            g_x=0, g_y=0, g_w=10, g_h=10;
2467     bool            bPaintButton = true;
2468     GtkWidget*      pButtonWidget = gWidgetData[m_nScreen].gToolbarButtonWidget;
2469     GdkRectangle	clipRect;
2470 
2471 	NWEnsureGTKToolbar( m_nScreen );
2472     if( nPart == PART_BUTTON ) // toolbar buttons cannot focus in gtk
2473         nState &= ~CTRL_STATE_FOCUSED;
2474 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2475 
2476 	x = rControlRectangle.Left();
2477     y = rControlRectangle.Top();
2478 	w = rControlRectangle.GetWidth();
2479 	h = rControlRectangle.GetHeight();
2480 
2481     // handle toolbar
2482     if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
2483     {
2484 	    NWSetWidgetState( gWidgetData[m_nScreen].gToolbarWidget, nState, stateType );
2485 
2486         GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE );
2487         if ( nState & CTRL_STATE_ENABLED )
2488             GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE );
2489 
2490         if( nPart == PART_DRAW_BACKGROUND_HORZ )
2491             gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_HORIZONTAL );
2492         else
2493             gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_VERTICAL );
2494     }
2495     // handle grip
2496     else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
2497     {
2498 	    NWSetWidgetState( gWidgetData[m_nScreen].gHandleBoxWidget, nState, stateType );
2499 
2500         GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE );
2501         if ( nState & CTRL_STATE_ENABLED )
2502             GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE );
2503 
2504         gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(gWidgetData[m_nScreen].gHandleBoxWidget), shadowType );
2505 
2506         // evaluate grip rect
2507         if( aValue.getType() == CTRL_TOOLBAR )
2508         {
2509             const ToolbarValue* pVal = static_cast<const ToolbarValue*>(&aValue);
2510             g_x = pVal->maGripRect.Left();
2511             g_y = pVal->maGripRect.Top();
2512             g_w = pVal->maGripRect.GetWidth();
2513             g_h = pVal->maGripRect.GetHeight();
2514         }
2515     }
2516     // handle button
2517     else if( nPart == PART_BUTTON )
2518     {
2519         bPaintButton =
2520             (GTK_BUTTON(pButtonWidget)->relief != GTK_RELIEF_NONE)
2521             || (nState & CTRL_STATE_PRESSED)
2522 		    || (nState & CTRL_STATE_ROLLOVER);
2523         if( aValue.getTristateVal() == BUTTONVALUE_ON )
2524         {
2525             pButtonWidget = gWidgetData[m_nScreen].gToolbarToggleWidget;
2526             shadowType = GTK_SHADOW_IN;
2527             stateType = GTK_STATE_ACTIVE;
2528             // special case stateType value for depressed toggle buttons
2529             // cf. gtk+/gtk/gtktogglebutton.c (gtk_toggle_button_update_state)
2530             if( (nState & (CTRL_STATE_ROLLOVER|CTRL_STATE_PRESSED)) )
2531             {
2532                 stateType = GTK_STATE_PRELIGHT;
2533                 shadowType = GTK_SHADOW_OUT;
2534             }
2535             bPaintButton = true;
2536         }
2537         else
2538             stateType = GTK_STATE_PRELIGHT; // only for bPaintButton = true, in which case always rollver is meant
2539 
2540         NWSetWidgetState( pButtonWidget, nState, stateType );
2541         gtk_widget_ensure_style( pButtonWidget );
2542     }
2543 
2544     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2545     {
2546         clipRect.x = it->Left();
2547         clipRect.y = it->Top();
2548         clipRect.width = it->GetWidth();
2549         clipRect.height = it->GetHeight();
2550 
2551         // draw toolbar
2552         if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
2553         {
2554             gtk_paint_flat_box( gWidgetData[m_nScreen].gToolbarWidget->style,
2555                                 gdkDrawable,
2556                                 (GtkStateType)GTK_STATE_NORMAL,
2557                                 GTK_SHADOW_NONE,
2558                                 &clipRect,
2559                                 gWidgetData[m_nScreen].gToolbarWidget,
2560                                 "base",
2561                                 x, y, w, h );
2562             gtk_paint_box( gWidgetData[m_nScreen].gToolbarWidget->style,
2563                            gdkDrawable,
2564                            stateType,
2565                            shadowType,
2566                            &clipRect,
2567                            gWidgetData[m_nScreen].gToolbarWidget,
2568                            "toolbar",
2569                            x, y, w, h );
2570         }
2571         // draw grip
2572         else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
2573         {
2574             gtk_paint_handle( gWidgetData[m_nScreen].gHandleBoxWidget->style,
2575                               gdkDrawable,
2576                               GTK_STATE_NORMAL,
2577                               GTK_SHADOW_OUT,
2578                               &clipRect,
2579                               gWidgetData[m_nScreen].gHandleBoxWidget,
2580                               "handlebox",
2581                               g_x, g_y, g_w, g_h,
2582                               nPart == PART_THUMB_HORZ ?
2583                               GTK_ORIENTATION_HORIZONTAL :
2584                               GTK_ORIENTATION_VERTICAL
2585                               );
2586         }
2587         // draw button
2588         else if( nPart == PART_BUTTON )
2589         {
2590             if( bPaintButton )
2591             {
2592                 gtk_paint_box( pButtonWidget->style, gdkDrawable,
2593                                stateType,
2594                                shadowType,
2595                                &clipRect,
2596                                pButtonWidget, "button", x, y, w, h );
2597             }
2598         }
2599     }
2600 
2601 	return( sal_True );
2602 }
2603 
2604 //----
2605 
2606 sal_Bool GtkSalGraphics::NWPaintGTKMenubar(
2607             GdkDrawable* gdkDrawable,
2608             ControlType, ControlPart nPart,
2609 			const Rectangle& rControlRectangle,
2610             const clipList& rClipList,
2611             ControlState nState, const ImplControlValue&,
2612 			const OUString& )
2613 {
2614 	GtkStateType	stateType;
2615 	GtkShadowType	shadowType;
2616     GtkShadowType   selected_shadow_type = GTK_SHADOW_OUT;
2617 	gint			x, y, w, h;
2618     GdkRectangle	clipRect;
2619 
2620 	NWEnsureGTKMenubar( m_nScreen );
2621 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2622 
2623 	x = rControlRectangle.Left();
2624     y = rControlRectangle.Top();
2625 	w = rControlRectangle.GetWidth();
2626 	h = rControlRectangle.GetHeight();
2627 
2628     if( nPart == PART_MENU_ITEM )
2629     {
2630         if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) )
2631         {
2632             gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenubarWidget,
2633                                   "selected_shadow_type", &selected_shadow_type,
2634                                   (char *)NULL);
2635         }
2636     }
2637 
2638     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2639     {
2640         clipRect.x = it->Left();
2641         clipRect.y = it->Top();
2642         clipRect.width = it->GetWidth();
2643         clipRect.height = it->GetHeight();
2644 
2645         // handle Menubar
2646         if( nPart == PART_ENTIRE_CONTROL )
2647         {
2648             NWSetWidgetState( gWidgetData[m_nScreen].gMenubarWidget, nState, stateType );
2649 
2650             GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE );
2651             if ( nState & CTRL_STATE_ENABLED )
2652                 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE );
2653 
2654             // #118704# for translucent menubar styles paint background first
2655             gtk_paint_flat_box( gWidgetData[m_nScreen].gMenubarWidget->style,
2656                                 gdkDrawable,
2657                                 GTK_STATE_NORMAL,
2658                                 GTK_SHADOW_NONE,
2659                                 &clipRect,
2660                                 GTK_WIDGET(m_pWindow),
2661                                 "base",
2662                                 x, y, w, h );
2663             gtk_paint_box( gWidgetData[m_nScreen].gMenubarWidget->style,
2664                            gdkDrawable,
2665                            stateType,
2666                            shadowType,
2667                            &clipRect,
2668                            gWidgetData[m_nScreen].gMenubarWidget,
2669                            "menubar",
2670                            x, y, w, h );
2671         }
2672         else if( nPart == PART_MENU_ITEM )
2673         {
2674             if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) )
2675             {
2676                 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenubarWidget->style,
2677                                gdkDrawable,
2678                                GTK_STATE_PRELIGHT,
2679                                selected_shadow_type,
2680                                &clipRect,
2681                                gWidgetData[m_nScreen].gMenuItemMenubarWidget,
2682                                "menuitem",
2683                                x, y, w, h);
2684             }
2685         }
2686     }
2687 
2688 	return( sal_True );
2689 }
2690 
2691 sal_Bool GtkSalGraphics::NWPaintGTKPopupMenu(
2692             GdkDrawable* gdkDrawable,
2693             ControlType, ControlPart nPart,
2694 			const Rectangle& rControlRectangle,
2695             const clipList& rClipList,
2696             ControlState nState, const ImplControlValue&,
2697 			const OUString& )
2698 {
2699     // #i50745# gtk does not draw disabled menu entries (and crux theme
2700     // even crashes), draw them using vcl functionality.
2701     if( nPart == PART_MENU_ITEM && ! (nState & CTRL_STATE_ENABLED) )
2702         return sal_False;
2703 
2704 	GtkStateType	stateType;
2705 	GtkShadowType	shadowType;
2706     GtkShadowType   selected_shadow_type = GTK_SHADOW_OUT;
2707 	gint			x, y, w, h;
2708     GdkRectangle	clipRect;
2709 
2710 	NWEnsureGTKMenu( m_nScreen );
2711 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2712 
2713 	x = rControlRectangle.Left();
2714     y = rControlRectangle.Top();
2715 	w = rControlRectangle.GetWidth();
2716 	h = rControlRectangle.GetHeight();
2717 
2718     if( nPart == PART_MENU_ITEM &&
2719         ( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) )
2720     {
2721         gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenuWidget,
2722                               "selected_shadow_type", &selected_shadow_type,
2723                               (char *)NULL);
2724     }
2725 
2726     NWSetWidgetState( gWidgetData[m_nScreen].gMenuWidget, nState, stateType );
2727 
2728     GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE );
2729     if ( nState & CTRL_STATE_ENABLED )
2730         GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE );
2731 
2732     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2733     {
2734         clipRect.x = it->Left();
2735         clipRect.y = it->Top();
2736         clipRect.width = it->GetWidth();
2737         clipRect.height = it->GetHeight();
2738 
2739         if( nPart == PART_ENTIRE_CONTROL )
2740         {
2741             // #118704# for translucent menubar styles paint background first
2742             gtk_paint_flat_box( gWidgetData[m_nScreen].gMenuWidget->style,
2743                                 gdkDrawable,
2744                                 GTK_STATE_NORMAL,
2745                                 GTK_SHADOW_NONE,
2746                                 &clipRect,
2747                                 GTK_WIDGET(m_pWindow),
2748                                 "base",
2749                                 x, y, w, h );
2750             gtk_paint_box( gWidgetData[m_nScreen].gMenuWidget->style,
2751                            gdkDrawable,
2752                            GTK_STATE_NORMAL,
2753                            GTK_SHADOW_OUT,
2754                            &clipRect,
2755                            gWidgetData[m_nScreen].gMenuWidget,
2756                            "menu",
2757                            x, y, w, h );
2758         }
2759         else if( nPart == PART_MENU_ITEM )
2760         {
2761             if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) )
2762             {
2763                 if( nState & CTRL_STATE_ENABLED )
2764                 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenuWidget->style,
2765                                gdkDrawable,
2766                                GTK_STATE_PRELIGHT,
2767                                selected_shadow_type,
2768                                &clipRect,
2769                                gWidgetData[m_nScreen].gMenuItemMenuWidget,
2770                                "menuitem",
2771                                x, y, w, h);
2772             }
2773         }
2774         else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK )
2775         {
2776             GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ?
2777                                  gWidgetData[m_nScreen].gMenuItemCheckMenuWidget :
2778                                  gWidgetData[m_nScreen].gMenuItemRadioMenuWidget;
2779 
2780             GtkStateType nStateType = GTK_STATE_NORMAL;
2781             GtkShadowType nShadowType;
2782 
2783             if ( nState & CTRL_STATE_SELECTED )
2784                 nStateType = GTK_STATE_PRELIGHT;
2785 
2786             NWSetWidgetState( pWidget, nState, nStateType );
2787 
2788             if ( nState & CTRL_STATE_PRESSED )
2789                 nShadowType = GTK_SHADOW_IN;
2790             else
2791                 nShadowType = GTK_SHADOW_OUT;
2792 
2793             if ( nPart == PART_MENU_ITEM_CHECK_MARK )
2794             {
2795                 gtk_paint_check( pWidget->style,
2796                                  gdkDrawable,
2797                                  nStateType,
2798                                  nShadowType,
2799                                  &clipRect,
2800                                  gWidgetData[m_nScreen].gMenuItemMenuWidget,
2801                                  "check",
2802                                  x, y, w, h );
2803             }
2804             else
2805             {
2806                 gtk_paint_option( pWidget->style,
2807                                   gdkDrawable,
2808                                   nStateType,
2809                                   nShadowType,
2810                                   &clipRect,
2811                                   gWidgetData[m_nScreen].gMenuItemMenuWidget,
2812                                   "option",
2813                                   x, y, w, h );
2814             }
2815         }
2816     }
2817 
2818 	return( sal_True );
2819 }
2820 
2821 sal_Bool GtkSalGraphics::NWPaintGTKTooltip(
2822             GdkDrawable* gdkDrawable,
2823             ControlType, ControlPart,
2824 			const Rectangle& rControlRectangle,
2825             const clipList& rClipList,
2826             ControlState, const ImplControlValue&,
2827 			const OUString& )
2828 {
2829     NWEnsureGTKTooltip( m_nScreen );
2830 
2831 	gint			x, y, w, h;
2832     GdkRectangle	clipRect;
2833 
2834 	x = rControlRectangle.Left();
2835     y = rControlRectangle.Top();
2836 	w = rControlRectangle.GetWidth();
2837 	h = rControlRectangle.GetHeight();
2838 
2839     for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2840     {
2841         clipRect.x = it->Left();
2842         clipRect.y = it->Top();
2843         clipRect.width = it->GetWidth();
2844         clipRect.height = it->GetHeight();
2845 
2846         gtk_paint_flat_box( gWidgetData[m_nScreen].gTooltipPopup->style,
2847                             gdkDrawable,
2848                             GTK_STATE_NORMAL,
2849                             GTK_SHADOW_OUT,
2850                             &clipRect,
2851                             gWidgetData[m_nScreen].gTooltipPopup,
2852                             "tooltip",
2853                             x, y, w, h );
2854     }
2855 
2856 	return( sal_True );
2857 }
2858 
2859 sal_Bool GtkSalGraphics::NWPaintGTKListNode(
2860             GdkDrawable*,
2861             ControlType, ControlPart,
2862 			const Rectangle& rControlRectangle,
2863             const clipList&,
2864             ControlState nState, const ImplControlValue& rValue,
2865 			const OUString& )
2866 {
2867     NWEnsureGTKTreeView( m_nScreen );
2868 
2869     Rectangle aRect( rControlRectangle );
2870     aRect.Left() -= 2;
2871     aRect.Right() += 2;
2872     aRect.Top() -= 2;
2873     aRect.Bottom() += 2;
2874 	gint			w, h;
2875 	w = aRect.GetWidth();
2876 	h = aRect.GetHeight();
2877 
2878 	GtkStateType	stateType;
2879 	GtkShadowType	shadowType;
2880 	NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2881 
2882     ButtonValue aButtonValue = rValue.getTristateVal();
2883     GtkExpanderStyle eStyle = GTK_EXPANDER_EXPANDED;
2884 
2885     switch( aButtonValue )
2886     {
2887         case BUTTONVALUE_ON: eStyle = GTK_EXPANDER_EXPANDED;break;
2888         case BUTTONVALUE_OFF: eStyle = GTK_EXPANDER_COLLAPSED; break;
2889         default:
2890             break;
2891     }
2892 
2893     GdkPixmap* pixmap = NWGetPixmapFromScreen( aRect );
2894     if( ! pixmap )
2895         return sal_False;
2896 
2897     GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap );
2898     gtk_paint_expander( gWidgetData[m_nScreen].gTreeView->style,
2899                         pixDrawable,
2900                         stateType,
2901                         NULL,
2902                         gWidgetData[m_nScreen].gTreeView,
2903                         "treeview",
2904                         w/2, h/2,
2905                         eStyle );
2906 
2907 	sal_Bool bRet = NWRenderPixmapToScreen( pixmap, aRect );
2908     g_object_unref( pixmap );
2909 
2910 	return bRet;
2911 }
2912 
2913 sal_Bool GtkSalGraphics::NWPaintGTKProgress(
2914             GdkDrawable*,
2915             ControlType, ControlPart,
2916 			const Rectangle& rControlRectangle,
2917             const clipList&,
2918             ControlState, const ImplControlValue& rValue,
2919 			const OUString& )
2920 {
2921     NWEnsureGTKProgressBar( m_nScreen );
2922 
2923 	gint			w, h;
2924 	w = rControlRectangle.GetWidth();
2925 	h = rControlRectangle.GetHeight();
2926 
2927     long nProgressWidth = rValue.getNumericVal();
2928 
2929     GdkPixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) );
2930     if( ! pixmap )
2931         return sal_False;
2932 
2933     GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap );
2934 
2935     // paint background
2936     gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style,
2937                         pixDrawable,
2938                         GTK_STATE_NORMAL,
2939                         GTK_SHADOW_NONE,
2940                         NULL,
2941                         gWidgetData[m_nScreen].gProgressBar,
2942                         "trough",
2943                         0, 0, w, h );
2944     if( nProgressWidth > 0 )
2945     {
2946         // paint progress
2947         if( Application::GetSettings().GetLayoutRTL() )
2948         {
2949             gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style,
2950                            pixDrawable,
2951                            GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
2952                            NULL,
2953                            gWidgetData[m_nScreen].gProgressBar,
2954                            "bar",
2955                            w-nProgressWidth, 0, nProgressWidth, h
2956                            );
2957         }
2958         else
2959         {
2960             gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style,
2961                            pixDrawable,
2962                            GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
2963                            NULL,
2964                            gWidgetData[m_nScreen].gProgressBar,
2965                            "bar",
2966                            0, 0, nProgressWidth, h
2967                            );
2968         }
2969     }
2970 
2971 	sal_Bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle );
2972     g_object_unref( pixmap );
2973 
2974 	return bRet;
2975 }
2976 
2977 sal_Bool GtkSalGraphics::NWPaintGTKSlider(
2978             GdkDrawable*,
2979             ControlType, ControlPart nPart,
2980 			const Rectangle& rControlRectangle,
2981             const clipList&,
2982             ControlState nState, const ImplControlValue& rValue,
2983 			const OUString& )
2984 {
2985     OSL_ASSERT( rValue.getType() == CTRL_SLIDER );
2986     NWEnsureGTKSlider( m_nScreen );
2987 
2988 	gint			w, h;
2989 	w = rControlRectangle.GetWidth();
2990 	h = rControlRectangle.GetHeight();
2991 
2992     const SliderValue* pVal = static_cast<const SliderValue*>(&rValue);
2993 
2994     GdkPixmap* pixmap = NWGetPixmapFromScreen( rControlRectangle );
2995     if( ! pixmap )
2996         return sal_False;
2997 
2998     GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap );
2999     GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA)
3000                          ? GTK_WIDGET(gWidgetData[m_nScreen].gHScale)
3001                          : GTK_WIDGET(gWidgetData[m_nScreen].gVScale);
3002     const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale";
3003     GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
3004     GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE;
3005     gint slider_width = 10;
3006     gint slider_length = 10;
3007     gint trough_border = 0;
3008     gtk_widget_style_get( pWidget,
3009                           "slider-width", &slider_width,
3010                           "slider-length", &slider_length,
3011                           "trough-border", &trough_border,
3012                           NULL);
3013 
3014     eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
3015     if( nPart == PART_TRACK_HORZ_AREA )
3016     {
3017         gtk_paint_box( pWidget->style,
3018                        pixDrawable,
3019                        eState,
3020                        GTK_SHADOW_IN,
3021                        NULL,
3022                        pWidget,
3023                        "trough",
3024                        0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border);
3025         gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
3026         gtk_paint_slider( pWidget->style,
3027                           pixDrawable,
3028                           eState,
3029                           GTK_SHADOW_OUT,
3030                           NULL,
3031                           pWidget,
3032                           pDetail,
3033                           x, (h-slider_width)/2,
3034                           slider_length, slider_width,
3035                           eOri );
3036     }
3037     else
3038     {
3039         gtk_paint_box( pWidget->style,
3040                        pixDrawable,
3041                        eState,
3042                        GTK_SHADOW_IN,
3043                        NULL,
3044                        pWidget,
3045                        "trough",
3046                        (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h);
3047         gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin);
3048         gtk_paint_slider( pWidget->style,
3049                           pixDrawable,
3050                           eState,
3051                           GTK_SHADOW_OUT,
3052                           NULL,
3053                           pWidget,
3054                           pDetail,
3055                           (w-slider_width)/2, y,
3056                           slider_width, slider_length,
3057                           eOri );
3058     }
3059     #if 0
3060     // paint background
3061     gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style,
3062                         pixDrawable,
3063                         GTK_STATE_NORMAL,
3064                         GTK_SHADOW_NONE,
3065                         NULL,
3066                         gWidgetData[m_nScreen].gProgressBar,
3067                         "trough",
3068                         0, 0, w, h );
3069     if( nProgressWidth > 0 )
3070     {
3071         // paint progress
3072         if( Application::GetSettings().GetLayoutRTL() )
3073         {
3074             gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style,
3075                            pixDrawable,
3076                            GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
3077                            NULL,
3078                            gWidgetData[m_nScreen].gProgressBar,
3079                            "bar",
3080                            w-nProgressWidth, 0, nProgressWidth, h
3081                            );
3082         }
3083         else
3084         {
3085             gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style,
3086                            pixDrawable,
3087                            GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
3088                            NULL,
3089                            gWidgetData[m_nScreen].gProgressBar,
3090                            "bar",
3091                            0, 0, nProgressWidth, h
3092                            );
3093         }
3094     }
3095     #endif
3096 
3097 	sal_Bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle );
3098     g_object_unref( pixmap );
3099 
3100 	return bRet;
3101 }
3102 
3103 //----
3104 
3105 static Rectangle NWGetListBoxButtonRect( int nScreen,
3106                                          ControlType,
3107                                          ControlPart    nPart,
3108                                          Rectangle      aAreaRect,
3109                                          ControlState,
3110                                          const ImplControlValue&,
3111                                          const OUString& )
3112 {
3113 	Rectangle       aPartRect;
3114 	GtkRequisition *pIndicatorSize = NULL;
3115 	GtkBorder      *pIndicatorSpacing = NULL;
3116 	gint            width = 13;	// GTK+ default
3117 	gint            right = 5;	// GTK+ default
3118 	gint            nButtonAreaWidth = 0;
3119     gint            xthickness = 0;
3120 
3121 	NWEnsureGTKOptionMenu( nScreen );
3122 
3123 	gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget,
3124 			"indicator_size",	&pIndicatorSize,
3125 			"indicator_spacing",&pIndicatorSpacing, (char *)NULL);
3126 
3127 	if ( pIndicatorSize )
3128 		width = pIndicatorSize->width;
3129 
3130 	if ( pIndicatorSpacing )
3131 		right = pIndicatorSpacing->right;
3132 
3133     Size aPartSize( 0, aAreaRect.GetHeight() );
3134     Point aPartPos ( 0, aAreaRect.Top() );
3135 
3136     xthickness = gWidgetData[nScreen].gOptionMenuWidget->style->xthickness;
3137 	nButtonAreaWidth = width + right + (xthickness * 2);
3138 	switch( nPart )
3139 	{
3140 		case PART_BUTTON_DOWN:
3141 			aPartSize.Width() = nButtonAreaWidth;
3142 			aPartPos.X() = aAreaRect.Left() + aAreaRect.GetWidth() - aPartSize.Width();
3143 			break;
3144 
3145 		case PART_SUB_EDIT:
3146 			aPartSize.Width() = aAreaRect.GetWidth() - nButtonAreaWidth - xthickness;
3147 			aPartPos.X() = aAreaRect.Left() + xthickness;
3148 			break;
3149 
3150 		default:
3151 			aPartSize.Width() = aAreaRect.GetWidth();
3152 			aPartPos.X() = aAreaRect.Left();
3153 			break;
3154 	}
3155     aPartRect = Rectangle( aPartPos, aPartSize );
3156 
3157 	if ( pIndicatorSize )
3158 		gtk_requisition_free( pIndicatorSize );
3159 	if ( pIndicatorSpacing )
3160 		gtk_border_free( pIndicatorSpacing );
3161 
3162 	return( aPartRect );
3163 }
3164 
3165 //----
3166 
3167 static Rectangle NWGetListBoxIndicatorRect( int nScreen,
3168                                             ControlType,
3169                                             ControlPart,
3170                                             Rectangle				aAreaRect,
3171                                             ControlState,
3172                                             const ImplControlValue&,
3173                                             const OUString& )
3174 {
3175 	Rectangle       aIndicatorRect;
3176 	GtkRequisition *pIndicatorSize = NULL;
3177 	GtkBorder      *pIndicatorSpacing = NULL;
3178 	gint            width = 13;	// GTK+ default
3179 	gint            height = 13;	// GTK+ default
3180 	gint            right = 5;	// GTK+ default
3181 
3182 	NWEnsureGTKOptionMenu( nScreen );
3183 
3184 	gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget,
3185 			"indicator_size",	&pIndicatorSize,
3186 			"indicator_spacing",&pIndicatorSpacing, (char *)NULL);
3187 
3188 	if ( pIndicatorSize )
3189     {
3190 		width = pIndicatorSize->width;
3191 		height = pIndicatorSize->height;
3192     }
3193 
3194 	if ( pIndicatorSpacing )
3195 		right = pIndicatorSpacing->right;
3196 
3197     aIndicatorRect.SetSize( Size( width, height ) );
3198 	aIndicatorRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - width - right - gWidgetData[nScreen].gOptionMenuWidget->style->xthickness,
3199                                   aAreaRect.Top() + ((aAreaRect.GetHeight() - height) / 2) ) );
3200 
3201 	// If height is odd, move the indicator down 1 pixel
3202 	if ( aIndicatorRect.GetHeight() % 2 )
3203 		aIndicatorRect.Move( 0, 1 );
3204 
3205 	if ( pIndicatorSize )
3206 		gtk_requisition_free( pIndicatorSize );
3207 	if ( pIndicatorSpacing )
3208 		gtk_border_free( pIndicatorSpacing );
3209 
3210 	return( aIndicatorRect );
3211 }
3212 
3213 static Rectangle NWGetToolbarRect(  int nScreen,
3214                                     ControlType,
3215 									ControlPart				nPart,
3216 									Rectangle				aAreaRect,
3217 									ControlState,
3218 									const ImplControlValue&,
3219 									const OUString& )
3220 {
3221     Rectangle aRet;
3222 
3223     if( nPart == PART_DRAW_BACKGROUND_HORZ ||
3224         nPart == PART_DRAW_BACKGROUND_VERT )
3225         aRet = aAreaRect;
3226     else if( nPart == PART_THUMB_HORZ )
3227         aRet = Rectangle( Point( 0, 0 ), Size( aAreaRect.GetWidth(), 10 ) );
3228     else if( nPart == PART_THUMB_VERT )
3229         aRet = Rectangle( Point( 0, 0 ), Size( 10, aAreaRect.GetHeight() ) );
3230     else if( nPart == PART_BUTTON )
3231     {
3232         aRet = aAreaRect;
3233 
3234         NWEnsureGTKToolbar( nScreen );
3235 
3236         gint nMinWidth =
3237             2*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness
3238             + 1 // CHILD_SPACING constant, found in gtk_button.c
3239             + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness; // Murphy factor
3240         gint nMinHeight =
3241             2*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness
3242             + 1 // CHILD_SPACING constant, found in gtk_button.c
3243             + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness; // Murphy factor
3244 
3245         gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarButtonWidget );
3246         if( aAreaRect.GetWidth() < nMinWidth )
3247             aRet.Right() = aRet.Left() + nMinWidth;
3248         if( aAreaRect.GetHeight() < nMinHeight  )
3249             aRet.Bottom() = aRet.Top() + nMinHeight;
3250     }
3251 
3252     return aRet;
3253 }
3254 
3255 /************************************************************************
3256  * helper for GtkSalFrame
3257  ************************************************************************/
3258 static inline Color getColor( const GdkColor& rCol )
3259 {
3260     return Color( rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
3261 }
3262 
3263 #if OSL_DEBUG_LEVEL > 1
3264 
3265 void printColor( const char* name, const GdkColor& rCol )
3266 {
3267     std::fprintf( stderr, "   %s = 0x%2x 0x%2x 0x%2x\n",
3268              name,
3269              rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
3270 }
3271 
3272 void printStyleColors( GtkStyle* pStyle )
3273 {
3274     static const char* pStates[] = { "NORMAL", "ACTIVE", "PRELIGHT", "SELECTED", "INSENSITIVE" };
3275 
3276     for( int i = 0; i < 5; i++ )
3277     {
3278         std::fprintf( stderr, "state %s colors:\n", pStates[i] );
3279         printColor( "bg     ", pStyle->bg[i] );
3280         printColor( "fg     ", pStyle->fg[i] );
3281         printColor( "light  ", pStyle->light[i] );
3282         printColor( "dark   ", pStyle->dark[i] );
3283         printColor( "mid    ", pStyle->mid[i] );
3284         printColor( "text   ", pStyle->text[i] );
3285         printColor( "base   ", pStyle->base[i] );
3286         printColor( "text_aa", pStyle->text_aa[i] );
3287     }
3288 }
3289 #endif
3290 
3291 void GtkSalGraphics::updateSettings( AllSettings& rSettings )
3292 {
3293     // get the widgets in place
3294     NWEnsureGTKMenu( m_nScreen );
3295     NWEnsureGTKMenubar( m_nScreen );
3296     NWEnsureGTKScrollbars( m_nScreen );
3297     NWEnsureGTKEditBox( m_nScreen );
3298     NWEnsureGTKTooltip( m_nScreen );
3299 
3300     gtk_widget_ensure_style( m_pWindow );
3301     GtkStyle* pStyle = gtk_widget_get_style( m_pWindow );
3302 
3303     StyleSettings aStyleSet = rSettings.GetStyleSettings();
3304 
3305 #if OSL_DEBUG_LEVEL > 2
3306     printStyleColors( pStyle );
3307 #endif
3308 
3309     // text colors
3310     Color aTextColor = getColor( pStyle->text[GTK_STATE_NORMAL] );
3311     aStyleSet.SetDialogTextColor( aTextColor );
3312     aStyleSet.SetButtonTextColor( aTextColor );
3313     aStyleSet.SetRadioCheckTextColor( aTextColor );
3314     aStyleSet.SetGroupTextColor( aTextColor );
3315     aStyleSet.SetLabelTextColor( aTextColor );
3316     aStyleSet.SetInfoTextColor( aTextColor );
3317     aStyleSet.SetWindowTextColor( aTextColor );
3318     aStyleSet.SetFieldTextColor( aTextColor );
3319 
3320     // Tooltip colors
3321     GtkStyle* pTooltipStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gTooltipPopup );
3322     aTextColor = getColor( pTooltipStyle->fg[ GTK_STATE_NORMAL ] );
3323     aStyleSet.SetHelpTextColor( aTextColor );
3324 
3325     // mouse over text colors
3326     aTextColor = getColor( pStyle->fg[ GTK_STATE_PRELIGHT ] );
3327     aStyleSet.SetButtonRolloverTextColor( aTextColor );
3328     aStyleSet.SetFieldRolloverTextColor( aTextColor );
3329 
3330     // background colors
3331     Color aBackColor = getColor( pStyle->bg[GTK_STATE_NORMAL] );
3332     Color aBackFieldColor = getColor( pStyle->base[ GTK_STATE_NORMAL ] );
3333     aStyleSet.Set3DColors( aBackColor );
3334     aStyleSet.SetFaceColor( aBackColor );
3335     aStyleSet.SetDialogColor( aBackColor );
3336     aStyleSet.SetWorkspaceColor( aBackColor );
3337     aStyleSet.SetFieldColor( aBackFieldColor );
3338     aStyleSet.SetWindowColor( aBackFieldColor );
3339 //    aStyleSet.SetHelpColor( aBackColor );
3340     // ancient wisdom tells us a mystic algorithm how to set checked color
3341     if( aBackColor == COL_LIGHTGRAY )
3342         aStyleSet.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
3343     else
3344     {
3345         Color aColor2 = aStyleSet.GetLightColor();
3346         Color aCheck( (sal_uInt8)(((sal_uInt16)aBackColor.GetRed()+(sal_uInt16)aColor2.GetRed())/2),
3347                       (sal_uInt8)(((sal_uInt16)aBackColor.GetGreen()+(sal_uInt16)aColor2.GetGreen())/2),
3348                       (sal_uInt8)(((sal_uInt16)aBackColor.GetBlue()+(sal_uInt16)aColor2.GetBlue())/2)
3349                       );
3350         aStyleSet.SetCheckedColor( aCheck );
3351     }
3352 
3353     // highlighting colors
3354     Color aHighlightColor = getColor( pStyle->base[GTK_STATE_SELECTED] );
3355     Color aHighlightTextColor = getColor( pStyle->text[GTK_STATE_SELECTED] );
3356     aStyleSet.SetHighlightColor( aHighlightColor );
3357     aStyleSet.SetHighlightTextColor( aHighlightTextColor );
3358 
3359     if( ! gtk_check_version( 2, 10, 0 ) ) // link colors came in with 2.10, avoid an assertion
3360     {
3361         // hyperlink colors
3362         GdkColor *link_color = NULL;
3363         gtk_widget_style_get (m_pWindow, "link-color", &link_color, NULL);
3364         if (link_color)
3365         {
3366             aStyleSet.SetLinkColor(getColor(*link_color));
3367             gdk_color_free (link_color);
3368             link_color = NULL;
3369         }
3370         gtk_widget_style_get (m_pWindow, "visited-link-color", &link_color, NULL);
3371         if (link_color)
3372         {
3373             aStyleSet.SetVisitedLinkColor(getColor(*link_color));
3374             gdk_color_free (link_color);
3375         }
3376     }
3377 
3378     // Tab colors
3379     aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color.
3380     Color aSelectedBackColor = getColor( pStyle->bg[GTK_STATE_ACTIVE] );
3381     aStyleSet.SetInactiveTabColor( aSelectedBackColor );
3382 
3383     // menu disabled entries handling
3384     aStyleSet.SetSkipDisabledInMenus( sal_True );
3385     // menu colors
3386     GtkStyle* pMenuStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gMenuWidget );
3387     GtkStyle* pMenuItemStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenuItemMenuWidget );
3388     GtkStyle* pMenubarStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenubarWidget );
3389     GtkStyle* pMenuTextStyle = gtk_rc_get_style( gtk_bin_get_child( GTK_BIN(gWidgetData[m_nScreen].gMenuItemMenuWidget) ) );
3390 
3391     aBackColor = getColor( pMenubarStyle->bg[GTK_STATE_NORMAL] );
3392     aStyleSet.SetMenuBarColor( aBackColor );
3393     aBackColor = getColor( pMenuStyle->bg[GTK_STATE_NORMAL] );
3394     aTextColor = getColor( pMenuTextStyle->fg[GTK_STATE_NORMAL] );
3395     aStyleSet.SetMenuColor( aBackColor );
3396     aStyleSet.SetMenuTextColor( aTextColor );
3397 
3398     aTextColor = getColor( pMenubarStyle->fg[GTK_STATE_NORMAL] );
3399     aStyleSet.SetMenuBarTextColor( aTextColor );
3400 
3401 #if OSL_DEBUG_LEVEL > 1
3402     std::fprintf( stderr, "==\n" );
3403     std::fprintf( stderr, "MenuColor = %x (%d)\n", (int)aStyleSet.GetMenuColor().GetColor(), aStyleSet.GetMenuColor().GetLuminance() );
3404     std::fprintf( stderr, "MenuTextColor = %x (%d)\n", (int)aStyleSet.GetMenuTextColor().GetColor(), aStyleSet.GetMenuTextColor().GetLuminance() );
3405     std::fprintf( stderr, "MenuBarColor = %x (%d)\n", (int)aStyleSet.GetMenuBarColor().GetColor(), aStyleSet.GetMenuBarColor().GetLuminance() );
3406     std::fprintf( stderr, "MenuBarTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarTextColor().GetColor(), aStyleSet.GetMenuBarTextColor().GetLuminance() );
3407     std::fprintf( stderr, "LightColor = %x (%d)\n", (int)aStyleSet.GetLightColor().GetColor(), aStyleSet.GetLightColor().GetLuminance() );
3408     std::fprintf( stderr, "ShadowColor = %x (%d)\n", (int)aStyleSet.GetShadowColor().GetColor(), aStyleSet.GetShadowColor().GetLuminance() );
3409 #endif
3410 
3411     // Awful hack for menu separators in the Sonar and similar themes.
3412     // If the menu color is not too dark, and the menu text color is lighter,
3413     // make the "light" color lighter than the menu color and the "shadow"
3414     // color darker than it.
3415     if ( aStyleSet.GetMenuColor().GetLuminance() >= 32 &&
3416 	 aStyleSet.GetMenuColor().GetLuminance() <= aStyleSet.GetMenuTextColor().GetLuminance() )
3417     {
3418       Color temp = aStyleSet.GetMenuColor();
3419       temp.IncreaseLuminance( 8 );
3420       aStyleSet.SetLightColor( temp );
3421       temp = aStyleSet.GetMenuColor();
3422       temp.DecreaseLuminance( 16 );
3423       aStyleSet.SetShadowColor( temp );
3424     }
3425 
3426     aHighlightColor = getColor( pMenuItemStyle->bg[ GTK_STATE_SELECTED ] );
3427     aHighlightTextColor = getColor( pMenuTextStyle->fg[ GTK_STATE_PRELIGHT ] );
3428     if( aHighlightColor == aHighlightTextColor )
3429         aHighlightTextColor = (aHighlightColor.GetLuminance() < 128) ? Color( COL_WHITE ) : Color( COL_BLACK );
3430     aStyleSet.SetMenuHighlightColor( aHighlightColor );
3431     aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
3432 
3433     // UI font
3434     OString	aFamily		= pango_font_description_get_family( pStyle->font_desc );
3435     int nPangoHeight	= pango_font_description_get_size( pStyle->font_desc );
3436     PangoStyle	eStyle	= pango_font_description_get_style( pStyle->font_desc );
3437     PangoWeight	eWeight	= pango_font_description_get_weight( pStyle->font_desc );
3438     PangoStretch eStretch = pango_font_description_get_stretch( pStyle->font_desc );
3439 
3440     psp::FastPrintFontInfo aInfo;
3441     // set family name
3442     aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
3443     // set italic
3444     switch( eStyle )
3445     {
3446         case PANGO_STYLE_NORMAL:	aInfo.m_eItalic = psp::italic::Upright;break;
3447         case PANGO_STYLE_ITALIC:	aInfo.m_eItalic = psp::italic::Italic;break;
3448         case PANGO_STYLE_OBLIQUE:	aInfo.m_eItalic = psp::italic::Oblique;break;
3449     }
3450     // set weight
3451     if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
3452         aInfo.m_eWeight = psp::weight::UltraLight;
3453     else if( eWeight <= PANGO_WEIGHT_LIGHT )
3454         aInfo.m_eWeight = psp::weight::Light;
3455     else if( eWeight <= PANGO_WEIGHT_NORMAL )
3456         aInfo.m_eWeight = psp::weight::Normal;
3457     else if( eWeight <= PANGO_WEIGHT_BOLD )
3458         aInfo.m_eWeight = psp::weight::Bold;
3459     else
3460         aInfo.m_eWeight = psp::weight::UltraBold;
3461     // set width
3462     switch( eStretch )
3463     {
3464         case PANGO_STRETCH_ULTRA_CONDENSED:	aInfo.m_eWidth = psp::width::UltraCondensed;break;
3465         case PANGO_STRETCH_EXTRA_CONDENSED:	aInfo.m_eWidth = psp::width::ExtraCondensed;break;
3466         case PANGO_STRETCH_CONDENSED:		aInfo.m_eWidth = psp::width::Condensed;break;
3467         case PANGO_STRETCH_SEMI_CONDENSED:	aInfo.m_eWidth = psp::width::SemiCondensed;break;
3468         case PANGO_STRETCH_NORMAL:			aInfo.m_eWidth = psp::width::Normal;break;
3469         case PANGO_STRETCH_SEMI_EXPANDED:	aInfo.m_eWidth = psp::width::SemiExpanded;break;
3470         case PANGO_STRETCH_EXPANDED:		aInfo.m_eWidth = psp::width::Expanded;break;
3471         case PANGO_STRETCH_EXTRA_EXPANDED:	aInfo.m_eWidth = psp::width::ExtraExpanded;break;
3472         case PANGO_STRETCH_ULTRA_EXPANDED:	aInfo.m_eWidth = psp::width::UltraExpanded;break;
3473     }
3474 
3475 #if OSL_DEBUG_LEVEL > 1
3476     std::fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() );
3477 #endif
3478 
3479     // match font to e.g. resolve "Sans"
3480     psp::PrintFontManager::get().matchFont( aInfo, rSettings.GetUILocale() );
3481 
3482 #if OSL_DEBUG_LEVEL > 1
3483     std::fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
3484              aInfo.m_nID != 0 ? "succeeded" : "failed",
3485              OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
3486 #endif
3487 
3488     sal_Int32 nDispDPIY = GetDisplay()->GetResolution().B();
3489     int nPointHeight = 0;
3490     static gboolean(*pAbso)(const PangoFontDescription*) =
3491         (gboolean(*)(const PangoFontDescription*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "pango_font_description_get_size_is_absolute" );
3492 
3493     if( pAbso && pAbso( pStyle->font_desc ) )
3494         nPointHeight = (nPangoHeight * 72 + nDispDPIY*PANGO_SCALE/2) / (nDispDPIY * PANGO_SCALE);
3495     else
3496         nPointHeight = nPangoHeight/PANGO_SCALE;
3497 
3498     Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
3499     if( aInfo.m_eWeight != psp::weight::Unknown )
3500         aFont.SetWeight( PspGraphics::ToFontWeight( aInfo.m_eWeight ) );
3501     if( aInfo.m_eWidth != psp::width::Unknown )
3502         aFont.SetWidthType( PspGraphics::ToFontWidth( aInfo.m_eWidth ) );
3503     if( aInfo.m_eItalic != psp::italic::Unknown )
3504         aFont.SetItalic( PspGraphics::ToFontItalic( aInfo.m_eItalic ) );
3505     if( aInfo.m_ePitch != psp::pitch::Unknown )
3506         aFont.SetPitch( PspGraphics::ToFontPitch( aInfo.m_ePitch ) );
3507 
3508     aStyleSet.SetAppFont( aFont );
3509     aStyleSet.SetHelpFont( aFont );
3510     aStyleSet.SetTitleFont( aFont );
3511     aStyleSet.SetFloatTitleFont( aFont );
3512     aStyleSet.SetMenuFont( aFont );
3513     aStyleSet.SetToolFont( aFont );
3514     aStyleSet.SetLabelFont( aFont );
3515     aStyleSet.SetInfoFont( aFont );
3516     aStyleSet.SetRadioCheckFont( aFont );
3517     aStyleSet.SetPushButtonFont( aFont );
3518     aStyleSet.SetFieldFont( aFont );
3519     aStyleSet.SetIconFont( aFont );
3520     aStyleSet.SetGroupFont( aFont );
3521 
3522     // get cursor blink time
3523     GtkSettings *pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gEditBoxWidget );
3524     gboolean blink = false;
3525 
3526     g_object_get( pSettings, "gtk-cursor-blink", &blink, (char *)NULL );
3527     if( blink )
3528     {
3529         gint blink_time = STYLE_CURSOR_NOBLINKTIME;
3530         g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, (char *)NULL );
3531         // set the blink_time if there is a setting and it is reasonable
3532         // else leave the default value
3533         if( blink_time > 100 && blink_time != gint(STYLE_CURSOR_NOBLINKTIME) )
3534             aStyleSet.SetCursorBlinkTime( blink_time/2 );
3535     }
3536     else
3537         aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
3538 
3539     gboolean showmenuicons = true;
3540     pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gImageMenuItem );
3541     g_object_get( pSettings, "gtk-menu-images", &showmenuicons, (char *)NULL );
3542     aStyleSet.SetUseImagesInMenus( showmenuicons );
3543 
3544     // set scrollbar settings
3545     gint slider_width = 14;
3546     gint trough_border = 1;
3547     gint min_slider_length = 21;
3548 
3549     // Grab some button style attributes
3550     gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget,
3551                           "slider-width", &slider_width,
3552                           "trough-border", &trough_border,
3553                           "min-slider-length", &min_slider_length,
3554                           (char *)NULL );
3555     gint magic = trough_border ? 1 : 0;
3556     aStyleSet.SetScrollBarSize( slider_width + 2*trough_border );
3557     aStyleSet.SetMinThumbSize( min_slider_length - magic );
3558 
3559     // preferred icon style
3560     gchar* pIconThemeName = NULL;
3561     g_object_get( gtk_settings_get_default(), "gtk-icon-theme-name", &pIconThemeName, (char *)NULL );
3562     aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii( pIconThemeName ) );
3563     g_free( pIconThemeName );
3564 
3565     //  FIXME: need some way of fetching toolbar icon size.
3566 //	aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_SMALL );
3567 
3568     const cairo_font_options_t* pNewOptions = NULL;
3569     if( GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), m_nScreen ) )
3570     {
3571 //#if !GTK_CHECK_VERSION(2,8,1)
3572 #if !GTK_CHECK_VERSION(2,9,0)
3573 	static cairo_font_options_t* (*gdk_screen_get_font_options)(GdkScreen*) =
3574 		(cairo_font_options_t*(*)(GdkScreen*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_screen_get_font_options" );
3575     if( gdk_screen_get_font_options != NULL )
3576 #endif
3577 		pNewOptions = gdk_screen_get_font_options( pScreen );
3578     }
3579     aStyleSet.SetCairoFontOptions( pNewOptions );
3580 
3581     // finally update the collected settings
3582     rSettings.SetStyleSettings( aStyleSet );
3583 
3584     #if OSL_DEBUG_LEVEL > 1
3585     {
3586         GtkSettings* pGtkSettings = gtk_settings_get_default();
3587         GValue aValue;
3588         memset( &aValue, 0, sizeof(GValue) );
3589         g_value_init( &aValue, G_TYPE_STRING );
3590         g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue );
3591         const gchar* pThemeName = g_value_get_string( &aValue );
3592         std::fprintf( stderr, "Theme name is \"%s\"\n", pThemeName );
3593         g_value_unset( &aValue );
3594     }
3595     #endif
3596     GtkSettings* pGtkSettings = gtk_settings_get_default();
3597     GValue aValue;
3598     memset( &aValue, 0, sizeof(GValue) );
3599     g_value_init( &aValue, G_TYPE_STRING );
3600     g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue );
3601     const gchar* pThemeName = g_value_get_string( &aValue );
3602 
3603     // default behaviour
3604     bNeedPixmapPaint = bGlobalNeedPixmapPaint;
3605     bToolbarGripWorkaround = false;
3606     bNeedButtonStyleAsEditBackgroundWorkaround = false;
3607 
3608     // setup some workarounds for "blueprint" theme
3609     if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 )
3610     {
3611         bNeedButtonStyleAsEditBackgroundWorkaround = true;
3612         if( GetX11SalData()->GetDisplay()->GetServerVendor() == vendor_sun )
3613         {
3614             // #i52570#, #i61532# workaround a weird paint issue;
3615             // on a Sunray Xserver sometimes painting buttons and edits
3616             // won't work when using the blueprint theme
3617             // not reproducible with simpler programs or other themes
3618             if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 )
3619             {
3620                 bNeedPixmapPaint = true;
3621                 bToolbarGripWorkaround = true;
3622             }
3623         }
3624     }
3625     // clean up
3626     g_value_unset( &aValue );
3627 }
3628 
3629 
3630 /************************************************************************
3631  * Create a GdkPixmap filled with the contents of an area of an Xlib window
3632  ************************************************************************/
3633 
3634 GdkPixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect )
3635 {
3636     // Create a new pixmap to hold the composite of the window background and the control
3637     GdkPixmap * pPixmap		= gdk_pixmap_new( GDK_DRAWABLE(GetGdkWindow()), srcRect.GetWidth(), srcRect.GetHeight(), -1 );
3638 	GdkGC *	 pPixmapGC	= gdk_gc_new( pPixmap );
3639 
3640     if( !pPixmap || !pPixmapGC )
3641     {
3642         if ( pPixmap )
3643             g_object_unref( pPixmap );
3644         if ( pPixmapGC )
3645             g_object_unref( pPixmapGC );
3646         std::fprintf( stderr, "salnativewidgets-gtk.cxx: could not get valid pixmap from screen\n" );
3647         return( NULL );
3648     }
3649 
3650     // Copy the background of the screen into a composite pixmap
3651     CopyScreenArea( GetXDisplay(),
3652               GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(),
3653               gdk_x11_drawable_get_xid(pPixmap),
3654               gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ),
3655               gdk_drawable_get_depth( GDK_DRAWABLE( pPixmap ) ),
3656               gdk_x11_gc_get_xgc(pPixmapGC),
3657               srcRect.Left(), srcRect.Top(), srcRect.GetWidth(), srcRect.GetHeight(), 0, 0 );
3658 
3659     g_object_unref( pPixmapGC );
3660     return( pPixmap );
3661 }
3662 
3663 
3664 
3665 
3666 /************************************************************************
3667  * Copy an alpha pixmap to screen using a gc with clipping
3668  ************************************************************************/
3669 
3670 sal_Bool GtkSalGraphics::NWRenderPixmapToScreen( GdkPixmap* pPixmap, Rectangle dstRect )
3671 {
3672     // The GC can't be null, otherwise we'd have no clip region
3673     GC aFontGC = GetFontGC();
3674     if( aFontGC == NULL )
3675     {
3676         std::fprintf(stderr, "salnativewidgets.cxx: no valid GC\n" );
3677         return( sal_False );
3678     }
3679 
3680     if ( !pPixmap )
3681         return( sal_False );
3682 
3683     // Copy the background of the screen into a composite pixmap
3684     CopyScreenArea( GetXDisplay(),
3685               GDK_DRAWABLE_XID(pPixmap),
3686               gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ),
3687               gdk_drawable_get_depth( GDK_DRAWABLE(pPixmap) ),
3688               GetDrawable(), m_nScreen, GetVisual().GetDepth(),
3689               aFontGC,
3690               0, 0, dstRect.GetWidth(), dstRect.GetHeight(), dstRect.Left(), dstRect.Top() );
3691 
3692     return( sal_True );
3693 }
3694 
3695 
3696 /************************************************************************
3697  * State conversion
3698  ************************************************************************/
3699 static void NWConvertVCLStateToGTKState( ControlState nVCLState,
3700 			GtkStateType* nGTKState, GtkShadowType* nGTKShadow )
3701 {
3702 	*nGTKShadow = GTK_SHADOW_OUT;
3703 	*nGTKState = GTK_STATE_INSENSITIVE;
3704 
3705 	if ( nVCLState & CTRL_STATE_ENABLED )
3706 	{
3707 		if ( nVCLState & CTRL_STATE_PRESSED )
3708 		{
3709 			*nGTKState = GTK_STATE_ACTIVE;
3710 			*nGTKShadow = GTK_SHADOW_IN;
3711 		}
3712 		else if ( nVCLState & CTRL_STATE_ROLLOVER )
3713 		{
3714 			*nGTKState = GTK_STATE_PRELIGHT;
3715 			*nGTKShadow = GTK_SHADOW_OUT;
3716 		}
3717 		else
3718 		{
3719 			*nGTKState = GTK_STATE_NORMAL;
3720 			*nGTKShadow = GTK_SHADOW_OUT;
3721 		}
3722 	}
3723 }
3724 
3725 /************************************************************************
3726  * Set widget flags
3727  ************************************************************************/
3728 static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState )
3729 {
3730 	// Set to default state, then build up from there
3731 	GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_DEFAULT );
3732 	GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_FOCUS );
3733 	GTK_WIDGET_UNSET_FLAGS( widget, GTK_SENSITIVE );
3734 	GTK_WIDGET_SET_FLAGS( widget, gWidgetDefaultFlags[(long)widget] );
3735 
3736 	if ( nState & CTRL_STATE_DEFAULT )
3737 		GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_DEFAULT );
3738 	if ( !GTK_IS_TOGGLE_BUTTON(widget) && (nState & CTRL_STATE_FOCUSED) )
3739 		GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_FOCUS );
3740 	if ( nState & CTRL_STATE_ENABLED )
3741 		GTK_WIDGET_SET_FLAGS( widget, GTK_SENSITIVE );
3742 	gtk_widget_set_state( widget, nGtkState );
3743 }
3744 
3745 /************************************************************************
3746  * Widget ensure functions - make sure cached objects are valid
3747  ************************************************************************/
3748 
3749 //-------------------------------------
3750 
3751 static void NWAddWidgetToCacheWindow( GtkWidget* widget, int nScreen )
3752 {
3753     NWFWidgetData& rData = gWidgetData[nScreen];
3754 	if ( !rData.gCacheWindow || !rData.gDumbContainer )
3755 	{
3756 		if ( !rData.gCacheWindow )
3757         {
3758 			rData.gCacheWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3759             GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen );
3760             if( pScreen )
3761                 gtk_window_set_screen( GTK_WINDOW(rData.gCacheWindow), pScreen );
3762         }
3763 		if ( !rData.gDumbContainer )
3764 			rData.gDumbContainer = gtk_fixed_new();
3765 		gtk_container_add( GTK_CONTAINER(rData.gCacheWindow), rData.gDumbContainer );
3766 		gtk_widget_realize( rData.gDumbContainer );
3767 		gtk_widget_realize( rData.gCacheWindow );
3768 	}
3769 
3770 	gtk_container_add( GTK_CONTAINER(rData.gDumbContainer), widget );
3771 	gtk_widget_realize( widget );
3772 	gtk_widget_ensure_style( widget );
3773 
3774 	// Store widget's default flags
3775 	gWidgetDefaultFlags[ (long)widget ] = GTK_WIDGET_FLAGS( widget );
3776 }
3777 
3778 //-------------------------------------
3779 
3780 static void NWEnsureGTKButton( int nScreen )
3781 {
3782 	if ( !gWidgetData[nScreen].gBtnWidget )
3783 	{
3784 		gWidgetData[nScreen].gBtnWidget = gtk_button_new_with_label( "" );
3785 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gBtnWidget, nScreen );
3786 	}
3787 }
3788 
3789 //-------------------------------------
3790 
3791 static void NWEnsureGTKRadio( int nScreen )
3792 {
3793 	if ( !gWidgetData[nScreen].gRadioWidget || !gWidgetData[nScreen].gRadioWidgetSibling )
3794 	{
3795 		gWidgetData[nScreen].gRadioWidget = gtk_radio_button_new( NULL );
3796 		gWidgetData[nScreen].gRadioWidgetSibling = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(gWidgetData[nScreen].gRadioWidget) );
3797 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidget, nScreen );
3798 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidgetSibling, nScreen );
3799 	}
3800 }
3801 
3802 //-------------------------------------
3803 
3804 static void NWEnsureGTKCheck( int nScreen )
3805 {
3806 	if ( !gWidgetData[nScreen].gCheckWidget )
3807 	{
3808 		gWidgetData[nScreen].gCheckWidget = gtk_check_button_new();
3809 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gCheckWidget, nScreen );
3810 	}
3811 }
3812 
3813 //-------------------------------------
3814 
3815 static void NWEnsureGTKScrollbars( int nScreen )
3816 {
3817 	if ( !gWidgetData[nScreen].gScrollHorizWidget )
3818 	{
3819 		gWidgetData[nScreen].gScrollHorizWidget = gtk_hscrollbar_new( NULL );
3820 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollHorizWidget, nScreen );
3821 	}
3822 
3823 	if ( !gWidgetData[nScreen].gScrollVertWidget )
3824 	{
3825 		gWidgetData[nScreen].gScrollVertWidget = gtk_vscrollbar_new( NULL );
3826 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollVertWidget, nScreen );
3827 	}
3828 }
3829 
3830 //-------------------------------------
3831 
3832 static void NWEnsureGTKArrow( int nScreen )
3833 {
3834 	if ( !gWidgetData[nScreen].gArrowWidget || !gWidgetData[nScreen].gDropdownWidget )
3835 	{
3836 		gWidgetData[nScreen].gDropdownWidget = gtk_toggle_button_new();
3837 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gDropdownWidget, nScreen );
3838 		gWidgetData[nScreen].gArrowWidget = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
3839 		gtk_container_add( GTK_CONTAINER(gWidgetData[nScreen].gDropdownWidget), gWidgetData[nScreen].gArrowWidget );
3840 		gtk_widget_set_rc_style( gWidgetData[nScreen].gArrowWidget );
3841 		gtk_widget_realize( gWidgetData[nScreen].gArrowWidget );
3842 	}
3843 }
3844 
3845 //-------------------------------------
3846 
3847 static void NWEnsureGTKEditBox( int nScreen )
3848 {
3849 	if ( !gWidgetData[nScreen].gEditBoxWidget )
3850 	{
3851 		gWidgetData[nScreen].gEditBoxWidget = gtk_entry_new();
3852 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gEditBoxWidget, nScreen );
3853 	}
3854 }
3855 
3856 //-------------------------------------
3857 
3858 static void NWEnsureGTKSpinButton( int nScreen )
3859 {
3860 	if ( !gWidgetData[nScreen].gSpinButtonWidget )
3861 	{
3862 		GtkAdjustment *adj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 1, 1, 1, 0) );
3863 		gWidgetData[nScreen].gSpinButtonWidget = gtk_spin_button_new( adj, 1, 2 );
3864 
3865 		//Setting non-editable means it doesn't blink, so there's no timeouts
3866 		//running around to nobble us
3867 		gtk_editable_set_editable(GTK_EDITABLE(gWidgetData[nScreen].gSpinButtonWidget), false);
3868 
3869 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gSpinButtonWidget, nScreen );
3870 	}
3871 }
3872 
3873 //-------------------------------------
3874 
3875 static void NWEnsureGTKNotebook( int nScreen )
3876 {
3877 	if ( !gWidgetData[nScreen].gNotebookWidget )
3878 	{
3879 		gWidgetData[nScreen].gNotebookWidget = gtk_notebook_new();
3880 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gNotebookWidget, nScreen );
3881 	}
3882 }
3883 
3884 //-------------------------------------
3885 
3886 static void NWEnsureGTKOptionMenu( int nScreen )
3887 {
3888 	if ( !gWidgetData[nScreen].gOptionMenuWidget )
3889 	{
3890 		gWidgetData[nScreen].gOptionMenuWidget = gtk_option_menu_new();
3891 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gOptionMenuWidget, nScreen );
3892 	}
3893 }
3894 
3895 //-------------------------------------
3896 
3897 static void NWEnsureGTKCombo( int nScreen )
3898 {
3899 	if ( !gWidgetData[nScreen].gComboWidget )
3900 	{
3901 		gWidgetData[nScreen].gComboWidget = gtk_combo_new();
3902 
3903 		// #i59129# Setting non-editable means it doesn't blink, so
3904         // there are no timeouts running around to nobble us
3905 		gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry), false);
3906 
3907 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gComboWidget, nScreen );
3908 		// Must realize the ComboBox's children, since GTK
3909 		// does not do this for us in GtkCombo::gtk_widget_realize()
3910 		gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->button );
3911 		gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry );
3912 	}
3913 }
3914 
3915 //-------------------------------------
3916 
3917 static void NWEnsureGTKScrolledWindow( int nScreen )
3918 {
3919 	if ( !gWidgetData[nScreen].gScrolledWindowWidget )
3920 	{
3921 		GtkAdjustment *hadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
3922 		GtkAdjustment *vadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
3923 
3924 		gWidgetData[nScreen].gScrolledWindowWidget = gtk_scrolled_window_new( hadj, vadj );
3925 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrolledWindowWidget, nScreen );
3926 	}
3927 }
3928 
3929 //-------------------------------------
3930 
3931 static void NWEnsureGTKToolbar( int nScreen )
3932 {
3933     if( !gWidgetData[nScreen].gToolbarWidget )
3934     {
3935         gWidgetData[nScreen].gToolbarWidget = gtk_toolbar_new();
3936         NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarWidget, nScreen );
3937         gWidgetData[nScreen].gToolbarButtonWidget = gtk_button_new();
3938         gWidgetData[nScreen].gToolbarToggleWidget = gtk_toggle_button_new();
3939 
3940         GtkReliefStyle aRelief = GTK_RELIEF_NORMAL;
3941         gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarWidget );
3942         gtk_widget_style_get( gWidgetData[nScreen].gToolbarWidget,
3943 			                  "button_relief", &aRelief,
3944                               (char *)NULL);
3945 
3946         gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarButtonWidget), aRelief );
3947         GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_FOCUS );
3948         GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_DEFAULT );
3949         NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarButtonWidget, nScreen );
3950 
3951         gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarToggleWidget), aRelief );
3952         GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_FOCUS );
3953         GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_DEFAULT );
3954         NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarToggleWidget, nScreen );
3955     }
3956     if( ! gWidgetData[nScreen].gHandleBoxWidget )
3957     {
3958         gWidgetData[nScreen].gHandleBoxWidget = gtk_handle_box_new();
3959         NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHandleBoxWidget, nScreen );
3960     }
3961 }
3962 
3963 //-------------------------------------
3964 
3965 static void NWEnsureGTKMenubar( int nScreen )
3966 {
3967     if( !gWidgetData[nScreen].gMenubarWidget )
3968     {
3969         gWidgetData[nScreen].gMenubarWidget = gtk_menu_bar_new();
3970         gWidgetData[nScreen].gMenuItemMenubarWidget = gtk_menu_item_new_with_label( "b" );
3971         gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenubarWidget ), gWidgetData[nScreen].gMenuItemMenubarWidget );
3972         gtk_widget_show( gWidgetData[nScreen].gMenuItemMenubarWidget );
3973         NWAddWidgetToCacheWindow( gWidgetData[nScreen].gMenubarWidget, nScreen );
3974         gtk_widget_show( gWidgetData[nScreen].gMenubarWidget );
3975 
3976         // do what NWAddWidgetToCacheWindow does except adding to def container
3977         gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenubarWidget );
3978         gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenubarWidget );
3979 
3980         gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenubarWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenubarWidget );
3981     }
3982 }
3983 
3984 static void NWEnsureGTKMenu( int nScreen )
3985 {
3986     if( !gWidgetData[nScreen].gMenuWidget )
3987     {
3988         gWidgetData[nScreen].gMenuWidget              = gtk_menu_new();
3989         gWidgetData[nScreen].gMenuItemMenuWidget      = gtk_menu_item_new_with_label( "b" );
3990         gWidgetData[nScreen].gMenuItemCheckMenuWidget = gtk_check_menu_item_new_with_label( "b" );
3991         gWidgetData[nScreen].gMenuItemRadioMenuWidget = gtk_radio_menu_item_new_with_label( NULL, "b" );
3992         gWidgetData[nScreen].gImageMenuItem           = gtk_image_menu_item_new();
3993 
3994         gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemMenuWidget );
3995         gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemCheckMenuWidget );
3996         gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemRadioMenuWidget );
3997         gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gImageMenuItem );
3998 
3999         // do what NWAddWidgetToCacheWindow does except adding to def container
4000         gtk_widget_realize( gWidgetData[nScreen].gMenuWidget );
4001         gtk_widget_ensure_style( gWidgetData[nScreen].gMenuWidget );
4002 
4003         gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenuWidget );
4004         gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenuWidget );
4005 
4006         gtk_widget_realize( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
4007         gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
4008 
4009         gtk_widget_realize( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
4010         gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
4011 
4012         gtk_widget_realize( gWidgetData[nScreen].gImageMenuItem );
4013         gtk_widget_ensure_style( gWidgetData[nScreen].gImageMenuItem );
4014 
4015         gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuWidget );
4016         gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenuWidget );
4017         gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemCheckMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
4018         gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemRadioMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
4019         gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gImageMenuItem ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gImageMenuItem );
4020     }
4021 }
4022 
4023 static void NWEnsureGTKTooltip( int nScreen )
4024 {
4025     if( !gWidgetData[nScreen].gTooltipPopup )
4026     {
4027         gWidgetData[nScreen].gTooltipPopup = gtk_window_new (GTK_WINDOW_POPUP);
4028         GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen );
4029         if( pScreen )
4030             gtk_window_set_screen( GTK_WINDOW(gWidgetData[nScreen].gTooltipPopup), pScreen );
4031         gtk_widget_set_name( gWidgetData[nScreen].gTooltipPopup, "gtk-tooltips");
4032         gtk_widget_realize( gWidgetData[nScreen].gTooltipPopup );
4033         gtk_widget_ensure_style( gWidgetData[nScreen].gTooltipPopup );
4034     }
4035 }
4036 
4037 static void NWEnsureGTKProgressBar( int nScreen )
4038 {
4039     if( !gWidgetData[nScreen].gProgressBar )
4040     {
4041         gWidgetData[nScreen].gProgressBar = gtk_progress_bar_new ();
4042 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gProgressBar, nScreen );
4043     }
4044 }
4045 
4046 static void NWEnsureGTKTreeView( int nScreen )
4047 {
4048     if( !gWidgetData[nScreen].gTreeView )
4049     {
4050         gWidgetData[nScreen].gTreeView = gtk_tree_view_new ();
4051 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gTreeView, nScreen );
4052     }
4053 }
4054 
4055 static void NWEnsureGTKSlider( int nScreen )
4056 {
4057     if( !gWidgetData[nScreen].gHScale )
4058     {
4059         gWidgetData[nScreen].gHScale = gtk_hscale_new_with_range(0, 10, 1);
4060 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHScale, nScreen );
4061     }
4062     if( !gWidgetData[nScreen].gVScale )
4063     {
4064         gWidgetData[nScreen].gVScale = gtk_vscale_new_with_range(0, 10, 1);
4065 		NWAddWidgetToCacheWindow( gWidgetData[nScreen].gVScale, nScreen );
4066     }
4067 }
4068