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