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