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