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