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