update dev300-m58
[ooovba.git] / vcl / unx / gtk / gdi / salnativewidgets-gtk.cxx
blobbad1e03c8df98c485079cc0b88d60c40603fa07a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salnativewidgets-gtk.cxx,v $
10 * $Revision: 1.47.32.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include "plugins/gtk/gtkframe.hxx"
35 #include "plugins/gtk/gtkdata.hxx"
36 #include "plugins/gtk/gtkinst.hxx"
37 #include "plugins/gtk/gtkgdi.hxx"
39 #include "pspgraphics.h"
41 #include <cstdio>
42 #include <cmath>
43 #include <vector>
44 #include <algorithm>
45 #include <hash_map>
47 #include "saldata.hxx"
48 #include "saldisp.hxx"
49 #include "vcl/svapp.hxx"
51 // initialize statics
52 BOOL GtkSalGraphics::bThemeChanged = TRUE;
53 BOOL GtkSalGraphics::bNeedPixmapPaint = FALSE;
54 BOOL GtkSalGraphics::bGlobalNeedPixmapPaint = FALSE;
55 BOOL GtkSalGraphics::bToolbarGripWorkaround = FALSE;
56 BOOL GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround = FALSE;
58 GtkSalGraphics::~GtkSalGraphics()
63 using namespace rtl;
65 /*************************************
66 * Cached native widget objects
67 *************************************/
68 class NWPixmapCacheList;
69 class NWPixmapCache;
70 struct NWFWidgetData
72 GtkWidget * gCacheWindow;
73 GtkWidget * gDumbContainer;
75 GtkWidget * gBtnWidget;
76 GtkWidget * gRadioWidget;
77 GtkWidget * gRadioWidgetSibling;
78 GtkWidget * gCheckWidget;
79 GtkWidget * gScrollHorizWidget;
80 GtkWidget * gScrollVertWidget;
81 GtkWidget * gArrowWidget;
82 GtkWidget * gDropdownWidget;
83 GtkWidget * gEditBoxWidget;
84 GtkWidget * gSpinButtonWidget;
85 GtkWidget * gNotebookWidget;
86 GtkWidget * gOptionMenuWidget;
87 GtkWidget * gComboWidget;
88 GtkWidget * gScrolledWindowWidget;
89 GtkWidget * gToolbarWidget;
90 GtkWidget * gToolbarButtonWidget;
91 GtkWidget * gToolbarToggleWidget;
92 GtkWidget * gHandleBoxWidget;
93 GtkWidget * gMenubarWidget;
94 GtkWidget * gMenuItemMenubarWidget;
95 GtkWidget * gMenuWidget;
96 GtkWidget * gMenuItemMenuWidget;
97 GtkWidget * gMenuItemCheckMenuWidget;
98 GtkWidget * gMenuItemRadioMenuWidget;
99 GtkWidget * gImageMenuItem;
100 GtkWidget * gTooltipPopup;
101 GtkWidget * gProgressBar;
102 GtkWidget * gTreeView;
104 NWPixmapCacheList* gNWPixmapCacheList;
105 NWPixmapCache* gCacheTabItems;
106 NWPixmapCache* gCacheTabPages;
108 NWFWidgetData() :
109 gCacheWindow( NULL ),
110 gDumbContainer( NULL ),
111 gBtnWidget( NULL ),
112 gRadioWidget( NULL ),
113 gRadioWidgetSibling( NULL ),
114 gCheckWidget( NULL ),
115 gScrollHorizWidget( NULL ),
116 gScrollVertWidget( NULL ),
117 gArrowWidget( NULL ),
118 gDropdownWidget( NULL ),
119 gEditBoxWidget( NULL ),
120 gSpinButtonWidget( NULL ),
121 gNotebookWidget( NULL ),
122 gOptionMenuWidget( NULL ),
123 gComboWidget( NULL ),
124 gScrolledWindowWidget( NULL ),
125 gToolbarWidget( NULL ),
126 gToolbarButtonWidget( NULL ),
127 gToolbarToggleWidget( NULL ),
128 gHandleBoxWidget( NULL ),
129 gMenubarWidget( NULL ),
130 gMenuItemMenubarWidget( NULL ),
131 gMenuWidget( NULL ),
132 gMenuItemMenuWidget( NULL ),
133 gMenuItemCheckMenuWidget( NULL ),
134 gMenuItemRadioMenuWidget( NULL ),
135 gImageMenuItem( NULL ),
136 gTooltipPopup( NULL ),
137 gProgressBar( NULL ),
138 gTreeView( NULL ),
139 gNWPixmapCacheList( NULL ),
140 gCacheTabItems( NULL ),
141 gCacheTabPages( NULL )
145 // Keep a hash table of Widgets->default flags so that we can
146 // easily and quickly reset each to a default state before using
147 // them
148 static std::hash_map<long, guint> gWidgetDefaultFlags;
149 static std::vector<NWFWidgetData> gWidgetData;
151 static const GtkBorder aDefDefBorder = { 1, 1, 1, 1 };
153 // Some GTK defaults
154 #define MIN_ARROW_SIZE 11
155 #define BTN_CHILD_SPACING 1
156 #define MIN_SPIN_ARROW_WIDTH 6
159 static void NWEnsureGTKRadio ( int nScreen );
160 static void NWEnsureGTKButton ( int nScreen );
161 static void NWEnsureGTKCheck ( int nScreen );
162 static void NWEnsureGTKScrollbars ( int nScreen );
163 static void NWEnsureGTKArrow ( int nScreen );
164 static void NWEnsureGTKEditBox ( int nScreen );
165 static void NWEnsureGTKSpinButton ( int nScreen );
166 static void NWEnsureGTKNotebook ( int nScreen );
167 static void NWEnsureGTKOptionMenu ( int nScreen );
168 static void NWEnsureGTKCombo ( int nScreen );
169 static void NWEnsureGTKScrolledWindow ( int nScreen );
170 static void NWEnsureGTKToolbar ( int nScreen );
171 static void NWEnsureGTKMenubar ( int nScreen );
172 static void NWEnsureGTKMenu ( int nScreen );
173 static void NWEnsureGTKTooltip ( int nScreen );
174 static void NWEnsureGTKProgressBar ( int nScreen );
175 static void NWEnsureGTKTreeView ( int nScreen );
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 );
181 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow );
184 * Individual helper functions
188 //---
189 static Rectangle NWGetButtonArea( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
190 const ImplControlValue& aValue, SalControlHandle& rControlHandle, const OUString& rCaption );
192 //---
193 static Rectangle NWGetEditBoxPixmapRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
194 const ImplControlValue& aValue, SalControlHandle& rControlHandle, const OUString& rCaption );
196 static void NWPaintOneEditBox( int nScreen, GdkDrawable * gdkDrawable, GdkRectangle *gdkRect,
197 ControlType nType, ControlPart nPart, Rectangle aEditBoxRect,
198 ControlState nState, const ImplControlValue& aValue,
199 SalControlHandle& rControlHandle, const OUString& rCaption );
201 //---
202 static Rectangle NWGetSpinButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
203 const ImplControlValue& aValue, SalControlHandle& rControlHandle, const OUString& rCaption );
205 static void NWPaintOneSpinButton( int nScreen, GdkPixmap * pixmap, ControlType nType, ControlPart nPart, Rectangle aAreaRect,
206 ControlState nState, const ImplControlValue& aValue, SalControlHandle& rControlHandle,
207 const OUString& rCaption );
208 //---
209 static Rectangle NWGetComboBoxButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
210 const ImplControlValue& aValue, SalControlHandle& rControlHandle, const OUString& rCaption );
212 //---
213 static Rectangle NWGetListBoxButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
214 const ImplControlValue& aValue, SalControlHandle& rControlHandle, const OUString& rCaption );
216 static Rectangle NWGetListBoxIndicatorRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState,
217 const ImplControlValue& aValue, SalControlHandle& rControlHandle, const OUString& rCaption );
219 static Rectangle NWGetToolbarRect( int nScreen,
220 ControlType nType,
221 ControlPart nPart,
222 Rectangle aAreaRect,
223 ControlState nState,
224 const ImplControlValue& aValue,
225 SalControlHandle& rControlHandle,
226 const OUString& rCaption );
227 //---
229 static Rectangle NWGetScrollButtonRect( int nScreen, ControlPart nPart, Rectangle aAreaRect );
230 //---
232 /*********************************************************
233 * PixmapCache
234 *********************************************************/
236 // as some native widget drawing operations are pretty slow
237 // with certain themes (eg tabpages)
238 // this cache can be used to cache the corresponding pixmap
239 // see NWPaintGTKTabItem
241 class NWPixmapCacheData
243 public:
244 ControlType m_nType;
245 ControlState m_nState;
246 Rectangle m_pixmapRect;
247 GdkPixmap* m_pixmap;
249 NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0) {}
250 ~NWPixmapCacheData()
251 { SetPixmap( NULL ); };
252 void SetPixmap( GdkPixmap* pPixmap );
255 class NWPixmapCache
257 int m_size;
258 int m_idx;
259 int m_screen;
260 NWPixmapCacheData* pData;
261 public:
262 NWPixmapCache( int nScreen );
263 ~NWPixmapCache();
265 void SetSize( int n)
266 { delete [] pData; m_idx = 0; m_size = n; pData = new NWPixmapCacheData[m_size]; }
267 int GetSize() { return m_size; }
269 BOOL Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap** pPixmap );
270 void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap* pPixmap );
272 void ThemeChanged();
275 class NWPixmapCacheList
277 public:
278 ::std::vector< NWPixmapCache* > mCaches;
280 void AddCache( NWPixmapCache *pCache );
281 void RemoveCache( NWPixmapCache *pCache );
282 void ThemeChanged();
285 // --- implementation ---
287 void NWPixmapCacheData::SetPixmap( GdkPixmap* pPixmap )
289 if( m_pixmap )
290 g_object_unref( m_pixmap );
292 m_pixmap = pPixmap;
294 if( m_pixmap )
295 g_object_ref( m_pixmap );
299 NWPixmapCache::NWPixmapCache( int nScreen )
301 m_idx = 0;
302 m_size = 0;
303 m_screen = nScreen;
304 pData = NULL;
305 if( gWidgetData[m_screen].gNWPixmapCacheList )
306 gWidgetData[m_screen].gNWPixmapCacheList->AddCache(this);
308 NWPixmapCache::~NWPixmapCache()
310 if( gWidgetData[m_screen].gNWPixmapCacheList )
311 gWidgetData[m_screen].gNWPixmapCacheList->RemoveCache(this);
312 delete[] pData;
314 void NWPixmapCache::ThemeChanged()
316 // throw away cached pixmaps
317 int i;
318 for(i=0; i<m_size; i++)
319 pData[i].SetPixmap( NULL );
322 BOOL NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap** pPixmap )
324 aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag
325 int i;
326 for(i=0; i<m_size; i++)
328 if( pData[i].m_nType == aType &&
329 pData[i].m_nState == aState &&
330 pData[i].m_pixmapRect.GetWidth() == r_pixmapRect.GetWidth() &&
331 pData[i].m_pixmapRect.GetHeight() == r_pixmapRect.GetHeight() &&
332 pData[i].m_pixmap != NULL )
334 *pPixmap = pData[i].m_pixmap;
335 return TRUE;
338 return FALSE;
341 void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap* pPixmap )
343 if( !(aState & CTRL_CACHING_ALLOWED) )
344 return;
346 aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag
347 m_idx = (m_idx+1) % m_size; // just wrap
348 pData[m_idx].m_nType = aType;
349 pData[m_idx].m_nState = aState;
350 pData[m_idx].m_pixmapRect = r_pixmapRect;
351 pData[m_idx].SetPixmap( pPixmap );
355 void NWPixmapCacheList::AddCache( NWPixmapCache* pCache )
357 mCaches.push_back( pCache );
359 void NWPixmapCacheList::RemoveCache( NWPixmapCache* pCache )
361 ::std::vector< NWPixmapCache* >::iterator p;
362 p = ::std::find( mCaches.begin(), mCaches.end(), pCache );
363 if( p != mCaches.end() )
364 mCaches.erase( p );
366 void NWPixmapCacheList::ThemeChanged( )
368 ::std::vector< NWPixmapCache* >::iterator p = mCaches.begin();
369 while( p != mCaches.end() )
371 (*p)->ThemeChanged();
372 p++;
377 /*********************************************************
378 * Make border manipulation easier
379 *********************************************************/
380 inline void NW_gtk_border_set_from_border( GtkBorder& aDst, const GtkBorder * pSrc )
382 aDst.left = pSrc->left;
383 aDst.top = pSrc->top;
384 aDst.right = pSrc->right;
385 aDst.bottom = pSrc->bottom;
389 /*********************************************************
390 * Initialize GTK and local stuff
391 *********************************************************/
392 void GtkData::initNWF( void )
394 ImplSVData* pSVData = ImplGetSVData();
396 // draw no border for popup menus (NWF draws its own)
397 pSVData->maNWFData.mbFlatMenu = true;
399 // draw separate buttons for toolbox dropdown items
400 pSVData->maNWFData.mbToolboxDropDownSeparate = true;
402 // small extra border around menu items
403 pSVData->maNWFData.mnMenuFormatExtraBorder = 1;
405 // draw toolbars in separate lines
406 pSVData->maNWFData.mbDockingAreaSeparateTB = true;
408 // open first menu on F10
409 pSVData->maNWFData.mbOpenMenuOnF10 = true;
411 int nScreens = GetX11SalData()->GetDisplay()->GetScreenCount();
412 gWidgetData = std::vector<NWFWidgetData>( nScreens );
413 for( int i = 0; i < nScreens; i++ )
414 gWidgetData[i].gNWPixmapCacheList = new NWPixmapCacheList;
417 if( SalGetDesktopEnvironment().equalsAscii( "KDE" ) )
419 // #i97196# ensure a widget exists and the style engine was loaded
420 NWEnsureGTKButton( 0 );
421 if( g_type_from_name( "QtEngineStyle" ) )
423 // KDE 3.3 invented a bug in the qt<->gtk theme engine
424 // that makes direct rendering impossible: they totally
425 // ignore the clip rectangle passed to the paint methods
426 GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true;
429 static const char* pEnv = getenv( "SAL_GTK_USE_PIXMAPPAINT" );
430 if( pEnv && *pEnv )
431 GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true;
433 #if OSL_DEBUG_LEVEL > 1
434 std::fprintf( stderr, "GtkPlugin: using %s NWF\n",
435 GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" );
436 #endif
440 /*********************************************************
441 * Release GTK and local stuff
442 *********************************************************/
443 void GtkData::deInitNWF( void )
446 for( unsigned int i = 0; i < gWidgetData.size(); i++ )
448 // free up global widgets
449 // gtk_widget_destroy will in turn destroy the child hierarchy
450 // so only destroy disjunct hierachies
451 if( gWidgetData[i].gCacheWindow )
452 gtk_widget_destroy( gWidgetData[i].gCacheWindow );
453 if( gWidgetData[i].gMenuWidget )
454 gtk_widget_destroy( gWidgetData[i].gMenuWidget );
455 if( gWidgetData[i].gTooltipPopup )
456 gtk_widget_destroy( gWidgetData[i].gTooltipPopup );
457 delete gWidgetData[i].gCacheTabPages;
458 gWidgetData[i].gCacheTabPages = NULL;
459 delete gWidgetData[i].gCacheTabItems;
460 gWidgetData[i].gCacheTabItems = NULL;
461 delete gWidgetData[i].gNWPixmapCacheList;
462 gWidgetData[i].gNWPixmapCacheList = NULL;
467 /**********************************************************
468 * track clip region
469 **********************************************************/
470 void GtkSalGraphics::ResetClipRegion()
472 m_aClipRegion.SetNull();
473 X11SalGraphics::ResetClipRegion();
476 void GtkSalGraphics::BeginSetClipRegion( ULONG nCount )
478 m_aClipRegion.SetNull();
479 X11SalGraphics::BeginSetClipRegion( nCount );
482 BOOL GtkSalGraphics::unionClipRegion( long nX, long nY, long nWidth, long nHeight )
484 Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
485 m_aClipRegion.Union( aRect );
486 return X11SalGraphics::unionClipRegion( nX, nY, nWidth, nHeight );
489 bool GtkSalGraphics::unionClipRegion( const ::basegfx::B2DPolyPolygon& )
491 // TODO: implement and advertise OutDevSupport_B2DClip support
492 return false;
495 void GtkSalGraphics::EndSetClipRegion()
497 if( m_aClipRegion.IsEmpty() )
498 m_aClipRegion.SetNull();
499 X11SalGraphics::EndSetClipRegion();
502 void GtkSalGraphics::copyBits( const SalTwoRect* pPosAry,
503 SalGraphics* pSrcGraphics )
505 GtkSalFrame* pFrame = GetGtkFrame();
506 XLIB_Window aWin = None;
507 if( pFrame && m_pWindow )
509 /* #i64117# some themes set the background pixmap VERY frequently */
510 GdkWindow* pWin = GTK_WIDGET(m_pWindow)->window;
511 if( pWin )
513 aWin = GDK_WINDOW_XWINDOW(pWin);
514 if( aWin != None )
515 XSetWindowBackgroundPixmap( pFrame->getDisplay()->GetDisplay(),
516 aWin,
517 None );
520 X11SalGraphics::copyBits( pPosAry, pSrcGraphics );
521 if( pFrame && pFrame->getBackgroundPixmap() != None )
522 XSetWindowBackgroundPixmap( pFrame->getDisplay()->GetDisplay(),
523 aWin,
524 pFrame->getBackgroundPixmap() );
528 * IsNativeControlSupported()
530 * Returns TRUE if the platform supports native
531 * drawing of the control defined by nPart
533 BOOL GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
535 if (
536 ((nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL)) ||
537 ((nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL)) ||
538 ((nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL)) ||
539 ((nType==CTRL_SCROLLBAR) &&
540 ( (nPart==PART_DRAW_BACKGROUND_HORZ)
541 || (nPart==PART_DRAW_BACKGROUND_VERT)
542 || (nPart==PART_ENTIRE_CONTROL)
543 || (nPart==HAS_THREE_BUTTONS) ) ) ||
544 ((nType==CTRL_EDITBOX) &&
545 ( (nPart==PART_ENTIRE_CONTROL)
546 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) ||
547 ((nType==CTRL_MULTILINE_EDITBOX) &&
548 ( (nPart==PART_ENTIRE_CONTROL)
549 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) ||
550 ((nType==CTRL_SPINBOX) &&
551 ( (nPart==PART_ENTIRE_CONTROL)
552 || (nPart==PART_ALL_BUTTONS)
553 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) ||
554 ((nType==CTRL_SPINBUTTONS) &&
555 ( (nPart==PART_ENTIRE_CONTROL)
556 || (nPart==PART_ALL_BUTTONS) ) ) ||
557 ((nType==CTRL_COMBOBOX) &&
558 ( (nPart==PART_ENTIRE_CONTROL)
559 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) ||
560 (((nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) ||
561 (nType==CTRL_TAB_BODY) || (nType==CTRL_FIXEDBORDER)) &&
562 ( (nPart==PART_ENTIRE_CONTROL)
563 || (nPart==PART_TABS_DRAW_RTL) ) ) ||
564 ((nType==CTRL_LISTBOX) &&
565 ( (nPart==PART_ENTIRE_CONTROL)
566 || (nPart==PART_WINDOW)
567 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) ||
568 ((nType == CTRL_TOOLBAR) &&
569 ( (nPart==PART_ENTIRE_CONTROL)
570 || (nPart==PART_DRAW_BACKGROUND_HORZ)
571 || (nPart==PART_DRAW_BACKGROUND_VERT)
572 || (nPart==PART_THUMB_HORZ)
573 || (nPart==PART_THUMB_VERT)
574 || (nPart==PART_BUTTON)
576 ) ||
577 ((nType == CTRL_MENUBAR) &&
578 ( (nPart==PART_ENTIRE_CONTROL) ) ) ||
579 ((nType == CTRL_TOOLTIP) &&
580 ( (nPart==PART_ENTIRE_CONTROL) ) ) ||
581 ((nType == CTRL_MENU_POPUP) &&
582 ( (nPart==PART_ENTIRE_CONTROL)
583 || (nPart==PART_MENU_ITEM)
584 || (nPart==PART_MENU_ITEM_CHECK_MARK)
585 || (nPart==PART_MENU_ITEM_RADIO_MARK)
587 ) ||
588 ((nType == CTRL_PROGRESS) &&
589 ( (nPart == PART_ENTIRE_CONTROL) )
590 ) ||
591 ((nType == CTRL_LISTNODE || nType == CTRL_LISTNET) &&
592 ( (nPart == PART_ENTIRE_CONTROL) )
595 return( TRUE );
597 return( FALSE );
602 * HitTestNativeControl()
604 * bIsInside is set to TRUE if aPos is contained within the
605 * given part of the control, whose bounding region is
606 * given by rControlRegion (in VCL frame coordinates).
608 * returns whether bIsInside was really set.
610 BOOL GtkSalGraphics::hitTestNativeControl( ControlType nType,
611 ControlPart nPart,
612 const Region& rControlRegion,
613 const Point& aPos,
614 SalControlHandle&,
615 BOOL& rIsInside )
617 if ( ( nType == CTRL_SCROLLBAR ) &&
618 ( ( nPart == PART_BUTTON_UP ) ||
619 ( nPart == PART_BUTTON_DOWN ) ||
620 ( nPart == PART_BUTTON_LEFT ) ||
621 ( nPart == PART_BUTTON_RIGHT ) ) )
623 NWEnsureGTKScrollbars( m_nScreen );
625 // Grab some button style attributes
626 gboolean has_forward;
627 gboolean has_forward2;
628 gboolean has_backward;
629 gboolean has_backward2;
631 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward,
632 "has-secondary-forward-stepper", &has_forward2,
633 "has-backward-stepper", &has_backward,
634 "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
635 Rectangle aForward;
636 Rectangle aBackward;
638 rIsInside = FALSE;
640 ControlPart nCounterPart = 0;
641 if ( nPart == PART_BUTTON_UP )
642 nCounterPart = PART_BUTTON_DOWN;
643 else if ( nPart == PART_BUTTON_DOWN )
644 nCounterPart = PART_BUTTON_UP;
645 else if ( nPart == PART_BUTTON_LEFT )
646 nCounterPart = PART_BUTTON_RIGHT;
647 else if ( nPart == PART_BUTTON_RIGHT )
648 nCounterPart = PART_BUTTON_LEFT;
650 aBackward = NWGetScrollButtonRect( m_nScreen, nPart, rControlRegion.GetBoundRect() );
651 aForward = NWGetScrollButtonRect( m_nScreen, nCounterPart, rControlRegion.GetBoundRect() );
653 if ( has_backward && has_forward2 )
655 Size aSize( aBackward.GetSize() );
656 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
657 aSize.setHeight( aBackward.GetHeight() / 2 );
658 else
659 aSize.setWidth( aBackward.GetWidth() / 2 );
660 aBackward.SetSize( aSize );
662 if ( nPart == PART_BUTTON_DOWN )
663 aBackward.Move( 0, aBackward.GetHeight() / 2 );
664 else if ( nPart == PART_BUTTON_RIGHT )
665 aBackward.Move( aBackward.GetWidth() / 2, 0 );
668 if ( has_backward2 && has_forward )
670 Size aSize( aForward.GetSize() );
671 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
672 aSize.setHeight( aForward.GetHeight() / 2 );
673 else
674 aSize.setWidth( aForward.GetWidth() / 2 );
675 aForward.SetSize( aSize );
677 if ( nPart == PART_BUTTON_DOWN )
678 aForward.Move( 0, aForward.GetHeight() / 2 );
679 else if ( nPart == PART_BUTTON_RIGHT )
680 aForward.Move( aForward.GetWidth() / 2, 0 );
683 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_LEFT ) )
685 if ( has_backward )
686 rIsInside |= aBackward.IsInside( aPos );
687 if ( has_backward2 )
688 rIsInside |= aForward.IsInside( aPos );
690 else
692 if ( has_forward )
693 rIsInside |= aBackward.IsInside( aPos );
694 if ( has_forward2 )
695 rIsInside |= aForward.IsInside( aPos );
697 return ( TRUE );
700 if( IsNativeControlSupported(nType, nPart) )
702 rIsInside = rControlRegion.IsInside( aPos );
703 return( TRUE );
705 else
707 return( FALSE );
713 * DrawNativeControl()
715 * Draws the requested control described by nPart/nState.
717 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
718 * aValue: An optional value (tristate/numerical/string)
719 * rControlHandle: Carries platform dependent data and is maintained by the SalFrame implementation.
720 * rCaption: A caption or title string (like button text etc)
722 BOOL GtkSalGraphics::drawNativeControl( ControlType nType,
723 ControlPart nPart,
724 const Region& rControlRegion,
725 ControlState nState,
726 const ImplControlValue& aValue,
727 SalControlHandle& rControlHandle,
728 const OUString& rCaption )
730 if( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) &&
731 aValue.getTristateVal() == BUTTONVALUE_MIXED )
733 return drawNativeMixedStateCheck( nType, nPart, rControlRegion, nState, aValue, rControlHandle, rCaption );
736 BOOL returnVal = FALSE;
737 // get a GC with current clipping region set
738 SelectFont();
741 // theme changed ?
742 if( GtkSalGraphics::bThemeChanged )
744 // invalidate caches
745 for( unsigned int i = 0; i < gWidgetData.size(); i++ )
746 if( gWidgetData[i].gNWPixmapCacheList )
747 gWidgetData[i].gNWPixmapCacheList->ThemeChanged();
748 GtkSalGraphics::bThemeChanged = FALSE;
751 Rectangle aCtrlRect = rControlRegion.GetBoundRect();
752 Region aClipRegion( m_aClipRegion );
753 if( aClipRegion.IsNull() )
754 aClipRegion = aCtrlRect;
756 clipList aClip;
757 GdkDrawable* gdkDrawable = GDK_DRAWABLE( GetGdkWindow() );
758 GdkPixmap* pixmap = NULL;
759 Rectangle aPixmapRect;
760 if( ( bNeedPixmapPaint )
761 && nType != CTRL_SCROLLBAR
762 && nType != CTRL_SPINBOX
763 && nType != CTRL_TAB_ITEM
764 && nType != CTRL_TAB_PANE
765 && nType != CTRL_PROGRESS
766 && ! (bToolbarGripWorkaround && nType == CTRL_TOOLBAR && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
769 // make pixmap a little larger since some themes draw decoration
770 // outside the rectangle, see e.g. checkbox
771 aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
772 Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
773 pixmap = NWGetPixmapFromScreen( aPixmapRect );
774 if( ! pixmap )
775 return FALSE;
776 gdkDrawable = GDK_DRAWABLE( pixmap );
777 aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() );
778 aClip.push_back( aCtrlRect );
780 else
782 RegionHandle aHdl = aClipRegion.BeginEnumRects();
783 Rectangle aPaintRect;
784 while( aClipRegion.GetNextEnumRect( aHdl, aPaintRect ) )
786 aPaintRect = aCtrlRect.GetIntersection( aPaintRect );
787 if( aPaintRect.IsEmpty() )
788 continue;
789 aClip.push_back( aPaintRect );
791 aClipRegion.EndEnumRects( aHdl );
794 if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
796 returnVal = NWPaintGTKButton( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
798 else if ( (nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL) )
800 returnVal = NWPaintGTKRadio( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
802 else if ( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) )
804 returnVal = NWPaintGTKCheck( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
806 else if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_DRAW_BACKGROUND_HORZ) || (nPart==PART_DRAW_BACKGROUND_VERT)) )
808 returnVal = NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
810 else if ( ((nType==CTRL_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) )
811 || ((nType==CTRL_SPINBOX) && (nPart==HAS_BACKGROUND_TEXTURE))
812 || ((nType==CTRL_COMBOBOX) && (nPart==HAS_BACKGROUND_TEXTURE))
813 || ((nType==CTRL_LISTBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) )
815 returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
817 else if ( ((nType==CTRL_MULTILINE_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) )
819 returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
821 else if ( ((nType==CTRL_SPINBOX) || (nType==CTRL_SPINBUTTONS))
822 && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_ALL_BUTTONS)) )
824 returnVal = NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
826 else if ( (nType == CTRL_COMBOBOX) &&
827 ( (nPart==PART_ENTIRE_CONTROL)
828 ||(nPart==PART_BUTTON_DOWN)
831 returnVal = NWPaintGTKComboBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
833 else if ( (nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || (nType==CTRL_TAB_BODY) || (nType==CTRL_FIXEDBORDER) )
835 if ( nType == CTRL_TAB_BODY )
836 returnVal = TRUE;
837 else
838 returnVal = NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption);
840 else if ( (nType==CTRL_LISTBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_WINDOW)) )
842 returnVal = NWPaintGTKListBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
844 else if ( (nType== CTRL_TOOLBAR) )
846 returnVal = NWPaintGTKToolbar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
848 else if ( (nType== CTRL_MENUBAR) )
850 returnVal = NWPaintGTKMenubar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
852 else if( (nType == CTRL_MENU_POPUP)
853 && ( (nPart == PART_ENTIRE_CONTROL)
854 || (nPart == PART_MENU_ITEM)
855 || (nPart == PART_MENU_ITEM_CHECK_MARK)
856 || (nPart == PART_MENU_ITEM_RADIO_MARK)
860 returnVal = NWPaintGTKPopupMenu( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
862 else if( (nType == CTRL_TOOLTIP) && (nPart == PART_ENTIRE_CONTROL) )
864 returnVal = NWPaintGTKTooltip( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
866 else if( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) )
868 returnVal = NWPaintGTKProgress( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
870 else if( (nType == CTRL_LISTNODE) && (nPart == PART_ENTIRE_CONTROL) )
872 returnVal = NWPaintGTKListNode( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rControlHandle, rCaption );
874 else if( (nType == CTRL_LISTNET) && (nPart == PART_ENTIRE_CONTROL) )
876 // don't actually draw anything; gtk treeviews do not draw lines
877 returnVal = true;
880 if( pixmap )
882 returnVal = NWRenderPixmapToScreen( pixmap, aPixmapRect ) && returnVal;
883 g_object_unref( pixmap );
886 return( returnVal );
889 BOOL GtkSalGraphics::drawNativeMixedStateCheck( ControlType nType,
890 ControlPart nPart,
891 const Region& rControlRegion,
892 ControlState nState,
893 const ImplControlValue& aValue,
894 SalControlHandle& rControlHandle,
895 const OUString& rCaption )
897 // need to emulate something for mixed state
899 // do this via pixmap since some themes don't care for regions
900 bool bOldNeedPixmapPaint = bNeedPixmapPaint;
901 bNeedPixmapPaint = true;
903 Rectangle aCtrlRect = rControlRegion.GetBoundRect();
904 BOOL returnVal = FALSE;
905 SelectFont();
907 // draw upper half in off state
908 const_cast<ImplControlValue&>(aValue).setTristateVal( BUTTONVALUE_OFF );
909 XLIB_Region aRegion = XCreateRegion();
910 XRectangle aXRect = { aCtrlRect.Left(), aCtrlRect.Top(), aCtrlRect.GetWidth(), aCtrlRect.GetHeight() };
911 const unsigned short nH = aXRect.height/2;
912 aXRect.height -= nH;
913 XUnionRectWithRegion( &aXRect, aRegion, aRegion );
914 SetClipRegion( pFontGC_, aRegion );
915 XDestroyRegion( aRegion );
917 returnVal = drawNativeControl( nType, nPart, rControlRegion, nState, aValue, rControlHandle, rCaption );
919 if( returnVal )
921 // draw lower half in on state
922 const_cast<ImplControlValue&>(aValue).setTristateVal( BUTTONVALUE_ON );
923 aXRect.y += nH;
924 aRegion = XCreateRegion();
925 XUnionRectWithRegion( &aXRect, aRegion, aRegion );
926 SetClipRegion( pFontGC_, aRegion );
927 XDestroyRegion( aRegion );
928 returnVal = drawNativeControl( nType, nPart, rControlRegion, nState, aValue, rControlHandle, rCaption );
931 // clean up
932 bNeedPixmapPaint = bOldNeedPixmapPaint;
933 const_cast<ImplControlValue&>(aValue).setTristateVal( BUTTONVALUE_MIXED );
934 SetClipRegion( pFontGC_ );
935 return returnVal;
940 * DrawNativeControlText()
942 * OPTIONAL. Draws the requested text for the control described by nPart/nState.
943 * Used if text not drawn by DrawNativeControl().
945 * rControlRegion: The bounding region of the complete control in VCL frame coordinates.
946 * aValue: An optional value (tristate/numerical/string)
947 * rControlHandle: Carries platform dependent data and is maintained by the SalFrame implementation.
948 * rCaption: A caption or title string (like button text etc)
950 BOOL GtkSalGraphics::drawNativeControlText( ControlType,
951 ControlPart,
952 const Region&,
953 ControlState,
954 const ImplControlValue&,
955 SalControlHandle&,
956 const OUString& )
958 return( FALSE );
963 * GetNativeControlRegion()
965 * If the return value is TRUE, rNativeBoundingRegion
966 * contains the TRUE bounding region covered by the control
967 * including any adornment, while rNativeContentRegion contains the area
968 * within the control that can be safely drawn into without drawing over
969 * the borders of the control.
971 * rControlRegion: The bounding region of the control in VCL frame coordinates.
972 * aValue: An optional value (tristate/numerical/string)
973 * rControlHandle: Carries platform dependent data and is maintained by the SalFrame implementation.
974 * rCaption: A caption or title string (like button text etc)
976 BOOL GtkSalGraphics::getNativeControlRegion( ControlType nType,
977 ControlPart nPart,
978 const Region& rControlRegion,
979 ControlState nState,
980 const ImplControlValue& aValue,
981 SalControlHandle& rControlHandle,
982 const OUString& rCaption,
983 Region &rNativeBoundingRegion,
984 Region &rNativeContentRegion )
986 BOOL returnVal = FALSE;
988 if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL)
989 && (rControlRegion.GetBoundRect().GetWidth() > 16)
990 && (rControlRegion.GetBoundRect().GetHeight() > 16) )
992 rNativeBoundingRegion = NWGetButtonArea( m_nScreen, nType, nPart, rControlRegion.GetBoundRect(),
993 nState, aValue, rControlHandle, rCaption );
994 rNativeContentRegion = rControlRegion;
996 returnVal = TRUE;
998 if ( (nType==CTRL_COMBOBOX) && ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
1000 rNativeBoundingRegion = NWGetComboBoxButtonRect( m_nScreen, nType, nPart, rControlRegion.GetBoundRect(), nState,
1001 aValue, rControlHandle, rCaption );
1002 rNativeContentRegion = rNativeBoundingRegion;
1004 returnVal = TRUE;
1006 if ( (nType==CTRL_SPINBOX) && ((nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
1009 rNativeBoundingRegion = NWGetSpinButtonRect( m_nScreen, nType, nPart, rControlRegion.GetBoundRect(), nState,
1010 aValue, rControlHandle, rCaption );
1011 rNativeContentRegion = rNativeBoundingRegion;
1013 returnVal = TRUE;
1015 if ( (nType==CTRL_LISTBOX) && ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
1017 rNativeBoundingRegion = NWGetListBoxButtonRect( m_nScreen, nType, nPart, rControlRegion.GetBoundRect(), nState,
1018 aValue, rControlHandle, rCaption );
1019 rNativeContentRegion = rNativeBoundingRegion;
1021 returnVal = TRUE;
1023 if ( (nType==CTRL_TOOLBAR) &&
1024 ((nPart==PART_DRAW_BACKGROUND_HORZ) ||
1025 (nPart==PART_DRAW_BACKGROUND_VERT) ||
1026 (nPart==PART_THUMB_HORZ) ||
1027 (nPart==PART_THUMB_VERT) ||
1028 (nPart==PART_BUTTON)
1031 rNativeBoundingRegion = NWGetToolbarRect( m_nScreen, nType, nPart, rControlRegion.GetBoundRect(), nState, aValue, rControlHandle, rCaption );
1032 rNativeContentRegion = rNativeBoundingRegion;
1033 returnVal = TRUE;
1035 if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_BUTTON_LEFT) || (nPart==PART_BUTTON_RIGHT) ||
1036 (nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) ) )
1038 rNativeBoundingRegion = NWGetScrollButtonRect( m_nScreen, nPart, rControlRegion.GetBoundRect() );
1039 rNativeContentRegion = rNativeBoundingRegion;
1041 returnVal = TRUE;
1043 if( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL) )
1045 NWEnsureGTKMenubar( m_nScreen );
1046 GtkRequisition aReq;
1047 gtk_widget_size_request( gWidgetData[m_nScreen].gMenubarWidget, &aReq );
1048 Rectangle aMenuBarRect = rControlRegion.GetBoundRect();
1049 aMenuBarRect = Rectangle( aMenuBarRect.TopLeft(),
1050 Size( aMenuBarRect.GetWidth(), aReq.height+1 ) );
1051 rNativeBoundingRegion = Region( aMenuBarRect );
1052 rNativeContentRegion = rNativeBoundingRegion;
1053 returnVal = TRUE;
1055 if( (nType == CTRL_MENU_POPUP) )
1057 if( (nPart == PART_MENU_ITEM_CHECK_MARK) ||
1058 (nPart == PART_MENU_ITEM_RADIO_MARK) )
1060 NWEnsureGTKMenu( m_nScreen );
1062 gint indicator_size = 0;
1063 GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ?
1064 gWidgetData[m_nScreen].gMenuItemCheckMenuWidget : gWidgetData[m_nScreen].gMenuItemRadioMenuWidget;
1065 gtk_widget_style_get( pWidget,
1066 "indicator_size", &indicator_size,
1067 (char *)NULL );
1068 rNativeBoundingRegion = rControlRegion;
1069 Rectangle aIndicatorRect( Point( 0,
1070 (rControlRegion.GetBoundRect().GetHeight()-indicator_size)/2),
1071 Size( indicator_size, indicator_size ) );
1072 rNativeContentRegion = Region( aIndicatorRect );
1073 returnVal = TRUE;
1076 if( (nType == CTRL_RADIOBUTTON || nType == CTRL_CHECKBOX) )
1078 NWEnsureGTKRadio( m_nScreen );
1079 NWEnsureGTKCheck( m_nScreen );
1080 GtkWidget* widget = (nType == CTRL_RADIOBUTTON) ? gWidgetData[m_nScreen].gRadioWidget : gWidgetData[m_nScreen].gCheckWidget;
1081 gint indicator_size, indicator_spacing;
1082 gtk_widget_style_get( widget,
1083 "indicator_size", &indicator_size,
1084 "indicator_spacing", &indicator_spacing,
1085 (char *)NULL);
1086 indicator_size += 2*indicator_spacing; // guess overpaint of theme
1087 rNativeBoundingRegion = rControlRegion;
1088 Rectangle aIndicatorRect( Point( 0,
1089 (rControlRegion.GetBoundRect().GetHeight()-indicator_size)/2),
1090 Size( indicator_size, indicator_size ) );
1091 rNativeContentRegion = Region( aIndicatorRect );
1092 returnVal = TRUE;
1095 return( returnVal );
1099 /************************************************************************
1100 * Individual control drawing functions
1101 ************************************************************************/
1102 BOOL GtkSalGraphics::NWPaintGTKButton(
1103 GdkDrawable* gdkDrawable,
1104 ControlType, ControlPart,
1105 const Rectangle& rControlRectangle,
1106 const clipList& rClipList,
1107 ControlState nState, const ImplControlValue&,
1108 SalControlHandle&, const OUString& )
1110 GtkStateType stateType;
1111 GtkShadowType shadowType;
1112 gboolean interiorFocus;
1113 gint focusWidth;
1114 gint focusPad;
1115 BOOL bDrawFocus = TRUE;
1116 gint x, y, w, h;
1117 GtkBorder aDefBorder;
1118 GtkBorder* pBorder;
1119 GdkRectangle clipRect;
1121 NWEnsureGTKButton( m_nScreen );
1122 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1124 x = rControlRectangle.Left();
1125 y = rControlRectangle.Top();
1126 w = rControlRectangle.GetWidth();
1127 h = rControlRectangle.GetHeight();
1129 // Grab some button style attributes
1130 gtk_widget_style_get( gWidgetData[m_nScreen].gBtnWidget, "focus-line-width", &focusWidth,
1131 "focus-padding", &focusPad,
1132 "interior_focus", &interiorFocus,
1133 "default_border", &pBorder,
1134 (char *)NULL );
1136 // Make sure the border values exist, otherwise use some defaults
1137 if ( pBorder )
1139 NW_gtk_border_set_from_border( aDefBorder, pBorder );
1140 gtk_border_free( pBorder );
1142 else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder );
1144 // If the button is too small, don't ever draw focus or grab more space
1145 if ( (w < 16) || (h < 16) )
1146 bDrawFocus = FALSE;
1148 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
1150 gint xi = x, yi = y, wi = w, hi = h;
1151 if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus )
1153 xi += aDefBorder.left;
1154 yi += aDefBorder.top;
1155 wi -= aDefBorder.left + aDefBorder.right;
1156 hi -= aDefBorder.top + aDefBorder.bottom;
1159 if ( !interiorFocus && bDrawFocus )
1161 xi += focusWidth + focusPad;
1162 yi += focusWidth + focusPad;
1163 wi -= 2 * (focusWidth + focusPad);
1164 hi -= 2 * (focusWidth + focusPad);
1167 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it)
1169 clipRect.x = it->Left();
1170 clipRect.y = it->Top();
1171 clipRect.width = it->GetWidth();
1172 clipRect.height = it->GetHeight();
1174 // Buttons must paint opaque since some themes have alpha-channel enabled buttons
1175 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
1176 &clipRect, m_pWindow, "base", x, y, w, h );
1178 if ( (nState & CTRL_STATE_DEFAULT) && (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief == GTK_RELIEF_NORMAL) )
1180 gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
1181 &clipRect, gWidgetData[m_nScreen].gBtnWidget, "buttondefault", x, y, w, h );
1184 if ( (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief != GTK_RELIEF_NONE)
1185 || (nState & CTRL_STATE_PRESSED)
1186 || (nState & CTRL_STATE_ROLLOVER) )
1188 gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, shadowType,
1189 &clipRect, gWidgetData[m_nScreen].gBtnWidget, "button", xi, yi, wi, hi );
1192 #if 0 // VCL draws focus rects
1193 // Draw focus rect
1194 if ( (nState & CTRL_STATE_FOCUSED) && (nState & CTRL_STATE_ENABLED) && bDrawFocus )
1196 if (interiorFocus)
1198 x += gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad;
1199 y += gWidgetData[m_nScreen].gBtnWidget->style->ythickness + focusPad;
1200 w -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad);
1201 h -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad);
1203 else
1205 x -= focusWidth + focusPad;
1206 y -= focusWidth + focusPad;
1207 w += 2 * (focusWidth + focusPad);
1208 h += 2 * (focusWidth + focusPad);
1210 if ( !interiorFocus )
1211 gtk_paint_focus( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, &clipRect,
1212 gWidgetData[m_nScreen].gBtnWidget, "button", x, y, w, h );
1214 #endif
1216 return( TRUE );
1219 static Rectangle NWGetButtonArea( int nScreen,
1220 ControlType, ControlPart, Rectangle aAreaRect, ControlState nState,
1221 const ImplControlValue&, SalControlHandle&, const OUString& )
1223 gboolean interiorFocus;
1224 gint focusWidth;
1225 gint focusPad;
1226 GtkBorder aDefBorder;
1227 GtkBorder * pBorder;
1228 BOOL bDrawFocus = TRUE;
1229 Rectangle aRect;
1230 gint x, y, w, h;
1232 NWEnsureGTKButton( nScreen );
1233 gtk_widget_style_get( gWidgetData[nScreen].gBtnWidget,
1234 "focus-line-width", &focusWidth,
1235 "focus-padding", &focusPad,
1236 "interior_focus", &interiorFocus,
1237 "default_border", &pBorder,
1238 (char *)NULL );
1240 // Make sure the border values exist, otherwise use some defaults
1241 if ( pBorder )
1243 NW_gtk_border_set_from_border( aDefBorder, pBorder );
1244 gtk_border_free( pBorder );
1246 else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder );
1248 x = aAreaRect.Left();
1249 y = aAreaRect.Top();
1250 w = aAreaRect.GetWidth();
1251 h = aAreaRect.GetHeight();
1253 // If the button is too small, don't ever draw focus or grab more space
1254 if ( (w < 16) || (h < 16) )
1255 bDrawFocus = FALSE;
1257 if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus )
1259 x -= aDefBorder.left;
1260 y -= aDefBorder.top;
1261 w += aDefBorder.left + aDefBorder.right;
1262 h += aDefBorder.top + aDefBorder.bottom;
1265 aRect = Rectangle( Point( x, y ), Size( w, h ) );
1267 return( aRect );
1270 //-------------------------------------
1272 BOOL GtkSalGraphics::NWPaintGTKRadio( GdkDrawable* gdkDrawable,
1273 ControlType, ControlPart,
1274 const Rectangle& rControlRectangle,
1275 const clipList& rClipList,
1276 ControlState nState,
1277 const ImplControlValue& aValue, SalControlHandle&,
1278 const OUString& )
1280 GtkStateType stateType;
1281 GtkShadowType shadowType;
1282 BOOL isChecked = (aValue.getTristateVal()==BUTTONVALUE_ON);
1283 gint x, y;
1284 GdkRectangle clipRect;
1286 NWEnsureGTKButton( m_nScreen );
1287 NWEnsureGTKRadio( m_nScreen );
1288 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1290 gint indicator_size;
1291 gtk_widget_style_get( gWidgetData[m_nScreen].gRadioWidget, "indicator_size", &indicator_size, (char *)NULL);
1293 x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2;
1294 y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2;
1296 // Set the shadow based on if checked or not so we get a freakin checkmark.
1297 shadowType = isChecked ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
1298 NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidget, nState, stateType );
1299 NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidgetSibling, nState, stateType );
1301 // GTK enforces radio groups, so that if we don't have 2 buttons in the group,
1302 // the single button will always be active. So we have to have 2 buttons.
1304 // #i59666# set the members directly where we should use
1305 // gtk_toggle_button_set_active. reason: there are animated themes
1306 // which are in active state only after a while leading to painting
1307 // intermediate states between active/inactive. Let's hope that
1308 // GtkToggleButtone stays binary compatible.
1309 if (!isChecked)
1310 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidgetSibling)->active = TRUE;
1311 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidget)->active = isChecked;
1313 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
1315 clipRect.x = it->Left();
1316 clipRect.y = it->Top();
1317 clipRect.width = it->GetWidth();
1318 clipRect.height = it->GetHeight();
1320 gtk_paint_option( gWidgetData[m_nScreen].gRadioWidget->style, gdkDrawable, stateType, shadowType,
1321 &clipRect, gWidgetData[m_nScreen].gRadioWidget, "radiobutton",
1322 x, y, indicator_size, indicator_size );
1325 return( TRUE );
1328 //-------------------------------------
1330 BOOL GtkSalGraphics::NWPaintGTKCheck( GdkDrawable* gdkDrawable,
1331 ControlType, ControlPart,
1332 const Rectangle& rControlRectangle,
1333 const clipList& rClipList,
1334 ControlState nState,
1335 const ImplControlValue& aValue,
1336 SalControlHandle&, const OUString& )
1338 GtkStateType stateType;
1339 GtkShadowType shadowType;
1340 BOOL isChecked = (aValue.getTristateVal()==BUTTONVALUE_ON) ? TRUE : FALSE;
1341 GdkRectangle clipRect;
1342 gint x,y;
1344 NWEnsureGTKButton( m_nScreen );
1345 NWEnsureGTKCheck( m_nScreen );
1346 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1348 gint indicator_size;
1349 gtk_widget_style_get( gWidgetData[m_nScreen].gCheckWidget, "indicator_size", &indicator_size, (char *)NULL);
1351 x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2;
1352 y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2;
1354 // Set the shadow based on if checked or not so we get a checkmark.
1355 shadowType = isChecked ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
1356 NWSetWidgetState( gWidgetData[m_nScreen].gCheckWidget, nState, stateType );
1357 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gCheckWidget)->active = isChecked;
1359 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
1361 clipRect.x = it->Left();
1362 clipRect.y = it->Top();
1363 clipRect.width = it->GetWidth();
1364 clipRect.height = it->GetHeight();
1366 gtk_paint_check( gWidgetData[m_nScreen].gCheckWidget->style, gdkDrawable, stateType, shadowType,
1367 &clipRect, gWidgetData[m_nScreen].gCheckWidget, "checkbutton",
1368 x, y, indicator_size, indicator_size );
1371 return( TRUE );
1374 //-------------------------------------
1375 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow )
1377 // Size the arrow appropriately
1378 Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
1379 rArrow.SetSize( aSize );
1381 rArrow.SetPos( Point(
1382 rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2,
1383 rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
1384 ) );
1387 BOOL GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart,
1388 const Rectangle& rControlRectangle,
1389 const clipList&,
1390 ControlState nState,
1391 const ImplControlValue& aValue, SalControlHandle&,
1392 const OUString& )
1394 ScrollbarValue* pScrollbarVal = (ScrollbarValue *)(aValue.getOptionalVal());
1395 GdkPixmap* pixmap = NULL;
1396 Rectangle pixmapRect, scrollbarRect;
1397 GtkStateType stateType;
1398 GtkShadowType shadowType;
1399 GtkScrollbar * scrollbarWidget;
1400 GtkStyle * style;
1401 GtkAdjustment* scrollbarValues = NULL;
1402 GtkOrientation scrollbarOrientation;
1403 Rectangle thumbRect = pScrollbarVal->maThumbRect;
1404 Rectangle button11BoundRect = pScrollbarVal->maButton1Rect; // backward
1405 Rectangle button22BoundRect = pScrollbarVal->maButton2Rect; // forward
1406 Rectangle button12BoundRect = pScrollbarVal->maButton1Rect; // secondary forward
1407 Rectangle button21BoundRect = pScrollbarVal->maButton2Rect; // secondary backward
1408 GtkArrowType button1Type; // backward
1409 GtkArrowType button2Type; // forward
1410 gchar * scrollbarTagH = (gchar *) "hscrollbar";
1411 gchar * scrollbarTagV = (gchar *) "vscrollbar";
1412 gchar * scrollbarTag = NULL;
1413 Rectangle arrowRect;
1414 gint slider_width = 0;
1415 gint stepper_size = 0;
1416 gint stepper_spacing = 0;
1417 gint trough_border = 0;
1418 gint min_slider_length = 0;
1419 gint vShim = 0;
1420 gint hShim = 0;
1421 gint x,y,w,h;
1423 // make controlvalue rectangles relative to area
1424 thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1425 button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1426 button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1427 button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1428 button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
1430 NWEnsureGTKButton( m_nScreen );
1431 NWEnsureGTKScrollbars( m_nScreen );
1432 NWEnsureGTKArrow( m_nScreen );
1434 // Find the overall bounding rect of the control
1435 pixmapRect = rControlRectangle;
1436 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 1,
1437 pixmapRect.GetHeight() + 1 ) );
1438 scrollbarRect = pixmapRect;
1440 if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) )
1441 return( TRUE );
1443 // Grab some button style attributes
1444 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget,
1445 "slider_width", &slider_width,
1446 "stepper_size", &stepper_size,
1447 "trough_border", &trough_border,
1448 "stepper_spacing", &stepper_spacing,
1449 "min_slider_length", &min_slider_length, (char *)NULL );
1450 gboolean has_forward;
1451 gboolean has_forward2;
1452 gboolean has_backward;
1453 gboolean has_backward2;
1455 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward,
1456 "has-secondary-forward-stepper", &has_forward2,
1457 "has-backward-stepper", &has_backward,
1458 "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
1459 gint magic = trough_border ? 1 : 0;
1460 gint nFirst = 0;
1462 if ( has_backward ) nFirst += 1;
1463 if ( has_forward2 ) nFirst += 1;
1465 if ( nPart == PART_DRAW_BACKGROUND_HORZ )
1467 unsigned int sliderHeight = slider_width + (trough_border * 2);
1468 vShim = (pixmapRect.GetHeight() - sliderHeight) / 2;
1470 scrollbarRect.Move( 0, vShim );
1471 scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), sliderHeight ) );
1473 scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollHorizWidget );
1474 scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
1475 scrollbarTag = scrollbarTagH;
1476 button1Type = GTK_ARROW_LEFT;
1477 button2Type = GTK_ARROW_RIGHT;
1479 if ( has_backward )
1481 button12BoundRect.Move( stepper_size - trough_border,
1482 (scrollbarRect.GetHeight() - slider_width) / 2 );
1485 button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 );
1486 button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
1487 button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
1489 if ( has_backward2 )
1491 button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
1492 button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
1494 else
1496 button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
1499 button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
1500 button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
1502 thumbRect.Bottom() = thumbRect.Top() + slider_width - 1;
1503 // Make sure the thumb is at least the default width (so we don't get tiny thumbs),
1504 // but if the VCL gives us a size smaller than the theme's default thumb size,
1505 // honor the VCL size
1506 #if 0
1507 if ( (thumbRect.GetWidth() < min_slider_length)
1508 && ((scrollbarRect.GetWidth()-button1BoundRect.GetWidth()-button2BoundRect.GetWidth()) > min_slider_length) )
1509 thumbRect.SetSize( Size( min_slider_length, thumbRect.GetHeight() ) );
1510 #endif
1512 thumbRect.Right() += magic;
1513 // Center vertically in the track
1514 thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
1516 else
1518 unsigned int sliderWidth = slider_width + (trough_border * 2);
1519 hShim = (pixmapRect.GetWidth() - sliderWidth) / 2;
1521 scrollbarRect.Move( hShim, 0 );
1522 scrollbarRect.SetSize( Size( sliderWidth, scrollbarRect.GetHeight() ) );
1524 scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollVertWidget );
1525 scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
1526 scrollbarTag = scrollbarTagV;
1527 button1Type = GTK_ARROW_UP;
1528 button2Type = GTK_ARROW_DOWN;
1530 if ( has_backward )
1532 button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
1533 stepper_size + trough_border );
1535 button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border );
1536 button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
1537 button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
1539 if ( has_backward2 )
1541 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 );
1542 button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
1544 else
1546 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
1549 button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
1550 button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
1552 thumbRect.Right() = thumbRect.Left() + slider_width - 1;
1553 #if 0
1554 // Make sure the thumb is at least the default width (so we don't get tiny thumbs),
1555 // but if the VCL gives us a size smaller than the theme's default thumb size,
1556 // honor the VCL size
1557 if ( (thumbRect.GetHeight() < min_slider_length)
1558 && ((scrollbarRect.GetHeight()-button1BoundRect.GetHeight()-button2BoundRect.GetHeight()) > min_slider_length) )
1559 thumbRect.SetSize( Size( thumbRect.GetWidth(), min_slider_length ) );
1560 #endif
1562 thumbRect.Bottom() += magic;
1563 // Center horizontally in the track
1564 thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
1567 BOOL has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
1569 scrollbarValues = gtk_range_get_adjustment( GTK_RANGE(scrollbarWidget) );
1570 if ( scrollbarValues == NULL )
1571 scrollbarValues = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
1572 if ( nPart == PART_DRAW_BACKGROUND_HORZ )
1574 scrollbarValues->lower = pScrollbarVal->mnMin;
1575 scrollbarValues->upper = pScrollbarVal->mnMax;
1576 scrollbarValues->value = pScrollbarVal->mnCur;
1577 scrollbarValues->page_size = scrollbarRect.GetWidth() / 2;
1579 else
1581 scrollbarValues->lower = pScrollbarVal->mnMin;
1582 scrollbarValues->upper = pScrollbarVal->mnMax;
1583 scrollbarValues->value = pScrollbarVal->mnCur;
1584 scrollbarValues->page_size = scrollbarRect.GetHeight() / 2;
1586 gtk_adjustment_changed( scrollbarValues );
1588 // as multiple paints are required for the scrollbar
1589 // painting them directly to the window flickers
1590 pixmap = NWGetPixmapFromScreen( pixmapRect );
1591 if( ! pixmap )
1592 return FALSE;
1593 x = y = 0;
1595 w = pixmapRect.GetWidth();
1596 h = pixmapRect.GetHeight();
1598 GdkDrawable* const &gdkDrawable = GDK_DRAWABLE( pixmap );
1599 GdkRectangle* gdkRect = NULL;
1601 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1602 NWSetWidgetState( GTK_WIDGET(scrollbarWidget), nState, stateType );
1603 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
1604 style = GTK_WIDGET( scrollbarWidget )->style;
1606 // ----------------- TROUGH
1607 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable,
1608 GTK_STATE_NORMAL, GTK_SHADOW_NONE, gdkRect,
1609 m_pWindow, "base", x, y,
1610 w, h );
1611 gtk_paint_box( style, gdkDrawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN,
1612 gdkRect, GTK_WIDGET(scrollbarWidget), "trough",
1613 x, y,
1614 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
1616 if ( nState & CTRL_STATE_FOCUSED )
1618 gtk_paint_focus( style, gdkDrawable, GTK_STATE_ACTIVE,
1619 gdkRect, GTK_WIDGET(scrollbarWidget), "trough",
1620 x, y,
1621 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
1624 // ----------------- THUMB
1625 if ( has_slider )
1627 NWConvertVCLStateToGTKState( pScrollbarVal->mnThumbState, &stateType, &shadowType );
1628 if ( pScrollbarVal->mnThumbState & CTRL_STATE_PRESSED ) stateType = GTK_STATE_PRELIGHT;
1629 gtk_paint_slider( style, gdkDrawable, stateType, GTK_SHADOW_OUT,
1630 gdkRect, GTK_WIDGET(scrollbarWidget), "slider",
1631 x+hShim+thumbRect.Left(), y+vShim+thumbRect.Top(),
1632 thumbRect.GetWidth(), thumbRect.GetHeight(), scrollbarOrientation );
1634 // ----------------- BUTTON 1 //
1635 if ( has_backward )
1637 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType );
1638 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL;
1639 gtk_paint_box( style, gdkDrawable, stateType, shadowType,
1640 gdkRect, GTK_WIDGET(scrollbarWidget), "stepper",
1641 x+hShim+button11BoundRect.Left(), y+vShim+button11BoundRect.Top(),
1642 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
1643 // ----------------- ARROW 1
1644 NWCalcArrowRect( button11BoundRect, arrowRect );
1645 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1646 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, TRUE,
1647 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1648 arrowRect.GetWidth(), arrowRect.GetHeight() );
1650 if ( has_forward2 )
1652 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType );
1653 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL;
1654 gtk_paint_box( style, gdkDrawable, stateType, shadowType,
1655 gdkRect, GTK_WIDGET(scrollbarWidget), "stepper",
1656 x+hShim+button12BoundRect.Left(), y+vShim+button12BoundRect.Top(),
1657 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
1658 // ----------------- ARROW 1
1659 NWCalcArrowRect( button12BoundRect, arrowRect );
1660 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1661 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, TRUE,
1662 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1663 arrowRect.GetWidth(), arrowRect.GetHeight() );
1665 // ----------------- BUTTON 2
1666 if ( has_backward2 )
1668 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType );
1669 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL;
1670 gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect,
1671 GTK_WIDGET(scrollbarWidget), "stepper",
1672 x+hShim+button21BoundRect.Left(), y+vShim+button21BoundRect.Top(),
1673 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
1674 // ----------------- ARROW 2
1675 NWCalcArrowRect( button21BoundRect, arrowRect );
1676 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1677 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, TRUE,
1678 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1679 arrowRect.GetWidth(), arrowRect.GetHeight() );
1681 if ( has_forward )
1683 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType );
1684 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL;
1685 gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect,
1686 GTK_WIDGET(scrollbarWidget), "stepper",
1687 x+hShim+button22BoundRect.Left(), y+vShim+button22BoundRect.Top(),
1688 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
1689 // ----------------- ARROW 2
1690 NWCalcArrowRect( button22BoundRect, arrowRect );
1691 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType,
1692 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, TRUE,
1693 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(),
1694 arrowRect.GetWidth(), arrowRect.GetHeight() );
1697 if( !NWRenderPixmapToScreen(pixmap, pixmapRect) )
1699 g_object_unref( pixmap );
1700 return( FALSE );
1702 g_object_unref( pixmap );
1704 return( TRUE );
1707 //---
1709 static Rectangle NWGetScrollButtonRect( int nScreen, ControlPart nPart, Rectangle aAreaRect )
1711 gint slider_width;
1712 gint stepper_size;
1713 gint stepper_spacing;
1714 gint trough_border;
1716 NWEnsureGTKScrollbars( nScreen );
1718 // Grab some button style attributes
1719 gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget,
1720 "slider-width", &slider_width,
1721 "stepper-size", &stepper_size,
1722 "trough-border", &trough_border,
1723 "stepper-spacing", &stepper_spacing, (char *)NULL );
1725 gboolean has_forward;
1726 gboolean has_forward2;
1727 gboolean has_backward;
1728 gboolean has_backward2;
1730 gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget,
1731 "has-forward-stepper", &has_forward,
1732 "has-secondary-forward-stepper", &has_forward2,
1733 "has-backward-stepper", &has_backward,
1734 "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
1735 gint buttonWidth;
1736 gint buttonHeight;
1737 Rectangle buttonRect;
1739 gint nFirst = 0;
1740 gint nSecond = 0;
1742 if ( has_forward ) nSecond += 1;
1743 if ( has_forward2 ) nFirst += 1;
1744 if ( has_backward ) nFirst += 1;
1745 if ( has_backward2 ) nSecond += 1;
1747 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
1749 buttonWidth = slider_width + 2 * trough_border;
1750 buttonHeight = stepper_size + trough_border + stepper_spacing;
1752 else
1754 buttonWidth = stepper_size + trough_border + stepper_spacing;
1755 buttonHeight = slider_width + 2 * trough_border;
1758 if ( nPart == PART_BUTTON_UP )
1760 buttonHeight *= nFirst;
1761 buttonHeight -= 1;
1762 buttonRect.setX( aAreaRect.Left() );
1763 buttonRect.setY( aAreaRect.Top() );
1765 else if ( nPart == PART_BUTTON_LEFT )
1767 buttonWidth *= nFirst;
1768 buttonWidth -= 1;
1769 buttonRect.setX( aAreaRect.Left() );
1770 buttonRect.setY( aAreaRect.Top() );
1772 else if ( nPart == PART_BUTTON_DOWN )
1774 buttonHeight *= nSecond;
1775 buttonRect.setX( aAreaRect.Left() );
1776 buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight );
1778 else if ( nPart == PART_BUTTON_RIGHT )
1780 buttonWidth *= nSecond;
1781 buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth );
1782 buttonRect.setY( aAreaRect.Top() );
1785 buttonRect.SetSize( Size( buttonWidth, buttonHeight ) );
1787 return( buttonRect );
1790 //-------------------------------------
1792 BOOL GtkSalGraphics::NWPaintGTKEditBox( GdkDrawable* gdkDrawable,
1793 ControlType nType, ControlPart nPart,
1794 const Rectangle& rControlRectangle,
1795 const clipList& rClipList,
1796 ControlState nState,
1797 const ImplControlValue& aValue, SalControlHandle& rControlHandle,
1798 const OUString& rCaption )
1800 Rectangle pixmapRect;
1801 GdkRectangle clipRect;
1803 // Find the overall bounding rect of the buttons's drawing area,
1804 // plus its actual draw rect excluding adornment
1805 pixmapRect = NWGetEditBoxPixmapRect( m_nScreen, nType, nPart, rControlRectangle,
1806 nState, aValue, rControlHandle, rCaption );
1807 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
1809 clipRect.x = it->Left();
1810 clipRect.y = it->Top();
1811 clipRect.width = it->GetWidth();
1812 clipRect.height = it->GetHeight();
1814 NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, pixmapRect, nState, aValue, rControlHandle, rCaption );
1817 return( TRUE );
1821 /* Take interior/exterior focus into account and return
1822 * the bounding rectangle of the edit box including
1823 * any focus requirements.
1825 static Rectangle NWGetEditBoxPixmapRect(int nScreen,
1826 ControlType,
1827 ControlPart,
1828 Rectangle aAreaRect,
1829 ControlState,
1830 const ImplControlValue&,
1831 SalControlHandle&,
1832 const OUString& )
1834 Rectangle pixmapRect = aAreaRect;
1835 gboolean interiorFocus;
1836 gint focusWidth;
1838 NWEnsureGTKEditBox( nScreen );
1840 // Grab some entry style attributes
1841 gtk_widget_style_get( gWidgetData[nScreen].gEditBoxWidget,
1842 "focus-line-width", &focusWidth,
1843 "interior-focus", &interiorFocus, (char *)NULL );
1845 if ( !interiorFocus )
1847 pixmapRect.Move( -(focusWidth), -(focusWidth) );
1848 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + (2*(focusWidth)),
1849 pixmapRect.GetHeight() + (2*(focusWidth)) ) );
1852 return( pixmapRect );
1856 /* Paint a GTK Entry widget into the specified GdkPixmap.
1857 * All coordinates should be local to the Pixmap, NOT
1858 * screen/window coordinates.
1860 static void NWPaintOneEditBox( int nScreen,
1861 GdkDrawable * gdkDrawable,
1862 GdkRectangle * gdkRect,
1863 ControlType nType,
1864 ControlPart,
1865 Rectangle aEditBoxRect,
1866 ControlState nState,
1867 const ImplControlValue&,
1868 SalControlHandle&,
1869 const OUString& )
1871 GtkStateType stateType;
1872 GtkShadowType shadowType;
1873 GtkWidget *widget;
1875 NWEnsureGTKButton( nScreen );
1876 NWEnsureGTKEditBox( nScreen );
1877 NWEnsureGTKSpinButton( nScreen );
1878 NWEnsureGTKCombo( nScreen );
1879 NWEnsureGTKScrolledWindow( nScreen );
1880 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1882 /* border's shadowType for gtk entries is always GTK_SHADOW_IN (see gtkentry.c)
1883 shadowType = GTK_SHADOW_IN;
1886 switch ( nType )
1888 case CTRL_SPINBOX:
1889 widget = gWidgetData[nScreen].gSpinButtonWidget;
1890 break;
1892 case CTRL_MULTILINE_EDITBOX:
1893 widget = gWidgetData[nScreen].gScrolledWindowWidget;
1894 break;
1895 case CTRL_COMBOBOX:
1896 widget = GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry;
1897 break;
1899 default:
1900 widget = gWidgetData[nScreen].gEditBoxWidget;
1901 break;
1904 if ( stateType == GTK_STATE_PRELIGHT )
1905 stateType = GTK_STATE_NORMAL;
1907 // Blueprint needs to paint entry_bg with a Button widget, not an Entry widget to get
1908 // a nice white (or whatever default color) background
1909 GtkWidget* pBGWidget = widget;
1910 if( GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround )
1912 NWSetWidgetState( gWidgetData[nScreen].gBtnWidget, nState, stateType );
1913 pBGWidget = gWidgetData[nScreen].gBtnWidget;
1915 NWSetWidgetState( widget, nState, stateType );
1917 gtk_paint_flat_box( pBGWidget->style, gdkDrawable, stateType, GTK_SHADOW_NONE,
1918 gdkRect, pBGWidget, "entry_bg",
1919 aEditBoxRect.Left(), aEditBoxRect.Top(),
1920 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
1921 gtk_paint_shadow( widget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN,
1922 gdkRect, widget, "entry",
1923 aEditBoxRect.Left(), aEditBoxRect.Top(),
1924 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
1930 //-------------------------------------
1932 BOOL GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart,
1933 const Rectangle& rControlRectangle,
1934 const clipList&,
1935 ControlState nState,
1936 const ImplControlValue& aValue,
1937 SalControlHandle& rControlHandle, const OUString& rCaption )
1939 GdkPixmap * pixmap;
1940 Rectangle pixmapRect;
1941 GtkStateType stateType;
1942 GtkShadowType shadowType;
1943 SpinbuttonValue * pSpinVal = (SpinbuttonValue *)(aValue.getOptionalVal());
1944 Rectangle upBtnRect;
1945 ControlPart upBtnPart = PART_BUTTON_UP;
1946 ControlState upBtnState = CTRL_STATE_ENABLED;
1947 Rectangle downBtnRect;
1948 ControlPart downBtnPart = PART_BUTTON_DOWN;
1949 ControlState downBtnState = CTRL_STATE_ENABLED;
1951 NWEnsureGTKButton( m_nScreen );
1952 NWEnsureGTKSpinButton( m_nScreen );
1953 NWEnsureGTKArrow( m_nScreen );
1955 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
1957 if ( pSpinVal )
1959 upBtnPart = pSpinVal->mnUpperPart;
1960 upBtnState = pSpinVal->mnUpperState;
1962 downBtnPart = pSpinVal->mnLowerPart;
1963 downBtnState = pSpinVal->mnLowerState;
1966 // CTRL_SPINBUTTONS pass their area in pSpinVal, not in rControlRectangle
1967 if ( nType == CTRL_SPINBUTTONS )
1969 if ( !pSpinVal )
1971 std::fprintf( stderr, "Tried to draw CTRL_SPINBUTTONS, but the SpinButtons data structure didn't exist!\n" );
1972 return( false );
1974 pixmapRect = pSpinVal->maUpperRect;
1975 pixmapRect.Union( pSpinVal->maLowerRect );
1977 else
1978 pixmapRect = rControlRectangle;
1981 pixmap = NWGetPixmapFromScreen( pixmapRect );
1982 if ( !pixmap )
1983 return( FALSE );
1985 upBtnRect = NWGetSpinButtonRect( m_nScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rControlHandle, rCaption );
1986 downBtnRect = NWGetSpinButtonRect( m_nScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rControlHandle, rCaption );
1988 if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) )
1990 // Draw an edit field for SpinBoxes and ComboBoxes
1991 Rectangle aEditBoxRect( pixmapRect );
1992 aEditBoxRect.SetSize( Size( upBtnRect.Left() - pixmapRect.Left(), aEditBoxRect.GetHeight() ) );
1993 aEditBoxRect.setX( 0 );
1994 aEditBoxRect.setY( 0 );
1996 NWPaintOneEditBox( m_nScreen, pixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rControlHandle, rCaption );
1999 NWSetWidgetState( gWidgetData[m_nScreen].gSpinButtonWidget, nState, stateType );
2000 gtk_widget_style_get( gWidgetData[m_nScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL );
2002 if ( shadowType != GTK_SHADOW_NONE )
2004 Rectangle shadowRect( upBtnRect );
2006 shadowRect.Union( downBtnRect );
2007 gtk_paint_box( gWidgetData[m_nScreen].gSpinButtonWidget->style, pixmap, GTK_STATE_NORMAL, shadowType, NULL,
2008 gWidgetData[m_nScreen].gSpinButtonWidget, "spinbutton",
2009 (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()),
2010 shadowRect.GetWidth(), shadowRect.GetHeight() );
2013 NWPaintOneSpinButton( m_nScreen, pixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rControlHandle, rCaption );
2014 NWPaintOneSpinButton( m_nScreen, pixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rControlHandle, rCaption );
2016 if( !NWRenderPixmapToScreen(pixmap, pixmapRect) )
2018 g_object_unref( pixmap );
2019 return( FALSE );
2022 g_object_unref( pixmap );
2023 return( TRUE );
2026 //---
2028 static Rectangle NWGetSpinButtonRect( int nScreen,
2029 ControlType,
2030 ControlPart nPart,
2031 Rectangle aAreaRect,
2032 ControlState,
2033 const ImplControlValue&,
2034 SalControlHandle&,
2035 const OUString& )
2037 gint buttonSize;
2038 Rectangle buttonRect;
2040 NWEnsureGTKSpinButton( nScreen );
2042 buttonSize = MAX( PANGO_PIXELS( pango_font_description_get_size(GTK_WIDGET(gWidgetData[nScreen].gSpinButtonWidget)->style->font_desc) ),
2043 MIN_SPIN_ARROW_WIDTH );
2044 buttonSize -= buttonSize % 2 - 1; /* force odd */
2045 buttonRect.SetSize( Size( buttonSize + 2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness,
2046 buttonRect.GetHeight() ) );
2047 buttonRect.setX( aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()) );
2048 if ( nPart == PART_BUTTON_UP )
2050 buttonRect.setY( aAreaRect.Top() );
2051 buttonRect.Bottom() = buttonRect.Top() + (aAreaRect.GetHeight() / 2);
2053 else if( nPart == PART_BUTTON_DOWN )
2055 buttonRect.setY( aAreaRect.Top() + (aAreaRect.GetHeight() / 2) );
2056 buttonRect.Bottom() = aAreaRect.Bottom(); // cover area completely
2058 else
2060 buttonRect.Right() = buttonRect.Left()-1;
2061 buttonRect.Left() = aAreaRect.Left();
2062 buttonRect.Top() = aAreaRect.Top();
2063 buttonRect.Bottom() = aAreaRect.Bottom();
2066 return( buttonRect );
2069 //---
2071 static void NWPaintOneSpinButton( int nScreen,
2072 GdkPixmap* pixmap,
2073 ControlType nType,
2074 ControlPart nPart,
2075 Rectangle aAreaRect,
2076 ControlState nState,
2077 const ImplControlValue& aValue,
2078 SalControlHandle& rControlHandle,
2079 const OUString& rCaption )
2081 Rectangle buttonRect;
2082 GtkStateType stateType;
2083 GtkShadowType shadowType;
2084 Rectangle arrowRect;
2085 gint arrowSize;
2087 NWEnsureGTKSpinButton( nScreen );
2088 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2090 buttonRect = NWGetSpinButtonRect( nScreen, nType, nPart, aAreaRect, nState, aValue, rControlHandle, rCaption );
2092 NWSetWidgetState( gWidgetData[nScreen].gSpinButtonWidget, nState, stateType );
2093 gtk_paint_box( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, shadowType, NULL, gWidgetData[nScreen].gSpinButtonWidget,
2094 (nPart == PART_BUTTON_UP) ? "spinbutton_up" : "spinbutton_down",
2095 (buttonRect.Left() - aAreaRect.Left()), (buttonRect.Top() - aAreaRect.Top()),
2096 buttonRect.GetWidth(), buttonRect.GetHeight() );
2098 arrowSize = (buttonRect.GetWidth() - (2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness)) - 4;
2099 arrowSize -= arrowSize % 2 - 1; /* force odd */
2100 arrowRect.SetSize( Size( arrowSize, arrowSize ) );
2101 arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
2102 if ( nPart == PART_BUTTON_UP )
2103 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 + 1);
2104 else
2105 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 - 1);
2107 gtk_paint_arrow( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[nScreen].gSpinButtonWidget,
2108 "spinbutton", (nPart == PART_BUTTON_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN, TRUE,
2109 (arrowRect.Left() - aAreaRect.Left()), (arrowRect.Top() - aAreaRect.Top()),
2110 arrowRect.GetWidth(), arrowRect.GetHeight() );
2114 //-------------------------------------
2116 BOOL GtkSalGraphics::NWPaintGTKComboBox( GdkDrawable* gdkDrawable,
2117 ControlType nType, ControlPart nPart,
2118 const Rectangle& rControlRectangle,
2119 const clipList& rClipList,
2120 ControlState nState,
2121 const ImplControlValue& aValue,
2122 SalControlHandle& rControlHandle, const OUString& rCaption )
2124 Rectangle pixmapRect;
2125 Rectangle buttonRect;
2126 GtkStateType stateType;
2127 GtkShadowType shadowType;
2128 Rectangle arrowRect;
2129 gint x,y;
2130 GdkRectangle clipRect;
2132 NWEnsureGTKButton( m_nScreen );
2133 NWEnsureGTKArrow( m_nScreen );
2134 NWEnsureGTKCombo( m_nScreen );
2135 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2137 // Find the overall bounding rect of the buttons's drawing area,
2138 // plus its actual draw rect excluding adornment
2139 pixmapRect = rControlRectangle;
2140 x = rControlRectangle.Left();
2141 y = rControlRectangle.Top();
2143 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
2144 NWSetWidgetState( gWidgetData[m_nScreen].gComboWidget, nState, stateType );
2145 NWSetWidgetState( gWidgetData[m_nScreen].gArrowWidget, nState, stateType );
2147 buttonRect = NWGetComboBoxButtonRect( m_nScreen, nType, PART_BUTTON_DOWN, pixmapRect, nState, aValue, rControlHandle, rCaption );
2148 if( nPart == PART_BUTTON_DOWN )
2149 buttonRect.Left() += 1;
2151 Rectangle aEditBoxRect( pixmapRect );
2152 aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
2154 #define ARROW_EXTENT 0.7
2155 arrowRect.SetSize( Size( (gint)(MIN_ARROW_SIZE * ARROW_EXTENT),
2156 (gint)(MIN_ARROW_SIZE * ARROW_EXTENT) ) );
2157 arrowRect.SetPos( Point( buttonRect.Left() + (gint)((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
2158 buttonRect.Top() + (gint)((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
2160 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2162 clipRect.x = it->Left();
2163 clipRect.y = it->Top();
2164 clipRect.width = it->GetWidth();
2165 clipRect.height = it->GetHeight();
2167 if( nPart == PART_ENTIRE_CONTROL )
2168 NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, aEditBoxRect,
2169 nState, aValue, rControlHandle, rCaption );
2171 // Buttons must paint opaque since some themes have alpha-channel enabled buttons
2172 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
2173 &clipRect, m_pWindow, "base",
2174 x+(buttonRect.Left() - pixmapRect.Left()),
2175 y+(buttonRect.Top() - pixmapRect.Top()),
2176 buttonRect.GetWidth(), buttonRect.GetHeight() );
2177 gtk_paint_box( GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button->style, gdkDrawable, stateType, shadowType,
2178 &clipRect, GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button, "button",
2179 x+(buttonRect.Left() - pixmapRect.Left()),
2180 y+(buttonRect.Top() - pixmapRect.Top()),
2181 buttonRect.GetWidth(), buttonRect.GetHeight() );
2183 gtk_paint_arrow( gWidgetData[m_nScreen].gArrowWidget->style, gdkDrawable, stateType, shadowType,
2184 &clipRect, gWidgetData[m_nScreen].gArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE,
2185 x+(arrowRect.Left() - pixmapRect.Left()), y+(arrowRect.Top() - pixmapRect.Top()),
2186 arrowRect.GetWidth(), arrowRect.GetHeight() );
2189 return( TRUE );
2192 //----
2194 static Rectangle NWGetComboBoxButtonRect( int nScreen,
2195 ControlType,
2196 ControlPart nPart,
2197 Rectangle aAreaRect,
2198 ControlState,
2199 const ImplControlValue&,
2200 SalControlHandle&,
2201 const OUString& )
2203 Rectangle aButtonRect;
2204 gint nArrowWidth;
2205 gint nButtonWidth;
2206 gint nFocusWidth;
2207 gint nFocusPad;
2209 NWEnsureGTKArrow( nScreen );
2211 // Grab some button style attributes
2212 gtk_widget_style_get( gWidgetData[nScreen].gDropdownWidget,
2213 "focus-line-width", &nFocusWidth,
2214 "focus-padding", &nFocusPad, (char *)NULL );
2216 nArrowWidth = MIN_ARROW_SIZE + (GTK_MISC(gWidgetData[nScreen].gArrowWidget)->xpad * 2);
2217 nButtonWidth = nArrowWidth +
2218 ((BTN_CHILD_SPACING + gWidgetData[nScreen].gDropdownWidget->style->xthickness) * 2)
2219 + (2 * (nFocusWidth+nFocusPad));
2220 if( nPart == PART_BUTTON_DOWN )
2222 aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
2223 aButtonRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth,
2224 aAreaRect.Top() ) );
2226 else if( nPart == PART_SUB_EDIT )
2228 NWEnsureGTKCombo( nScreen );
2230 gint adjust_x = GTK_CONTAINER(gWidgetData[nScreen].gComboWidget)->border_width +
2231 nFocusWidth +
2232 nFocusPad;
2233 gint adjust_y = adjust_x + gWidgetData[nScreen].gComboWidget->style->ythickness;
2234 adjust_x += gWidgetData[nScreen].gComboWidget->style->xthickness;
2235 aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - 2 * adjust_x,
2236 aAreaRect.GetHeight() - 2 * adjust_y ) );
2237 Point aEditPos = aAreaRect.TopLeft();
2238 aEditPos.X() += adjust_x;
2239 aEditPos.Y() += adjust_y;
2240 aButtonRect.SetPos( aEditPos );
2243 return( aButtonRect );
2246 //-------------------------------------
2250 BOOL GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart,
2251 const Rectangle& rControlRectangle,
2252 const clipList&,
2253 ControlState nState,
2254 const ImplControlValue& aValue,
2255 SalControlHandle&, const OUString& )
2257 GdkPixmap * pixmap;
2258 Rectangle pixmapRect;
2259 Rectangle tabRect;
2260 TabitemValue * pTabitemValue = (TabitemValue *)(aValue.getOptionalVal());
2261 GtkStateType stateType;
2262 GtkShadowType shadowType;
2263 if( ! gWidgetData[ m_nScreen ].gCacheTabItems )
2265 gWidgetData[ m_nScreen ].gCacheTabItems = new NWPixmapCache( m_nScreen );
2266 gWidgetData[ m_nScreen ].gCacheTabPages = new NWPixmapCache( m_nScreen );
2268 NWPixmapCache& aCacheItems = *gWidgetData[ m_nScreen ].gCacheTabItems;
2269 NWPixmapCache& aCachePage = *gWidgetData[ m_nScreen ].gCacheTabPages;
2271 if( !aCacheItems.GetSize() )
2272 aCacheItems.SetSize( 20 );
2273 if( !aCachePage.GetSize() )
2274 aCachePage.SetSize( 1 );
2276 if ( !pTabitemValue && (nType==CTRL_TAB_ITEM) )
2278 std::fprintf( stderr, "NWPaintGTKTabItem() received a NULL TabitemValue. Cannot draw native tab\n" );
2279 return( false );
2282 NWEnsureGTKButton( m_nScreen );
2283 NWEnsureGTKNotebook( m_nScreen );
2284 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2286 // Find the overall bounding rect of the buttons's drawing area,
2287 // plus its actual draw rect excluding adornment
2288 pixmapRect = rControlRectangle;
2289 if ( nType == CTRL_TAB_ITEM )
2291 if ( !pTabitemValue->isFirst() )
2293 // GTK+ tabs overlap on the right edge (the top tab obscures the
2294 // left edge of the tab right "below" it, so adjust the rectangle
2295 // to draw tabs slightly large so the overlap happens
2296 pixmapRect.Move( -2, 0 );
2297 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, pixmapRect.GetHeight() ) );
2299 if ( nState & CTRL_STATE_SELECTED )
2301 // In GTK+, the selected tab is 2px taller than all other tabs
2302 pixmapRect.Move( 0, -2 );
2303 pixmapRect.Bottom() += 2;
2304 tabRect = pixmapRect;
2305 // Only draw over 1 pixel of the tab pane that this tab is drawn on top of.
2306 tabRect.Bottom() -= 1;
2308 else
2309 tabRect = pixmapRect;
2311 // Allow the tab to draw a right border if needed
2312 tabRect.Right() -= 1;
2314 // #129732# avoid degenerate cases which might lead to crashes
2315 if( tabRect.GetWidth() <= 1 || tabRect.GetHeight() <= 1 )
2316 return false;
2319 if( nType == CTRL_TAB_ITEM )
2321 if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) )
2322 return NWRenderPixmapToScreen( pixmap, pixmapRect );
2324 else
2326 if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) )
2327 return NWRenderPixmapToScreen( pixmap, pixmapRect );
2331 // gtk_widget_set_state( gWidgetData[m_nScreen].gNotebookWidget, stateType );
2333 pixmap = gdk_pixmap_new( NULL, pixmapRect.GetWidth(), pixmapRect.GetHeight(),
2334 GetX11SalData()->GetDisplay()->GetVisual( m_nScreen ).GetDepth() );
2335 GdkRectangle paintRect;
2336 paintRect.x = paintRect.y = 0;
2337 paintRect.width = pixmapRect.GetWidth();
2338 paintRect.height = pixmapRect.GetHeight();
2340 gtk_paint_flat_box( m_pWindow->style, pixmap, GTK_STATE_NORMAL,
2341 GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", 0, 0, -1, -1);
2343 NWSetWidgetState( gWidgetData[m_nScreen].gNotebookWidget, nState, stateType );
2345 switch( nType )
2347 case CTRL_TAB_BODY:
2348 break;
2350 case CTRL_FIXEDBORDER:
2351 case CTRL_TAB_PANE:
2352 gtk_paint_box_gap( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget,
2353 (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 );
2354 break;
2356 case CTRL_TAB_ITEM:
2357 stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE;
2359 gtk_paint_extension( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget,
2360 (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()),
2361 tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM );
2363 if ( nState & CTRL_STATE_SELECTED )
2365 gtk_paint_flat_box( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow,
2366 (char *)"base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 );
2368 break;
2370 default:
2371 break;
2374 // Crux seems to think it can make the pane without a left edge
2375 if ( nType == CTRL_FIXEDBORDER )
2376 pixmapRect.Move( 1, 0 );
2378 // cache data
2379 if( nType == CTRL_TAB_ITEM )
2380 aCacheItems.Fill( nType, nState, pixmapRect, pixmap );
2381 else
2382 aCachePage.Fill( nType, nState, pixmapRect, pixmap );
2384 BOOL bSuccess = NWRenderPixmapToScreen(pixmap, pixmapRect);
2385 g_object_unref( pixmap );
2386 return bSuccess;
2389 //-------------------------------------
2391 BOOL GtkSalGraphics::NWPaintGTKListBox( GdkDrawable* gdkDrawable,
2392 ControlType nType, ControlPart nPart,
2393 const Rectangle& rControlRectangle,
2394 const clipList& rClipList,
2395 ControlState nState,
2396 const ImplControlValue& aValue,
2397 SalControlHandle& rControlHandle, const OUString& rCaption )
2399 Rectangle pixmapRect;
2400 Rectangle widgetRect;
2401 Rectangle aIndicatorRect;
2402 GtkStateType stateType;
2403 GtkShadowType shadowType;
2404 gint bInteriorFocus;
2405 gint nFocusLineWidth;
2406 gint nFocusPadding;
2407 gint x,y;
2408 GdkRectangle clipRect;
2410 NWEnsureGTKButton( m_nScreen );
2411 NWEnsureGTKOptionMenu( m_nScreen );
2412 NWEnsureGTKScrolledWindow( m_nScreen );
2413 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2415 // Find the overall bounding rect of the buttons's drawing area,
2416 // plus its actual draw rect excluding adornment
2417 pixmapRect = rControlRectangle;
2418 if ( nPart == PART_WINDOW )
2420 // Make the widget a _bit_ bigger
2421 pixmapRect.SetPos( Point( pixmapRect.Left() - 1,
2422 pixmapRect.Top() - 1 ) );
2423 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2,
2424 pixmapRect.GetHeight() + 2 ) );
2427 widgetRect = pixmapRect;
2428 x = pixmapRect.Left();
2429 y = pixmapRect.Top();
2431 // set up references to correct drawable and cliprect
2432 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType );
2433 NWSetWidgetState( gWidgetData[m_nScreen].gOptionMenuWidget, nState, stateType );
2434 NWSetWidgetState( gWidgetData[m_nScreen].gScrolledWindowWidget, nState, stateType );
2436 if ( nPart != PART_WINDOW )
2438 gtk_widget_style_get( gWidgetData[m_nScreen].gOptionMenuWidget,
2439 "interior_focus", &bInteriorFocus,
2440 "focus_line_width", &nFocusLineWidth,
2441 "focus_padding", &nFocusPadding,
2442 (char *)NULL);
2445 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2447 clipRect.x = it->Left();
2448 clipRect.y = it->Top();
2449 clipRect.width = it->GetWidth();
2450 clipRect.height = it->GetHeight();
2452 if ( nPart != PART_WINDOW )
2454 // Listboxes must paint opaque since some themes have alpha-channel enabled bodies
2455 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE,
2456 &clipRect, m_pWindow, "base", x, y,
2457 pixmapRect.GetWidth(), pixmapRect.GetHeight() );
2458 gtk_paint_box( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect,
2459 gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenu",
2460 x+(widgetRect.Left() - pixmapRect.Left()),
2461 y+(widgetRect.Top() - pixmapRect.Top()),
2462 widgetRect.GetWidth(), widgetRect.GetHeight() );
2463 aIndicatorRect = NWGetListBoxIndicatorRect( m_nScreen, nType, nPart, widgetRect, nState,
2464 aValue, rControlHandle, rCaption );
2465 gtk_paint_tab( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect,
2466 gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenutab",
2467 x+(aIndicatorRect.Left() - pixmapRect.Left()),
2468 y+(aIndicatorRect.Top() - pixmapRect.Top()),
2469 aIndicatorRect.GetWidth(), aIndicatorRect.GetHeight() );
2471 else
2473 shadowType = GTK_SHADOW_IN;
2475 gtk_paint_shadow( gWidgetData[m_nScreen].gScrolledWindowWidget->style, gdkDrawable, GTK_STATE_NORMAL, shadowType,
2476 &clipRect, gWidgetData[m_nScreen].gScrolledWindowWidget, "scrolled_window",
2477 x+(widgetRect.Left() - pixmapRect.Left()), y+(widgetRect.Top() - pixmapRect.Top()),
2478 widgetRect.GetWidth(), widgetRect.GetHeight() );
2482 return( TRUE );
2485 BOOL GtkSalGraphics::NWPaintGTKToolbar(
2486 GdkDrawable* gdkDrawable,
2487 ControlType, ControlPart nPart,
2488 const Rectangle& rControlRectangle,
2489 const clipList& rClipList,
2490 ControlState nState, const ImplControlValue& aValue,
2491 SalControlHandle&, const OUString& )
2493 GtkStateType stateType;
2494 GtkShadowType shadowType;
2495 gint x, y, w, h;
2496 gint g_x=0, g_y=0, g_w=10, g_h=10;
2497 bool bPaintButton = true;
2498 GtkWidget* pButtonWidget = gWidgetData[m_nScreen].gToolbarButtonWidget;
2499 const gchar* pButtonDetail = "button";
2500 GdkRectangle clipRect;
2502 NWEnsureGTKToolbar( m_nScreen );
2503 if( nPart == PART_BUTTON ) // toolbar buttons cannot focus in gtk
2504 nState &= ~CTRL_STATE_FOCUSED;
2505 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2507 x = rControlRectangle.Left();
2508 y = rControlRectangle.Top();
2509 w = rControlRectangle.GetWidth();
2510 h = rControlRectangle.GetHeight();
2512 // handle toolbar
2513 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
2515 NWSetWidgetState( gWidgetData[m_nScreen].gToolbarWidget, nState, stateType );
2517 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE );
2518 if ( nState & CTRL_STATE_ENABLED )
2519 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE );
2521 if( nPart == PART_DRAW_BACKGROUND_HORZ )
2522 gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_HORIZONTAL );
2523 else
2524 gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_VERTICAL );
2526 // handle grip
2527 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
2529 NWSetWidgetState( gWidgetData[m_nScreen].gHandleBoxWidget, nState, stateType );
2531 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE );
2532 if ( nState & CTRL_STATE_ENABLED )
2533 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE );
2535 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(gWidgetData[m_nScreen].gHandleBoxWidget), shadowType );
2537 // evaluate grip rect
2538 ToolbarValue* pVal = (ToolbarValue*)aValue.getOptionalVal();
2539 if( pVal )
2541 g_x = pVal->maGripRect.Left();
2542 g_y = pVal->maGripRect.Top();
2543 g_w = pVal->maGripRect.GetWidth();
2544 g_h = pVal->maGripRect.GetHeight();
2547 // handle button
2548 else if( nPart == PART_BUTTON )
2550 bPaintButton =
2551 (GTK_BUTTON(pButtonWidget)->relief != GTK_RELIEF_NONE)
2552 || (nState & CTRL_STATE_PRESSED)
2553 || (nState & CTRL_STATE_ROLLOVER);
2554 if( aValue.getTristateVal() == BUTTONVALUE_ON )
2556 pButtonWidget = gWidgetData[m_nScreen].gToolbarToggleWidget;
2557 shadowType = GTK_SHADOW_IN;
2558 // special case stateType value for depressed toggle buttons
2559 // cf. gtk+/gtk/gtktogglebutton.c (gtk_toggle_button_update_state)
2560 if( ! (nState & (CTRL_STATE_PRESSED|CTRL_STATE_ROLLOVER)) )
2561 stateType = GTK_STATE_ACTIVE;
2562 pButtonDetail = "togglebutton";
2563 bPaintButton = true;
2566 NWSetWidgetState( pButtonWidget, nState, stateType );
2567 gtk_widget_ensure_style( pButtonWidget );
2570 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2572 clipRect.x = it->Left();
2573 clipRect.y = it->Top();
2574 clipRect.width = it->GetWidth();
2575 clipRect.height = it->GetHeight();
2577 // draw toolbar
2578 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT )
2580 gtk_paint_flat_box( gWidgetData[m_nScreen].gToolbarWidget->style,
2581 gdkDrawable,
2582 (GtkStateType)GTK_STATE_NORMAL,
2583 GTK_SHADOW_NONE,
2584 &clipRect,
2585 gWidgetData[m_nScreen].gToolbarWidget,
2586 "base",
2587 x, y, w, h );
2588 gtk_paint_box( gWidgetData[m_nScreen].gToolbarWidget->style,
2589 gdkDrawable,
2590 stateType,
2591 shadowType,
2592 &clipRect,
2593 gWidgetData[m_nScreen].gToolbarWidget,
2594 "toolbar",
2595 x, y, w, h );
2597 // draw grip
2598 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT )
2600 gtk_paint_handle( gWidgetData[m_nScreen].gHandleBoxWidget->style,
2601 gdkDrawable,
2602 GTK_STATE_NORMAL,
2603 GTK_SHADOW_OUT,
2604 &clipRect,
2605 gWidgetData[m_nScreen].gHandleBoxWidget,
2606 "handlebox",
2607 g_x, g_y, g_w, g_h,
2608 nPart == PART_THUMB_HORZ ?
2609 GTK_ORIENTATION_HORIZONTAL :
2610 GTK_ORIENTATION_VERTICAL
2613 // draw button
2614 else if( nPart == PART_BUTTON )
2616 if( bPaintButton )
2618 gtk_paint_box( pButtonWidget->style, gdkDrawable,
2619 stateType,
2620 shadowType,
2621 &clipRect,
2622 pButtonWidget, pButtonDetail, x, y, w, h );
2627 return( TRUE );
2630 //----
2632 BOOL GtkSalGraphics::NWPaintGTKMenubar(
2633 GdkDrawable* gdkDrawable,
2634 ControlType, ControlPart nPart,
2635 const Rectangle& rControlRectangle,
2636 const clipList& rClipList,
2637 ControlState nState, const ImplControlValue&,
2638 SalControlHandle&, const OUString& )
2640 GtkStateType stateType;
2641 GtkShadowType shadowType;
2642 GtkShadowType selected_shadow_type = GTK_SHADOW_OUT;
2643 gint x, y, w, h;
2644 GdkRectangle clipRect;
2646 NWEnsureGTKMenubar( m_nScreen );
2647 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2649 x = rControlRectangle.Left();
2650 y = rControlRectangle.Top();
2651 w = rControlRectangle.GetWidth();
2652 h = rControlRectangle.GetHeight();
2654 if( nPart == PART_MENU_ITEM )
2656 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) )
2658 gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenubarWidget,
2659 "selected_shadow_type", &selected_shadow_type,
2660 (char *)NULL);
2664 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2666 clipRect.x = it->Left();
2667 clipRect.y = it->Top();
2668 clipRect.width = it->GetWidth();
2669 clipRect.height = it->GetHeight();
2671 // handle Menubar
2672 if( nPart == PART_ENTIRE_CONTROL )
2674 NWSetWidgetState( gWidgetData[m_nScreen].gMenubarWidget, nState, stateType );
2676 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE );
2677 if ( nState & CTRL_STATE_ENABLED )
2678 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE );
2680 // #118704# for translucent menubar styles paint background first
2681 gtk_paint_flat_box( gWidgetData[m_nScreen].gMenubarWidget->style,
2682 gdkDrawable,
2683 GTK_STATE_NORMAL,
2684 GTK_SHADOW_NONE,
2685 &clipRect,
2686 GTK_WIDGET(m_pWindow),
2687 "base",
2688 x, y, w, h );
2689 gtk_paint_box( gWidgetData[m_nScreen].gMenubarWidget->style,
2690 gdkDrawable,
2691 stateType,
2692 shadowType,
2693 &clipRect,
2694 gWidgetData[m_nScreen].gMenubarWidget,
2695 "menubar",
2696 x, y, w, h );
2698 else if( nPart == PART_MENU_ITEM )
2700 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) )
2702 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenubarWidget->style,
2703 gdkDrawable,
2704 GTK_STATE_PRELIGHT,
2705 selected_shadow_type,
2706 &clipRect,
2707 gWidgetData[m_nScreen].gMenuItemMenubarWidget,
2708 "menuitem",
2709 x, y, w, h);
2714 return( TRUE );
2717 BOOL GtkSalGraphics::NWPaintGTKPopupMenu(
2718 GdkDrawable* gdkDrawable,
2719 ControlType, ControlPart nPart,
2720 const Rectangle& rControlRectangle,
2721 const clipList& rClipList,
2722 ControlState nState, const ImplControlValue&,
2723 SalControlHandle&, const OUString& )
2725 // #i50745# gtk does not draw disabled menu entries (and crux theme
2726 // even crashes), draw them using vcl functionality.
2727 if( nPart == PART_MENU_ITEM && ! (nState & CTRL_STATE_ENABLED) )
2728 return FALSE;
2730 GtkStateType stateType;
2731 GtkShadowType shadowType;
2732 GtkShadowType selected_shadow_type = GTK_SHADOW_OUT;
2733 gint x, y, w, h;
2734 GdkRectangle clipRect;
2736 NWEnsureGTKMenu( m_nScreen );
2737 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2739 x = rControlRectangle.Left();
2740 y = rControlRectangle.Top();
2741 w = rControlRectangle.GetWidth();
2742 h = rControlRectangle.GetHeight();
2744 if( nPart == PART_MENU_ITEM &&
2745 ( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) )
2747 gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenuWidget,
2748 "selected_shadow_type", &selected_shadow_type,
2749 (char *)NULL);
2752 NWSetWidgetState( gWidgetData[m_nScreen].gMenuWidget, nState, stateType );
2754 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE );
2755 if ( nState & CTRL_STATE_ENABLED )
2756 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE );
2758 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2760 clipRect.x = it->Left();
2761 clipRect.y = it->Top();
2762 clipRect.width = it->GetWidth();
2763 clipRect.height = it->GetHeight();
2765 if( nPart == PART_ENTIRE_CONTROL )
2767 // #118704# for translucent menubar styles paint background first
2768 gtk_paint_flat_box( gWidgetData[m_nScreen].gMenuWidget->style,
2769 gdkDrawable,
2770 GTK_STATE_NORMAL,
2771 GTK_SHADOW_NONE,
2772 &clipRect,
2773 GTK_WIDGET(m_pWindow),
2774 "base",
2775 x, y, w, h );
2776 gtk_paint_box( gWidgetData[m_nScreen].gMenuWidget->style,
2777 gdkDrawable,
2778 GTK_STATE_NORMAL,
2779 GTK_SHADOW_OUT,
2780 &clipRect,
2781 gWidgetData[m_nScreen].gMenuWidget,
2782 "menu",
2783 x, y, w, h );
2785 else if( nPart == PART_MENU_ITEM )
2787 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) )
2789 if( nState & CTRL_STATE_ENABLED )
2790 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenuWidget->style,
2791 gdkDrawable,
2792 GTK_STATE_PRELIGHT,
2793 selected_shadow_type,
2794 &clipRect,
2795 gWidgetData[m_nScreen].gMenuItemMenuWidget,
2796 "menuitem",
2797 x, y, w, h);
2800 else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK )
2802 GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ?
2803 gWidgetData[m_nScreen].gMenuItemCheckMenuWidget :
2804 gWidgetData[m_nScreen].gMenuItemRadioMenuWidget;
2806 GtkStateType nStateType = GTK_STATE_NORMAL;
2807 GtkShadowType nShadowType;
2809 if ( nState & CTRL_STATE_SELECTED )
2810 nStateType = GTK_STATE_PRELIGHT;
2812 NWSetWidgetState( pWidget, nState, nStateType );
2814 if ( nState & CTRL_STATE_PRESSED )
2815 nShadowType = GTK_SHADOW_IN;
2816 else
2817 nShadowType = GTK_SHADOW_OUT;
2819 if ( nPart == PART_MENU_ITEM_CHECK_MARK )
2821 gtk_paint_check( pWidget->style,
2822 gdkDrawable,
2823 nStateType,
2824 nShadowType,
2825 &clipRect,
2826 gWidgetData[m_nScreen].gMenuItemMenuWidget,
2827 "check",
2828 x, y, w, h );
2830 else
2832 gtk_paint_option( pWidget->style,
2833 gdkDrawable,
2834 nStateType,
2835 nShadowType,
2836 &clipRect,
2837 gWidgetData[m_nScreen].gMenuItemMenuWidget,
2838 "option",
2839 x, y, w, h );
2844 return( TRUE );
2847 BOOL GtkSalGraphics::NWPaintGTKTooltip(
2848 GdkDrawable* gdkDrawable,
2849 ControlType, ControlPart,
2850 const Rectangle& rControlRectangle,
2851 const clipList& rClipList,
2852 ControlState, const ImplControlValue&,
2853 SalControlHandle&, const OUString& )
2855 NWEnsureGTKTooltip( m_nScreen );
2857 gint x, y, w, h;
2858 GdkRectangle clipRect;
2860 x = rControlRectangle.Left();
2861 y = rControlRectangle.Top();
2862 w = rControlRectangle.GetWidth();
2863 h = rControlRectangle.GetHeight();
2865 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it )
2867 clipRect.x = it->Left();
2868 clipRect.y = it->Top();
2869 clipRect.width = it->GetWidth();
2870 clipRect.height = it->GetHeight();
2872 gtk_paint_flat_box( gWidgetData[m_nScreen].gTooltipPopup->style,
2873 gdkDrawable,
2874 GTK_STATE_NORMAL,
2875 GTK_SHADOW_OUT,
2876 &clipRect,
2877 gWidgetData[m_nScreen].gTooltipPopup,
2878 "tooltip",
2879 x, y, w, h );
2882 return( TRUE );
2885 BOOL GtkSalGraphics::NWPaintGTKListNode(
2886 GdkDrawable*,
2887 ControlType, ControlPart,
2888 const Rectangle& rControlRectangle,
2889 const clipList&,
2890 ControlState nState, const ImplControlValue& rValue,
2891 SalControlHandle&, const OUString& )
2893 NWEnsureGTKTreeView( m_nScreen );
2895 Rectangle aRect( rControlRectangle );
2896 aRect.Left() -= 2;
2897 aRect.Right() += 2;
2898 aRect.Top() -= 2;
2899 aRect.Bottom() += 2;
2900 gint w, h;
2901 w = aRect.GetWidth();
2902 h = aRect.GetHeight();
2904 GtkStateType stateType;
2905 GtkShadowType shadowType;
2906 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType );
2908 ButtonValue aButtonValue = rValue.getTristateVal();
2909 GtkExpanderStyle eStyle = GTK_EXPANDER_EXPANDED;
2911 switch( aButtonValue )
2913 case BUTTONVALUE_ON: eStyle = GTK_EXPANDER_EXPANDED;break;
2914 case BUTTONVALUE_OFF: eStyle = GTK_EXPANDER_COLLAPSED; break;
2915 default:
2916 break;
2919 GdkPixmap* pixmap = NWGetPixmapFromScreen( aRect );
2920 if( ! pixmap )
2921 return FALSE;
2923 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap );
2924 gtk_paint_expander( gWidgetData[m_nScreen].gTreeView->style,
2925 pixDrawable,
2926 stateType,
2927 NULL,
2928 gWidgetData[m_nScreen].gTreeView,
2929 "treeview",
2930 w/2, h/2,
2931 eStyle );
2933 BOOL bRet = NWRenderPixmapToScreen( pixmap, aRect );
2934 g_object_unref( pixmap );
2936 return bRet;
2939 BOOL GtkSalGraphics::NWPaintGTKProgress(
2940 GdkDrawable*,
2941 ControlType, ControlPart,
2942 const Rectangle& rControlRectangle,
2943 const clipList&,
2944 ControlState, const ImplControlValue& rValue,
2945 SalControlHandle&, const OUString& )
2947 NWEnsureGTKProgressBar( m_nScreen );
2949 gint w, h;
2950 w = rControlRectangle.GetWidth();
2951 h = rControlRectangle.GetHeight();
2953 long nProgressWidth = rValue.getNumericVal();
2955 GdkPixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) );
2956 if( ! pixmap )
2957 return FALSE;
2959 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap );
2961 // paint background
2962 gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style,
2963 pixDrawable,
2964 GTK_STATE_NORMAL,
2965 GTK_SHADOW_NONE,
2966 NULL,
2967 gWidgetData[m_nScreen].gProgressBar,
2968 "trough",
2969 0, 0, w, h );
2970 if( nProgressWidth > 0 )
2972 // paint progress
2973 if( Application::GetSettings().GetLayoutRTL() )
2975 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style,
2976 pixDrawable,
2977 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
2978 NULL,
2979 gWidgetData[m_nScreen].gProgressBar,
2980 "bar",
2981 w-nProgressWidth, 0, nProgressWidth, h
2984 else
2986 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style,
2987 pixDrawable,
2988 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
2989 NULL,
2990 gWidgetData[m_nScreen].gProgressBar,
2991 "bar",
2992 0, 0, nProgressWidth, h
2997 BOOL bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle );
2998 g_object_unref( pixmap );
3000 return bRet;
3003 //----
3005 static Rectangle NWGetListBoxButtonRect( int nScreen,
3006 ControlType,
3007 ControlPart nPart,
3008 Rectangle aAreaRect,
3009 ControlState,
3010 const ImplControlValue&,
3011 SalControlHandle&,
3012 const OUString& )
3014 Rectangle aPartRect;
3015 GtkRequisition *pIndicatorSize = NULL;
3016 GtkBorder *pIndicatorSpacing = NULL;
3017 gint width = 13; // GTK+ default
3018 gint right = 5; // GTK+ default
3019 gint nButtonAreaWidth = 0;
3020 gint xthickness = 0;
3022 NWEnsureGTKOptionMenu( nScreen );
3024 gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget,
3025 "indicator_size", &pIndicatorSize,
3026 "indicator_spacing",&pIndicatorSpacing, (char *)NULL);
3028 if ( pIndicatorSize )
3029 width = pIndicatorSize->width;
3031 if ( pIndicatorSpacing )
3032 right = pIndicatorSpacing->right;
3034 Size aPartSize( 0, aAreaRect.GetHeight() );
3035 Point aPartPos ( 0, aAreaRect.Top() );
3037 xthickness = gWidgetData[nScreen].gOptionMenuWidget->style->xthickness;
3038 nButtonAreaWidth = width + right + (xthickness * 2);
3039 switch( nPart )
3041 case PART_BUTTON_DOWN:
3042 aPartSize.Width() = nButtonAreaWidth;
3043 aPartPos.X() = aAreaRect.Left() + aAreaRect.GetWidth() - aPartSize.Width();
3044 break;
3046 case PART_SUB_EDIT:
3047 aPartSize.Width() = aAreaRect.GetWidth() - nButtonAreaWidth - xthickness;
3048 aPartPos.X() = aAreaRect.Left() + xthickness;
3049 break;
3051 default:
3052 aPartSize.Width() = aAreaRect.GetWidth();
3053 aPartPos.X() = aAreaRect.Left();
3054 break;
3056 aPartRect = Rectangle( aPartPos, aPartSize );
3058 if ( pIndicatorSize )
3059 gtk_requisition_free( pIndicatorSize );
3060 if ( pIndicatorSpacing )
3061 gtk_border_free( pIndicatorSpacing );
3063 return( aPartRect );
3066 //----
3068 static Rectangle NWGetListBoxIndicatorRect( int nScreen,
3069 ControlType,
3070 ControlPart,
3071 Rectangle aAreaRect,
3072 ControlState,
3073 const ImplControlValue&,
3074 SalControlHandle&,
3075 const OUString& )
3077 Rectangle aIndicatorRect;
3078 GtkRequisition *pIndicatorSize = NULL;
3079 GtkBorder *pIndicatorSpacing = NULL;
3080 gint width = 13; // GTK+ default
3081 gint height = 13; // GTK+ default
3082 gint right = 5; // GTK+ default
3084 NWEnsureGTKOptionMenu( nScreen );
3086 gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget,
3087 "indicator_size", &pIndicatorSize,
3088 "indicator_spacing",&pIndicatorSpacing, (char *)NULL);
3090 if ( pIndicatorSize )
3092 width = pIndicatorSize->width;
3093 height = pIndicatorSize->height;
3096 if ( pIndicatorSpacing )
3097 right = pIndicatorSpacing->right;
3099 aIndicatorRect.SetSize( Size( width, height ) );
3100 aIndicatorRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - width - right - gWidgetData[nScreen].gOptionMenuWidget->style->xthickness,
3101 aAreaRect.Top() + ((aAreaRect.GetHeight() - height) / 2) ) );
3103 // If height is odd, move the indicator down 1 pixel
3104 if ( aIndicatorRect.GetHeight() % 2 )
3105 aIndicatorRect.Move( 0, 1 );
3107 if ( pIndicatorSize )
3108 gtk_requisition_free( pIndicatorSize );
3109 if ( pIndicatorSpacing )
3110 gtk_border_free( pIndicatorSpacing );
3112 return( aIndicatorRect );
3115 static Rectangle NWGetToolbarRect( int nScreen,
3116 ControlType,
3117 ControlPart nPart,
3118 Rectangle aAreaRect,
3119 ControlState,
3120 const ImplControlValue&,
3121 SalControlHandle&,
3122 const OUString& )
3124 Rectangle aRet;
3126 if( nPart == PART_DRAW_BACKGROUND_HORZ ||
3127 nPart == PART_DRAW_BACKGROUND_VERT )
3128 aRet = aAreaRect;
3129 else if( nPart == PART_THUMB_HORZ )
3130 aRet = Rectangle( Point( 0, 0 ), Size( aAreaRect.GetWidth(), 10 ) );
3131 else if( nPart == PART_THUMB_VERT )
3132 aRet = Rectangle( Point( 0, 0 ), Size( 10, aAreaRect.GetHeight() ) );
3133 else if( nPart == PART_BUTTON )
3135 aRet = aAreaRect;
3137 NWEnsureGTKToolbar( nScreen );
3139 gint nMinWidth =
3140 2*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness
3141 + 1 // CHILD_SPACING constant, found in gtk_button.c
3142 + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness; // Murphy factor
3143 gint nMinHeight =
3144 2*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness
3145 + 1 // CHILD_SPACING constant, found in gtk_button.c
3146 + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness; // Murphy factor
3148 gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarButtonWidget );
3149 if( aAreaRect.GetWidth() < nMinWidth )
3150 aRet.Right() = aRet.Left() + nMinWidth;
3151 if( aAreaRect.GetHeight() < nMinHeight )
3152 aRet.Bottom() = aRet.Top() + nMinHeight;
3155 return aRet;
3158 /************************************************************************
3159 * helper for GtkSalFrame
3160 ************************************************************************/
3161 static inline Color getColor( const GdkColor& rCol )
3163 return Color( rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
3166 #if OSL_DEBUG_LEVEL > 1
3168 void printColor( const char* name, const GdkColor& rCol )
3170 std::fprintf( stderr, " %s = 0x%2x 0x%2x 0x%2x\n",
3171 name,
3172 rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
3175 void printStyleColors( GtkStyle* pStyle )
3177 static const char* pStates[] = { "NORMAL", "ACTIVE", "PRELIGHT", "SELECTED", "INSENSITIVE" };
3179 for( int i = 0; i < 5; i++ )
3181 std::fprintf( stderr, "state %s colors:\n", pStates[i] );
3182 printColor( "bg ", pStyle->bg[i] );
3183 printColor( "fg ", pStyle->fg[i] );
3184 printColor( "light ", pStyle->light[i] );
3185 printColor( "dark ", pStyle->dark[i] );
3186 printColor( "mid ", pStyle->mid[i] );
3187 printColor( "text ", pStyle->text[i] );
3188 printColor( "base ", pStyle->base[i] );
3189 printColor( "text_aa", pStyle->text_aa[i] );
3192 #endif
3194 void GtkSalGraphics::updateSettings( AllSettings& rSettings )
3196 // get the widgets in place
3197 NWEnsureGTKMenu( m_nScreen );
3198 NWEnsureGTKMenubar( m_nScreen );
3199 NWEnsureGTKScrollbars( m_nScreen );
3200 NWEnsureGTKEditBox( m_nScreen );
3201 NWEnsureGTKTooltip( m_nScreen );
3203 gtk_widget_ensure_style( m_pWindow );
3204 GtkStyle* pStyle = gtk_widget_get_style( m_pWindow );
3206 StyleSettings aStyleSet = rSettings.GetStyleSettings();
3208 #if OSL_DEBUG_LEVEL > 2
3209 printStyleColors( pStyle );
3210 #endif
3212 // text colors
3213 Color aTextColor = getColor( pStyle->text[GTK_STATE_NORMAL] );
3214 aStyleSet.SetDialogTextColor( aTextColor );
3215 aStyleSet.SetButtonTextColor( aTextColor );
3216 aStyleSet.SetRadioCheckTextColor( aTextColor );
3217 aStyleSet.SetGroupTextColor( aTextColor );
3218 aStyleSet.SetLabelTextColor( aTextColor );
3219 aStyleSet.SetInfoTextColor( aTextColor );
3220 aStyleSet.SetWindowTextColor( aTextColor );
3221 aStyleSet.SetFieldTextColor( aTextColor );
3223 // Tooltip colors
3224 GtkStyle* pTooltipStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gTooltipPopup );
3225 aTextColor = getColor( pTooltipStyle->fg[ GTK_STATE_NORMAL ] );
3226 aStyleSet.SetHelpTextColor( aTextColor );
3228 // mouse over text colors
3229 aTextColor = getColor( pStyle->fg[ GTK_STATE_PRELIGHT ] );
3230 aStyleSet.SetButtonRolloverTextColor( aTextColor );
3231 aStyleSet.SetFieldRolloverTextColor( aTextColor );
3233 // background colors
3234 Color aBackColor = getColor( pStyle->bg[GTK_STATE_NORMAL] );
3235 Color aBackFieldColor = getColor( pStyle->base[ GTK_STATE_NORMAL ] );
3236 aStyleSet.Set3DColors( aBackColor );
3237 aStyleSet.SetFaceColor( aBackColor );
3238 aStyleSet.SetDialogColor( aBackColor );
3239 aStyleSet.SetWorkspaceColor( aBackColor );
3240 aStyleSet.SetFieldColor( aBackFieldColor );
3241 aStyleSet.SetWindowColor( aBackFieldColor );
3242 // aStyleSet.SetHelpColor( aBackColor );
3243 // ancient wisdom tells us a mystic algorithm how to set checked color
3244 if( aBackColor == COL_LIGHTGRAY )
3245 aStyleSet.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
3246 else
3248 Color aColor2 = aStyleSet.GetLightColor();
3249 Color aCheck( (BYTE)(((USHORT)aBackColor.GetRed()+(USHORT)aColor2.GetRed())/2),
3250 (BYTE)(((USHORT)aBackColor.GetGreen()+(USHORT)aColor2.GetGreen())/2),
3251 (BYTE)(((USHORT)aBackColor.GetBlue()+(USHORT)aColor2.GetBlue())/2)
3253 aStyleSet.SetCheckedColor( aCheck );
3256 // highlighting colors
3257 Color aHighlightColor = getColor( pStyle->base[GTK_STATE_SELECTED] );
3258 Color aHighlightTextColor = getColor( pStyle->text[GTK_STATE_SELECTED] );
3259 aStyleSet.SetHighlightColor( aHighlightColor );
3260 aStyleSet.SetHighlightTextColor( aHighlightTextColor );
3262 // hyperlink colors
3263 GdkColor *link_color = NULL;
3264 gtk_widget_style_get (m_pWindow, "link-color", &link_color, NULL);
3265 if (link_color)
3267 aStyleSet.SetLinkColor(getColor(*link_color));
3268 gdk_color_free (link_color);
3269 link_color = NULL;
3271 gtk_widget_style_get (m_pWindow, "visited-link-color", &link_color, NULL);
3272 if (link_color)
3274 aStyleSet.SetVisitedLinkColor(getColor(*link_color));
3275 gdk_color_free (link_color);
3278 // Tab colors
3279 aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color.
3280 Color aSelectedBackColor = getColor( pStyle->bg[GTK_STATE_ACTIVE] );
3281 aStyleSet.SetInactiveTabColor( aSelectedBackColor );
3283 // menu disabled entries handling
3284 aStyleSet.SetSkipDisabledInMenus( TRUE );
3285 // menu colors
3286 GtkStyle* pMenuStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gMenuWidget );
3287 GtkStyle* pMenuItemStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenuItemMenuWidget );
3288 GtkStyle* pMenubarStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenubarWidget );
3289 GtkStyle* pMenuTextStyle = gtk_rc_get_style( gtk_bin_get_child( GTK_BIN(gWidgetData[m_nScreen].gMenuItemMenuWidget) ) );
3291 aBackColor = getColor( pMenubarStyle->bg[GTK_STATE_NORMAL] );
3292 aStyleSet.SetMenuBarColor( aBackColor );
3293 aBackColor = getColor( pMenuStyle->bg[GTK_STATE_NORMAL] );
3294 aTextColor = getColor( pMenuTextStyle->text[GTK_STATE_NORMAL] );
3295 aStyleSet.SetMenuColor( aBackColor );
3296 aStyleSet.SetMenuTextColor( aTextColor );
3298 aTextColor = getColor( pMenubarStyle->text[GTK_STATE_NORMAL] );
3299 aStyleSet.SetMenuBarTextColor( aTextColor );
3301 #if OSL_DEBUG_LEVEL > 1
3302 std::fprintf( stderr, "==\n" );
3303 std::fprintf( stderr, "MenuColor = %x (%d)\n", (int)aStyleSet.GetMenuColor().GetColor(), aStyleSet.GetMenuColor().GetLuminance() );
3304 std::fprintf( stderr, "MenuTextColor = %x (%d)\n", (int)aStyleSet.GetMenuTextColor().GetColor(), aStyleSet.GetMenuTextColor().GetLuminance() );
3305 std::fprintf( stderr, "MenuBarColor = %x (%d)\n", (int)aStyleSet.GetMenuBarColor().GetColor(), aStyleSet.GetMenuBarColor().GetLuminance() );
3306 std::fprintf( stderr, "MenuBarTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarTextColor().GetColor(), aStyleSet.GetMenuBarTextColor().GetLuminance() );
3307 std::fprintf( stderr, "LightColor = %x (%d)\n", (int)aStyleSet.GetLightColor().GetColor(), aStyleSet.GetLightColor().GetLuminance() );
3308 std::fprintf( stderr, "ShadowColor = %x (%d)\n", (int)aStyleSet.GetShadowColor().GetColor(), aStyleSet.GetShadowColor().GetLuminance() );
3309 #endif
3311 // Awful hack for menu separators in the Sonar and similar themes.
3312 // If the menu color is not too dark, and the menu text color is lighter,
3313 // make the "light" color lighter than the menu color and the "shadow"
3314 // color darker than it.
3315 if ( aStyleSet.GetMenuColor().GetLuminance() >= 32 &&
3316 aStyleSet.GetMenuColor().GetLuminance() <= aStyleSet.GetMenuTextColor().GetLuminance() )
3318 Color temp = aStyleSet.GetMenuColor();
3319 temp.IncreaseLuminance( 8 );
3320 aStyleSet.SetLightColor( temp );
3321 temp = aStyleSet.GetMenuColor();
3322 temp.DecreaseLuminance( 16 );
3323 aStyleSet.SetShadowColor( temp );
3326 aHighlightColor = getColor( pMenuItemStyle->bg[ GTK_STATE_SELECTED ] );
3327 aHighlightTextColor = getColor( pMenuTextStyle->fg[ GTK_STATE_PRELIGHT ] );
3328 if( aHighlightColor == aHighlightTextColor )
3329 aHighlightTextColor = (aHighlightColor.GetLuminance() < 128) ? Color( COL_WHITE ) : Color( COL_BLACK );
3330 aStyleSet.SetMenuHighlightColor( aHighlightColor );
3331 aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
3333 // UI font
3334 OString aFamily = pango_font_description_get_family( pStyle->font_desc );
3335 int nPangoHeight = pango_font_description_get_size( pStyle->font_desc );
3336 PangoStyle eStyle = pango_font_description_get_style( pStyle->font_desc );
3337 PangoWeight eWeight = pango_font_description_get_weight( pStyle->font_desc );
3338 PangoStretch eStretch = pango_font_description_get_stretch( pStyle->font_desc );
3340 psp::FastPrintFontInfo aInfo;
3341 // set family name
3342 aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
3343 // set italic
3344 switch( eStyle )
3346 case PANGO_STYLE_NORMAL: aInfo.m_eItalic = psp::italic::Upright;break;
3347 case PANGO_STYLE_ITALIC: aInfo.m_eItalic = psp::italic::Italic;break;
3348 case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = psp::italic::Oblique;break;
3350 // set weight
3351 if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
3352 aInfo.m_eWeight = psp::weight::UltraLight;
3353 else if( eWeight <= PANGO_WEIGHT_LIGHT )
3354 aInfo.m_eWeight = psp::weight::Light;
3355 else if( eWeight <= PANGO_WEIGHT_NORMAL )
3356 aInfo.m_eWeight = psp::weight::Normal;
3357 else if( eWeight <= PANGO_WEIGHT_BOLD )
3358 aInfo.m_eWeight = psp::weight::Bold;
3359 else
3360 aInfo.m_eWeight = psp::weight::UltraBold;
3361 // set width
3362 switch( eStretch )
3364 case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = psp::width::UltraCondensed;break;
3365 case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = psp::width::ExtraCondensed;break;
3366 case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = psp::width::Condensed;break;
3367 case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = psp::width::SemiCondensed;break;
3368 case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = psp::width::Normal;break;
3369 case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = psp::width::SemiExpanded;break;
3370 case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = psp::width::Expanded;break;
3371 case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = psp::width::ExtraExpanded;break;
3372 case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = psp::width::UltraExpanded;break;
3375 #if OSL_DEBUG_LEVEL > 1
3376 std::fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() );
3377 #endif
3379 // match font to e.g. resolve "Sans"
3380 psp::PrintFontManager::get().matchFont( aInfo, rSettings.GetUILocale() );
3382 #if OSL_DEBUG_LEVEL > 1
3383 std::fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
3384 aInfo.m_nID != 0 ? "succeeded" : "failed",
3385 OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
3386 #endif
3388 sal_Int32 nDispDPIY = GetDisplay()->GetResolution().B();
3389 int nPointHeight = 0;
3390 static gboolean(*pAbso)(const PangoFontDescription*) =
3391 (gboolean(*)(const PangoFontDescription*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "pango_font_description_get_size_is_absolute" );
3393 if( pAbso && pAbso( pStyle->font_desc ) )
3394 nPointHeight = (nPangoHeight * 72 + nDispDPIY*PANGO_SCALE/2) / (nDispDPIY * PANGO_SCALE);
3395 else
3396 nPointHeight = nPangoHeight/PANGO_SCALE;
3398 Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
3399 if( aInfo.m_eWeight != psp::weight::Unknown )
3400 aFont.SetWeight( PspGraphics::ToFontWeight( aInfo.m_eWeight ) );
3401 if( aInfo.m_eWidth != psp::width::Unknown )
3402 aFont.SetWidthType( PspGraphics::ToFontWidth( aInfo.m_eWidth ) );
3403 if( aInfo.m_eItalic != psp::italic::Unknown )
3404 aFont.SetItalic( PspGraphics::ToFontItalic( aInfo.m_eItalic ) );
3405 if( aInfo.m_ePitch != psp::pitch::Unknown )
3406 aFont.SetPitch( PspGraphics::ToFontPitch( aInfo.m_ePitch ) );
3408 aStyleSet.SetAppFont( aFont );
3409 aStyleSet.SetHelpFont( aFont );
3410 aStyleSet.SetTitleFont( aFont );
3411 aStyleSet.SetFloatTitleFont( aFont );
3412 aStyleSet.SetMenuFont( aFont );
3413 aStyleSet.SetToolFont( aFont );
3414 aStyleSet.SetLabelFont( aFont );
3415 aStyleSet.SetInfoFont( aFont );
3416 aStyleSet.SetRadioCheckFont( aFont );
3417 aStyleSet.SetPushButtonFont( aFont );
3418 aStyleSet.SetFieldFont( aFont );
3419 aStyleSet.SetIconFont( aFont );
3420 aStyleSet.SetGroupFont( aFont );
3422 // get cursor blink time
3423 GtkSettings *pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gEditBoxWidget );
3424 gboolean blink = false;
3426 g_object_get( pSettings, "gtk-cursor-blink", &blink, (char *)NULL );
3427 if( blink )
3429 gint blink_time = STYLE_CURSOR_NOBLINKTIME;
3430 g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, (char *)NULL );
3431 // set the blink_time if there is a setting and it is reasonable
3432 // else leave the default value
3433 if( blink_time > 100 && blink_time != gint(STYLE_CURSOR_NOBLINKTIME) )
3434 aStyleSet.SetCursorBlinkTime( blink_time/2 );
3436 else
3437 aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
3439 gboolean showmenuicons = true;
3440 pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gImageMenuItem );
3441 g_object_get( pSettings, "gtk-menu-images", &showmenuicons, (char *)NULL );
3442 aStyleSet.SetUseImagesInMenus( showmenuicons );
3444 // set scrollbar settings
3445 gint slider_width = 14;
3446 gint trough_border = 1;
3447 gint min_slider_length = 21;
3449 // Grab some button style attributes
3450 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget,
3451 "slider-width", &slider_width,
3452 "trough-border", &trough_border,
3453 "min-slider-length", &min_slider_length,
3454 (char *)NULL );
3455 gint magic = trough_border ? 1 : 0;
3456 aStyleSet.SetScrollBarSize( slider_width + 2*trough_border );
3457 aStyleSet.SetMinThumbSize( min_slider_length - magic );
3459 // preferred icon style
3460 gchar* pIconThemeName = NULL;
3461 g_object_get( gtk_settings_get_default(), "gtk-icon-theme-name", &pIconThemeName, (char *)NULL );
3462 aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii(pIconThemeName) );
3463 g_free (pIconThemeName);
3465 // FIXME: need some way of fetching toolbar icon size.
3466 // aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_SMALL );
3468 /* #i35482# do not override HC mode per force
3469 // #i59364# high contrast mode
3470 bool bHC = ( aStyleSet.GetFaceColor().IsDark() ||
3471 aStyleSet.GetWindowColor().IsDark() );
3472 aStyleSet.SetHighContrastMode( bHC );
3475 // finally update the collected settings
3476 rSettings.SetStyleSettings( aStyleSet );
3478 #if OSL_DEBUG_LEVEL > 1
3480 GtkSettings* pGtkSettings = gtk_settings_get_default();
3481 GValue aValue;
3482 memset( &aValue, 0, sizeof(GValue) );
3483 g_value_init( &aValue, G_TYPE_STRING );
3484 g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue );
3485 const gchar* pThemeName = g_value_get_string( &aValue );
3486 std::fprintf( stderr, "Theme name is \"%s\"\n", pThemeName );
3487 g_value_unset( &aValue );
3489 #endif
3490 GtkSettings* pGtkSettings = gtk_settings_get_default();
3491 GValue aValue;
3492 memset( &aValue, 0, sizeof(GValue) );
3493 g_value_init( &aValue, G_TYPE_STRING );
3494 g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue );
3495 const gchar* pThemeName = g_value_get_string( &aValue );
3497 // default behaviour
3498 bNeedPixmapPaint = bGlobalNeedPixmapPaint;
3499 bToolbarGripWorkaround = false;
3500 bNeedButtonStyleAsEditBackgroundWorkaround = false;
3502 // setup some workarounds for "blueprint" theme
3503 if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 )
3505 bNeedButtonStyleAsEditBackgroundWorkaround = true;
3506 if( GetX11SalData()->GetDisplay()->GetServerVendor() == vendor_sun )
3508 // #i52570#, #i61532# workaround a weird paint issue;
3509 // on a Sunray Xserver sometimes painting buttons and edits
3510 // won't work when using the blueprint theme
3511 // not reproducible with simpler programs or other themes
3512 if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 )
3514 bNeedPixmapPaint = true;
3515 bToolbarGripWorkaround = true;
3519 // clean up
3520 g_value_unset( &aValue );
3524 /************************************************************************
3525 * Create a GdkPixmap filled with the contents of an area of an Xlib window
3526 ************************************************************************/
3528 GdkPixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect )
3530 // Create a new pixmap to hold the composite of the window background and the control
3531 GdkPixmap * pPixmap = gdk_pixmap_new( GDK_DRAWABLE(GetGdkWindow()), srcRect.GetWidth(), srcRect.GetHeight(), -1 );
3532 GdkGC * pPixmapGC = gdk_gc_new( pPixmap );
3534 if( !pPixmap || !pPixmapGC )
3536 if ( pPixmap )
3537 g_object_unref( pPixmap );
3538 if ( pPixmapGC )
3539 g_object_unref( pPixmapGC );
3540 std::fprintf( stderr, "salnativewidgets-gtk.cxx: could not get valid pixmap from screen\n" );
3541 return( NULL );
3544 // Copy the background of the screen into a composite pixmap
3545 CopyScreenArea( GetXDisplay(),
3546 GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(),
3547 gdk_x11_drawable_get_xid(pPixmap),
3548 gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ),
3549 gdk_drawable_get_depth( GDK_DRAWABLE( pPixmap ) ),
3550 gdk_x11_gc_get_xgc(pPixmapGC),
3551 srcRect.Left(), srcRect.Top(), srcRect.GetWidth(), srcRect.GetHeight(), 0, 0 );
3553 g_object_unref( pPixmapGC );
3554 return( pPixmap );
3560 /************************************************************************
3561 * Copy an alpha pixmap to screen using a gc with clipping
3562 ************************************************************************/
3564 BOOL GtkSalGraphics::NWRenderPixmapToScreen( GdkPixmap* pPixmap, Rectangle dstRect )
3566 // The GC can't be null, otherwise we'd have no clip region
3567 if( SelectFont() == NULL )
3569 std::fprintf(stderr, "salnativewidgets.cxx: no valid GC\n" );
3570 return( FALSE );
3573 if ( !pPixmap )
3574 return( FALSE );
3576 // Copy the background of the screen into a composite pixmap
3577 CopyScreenArea( GetXDisplay(),
3578 GDK_DRAWABLE_XID(pPixmap),
3579 gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ),
3580 gdk_drawable_get_depth( GDK_DRAWABLE(pPixmap) ),
3581 GetDrawable(), m_nScreen, GetVisual().GetDepth(),
3582 SelectFont(),
3583 0, 0, dstRect.GetWidth(), dstRect.GetHeight(), dstRect.Left(), dstRect.Top() );
3585 return( TRUE );
3589 /************************************************************************
3590 * State conversion
3591 ************************************************************************/
3592 static void NWConvertVCLStateToGTKState( ControlState nVCLState,
3593 GtkStateType* nGTKState, GtkShadowType* nGTKShadow )
3595 *nGTKShadow = GTK_SHADOW_OUT;
3596 *nGTKState = GTK_STATE_INSENSITIVE;
3598 if ( nVCLState & CTRL_STATE_ENABLED )
3600 if ( nVCLState & CTRL_STATE_PRESSED )
3602 *nGTKState = GTK_STATE_ACTIVE;
3603 *nGTKShadow = GTK_SHADOW_IN;
3605 else if ( nVCLState & CTRL_STATE_ROLLOVER )
3607 *nGTKState = GTK_STATE_PRELIGHT;
3608 *nGTKShadow = GTK_SHADOW_OUT;
3610 else
3612 *nGTKState = GTK_STATE_NORMAL;
3613 *nGTKShadow = GTK_SHADOW_OUT;
3618 /************************************************************************
3619 * Set widget flags
3620 ************************************************************************/
3621 static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState )
3623 // Set to default state, then build up from there
3624 GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_DEFAULT );
3625 GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_FOCUS );
3626 GTK_WIDGET_UNSET_FLAGS( widget, GTK_SENSITIVE );
3627 GTK_WIDGET_SET_FLAGS( widget, gWidgetDefaultFlags[(long)widget] );
3629 if ( nState & CTRL_STATE_DEFAULT )
3630 GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_DEFAULT );
3631 if ( !GTK_IS_TOGGLE_BUTTON(widget) && (nState & CTRL_STATE_FOCUSED) )
3632 GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_FOCUS );
3633 if ( nState & CTRL_STATE_ENABLED )
3634 GTK_WIDGET_SET_FLAGS( widget, GTK_SENSITIVE );
3635 gtk_widget_set_state( widget, nGtkState );
3638 /************************************************************************
3639 * Widget ensure functions - make sure cached objects are valid
3640 ************************************************************************/
3642 //-------------------------------------
3644 static void NWAddWidgetToCacheWindow( GtkWidget* widget, int nScreen )
3646 NWFWidgetData& rData = gWidgetData[nScreen];
3647 if ( !rData.gCacheWindow || !rData.gDumbContainer )
3649 if ( !rData.gCacheWindow )
3651 rData.gCacheWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3652 GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen );
3653 if( pScreen )
3654 gtk_window_set_screen( GTK_WINDOW(rData.gCacheWindow), pScreen );
3656 if ( !rData.gDumbContainer )
3657 rData.gDumbContainer = gtk_fixed_new();
3658 gtk_container_add( GTK_CONTAINER(rData.gCacheWindow), rData.gDumbContainer );
3659 gtk_widget_realize( rData.gDumbContainer );
3660 gtk_widget_realize( rData.gCacheWindow );
3663 gtk_container_add( GTK_CONTAINER(rData.gDumbContainer), widget );
3664 gtk_widget_realize( widget );
3665 gtk_widget_ensure_style( widget );
3667 // Store widget's default flags
3668 gWidgetDefaultFlags[ (long)widget ] = GTK_WIDGET_FLAGS( widget );
3671 //-------------------------------------
3673 static void NWEnsureGTKButton( int nScreen )
3675 if ( !gWidgetData[nScreen].gBtnWidget )
3677 gWidgetData[nScreen].gBtnWidget = gtk_button_new_with_label( "" );
3678 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gBtnWidget, nScreen );
3682 //-------------------------------------
3684 static void NWEnsureGTKRadio( int nScreen )
3686 if ( !gWidgetData[nScreen].gRadioWidget || !gWidgetData[nScreen].gRadioWidgetSibling )
3688 gWidgetData[nScreen].gRadioWidget = gtk_radio_button_new( NULL );
3689 gWidgetData[nScreen].gRadioWidgetSibling = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(gWidgetData[nScreen].gRadioWidget) );
3690 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidget, nScreen );
3691 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidgetSibling, nScreen );
3695 //-------------------------------------
3697 static void NWEnsureGTKCheck( int nScreen )
3699 if ( !gWidgetData[nScreen].gCheckWidget )
3701 gWidgetData[nScreen].gCheckWidget = gtk_check_button_new();
3702 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gCheckWidget, nScreen );
3706 //-------------------------------------
3708 static void NWEnsureGTKScrollbars( int nScreen )
3710 if ( !gWidgetData[nScreen].gScrollHorizWidget )
3712 gWidgetData[nScreen].gScrollHorizWidget = gtk_hscrollbar_new( NULL );
3713 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollHorizWidget, nScreen );
3716 if ( !gWidgetData[nScreen].gScrollVertWidget )
3718 gWidgetData[nScreen].gScrollVertWidget = gtk_vscrollbar_new( NULL );
3719 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollVertWidget, nScreen );
3723 //-------------------------------------
3725 static void NWEnsureGTKArrow( int nScreen )
3727 if ( !gWidgetData[nScreen].gArrowWidget || !gWidgetData[nScreen].gDropdownWidget )
3729 gWidgetData[nScreen].gDropdownWidget = gtk_toggle_button_new();
3730 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gDropdownWidget, nScreen );
3731 gWidgetData[nScreen].gArrowWidget = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
3732 gtk_container_add( GTK_CONTAINER(gWidgetData[nScreen].gDropdownWidget), gWidgetData[nScreen].gArrowWidget );
3733 gtk_widget_set_rc_style( gWidgetData[nScreen].gArrowWidget );
3734 gtk_widget_realize( gWidgetData[nScreen].gArrowWidget );
3738 //-------------------------------------
3740 static void NWEnsureGTKEditBox( int nScreen )
3742 if ( !gWidgetData[nScreen].gEditBoxWidget )
3744 gWidgetData[nScreen].gEditBoxWidget = gtk_entry_new();
3745 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gEditBoxWidget, nScreen );
3749 //-------------------------------------
3751 static void NWEnsureGTKSpinButton( int nScreen )
3753 if ( !gWidgetData[nScreen].gSpinButtonWidget )
3755 GtkAdjustment *adj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 1, 1, 1, 0) );
3756 gWidgetData[nScreen].gSpinButtonWidget = gtk_spin_button_new( adj, 1, 2 );
3758 //Setting non-editable means it doesn't blink, so there's no timeouts
3759 //running around to nobble us
3760 gtk_editable_set_editable(GTK_EDITABLE(gWidgetData[nScreen].gSpinButtonWidget), false);
3762 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gSpinButtonWidget, nScreen );
3766 //-------------------------------------
3768 static void NWEnsureGTKNotebook( int nScreen )
3770 if ( !gWidgetData[nScreen].gNotebookWidget )
3772 gWidgetData[nScreen].gNotebookWidget = gtk_notebook_new();
3773 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gNotebookWidget, nScreen );
3777 //-------------------------------------
3779 static void NWEnsureGTKOptionMenu( int nScreen )
3781 if ( !gWidgetData[nScreen].gOptionMenuWidget )
3783 gWidgetData[nScreen].gOptionMenuWidget = gtk_option_menu_new();
3784 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gOptionMenuWidget, nScreen );
3788 //-------------------------------------
3790 static void NWEnsureGTKCombo( int nScreen )
3792 if ( !gWidgetData[nScreen].gComboWidget )
3794 gWidgetData[nScreen].gComboWidget = gtk_combo_new();
3796 // #i59129# Setting non-editable means it doesn't blink, so
3797 // there are no timeouts running around to nobble us
3798 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry), false);
3800 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gComboWidget, nScreen );
3801 // Must realize the ComboBox's children, since GTK
3802 // does not do this for us in GtkCombo::gtk_widget_realize()
3803 gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->button );
3804 gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry );
3808 //-------------------------------------
3810 static void NWEnsureGTKScrolledWindow( int nScreen )
3812 if ( !gWidgetData[nScreen].gScrolledWindowWidget )
3814 GtkAdjustment *hadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
3815 GtkAdjustment *vadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) );
3817 gWidgetData[nScreen].gScrolledWindowWidget = gtk_scrolled_window_new( hadj, vadj );
3818 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrolledWindowWidget, nScreen );
3822 //-------------------------------------
3824 static void NWEnsureGTKToolbar( int nScreen )
3826 if( !gWidgetData[nScreen].gToolbarWidget )
3828 gWidgetData[nScreen].gToolbarWidget = gtk_toolbar_new();
3829 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarWidget, nScreen );
3830 gWidgetData[nScreen].gToolbarButtonWidget = gtk_button_new();
3831 gWidgetData[nScreen].gToolbarToggleWidget = gtk_toggle_button_new();
3833 GtkReliefStyle aRelief = GTK_RELIEF_NORMAL;
3834 gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarWidget );
3835 gtk_widget_style_get( gWidgetData[nScreen].gToolbarWidget,
3836 "button_relief", &aRelief,
3837 (char *)NULL);
3839 gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarButtonWidget), aRelief );
3840 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_FOCUS );
3841 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_DEFAULT );
3842 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarButtonWidget, nScreen );
3844 gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarToggleWidget), aRelief );
3845 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_FOCUS );
3846 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_DEFAULT );
3847 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarToggleWidget, nScreen );
3849 if( ! gWidgetData[nScreen].gHandleBoxWidget )
3851 gWidgetData[nScreen].gHandleBoxWidget = gtk_handle_box_new();
3852 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHandleBoxWidget, nScreen );
3856 //-------------------------------------
3858 static void NWEnsureGTKMenubar( int nScreen )
3860 if( !gWidgetData[nScreen].gMenubarWidget )
3862 gWidgetData[nScreen].gMenubarWidget = gtk_menu_bar_new();
3863 gWidgetData[nScreen].gMenuItemMenubarWidget = gtk_menu_item_new_with_label( "b" );
3864 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenubarWidget ), gWidgetData[nScreen].gMenuItemMenubarWidget );
3865 gtk_widget_show( gWidgetData[nScreen].gMenuItemMenubarWidget );
3866 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gMenubarWidget, nScreen );
3867 gtk_widget_show( gWidgetData[nScreen].gMenubarWidget );
3869 // do what NWAddWidgetToCacheWindow does except adding to def container
3870 gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenubarWidget );
3871 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenubarWidget );
3873 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenubarWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenubarWidget );
3877 static void NWEnsureGTKMenu( int nScreen )
3879 if( !gWidgetData[nScreen].gMenuWidget )
3881 gWidgetData[nScreen].gMenuWidget = gtk_menu_new();
3882 gWidgetData[nScreen].gMenuItemMenuWidget = gtk_menu_item_new_with_label( "b" );
3883 gWidgetData[nScreen].gMenuItemCheckMenuWidget = gtk_check_menu_item_new_with_label( "b" );
3884 gWidgetData[nScreen].gMenuItemRadioMenuWidget = gtk_radio_menu_item_new_with_label( NULL, "b" );
3885 gWidgetData[nScreen].gImageMenuItem = gtk_image_menu_item_new();
3887 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemMenuWidget );
3888 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemCheckMenuWidget );
3889 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemRadioMenuWidget );
3890 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gImageMenuItem );
3892 // do what NWAddWidgetToCacheWindow does except adding to def container
3893 gtk_widget_realize( gWidgetData[nScreen].gMenuWidget );
3894 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuWidget );
3896 gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenuWidget );
3897 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenuWidget );
3899 gtk_widget_realize( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
3900 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
3902 gtk_widget_realize( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
3903 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
3905 gtk_widget_realize( gWidgetData[nScreen].gImageMenuItem );
3906 gtk_widget_ensure_style( gWidgetData[nScreen].gImageMenuItem );
3908 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuWidget );
3909 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenuWidget );
3910 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemCheckMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemCheckMenuWidget );
3911 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemRadioMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemRadioMenuWidget );
3912 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gImageMenuItem ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gImageMenuItem );
3916 static void NWEnsureGTKTooltip( int nScreen )
3918 if( !gWidgetData[nScreen].gTooltipPopup )
3920 gWidgetData[nScreen].gTooltipPopup = gtk_window_new (GTK_WINDOW_POPUP);
3921 GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen );
3922 if( pScreen )
3923 gtk_window_set_screen( GTK_WINDOW(gWidgetData[nScreen].gTooltipPopup), pScreen );
3924 gtk_widget_set_name( gWidgetData[nScreen].gTooltipPopup, "gtk-tooltips");
3925 gtk_widget_realize( gWidgetData[nScreen].gTooltipPopup );
3926 gtk_widget_ensure_style( gWidgetData[nScreen].gTooltipPopup );
3930 static void NWEnsureGTKProgressBar( int nScreen )
3932 if( !gWidgetData[nScreen].gProgressBar )
3934 gWidgetData[nScreen].gProgressBar = gtk_progress_bar_new ();
3935 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gProgressBar, nScreen );
3939 static void NWEnsureGTKTreeView( int nScreen )
3941 if( !gWidgetData[nScreen].gTreeView )
3943 gWidgetData[nScreen].gTreeView = gtk_tree_view_new ();
3944 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gTreeView, nScreen );