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