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