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