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 
10 #include <sal/config.h>
11 #include <sal/log.hxx>
12 #include <osl/module.h>
13 
14 #include <config_cairo_canvas.h>
15 
16 #include <unx/gtk/gtkframe.hxx>
17 #include <unx/gtk/gtkdata.hxx>
18 #include <unx/gtk/gtkinst.hxx>
19 #include <unx/gtk/gtkgdi.hxx>
20 #include <unx/gtk/gtkbackend.hxx>
21 #include <vcl/decoview.hxx>
22 #include <vcl/settings.hxx>
23 #include <unx/fontmanager.hxx>
24 
25 #include "cairo_gtk3_cairo.hxx"
26 #include <boost/optional.hpp>
27 
28 GtkStyleContext* GtkSalGraphics::mpWindowStyle = nullptr;
29 GtkStyleContext* GtkSalGraphics::mpButtonStyle = nullptr;
30 GtkStyleContext* GtkSalGraphics::mpLinkButtonStyle = nullptr;
31 GtkStyleContext* GtkSalGraphics::mpEntryStyle = nullptr;
32 GtkStyleContext* GtkSalGraphics::mpTextViewStyle = nullptr;
33 GtkStyleContext* GtkSalGraphics::mpVScrollbarStyle = nullptr;
34 GtkStyleContext* GtkSalGraphics::mpVScrollbarContentsStyle = nullptr;
35 GtkStyleContext* GtkSalGraphics::mpVScrollbarTroughStyle = nullptr;
36 GtkStyleContext* GtkSalGraphics::mpVScrollbarSliderStyle = nullptr;
37 GtkStyleContext* GtkSalGraphics::mpVScrollbarButtonStyle = nullptr;
38 GtkStyleContext* GtkSalGraphics::mpHScrollbarStyle = nullptr;
39 GtkStyleContext* GtkSalGraphics::mpHScrollbarContentsStyle = nullptr;
40 GtkStyleContext* GtkSalGraphics::mpHScrollbarTroughStyle = nullptr;
41 GtkStyleContext* GtkSalGraphics::mpHScrollbarSliderStyle = nullptr;
42 GtkStyleContext* GtkSalGraphics::mpHScrollbarButtonStyle = nullptr;
43 GtkStyleContext* GtkSalGraphics::mpToolbarStyle = nullptr;
44 GtkStyleContext* GtkSalGraphics::mpToolButtonStyle = nullptr;
45 GtkStyleContext* GtkSalGraphics::mpToolbarSeperatorStyle = nullptr;
46 GtkStyleContext* GtkSalGraphics::mpCheckButtonStyle = nullptr;
47 GtkStyleContext* GtkSalGraphics::mpCheckButtonCheckStyle = nullptr;
48 GtkStyleContext* GtkSalGraphics::mpRadioButtonStyle = nullptr;
49 GtkStyleContext* GtkSalGraphics::mpRadioButtonRadioStyle = nullptr;
50 GtkStyleContext* GtkSalGraphics::mpSpinStyle = nullptr;
51 GtkStyleContext* GtkSalGraphics::mpSpinEntryStyle = nullptr;
52 GtkStyleContext* GtkSalGraphics::mpSpinUpStyle = nullptr;
53 GtkStyleContext* GtkSalGraphics::mpSpinDownStyle = nullptr;
54 GtkStyleContext* GtkSalGraphics::mpComboboxStyle = nullptr;
55 GtkStyleContext* GtkSalGraphics::mpComboboxBoxStyle = nullptr;
56 GtkStyleContext* GtkSalGraphics::mpComboboxEntryStyle = nullptr;
57 GtkStyleContext* GtkSalGraphics::mpComboboxButtonStyle = nullptr;
58 GtkStyleContext* GtkSalGraphics::mpComboboxButtonBoxStyle = nullptr;
59 GtkStyleContext* GtkSalGraphics::mpComboboxButtonArrowStyle = nullptr;
60 GtkStyleContext* GtkSalGraphics::mpListboxStyle = nullptr;
61 GtkStyleContext* GtkSalGraphics::mpListboxBoxStyle = nullptr;
62 GtkStyleContext* GtkSalGraphics::mpListboxButtonStyle = nullptr;
63 GtkStyleContext* GtkSalGraphics::mpListboxButtonBoxStyle= nullptr;
64 GtkStyleContext* GtkSalGraphics::mpListboxButtonArrowStyle = nullptr;
65 GtkStyleContext* GtkSalGraphics::mpFrameInStyle = nullptr;
66 GtkStyleContext* GtkSalGraphics::mpFrameOutStyle = nullptr;
67 GtkStyleContext* GtkSalGraphics::mpFixedHoriLineStyle = nullptr;
68 GtkStyleContext* GtkSalGraphics::mpFixedVertLineStyle = nullptr;
69 GtkStyleContext* GtkSalGraphics::mpTreeHeaderButtonStyle = nullptr;
70 GtkStyleContext* GtkSalGraphics::mpProgressBarStyle = nullptr;
71 GtkStyleContext* GtkSalGraphics::mpProgressBarTroughStyle = nullptr;
72 GtkStyleContext* GtkSalGraphics::mpProgressBarProgressStyle = nullptr;
73 GtkStyleContext* GtkSalGraphics::mpNotebookStyle = nullptr;
74 GtkStyleContext* GtkSalGraphics::mpNotebookStackStyle = nullptr;
75 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderStyle = nullptr;
76 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsStyle = nullptr;
77 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabStyle = nullptr;
78 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabLabelStyle = nullptr;
79 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabActiveLabelStyle = nullptr;
80 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabHoverLabelStyle = nullptr;
81 GtkStyleContext* GtkSalGraphics::mpMenuBarStyle = nullptr;
82 GtkStyleContext* GtkSalGraphics::mpMenuBarItemStyle = nullptr;
83 GtkStyleContext* GtkSalGraphics::mpMenuWindowStyle = nullptr;
84 GtkStyleContext* GtkSalGraphics::mpMenuStyle = nullptr;
85 GtkStyleContext* GtkSalGraphics::mpMenuItemStyle = nullptr;
86 GtkStyleContext* GtkSalGraphics::mpMenuItemArrowStyle = nullptr;
87 GtkStyleContext* GtkSalGraphics::mpMenuItemLabelStyle = nullptr;
88 GtkStyleContext* GtkSalGraphics::mpCheckMenuItemStyle = nullptr;
89 GtkStyleContext* GtkSalGraphics::mpCheckMenuItemCheckStyle = nullptr;
90 GtkStyleContext* GtkSalGraphics::mpRadioMenuItemStyle = nullptr;
91 GtkStyleContext* GtkSalGraphics::mpRadioMenuItemRadioStyle = nullptr;
92 GtkStyleContext* GtkSalGraphics::mpSeparatorMenuItemStyle = nullptr;
93 GtkStyleContext* GtkSalGraphics::mpSeparatorMenuItemSeparatorStyle = nullptr;
94 
95 bool GtkSalGraphics::style_loaded = false;
96 /************************************************************************
97  * State conversion
98  ************************************************************************/
NWConvertVCLStateToGTKState(ControlState nVCLState)99 static GtkStateFlags NWConvertVCLStateToGTKState(ControlState nVCLState)
100 {
101     GtkStateFlags nGTKState = GTK_STATE_FLAG_NORMAL;
102 
103     if (!( nVCLState & ControlState::ENABLED ))
104     {
105         nGTKState = GTK_STATE_FLAG_INSENSITIVE;
106     }
107 
108     if ( nVCLState & ControlState::PRESSED )
109     {
110         nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_ACTIVE);
111     }
112 
113     if ( nVCLState & ControlState::ROLLOVER )
114     {
115         nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_PRELIGHT);
116     }
117 
118     if ( nVCLState & ControlState::SELECTED )
119         nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_SELECTED);
120 
121     if ( nVCLState & ControlState::FOCUSED )
122         nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_FOCUSED);
123 
124     if (AllSettings::GetLayoutRTL())
125     {
126         nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_DIR_RTL);
127     }
128     else
129     {
130         nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_DIR_LTR);
131     }
132 
133     return nGTKState;
134 }
135 
136 enum class RenderType {
137     BackgroundAndFrame = 1,
138     Check,
139     Background,
140     MenuSeparator,
141     ToolbarSeparator,
142     Separator,
143     Arrow,
144     Radio,
145     Scrollbar,
146     Spinbutton,
147     Combobox,
148     Expander,
149     Icon,
150     Progress,
151     TabItem,
152     Focus
153 };
154 
NWCalcArrowRect(const tools::Rectangle & rButton,tools::Rectangle & rArrow)155 static void NWCalcArrowRect( const tools::Rectangle& rButton, tools::Rectangle& rArrow )
156 {
157     // Size the arrow appropriately
158     Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
159     rArrow.SetSize( aSize );
160 
161     rArrow.SetPos( Point(
162         rButton.Left() + ( rButton.GetWidth()  - rArrow.GetWidth()  ) / 2,
163         rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
164         ) );
165 }
166 
NWGetSpinButtonRect(ControlPart nPart,tools::Rectangle aAreaRect)167 tools::Rectangle GtkSalGraphics::NWGetSpinButtonRect( ControlPart nPart, tools::Rectangle aAreaRect)
168 {
169     gint w, h;
170     gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
171     gint icon_size = std::max(w, h);
172 
173     GtkBorder padding, border;
174     gtk_style_context_get_padding(mpSpinUpStyle, gtk_style_context_get_state(mpSpinUpStyle), &padding);
175     gtk_style_context_get_border(mpSpinUpStyle, gtk_style_context_get_state(mpSpinUpStyle), &border);
176 
177     gint buttonWidth = icon_size + padding.left + padding.right +
178         border.left + border.right;
179 
180     gint buttonHeight = icon_size + padding.top + padding.bottom +
181         border.top + border.bottom;
182 
183     tools::Rectangle buttonRect;
184     buttonRect.SetSize(Size(buttonWidth, buttonHeight));
185     buttonRect.setY(aAreaRect.Top());
186     buttonRect.SetBottom( buttonRect.Top() + aAreaRect.GetHeight() );
187     tools::Rectangle partRect(buttonRect);
188     if ( nPart == ControlPart::ButtonUp )
189     {
190         if (AllSettings::GetLayoutRTL())
191             partRect.setX(aAreaRect.Left());
192         else
193             partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()));
194     }
195     else if( nPart == ControlPart::ButtonDown )
196     {
197         if (AllSettings::GetLayoutRTL())
198             partRect.setX(aAreaRect.Left() + buttonRect.GetWidth());
199         else
200             partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth()));
201     }
202     else
203     {
204         if (AllSettings::GetLayoutRTL())
205         {
206             partRect.SetRight( aAreaRect.Left() + aAreaRect.GetWidth() );
207             partRect.SetLeft( aAreaRect.Left() + (2 * buttonRect.GetWidth()) - 1 );
208         }
209         else
210         {
211             partRect.SetRight( (aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth())) - 1 );
212             partRect.SetLeft( aAreaRect.Left() );
213         }
214         partRect.SetTop( aAreaRect.Top() );
215         partRect.SetBottom( aAreaRect.Bottom() );
216     }
217 
218     return partRect;
219 }
220 
221 namespace
222 {
QuerySize(GtkStyleContext * pContext,Size & rSize)223     void QuerySize(GtkStyleContext *pContext, Size &rSize)
224     {
225         GtkBorder margin, border, padding;
226         GtkStateFlags stateflags = gtk_style_context_get_state (pContext);
227 
228         gtk_style_context_get_margin(pContext, stateflags, &margin);
229         gtk_style_context_get_border(pContext, stateflags, &border);
230         gtk_style_context_get_padding(pContext, stateflags, &padding);
231 
232         int nMinWidth, nMinHeight;
233         gtk_style_context_get(pContext, stateflags,
234                 "min-width", &nMinWidth, "min-height", &nMinHeight, nullptr);
235 
236         nMinWidth += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
237         nMinHeight += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
238 
239         rSize = Size(std::max<long>(rSize.Width(), nMinWidth), std::max<long>(rSize.Height(), nMinHeight));
240     }
241 }
242 
NWGetScrollButtonRect(ControlPart nPart,tools::Rectangle aAreaRect)243 tools::Rectangle GtkSalGraphics::NWGetScrollButtonRect( ControlPart nPart, tools::Rectangle aAreaRect )
244 {
245     tools::Rectangle  buttonRect;
246 
247     gboolean has_forward;
248     gboolean has_forward2;
249     gboolean has_backward;
250     gboolean has_backward2;
251 
252     GtkStyleContext* pScrollbarStyle = nullptr;
253     if ((nPart == ControlPart::ButtonLeft) || (nPart == ControlPart::ButtonRight))
254         pScrollbarStyle = mpHScrollbarStyle;
255     else // (nPart == ControlPart::ButtonUp) || (nPart == ControlPart::ButtonDown)
256         pScrollbarStyle = mpVScrollbarStyle;
257 
258     gtk_style_context_get_style( pScrollbarStyle,
259                                  "has-forward-stepper", &has_forward,
260                                  "has-secondary-forward-stepper", &has_forward2,
261                                  "has-backward-stepper", &has_backward,
262                                  "has-secondary-backward-stepper", &has_backward2, nullptr );
263     gint       buttonWidth;
264     gint       buttonHeight;
265 
266     gint nFirst = 0;
267     gint nSecond = 0;
268 
269     if ( has_forward )   nSecond += 1;
270     if ( has_forward2 )  nFirst  += 1;
271     if ( has_backward )  nFirst  += 1;
272     if ( has_backward2 ) nSecond += 1;
273 
274     if (gtk_check_version(3, 20, 0) == nullptr)
275     {
276         Size aSize;
277         if (nPart == ControlPart::ButtonLeft || nPart == ControlPart::ButtonRight)
278         {
279             QuerySize(mpHScrollbarStyle, aSize);
280             QuerySize(mpHScrollbarContentsStyle, aSize);
281             QuerySize(mpHScrollbarButtonStyle, aSize);
282         }
283         else
284         {
285             QuerySize(mpVScrollbarStyle, aSize);
286             QuerySize(mpVScrollbarContentsStyle, aSize);
287             QuerySize(mpVScrollbarButtonStyle, aSize);
288         }
289 
290         if (nPart == ControlPart::ButtonUp)
291         {
292             aSize.setHeight( aSize.Height() * nFirst );
293             buttonRect.setX(aAreaRect.Left());
294             buttonRect.setY(aAreaRect.Top());
295         }
296         else if (nPart == ControlPart::ButtonLeft)
297         {
298             aSize.setWidth( aSize.Width() * nFirst );
299             buttonRect.setX(aAreaRect.Left());
300             buttonRect.setY(aAreaRect.Top());
301         }
302         else if (nPart == ControlPart::ButtonDown)
303         {
304             aSize.setHeight( aSize.Height() * nSecond );
305             buttonRect.setX(aAreaRect.Left());
306             buttonRect.setY(aAreaRect.Top() + aAreaRect.GetHeight() - aSize.Height());
307         }
308         else if (nPart == ControlPart::ButtonRight)
309         {
310             aSize.setWidth( aSize.Width() * nSecond );
311             buttonRect.setX(aAreaRect.Left() + aAreaRect.GetWidth() - aSize.Width());
312             buttonRect.setY(aAreaRect.Top());
313         }
314 
315         buttonRect.SetSize(aSize);
316 
317         return buttonRect;
318     }
319 
320     gint slider_width;
321     gint stepper_size;
322     gint stepper_spacing;
323     gint trough_border;
324 
325     // Grab some button style attributes
326     gtk_style_context_get_style( pScrollbarStyle,
327                                  "slider-width", &slider_width,
328                                  "stepper-size", &stepper_size,
329                                  "trough-border", &trough_border,
330                                  "stepper-spacing", &stepper_spacing, nullptr );
331 
332     if ( ( nPart == ControlPart::ButtonUp ) || ( nPart == ControlPart::ButtonDown ) )
333     {
334         buttonWidth = slider_width + 2 * trough_border;
335         buttonHeight = stepper_size + trough_border + stepper_spacing;
336     }
337     else
338     {
339         buttonWidth = stepper_size + trough_border + stepper_spacing;
340         buttonHeight = slider_width + 2 * trough_border;
341     }
342 
343     if ( nPart == ControlPart::ButtonUp )
344     {
345         buttonHeight *= nFirst;
346         buttonHeight -= 1;
347         buttonRect.setX( aAreaRect.Left() );
348         buttonRect.setY( aAreaRect.Top() );
349     }
350     else if ( nPart == ControlPart::ButtonLeft )
351     {
352         buttonWidth *= nFirst;
353         buttonWidth -= 1;
354         buttonRect.setX( aAreaRect.Left() );
355         buttonRect.setY( aAreaRect.Top() );
356     }
357     else if ( nPart == ControlPart::ButtonDown )
358     {
359         buttonHeight *= nSecond;
360         buttonRect.setX( aAreaRect.Left() );
361         buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight );
362     }
363     else if ( nPart == ControlPart::ButtonRight )
364     {
365         buttonWidth *= nSecond;
366         buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth );
367         buttonRect.setY( aAreaRect.Top() );
368     }
369 
370     buttonRect.SetSize( Size( buttonWidth, buttonHeight ) );
371 
372     return buttonRect;
373 }
374 
375 static GtkWidget* gCacheWindow;
376 static GtkWidget* gDumbContainer;
377 static GtkWidget* gSpinBox;
378 static GtkWidget* gEntryBox;
379 static GtkWidget* gComboBox;
380 static GtkWidget* gListBox;
381 static GtkWidget* gMenuBarWidget;
382 static GtkWidget* gMenuItemMenuBarWidget;
383 static GtkWidget* gCheckMenuItemWidget;
384 static GtkWidget* gTreeViewWidget;
385 
386 namespace
387 {
style_context_set_state(GtkStyleContext * context,GtkStateFlags flags)388     void style_context_set_state(GtkStyleContext* context, GtkStateFlags flags)
389     {
390         do
391         {
392             gtk_style_context_set_state(context, flags);
393         }
394         while ((context = gtk_style_context_get_parent(context)));
395     }
396 
397     class StyleContextSave
398     {
399     private:
400         std::vector<std::pair<GtkStyleContext*, GtkStateFlags>> m_aStates;
401     public:
save(GtkStyleContext * context)402         void save(GtkStyleContext* context)
403         {
404             do
405             {
406                 m_aStates.emplace_back(context, gtk_style_context_get_state(context));
407             }
408             while ((context = gtk_style_context_get_parent(context)));
409         }
restore()410         void restore()
411         {
412             for (auto a = m_aStates.rbegin(); a != m_aStates.rend(); ++a)
413             {
414                 gtk_style_context_set_state(a->first, a->second);
415             }
416             m_aStates.clear();
417         }
418     };
419 
render_common(GtkStyleContext * pContext,cairo_t * cr,const tools::Rectangle & rIn,GtkStateFlags flags)420     tools::Rectangle render_common(GtkStyleContext *pContext, cairo_t *cr, const tools::Rectangle &rIn, GtkStateFlags flags)
421     {
422         if (!pContext)
423             return rIn;
424 
425         gtk_style_context_set_state(pContext, flags);
426 
427         tools::Rectangle aRect(rIn);
428         GtkBorder margin;
429         gtk_style_context_get_margin(pContext, gtk_style_context_get_state(pContext), &margin);
430 
431         aRect.AdjustLeft(margin.left );
432         aRect.AdjustTop(margin.top );
433         aRect.AdjustRight( -(margin.right) );
434         aRect.AdjustBottom( -(margin.bottom) );
435 
436         gtk_render_background(pContext, cr, aRect.Left(), aRect.Top(),
437                                             aRect.GetWidth(), aRect.GetHeight());
438         gtk_render_frame(pContext, cr, aRect.Left(), aRect.Top(),
439                                        aRect.GetWidth(), aRect.GetHeight());
440 
441         GtkBorder border, padding;
442         gtk_style_context_get_border(pContext, gtk_style_context_get_state(pContext), &border);
443         gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &padding);
444 
445         aRect.AdjustLeft(border.left + padding.left );
446         aRect.AdjustTop(border.top + padding.top );
447         aRect.AdjustRight( -(border.right + padding.right) );
448         aRect.AdjustBottom( -(border.bottom + padding.bottom) );
449 
450         return aRect;
451     }
452 }
453 
PaintScrollbar(GtkStyleContext * context,cairo_t * cr,const tools::Rectangle & rControlRectangle,ControlPart nPart,const ImplControlValue & rValue)454 void GtkSalGraphics::PaintScrollbar(GtkStyleContext *context,
455                                     cairo_t *cr,
456                                     const tools::Rectangle& rControlRectangle,
457                                     ControlPart nPart,
458                                     const ImplControlValue& rValue )
459 {
460     if (gtk_check_version(3, 20, 0) == nullptr)
461     {
462         assert(rValue.getType() == ControlType::Scrollbar);
463         const ScrollbarValue& rScrollbarVal = static_cast<const ScrollbarValue&>(rValue);
464         tools::Rectangle        scrollbarRect;
465         GtkStateFlags    stateFlags;
466         GtkOrientation    scrollbarOrientation;
467         tools::Rectangle        thumbRect = rScrollbarVal.maThumbRect;
468         tools::Rectangle        button11BoundRect = rScrollbarVal.maButton1Rect;   // backward
469         tools::Rectangle        button22BoundRect = rScrollbarVal.maButton2Rect;   // forward
470         tools::Rectangle        button12BoundRect = rScrollbarVal.maButton1Rect;   // secondary forward
471         tools::Rectangle        button21BoundRect = rScrollbarVal.maButton2Rect;   // secondary backward
472         gdouble          arrow1Angle;                                        // backward
473         gdouble          arrow2Angle;                                        // forward
474         tools::Rectangle        arrowRect;
475         gint            slider_width = 0;
476         gint            stepper_size = 0;
477 
478         // make controlvalue rectangles relative to area
479         thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
480         button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
481         button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
482         button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
483         button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
484 
485         // Find the overall bounding rect of the control
486         scrollbarRect = rControlRectangle;
487         if (scrollbarRect.GetWidth() <= 0 || scrollbarRect.GetHeight() <= 0)
488             return;
489 
490         gint slider_side;
491         Size aSize;
492         if (nPart == ControlPart::DrawBackgroundHorz)
493         {
494             QuerySize(mpHScrollbarStyle, aSize);
495             QuerySize(mpHScrollbarContentsStyle, aSize);
496             QuerySize(mpHScrollbarTroughStyle, aSize);
497             QuerySize(mpHScrollbarSliderStyle, aSize);
498             slider_side = aSize.Height();
499             gtk_style_context_get(mpHScrollbarButtonStyle,
500                                   gtk_style_context_get_state(mpHScrollbarButtonStyle),
501                                   "min-height", &slider_width,
502                                   "min-width", &stepper_size, nullptr);
503         }
504         else
505         {
506             QuerySize(mpVScrollbarStyle, aSize);
507             QuerySize(mpVScrollbarContentsStyle, aSize);
508             QuerySize(mpVScrollbarTroughStyle, aSize);
509             QuerySize(mpVScrollbarSliderStyle, aSize);
510             slider_side = aSize.Width();
511             gtk_style_context_get(mpVScrollbarButtonStyle,
512                                   gtk_style_context_get_state(mpVScrollbarButtonStyle),
513                                   "min-width", &slider_width,
514                                   "min-height", &stepper_size, nullptr);
515         }
516 
517         gboolean has_forward;
518         gboolean has_forward2;
519         gboolean has_backward;
520         gboolean has_backward2;
521 
522         gtk_style_context_get_style( context,
523                                      "has-forward-stepper", &has_forward,
524                                      "has-secondary-forward-stepper", &has_forward2,
525                                      "has-backward-stepper", &has_backward,
526                                      "has-secondary-backward-stepper", &has_backward2, nullptr );
527 
528         if ( nPart == ControlPart::DrawBackgroundHorz )
529         {
530             // Center vertically in the track
531             scrollbarRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
532             scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), slider_side ) );
533             thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
534             thumbRect.SetSize( Size( thumbRect.GetWidth(), slider_side ) );
535 
536             scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
537             arrow1Angle = G_PI * 3 / 2;
538             arrow2Angle = G_PI / 2;
539 
540             if ( has_backward )
541             {
542                 button12BoundRect.Move( stepper_size,
543                                         (scrollbarRect.GetHeight() - slider_width) / 2 );
544             }
545 
546             button11BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
547             button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
548             button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
549 
550             if ( has_backward2 )
551             {
552                 button22BoundRect.Move( stepper_size, (scrollbarRect.GetHeight() - slider_width) / 2 );
553                 button21BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
554             }
555             else
556             {
557                 button22BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
558             }
559 
560             button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
561             button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
562         }
563         else
564         {
565             // Center horizontally in the track
566             scrollbarRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
567             scrollbarRect.SetSize( Size( slider_side, scrollbarRect.GetHeight() ) );
568             thumbRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
569             thumbRect.SetSize( Size( slider_side, thumbRect.GetHeight() ) );
570 
571             scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
572             arrow1Angle = 0;
573             arrow2Angle = G_PI;
574 
575             if ( has_backward )
576             {
577                 button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
578                                         stepper_size );
579             }
580             button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
581             button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
582             button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
583 
584             if ( has_backward2 )
585             {
586                 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size );
587                 button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
588             }
589             else
590             {
591                 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
592             }
593 
594             button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
595             button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
596         }
597 
598         bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
599 
600         // ----------------- CONTENTS
601         GtkStyleContext* pScrollbarContentsStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
602                                                   mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
603 
604         gtk_render_background(gtk_widget_get_style_context(gCacheWindow), cr, 0, 0,
605                               scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
606 
607         gtk_render_background(context, cr, 0, 0,
608                               scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
609         gtk_render_frame(context, cr, 0, 0,
610                          scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
611 
612         gtk_render_background(pScrollbarContentsStyle, cr, 0, 0,
613                               scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
614         gtk_render_frame(pScrollbarContentsStyle, cr, 0, 0,
615                          scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
616 
617         bool backwardButtonInsensitive =
618             rScrollbarVal.mnCur == rScrollbarVal.mnMin;
619         bool forwardButtonInsensitive = rScrollbarVal.mnMax == 0 ||
620             rScrollbarVal.mnCur + rScrollbarVal.mnVisibleSize >= rScrollbarVal.mnMax;
621 
622         // ----------------- BUTTON 1
623         if ( has_backward )
624         {
625             stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
626             if ( backwardButtonInsensitive )
627                 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
628 
629             GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
630                                                      mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
631 
632             gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
633 
634             gtk_render_background(pScrollbarButtonStyle, cr,
635                                   button11BoundRect.Left(), button11BoundRect.Top(),
636                                   button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
637             gtk_render_frame(pScrollbarButtonStyle, cr,
638                              button11BoundRect.Left(), button11BoundRect.Top(),
639                              button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
640 
641             // ----------------- ARROW 1
642             NWCalcArrowRect( button11BoundRect, arrowRect );
643             gtk_render_arrow(pScrollbarButtonStyle, cr,
644                              arrow1Angle,
645                              arrowRect.Left(), arrowRect.Top(),
646                              MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
647         }
648         if ( has_forward2 )
649         {
650             stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
651             if ( forwardButtonInsensitive )
652                 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
653 
654             GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
655                                                      mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
656 
657             gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
658 
659             gtk_render_background(pScrollbarButtonStyle, cr,
660                                   button12BoundRect.Left(), button12BoundRect.Top(),
661                                   button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
662             gtk_render_frame(pScrollbarButtonStyle, cr,
663                              button12BoundRect.Left(), button12BoundRect.Top(),
664                              button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
665 
666             // ----------------- ARROW 1
667             NWCalcArrowRect( button12BoundRect, arrowRect );
668             gtk_render_arrow(pScrollbarButtonStyle, cr,
669                              arrow2Angle,
670                              arrowRect.Left(), arrowRect.Top(),
671                              MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
672         }
673         // ----------------- BUTTON 2
674 
675         if ( has_forward )
676         {
677             stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
678             if ( forwardButtonInsensitive )
679                 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
680 
681             GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
682                                                      mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
683 
684             gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
685 
686             gtk_render_background(pScrollbarButtonStyle, cr,
687                            button22BoundRect.Left(), button22BoundRect.Top(),
688                            button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
689             gtk_render_frame(pScrollbarButtonStyle, cr,
690                            button22BoundRect.Left(), button22BoundRect.Top(),
691                            button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
692 
693             // ----------------- ARROW 2
694             NWCalcArrowRect( button22BoundRect, arrowRect );
695             gtk_render_arrow(pScrollbarButtonStyle, cr,
696                              arrow2Angle,
697                              arrowRect.Left(), arrowRect.Top(),
698                              MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
699         }
700 
701         if ( has_backward2 )
702         {
703             stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
704             if ( backwardButtonInsensitive )
705                 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
706 
707             GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
708                                                      mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
709 
710             gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
711 
712             gtk_render_background(pScrollbarButtonStyle, cr,
713                                   button21BoundRect.Left(), button21BoundRect.Top(),
714                                   button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
715             gtk_render_frame(pScrollbarButtonStyle, cr,
716                              button21BoundRect.Left(), button21BoundRect.Top(),
717                              button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
718 
719             // ----------------- ARROW 2
720             NWCalcArrowRect( button21BoundRect, arrowRect );
721             gtk_render_arrow(pScrollbarButtonStyle, cr,
722                              arrow1Angle,
723                              arrowRect.Left(), arrowRect.Top(),
724                              MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
725         }
726 
727         // ----------------- TROUGH
728         // trackrect matches that of ScrollBar::ImplCalc
729         tools::Rectangle aTrackRect(Point(0, 0), scrollbarRect.GetSize());
730         if (nPart == ControlPart::DrawBackgroundHorz)
731         {
732             tools::Rectangle aBtn1Rect = NWGetScrollButtonRect(ControlPart::ButtonLeft, aTrackRect);
733             tools::Rectangle aBtn2Rect = NWGetScrollButtonRect(ControlPart::ButtonRight, aTrackRect);
734             if (!aBtn1Rect.IsWidthEmpty())
735                 aTrackRect.SetLeft( aBtn1Rect.Right() );
736             if (!aBtn2Rect.IsWidthEmpty())
737                 aTrackRect.SetRight( aBtn2Rect.Left() );
738         }
739         else
740         {
741             tools::Rectangle aBtn1Rect = NWGetScrollButtonRect(ControlPart::ButtonUp, aTrackRect);
742             tools::Rectangle aBtn2Rect = NWGetScrollButtonRect(ControlPart::ButtonDown, aTrackRect);
743             if (!aBtn1Rect.IsHeightEmpty())
744                 aTrackRect.SetTop( aBtn1Rect.Bottom() + 1 );
745             if (!aBtn2Rect.IsHeightEmpty())
746                 aTrackRect.SetBottom( aBtn2Rect.Top() );
747         }
748 
749         GtkStyleContext* pScrollbarTroughStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
750                                                   mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
751         gtk_render_background(pScrollbarTroughStyle, cr, aTrackRect.Left(), aTrackRect.Top(),
752                               aTrackRect.GetWidth(), aTrackRect.GetHeight() );
753         gtk_render_frame(pScrollbarTroughStyle, cr, aTrackRect.Left(), aTrackRect.Top(),
754                          aTrackRect.GetWidth(), aTrackRect.GetHeight() );
755 
756         // ----------------- THUMB
757         if ( has_slider )
758         {
759             stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnThumbState);
760             if ( rScrollbarVal.mnThumbState & ControlState::PRESSED )
761                 stateFlags = static_cast<GtkStateFlags>(stateFlags | GTK_STATE_PRELIGHT);
762 
763             GtkStyleContext* pScrollbarSliderStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
764                                                       mpVScrollbarSliderStyle : mpHScrollbarSliderStyle;
765 
766             gtk_style_context_set_state(pScrollbarSliderStyle, stateFlags);
767 
768             GtkBorder margin;
769             gtk_style_context_get_margin(pScrollbarSliderStyle, stateFlags, &margin);
770 
771             gtk_render_background(pScrollbarSliderStyle, cr,
772                               thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
773                               thumbRect.GetWidth() - margin.left - margin.right,
774                               thumbRect.GetHeight() - margin.top - margin.bottom);
775 
776             gtk_render_frame(pScrollbarSliderStyle, cr,
777                               thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
778                               thumbRect.GetWidth() - margin.left - margin.right,
779                               thumbRect.GetHeight() - margin.top - margin.bottom);
780         }
781 
782         return;
783     }
784 
785     OSL_ASSERT( rValue.getType() == ControlType::Scrollbar );
786     const ScrollbarValue& rScrollbarVal = static_cast<const ScrollbarValue&>(rValue);
787     tools::Rectangle        scrollbarRect;
788     GtkStateFlags    stateFlags;
789     GtkOrientation    scrollbarOrientation;
790     tools::Rectangle        thumbRect = rScrollbarVal.maThumbRect;
791     tools::Rectangle        button11BoundRect = rScrollbarVal.maButton1Rect;   // backward
792     tools::Rectangle        button22BoundRect = rScrollbarVal.maButton2Rect;   // forward
793     tools::Rectangle        button12BoundRect = rScrollbarVal.maButton1Rect;   // secondary forward
794     tools::Rectangle        button21BoundRect = rScrollbarVal.maButton2Rect;   // secondary backward
795     gdouble          arrow1Angle;                                        // backward
796     gdouble          arrow2Angle;                                        // forward
797     tools::Rectangle        arrowRect;
798     gint            slider_width = 0;
799     gint            stepper_size = 0;
800     gint            trough_border = 0;
801 
802     // make controlvalue rectangles relative to area
803     thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
804     button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
805     button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
806     button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
807     button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
808 
809     // Find the overall bounding rect of the control
810     scrollbarRect = rControlRectangle;
811     scrollbarRect.SetSize( Size( scrollbarRect.GetWidth() + 1,
812                                  scrollbarRect.GetHeight() + 1 ) );
813 
814     if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) )
815         return;
816 
817     // Grab some button style attributes
818     gtk_style_context_get_style( context,
819                                  "slider_width", &slider_width,
820                                  "stepper_size", &stepper_size,
821                                  "trough_border", &trough_border, nullptr );
822     gboolean has_forward;
823     gboolean has_forward2;
824     gboolean has_backward;
825     gboolean has_backward2;
826 
827     gtk_style_context_get_style( context,
828                                  "has-forward-stepper", &has_forward,
829                                  "has-secondary-forward-stepper", &has_forward2,
830                                  "has-backward-stepper", &has_backward,
831                                  "has-secondary-backward-stepper", &has_backward2, nullptr );
832     gint magic = trough_border ? 1 : 0;
833     gint slider_side = slider_width + (trough_border * 2);
834 
835     if ( nPart == ControlPart::DrawBackgroundHorz )
836     {
837         scrollbarRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
838         scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), slider_side ) );
839 
840         scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
841         arrow1Angle = G_PI * 3 / 2;
842         arrow2Angle = G_PI / 2;
843 
844         if ( has_backward )
845         {
846             button12BoundRect.Move( stepper_size - trough_border,
847                                     (scrollbarRect.GetHeight() - slider_width) / 2 );
848         }
849 
850         button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 );
851         button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
852         button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
853 
854         if ( has_backward2 )
855         {
856             button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
857             button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
858         }
859         else
860         {
861             button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
862         }
863 
864         button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
865         button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
866 
867         thumbRect.SetBottom( thumbRect.Top() + slider_width - 1 );
868         // Make sure the thumb is at least the default width (so we don't get tiny thumbs),
869         // but if the VCL gives us a size smaller than the theme's default thumb size,
870         // honor the VCL size
871         thumbRect.AdjustRight(magic );
872         // Center vertically in the track
873         thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
874     }
875     else
876     {
877         scrollbarRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
878         scrollbarRect.SetSize( Size( slider_side, scrollbarRect.GetHeight() ) );
879 
880         scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
881         arrow1Angle = 0;
882         arrow2Angle = G_PI;
883 
884         if ( has_backward )
885         {
886             button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
887                                     stepper_size + trough_border );
888         }
889         button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border );
890         button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
891         button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
892 
893         if ( has_backward2 )
894         {
895             button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 );
896             button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
897         }
898         else
899         {
900             button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
901         }
902 
903         button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
904         button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
905 
906         thumbRect.SetRight( thumbRect.Left() + slider_width - 1 );
907 
908         thumbRect.AdjustBottom(magic );
909         // Center horizontally in the track
910         thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
911     }
912 
913     bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
914 
915     // ----------------- CONTENTS
916     GtkStyleContext* pScrollbarContentsStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
917                                               mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
918 
919     gtk_render_background(gtk_widget_get_style_context(gCacheWindow), cr, 0, 0,
920                           scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
921 
922     gtk_render_background(context, cr, 0, 0,
923                           scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
924     gtk_render_frame(context, cr, 0, 0,
925                      scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
926 
927     gtk_render_background(pScrollbarContentsStyle, cr, 0, 0,
928                           scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
929     gtk_render_frame(pScrollbarContentsStyle, cr, 0, 0,
930                      scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
931 
932     // ----------------- TROUGH
933     GtkStyleContext* pScrollbarTroughStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
934                                               mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
935     gtk_render_background(pScrollbarTroughStyle, cr, 0, 0,
936                           scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
937     gtk_render_frame(pScrollbarTroughStyle, cr, 0, 0,
938                      scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
939 
940     // ----------------- THUMB
941     if ( has_slider )
942     {
943         stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnThumbState);
944         if ( rScrollbarVal.mnThumbState & ControlState::PRESSED )
945             stateFlags = static_cast<GtkStateFlags>(stateFlags | GTK_STATE_PRELIGHT);
946 
947         GtkStyleContext* pScrollbarSliderStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
948                                                   mpVScrollbarSliderStyle : mpHScrollbarSliderStyle;
949 
950         gtk_style_context_set_state(pScrollbarSliderStyle, stateFlags);
951 
952         GtkBorder margin;
953         gtk_style_context_get_margin(pScrollbarSliderStyle, stateFlags, &margin);
954 
955         gtk_render_background(pScrollbarSliderStyle, cr,
956                           thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
957                           thumbRect.GetWidth() - margin.left - margin.right,
958                           thumbRect.GetHeight() - margin.top - margin.bottom);
959 
960         gtk_render_frame(pScrollbarSliderStyle, cr,
961                           thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
962                           thumbRect.GetWidth() - margin.left - margin.right,
963                           thumbRect.GetHeight() - margin.top - margin.bottom);
964     }
965 
966     bool backwardButtonInsensitive =
967         rScrollbarVal.mnCur == rScrollbarVal.mnMin;
968     bool forwardButtonInsensitive = rScrollbarVal.mnMax == 0 ||
969         rScrollbarVal.mnCur + rScrollbarVal.mnVisibleSize >= rScrollbarVal.mnMax;
970 
971     // ----------------- BUTTON 1
972     if ( has_backward )
973     {
974         stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
975         if ( backwardButtonInsensitive )
976             stateFlags = GTK_STATE_FLAG_INSENSITIVE;
977 
978         GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
979                                                  mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
980 
981         gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
982 
983         gtk_render_background(pScrollbarButtonStyle, cr,
984                               button11BoundRect.Left(), button11BoundRect.Top(),
985                               button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
986         gtk_render_frame(pScrollbarButtonStyle, cr,
987                          button11BoundRect.Left(), button11BoundRect.Top(),
988                          button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
989 
990         // ----------------- ARROW 1
991         NWCalcArrowRect( button11BoundRect, arrowRect );
992         gtk_render_arrow(pScrollbarButtonStyle, cr,
993                          arrow1Angle,
994                          arrowRect.Left(), arrowRect.Top(),
995                          MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
996     }
997     if ( has_forward2 )
998     {
999         stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
1000         if ( forwardButtonInsensitive )
1001             stateFlags = GTK_STATE_FLAG_INSENSITIVE;
1002 
1003         GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
1004                                                  mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
1005 
1006         gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
1007 
1008         gtk_render_background(pScrollbarButtonStyle, cr,
1009                               button12BoundRect.Left(), button12BoundRect.Top(),
1010                               button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
1011         gtk_render_frame(pScrollbarButtonStyle, cr,
1012                          button12BoundRect.Left(), button12BoundRect.Top(),
1013                          button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
1014 
1015         // ----------------- ARROW 1
1016         NWCalcArrowRect( button12BoundRect, arrowRect );
1017         gtk_render_arrow(pScrollbarButtonStyle, cr,
1018                          arrow2Angle,
1019                          arrowRect.Left(), arrowRect.Top(),
1020                          MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
1021     }
1022     // ----------------- BUTTON 2
1023     if ( has_backward2 )
1024     {
1025         stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
1026         if ( backwardButtonInsensitive )
1027             stateFlags = GTK_STATE_FLAG_INSENSITIVE;
1028 
1029         GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
1030                                                  mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
1031 
1032         gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
1033 
1034         gtk_render_background(pScrollbarButtonStyle, cr,
1035                               button21BoundRect.Left(), button21BoundRect.Top(),
1036                               button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
1037         gtk_render_frame(pScrollbarButtonStyle, cr,
1038                          button21BoundRect.Left(), button21BoundRect.Top(),
1039                          button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
1040 
1041         // ----------------- ARROW 2
1042         NWCalcArrowRect( button21BoundRect, arrowRect );
1043         gtk_render_arrow(pScrollbarButtonStyle, cr,
1044                          arrow1Angle,
1045                          arrowRect.Left(), arrowRect.Top(),
1046                          MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
1047     }
1048     if ( has_forward )
1049     {
1050         stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
1051         if ( forwardButtonInsensitive )
1052             stateFlags = GTK_STATE_FLAG_INSENSITIVE;
1053 
1054         GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
1055                                                  mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
1056 
1057         gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
1058 
1059         gtk_render_background(pScrollbarButtonStyle, cr,
1060                        button22BoundRect.Left(), button22BoundRect.Top(),
1061                        button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
1062         gtk_render_frame(pScrollbarButtonStyle, cr,
1063                        button22BoundRect.Left(), button22BoundRect.Top(),
1064                        button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
1065 
1066         // ----------------- ARROW 2
1067         NWCalcArrowRect( button22BoundRect, arrowRect );
1068         gtk_render_arrow(pScrollbarButtonStyle, cr,
1069                          arrow2Angle,
1070                          arrowRect.Left(), arrowRect.Top(),
1071                          MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
1072     }
1073 }
1074 
PaintOneSpinButton(GtkStyleContext * context,cairo_t * cr,ControlPart nPart,tools::Rectangle aAreaRect,ControlState nState)1075 void GtkSalGraphics::PaintOneSpinButton( GtkStyleContext *context,
1076                                          cairo_t *cr,
1077                                          ControlPart nPart,
1078                                          tools::Rectangle aAreaRect,
1079                                          ControlState nState )
1080 {
1081     GtkBorder            padding, border;
1082 
1083     GtkStateFlags stateFlags = NWConvertVCLStateToGTKState(nState);
1084     tools::Rectangle buttonRect = NWGetSpinButtonRect( nPart, aAreaRect );
1085 
1086     gtk_style_context_set_state(context, stateFlags);
1087     stateFlags = gtk_style_context_get_state(context);
1088 
1089     gtk_style_context_get_padding(context, stateFlags, &padding);
1090     gtk_style_context_get_border(context, stateFlags, &border);
1091 
1092     gtk_render_background(context, cr,
1093                           buttonRect.Left(), buttonRect.Top(),
1094                           buttonRect.GetWidth(), buttonRect.GetHeight() );
1095 
1096     gint iconWidth = buttonRect.GetWidth() - padding.left - padding.right - border.left - border.right;
1097     gint iconHeight = buttonRect.GetHeight() - padding.top - padding.bottom - border.top - border.bottom;
1098 
1099     const char* icon = (nPart == ControlPart::ButtonUp) ? "list-add-symbolic" : "list-remove-symbolic";
1100     GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
1101 
1102     gint scale = gtk_style_context_get_scale (context);
1103     GtkIconInfo *info = gtk_icon_theme_lookup_icon_for_scale(pIconTheme, icon, std::min(iconWidth, iconHeight), scale,
1104                                                    static_cast<GtkIconLookupFlags>(0));
1105 
1106     GdkPixbuf *pixbuf = gtk_icon_info_load_symbolic_for_context(info, context, nullptr, nullptr);
1107     g_object_unref(info);
1108 
1109     iconWidth = gdk_pixbuf_get_width(pixbuf)/scale;
1110     iconHeight = gdk_pixbuf_get_height(pixbuf)/scale;
1111     tools::Rectangle arrowRect;
1112     arrowRect.SetSize(Size(iconWidth, iconHeight));
1113     arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
1114     arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 );
1115 
1116     gtk_style_context_save (context);
1117     gtk_style_context_set_scale (context, 1);
1118     gtk_render_icon(context, cr, pixbuf, arrowRect.Left(), arrowRect.Top());
1119     gtk_style_context_restore (context);
1120     g_object_unref(pixbuf);
1121 
1122     gtk_render_frame(context, cr,
1123                      buttonRect.Left(), buttonRect.Top(),
1124                      buttonRect.GetWidth(), buttonRect.GetHeight() );
1125 }
1126 
PaintSpinButton(GtkStateFlags flags,cairo_t * cr,const tools::Rectangle & rControlRectangle,ControlPart nPart,const ImplControlValue & rValue)1127 void GtkSalGraphics::PaintSpinButton(GtkStateFlags flags,
1128                                      cairo_t *cr,
1129                                      const tools::Rectangle& rControlRectangle,
1130                                      ControlPart nPart,
1131                                      const ImplControlValue& rValue )
1132 {
1133     const SpinbuttonValue *pSpinVal = (rValue.getType() == ControlType::SpinButtons) ? static_cast<const SpinbuttonValue *>(&rValue) : nullptr;
1134     ControlPart upBtnPart = ControlPart::ButtonUp;
1135     ControlState upBtnState = ControlState::NONE;
1136     ControlPart downBtnPart = ControlPart::ButtonDown;
1137     ControlState downBtnState = ControlState::NONE;
1138 
1139     if ( pSpinVal )
1140     {
1141         upBtnPart = pSpinVal->mnUpperPart;
1142         upBtnState = pSpinVal->mnUpperState;
1143 
1144         downBtnPart = pSpinVal->mnLowerPart;
1145         downBtnState = pSpinVal->mnLowerState;
1146     }
1147 
1148     if (nPart == ControlPart::Entire)
1149     {
1150         gtk_style_context_set_state(mpWindowStyle, flags);
1151 
1152         gtk_render_background(mpWindowStyle, cr,
1153                               0, 0,
1154                               rControlRectangle.GetWidth(), rControlRectangle.GetHeight());
1155 
1156         gtk_style_context_set_state(mpSpinStyle, flags);
1157 
1158         gtk_render_background(mpSpinStyle, cr,
1159                               0, 0,
1160                               rControlRectangle.GetWidth(), rControlRectangle.GetHeight());
1161     }
1162 
1163     cairo_translate(cr, -rControlRectangle.Left(), -rControlRectangle.Top());
1164     PaintOneSpinButton(mpSpinUpStyle, cr, upBtnPart, rControlRectangle, upBtnState );
1165     PaintOneSpinButton(mpSpinDownStyle, cr, downBtnPart, rControlRectangle, downBtnState );
1166     cairo_translate(cr, rControlRectangle.Left(), rControlRectangle.Top());
1167 
1168     if (nPart == ControlPart::Entire)
1169     {
1170         gtk_render_frame(mpSpinStyle, cr,
1171                          0, 0,
1172                          rControlRectangle.GetWidth(), rControlRectangle.GetHeight() );
1173     }
1174 }
1175 
1176 #define FALLBACK_ARROW_SIZE gint(11 * 0.85)
1177 
NWGetComboBoxButtonRect(ControlType nType,ControlPart nPart,tools::Rectangle aAreaRect)1178 tools::Rectangle GtkSalGraphics::NWGetComboBoxButtonRect(ControlType nType,
1179                                                    ControlPart nPart,
1180                                                    tools::Rectangle aAreaRect )
1181 {
1182     tools::Rectangle    aButtonRect;
1183 
1184     GtkBorder padding;
1185     if (nType == ControlType::Listbox)
1186         gtk_style_context_get_padding(mpListboxButtonStyle, gtk_style_context_get_state(mpListboxButtonStyle), &padding);
1187     else
1188         gtk_style_context_get_padding(mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &padding);
1189 
1190     gint nArrowWidth = FALLBACK_ARROW_SIZE;
1191     if (gtk_check_version(3, 20, 0) == nullptr)
1192     {
1193         gtk_style_context_get(mpComboboxButtonArrowStyle,
1194             gtk_style_context_get_state(mpComboboxButtonArrowStyle),
1195             "min-width", &nArrowWidth, nullptr);
1196     }
1197     else
1198     {
1199         nArrowWidth = nArrowWidth * gtk_style_context_get_scale (mpComboboxButtonArrowStyle);
1200     }
1201 
1202     gint nButtonWidth = nArrowWidth + padding.left + padding.right;
1203     if( nPart == ControlPart::ButtonDown )
1204     {
1205         Point aPos(aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, aAreaRect.Top());
1206         if (AllSettings::GetLayoutRTL())
1207             aPos.setX( aAreaRect.Left() );
1208         aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
1209         aButtonRect.SetPos(aPos);
1210     }
1211     else if( nPart == ControlPart::SubEdit )
1212     {
1213         gint adjust_left = padding.left;
1214         gint adjust_top = padding.top;
1215         gint adjust_right = padding.right;
1216         gint adjust_bottom = padding.bottom;
1217 
1218         aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - (adjust_left + adjust_right),
1219                                    aAreaRect.GetHeight() - (adjust_top + adjust_bottom)) );
1220         Point aEditPos = aAreaRect.TopLeft();
1221         if (AllSettings::GetLayoutRTL())
1222             aEditPos.AdjustX(nButtonWidth );
1223         else
1224             aEditPos.AdjustX(adjust_left );
1225         aEditPos.AdjustY(adjust_top );
1226         aButtonRect.SetPos( aEditPos );
1227     }
1228 
1229     return aButtonRect;
1230 }
1231 
PaintCombobox(GtkStateFlags flags,cairo_t * cr,const tools::Rectangle & rControlRectangle,ControlType nType,ControlPart nPart)1232 void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
1233                                     const tools::Rectangle& rControlRectangle,
1234                                     ControlType nType,
1235                                     ControlPart nPart )
1236 {
1237     tools::Rectangle        areaRect;
1238     tools::Rectangle        buttonRect;
1239     tools::Rectangle        arrowRect;
1240 
1241     // Find the overall bounding rect of the buttons's drawing area,
1242     // plus its actual draw rect excluding adornment
1243     areaRect = rControlRectangle;
1244 
1245     buttonRect = NWGetComboBoxButtonRect(ControlType::Combobox, ControlPart::ButtonDown, areaRect);
1246 
1247     tools::Rectangle        aEditBoxRect( areaRect );
1248     aEditBoxRect.SetSize( Size( areaRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
1249     if (AllSettings::GetLayoutRTL())
1250         aEditBoxRect.SetPos( Point( areaRect.Left() + buttonRect.GetWidth(), areaRect.Top() ) );
1251 
1252     gint arrow_width = FALLBACK_ARROW_SIZE, arrow_height = FALLBACK_ARROW_SIZE;
1253     if (gtk_check_version(3, 20, 0) == nullptr)
1254     {
1255         if (nType == ControlType::Combobox)
1256         {
1257             gtk_style_context_get(mpComboboxButtonArrowStyle,
1258                 gtk_style_context_get_state(mpComboboxButtonArrowStyle),
1259                 "min-width", &arrow_width, "min-height", &arrow_height, nullptr);
1260         }
1261         else if (nType == ControlType::Listbox)
1262         {
1263             gtk_style_context_get(mpListboxButtonArrowStyle,
1264                 gtk_style_context_get_state(mpListboxButtonArrowStyle),
1265                 "min-width", &arrow_width, "min-height", &arrow_height, nullptr);
1266         }
1267     }
1268     else
1269     {
1270         if (nType == ControlType::Combobox)
1271         {
1272             arrow_width = arrow_width * gtk_style_context_get_scale (mpComboboxButtonArrowStyle);
1273             arrow_height = arrow_height * gtk_style_context_get_scale (mpComboboxButtonArrowStyle);
1274         }
1275         else if (nType == ControlType::Listbox)
1276         {
1277             arrow_width = arrow_width * gtk_style_context_get_scale (mpListboxButtonArrowStyle);
1278             arrow_height = arrow_height * gtk_style_context_get_scale (mpListboxButtonArrowStyle);
1279         }
1280     }
1281 
1282     arrowRect.SetSize(Size(arrow_width, arrow_height));
1283     arrowRect.SetPos( Point( buttonRect.Left() + static_cast<gint>((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
1284                              buttonRect.Top() + static_cast<gint>((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
1285 
1286 
1287     tools::Rectangle aRect(Point(0, 0), Size(areaRect.GetWidth(), areaRect.GetHeight()));
1288 
1289     if (nType == ControlType::Combobox)
1290     {
1291         if( nPart == ControlPart::Entire )
1292         {
1293             render_common(mpComboboxStyle, cr, aRect, flags);
1294             render_common(mpComboboxBoxStyle, cr, aRect, flags);
1295             tools::Rectangle aEntryRect(Point(aEditBoxRect.Left() - areaRect.Left(),
1296                                  aEditBoxRect.Top() - areaRect.Top()),
1297                                  Size(aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight()));
1298 
1299             GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxEntryStyle);
1300             if (AllSettings::GetLayoutRTL())
1301                 gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_LEFT);
1302             else
1303                 gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_RIGHT);
1304             render_common(mpComboboxEntryStyle, cr, aEntryRect, flags);
1305             gtk_style_context_set_junction_sides(mpComboboxEntryStyle, eJuncSides);
1306         }
1307 
1308         tools::Rectangle aButtonRect(Point(buttonRect.Left() - areaRect.Left(), buttonRect.Top() - areaRect.Top()),
1309                               Size(buttonRect.GetWidth(), buttonRect.GetHeight()));
1310         GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxButtonStyle);
1311         if (AllSettings::GetLayoutRTL())
1312             gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_RIGHT);
1313         else
1314             gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_LEFT);
1315         render_common(mpComboboxButtonStyle, cr, aButtonRect, flags);
1316         gtk_style_context_set_junction_sides(mpComboboxButtonStyle, eJuncSides);
1317 
1318         gtk_render_arrow(mpComboboxButtonArrowStyle, cr,
1319                          G_PI,
1320                          (arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
1321                          arrowRect.GetWidth() );
1322     }
1323     else if (nType == ControlType::Listbox)
1324     {
1325         if( nPart == ControlPart::ListboxWindow )
1326         {
1327             /* render the popup window with the menu style */
1328             gtk_render_frame(mpMenuStyle, cr,
1329                              0, 0,
1330                              areaRect.GetWidth(), areaRect.GetHeight());
1331         }
1332         else
1333         {
1334             render_common(mpListboxStyle, cr, aRect, flags);
1335             render_common(mpListboxBoxStyle, cr, aRect, flags);
1336 
1337             render_common(mpListboxButtonStyle, cr, aRect, flags);
1338 
1339             gtk_render_arrow(mpListboxButtonArrowStyle, cr,
1340                              G_PI,
1341                              (arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
1342                              arrowRect.GetWidth() );
1343         }
1344     }
1345 }
1346 
appendComboEntry(GtkWidgetPath * pSiblingsPath,gtk_widget_path_iter_set_object_nameFunc set_object_name)1347 static void appendComboEntry(GtkWidgetPath* pSiblingsPath, gtk_widget_path_iter_set_object_nameFunc set_object_name)
1348 {
1349     gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_ENTRY);
1350     set_object_name(pSiblingsPath, -1, "entry");
1351     gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
1352 }
1353 
appendComboButton(GtkWidgetPath * pSiblingsPath,gtk_widget_path_iter_set_object_nameFunc set_object_name)1354 static void appendComboButton(GtkWidgetPath* pSiblingsPath, gtk_widget_path_iter_set_object_nameFunc set_object_name)
1355 {
1356     gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
1357     set_object_name(pSiblingsPath, -1, "button");
1358     gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
1359 }
1360 
buildLTRComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)1361 static GtkWidgetPath* buildLTRComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)
1362 {
1363     GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
1364 
1365     appendComboEntry(pSiblingsPath, set_object_name);
1366     appendComboButton(pSiblingsPath, set_object_name);
1367 
1368     return pSiblingsPath;
1369 }
1370 
buildRTLComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)1371 static GtkWidgetPath* buildRTLComboSiblingsPath(gtk_widget_path_iter_set_object_nameFunc set_object_name)
1372 {
1373     GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
1374 
1375     appendComboButton(pSiblingsPath, set_object_name);
1376     appendComboEntry(pSiblingsPath, set_object_name);
1377 
1378     return pSiblingsPath;
1379 }
1380 
makeContext(GtkWidgetPath * pPath,GtkStyleContext * pParent)1381 GtkStyleContext* GtkSalGraphics::makeContext(GtkWidgetPath *pPath, GtkStyleContext *pParent)
1382 {
1383     GtkStyleContext* context = gtk_style_context_new();
1384     gtk_style_context_set_screen(context, gtk_widget_get_screen(mpWindow));
1385     gtk_style_context_set_path(context, pPath);
1386     if (pParent == nullptr)
1387     {
1388         GtkWidget* pTopLevel = gtk_widget_get_toplevel(mpWindow);
1389         GtkStyleContext* pStyle = gtk_widget_get_style_context(pTopLevel);
1390         gtk_style_context_set_parent(context, pStyle);
1391         gtk_style_context_set_scale (context, gtk_style_context_get_scale (pStyle));
1392     }
1393     else
1394     {
1395         gtk_style_context_set_parent(context, pParent);
1396         gtk_style_context_set_scale (context, gtk_style_context_get_scale (pParent));
1397     }
1398     gtk_widget_path_unref(pPath);
1399     return context;
1400 }
1401 
createNewContext(GtkControlPart ePart,gtk_widget_path_iter_set_object_nameFunc set_object_name)1402 GtkStyleContext* GtkSalGraphics::createNewContext(GtkControlPart ePart, gtk_widget_path_iter_set_object_nameFunc set_object_name)
1403 {
1404     switch (ePart)
1405     {
1406         case GtkControlPart::ToplevelWindow:
1407         {
1408             GtkWidgetPath *path = gtk_widget_path_new();
1409             gtk_widget_path_append_type(path, G_TYPE_NONE);
1410             set_object_name(path, -1, "window");
1411             gtk_widget_path_iter_add_class(path, -1, "background");
1412             return makeContext(path, nullptr);
1413         }
1414         case GtkControlPart::Button:
1415         {
1416             GtkWidgetPath *path = gtk_widget_path_new();
1417             gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1418             set_object_name(path, -1, "button");
1419             return makeContext(path, nullptr);
1420         }
1421         case GtkControlPart::LinkButton:
1422         {
1423             GtkWidgetPath *path = gtk_widget_path_new();
1424             gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1425             set_object_name(path, -1, "button");
1426             gtk_widget_path_iter_add_class(path, -1, "link");
1427             return makeContext(path, nullptr);
1428         }
1429         case GtkControlPart::CheckButton:
1430         {
1431             GtkWidgetPath *path = gtk_widget_path_new();
1432             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
1433             set_object_name(path, -1, "checkbutton");
1434             return makeContext(path, nullptr);
1435         }
1436         case GtkControlPart::CheckButtonCheck:
1437         {
1438             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckButtonStyle));
1439             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
1440             set_object_name(path, -1, "check");
1441             return makeContext(path, mpCheckButtonStyle);
1442         }
1443         case GtkControlPart::RadioButton:
1444         {
1445             GtkWidgetPath *path = gtk_widget_path_new();
1446             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1447             set_object_name(path, -1, "radiobutton");
1448             return makeContext(path, nullptr);
1449         }
1450         case GtkControlPart::RadioButtonRadio:
1451         {
1452             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioButtonStyle));
1453             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1454             set_object_name(path, -1, "radio");
1455             return makeContext(path, mpRadioButtonStyle);
1456         }
1457         case GtkControlPart::ComboboxBoxButtonBoxArrow:
1458         {
1459             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxButtonBoxStyle));
1460             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1461             gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1462             set_object_name(path, -1, "arrow");
1463             return makeContext(path, mpComboboxButtonBoxStyle);
1464         }
1465         case GtkControlPart::ListboxBoxButtonBoxArrow:
1466         {
1467             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxButtonBoxStyle));
1468             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1469             gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1470             set_object_name(path, -1, "arrow");
1471             return makeContext(path, mpListboxButtonBoxStyle);
1472         }
1473         case GtkControlPart::Entry:
1474         {
1475             GtkWidgetPath *path = gtk_widget_path_new();
1476             gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
1477             set_object_name(path, -1, "entry");
1478             return makeContext(path, nullptr);
1479         }
1480         case GtkControlPart::Combobox:
1481         case GtkControlPart::Listbox:
1482         {
1483             GtkWidgetPath *path = gtk_widget_path_new();
1484             gtk_widget_path_append_type(path, G_TYPE_NONE);
1485             set_object_name(path, -1, "combobox");
1486             return makeContext(path, nullptr);
1487         }
1488         case GtkControlPart::ComboboxBox:
1489         {
1490             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxStyle));
1491             gtk_widget_path_append_type(path, G_TYPE_NONE);
1492             set_object_name(path, -1, "box");
1493             gtk_widget_path_iter_add_class(path, -1, "horizontal");
1494             gtk_widget_path_iter_add_class(path, -1, "linked");
1495             return makeContext(path, mpComboboxStyle);
1496         }
1497         case GtkControlPart::ListboxBox:
1498         {
1499             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxStyle));
1500             gtk_widget_path_append_type(path, G_TYPE_NONE);
1501             set_object_name(path, -1, "box");
1502             gtk_widget_path_iter_add_class(path, -1, "horizontal");
1503             gtk_widget_path_iter_add_class(path, -1, "linked");
1504             return makeContext(path, mpListboxStyle);
1505         }
1506         case GtkControlPart::ComboboxBoxEntry:
1507         {
1508             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxBoxStyle));
1509             GtkWidgetPath* pSiblingsPath;
1510             if (AllSettings::GetLayoutRTL())
1511             {
1512                 pSiblingsPath = buildRTLComboSiblingsPath(set_object_name);
1513                 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
1514             }
1515             else
1516             {
1517                 pSiblingsPath = buildLTRComboSiblingsPath(set_object_name);
1518                 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
1519             }
1520             gtk_widget_path_unref(pSiblingsPath);
1521             return makeContext(path, mpComboboxBoxStyle);
1522         }
1523         case GtkControlPart::ComboboxBoxButton:
1524         {
1525             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxBoxStyle));
1526             GtkWidgetPath* pSiblingsPath;
1527             if (AllSettings::GetLayoutRTL())
1528             {
1529                 pSiblingsPath = buildRTLComboSiblingsPath(set_object_name);
1530                 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
1531             }
1532             else
1533             {
1534                 pSiblingsPath = buildLTRComboSiblingsPath(set_object_name);
1535                 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
1536             }
1537             gtk_widget_path_unref(pSiblingsPath);
1538             return makeContext(path, mpComboboxBoxStyle);
1539         }
1540         case GtkControlPart::ListboxBoxButton:
1541         {
1542             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxBoxStyle));
1543             GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
1544 
1545             gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
1546             set_object_name(pSiblingsPath, -1, "button");
1547             gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
1548 
1549             gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
1550             gtk_widget_path_unref(pSiblingsPath);
1551             return makeContext(path, mpListboxBoxStyle);
1552         }
1553         case GtkControlPart::ComboboxBoxButtonBox:
1554         {
1555             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxButtonStyle));
1556             gtk_widget_path_append_type(path, G_TYPE_NONE);
1557             set_object_name(path, -1, "box");
1558             gtk_widget_path_iter_add_class(path, -1, "horizontal");
1559             return makeContext(path, mpComboboxButtonStyle);
1560         }
1561         case GtkControlPart::ListboxBoxButtonBox:
1562         {
1563             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxButtonStyle));
1564             gtk_widget_path_append_type(path, G_TYPE_NONE);
1565             set_object_name(path, -1, "box");
1566             gtk_widget_path_iter_add_class(path, -1, "horizontal");
1567             return makeContext(path, mpListboxButtonStyle);
1568         }
1569         case GtkControlPart::SpinButton:
1570         {
1571             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
1572             gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
1573             set_object_name(path, -1, "spinbutton");
1574             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
1575             return makeContext(path, mpWindowStyle);
1576         }
1577         case GtkControlPart::SpinButtonEntry:
1578         {
1579             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSpinStyle));
1580             gtk_widget_path_append_type(path, G_TYPE_NONE);
1581             set_object_name(path, -1, "entry");
1582             return makeContext(path, mpSpinStyle);
1583         }
1584         case GtkControlPart::SpinButtonUpButton:
1585         case GtkControlPart::SpinButtonDownButton:
1586         {
1587             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSpinStyle));
1588             gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
1589             set_object_name(path, -1, "button");
1590             gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::SpinButtonUpButton ? "up" : "down");
1591             return makeContext(path, mpSpinStyle);
1592         }
1593         case GtkControlPart::ScrollbarVertical:
1594         case GtkControlPart::ScrollbarHorizontal:
1595         {
1596             GtkWidgetPath *path = gtk_widget_path_new();
1597             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1598             set_object_name(path, -1, "scrollbar");
1599             gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::ScrollbarVertical ? "vertical" : "horizontal");
1600             return makeContext(path, nullptr);
1601         }
1602         case GtkControlPart::ScrollbarVerticalContents:
1603         case GtkControlPart::ScrollbarHorizontalContents:
1604         {
1605             GtkStyleContext *pParent =
1606                 (ePart == GtkControlPart::ScrollbarVerticalContents) ? mpVScrollbarStyle : mpHScrollbarStyle;
1607             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1608             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1609             set_object_name(path, -1, "contents");
1610             return makeContext(path, pParent);
1611         }
1612         case GtkControlPart::ScrollbarVerticalTrough:
1613         case GtkControlPart::ScrollbarHorizontalTrough:
1614         {
1615             GtkStyleContext *pParent =
1616                 (ePart == GtkControlPart::ScrollbarVerticalTrough) ? mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
1617             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1618             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1619             set_object_name(path, -1, "trough");
1620             return makeContext(path, pParent);
1621         }
1622         case GtkControlPart::ScrollbarVerticalSlider:
1623         case GtkControlPart::ScrollbarHorizontalSlider:
1624         {
1625             GtkStyleContext *pParent =
1626                 (ePart == GtkControlPart::ScrollbarVerticalSlider) ? mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
1627             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1628             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1629             set_object_name(path, -1, "slider");
1630             return makeContext(path, pParent);
1631         }
1632         case GtkControlPart::ScrollbarVerticalButton:
1633         case GtkControlPart::ScrollbarHorizontalButton:
1634         {
1635             GtkStyleContext *pParent =
1636                 (ePart == GtkControlPart::ScrollbarVerticalButton) ? mpVScrollbarStyle : mpHScrollbarStyle;
1637             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1638             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1639             set_object_name(path, -1, "button");
1640             return makeContext(path, pParent);
1641         }
1642         case GtkControlPart::ProgressBar:
1643         {
1644             GtkWidgetPath *path = gtk_widget_path_new();
1645             gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1646             set_object_name(path, -1, "progressbar");
1647             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
1648             return makeContext(path, nullptr);
1649         }
1650         case GtkControlPart::ProgressBarTrough:
1651         {
1652             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarStyle));
1653             gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1654             set_object_name(path, -1, "trough");
1655             return makeContext(path, mpProgressBarStyle);
1656         }
1657         case GtkControlPart::ProgressBarProgress:
1658         {
1659             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarTroughStyle));
1660             gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1661             set_object_name(path, -1, "progress");
1662             return makeContext(path, mpProgressBarTroughStyle);
1663         }
1664         case GtkControlPart::Notebook:
1665         {
1666             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
1667             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1668             set_object_name(path, -1, "notebook");
1669             return makeContext(path, mpWindowStyle);
1670         }
1671         case GtkControlPart::NotebookStack:
1672         {
1673             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
1674             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1675             set_object_name(path, -1, "stack");
1676             return makeContext(path, mpNotebookStyle);
1677         }
1678         case GtkControlPart::NotebookHeader:
1679         {
1680             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
1681             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1682             set_object_name(path, -1, "header");
1683             gtk_widget_path_iter_add_class(path, -1, "frame");
1684             gtk_widget_path_iter_add_class(path, -1, "top");
1685             return makeContext(path, mpNotebookStyle);
1686         }
1687         case GtkControlPart::NotebookHeaderTabs:
1688         {
1689             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderStyle));
1690             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1691             set_object_name(path, -1, "tabs");
1692             gtk_widget_path_iter_add_class(path, -1, "top");
1693             return makeContext(path, mpNotebookHeaderStyle);
1694         }
1695         case GtkControlPart::NotebookHeaderTabsTab:
1696         {
1697             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsStyle));
1698             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1699             set_object_name(path, -1, "tab");
1700             gtk_widget_path_iter_add_class(path, -1, "top");
1701             return makeContext(path, mpNotebookHeaderTabsStyle);
1702         }
1703         case GtkControlPart::NotebookHeaderTabsTabLabel:
1704         {
1705             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
1706             gtk_widget_path_append_type(path, G_TYPE_NONE);
1707             set_object_name(path, -1, "label");
1708             return makeContext(path, mpNotebookHeaderTabsTabStyle);
1709         }
1710         case GtkControlPart::NotebookHeaderTabsTabActiveLabel:
1711         case GtkControlPart::NotebookHeaderTabsTabHoverLabel:
1712             return mpNotebookHeaderTabsTabLabelStyle;
1713         case GtkControlPart::FrameBorder:
1714         {
1715             GtkWidgetPath *path = gtk_widget_path_new();
1716             gtk_widget_path_append_type(path, GTK_TYPE_FRAME);
1717             set_object_name(path, -1, "frame");
1718             gtk_widget_path_iter_add_class(path, -1, "frame");
1719             return makeContext(path, nullptr);
1720         }
1721         case GtkControlPart::MenuBar:
1722         {
1723             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
1724             gtk_widget_path_append_type(path, GTK_TYPE_MENU_BAR);
1725             set_object_name(path, -1, "menubar");
1726             return makeContext(path, mpWindowStyle);
1727         }
1728         case GtkControlPart::MenuBarItem:
1729         {
1730             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarStyle));
1731             gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
1732             set_object_name(path, -1, "menuitem");
1733             return makeContext(path, mpMenuBarStyle);
1734         }
1735         case GtkControlPart::MenuWindow:
1736         {
1737             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarItemStyle));
1738             gtk_widget_path_append_type(path, G_TYPE_NONE);
1739             set_object_name(path, -1, "window");
1740             gtk_widget_path_iter_add_class(path, -1, "background");
1741             gtk_widget_path_iter_add_class(path, -1, "popup");
1742             return makeContext(path, mpMenuBarItemStyle);
1743         }
1744         case GtkControlPart::Menu:
1745         {
1746             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuWindowStyle));
1747             gtk_widget_path_append_type(path, GTK_TYPE_MENU);
1748             set_object_name(path, -1, "menu");
1749             return makeContext(path, mpMenuWindowStyle);
1750         }
1751         case GtkControlPart::MenuItem:
1752         {
1753             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1754             gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
1755             set_object_name(path, -1, "menuitem");
1756             return makeContext(path, mpMenuStyle);
1757         }
1758         case GtkControlPart::MenuItemLabel:
1759         {
1760             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
1761             gtk_widget_path_append_type(path, G_TYPE_NONE);
1762             set_object_name(path, -1, "label");
1763             return makeContext(path, mpMenuItemStyle);
1764         }
1765         case GtkControlPart::MenuItemArrow:
1766         {
1767             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
1768             gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
1769             set_object_name(path, -1, "arrow");
1770             return makeContext(path, mpMenuItemStyle);
1771         }
1772         case GtkControlPart::CheckMenuItem:
1773         {
1774             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1775             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
1776             set_object_name(path, -1, "menuitem");
1777             return makeContext(path, mpMenuStyle);
1778         }
1779         case GtkControlPart::CheckMenuItemCheck:
1780         {
1781             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckMenuItemStyle));
1782             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
1783             set_object_name(path, -1, "check");
1784             return makeContext(path, mpCheckMenuItemStyle);
1785         }
1786         case GtkControlPart::RadioMenuItem:
1787         {
1788             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1789             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
1790             set_object_name(path, -1, "menuitem");
1791             return makeContext(path, mpMenuStyle);
1792         }
1793         case GtkControlPart::RadioMenuItemRadio:
1794         {
1795             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioMenuItemStyle));
1796             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
1797             set_object_name(path, -1, "radio");
1798             return makeContext(path, mpRadioMenuItemStyle);
1799         }
1800         case GtkControlPart::SeparatorMenuItem:
1801         {
1802             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1803             gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
1804             set_object_name(path, -1, "menuitem");
1805             return makeContext(path, mpMenuStyle);
1806         }
1807         case GtkControlPart::SeparatorMenuItemSeparator:
1808         {
1809             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSeparatorMenuItemStyle));
1810             gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
1811             set_object_name(path, -1, "separator");
1812             return makeContext(path, mpSeparatorMenuItemStyle);
1813         }
1814     }
1815 
1816     return nullptr;
1817 }
1818 
1819 #ifndef GTK_STYLE_CLASS_POPUP
1820 #define GTK_STYLE_CLASS_POPUP "popup"
1821 #endif
1822 #ifndef GTK_STYLE_CLASS_LABEL
1823 #define GTK_STYLE_CLASS_LABEL "label"
1824 #endif
1825 
createOldContext(GtkControlPart ePart)1826 GtkStyleContext* GtkSalGraphics::createOldContext(GtkControlPart ePart)
1827 {
1828     switch (ePart)
1829     {
1830         case GtkControlPart::ToplevelWindow:
1831         {
1832             GtkWidgetPath *path = gtk_widget_path_new();
1833             gtk_widget_path_append_type(path, GTK_TYPE_WINDOW);
1834             gtk_widget_path_iter_add_class(path, -1, "background");
1835             return makeContext(path, nullptr);
1836         }
1837         case GtkControlPart::Button:
1838         {
1839             GtkWidgetPath *path = gtk_widget_path_new();
1840             gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1841             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
1842             gtk_widget_path_iter_add_class(path, -1, "button");
1843             gtk_widget_path_iter_add_class(path, -1, "text-button");
1844             return makeContext(path, nullptr);
1845         }
1846         case GtkControlPart::LinkButton:
1847         {
1848             GtkWidgetPath *path = gtk_widget_path_new();
1849             gtk_widget_path_append_type(path, GTK_TYPE_LINK_BUTTON);
1850             gtk_widget_path_iter_add_class(path, -1, "text-button");
1851             return makeContext(path, nullptr);
1852         }
1853         case GtkControlPart::CheckButton:
1854         {
1855             GtkWidgetPath *path = gtk_widget_path_new();
1856             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
1857             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_CHECK);
1858             gtk_widget_path_iter_add_class(path, -1, "text-button");
1859             return makeContext(path, nullptr);
1860         }
1861         case GtkControlPart::CheckButtonCheck:
1862             return mpCheckButtonStyle;
1863         case GtkControlPart::RadioButton:
1864         {
1865             GtkWidgetPath *path = gtk_widget_path_new();
1866             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1867             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_RADIO);
1868             gtk_widget_path_iter_add_class(path, -1, "text-button");
1869             return makeContext(path, nullptr);
1870         }
1871         case GtkControlPart::RadioButtonRadio:
1872             return mpRadioButtonStyle;
1873         case GtkControlPart::ComboboxBoxButtonBoxArrow:
1874         case GtkControlPart::ListboxBoxButtonBoxArrow:
1875         {
1876             return (ePart == GtkControlPart::ComboboxBoxButtonBoxArrow)
1877                 ? mpComboboxButtonStyle : mpListboxButtonStyle;
1878         }
1879         case GtkControlPart::Entry:
1880         case GtkControlPart::ComboboxBoxEntry:
1881         case GtkControlPart::SpinButtonEntry:
1882         {
1883             GtkWidgetPath *path = gtk_widget_path_new();
1884             gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
1885             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_ENTRY);
1886             return makeContext(path, nullptr);
1887         }
1888         case GtkControlPart::Combobox:
1889         {
1890             GtkWidgetPath *path = gtk_widget_path_new();
1891             gtk_widget_path_append_type(path, GTK_TYPE_COMBO_BOX_TEXT);
1892             return makeContext(path, nullptr);
1893         }
1894         case GtkControlPart::Listbox:
1895         {
1896             GtkWidgetPath *path = gtk_widget_path_new();
1897             gtk_widget_path_append_type(path, GTK_TYPE_COMBO_BOX);
1898             return makeContext(path, nullptr);
1899         }
1900         case GtkControlPart::ComboboxBoxButton:
1901         case GtkControlPart::ListboxBoxButton:
1902         {
1903             GtkStyleContext *pParent =
1904                 (ePart == GtkControlPart::ComboboxBoxButton ) ? mpComboboxStyle : mpListboxStyle;
1905             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1906             gtk_widget_path_append_type(path, GTK_TYPE_TOGGLE_BUTTON);
1907             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
1908             gtk_widget_path_iter_add_class(path, -1, "the-button-in-the-combobox");
1909             return makeContext(path, pParent);
1910         }
1911         case GtkControlPart::SpinButton:
1912         {
1913             GtkWidgetPath *path = gtk_widget_path_new();
1914             gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
1915             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_ENTRY);
1916             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
1917             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SPINBUTTON);
1918             return makeContext(path, nullptr);
1919         }
1920         case GtkControlPart::SpinButtonUpButton:
1921         case GtkControlPart::SpinButtonDownButton:
1922         {
1923             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSpinStyle));
1924             gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
1925             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SPINBUTTON);
1926             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
1927             return makeContext(path, mpSpinStyle);
1928         }
1929         case GtkControlPart::ScrollbarVertical:
1930         case GtkControlPart::ScrollbarHorizontal:
1931         {
1932             GtkWidgetPath *path = gtk_widget_path_new();
1933             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1934             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
1935             gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::ScrollbarVertical ? "vertical" : "horizontal");
1936             return makeContext(path, nullptr);
1937         }
1938         case GtkControlPart::ScrollbarVerticalContents:
1939         case GtkControlPart::ScrollbarHorizontalContents:
1940         {
1941             GtkStyleContext *pParent =
1942                 (ePart == GtkControlPart::ScrollbarVerticalContents) ? mpVScrollbarStyle : mpHScrollbarStyle;
1943             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1944             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1945             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
1946             gtk_widget_path_iter_add_class(path, -1, "contents");
1947             return makeContext(path, pParent);
1948         }
1949         case GtkControlPart::ScrollbarHorizontalTrough:
1950         case GtkControlPart::ScrollbarVerticalTrough:
1951         {
1952             GtkStyleContext *pParent =
1953                 (ePart == GtkControlPart::ScrollbarVerticalTrough) ? mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
1954             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1955             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1956             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
1957             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_TROUGH);
1958             return makeContext(path, pParent);
1959         }
1960         case GtkControlPart::ScrollbarHorizontalSlider:
1961         case GtkControlPart::ScrollbarVerticalSlider:
1962         {
1963             GtkStyleContext *pParent =
1964                 (ePart == GtkControlPart::ScrollbarVerticalSlider) ? mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
1965             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1966             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1967             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
1968             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SLIDER);
1969             return makeContext(path, pParent);
1970         }
1971         case GtkControlPart::ScrollbarHorizontalButton:
1972         case GtkControlPart::ScrollbarVerticalButton:
1973         {
1974             GtkStyleContext *pParent =
1975                 (ePart == GtkControlPart::ScrollbarVerticalButton) ? mpVScrollbarStyle : mpHScrollbarStyle;
1976             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1977             gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1978             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SCROLLBAR);
1979             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_BUTTON);
1980             return makeContext(path, pParent);
1981         }
1982         case GtkControlPart::ProgressBar:
1983         {
1984             GtkWidgetPath *path = gtk_widget_path_new();
1985             gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1986             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_PROGRESSBAR);
1987             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
1988             return makeContext(path, nullptr);
1989         }
1990         case GtkControlPart::ProgressBarTrough:
1991         {
1992             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarStyle));
1993             gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1994             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_TROUGH);
1995             return makeContext(path, mpProgressBarStyle);
1996         }
1997         case GtkControlPart::ProgressBarProgress:
1998         {
1999             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarTroughStyle));
2000             gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
2001             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_PROGRESSBAR);
2002             return makeContext(path, mpProgressBarTroughStyle);
2003         }
2004         case GtkControlPart::Notebook:
2005         {
2006             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
2007             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
2008             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_NOTEBOOK);
2009             gtk_widget_path_iter_add_class(path, -1, "frame");
2010             return makeContext(path, mpWindowStyle);
2011         }
2012         case GtkControlPart::NotebookStack:
2013             return mpNotebookStyle;
2014         case GtkControlPart::NotebookHeader:
2015         {
2016             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
2017             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HEADER);
2018             gtk_widget_path_iter_add_class(path, -1, "top");
2019             return makeContext(path, gtk_style_context_get_parent(mpNotebookStyle));
2020         }
2021         case GtkControlPart::NotebookHeaderTabs:
2022             return mpNotebookHeaderStyle;
2023         case GtkControlPart::NotebookHeaderTabsTab:
2024         {
2025             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsStyle));
2026             gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
2027             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HEADER);
2028             gtk_widget_path_iter_add_class(path, -1, "top");
2029             gtk_widget_path_iter_add_region(path, -1, GTK_STYLE_REGION_TAB, static_cast<GtkRegionFlags>(GTK_REGION_EVEN | GTK_REGION_FIRST));
2030             return makeContext(path, mpNotebookHeaderTabsStyle);
2031         }
2032         case GtkControlPart::NotebookHeaderTabsTabLabel:
2033         {
2034             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
2035             gtk_widget_path_append_type(path, GTK_TYPE_LABEL);
2036             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_LABEL);
2037             return makeContext(path, mpNotebookHeaderTabsTabStyle);
2038         }
2039         case GtkControlPart::NotebookHeaderTabsTabActiveLabel:
2040         {
2041             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
2042             gtk_widget_path_append_type(path, GTK_TYPE_LABEL);
2043             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_LABEL);
2044             gtk_widget_path_iter_add_class(path, -1, "active-page");
2045             return makeContext(path, mpNotebookHeaderTabsTabStyle);
2046         }
2047         case GtkControlPart::NotebookHeaderTabsTabHoverLabel:
2048         {
2049             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
2050             gtk_widget_path_append_type(path, GTK_TYPE_LABEL);
2051             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_LABEL);
2052             gtk_widget_path_iter_add_class(path, -1, "prelight-page");
2053             return makeContext(path, mpNotebookHeaderTabsTabStyle);
2054         }
2055         case GtkControlPart::FrameBorder:
2056         {
2057             GtkWidgetPath *path = gtk_widget_path_new();
2058             gtk_widget_path_append_type(path, GTK_TYPE_FRAME);
2059             gtk_widget_path_iter_add_class(path, -1, "frame");
2060             return makeContext(path, nullptr);
2061         }
2062         case GtkControlPart::MenuBar:
2063         {
2064             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
2065             gtk_widget_path_append_type(path, GTK_TYPE_MENU_BAR);
2066             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_MENUBAR);
2067             return makeContext(path, mpWindowStyle);
2068         }
2069         case GtkControlPart::MenuBarItem:
2070         {
2071             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarStyle));
2072             gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
2073             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_MENUITEM);
2074             return makeContext(path, mpMenuBarStyle);
2075         }
2076         case GtkControlPart::MenuWindow:
2077         {
2078             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarItemStyle));
2079             gtk_widget_path_append_type(path, GTK_TYPE_WINDOW);
2080             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_POPUP);
2081             gtk_widget_path_iter_add_class(path, -1, "background");
2082             return makeContext(path, mpMenuBarItemStyle);
2083         }
2084         case GtkControlPart::Menu:
2085         {
2086             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuWindowStyle));
2087             gtk_widget_path_append_type(path, GTK_TYPE_MENU);
2088             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_MENU);
2089             return makeContext(path, mpMenuWindowStyle);
2090         }
2091         case GtkControlPart::MenuItem:
2092         {
2093             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
2094             gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
2095             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_MENUITEM);
2096             return makeContext(path, mpMenuStyle);
2097         }
2098         case GtkControlPart::MenuItemLabel:
2099         {
2100             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
2101             gtk_widget_path_append_type(path, GTK_TYPE_LABEL);
2102             return makeContext(path, mpMenuItemStyle);
2103         }
2104         case GtkControlPart::MenuItemArrow:
2105         {
2106             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
2107             gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
2108             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_ARROW);
2109             return makeContext(path, mpMenuItemStyle);
2110         }
2111         case GtkControlPart::CheckMenuItem:
2112         {
2113             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
2114             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
2115             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_CHECK);
2116             return makeContext(path, mpMenuStyle);
2117         }
2118         case GtkControlPart::CheckMenuItemCheck:
2119         {
2120             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckMenuItemStyle));
2121             gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
2122             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_CHECK);
2123             return makeContext(path, mpCheckMenuItemStyle);
2124         }
2125         case GtkControlPart::RadioMenuItem:
2126         {
2127             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
2128             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
2129             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_MENUITEM);
2130             return makeContext(path, mpMenuStyle);
2131         }
2132         case GtkControlPart::RadioMenuItemRadio:
2133         {
2134             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioMenuItemStyle));
2135             gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
2136             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_RADIO);
2137             return makeContext(path, mpRadioMenuItemStyle);
2138         }
2139         case GtkControlPart::SeparatorMenuItem:
2140         {
2141             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
2142             gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
2143             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_MENUITEM);
2144             return makeContext(path, mpMenuStyle);
2145         }
2146         case GtkControlPart::SeparatorMenuItemSeparator:
2147         {
2148             GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSeparatorMenuItemStyle));
2149             gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
2150             gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_SEPARATOR);
2151             return makeContext(path, mpSeparatorMenuItemStyle);
2152         }
2153         case GtkControlPart::ComboboxBox:
2154         case GtkControlPart::ListboxBox:
2155         case GtkControlPart::ComboboxBoxButtonBox:
2156         case GtkControlPart::ListboxBoxButtonBox:
2157             return nullptr;
2158         default:
2159             break;
2160     }
2161 
2162     return mpButtonStyle;
2163 }
2164 
createStyleContext(gtk_widget_path_iter_set_object_nameFunc set_object_name,GtkControlPart ePart)2165 GtkStyleContext* GtkSalGraphics::createStyleContext(gtk_widget_path_iter_set_object_nameFunc set_object_name,
2166                                                     GtkControlPart ePart)
2167 {
2168     if (set_object_name)
2169         return createNewContext(ePart, set_object_name);
2170     return createOldContext(ePart);
2171 }
2172 
2173 namespace
2174 {
ACTIVE_TAB()2175     GtkStateFlags ACTIVE_TAB()
2176     {
2177 #if GTK_CHECK_VERSION(3,20,0)
2178         if (gtk_check_version(3, 20, 0) == nullptr)
2179             return GTK_STATE_FLAG_CHECKED;
2180 #endif
2181         return GTK_STATE_FLAG_ACTIVE;
2182     }
2183 }
2184 
PaintCheckOrRadio(cairo_t * cr,GtkStyleContext * context,const tools::Rectangle & rControlRectangle,bool bIsCheck,bool bInMenu)2185 void GtkSalGraphics::PaintCheckOrRadio(cairo_t *cr, GtkStyleContext *context,
2186                                        const tools::Rectangle& rControlRectangle, bool bIsCheck, bool bInMenu)
2187 {
2188     gint indicator_size;
2189     gtk_style_context_get_style(context, "indicator-size", &indicator_size, nullptr);
2190 
2191     gint x = (rControlRectangle.GetWidth() - indicator_size) / 2;
2192     gint y = (rControlRectangle.GetHeight() - indicator_size) / 2;
2193 
2194     if (!bInMenu)
2195         gtk_render_background(context, cr, x, y, indicator_size, indicator_size);
2196 
2197     if (bIsCheck)
2198         gtk_render_check(context, cr, x, y, indicator_size, indicator_size);
2199     else
2200         gtk_render_option(context, cr, x, y, indicator_size, indicator_size);
2201 
2202     gtk_render_frame(context, cr, x, y, indicator_size, indicator_size);
2203 }
2204 
PaintCheck(cairo_t * cr,GtkStyleContext * context,const tools::Rectangle & rControlRectangle,bool bInMenu)2205 void GtkSalGraphics::PaintCheck(cairo_t *cr, GtkStyleContext *context,
2206                                 const tools::Rectangle& rControlRectangle, bool bInMenu)
2207 {
2208     PaintCheckOrRadio(cr, context, rControlRectangle, true, bInMenu);
2209 }
2210 
PaintRadio(cairo_t * cr,GtkStyleContext * context,const tools::Rectangle & rControlRectangle,bool bInMenu)2211 void GtkSalGraphics::PaintRadio(cairo_t *cr, GtkStyleContext *context,
2212                                 const tools::Rectangle& rControlRectangle, bool bInMenu)
2213 {
2214     PaintCheckOrRadio(cr, context, rControlRectangle, false, bInMenu);
2215 }
2216 
getArrowSize(GtkStyleContext * context)2217 static gfloat getArrowSize(GtkStyleContext* context)
2218 {
2219     if (gtk_check_version(3, 20, 0) == nullptr)
2220     {
2221         gint min_width, min_weight;
2222         gtk_style_context_get_style(context, "min-width", &min_width, nullptr);
2223         gtk_style_context_get_style(context, "min-height", &min_weight, nullptr);
2224         gfloat arrow_size = 11 * MAX (min_width, min_weight);
2225         return arrow_size;
2226     }
2227     else
2228     {
2229         gfloat arrow_scaling = 1.0;
2230         gtk_style_context_get_style(context, "arrow-scaling", &arrow_scaling, nullptr);
2231         gfloat arrow_size = 11 * arrow_scaling;
2232         return arrow_size;
2233     }
2234 }
2235 
2236 namespace
2237 {
draw_vertical_separator(GtkStyleContext * context,cairo_t * cr,const tools::Rectangle & rControlRegion)2238     void draw_vertical_separator(GtkStyleContext *context, cairo_t *cr, const tools::Rectangle& rControlRegion)
2239     {
2240         long nX = 0;
2241         long nY = 0;
2242 
2243         const bool bNewStyle = gtk_check_version(3, 20, 0) == nullptr;
2244 
2245         gint nSeparatorWidth = 1;
2246 
2247         if (bNewStyle)
2248         {
2249             gtk_style_context_get(context,
2250                 gtk_style_context_get_state(context),
2251                 "min-width", &nSeparatorWidth, nullptr);
2252         }
2253 
2254         gint nHalfSeparatorWidth = nSeparatorWidth / 2;
2255         gint nHalfRegionWidth = rControlRegion.GetWidth() / 2;
2256 
2257         nX = nX + nHalfRegionWidth - nHalfSeparatorWidth;
2258         nY = rControlRegion.GetHeight() > 5 ? 1 : 0;
2259         int nHeight = rControlRegion.GetHeight() - (2 * nY);
2260 
2261         if (bNewStyle)
2262         {
2263             gtk_render_background(context, cr, nX, nY, nSeparatorWidth, nHeight);
2264             gtk_render_frame(context, cr, nX, nY, nSeparatorWidth, nHeight);
2265         }
2266         else
2267         {
2268             gtk_render_line(context, cr, nX, nY, nX, nY + nHeight);
2269         }
2270     }
2271 
draw_horizontal_separator(GtkStyleContext * context,cairo_t * cr,const tools::Rectangle & rControlRegion)2272     void draw_horizontal_separator(GtkStyleContext *context, cairo_t *cr, const tools::Rectangle& rControlRegion)
2273     {
2274         long nX = 0;
2275         long nY = 0;
2276 
2277         const bool bNewStyle = gtk_check_version(3, 20, 0) == nullptr;
2278 
2279         gint nSeparatorHeight = 1;
2280 
2281         if (bNewStyle)
2282         {
2283             gtk_style_context_get(context,
2284                 gtk_style_context_get_state(context),
2285                 "min-height", &nSeparatorHeight, nullptr);
2286         }
2287 
2288         gint nHalfSeparatorHeight = nSeparatorHeight / 2;
2289         gint nHalfRegionHeight = rControlRegion.GetHeight() / 2;
2290 
2291         nY = nY + nHalfRegionHeight - nHalfSeparatorHeight;
2292         nX = rControlRegion.GetWidth() > 5 ? 1 : 0;
2293         int nWidth = rControlRegion.GetWidth() - (2 * nX);
2294 
2295         if (bNewStyle)
2296         {
2297             gtk_render_background(context, cr, nX, nY, nWidth, nSeparatorHeight);
2298             gtk_render_frame(context, cr, nX, nY, nWidth, nSeparatorHeight);
2299         }
2300         else
2301         {
2302             gtk_render_line(context, cr, nX, nY, nX + nWidth, nY);
2303         }
2304     }
2305 }
2306 
handleDamage(const tools::Rectangle & rDamagedRegion)2307 void GtkSalGraphics::handleDamage(const tools::Rectangle& rDamagedRegion)
2308 {
2309     assert(m_pWidgetDraw);
2310     assert(!rDamagedRegion.IsEmpty());
2311     mpFrame->damaged(rDamagedRegion.Left(), rDamagedRegion.Top(), rDamagedRegion.GetWidth(), rDamagedRegion.GetHeight());
2312 }
2313 
drawNativeControl(ControlType nType,ControlPart nPart,const tools::Rectangle & rControlRegion,ControlState nState,const ImplControlValue & rValue,const OUString &)2314 bool GtkSalGraphics::drawNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion,
2315                                             ControlState nState, const ImplControlValue& rValue,
2316                                             const OUString&)
2317 {
2318     RenderType renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::BackgroundAndFrame;
2319     GtkStyleContext *context = nullptr;
2320     const gchar *styleClass = nullptr;
2321     GdkPixbuf *pixbuf = nullptr;
2322     bool bInMenu = false;
2323 
2324     GtkStateFlags flags = NWConvertVCLStateToGTKState(nState);
2325 
2326     switch(nType)
2327     {
2328     case ControlType::Spinbox:
2329     case ControlType::SpinButtons:
2330         context = mpSpinStyle;
2331         renderType = RenderType::Spinbutton;
2332         break;
2333     case ControlType::Editbox:
2334         context = mpEntryStyle;
2335         break;
2336     case ControlType::MultilineEditbox:
2337         context = mpTextViewStyle;
2338         break;
2339     case ControlType::Combobox:
2340         context = mpComboboxStyle;
2341         renderType = RenderType::Combobox;
2342         break;
2343     case ControlType::Listbox:
2344         if (nPart == ControlPart::Focus)
2345         {
2346             renderType = RenderType::Focus;
2347             context = mpListboxButtonStyle;
2348         }
2349         else
2350         {
2351             renderType = RenderType::Combobox;
2352             context = mpListboxStyle;
2353         }
2354         break;
2355     case ControlType::MenuPopup:
2356         bInMenu = true;
2357 
2358         // map selected menu entries in vcl parlance to gtk prelight
2359         if (nPart >= ControlPart::MenuItem && nPart <= ControlPart::SubmenuArrow && (nState & ControlState::SELECTED))
2360             flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_PRELIGHT);
2361         flags = static_cast<GtkStateFlags>(flags & ~GTK_STATE_FLAG_ACTIVE);
2362         switch(nPart)
2363         {
2364         case ControlPart::MenuItem:
2365             context = mpMenuItemStyle;
2366             renderType = RenderType::BackgroundAndFrame;
2367             break;
2368         case ControlPart::MenuItemCheckMark:
2369             if (gtk_check_version(3, 20, 0) == nullptr)
2370                 context = mpCheckMenuItemCheckStyle;
2371             else
2372             {
2373                 context = gtk_widget_get_style_context(gCheckMenuItemWidget);
2374                 styleClass = GTK_STYLE_CLASS_CHECK;
2375             }
2376             renderType = RenderType::Check;
2377             nType = ControlType::Checkbox;
2378             if (nState & ControlState::PRESSED)
2379             {
2380                 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
2381             }
2382             break;
2383         case ControlPart::MenuItemRadioMark:
2384             if (gtk_check_version(3, 20, 0) == nullptr)
2385                 context = mpRadioMenuItemRadioStyle;
2386             else
2387             {
2388                 context = gtk_widget_get_style_context(gCheckMenuItemWidget);
2389                 styleClass = GTK_STYLE_CLASS_RADIO;
2390             }
2391             renderType = RenderType::Radio;
2392             nType = ControlType::Radiobutton;
2393             if (nState & ControlState::PRESSED)
2394             {
2395                 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
2396             }
2397             break;
2398         case ControlPart::Separator:
2399             context = mpSeparatorMenuItemSeparatorStyle;
2400             flags = GtkStateFlags(GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_INSENSITIVE); //GTK_STATE_FLAG_BACKDROP hack ?
2401             renderType = RenderType::MenuSeparator;
2402             break;
2403         case ControlPart::SubmenuArrow:
2404             if (gtk_check_version(3, 20, 0) == nullptr)
2405                 context = mpMenuItemArrowStyle;
2406             else
2407             {
2408                 context = gtk_widget_get_style_context(gCheckMenuItemWidget);
2409                 styleClass = GTK_STYLE_CLASS_ARROW;
2410             }
2411             renderType = RenderType::Arrow;
2412             break;
2413         case ControlPart::Entire:
2414             context = mpMenuStyle;
2415             renderType = RenderType::Background;
2416             break;
2417         default: break;
2418         }
2419         break;
2420     case ControlType::Toolbar:
2421         switch(nPart)
2422         {
2423         case ControlPart::DrawBackgroundHorz:
2424         case ControlPart::DrawBackgroundVert:
2425             context = mpToolbarStyle;
2426             break;
2427         case ControlPart::Button:
2428             /* For all checkbuttons in the toolbars */
2429             flags = static_cast<GtkStateFlags>(flags |
2430                     ( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_CHECKED : GTK_STATE_FLAG_NORMAL));
2431             context = mpToolButtonStyle;
2432             break;
2433         case ControlPart::SeparatorVert:
2434             context = mpToolbarSeperatorStyle;
2435             renderType = RenderType::ToolbarSeparator;
2436             break;
2437         default:
2438             return false;
2439         }
2440         break;
2441     case ControlType::Radiobutton:
2442         flags = static_cast<GtkStateFlags>(flags |
2443                 ( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_CHECKED : GTK_STATE_FLAG_NORMAL));
2444         context = mpRadioButtonRadioStyle;
2445         renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::Radio;
2446         break;
2447     case ControlType::Checkbox:
2448         flags = static_cast<GtkStateFlags>(flags |
2449                 ( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_CHECKED :
2450                   (rValue.getTristateVal() == ButtonValue::Mixed) ? GTK_STATE_FLAG_INCONSISTENT :
2451                   GTK_STATE_FLAG_NORMAL));
2452         context = mpCheckButtonCheckStyle;
2453         renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::Check;
2454         break;
2455     case ControlType::Pushbutton:
2456         context = mpButtonStyle;
2457         break;
2458     case ControlType::Scrollbar:
2459         switch(nPart)
2460         {
2461         case ControlPart::DrawBackgroundVert:
2462         case ControlPart::DrawBackgroundHorz:
2463             context = (nPart == ControlPart::DrawBackgroundVert)
2464                 ? mpVScrollbarStyle : mpHScrollbarStyle;
2465             renderType = RenderType::Scrollbar;
2466             break;
2467         default: break;
2468         }
2469         break;
2470     case ControlType::ListNet:
2471         return true;
2472         break;
2473     case ControlType::TabPane:
2474         context = mpNotebookStyle;
2475         break;
2476     case ControlType::TabBody:
2477         context = mpNotebookStackStyle;
2478         break;
2479     case ControlType::TabHeader:
2480         context = mpNotebookHeaderStyle;
2481         break;
2482     case ControlType::TabItem:
2483         context = mpNotebookHeaderTabsTabStyle;
2484         if (nState & ControlState::SELECTED)
2485             flags = static_cast<GtkStateFlags>(flags | ACTIVE_TAB());
2486         renderType = RenderType::TabItem;
2487         break;
2488     case ControlType::WindowBackground:
2489         context = gtk_widget_get_style_context(gtk_widget_get_toplevel(mpWindow));
2490         break;
2491     case ControlType::Frame:
2492     {
2493         DrawFrameStyle nStyle = static_cast<DrawFrameStyle>(rValue.getNumericVal() & 0x0f);
2494         if (nStyle == DrawFrameStyle::In)
2495             context = mpFrameOutStyle;
2496         else
2497             context = mpFrameInStyle;
2498         break;
2499     }
2500     case ControlType::Menubar:
2501         if (nPart == ControlPart::MenuItem)
2502         {
2503             context = mpMenuBarItemStyle;
2504 
2505             flags = (!(nState & ControlState::ENABLED)) ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
2506             if (nState & ControlState::SELECTED)
2507                 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_PRELIGHT);
2508         }
2509         else
2510         {
2511             context = mpMenuBarStyle;
2512         }
2513         break;
2514     case ControlType::Fixedline:
2515         context = nPart == ControlPart::SeparatorHorz ? mpFixedHoriLineStyle : mpFixedVertLineStyle;
2516         renderType = RenderType::Separator;
2517         break;
2518     case ControlType::ListNode:
2519     {
2520         context = mpTreeHeaderButtonStyle;
2521         ButtonValue aButtonValue = rValue.getTristateVal();
2522         if (aButtonValue == ButtonValue::On)
2523             flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
2524         renderType = RenderType::Expander;
2525         break;
2526     }
2527     case ControlType::ListHeader:
2528         context = mpTreeHeaderButtonStyle;
2529         if (nPart == ControlPart::Arrow)
2530         {
2531             const char* icon = (rValue.getNumericVal() & 1) ? "pan-down-symbolic" : "pan-up-symbolic";
2532             GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
2533             pixbuf = gtk_icon_theme_load_icon_for_scale(pIconTheme, icon,
2534                                                         std::max(rControlRegion.GetWidth(), rControlRegion.GetHeight()),
2535                                                         gtk_style_context_get_scale (context),
2536                                                         static_cast<GtkIconLookupFlags>(0), nullptr);
2537             flags = GTK_STATE_FLAG_SELECTED;
2538             renderType = RenderType::Icon;
2539         }
2540         break;
2541     case ControlType::Progress:
2542         context = mpProgressBarProgressStyle;
2543         renderType = RenderType::Progress;
2544         break;
2545     default:
2546         return false;
2547     }
2548 
2549     cairo_t *cr = getCairoContext(false);
2550     clipRegion(cr);
2551     cairo_translate(cr, rControlRegion.Left(), rControlRegion.Top());
2552 
2553     long nX = 0;
2554     long nY = 0;
2555     long nWidth = rControlRegion.GetWidth();
2556     long nHeight = rControlRegion.GetHeight();
2557 
2558     StyleContextSave aContextState;
2559     aContextState.save(context);
2560     style_context_set_state(context, flags);
2561 
2562     if (styleClass)
2563     {
2564         gtk_style_context_add_class(context, styleClass);
2565     }
2566 
2567     switch(renderType)
2568     {
2569     case RenderType::Background:
2570     case RenderType::BackgroundAndFrame:
2571         gtk_render_background(context, cr, nX, nY, nWidth, nHeight);
2572         if (renderType == RenderType::BackgroundAndFrame)
2573         {
2574             gtk_render_frame(context, cr, nX, nY, nWidth, nHeight);
2575         }
2576         break;
2577     case RenderType::Check:
2578     {
2579         PaintCheck(cr, context, rControlRegion, bInMenu);
2580         break;
2581     }
2582     case RenderType::Radio:
2583     {
2584         PaintRadio(cr, context, rControlRegion, bInMenu);
2585         break;
2586     }
2587     case RenderType::MenuSeparator:
2588         gtk_render_line(context, cr,
2589                         0, rControlRegion.GetHeight() / 2,
2590                         rControlRegion.GetWidth() - 1, rControlRegion.GetHeight() / 2);
2591         break;
2592     case RenderType::ToolbarSeparator:
2593     {
2594         draw_vertical_separator(context, cr, rControlRegion);
2595         break;
2596     }
2597     case RenderType::Separator:
2598         if (nPart == ControlPart::SeparatorHorz)
2599             draw_horizontal_separator(context, cr, rControlRegion);
2600         else
2601             draw_vertical_separator(context, cr, rControlRegion);
2602         break;
2603     case RenderType::Arrow:
2604         gtk_render_arrow(context, cr,
2605                          G_PI / 2, 0, 0,
2606                          MIN(rControlRegion.GetWidth(), 1 + rControlRegion.GetHeight()));
2607         break;
2608     case RenderType::Expander:
2609         gtk_render_expander(context, cr, -2, -2, nWidth+4, nHeight+4);
2610         break;
2611     case RenderType::Scrollbar:
2612         PaintScrollbar(context, cr, rControlRegion, nPart, rValue);
2613         break;
2614     case RenderType::Spinbutton:
2615         PaintSpinButton(flags, cr, rControlRegion, nPart, rValue);
2616         break;
2617     case RenderType::Combobox:
2618         PaintCombobox(flags, cr, rControlRegion, nType, nPart);
2619         break;
2620     case RenderType::Icon:
2621         gtk_style_context_save (context);
2622         gtk_style_context_set_scale (context, 1);
2623         gtk_render_icon(context, cr, pixbuf, nX, nY);
2624         gtk_style_context_restore (context);
2625         g_object_unref(pixbuf);
2626         break;
2627     case RenderType::Focus:
2628     {
2629         if (nType == ControlType::Checkbox ||
2630             nType == ControlType::Radiobutton)
2631         {
2632             nX -= 2; nY -=2;
2633             nHeight += 4; nWidth += 4;
2634         }
2635         else
2636         {
2637             GtkBorder border;
2638 
2639             gtk_style_context_get_border(context, flags, &border);
2640 
2641             nX += border.left;
2642             nY += border.top;
2643             nWidth -= border.left + border.right;
2644             nHeight -= border.top + border.bottom;
2645         }
2646 
2647         gtk_render_focus(context, cr, nX, nY, nWidth, nHeight);
2648 
2649         break;
2650     }
2651     case RenderType::Progress:
2652     {
2653         gtk_render_background(mpProgressBarTroughStyle, cr, nX, nY, nWidth, nHeight);
2654 
2655         long nProgressWidth = rValue.getNumericVal();
2656         if (nProgressWidth)
2657         {
2658             GtkBorder padding;
2659             gtk_style_context_get_padding(context, gtk_style_context_get_state(context), &padding);
2660 
2661             nX += padding.left;
2662             nY += padding.top;
2663             nHeight -= (padding.top + padding.bottom);
2664             nProgressWidth -= (padding.left + padding.right);
2665             gtk_render_background(context, cr, nX, nY, nProgressWidth, nHeight);
2666             gtk_render_frame(context, cr, nX, nY, nProgressWidth, nHeight);
2667         }
2668 
2669         gtk_render_frame(mpProgressBarTroughStyle, cr, nX, nY, nWidth, nHeight);
2670 
2671         break;
2672     }
2673     case RenderType::TabItem:
2674     {
2675         if (gtk_check_version(3, 20, 0) != nullptr)
2676         {
2677             gint initial_gap(0);
2678             gtk_style_context_get_style(mpNotebookStyle,
2679                                     "initial-gap", &initial_gap,
2680                                     nullptr);
2681 
2682             nX += initial_gap/2;
2683             nWidth -= initial_gap;
2684         }
2685         tools::Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
2686         render_common(mpNotebookHeaderTabsTabStyle, cr, aRect, flags);
2687         break;
2688     }
2689     default:
2690         break;
2691     }
2692 
2693     if (styleClass)
2694     {
2695         gtk_style_context_remove_class(context, styleClass);
2696     }
2697     aContextState.restore();
2698 
2699     cairo_destroy(cr); // unref
2700 
2701     if (!rControlRegion.IsEmpty())
2702         mpFrame->damaged(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight());
2703 
2704     return true;
2705 }
2706 
GetWidgetSize(const tools::Rectangle & rControlRegion,GtkWidget * widget)2707 static tools::Rectangle GetWidgetSize(const tools::Rectangle& rControlRegion, GtkWidget* widget)
2708 {
2709     GtkRequisition aReq;
2710     gtk_widget_get_preferred_size(widget, nullptr, &aReq);
2711     long nHeight = std::max<long>(rControlRegion.GetHeight(), aReq.height);
2712     return tools::Rectangle(rControlRegion.TopLeft(), Size(rControlRegion.GetWidth(), nHeight));
2713 }
2714 
AdjustRectForTextBordersPadding(GtkStyleContext * pStyle,long nContentWidth,long nContentHeight,const tools::Rectangle & rControlRegion)2715 static tools::Rectangle AdjustRectForTextBordersPadding(GtkStyleContext* pStyle, long nContentWidth, long nContentHeight, const tools::Rectangle& rControlRegion)
2716 {
2717     GtkBorder border;
2718     gtk_style_context_get_border(pStyle, gtk_style_context_get_state(pStyle), &border);
2719 
2720     GtkBorder padding;
2721     gtk_style_context_get_padding(pStyle, gtk_style_context_get_state(pStyle), &padding);
2722 
2723     gint nWidgetHeight = nContentHeight + padding.top + padding.bottom + border.top + border.bottom;
2724     nWidgetHeight = std::max(std::max<gint>(nWidgetHeight, rControlRegion.GetHeight()), 34);
2725 
2726     gint nWidgetWidth = nContentWidth + padding.left + padding.right + border.left + border.right;
2727     nWidgetWidth = std::max<gint>(nWidgetWidth, rControlRegion.GetWidth());
2728 
2729     tools::Rectangle aEditRect(rControlRegion.TopLeft(), Size(nWidgetWidth, nWidgetHeight));
2730 
2731     return aEditRect;
2732 }
2733 
getNativeControlRegion(ControlType nType,ControlPart nPart,const tools::Rectangle & rControlRegion,ControlState,const ImplControlValue & rValue,const OUString &,tools::Rectangle & rNativeBoundingRegion,tools::Rectangle & rNativeContentRegion)2734 bool GtkSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState,
2735                                                 const ImplControlValue& rValue, const OUString&,
2736                                                 tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion )
2737 {
2738     /* TODO: all this functions needs improvements */
2739     tools::Rectangle aEditRect = rControlRegion;
2740     gint indicator_size, indicator_spacing, point;
2741 
2742     if(((nType == ControlType::Checkbox) || (nType == ControlType::Radiobutton)) &&
2743        nPart == ControlPart::Entire)
2744     {
2745         rNativeBoundingRegion = rControlRegion;
2746 
2747         GtkStyleContext *pButtonStyle = (nType == ControlType::Checkbox) ? mpCheckButtonCheckStyle : mpRadioButtonRadioStyle;
2748 
2749 
2750         gtk_style_context_get_style( pButtonStyle,
2751                                      "indicator-size", &indicator_size,
2752                                      "indicator-spacing", &indicator_spacing,
2753                                      nullptr );
2754 
2755         GtkBorder border;
2756         gtk_style_context_get_border(pButtonStyle, gtk_style_context_get_state(pButtonStyle), &border);
2757 
2758         GtkBorder padding;
2759         gtk_style_context_get_padding(pButtonStyle, gtk_style_context_get_state(pButtonStyle), &padding);
2760 
2761 
2762         indicator_size += 2*indicator_spacing + border.left + padding.left + border.right + padding.right;
2763         tools::Rectangle aIndicatorRect( Point( 0,
2764                                          (rControlRegion.GetHeight()-indicator_size)/2),
2765                                   Size( indicator_size, indicator_size ) );
2766         rNativeContentRegion = aIndicatorRect;
2767 
2768         return true;
2769     }
2770     else if( nType == ControlType::MenuPopup)
2771     {
2772         if ((nPart == ControlPart::MenuItemCheckMark) ||
2773             (nPart == ControlPart::MenuItemRadioMark) )
2774         {
2775             indicator_size = 0;
2776 
2777             GtkStyleContext *pMenuItemStyle = (nPart == ControlPart::MenuItemCheckMark ) ? mpCheckMenuItemCheckStyle
2778                                                                                          : mpRadioMenuItemRadioStyle;
2779 
2780             gtk_style_context_get_style( pMenuItemStyle,
2781                                          "indicator-size", &indicator_size,
2782                                          nullptr );
2783 
2784             point = MAX(0, rControlRegion.GetHeight() - indicator_size);
2785             aEditRect = tools::Rectangle( Point( 0, point / 2),
2786                                    Size( indicator_size, indicator_size ) );
2787         }
2788         else if (nPart == ControlPart::Separator)
2789         {
2790             gint separator_height, separator_width, wide_separators;
2791 
2792             gtk_style_context_get_style (mpSeparatorMenuItemSeparatorStyle,
2793                                          "wide-separators",  &wide_separators,
2794                                          "separator-width",  &separator_width,
2795                                          "separator-height", &separator_height,
2796                                          nullptr);
2797 
2798             aEditRect = tools::Rectangle( aEditRect.TopLeft(),
2799                                    Size( aEditRect.GetWidth(), wide_separators ? separator_height : 1 ) );
2800         }
2801         else if (nPart == ControlPart::SubmenuArrow)
2802         {
2803             gfloat arrow_size = getArrowSize(mpMenuItemArrowStyle);
2804             aEditRect = tools::Rectangle( aEditRect.TopLeft(),
2805                                    Size( arrow_size, arrow_size ) );
2806         }
2807     }
2808     else if ( (nType==ControlType::Scrollbar) &&
2809               ((nPart==ControlPart::ButtonLeft) || (nPart==ControlPart::ButtonRight) ||
2810                (nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown)  ) )
2811     {
2812         rNativeBoundingRegion = NWGetScrollButtonRect( nPart, rControlRegion );
2813         rNativeContentRegion = rNativeBoundingRegion;
2814 
2815         if (!rNativeContentRegion.GetWidth())
2816             rNativeContentRegion.SetRight( rNativeContentRegion.Left() + 1 );
2817         if (!rNativeContentRegion.GetHeight())
2818             rNativeContentRegion.SetBottom( rNativeContentRegion.Top() + 1 );
2819 
2820         return true;
2821     }
2822     else if ( (nType==ControlType::Spinbox) &&
2823               ((nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) ||
2824                (nPart==ControlPart::SubEdit)) )
2825     {
2826         tools::Rectangle aControlRegion(GetWidgetSize(rControlRegion, gSpinBox));
2827         aEditRect = NWGetSpinButtonRect(nPart, aControlRegion);
2828     }
2829     else if ( (nType==ControlType::Combobox) &&
2830               ((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
2831     {
2832         aEditRect = NWGetComboBoxButtonRect(nType, nPart, rControlRegion);
2833     }
2834     else if ( (nType==ControlType::Listbox) &&
2835               ((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
2836     {
2837         aEditRect = NWGetComboBoxButtonRect(nType, nPart, rControlRegion);
2838     }
2839     else if (nType == ControlType::Editbox && nPart == ControlPart::Entire)
2840     {
2841         aEditRect = GetWidgetSize(rControlRegion, gEntryBox);
2842     }
2843     else if (nType == ControlType::Listbox && nPart == ControlPart::Entire)
2844     {
2845         aEditRect = GetWidgetSize(rControlRegion, gListBox);
2846     }
2847     else if (nType == ControlType::Combobox && nPart == ControlPart::Entire)
2848     {
2849         aEditRect = GetWidgetSize(rControlRegion, gComboBox);
2850     }
2851     else if (nType == ControlType::Spinbox && nPart == ControlPart::Entire)
2852     {
2853         aEditRect = GetWidgetSize(rControlRegion, gSpinBox);
2854     }
2855     else if (nType == ControlType::TabItem && nPart == ControlPart::Entire)
2856     {
2857         const TabitemValue& rTabitemValue = static_cast<const TabitemValue&>(rValue);
2858         const tools::Rectangle& rTabitemRect = rTabitemValue.getContentRect();
2859 
2860         aEditRect = AdjustRectForTextBordersPadding(mpNotebookHeaderTabsTabStyle, rTabitemRect.GetWidth(),
2861                                                     rTabitemRect.GetHeight(), rControlRegion);
2862     }
2863     else if (nType == ControlType::Frame && nPart == ControlPart::Border)
2864     {
2865         aEditRect = rControlRegion;
2866         DrawFrameFlags nStyle = static_cast<DrawFrameFlags>(rValue.getNumericVal() & 0xfff0);
2867         if (nStyle & DrawFrameFlags::NoDraw)
2868         {
2869             GtkBorder padding;
2870             gtk_style_context_get_padding(mpFrameInStyle, gtk_style_context_get_state(mpFrameInStyle), &padding);
2871 
2872             GtkBorder border;
2873             gtk_style_context_get_border(mpFrameInStyle, gtk_style_context_get_state(mpFrameInStyle), &border);
2874 
2875             int x1 = aEditRect.Left();
2876             int y1 = aEditRect.Top();
2877             int x2 = aEditRect.Right();
2878             int y2 = aEditRect.Bottom();
2879 
2880             rNativeBoundingRegion = aEditRect;
2881             rNativeContentRegion = tools::Rectangle(x1 + (padding.left + border.left),
2882                                              y1 + (padding.top + border.top),
2883                                              x2 - (padding.right + border.right),
2884                                              y2 - (padding.bottom + border.bottom));
2885 
2886             return true;
2887         }
2888         else
2889             rNativeContentRegion = rControlRegion;
2890     }
2891     else
2892     {
2893         return false;
2894     }
2895 
2896     rNativeBoundingRegion = aEditRect;
2897     rNativeContentRegion = rNativeBoundingRegion;
2898 
2899     return true;
2900 }
2901 /************************************************************************
2902  * helper for GtkSalFrame
2903  ************************************************************************/
getColor(const GdkRGBA & rCol)2904 static ::Color getColor( const GdkRGBA& rCol )
2905 {
2906     return ::Color( static_cast<int>(rCol.red * 0xFFFF) >> 8, static_cast<int>(rCol.green * 0xFFFF) >> 8, static_cast<int>(rCol.blue * 0xFFFF) >> 8 );
2907 }
2908 
getFont(GtkStyleContext * pStyle,const css::lang::Locale & rLocale)2909 static vcl::Font getFont(GtkStyleContext* pStyle, const css::lang::Locale& rLocale)
2910 {
2911     const PangoFontDescription* font = gtk_style_context_get_font(pStyle, gtk_style_context_get_state(pStyle));
2912     return pango_to_vcl(font, rLocale);
2913 }
2914 
pango_to_vcl(const PangoFontDescription * font,const css::lang::Locale & rLocale)2915 vcl::Font pango_to_vcl(const PangoFontDescription* font, const css::lang::Locale& rLocale)
2916 {
2917     OString    aFamily        = pango_font_description_get_family( font );
2918     int nPangoHeight    = pango_font_description_get_size( font );
2919     PangoStyle    eStyle    = pango_font_description_get_style( font );
2920     PangoWeight    eWeight    = pango_font_description_get_weight( font );
2921     PangoStretch eStretch = pango_font_description_get_stretch( font );
2922 
2923     psp::FastPrintFontInfo aInfo;
2924     // set family name
2925     aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
2926     // set italic
2927     switch( eStyle )
2928     {
2929         case PANGO_STYLE_NORMAL:    aInfo.m_eItalic = ITALIC_NONE;break;
2930         case PANGO_STYLE_ITALIC:    aInfo.m_eItalic = ITALIC_NORMAL;break;
2931         case PANGO_STYLE_OBLIQUE:    aInfo.m_eItalic = ITALIC_OBLIQUE;break;
2932     }
2933     // set weight
2934     if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
2935         aInfo.m_eWeight = WEIGHT_ULTRALIGHT;
2936     else if( eWeight <= PANGO_WEIGHT_LIGHT )
2937         aInfo.m_eWeight = WEIGHT_LIGHT;
2938     else if( eWeight <= PANGO_WEIGHT_NORMAL )
2939         aInfo.m_eWeight = WEIGHT_NORMAL;
2940     else if( eWeight <= PANGO_WEIGHT_BOLD )
2941         aInfo.m_eWeight = WEIGHT_BOLD;
2942     else
2943         aInfo.m_eWeight = WEIGHT_ULTRABOLD;
2944     // set width
2945     switch( eStretch )
2946     {
2947         case PANGO_STRETCH_ULTRA_CONDENSED:    aInfo.m_eWidth = WIDTH_ULTRA_CONDENSED;break;
2948         case PANGO_STRETCH_EXTRA_CONDENSED:    aInfo.m_eWidth = WIDTH_EXTRA_CONDENSED;break;
2949         case PANGO_STRETCH_CONDENSED:        aInfo.m_eWidth = WIDTH_CONDENSED;break;
2950         case PANGO_STRETCH_SEMI_CONDENSED:    aInfo.m_eWidth = WIDTH_SEMI_CONDENSED;break;
2951         case PANGO_STRETCH_NORMAL:            aInfo.m_eWidth = WIDTH_NORMAL;break;
2952         case PANGO_STRETCH_SEMI_EXPANDED:    aInfo.m_eWidth = WIDTH_SEMI_EXPANDED;break;
2953         case PANGO_STRETCH_EXPANDED:        aInfo.m_eWidth = WIDTH_EXPANDED;break;
2954         case PANGO_STRETCH_EXTRA_EXPANDED:    aInfo.m_eWidth = WIDTH_EXTRA_EXPANDED;break;
2955         case PANGO_STRETCH_ULTRA_EXPANDED:    aInfo.m_eWidth = WIDTH_ULTRA_EXPANDED;break;
2956     }
2957 
2958 #if OSL_DEBUG_LEVEL > 1
2959     fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() );
2960 #endif
2961 
2962     // match font to e.g. resolve "Sans"
2963     psp::PrintFontManager::get().matchFont(aInfo, rLocale);
2964 
2965 #if OSL_DEBUG_LEVEL > 1
2966     fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
2967                   aInfo.m_nID != 0 ? "succeeded" : "failed",
2968                   OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
2969 #endif
2970 
2971     int nPointHeight = nPangoHeight/PANGO_SCALE;
2972 
2973     vcl::Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
2974     if( aInfo.m_eWeight != WEIGHT_DONTKNOW )
2975         aFont.SetWeight( aInfo.m_eWeight );
2976     if( aInfo.m_eWidth != WIDTH_DONTKNOW )
2977         aFont.SetWidthType( aInfo.m_eWidth );
2978     if( aInfo.m_eItalic != ITALIC_DONTKNOW )
2979         aFont.SetItalic( aInfo.m_eItalic );
2980     if( aInfo.m_ePitch != PITCH_DONTKNOW )
2981         aFont.SetPitch( aInfo.m_ePitch );
2982     return aFont;
2983 }
2984 
updateSettings(AllSettings & rSettings)2985 bool GtkSalGraphics::updateSettings(AllSettings& rSettings)
2986 {
2987     GtkWidget* pTopLevel = gtk_widget_get_toplevel(mpWindow);
2988     GtkStyleContext* pStyle = gtk_widget_get_style_context(pTopLevel);
2989     StyleContextSave aContextState;
2990     aContextState.save(pStyle);
2991     GtkSettings* pSettings = gtk_widget_get_settings(pTopLevel);
2992     StyleSettings aStyleSet = rSettings.GetStyleSettings();
2993     GdkRGBA color;
2994 
2995     // text colors
2996     GdkRGBA text_color;
2997     style_context_set_state(pStyle, GTK_STATE_FLAG_NORMAL);
2998     gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), &text_color);
2999     ::Color aTextColor = getColor( text_color );
3000     aStyleSet.SetDialogTextColor( aTextColor );
3001     aStyleSet.SetButtonTextColor( aTextColor );
3002     aStyleSet.SetDefaultActionButtonTextColor(aTextColor);
3003     aStyleSet.SetActionButtonTextColor(aTextColor);
3004     aStyleSet.SetRadioCheckTextColor( aTextColor );
3005     aStyleSet.SetGroupTextColor( aTextColor );
3006     aStyleSet.SetLabelTextColor( aTextColor );
3007     aStyleSet.SetWindowTextColor( aTextColor );
3008     aStyleSet.SetFieldTextColor( aTextColor );
3009 
3010     // background colors
3011     GdkRGBA background_color;
3012     gtk_style_context_get_background_color(pStyle, gtk_style_context_get_state(pStyle), &background_color);
3013 
3014     ::Color aBackColor = getColor( background_color );
3015     aStyleSet.BatchSetBackgrounds( aBackColor );
3016 
3017     // UI font
3018     vcl::Font aFont(getFont(pStyle, rSettings.GetUILanguageTag().getLocale()));
3019 
3020     aStyleSet.BatchSetFonts( aFont, aFont);
3021 
3022     aFont.SetWeight( WEIGHT_BOLD );
3023     aStyleSet.SetTitleFont( aFont );
3024     aStyleSet.SetFloatTitleFont( aFont );
3025 
3026     // mouse over text colors
3027     style_context_set_state(pStyle, GTK_STATE_FLAG_PRELIGHT);
3028     gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), &text_color);
3029     aTextColor = getColor( text_color );
3030     aStyleSet.SetButtonRolloverTextColor(aTextColor);
3031     aStyleSet.SetActionButtonRolloverTextColor(aTextColor);
3032     aStyleSet.SetFieldRolloverTextColor( aTextColor );
3033 
3034     aContextState.restore();
3035 
3036     // button mouse over colors
3037     {
3038         GdkRGBA normal_button_rollover_text_color, pressed_button_rollover_text_color;
3039         aContextState.save(mpButtonStyle);
3040         style_context_set_state(mpButtonStyle, GTK_STATE_FLAG_PRELIGHT);
3041         gtk_style_context_get_color(mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &normal_button_rollover_text_color);
3042         aTextColor = getColor(normal_button_rollover_text_color);
3043         aStyleSet.SetButtonRolloverTextColor( aTextColor );
3044         style_context_set_state(mpButtonStyle, static_cast<GtkStateFlags>(GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_ACTIVE));
3045         gtk_style_context_get_color(mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &pressed_button_rollover_text_color);
3046         aTextColor = getColor(pressed_button_rollover_text_color);
3047         style_context_set_state(mpButtonStyle, GTK_STATE_FLAG_NORMAL);
3048         aStyleSet.SetButtonPressedRolloverTextColor( aTextColor );
3049         aContextState.restore();
3050     }
3051 
3052     // tooltip colors
3053     {
3054         GtkWidgetPath *pCPath = gtk_widget_path_new();
3055         guint pos = gtk_widget_path_append_type(pCPath, GTK_TYPE_WINDOW);
3056         gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_TOOLTIP);
3057         pos = gtk_widget_path_append_type (pCPath, GTK_TYPE_LABEL);
3058         gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_LABEL);
3059         GtkStyleContext *pCStyle = makeContext (pCPath, nullptr);
3060         aContextState.save(pCStyle);
3061 
3062         GdkRGBA tooltip_bg_color, tooltip_fg_color;
3063         style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
3064         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &tooltip_fg_color);
3065         gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &tooltip_bg_color);
3066 
3067         aContextState.restore();
3068         g_object_unref( pCStyle );
3069 
3070         aStyleSet.SetHelpColor( getColor( tooltip_bg_color ));
3071         aStyleSet.SetHelpTextColor( getColor( tooltip_fg_color ));
3072     }
3073 
3074     {
3075         // construct style context for text view
3076         GtkWidgetPath *pCPath = gtk_widget_path_new();
3077         gtk_widget_path_append_type( pCPath, GTK_TYPE_TEXT_VIEW );
3078         gtk_widget_path_iter_add_class( pCPath, -1, GTK_STYLE_CLASS_VIEW );
3079         GtkStyleContext *pCStyle = makeContext( pCPath, nullptr );
3080         aContextState.save(pCStyle);
3081 
3082         // highlighting colors
3083         style_context_set_state(pCStyle, GTK_STATE_FLAG_SELECTED);
3084         gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
3085         ::Color aHighlightColor = getColor( text_color );
3086         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
3087         ::Color aHighlightTextColor = getColor( text_color );
3088         aStyleSet.SetHighlightColor( aHighlightColor );
3089         aStyleSet.SetHighlightTextColor( aHighlightTextColor );
3090 
3091         // field background color
3092         GdkRGBA field_background_color;
3093         style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
3094         gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &field_background_color);
3095 
3096         ::Color aBackFieldColor = getColor( field_background_color );
3097         aStyleSet.SetFieldColor( aBackFieldColor );
3098         // This baby is the default page/paper color
3099         aStyleSet.SetWindowColor( aBackFieldColor );
3100 
3101         // Cursor width
3102         gfloat caretAspectRatio = 0.04f;
3103         gtk_style_context_get_style( pCStyle, "cursor-aspect-ratio", &caretAspectRatio, nullptr );
3104         // Assume 20px tall for the ratio computation, which should give reasonable results
3105         aStyleSet.SetCursorSize( 20 * caretAspectRatio + 1 );
3106 
3107         // Dark shadow color
3108         style_context_set_state(pCStyle, GTK_STATE_FLAG_INSENSITIVE);
3109         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &color);
3110         ::Color aDarkShadowColor = getColor( color );
3111         aStyleSet.SetDarkShadowColor( aDarkShadowColor );
3112 
3113         ::Color aShadowColor(aBackColor);
3114         if (aDarkShadowColor.GetLuminance() > aBackColor.GetLuminance())
3115             aShadowColor.IncreaseLuminance(64);
3116         else
3117             aShadowColor.DecreaseLuminance(64);
3118         aStyleSet.SetShadowColor(aShadowColor);
3119 
3120         aContextState.restore();
3121         g_object_unref( pCStyle );
3122 
3123         // Tab colors
3124         aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color.
3125         aStyleSet.SetInactiveTabColor( aBackColor );
3126     }
3127 
3128     // menu disabled entries handling
3129     aStyleSet.SetSkipDisabledInMenus( true );
3130     aStyleSet.SetPreferredContextMenuShortcuts( false );
3131 
3132     aContextState.save(mpMenuItemLabelStyle);
3133 
3134     // menu colors
3135     style_context_set_state(mpMenuStyle, GTK_STATE_FLAG_NORMAL);
3136     gtk_style_context_get_background_color( mpMenuStyle, gtk_style_context_get_state(mpMenuStyle), &background_color );
3137     aBackColor = getColor( background_color );
3138     aStyleSet.SetMenuColor( aBackColor );
3139 
3140     // menu bar
3141     style_context_set_state(mpMenuBarStyle, GTK_STATE_FLAG_NORMAL);
3142     gtk_style_context_get_background_color( mpMenuBarStyle, gtk_style_context_get_state(mpMenuBarStyle), &background_color );
3143     aBackColor = getColor( background_color );
3144     aStyleSet.SetMenuBarColor( aBackColor );
3145     aStyleSet.SetMenuBarRolloverColor( aBackColor );
3146 
3147     style_context_set_state(mpMenuBarItemStyle, GTK_STATE_FLAG_NORMAL);
3148     gtk_style_context_get_color( mpMenuBarItemStyle, gtk_style_context_get_state(mpMenuBarItemStyle), &text_color );
3149     aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( text_color ) );
3150     aStyleSet.SetMenuBarTextColor( aTextColor );
3151     aStyleSet.SetMenuBarRolloverTextColor( aTextColor );
3152 
3153     style_context_set_state(mpMenuBarItemStyle, GTK_STATE_FLAG_PRELIGHT);
3154     gtk_style_context_get_color( mpMenuBarItemStyle, gtk_style_context_get_state(mpMenuBarItemStyle), &text_color );
3155     aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( text_color ) );
3156     aStyleSet.SetMenuBarHighlightTextColor( aTextColor );
3157 
3158     // menu items
3159     style_context_set_state(mpMenuItemLabelStyle, GTK_STATE_FLAG_NORMAL);
3160     gtk_style_context_get_color(mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &color);
3161     aTextColor = getColor(color);
3162     aStyleSet.SetMenuTextColor(aTextColor);
3163 
3164     style_context_set_state(mpMenuItemLabelStyle, GTK_STATE_FLAG_PRELIGHT);
3165     gtk_style_context_get_background_color( mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &background_color );
3166     ::Color aHighlightColor = getColor( background_color );
3167     aStyleSet.SetMenuHighlightColor( aHighlightColor );
3168 
3169     gtk_style_context_get_color( mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &color );
3170     ::Color aHighlightTextColor = getColor( color );
3171     aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
3172 
3173     aContextState.restore();
3174 
3175     // hyperlink colors
3176     aContextState.save(mpLinkButtonStyle);
3177     style_context_set_state(mpLinkButtonStyle, GTK_STATE_FLAG_LINK);
3178     gtk_style_context_get_color(mpLinkButtonStyle, gtk_style_context_get_state(mpLinkButtonStyle), &text_color);
3179     aStyleSet.SetLinkColor(getColor(text_color));
3180     style_context_set_state(mpLinkButtonStyle, GTK_STATE_FLAG_VISITED);
3181     gtk_style_context_get_color(mpLinkButtonStyle, gtk_style_context_get_state(mpLinkButtonStyle), &text_color);
3182     aStyleSet.SetVisitedLinkColor(getColor(text_color));
3183     aContextState.restore();
3184 
3185     {
3186         GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabLabelStyle;
3187         aContextState.save(pCStyle);
3188         style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
3189         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
3190         aTextColor = getColor( text_color );
3191         aStyleSet.SetTabTextColor(aTextColor);
3192         aStyleSet.SetTabFont(getFont(mpNotebookHeaderTabsTabLabelStyle, rSettings.GetUILanguageTag().getLocale()));
3193         aContextState.restore();
3194     }
3195 
3196     {
3197         GtkStyleContext *pCStyle = mpToolButtonStyle;
3198         aContextState.save(pCStyle);
3199         style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
3200         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
3201         aTextColor = getColor( text_color );
3202         aStyleSet.SetToolTextColor(aTextColor);
3203         aStyleSet.SetToolFont(getFont(mpToolButtonStyle, rSettings.GetUILanguageTag().getLocale()));
3204         aContextState.restore();
3205     }
3206 
3207     // mouse over text colors
3208     {
3209         GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabHoverLabelStyle;
3210         aContextState.save(pCStyle);
3211         style_context_set_state(pCStyle, GTK_STATE_FLAG_PRELIGHT);
3212         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
3213         aTextColor = getColor( text_color );
3214         aStyleSet.SetTabRolloverTextColor(aTextColor);
3215         aContextState.restore();
3216     }
3217 
3218     {
3219         GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabActiveLabelStyle;
3220         aContextState.save(pCStyle);
3221         style_context_set_state(pCStyle, ACTIVE_TAB());
3222         gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
3223         aTextColor = getColor( text_color );
3224         aStyleSet.SetTabHighlightTextColor(aTextColor);
3225         aContextState.restore();
3226     }
3227 
3228     // get cursor blink time
3229     gboolean blink = false;
3230 
3231     g_object_get( pSettings, "gtk-cursor-blink", &blink, nullptr );
3232     if( blink )
3233     {
3234         gint blink_time = static_cast<gint>(STYLE_CURSOR_NOBLINKTIME);
3235         g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, nullptr );
3236         // set the blink_time if there is a setting and it is reasonable
3237         // else leave the default value
3238         if( blink_time > 100 )
3239             aStyleSet.SetCursorBlinkTime( blink_time/2 );
3240     }
3241     else
3242         aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
3243 
3244     MouseSettings aMouseSettings = rSettings.GetMouseSettings();
3245     int iDoubleClickTime, iDoubleClickDistance, iDragThreshold;
3246     static const int MENU_POPUP_DELAY = 225;
3247     g_object_get( pSettings,
3248                   "gtk-double-click-time", &iDoubleClickTime,
3249                   "gtk-double-click-distance", &iDoubleClickDistance,
3250                   "gtk-dnd-drag-threshold", &iDragThreshold,
3251                   nullptr );
3252     aMouseSettings.SetDoubleClickTime( iDoubleClickTime );
3253     aMouseSettings.SetDoubleClickWidth( iDoubleClickDistance );
3254     aMouseSettings.SetDoubleClickHeight( iDoubleClickDistance );
3255     aMouseSettings.SetStartDragWidth( iDragThreshold );
3256     aMouseSettings.SetStartDragHeight( iDragThreshold );
3257     aMouseSettings.SetMenuDelay( MENU_POPUP_DELAY );
3258     rSettings.SetMouseSettings( aMouseSettings );
3259 
3260     gboolean primarybuttonwarps = false;
3261     g_object_get( pSettings,
3262         "gtk-primary-button-warps-slider", &primarybuttonwarps,
3263         nullptr );
3264     aStyleSet.SetPreferredUseImagesInMenus(false);
3265     aStyleSet.SetPrimaryButtonWarpsSlider(primarybuttonwarps);
3266 
3267     // set scrollbar settings
3268     gint min_slider_length = 21;
3269 
3270     // Grab some button style attributes
3271     if (gtk_check_version(3, 20, 0) == nullptr)
3272     {
3273         Size aSize;
3274         QuerySize(mpHScrollbarStyle, aSize);
3275         QuerySize(mpHScrollbarContentsStyle, aSize);
3276         QuerySize(mpHScrollbarTroughStyle, aSize);
3277         QuerySize(mpHScrollbarSliderStyle, aSize);
3278 
3279         gboolean has_forward, has_forward2, has_backward, has_backward2;
3280         gtk_style_context_get_style(mpHScrollbarStyle,
3281                                     "has-forward-stepper", &has_forward,
3282                                     "has-secondary-forward-stepper", &has_forward2,
3283                                     "has-backward-stepper", &has_backward,
3284                                     "has-secondary-backward-stepper", &has_backward2, nullptr);
3285         if (has_forward || has_backward || has_forward2 || has_backward2)
3286             QuerySize(mpHScrollbarButtonStyle, aSize);
3287 
3288         aStyleSet.SetScrollBarSize(aSize.Height());
3289 
3290         gtk_style_context_get(mpVScrollbarSliderStyle, gtk_style_context_get_state(mpVScrollbarSliderStyle),
3291                               "min-height", &min_slider_length,
3292                               nullptr);
3293         aStyleSet.SetMinThumbSize(min_slider_length);
3294     }
3295     else
3296     {
3297         gint slider_width = 14;
3298         gint trough_border = 1;
3299 
3300         gtk_style_context_get_style(mpVScrollbarStyle,
3301                                     "slider-width", &slider_width,
3302                                     "trough-border", &trough_border,
3303                                     "min-slider-length", &min_slider_length,
3304                                     nullptr);
3305         aStyleSet.SetScrollBarSize(slider_width + 2*trough_border);
3306         gint magic = trough_border ? 1 : 0;
3307         aStyleSet.SetMinThumbSize(min_slider_length - magic);
3308     }
3309 
3310     // preferred icon style
3311     gchar* pIconThemeName = nullptr;
3312     gboolean bDarkIconTheme = false;
3313     g_object_get(pSettings, "gtk-icon-theme-name", &pIconThemeName,
3314                             "gtk-application-prefer-dark-theme", &bDarkIconTheme,
3315                             nullptr );
3316     OUString sIconThemeName(OUString::createFromAscii(pIconThemeName));
3317     aStyleSet.SetPreferredIconTheme(sIconThemeName, bDarkIconTheme);
3318     g_free( pIconThemeName );
3319 
3320     aStyleSet.SetToolbarIconSize( ToolbarIconSize::Large );
3321 
3322     // finally update the collected settings
3323     rSettings.SetStyleSettings( aStyleSet );
3324 #if OSL_DEBUG_LEVEL > 1
3325     gchar* pThemeName = NULL;
3326     g_object_get( pSettings, "gtk-theme-name", &pThemeName, nullptr );
3327     fprintf( stderr, "Theme name is \"%s\"\n", pThemeName );
3328     g_free(pThemeName);
3329 #endif
3330 
3331     return true;
3332 }
3333 
isNativeControlSupported(ControlType nType,ControlPart nPart)3334 bool GtkSalGraphics::isNativeControlSupported( ControlType nType, ControlPart nPart )
3335 {
3336     switch(nType)
3337     {
3338         case ControlType::Pushbutton:
3339         case ControlType::Radiobutton:
3340         case ControlType::Checkbox:
3341         case ControlType::Progress:
3342         case ControlType::ListNode:
3343         case ControlType::ListNet:
3344             if (nPart==ControlPart::Entire || nPart == ControlPart::Focus)
3345                 return true;
3346             break;
3347 
3348         case ControlType::Scrollbar:
3349             if(nPart==ControlPart::DrawBackgroundHorz || nPart==ControlPart::DrawBackgroundVert ||
3350                nPart==ControlPart::Entire       || nPart==ControlPart::HasThreeButtons)
3351                 return true;
3352             break;
3353 
3354         case ControlType::Editbox:
3355         case ControlType::MultilineEditbox:
3356             if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture)
3357                 return true;
3358             break;
3359 
3360         case ControlType::Combobox:
3361             if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::AllButtons)
3362                 return true;
3363             break;
3364 
3365         case ControlType::Spinbox:
3366             if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::AllButtons || nPart == ControlPart::ButtonUp || nPart == ControlPart::ButtonDown)
3367                 return true;
3368             break;
3369 
3370         case ControlType::SpinButtons:
3371             if (nPart==ControlPart::Entire || nPart==ControlPart::AllButtons)
3372                 return true;
3373             break;
3374 
3375         case ControlType::Frame:
3376         case ControlType::WindowBackground:
3377             return true;
3378 
3379         case ControlType::TabItem:
3380         case ControlType::TabHeader:
3381         case ControlType::TabPane:
3382         case ControlType::TabBody:
3383             if(nPart==ControlPart::Entire || nPart==ControlPart::TabsDrawRtl)
3384                 return true;
3385             break;
3386 
3387         case ControlType::Listbox:
3388             if (nPart==ControlPart::Entire || nPart==ControlPart::ListboxWindow || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::Focus)
3389                 return true;
3390             break;
3391 
3392         case ControlType::Toolbar:
3393             if( nPart==ControlPart::Entire
3394 //                ||  nPart==ControlPart::DrawBackgroundHorz
3395 //                ||  nPart==ControlPart::DrawBackgroundVert
3396 //                ||  nPart==ControlPart::ThumbHorz
3397 //                ||  nPart==ControlPart::ThumbVert
3398                 ||  nPart==ControlPart::Button
3399 //                ||  nPart==ControlPart::SeparatorHorz
3400                 ||  nPart==ControlPart::SeparatorVert
3401                 )
3402                 return true;
3403             break;
3404 
3405         case ControlType::Menubar:
3406             if (nPart==ControlPart::Entire || nPart==ControlPart::MenuItem)
3407                 return true;
3408             break;
3409 
3410         case ControlType::MenuPopup:
3411             if (nPart==ControlPart::Entire
3412                 ||  nPart==ControlPart::MenuItem
3413                 ||  nPart==ControlPart::MenuItemCheckMark
3414                 ||  nPart==ControlPart::MenuItemRadioMark
3415                 ||  nPart==ControlPart::Separator
3416                 ||  nPart==ControlPart::SubmenuArrow
3417             )
3418                 return true;
3419             break;
3420 
3421 //        case ControlType::Slider:
3422 //            if(nPart == ControlPart::TrackHorzArea || nPart == ControlPart::TrackVertArea)
3423 //                return true;
3424 //            break;
3425 
3426         case ControlType::Fixedline:
3427             if (nPart == ControlPart::SeparatorVert || nPart == ControlPart::SeparatorHorz)
3428                 return true;
3429             break;
3430 
3431         case ControlType::ListHeader:
3432             if (nPart == ControlPart::Button || nPart == ControlPart::Arrow)
3433                 return true;
3434             break;
3435         default: break;
3436     }
3437 
3438     SAL_INFO("vcl.gtk", "Unhandled is native supported for Type:" << static_cast<int>(nType) << ", Part" << static_cast<int>(nPart));
3439 
3440     return false;
3441 }
3442 
3443 #if ENABLE_CAIRO_CANVAS
3444 
SupportsCairo() const3445 bool GtkSalGraphics::SupportsCairo() const
3446 {
3447     return true;
3448 }
3449 
CreateSurface(const cairo::CairoSurfaceSharedPtr & rSurface) const3450 cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
3451 {
3452     return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(rSurface));
3453 }
3454 
CreateSurface(const OutputDevice &,int x,int y,int width,int height) const3455 cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int x, int y, int width, int height) const
3456 {
3457     return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(this, x, y, width, height));
3458 }
3459 
3460 #endif
3461 
WidgetQueueDraw() const3462 void GtkSalGraphics::WidgetQueueDraw() const
3463 {
3464     //request gtk to sync the entire contents
3465     GtkWidget *pWidget = GTK_WIDGET(mpFrame->getFixedContainer());
3466     gtk_widget_queue_draw(pWidget);
3467 }
3468 
3469 namespace {
3470 
getStyleContext(GtkStyleContext ** style,GtkWidget * widget)3471 void getStyleContext(GtkStyleContext** style, GtkWidget* widget)
3472 {
3473     gtk_container_add(GTK_CONTAINER(gDumbContainer), widget);
3474     *style = gtk_widget_get_style_context(widget);
3475     g_object_ref(*style);
3476 }
3477 
3478 }
3479 
initNWF()3480 void GtkSalData::initNWF()
3481 {
3482     ImplSVData* pSVData = ImplGetSVData();
3483     pSVData->maNWFData.mbFlatMenu = true;
3484     pSVData->maNWFData.mbDockingAreaAvoidTBFrames = true;
3485     pSVData->maNWFData.mbCanDrawWidgetAnySize = true;
3486     pSVData->maNWFData.mbDDListBoxNoTextArea = true;
3487     pSVData->maNWFData.mbNoFocusRects = true;
3488     pSVData->maNWFData.mbNoFocusRectsForFlatButtons = true;
3489     pSVData->maNWFData.mbAutoAccel = true;
3490 
3491 #if defined(GDK_WINDOWING_WAYLAND)
3492     //gnome#768128 for the car crash that is wayland
3493     //and floating dockable toolbars
3494     GdkDisplay *pDisplay = gdk_display_get_default();
3495     if (DLSYM_GDK_IS_WAYLAND_DISPLAY(pDisplay))
3496         pSVData->maNWFData.mbCanDetermineWindowPosition = false;
3497 #endif
3498 }
3499 
deInitNWF()3500 void GtkSalData::deInitNWF()
3501 {
3502     if (gCacheWindow)
3503         gtk_widget_destroy(gCacheWindow);
3504 }
3505 
GtkSalGraphics(GtkSalFrame * pFrame,GtkWidget * pWindow)3506 GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
3507     : SvpSalGraphics(),
3508       mpFrame( pFrame ),
3509       mpWindow( pWindow )
3510 {
3511     if (style_loaded)
3512         return;
3513 
3514     style_loaded = true;
3515 
3516     /* Load the GtkStyleContexts, it might be a bit slow, but usually,
3517      * gtk apps create a lot of widgets at startup, so, it shouldn't be
3518      * too slow */
3519     gtk_widget_path_iter_set_object_nameFunc set_object_name =
3520         reinterpret_cast<gtk_widget_path_iter_set_object_nameFunc>(osl_getAsciiFunctionSymbol(nullptr,
3521             "gtk_widget_path_iter_set_object_name"));
3522 
3523     gCacheWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
3524     gDumbContainer = gtk_fixed_new();
3525     gtk_container_add(GTK_CONTAINER(gCacheWindow), gDumbContainer);
3526     gtk_widget_realize(gDumbContainer);
3527     gtk_widget_realize(gCacheWindow);
3528 
3529     gEntryBox = gtk_entry_new();
3530     gtk_container_add(GTK_CONTAINER(gDumbContainer), gEntryBox);
3531 
3532     mpWindowStyle = createStyleContext(set_object_name, GtkControlPart::ToplevelWindow);
3533     mpEntryStyle = createStyleContext(set_object_name, GtkControlPart::Entry);
3534 
3535     getStyleContext(&mpTextViewStyle, gtk_text_view_new());
3536 
3537     mpButtonStyle = createStyleContext(set_object_name, GtkControlPart::Button);
3538     mpLinkButtonStyle = createStyleContext(set_object_name, GtkControlPart::LinkButton);
3539 
3540     GtkWidget* pToolbar = gtk_toolbar_new();
3541     mpToolbarStyle = gtk_widget_get_style_context(pToolbar);
3542     gtk_style_context_add_class(mpToolbarStyle, GTK_STYLE_CLASS_TOOLBAR);
3543 
3544     GtkToolItem *item = gtk_separator_tool_item_new();
3545     gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
3546     mpToolbarSeperatorStyle = gtk_widget_get_style_context(GTK_WIDGET(item));
3547 
3548     GtkWidget *pButton = gtk_button_new();
3549     item = gtk_tool_button_new(pButton, nullptr);
3550     gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
3551     mpToolButtonStyle = gtk_widget_get_style_context(GTK_WIDGET(pButton));
3552 
3553     mpVScrollbarStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVertical);
3554     mpVScrollbarContentsStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalContents);
3555     mpVScrollbarTroughStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalTrough);
3556     mpVScrollbarSliderStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalSlider);
3557     mpVScrollbarButtonStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarVerticalButton);
3558     mpHScrollbarStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontal);
3559     mpHScrollbarContentsStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalContents);
3560     mpHScrollbarTroughStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalTrough);
3561     mpHScrollbarSliderStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalSlider);
3562     mpHScrollbarButtonStyle = createStyleContext(set_object_name, GtkControlPart::ScrollbarHorizontalButton);
3563 
3564     mpCheckButtonStyle = createStyleContext(set_object_name, GtkControlPart::CheckButton);
3565     mpCheckButtonCheckStyle = createStyleContext(set_object_name, GtkControlPart::CheckButtonCheck);
3566 
3567     mpRadioButtonStyle = createStyleContext(set_object_name, GtkControlPart::RadioButton);
3568     mpRadioButtonRadioStyle = createStyleContext(set_object_name, GtkControlPart::RadioButtonRadio);
3569 
3570     /* Spinbutton */
3571     gSpinBox = gtk_spin_button_new(nullptr, 0, 0);
3572     gtk_container_add(GTK_CONTAINER(gDumbContainer), gSpinBox);
3573     mpSpinStyle = createStyleContext(set_object_name, GtkControlPart::SpinButton);
3574     mpSpinEntryStyle = createStyleContext(set_object_name, GtkControlPart::SpinButtonEntry);
3575     mpSpinUpStyle = createStyleContext(set_object_name, GtkControlPart::SpinButtonUpButton);
3576     mpSpinDownStyle = createStyleContext(set_object_name, GtkControlPart::SpinButtonDownButton);
3577 
3578     /* NoteBook */
3579     mpNotebookStyle = createStyleContext(set_object_name, GtkControlPart::Notebook);
3580     mpNotebookStackStyle = createStyleContext(set_object_name, GtkControlPart::NotebookStack);
3581     mpNotebookHeaderStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeader);
3582     mpNotebookHeaderTabsStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabs);
3583     mpNotebookHeaderTabsTabStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTab);
3584     mpNotebookHeaderTabsTabLabelStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTabLabel);
3585     mpNotebookHeaderTabsTabActiveLabelStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTabActiveLabel);
3586     mpNotebookHeaderTabsTabHoverLabelStyle = createStyleContext(set_object_name, GtkControlPart::NotebookHeaderTabsTabHoverLabel);
3587 
3588     /* Combobox */
3589     gComboBox = gtk_combo_box_text_new_with_entry();
3590     gtk_container_add(GTK_CONTAINER(gDumbContainer), gComboBox);
3591     mpComboboxStyle = createStyleContext(set_object_name, GtkControlPart::Combobox);
3592     mpComboboxBoxStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBox);
3593     mpComboboxEntryStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxEntry);
3594     mpComboboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButton);
3595     mpComboboxButtonBoxStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButtonBox);
3596     mpComboboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::ComboboxBoxButtonBoxArrow);
3597 
3598     /* Listbox */
3599     gListBox = gtk_combo_box_text_new();
3600     gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gListBox), "sample");
3601     gtk_container_add(GTK_CONTAINER(gDumbContainer), gListBox);
3602     mpListboxStyle = createStyleContext(set_object_name, GtkControlPart::Listbox);
3603     mpListboxBoxStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBox);
3604     mpListboxButtonStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButton);
3605     mpListboxButtonBoxStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButtonBox);
3606     mpListboxButtonArrowStyle = createStyleContext(set_object_name, GtkControlPart::ListboxBoxButtonBoxArrow);
3607 
3608     /* Menu bar */
3609     gMenuBarWidget = gtk_menu_bar_new();
3610     gMenuItemMenuBarWidget = gtk_menu_item_new_with_label( "b" );
3611     gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget), gMenuItemMenuBarWidget);
3612     gtk_container_add(GTK_CONTAINER(gDumbContainer), gMenuBarWidget);
3613 
3614     mpMenuBarStyle = createStyleContext(set_object_name, GtkControlPart::MenuBar);
3615     mpMenuBarItemStyle = createStyleContext(set_object_name, GtkControlPart::MenuBarItem);
3616 
3617     /* Menu */
3618     mpMenuWindowStyle = createStyleContext(set_object_name, GtkControlPart::MenuWindow);
3619     mpMenuStyle = createStyleContext(set_object_name, GtkControlPart::Menu);
3620     GtkWidget *menu = gtk_menu_new();
3621     gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuItemMenuBarWidget), menu);
3622 
3623     /* Menu Items */
3624     gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
3625     gtk_menu_shell_append(GTK_MENU_SHELL(menu), gCheckMenuItemWidget);
3626 
3627     mpMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::MenuItem);
3628     mpMenuItemLabelStyle = createStyleContext(set_object_name, GtkControlPart::MenuItemLabel);
3629     mpMenuItemArrowStyle = createStyleContext(set_object_name, GtkControlPart::MenuItemArrow);
3630     mpCheckMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::CheckMenuItem);
3631     mpCheckMenuItemCheckStyle = createStyleContext(set_object_name, GtkControlPart::CheckMenuItemCheck);
3632     mpRadioMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::RadioMenuItem);
3633     mpRadioMenuItemRadioStyle = createStyleContext(set_object_name, GtkControlPart::RadioMenuItemRadio);
3634     mpSeparatorMenuItemStyle = createStyleContext(set_object_name, GtkControlPart::SeparatorMenuItem);
3635     mpSeparatorMenuItemSeparatorStyle = createStyleContext(set_object_name, GtkControlPart::SeparatorMenuItemSeparator);
3636 
3637     /* Frames */
3638     mpFrameOutStyle = mpFrameInStyle = createStyleContext(set_object_name, GtkControlPart::FrameBorder);
3639     getStyleContext(&mpFixedHoriLineStyle, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL));
3640     getStyleContext(&mpFixedVertLineStyle, gtk_separator_new(GTK_ORIENTATION_VERTICAL));
3641 
3642 
3643     /* Tree List */
3644     gTreeViewWidget = gtk_tree_view_new();
3645     gtk_container_add(GTK_CONTAINER(gDumbContainer), gTreeViewWidget);
3646 
3647     GtkTreeViewColumn* firstTreeViewColumn = gtk_tree_view_column_new();
3648     gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
3649     gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
3650 
3651     GtkTreeViewColumn* middleTreeViewColumn = gtk_tree_view_column_new();
3652     gtk_tree_view_column_set_title(middleTreeViewColumn, "M");
3653     gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
3654     gtk_tree_view_set_expander_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
3655 
3656     GtkTreeViewColumn* lastTreeViewColumn = gtk_tree_view_column_new();
3657     gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
3658     gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
3659 
3660     /* Use the middle column's header for our button */
3661     GtkWidget* pTreeHeaderCellWidget = gtk_tree_view_column_get_button(middleTreeViewColumn);
3662     mpTreeHeaderButtonStyle = gtk_widget_get_style_context(pTreeHeaderCellWidget);
3663 
3664     /* Progress Bar */
3665     mpProgressBarStyle = createStyleContext(set_object_name, GtkControlPart::ProgressBar);
3666     mpProgressBarTroughStyle = createStyleContext(set_object_name, GtkControlPart::ProgressBarTrough);
3667     mpProgressBarProgressStyle = createStyleContext(set_object_name, GtkControlPart::ProgressBarProgress);
3668 
3669     gtk_widget_show_all(gDumbContainer);
3670 }
3671 
GetResolution(sal_Int32 & rDPIX,sal_Int32 & rDPIY)3672 void GtkSalGraphics::GetResolution(sal_Int32& rDPIX, sal_Int32& rDPIY)
3673 {
3674     char* pForceDpi;
3675     if ((pForceDpi = getenv("SAL_FORCEDPI")))
3676     {
3677         OString sForceDPI(pForceDpi);
3678         rDPIX = rDPIY = sForceDPI.toInt32();
3679         return;
3680     }
3681 
3682     GdkScreen* pScreen = gtk_widget_get_screen(mpWindow);
3683     double fResolution = -1.0;
3684     g_object_get(pScreen, "resolution", &fResolution, nullptr);
3685 
3686     if (fResolution > 0.0)
3687         rDPIX = rDPIY = sal_Int32(fResolution);
3688     else
3689         rDPIX = rDPIY = 96;
3690 }
3691 
3692 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3693