nss: upgrade to release 3.73
[LibreOffice.git] / vcl / unx / gtk3 / gtk3salnativewidgets-gtk.cxx
blob6e91fc3503d283e7aa48a27e927219933c6a13aa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
11 #include <sal/log.hxx>
12 #include <osl/module.h>
14 #include <config_cairo_canvas.h>
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>
25 #include "cairo_gtk3_cairo.hxx"
26 #include <optional>
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::mpToolbarSeparatorStyle = 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::mpSpinUpStyle = nullptr;
52 GtkStyleContext* GtkSalGraphics::mpSpinDownStyle = nullptr;
53 GtkStyleContext* GtkSalGraphics::mpComboboxStyle = nullptr;
54 GtkStyleContext* GtkSalGraphics::mpComboboxBoxStyle = nullptr;
55 GtkStyleContext* GtkSalGraphics::mpComboboxEntryStyle = nullptr;
56 GtkStyleContext* GtkSalGraphics::mpComboboxButtonStyle = nullptr;
57 GtkStyleContext* GtkSalGraphics::mpComboboxButtonBoxStyle = nullptr;
58 GtkStyleContext* GtkSalGraphics::mpComboboxButtonArrowStyle = nullptr;
59 GtkStyleContext* GtkSalGraphics::mpListboxStyle = nullptr;
60 GtkStyleContext* GtkSalGraphics::mpListboxBoxStyle = nullptr;
61 GtkStyleContext* GtkSalGraphics::mpListboxButtonStyle = nullptr;
62 GtkStyleContext* GtkSalGraphics::mpListboxButtonBoxStyle= nullptr;
63 GtkStyleContext* GtkSalGraphics::mpListboxButtonArrowStyle = nullptr;
64 GtkStyleContext* GtkSalGraphics::mpFrameInStyle = nullptr;
65 GtkStyleContext* GtkSalGraphics::mpFrameOutStyle = nullptr;
66 GtkStyleContext* GtkSalGraphics::mpFixedHoriLineStyle = nullptr;
67 GtkStyleContext* GtkSalGraphics::mpFixedVertLineStyle = nullptr;
68 GtkStyleContext* GtkSalGraphics::mpTreeHeaderButtonStyle = nullptr;
69 GtkStyleContext* GtkSalGraphics::mpProgressBarStyle = nullptr;
70 GtkStyleContext* GtkSalGraphics::mpProgressBarTroughStyle = nullptr;
71 GtkStyleContext* GtkSalGraphics::mpProgressBarProgressStyle = nullptr;
72 GtkStyleContext* GtkSalGraphics::mpNotebookStyle = nullptr;
73 GtkStyleContext* GtkSalGraphics::mpNotebookStackStyle = nullptr;
74 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderStyle = nullptr;
75 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsStyle = nullptr;
76 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabStyle = nullptr;
77 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabLabelStyle = nullptr;
78 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabActiveLabelStyle = nullptr;
79 GtkStyleContext* GtkSalGraphics::mpNotebookHeaderTabsTabHoverLabelStyle = nullptr;
80 GtkStyleContext* GtkSalGraphics::mpMenuBarStyle = nullptr;
81 GtkStyleContext* GtkSalGraphics::mpMenuBarItemStyle = nullptr;
82 GtkStyleContext* GtkSalGraphics::mpMenuWindowStyle = nullptr;
83 GtkStyleContext* GtkSalGraphics::mpMenuStyle = nullptr;
84 GtkStyleContext* GtkSalGraphics::mpMenuItemStyle = nullptr;
85 GtkStyleContext* GtkSalGraphics::mpMenuItemArrowStyle = nullptr;
86 GtkStyleContext* GtkSalGraphics::mpMenuItemLabelStyle = nullptr;
87 GtkStyleContext* GtkSalGraphics::mpCheckMenuItemStyle = nullptr;
88 GtkStyleContext* GtkSalGraphics::mpCheckMenuItemCheckStyle = nullptr;
89 GtkStyleContext* GtkSalGraphics::mpRadioMenuItemStyle = nullptr;
90 GtkStyleContext* GtkSalGraphics::mpRadioMenuItemRadioStyle = nullptr;
91 GtkStyleContext* GtkSalGraphics::mpSeparatorMenuItemStyle = nullptr;
92 GtkStyleContext* GtkSalGraphics::mpSeparatorMenuItemSeparatorStyle = nullptr;
94 bool GtkSalGraphics::style_loaded = false;
95 /************************************************************************
96 * State conversion
97 ************************************************************************/
98 static GtkStateFlags NWConvertVCLStateToGTKState(ControlState nVCLState)
100 GtkStateFlags nGTKState = GTK_STATE_FLAG_NORMAL;
102 if (!( nVCLState & ControlState::ENABLED ))
104 nGTKState = GTK_STATE_FLAG_INSENSITIVE;
107 if ( nVCLState & ControlState::PRESSED )
109 nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_ACTIVE);
112 if ( nVCLState & ControlState::ROLLOVER )
114 nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_PRELIGHT);
117 if ( nVCLState & ControlState::SELECTED )
118 nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_SELECTED);
120 if ( nVCLState & ControlState::FOCUSED )
121 nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_FOCUSED);
123 if (AllSettings::GetLayoutRTL())
125 nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_DIR_RTL);
127 else
129 nGTKState = static_cast<GtkStateFlags>(nGTKState | GTK_STATE_FLAG_DIR_LTR);
132 return nGTKState;
135 namespace {
137 enum class RenderType {
138 BackgroundAndFrame = 1,
139 Check,
140 Background,
141 MenuSeparator,
142 ToolbarSeparator,
143 Separator,
144 Arrow,
145 Radio,
146 Scrollbar,
147 Spinbutton,
148 Combobox,
149 Expander,
150 Icon,
151 Progress,
152 TabItem,
153 Focus
158 static void NWCalcArrowRect( const tools::Rectangle& rButton, tools::Rectangle& rArrow )
160 // Size the arrow appropriately
161 Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
162 rArrow.SetSize( aSize );
164 rArrow.SetPos( Point(
165 rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2,
166 rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
167 ) );
170 tools::Rectangle GtkSalGraphics::NWGetSpinButtonRect( ControlPart nPart, tools::Rectangle aAreaRect)
172 gint w, h;
173 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
174 gint icon_size = std::max(w, h);
176 GtkBorder padding, border;
177 gtk_style_context_get_padding(mpSpinUpStyle, gtk_style_context_get_state(mpSpinUpStyle), &padding);
178 gtk_style_context_get_border(mpSpinUpStyle, gtk_style_context_get_state(mpSpinUpStyle), &border);
180 gint buttonWidth = icon_size + padding.left + padding.right +
181 border.left + border.right;
183 gint buttonHeight = icon_size + padding.top + padding.bottom +
184 border.top + border.bottom;
186 tools::Rectangle buttonRect;
187 buttonRect.SetSize(Size(buttonWidth, buttonHeight));
188 buttonRect.setY(aAreaRect.Top());
189 buttonRect.SetBottom( buttonRect.Top() + aAreaRect.GetHeight() );
190 tools::Rectangle partRect(buttonRect);
191 if ( nPart == ControlPart::ButtonUp )
193 if (AllSettings::GetLayoutRTL())
194 partRect.setX(aAreaRect.Left());
195 else
196 partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()));
198 else if( nPart == ControlPart::ButtonDown )
200 if (AllSettings::GetLayoutRTL())
201 partRect.setX(aAreaRect.Left() + buttonRect.GetWidth());
202 else
203 partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth()));
205 else
207 if (AllSettings::GetLayoutRTL())
209 partRect.SetRight( aAreaRect.Left() + aAreaRect.GetWidth() );
210 partRect.SetLeft( aAreaRect.Left() + (2 * buttonRect.GetWidth()) - 1 );
212 else
214 partRect.SetRight( (aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth())) - 1 );
215 partRect.SetLeft( aAreaRect.Left() );
217 partRect.SetTop( aAreaRect.Top() );
218 partRect.SetBottom( aAreaRect.Bottom() );
221 return partRect;
224 namespace
226 void QuerySize(GtkStyleContext *pContext, Size &rSize)
228 GtkBorder margin, border, padding;
229 GtkStateFlags stateflags = gtk_style_context_get_state (pContext);
231 gtk_style_context_get_margin(pContext, stateflags, &margin);
232 gtk_style_context_get_border(pContext, stateflags, &border);
233 gtk_style_context_get_padding(pContext, stateflags, &padding);
235 int nMinWidth, nMinHeight;
236 gtk_style_context_get(pContext, stateflags,
237 "min-width", &nMinWidth, "min-height", &nMinHeight, nullptr);
239 nMinWidth += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
240 nMinHeight += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
242 rSize = Size(std::max<tools::Long>(rSize.Width(), nMinWidth), std::max<tools::Long>(rSize.Height(), nMinHeight));
246 tools::Rectangle GtkSalGraphics::NWGetScrollButtonRect( ControlPart nPart, tools::Rectangle aAreaRect )
248 tools::Rectangle buttonRect;
250 gboolean has_forward;
251 gboolean has_forward2;
252 gboolean has_backward;
253 gboolean has_backward2;
255 GtkStyleContext* pScrollbarStyle = nullptr;
256 if ((nPart == ControlPart::ButtonLeft) || (nPart == ControlPart::ButtonRight))
257 pScrollbarStyle = mpHScrollbarStyle;
258 else // (nPart == ControlPart::ButtonUp) || (nPart == ControlPart::ButtonDown)
259 pScrollbarStyle = mpVScrollbarStyle;
261 gtk_style_context_get_style( pScrollbarStyle,
262 "has-forward-stepper", &has_forward,
263 "has-secondary-forward-stepper", &has_forward2,
264 "has-backward-stepper", &has_backward,
265 "has-secondary-backward-stepper", &has_backward2, nullptr );
267 gint nFirst = 0;
268 gint nSecond = 0;
270 if ( has_forward ) nSecond += 1;
271 if ( has_forward2 ) nFirst += 1;
272 if ( has_backward ) nFirst += 1;
273 if ( has_backward2 ) nSecond += 1;
275 Size aSize;
276 if (nPart == ControlPart::ButtonLeft || nPart == ControlPart::ButtonRight)
278 QuerySize(mpHScrollbarStyle, aSize);
279 QuerySize(mpHScrollbarContentsStyle, aSize);
280 QuerySize(mpHScrollbarButtonStyle, aSize);
282 else
284 QuerySize(mpVScrollbarStyle, aSize);
285 QuerySize(mpVScrollbarContentsStyle, aSize);
286 QuerySize(mpVScrollbarButtonStyle, aSize);
289 if (nPart == ControlPart::ButtonUp)
291 aSize.setHeight( aSize.Height() * nFirst );
292 buttonRect.setX(aAreaRect.Left());
293 buttonRect.setY(aAreaRect.Top());
295 else if (nPart == ControlPart::ButtonLeft)
297 aSize.setWidth( aSize.Width() * nFirst );
298 buttonRect.setX(aAreaRect.Left());
299 buttonRect.setY(aAreaRect.Top());
301 else if (nPart == ControlPart::ButtonDown)
303 aSize.setHeight( aSize.Height() * nSecond );
304 buttonRect.setX(aAreaRect.Left());
305 buttonRect.setY(aAreaRect.Top() + aAreaRect.GetHeight() - aSize.Height());
307 else if (nPart == ControlPart::ButtonRight)
309 aSize.setWidth( aSize.Width() * nSecond );
310 buttonRect.setX(aAreaRect.Left() + aAreaRect.GetWidth() - aSize.Width());
311 buttonRect.setY(aAreaRect.Top());
314 buttonRect.SetSize(aSize);
316 return buttonRect;
319 static GtkWidget* gCacheWindow;
320 static GtkWidget* gDumbContainer;
321 static GtkWidget* gSpinBox;
322 static GtkWidget* gEntryBox;
323 static GtkWidget* gComboBox;
324 static GtkWidget* gListBox;
325 static GtkWidget* gTreeViewWidget;
327 namespace
329 void style_context_set_state(GtkStyleContext* context, GtkStateFlags flags)
333 gtk_style_context_set_state(context, flags);
335 while ((context = gtk_style_context_get_parent(context)));
338 class StyleContextSave
340 private:
341 std::vector<std::pair<GtkStyleContext*, GtkStateFlags>> m_aStates;
342 public:
343 void save(GtkStyleContext* context)
347 m_aStates.emplace_back(context, gtk_style_context_get_state(context));
349 while ((context = gtk_style_context_get_parent(context)));
351 void restore()
353 for (auto a = m_aStates.rbegin(); a != m_aStates.rend(); ++a)
355 gtk_style_context_set_state(a->first, a->second);
357 m_aStates.clear();
361 tools::Rectangle render_common(GtkStyleContext *pContext, cairo_t *cr, const tools::Rectangle &rIn, GtkStateFlags flags)
363 if (!pContext)
364 return rIn;
366 gtk_style_context_set_state(pContext, flags);
368 tools::Rectangle aRect(rIn);
369 GtkBorder margin;
370 gtk_style_context_get_margin(pContext, gtk_style_context_get_state(pContext), &margin);
372 aRect.AdjustLeft(margin.left );
373 aRect.AdjustTop(margin.top );
374 aRect.AdjustRight( -(margin.right) );
375 aRect.AdjustBottom( -(margin.bottom) );
377 gtk_render_background(pContext, cr, aRect.Left(), aRect.Top(),
378 aRect.GetWidth(), aRect.GetHeight());
379 gtk_render_frame(pContext, cr, aRect.Left(), aRect.Top(),
380 aRect.GetWidth(), aRect.GetHeight());
382 GtkBorder border, padding;
383 gtk_style_context_get_border(pContext, gtk_style_context_get_state(pContext), &border);
384 gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &padding);
386 aRect.AdjustLeft(border.left + padding.left );
387 aRect.AdjustTop(border.top + padding.top );
388 aRect.AdjustRight( -(border.right + padding.right) );
389 aRect.AdjustBottom( -(border.bottom + padding.bottom) );
391 return aRect;
395 void GtkSalGraphics::PaintScrollbar(GtkStyleContext *context,
396 cairo_t *cr,
397 const tools::Rectangle& rControlRectangle,
398 ControlPart nPart,
399 const ImplControlValue& rValue )
401 assert(rValue.getType() == ControlType::Scrollbar);
402 const ScrollbarValue& rScrollbarVal = static_cast<const ScrollbarValue&>(rValue);
403 tools::Rectangle scrollbarRect;
404 GtkStateFlags stateFlags;
405 GtkOrientation scrollbarOrientation;
406 tools::Rectangle thumbRect = rScrollbarVal.maThumbRect;
407 tools::Rectangle button11BoundRect = rScrollbarVal.maButton1Rect; // backward
408 tools::Rectangle button22BoundRect = rScrollbarVal.maButton2Rect; // forward
409 tools::Rectangle button12BoundRect = rScrollbarVal.maButton1Rect; // secondary forward
410 tools::Rectangle button21BoundRect = rScrollbarVal.maButton2Rect; // secondary backward
411 gdouble arrow1Angle; // backward
412 gdouble arrow2Angle; // forward
413 tools::Rectangle arrowRect;
414 gint slider_width = 0;
415 gint stepper_size = 0;
417 // make controlvalue rectangles relative to area
418 thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
419 button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
420 button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
421 button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
422 button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
424 // Find the overall bounding rect of the control
425 scrollbarRect = rControlRectangle;
426 if (scrollbarRect.IsEmpty())
427 return;
429 gint slider_side;
430 Size aSize;
431 if (nPart == ControlPart::DrawBackgroundHorz)
433 QuerySize(mpHScrollbarStyle, aSize);
434 QuerySize(mpHScrollbarContentsStyle, aSize);
435 QuerySize(mpHScrollbarTroughStyle, aSize);
436 QuerySize(mpHScrollbarSliderStyle, aSize);
437 slider_side = aSize.Height();
438 gtk_style_context_get(mpHScrollbarButtonStyle,
439 gtk_style_context_get_state(mpHScrollbarButtonStyle),
440 "min-height", &slider_width,
441 "min-width", &stepper_size, nullptr);
443 else
445 QuerySize(mpVScrollbarStyle, aSize);
446 QuerySize(mpVScrollbarContentsStyle, aSize);
447 QuerySize(mpVScrollbarTroughStyle, aSize);
448 QuerySize(mpVScrollbarSliderStyle, aSize);
449 slider_side = aSize.Width();
450 gtk_style_context_get(mpVScrollbarButtonStyle,
451 gtk_style_context_get_state(mpVScrollbarButtonStyle),
452 "min-width", &slider_width,
453 "min-height", &stepper_size, nullptr);
456 gboolean has_forward;
457 gboolean has_forward2;
458 gboolean has_backward;
459 gboolean has_backward2;
461 gtk_style_context_get_style( context,
462 "has-forward-stepper", &has_forward,
463 "has-secondary-forward-stepper", &has_forward2,
464 "has-backward-stepper", &has_backward,
465 "has-secondary-backward-stepper", &has_backward2, nullptr );
467 if ( nPart == ControlPart::DrawBackgroundHorz )
469 // Center vertically in the track
470 scrollbarRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
471 scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), slider_side ) );
472 thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
473 thumbRect.SetSize( Size( thumbRect.GetWidth(), slider_side ) );
475 scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
476 arrow1Angle = G_PI * 3 / 2;
477 arrow2Angle = G_PI / 2;
479 if ( has_backward )
481 button12BoundRect.Move( stepper_size,
482 (scrollbarRect.GetHeight() - slider_width) / 2 );
485 button11BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
486 button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
487 button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
489 if ( has_backward2 )
491 button22BoundRect.Move( stepper_size, (scrollbarRect.GetHeight() - slider_width) / 2 );
492 button21BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
494 else
496 button22BoundRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
499 button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
500 button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
502 else
504 // Center horizontally in the track
505 scrollbarRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
506 scrollbarRect.SetSize( Size( slider_side, scrollbarRect.GetHeight() ) );
507 thumbRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
508 thumbRect.SetSize( Size( slider_side, thumbRect.GetHeight() ) );
510 scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
511 arrow1Angle = 0;
512 arrow2Angle = G_PI;
514 if ( has_backward )
516 button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
517 stepper_size );
519 button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
520 button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
521 button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
523 if ( has_backward2 )
525 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size );
526 button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
528 else
530 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
533 button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
534 button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
537 bool has_slider = !thumbRect.IsEmpty();
539 // ----------------- CONTENTS
540 GtkStyleContext* pScrollbarContentsStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
541 mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
543 gtk_render_background(gtk_widget_get_style_context(gCacheWindow), cr, 0, 0,
544 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
546 gtk_render_background(context, cr, 0, 0,
547 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
548 gtk_render_frame(context, cr, 0, 0,
549 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
551 gtk_render_background(pScrollbarContentsStyle, cr, 0, 0,
552 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
553 gtk_render_frame(pScrollbarContentsStyle, cr, 0, 0,
554 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
556 bool backwardButtonInsensitive =
557 rScrollbarVal.mnCur == rScrollbarVal.mnMin;
558 bool forwardButtonInsensitive = rScrollbarVal.mnMax == 0 ||
559 rScrollbarVal.mnCur + rScrollbarVal.mnVisibleSize >= rScrollbarVal.mnMax;
561 // ----------------- BUTTON 1
562 if ( has_backward )
564 stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
565 if ( backwardButtonInsensitive )
566 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
568 GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
569 mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
571 gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
573 gtk_render_background(pScrollbarButtonStyle, cr,
574 button11BoundRect.Left(), button11BoundRect.Top(),
575 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
576 gtk_render_frame(pScrollbarButtonStyle, cr,
577 button11BoundRect.Left(), button11BoundRect.Top(),
578 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
580 // ----------------- ARROW 1
581 NWCalcArrowRect( button11BoundRect, arrowRect );
582 gtk_render_arrow(pScrollbarButtonStyle, cr,
583 arrow1Angle,
584 arrowRect.Left(), arrowRect.Top(),
585 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
587 if ( has_forward2 )
589 stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
590 if ( forwardButtonInsensitive )
591 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
593 GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
594 mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
596 gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
598 gtk_render_background(pScrollbarButtonStyle, cr,
599 button12BoundRect.Left(), button12BoundRect.Top(),
600 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
601 gtk_render_frame(pScrollbarButtonStyle, cr,
602 button12BoundRect.Left(), button12BoundRect.Top(),
603 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
605 // ----------------- ARROW 1
606 NWCalcArrowRect( button12BoundRect, arrowRect );
607 gtk_render_arrow(pScrollbarButtonStyle, cr,
608 arrow2Angle,
609 arrowRect.Left(), arrowRect.Top(),
610 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
612 // ----------------- BUTTON 2
614 if ( has_forward )
616 stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton2State);
617 if ( forwardButtonInsensitive )
618 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
620 GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
621 mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
623 gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
625 gtk_render_background(pScrollbarButtonStyle, cr,
626 button22BoundRect.Left(), button22BoundRect.Top(),
627 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
628 gtk_render_frame(pScrollbarButtonStyle, cr,
629 button22BoundRect.Left(), button22BoundRect.Top(),
630 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
632 // ----------------- ARROW 2
633 NWCalcArrowRect( button22BoundRect, arrowRect );
634 gtk_render_arrow(pScrollbarButtonStyle, cr,
635 arrow2Angle,
636 arrowRect.Left(), arrowRect.Top(),
637 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
640 if ( has_backward2 )
642 stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnButton1State);
643 if ( backwardButtonInsensitive )
644 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
646 GtkStyleContext* pScrollbarButtonStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
647 mpVScrollbarButtonStyle : mpHScrollbarButtonStyle;
649 gtk_style_context_set_state(pScrollbarButtonStyle, stateFlags);
651 gtk_render_background(pScrollbarButtonStyle, cr,
652 button21BoundRect.Left(), button21BoundRect.Top(),
653 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
654 gtk_render_frame(pScrollbarButtonStyle, cr,
655 button21BoundRect.Left(), button21BoundRect.Top(),
656 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
658 // ----------------- ARROW 2
659 NWCalcArrowRect( button21BoundRect, arrowRect );
660 gtk_render_arrow(pScrollbarButtonStyle, cr,
661 arrow1Angle,
662 arrowRect.Left(), arrowRect.Top(),
663 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
666 // ----------------- TROUGH
667 // trackrect matches that of ScrollBar::ImplCalc
668 tools::Rectangle aTrackRect(Point(0, 0), scrollbarRect.GetSize());
669 if (nPart == ControlPart::DrawBackgroundHorz)
671 tools::Rectangle aBtn1Rect = NWGetScrollButtonRect(ControlPart::ButtonLeft, aTrackRect);
672 tools::Rectangle aBtn2Rect = NWGetScrollButtonRect(ControlPart::ButtonRight, aTrackRect);
673 if (!aBtn1Rect.IsWidthEmpty())
674 aTrackRect.SetLeft( aBtn1Rect.Right() );
675 if (!aBtn2Rect.IsWidthEmpty())
676 aTrackRect.SetRight( aBtn2Rect.Left() );
678 else
680 tools::Rectangle aBtn1Rect = NWGetScrollButtonRect(ControlPart::ButtonUp, aTrackRect);
681 tools::Rectangle aBtn2Rect = NWGetScrollButtonRect(ControlPart::ButtonDown, aTrackRect);
682 if (!aBtn1Rect.IsHeightEmpty())
683 aTrackRect.SetTop( aBtn1Rect.Bottom() + 1 );
684 if (!aBtn2Rect.IsHeightEmpty())
685 aTrackRect.SetBottom( aBtn2Rect.Top() );
688 GtkStyleContext* pScrollbarTroughStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
689 mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
690 gtk_render_background(pScrollbarTroughStyle, cr, aTrackRect.Left(), aTrackRect.Top(),
691 aTrackRect.GetWidth(), aTrackRect.GetHeight() );
692 gtk_render_frame(pScrollbarTroughStyle, cr, aTrackRect.Left(), aTrackRect.Top(),
693 aTrackRect.GetWidth(), aTrackRect.GetHeight() );
695 // ----------------- THUMB
696 if ( has_slider )
698 stateFlags = NWConvertVCLStateToGTKState(rScrollbarVal.mnThumbState);
699 if ( rScrollbarVal.mnThumbState & ControlState::PRESSED )
700 stateFlags = static_cast<GtkStateFlags>(stateFlags | GTK_STATE_FLAG_PRELIGHT);
702 GtkStyleContext* pScrollbarSliderStyle = scrollbarOrientation == GTK_ORIENTATION_VERTICAL ?
703 mpVScrollbarSliderStyle : mpHScrollbarSliderStyle;
705 gtk_style_context_set_state(pScrollbarSliderStyle, stateFlags);
707 GtkBorder margin;
708 gtk_style_context_get_margin(pScrollbarSliderStyle, stateFlags, &margin);
710 gtk_render_background(pScrollbarSliderStyle, cr,
711 thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
712 thumbRect.GetWidth() - margin.left - margin.right,
713 thumbRect.GetHeight() - margin.top - margin.bottom);
715 gtk_render_frame(pScrollbarSliderStyle, cr,
716 thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
717 thumbRect.GetWidth() - margin.left - margin.right,
718 thumbRect.GetHeight() - margin.top - margin.bottom);
722 void GtkSalGraphics::PaintOneSpinButton( GtkStyleContext *context,
723 cairo_t *cr,
724 ControlPart nPart,
725 tools::Rectangle aAreaRect,
726 ControlState nState )
728 GtkBorder padding, border;
730 GtkStateFlags stateFlags = NWConvertVCLStateToGTKState(nState);
731 tools::Rectangle buttonRect = NWGetSpinButtonRect( nPart, aAreaRect );
733 gtk_style_context_set_state(context, stateFlags);
734 stateFlags = gtk_style_context_get_state(context);
736 gtk_style_context_get_padding(context, stateFlags, &padding);
737 gtk_style_context_get_border(context, stateFlags, &border);
739 gtk_render_background(context, cr,
740 buttonRect.Left(), buttonRect.Top(),
741 buttonRect.GetWidth(), buttonRect.GetHeight() );
743 gint iconWidth = buttonRect.GetWidth() - padding.left - padding.right - border.left - border.right;
744 gint iconHeight = buttonRect.GetHeight() - padding.top - padding.bottom - border.top - border.bottom;
746 const char* icon = (nPart == ControlPart::ButtonUp) ? "list-add-symbolic" : "list-remove-symbolic";
747 GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
749 gint scale = gtk_style_context_get_scale (context);
750 GtkIconInfo *info = gtk_icon_theme_lookup_icon_for_scale(pIconTheme, icon, std::min(iconWidth, iconHeight), scale,
751 static_cast<GtkIconLookupFlags>(0));
753 GdkPixbuf *pixbuf = gtk_icon_info_load_symbolic_for_context(info, context, nullptr, nullptr);
754 g_object_unref(info);
756 iconWidth = gdk_pixbuf_get_width(pixbuf)/scale;
757 iconHeight = gdk_pixbuf_get_height(pixbuf)/scale;
758 tools::Rectangle arrowRect;
759 arrowRect.SetSize(Size(iconWidth, iconHeight));
760 arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
761 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 );
763 gtk_style_context_save (context);
764 gtk_style_context_set_scale (context, 1);
765 gtk_render_icon(context, cr, pixbuf, arrowRect.Left(), arrowRect.Top());
766 gtk_style_context_restore (context);
767 g_object_unref(pixbuf);
769 gtk_render_frame(context, cr,
770 buttonRect.Left(), buttonRect.Top(),
771 buttonRect.GetWidth(), buttonRect.GetHeight() );
774 void GtkSalGraphics::PaintSpinButton(GtkStateFlags flags,
775 cairo_t *cr,
776 const tools::Rectangle& rControlRectangle,
777 ControlPart nPart,
778 const ImplControlValue& rValue )
780 const SpinbuttonValue *pSpinVal = (rValue.getType() == ControlType::SpinButtons) ? static_cast<const SpinbuttonValue *>(&rValue) : nullptr;
781 ControlPart upBtnPart = ControlPart::ButtonUp;
782 ControlState upBtnState = ControlState::NONE;
783 ControlPart downBtnPart = ControlPart::ButtonDown;
784 ControlState downBtnState = ControlState::NONE;
786 if ( pSpinVal )
788 upBtnPart = pSpinVal->mnUpperPart;
789 upBtnState = pSpinVal->mnUpperState;
791 downBtnPart = pSpinVal->mnLowerPart;
792 downBtnState = pSpinVal->mnLowerState;
795 if (nPart == ControlPart::Entire)
797 gtk_style_context_set_state(mpWindowStyle, flags);
799 gtk_render_background(mpWindowStyle, cr,
800 0, 0,
801 rControlRectangle.GetWidth(), rControlRectangle.GetHeight());
803 gtk_style_context_set_state(mpSpinStyle, flags);
805 gtk_render_background(mpSpinStyle, cr,
806 0, 0,
807 rControlRectangle.GetWidth(), rControlRectangle.GetHeight());
810 cairo_translate(cr, -rControlRectangle.Left(), -rControlRectangle.Top());
811 PaintOneSpinButton(mpSpinUpStyle, cr, upBtnPart, rControlRectangle, upBtnState );
812 PaintOneSpinButton(mpSpinDownStyle, cr, downBtnPart, rControlRectangle, downBtnState );
813 cairo_translate(cr, rControlRectangle.Left(), rControlRectangle.Top());
815 if (nPart == ControlPart::Entire)
817 gtk_render_frame(mpSpinStyle, cr,
818 0, 0,
819 rControlRectangle.GetWidth(), rControlRectangle.GetHeight() );
823 #define FALLBACK_ARROW_SIZE gint(11 * 0.85)
825 tools::Rectangle GtkSalGraphics::NWGetComboBoxButtonRect(ControlType nType,
826 ControlPart nPart,
827 tools::Rectangle aAreaRect )
829 tools::Rectangle aButtonRect;
831 GtkBorder padding;
832 if (nType == ControlType::Listbox)
833 gtk_style_context_get_padding(mpListboxButtonStyle, gtk_style_context_get_state(mpListboxButtonStyle), &padding);
834 else
835 gtk_style_context_get_padding(mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &padding);
837 gint nArrowWidth = FALLBACK_ARROW_SIZE;
838 gtk_style_context_get(mpComboboxButtonArrowStyle,
839 gtk_style_context_get_state(mpComboboxButtonArrowStyle),
840 "min-width", &nArrowWidth, nullptr);
842 gint nButtonWidth = nArrowWidth + padding.left + padding.right;
843 if( nPart == ControlPart::ButtonDown )
845 Point aPos(aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, aAreaRect.Top());
846 if (AllSettings::GetLayoutRTL())
847 aPos.setX( aAreaRect.Left() );
848 aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
849 aButtonRect.SetPos(aPos);
851 else if( nPart == ControlPart::SubEdit )
853 gint adjust_left = padding.left;
854 gint adjust_top = padding.top;
855 gint adjust_right = padding.right;
856 gint adjust_bottom = padding.bottom;
858 aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - (adjust_left + adjust_right),
859 aAreaRect.GetHeight() - (adjust_top + adjust_bottom)) );
860 Point aEditPos = aAreaRect.TopLeft();
861 if (AllSettings::GetLayoutRTL())
862 aEditPos.AdjustX(nButtonWidth );
863 else
864 aEditPos.AdjustX(adjust_left );
865 aEditPos.AdjustY(adjust_top );
866 aButtonRect.SetPos( aEditPos );
869 return aButtonRect;
872 void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
873 const tools::Rectangle& rControlRectangle,
874 ControlType nType,
875 ControlPart nPart )
877 tools::Rectangle areaRect;
878 tools::Rectangle buttonRect;
879 tools::Rectangle arrowRect;
881 // Find the overall bounding rect of the buttons's drawing area,
882 // plus its actual draw rect excluding adornment
883 areaRect = rControlRectangle;
885 buttonRect = NWGetComboBoxButtonRect(ControlType::Combobox, ControlPart::ButtonDown, areaRect);
887 tools::Rectangle aEditBoxRect( areaRect );
888 aEditBoxRect.SetSize( Size( areaRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
889 if (AllSettings::GetLayoutRTL())
890 aEditBoxRect.SetPos( Point( areaRect.Left() + buttonRect.GetWidth(), areaRect.Top() ) );
892 gint arrow_width = FALLBACK_ARROW_SIZE, arrow_height = FALLBACK_ARROW_SIZE;
893 if (nType == ControlType::Combobox)
895 gtk_style_context_get(mpComboboxButtonArrowStyle,
896 gtk_style_context_get_state(mpComboboxButtonArrowStyle),
897 "min-width", &arrow_width, "min-height", &arrow_height, nullptr);
899 else if (nType == ControlType::Listbox)
901 gtk_style_context_get(mpListboxButtonArrowStyle,
902 gtk_style_context_get_state(mpListboxButtonArrowStyle),
903 "min-width", &arrow_width, "min-height", &arrow_height, nullptr);
906 arrowRect.SetSize(Size(arrow_width, arrow_height));
907 arrowRect.SetPos( Point( buttonRect.Left() + static_cast<gint>((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
908 buttonRect.Top() + static_cast<gint>((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
911 tools::Rectangle aRect(Point(0, 0), Size(areaRect.GetWidth(), areaRect.GetHeight()));
913 if (nType == ControlType::Combobox)
915 if( nPart == ControlPart::Entire )
917 render_common(mpComboboxStyle, cr, aRect, flags);
918 render_common(mpComboboxBoxStyle, cr, aRect, flags);
919 tools::Rectangle aEntryRect(Point(aEditBoxRect.Left() - areaRect.Left(),
920 aEditBoxRect.Top() - areaRect.Top()),
921 Size(aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight()));
923 GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxEntryStyle);
924 if (AllSettings::GetLayoutRTL())
925 gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_LEFT);
926 else
927 gtk_style_context_set_junction_sides(mpComboboxEntryStyle, GTK_JUNCTION_RIGHT);
928 render_common(mpComboboxEntryStyle, cr, aEntryRect, flags);
929 gtk_style_context_set_junction_sides(mpComboboxEntryStyle, eJuncSides);
932 tools::Rectangle aButtonRect(Point(buttonRect.Left() - areaRect.Left(), buttonRect.Top() - areaRect.Top()),
933 Size(buttonRect.GetWidth(), buttonRect.GetHeight()));
934 GtkJunctionSides eJuncSides = gtk_style_context_get_junction_sides(mpComboboxButtonStyle);
935 if (AllSettings::GetLayoutRTL())
936 gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_RIGHT);
937 else
938 gtk_style_context_set_junction_sides(mpComboboxButtonStyle, GTK_JUNCTION_LEFT);
939 render_common(mpComboboxButtonStyle, cr, aButtonRect, flags);
940 gtk_style_context_set_junction_sides(mpComboboxButtonStyle, eJuncSides);
942 gtk_render_arrow(mpComboboxButtonArrowStyle, cr,
943 G_PI,
944 (arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
945 arrowRect.GetWidth() );
947 else if (nType == ControlType::Listbox)
949 if( nPart == ControlPart::ListboxWindow )
951 /* render the popup window with the menu style */
952 gtk_render_frame(mpMenuStyle, cr,
953 0, 0,
954 areaRect.GetWidth(), areaRect.GetHeight());
956 else
958 render_common(mpListboxStyle, cr, aRect, flags);
959 render_common(mpListboxBoxStyle, cr, aRect, flags);
961 render_common(mpListboxButtonStyle, cr, aRect, flags);
963 gtk_render_arrow(mpListboxButtonArrowStyle, cr,
964 G_PI,
965 (arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
966 arrowRect.GetWidth() );
971 static void appendComboEntry(GtkWidgetPath* pSiblingsPath)
973 gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_ENTRY);
974 gtk_widget_path_iter_set_object_name(pSiblingsPath, -1, "entry");
975 gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
978 static void appendComboButton(GtkWidgetPath* pSiblingsPath)
980 gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
981 gtk_widget_path_iter_set_object_name(pSiblingsPath, -1, "button");
982 gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
985 static GtkWidgetPath* buildLTRComboSiblingsPath()
987 GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
989 appendComboEntry(pSiblingsPath);
990 appendComboButton(pSiblingsPath);
992 return pSiblingsPath;
995 static GtkWidgetPath* buildRTLComboSiblingsPath()
997 GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
999 appendComboButton(pSiblingsPath);
1000 appendComboEntry(pSiblingsPath);
1002 return pSiblingsPath;
1005 GtkStyleContext* GtkSalGraphics::makeContext(GtkWidgetPath *pPath, GtkStyleContext *pParent)
1007 GtkStyleContext* context = gtk_style_context_new();
1008 gtk_style_context_set_screen(context, gtk_widget_get_screen(mpWindow));
1009 gtk_style_context_set_path(context, pPath);
1010 if (pParent == nullptr)
1012 GtkWidget* pTopLevel = gtk_widget_get_toplevel(mpWindow);
1013 GtkStyleContext* pStyle = gtk_widget_get_style_context(pTopLevel);
1014 gtk_style_context_set_parent(context, pStyle);
1015 gtk_style_context_set_scale (context, gtk_style_context_get_scale (pStyle));
1017 else
1019 gtk_style_context_set_parent(context, pParent);
1020 gtk_style_context_set_scale (context, gtk_style_context_get_scale (pParent));
1022 gtk_widget_path_unref(pPath);
1023 return context;
1026 GtkStyleContext* GtkSalGraphics::createStyleContext(GtkControlPart ePart)
1028 switch (ePart)
1030 case GtkControlPart::ToplevelWindow:
1032 GtkWidgetPath *path = gtk_widget_path_new();
1033 gtk_widget_path_append_type(path, G_TYPE_NONE);
1034 gtk_widget_path_iter_set_object_name(path, -1, "window");
1035 gtk_widget_path_iter_add_class(path, -1, "background");
1036 return makeContext(path, nullptr);
1038 case GtkControlPart::Button:
1040 GtkWidgetPath *path = gtk_widget_path_new();
1041 gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1042 gtk_widget_path_iter_set_object_name(path, -1, "button");
1043 return makeContext(path, nullptr);
1045 case GtkControlPart::LinkButton:
1047 GtkWidgetPath *path = gtk_widget_path_new();
1048 gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1049 gtk_widget_path_iter_set_object_name(path, -1, "button");
1050 gtk_widget_path_iter_add_class(path, -1, "link");
1051 return makeContext(path, nullptr);
1053 case GtkControlPart::CheckButton:
1055 GtkWidgetPath *path = gtk_widget_path_new();
1056 gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
1057 gtk_widget_path_iter_set_object_name(path, -1, "checkbutton");
1058 return makeContext(path, nullptr);
1060 case GtkControlPart::CheckButtonCheck:
1062 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckButtonStyle));
1063 gtk_widget_path_append_type(path, GTK_TYPE_CHECK_BUTTON);
1064 gtk_widget_path_iter_set_object_name(path, -1, "check");
1065 return makeContext(path, mpCheckButtonStyle);
1067 case GtkControlPart::RadioButton:
1069 GtkWidgetPath *path = gtk_widget_path_new();
1070 gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1071 gtk_widget_path_iter_set_object_name(path, -1, "radiobutton");
1072 return makeContext(path, nullptr);
1074 case GtkControlPart::RadioButtonRadio:
1076 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioButtonStyle));
1077 gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1078 gtk_widget_path_iter_set_object_name(path, -1, "radio");
1079 return makeContext(path, mpRadioButtonStyle);
1081 case GtkControlPart::ComboboxBoxButtonBoxArrow:
1083 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxButtonBoxStyle));
1084 gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1085 gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1086 gtk_widget_path_iter_set_object_name(path, -1, "arrow");
1087 return makeContext(path, mpComboboxButtonBoxStyle);
1089 case GtkControlPart::ListboxBoxButtonBoxArrow:
1091 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxButtonBoxStyle));
1092 gtk_widget_path_append_type(path, GTK_TYPE_RADIO_BUTTON);
1093 gtk_widget_path_append_type(path, GTK_TYPE_BUTTON);
1094 gtk_widget_path_iter_set_object_name(path, -1, "arrow");
1095 return makeContext(path, mpListboxButtonBoxStyle);
1097 case GtkControlPart::Entry:
1099 GtkWidgetPath *path = gtk_widget_path_new();
1100 gtk_widget_path_append_type(path, GTK_TYPE_ENTRY);
1101 gtk_widget_path_iter_set_object_name(path, -1, "entry");
1102 return makeContext(path, nullptr);
1104 case GtkControlPart::Combobox:
1105 case GtkControlPart::Listbox:
1107 GtkWidgetPath *path = gtk_widget_path_new();
1108 gtk_widget_path_append_type(path, G_TYPE_NONE);
1109 gtk_widget_path_iter_set_object_name(path, -1, "combobox");
1110 return makeContext(path, nullptr);
1112 case GtkControlPart::ComboboxBox:
1114 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxStyle));
1115 gtk_widget_path_append_type(path, G_TYPE_NONE);
1116 gtk_widget_path_iter_set_object_name(path, -1, "box");
1117 gtk_widget_path_iter_add_class(path, -1, "horizontal");
1118 gtk_widget_path_iter_add_class(path, -1, "linked");
1119 return makeContext(path, mpComboboxStyle);
1121 case GtkControlPart::ListboxBox:
1123 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxStyle));
1124 gtk_widget_path_append_type(path, G_TYPE_NONE);
1125 gtk_widget_path_iter_set_object_name(path, -1, "box");
1126 gtk_widget_path_iter_add_class(path, -1, "horizontal");
1127 gtk_widget_path_iter_add_class(path, -1, "linked");
1128 return makeContext(path, mpListboxStyle);
1130 case GtkControlPart::ComboboxBoxEntry:
1132 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxBoxStyle));
1133 GtkWidgetPath* pSiblingsPath;
1134 if (AllSettings::GetLayoutRTL())
1136 pSiblingsPath = buildRTLComboSiblingsPath();
1137 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
1139 else
1141 pSiblingsPath = buildLTRComboSiblingsPath();
1142 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
1144 gtk_widget_path_unref(pSiblingsPath);
1145 return makeContext(path, mpComboboxBoxStyle);
1147 case GtkControlPart::ComboboxBoxButton:
1149 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxBoxStyle));
1150 GtkWidgetPath* pSiblingsPath;
1151 if (AllSettings::GetLayoutRTL())
1153 pSiblingsPath = buildRTLComboSiblingsPath();
1154 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
1156 else
1158 pSiblingsPath = buildLTRComboSiblingsPath();
1159 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 1);
1161 gtk_widget_path_unref(pSiblingsPath);
1162 return makeContext(path, mpComboboxBoxStyle);
1164 case GtkControlPart::ListboxBoxButton:
1166 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxBoxStyle));
1167 GtkWidgetPath* pSiblingsPath = gtk_widget_path_new();
1169 gtk_widget_path_append_type(pSiblingsPath, GTK_TYPE_BUTTON);
1170 gtk_widget_path_iter_set_object_name(pSiblingsPath, -1, "button");
1171 gtk_widget_path_iter_add_class(pSiblingsPath, -1, "combo");
1173 gtk_widget_path_append_with_siblings(path, pSiblingsPath, 0);
1174 gtk_widget_path_unref(pSiblingsPath);
1175 return makeContext(path, mpListboxBoxStyle);
1177 case GtkControlPart::ComboboxBoxButtonBox:
1179 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpComboboxButtonStyle));
1180 gtk_widget_path_append_type(path, G_TYPE_NONE);
1181 gtk_widget_path_iter_set_object_name(path, -1, "box");
1182 gtk_widget_path_iter_add_class(path, -1, "horizontal");
1183 return makeContext(path, mpComboboxButtonStyle);
1185 case GtkControlPart::ListboxBoxButtonBox:
1187 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpListboxButtonStyle));
1188 gtk_widget_path_append_type(path, G_TYPE_NONE);
1189 gtk_widget_path_iter_set_object_name(path, -1, "box");
1190 gtk_widget_path_iter_add_class(path, -1, "horizontal");
1191 return makeContext(path, mpListboxButtonStyle);
1193 case GtkControlPart::SpinButton:
1195 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
1196 gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
1197 gtk_widget_path_iter_set_object_name(path, -1, "spinbutton");
1198 gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
1199 return makeContext(path, mpWindowStyle);
1201 case GtkControlPart::SpinButtonUpButton:
1202 case GtkControlPart::SpinButtonDownButton:
1204 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSpinStyle));
1205 gtk_widget_path_append_type(path, GTK_TYPE_SPIN_BUTTON);
1206 gtk_widget_path_iter_set_object_name(path, -1, "button");
1207 gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::SpinButtonUpButton ? "up" : "down");
1208 return makeContext(path, mpSpinStyle);
1210 case GtkControlPart::ScrollbarVertical:
1211 case GtkControlPart::ScrollbarHorizontal:
1213 GtkWidgetPath *path = gtk_widget_path_new();
1214 gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1215 gtk_widget_path_iter_set_object_name(path, -1, "scrollbar");
1216 gtk_widget_path_iter_add_class(path, -1, ePart == GtkControlPart::ScrollbarVertical ? "vertical" : "horizontal");
1217 return makeContext(path, nullptr);
1219 case GtkControlPart::ScrollbarVerticalContents:
1220 case GtkControlPart::ScrollbarHorizontalContents:
1222 GtkStyleContext *pParent =
1223 (ePart == GtkControlPart::ScrollbarVerticalContents) ? mpVScrollbarStyle : mpHScrollbarStyle;
1224 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1225 gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1226 gtk_widget_path_iter_set_object_name(path, -1, "contents");
1227 return makeContext(path, pParent);
1229 case GtkControlPart::ScrollbarVerticalTrough:
1230 case GtkControlPart::ScrollbarHorizontalTrough:
1232 GtkStyleContext *pParent =
1233 (ePart == GtkControlPart::ScrollbarVerticalTrough) ? mpVScrollbarContentsStyle : mpHScrollbarContentsStyle;
1234 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1235 gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1236 gtk_widget_path_iter_set_object_name(path, -1, "trough");
1237 return makeContext(path, pParent);
1239 case GtkControlPart::ScrollbarVerticalSlider:
1240 case GtkControlPart::ScrollbarHorizontalSlider:
1242 GtkStyleContext *pParent =
1243 (ePart == GtkControlPart::ScrollbarVerticalSlider) ? mpVScrollbarTroughStyle : mpHScrollbarTroughStyle;
1244 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1245 gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1246 gtk_widget_path_iter_set_object_name(path, -1, "slider");
1247 return makeContext(path, pParent);
1249 case GtkControlPart::ScrollbarVerticalButton:
1250 case GtkControlPart::ScrollbarHorizontalButton:
1252 GtkStyleContext *pParent =
1253 (ePart == GtkControlPart::ScrollbarVerticalButton) ? mpVScrollbarStyle : mpHScrollbarStyle;
1254 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(pParent));
1255 gtk_widget_path_append_type(path, GTK_TYPE_SCROLLBAR);
1256 gtk_widget_path_iter_set_object_name(path, -1, "button");
1257 return makeContext(path, pParent);
1259 case GtkControlPart::ProgressBar:
1261 GtkWidgetPath *path = gtk_widget_path_new();
1262 gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1263 gtk_widget_path_iter_set_object_name(path, -1, "progressbar");
1264 gtk_widget_path_iter_add_class(path, -1, GTK_STYLE_CLASS_HORIZONTAL);
1265 return makeContext(path, nullptr);
1267 case GtkControlPart::ProgressBarTrough:
1269 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarStyle));
1270 gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1271 gtk_widget_path_iter_set_object_name(path, -1, "trough");
1272 return makeContext(path, mpProgressBarStyle);
1274 case GtkControlPart::ProgressBarProgress:
1276 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpProgressBarTroughStyle));
1277 gtk_widget_path_append_type(path, GTK_TYPE_PROGRESS_BAR);
1278 gtk_widget_path_iter_set_object_name(path, -1, "progress");
1279 return makeContext(path, mpProgressBarTroughStyle);
1281 case GtkControlPart::Notebook:
1283 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
1284 gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1285 gtk_widget_path_iter_set_object_name(path, -1, "notebook");
1286 return makeContext(path, mpWindowStyle);
1288 case GtkControlPart::NotebookStack:
1290 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
1291 gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1292 gtk_widget_path_iter_set_object_name(path, -1, "stack");
1293 return makeContext(path, mpNotebookStyle);
1295 case GtkControlPart::NotebookHeader:
1297 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookStyle));
1298 gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1299 gtk_widget_path_iter_set_object_name(path, -1, "header");
1300 gtk_widget_path_iter_add_class(path, -1, "frame");
1301 gtk_widget_path_iter_add_class(path, -1, "top");
1302 return makeContext(path, mpNotebookStyle);
1304 case GtkControlPart::NotebookHeaderTabs:
1306 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderStyle));
1307 gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1308 gtk_widget_path_iter_set_object_name(path, -1, "tabs");
1309 gtk_widget_path_iter_add_class(path, -1, "top");
1310 return makeContext(path, mpNotebookHeaderStyle);
1312 case GtkControlPart::NotebookHeaderTabsTab:
1314 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsStyle));
1315 gtk_widget_path_append_type(path, GTK_TYPE_NOTEBOOK);
1316 gtk_widget_path_iter_set_object_name(path, -1, "tab");
1317 gtk_widget_path_iter_add_class(path, -1, "top");
1318 return makeContext(path, mpNotebookHeaderTabsStyle);
1320 case GtkControlPart::NotebookHeaderTabsTabLabel:
1322 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpNotebookHeaderTabsTabStyle));
1323 gtk_widget_path_append_type(path, G_TYPE_NONE);
1324 gtk_widget_path_iter_set_object_name(path, -1, "label");
1325 return makeContext(path, mpNotebookHeaderTabsTabStyle);
1327 case GtkControlPart::NotebookHeaderTabsTabActiveLabel:
1328 case GtkControlPart::NotebookHeaderTabsTabHoverLabel:
1329 return mpNotebookHeaderTabsTabLabelStyle;
1330 case GtkControlPart::FrameBorder:
1332 GtkWidgetPath *path = gtk_widget_path_new();
1333 gtk_widget_path_append_type(path, GTK_TYPE_FRAME);
1334 gtk_widget_path_iter_set_object_name(path, -1, "frame");
1335 gtk_widget_path_iter_add_class(path, -1, "frame");
1336 return makeContext(path, nullptr);
1338 case GtkControlPart::MenuBar:
1340 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpWindowStyle));
1341 gtk_widget_path_append_type(path, GTK_TYPE_MENU_BAR);
1342 gtk_widget_path_iter_set_object_name(path, -1, "menubar");
1343 return makeContext(path, mpWindowStyle);
1345 case GtkControlPart::MenuBarItem:
1347 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarStyle));
1348 gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
1349 gtk_widget_path_iter_set_object_name(path, -1, "menuitem");
1350 return makeContext(path, mpMenuBarStyle);
1352 case GtkControlPart::MenuWindow:
1354 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuBarItemStyle));
1355 gtk_widget_path_append_type(path, G_TYPE_NONE);
1356 gtk_widget_path_iter_set_object_name(path, -1, "window");
1357 gtk_widget_path_iter_add_class(path, -1, "background");
1358 gtk_widget_path_iter_add_class(path, -1, "popup");
1359 return makeContext(path, mpMenuBarItemStyle);
1361 case GtkControlPart::Menu:
1363 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuWindowStyle));
1364 gtk_widget_path_append_type(path, GTK_TYPE_MENU);
1365 gtk_widget_path_iter_set_object_name(path, -1, "menu");
1366 return makeContext(path, mpMenuWindowStyle);
1368 case GtkControlPart::MenuItem:
1370 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1371 gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
1372 gtk_widget_path_iter_set_object_name(path, -1, "menuitem");
1373 return makeContext(path, mpMenuStyle);
1375 case GtkControlPart::MenuItemLabel:
1377 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
1378 gtk_widget_path_append_type(path, G_TYPE_NONE);
1379 gtk_widget_path_iter_set_object_name(path, -1, "label");
1380 return makeContext(path, mpMenuItemStyle);
1382 case GtkControlPart::MenuItemArrow:
1384 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuItemStyle));
1385 gtk_widget_path_append_type(path, GTK_TYPE_MENU_ITEM);
1386 gtk_widget_path_iter_set_object_name(path, -1, "arrow");
1387 return makeContext(path, mpMenuItemStyle);
1389 case GtkControlPart::CheckMenuItem:
1391 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1392 gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
1393 gtk_widget_path_iter_set_object_name(path, -1, "menuitem");
1394 return makeContext(path, mpMenuStyle);
1396 case GtkControlPart::CheckMenuItemCheck:
1398 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpCheckMenuItemStyle));
1399 gtk_widget_path_append_type(path, GTK_TYPE_CHECK_MENU_ITEM);
1400 gtk_widget_path_iter_set_object_name(path, -1, "check");
1401 return makeContext(path, mpCheckMenuItemStyle);
1403 case GtkControlPart::RadioMenuItem:
1405 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1406 gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
1407 gtk_widget_path_iter_set_object_name(path, -1, "menuitem");
1408 return makeContext(path, mpMenuStyle);
1410 case GtkControlPart::RadioMenuItemRadio:
1412 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpRadioMenuItemStyle));
1413 gtk_widget_path_append_type(path, GTK_TYPE_RADIO_MENU_ITEM);
1414 gtk_widget_path_iter_set_object_name(path, -1, "radio");
1415 return makeContext(path, mpRadioMenuItemStyle);
1417 case GtkControlPart::SeparatorMenuItem:
1419 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpMenuStyle));
1420 gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
1421 gtk_widget_path_iter_set_object_name(path, -1, "menuitem");
1422 return makeContext(path, mpMenuStyle);
1424 case GtkControlPart::SeparatorMenuItemSeparator:
1426 GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(mpSeparatorMenuItemStyle));
1427 gtk_widget_path_append_type(path, GTK_TYPE_SEPARATOR_MENU_ITEM);
1428 gtk_widget_path_iter_set_object_name(path, -1, "separator");
1429 return makeContext(path, mpSeparatorMenuItemStyle);
1433 return nullptr;
1436 #ifndef GTK_STYLE_CLASS_POPUP
1437 #define GTK_STYLE_CLASS_POPUP "popup"
1438 #endif
1439 #ifndef GTK_STYLE_CLASS_LABEL
1440 #define GTK_STYLE_CLASS_LABEL "label"
1441 #endif
1443 void GtkSalGraphics::PaintCheckOrRadio(cairo_t *cr, GtkStyleContext *context,
1444 const tools::Rectangle& rControlRectangle, bool bIsCheck, bool bInMenu)
1446 gint indicator_size;
1447 gtk_style_context_get_style(context, "indicator-size", &indicator_size, nullptr);
1449 gint x = (rControlRectangle.GetWidth() - indicator_size) / 2;
1450 gint y = (rControlRectangle.GetHeight() - indicator_size) / 2;
1452 if (!bInMenu)
1453 gtk_render_background(context, cr, x, y, indicator_size, indicator_size);
1455 if (bIsCheck)
1456 gtk_render_check(context, cr, x, y, indicator_size, indicator_size);
1457 else
1458 gtk_render_option(context, cr, x, y, indicator_size, indicator_size);
1460 gtk_render_frame(context, cr, x, y, indicator_size, indicator_size);
1463 void GtkSalGraphics::PaintCheck(cairo_t *cr, GtkStyleContext *context,
1464 const tools::Rectangle& rControlRectangle, bool bInMenu)
1466 PaintCheckOrRadio(cr, context, rControlRectangle, true, bInMenu);
1469 void GtkSalGraphics::PaintRadio(cairo_t *cr, GtkStyleContext *context,
1470 const tools::Rectangle& rControlRectangle, bool bInMenu)
1472 PaintCheckOrRadio(cr, context, rControlRectangle, false, bInMenu);
1475 static gfloat getArrowSize(GtkStyleContext* context)
1477 gint min_width, min_weight;
1478 gtk_style_context_get_style(context, "min-width", &min_width, nullptr);
1479 gtk_style_context_get_style(context, "min-height", &min_weight, nullptr);
1480 gfloat arrow_size = 11 * MAX (min_width, min_weight);
1481 return arrow_size;
1484 namespace
1486 void draw_vertical_separator(GtkStyleContext *context, cairo_t *cr, const tools::Rectangle& rControlRegion)
1488 tools::Long nX = 0;
1489 tools::Long nY = 0;
1491 gint nSeparatorWidth = 1;
1493 gtk_style_context_get(context,
1494 gtk_style_context_get_state(context),
1495 "min-width", &nSeparatorWidth, nullptr);
1497 gint nHalfSeparatorWidth = nSeparatorWidth / 2;
1498 gint nHalfRegionWidth = rControlRegion.GetWidth() / 2;
1500 nX = nX + nHalfRegionWidth - nHalfSeparatorWidth;
1501 nY = rControlRegion.GetHeight() > 5 ? 1 : 0;
1502 int nHeight = rControlRegion.GetHeight() - (2 * nY);
1504 gtk_render_background(context, cr, nX, nY, nSeparatorWidth, nHeight);
1505 gtk_render_frame(context, cr, nX, nY, nSeparatorWidth, nHeight);
1508 void draw_horizontal_separator(GtkStyleContext *context, cairo_t *cr, const tools::Rectangle& rControlRegion)
1510 tools::Long nX = 0;
1511 tools::Long nY = 0;
1513 gint nSeparatorHeight = 1;
1515 gtk_style_context_get(context,
1516 gtk_style_context_get_state(context),
1517 "min-height", &nSeparatorHeight, nullptr);
1519 gint nHalfSeparatorHeight = nSeparatorHeight / 2;
1520 gint nHalfRegionHeight = rControlRegion.GetHeight() / 2;
1522 nY = nY + nHalfRegionHeight - nHalfSeparatorHeight;
1523 nX = rControlRegion.GetWidth() > 5 ? 1 : 0;
1524 int nWidth = rControlRegion.GetWidth() - (2 * nX);
1526 gtk_render_background(context, cr, nX, nY, nWidth, nSeparatorHeight);
1527 gtk_render_frame(context, cr, nX, nY, nWidth, nSeparatorHeight);
1531 void GtkSalGraphics::handleDamage(const tools::Rectangle& rDamagedRegion)
1533 assert(m_pWidgetDraw);
1534 assert(!rDamagedRegion.IsEmpty());
1535 mpFrame->damaged(rDamagedRegion.Left(), rDamagedRegion.Top(), rDamagedRegion.GetWidth(), rDamagedRegion.GetHeight());
1538 bool GtkSalGraphics::drawNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion,
1539 ControlState nState, const ImplControlValue& rValue,
1540 const OUString&, const Color& rBackgroundColor)
1542 RenderType renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::BackgroundAndFrame;
1543 GtkStyleContext *context = nullptr;
1544 GdkPixbuf *pixbuf = nullptr;
1545 bool bInMenu = false;
1547 GtkStateFlags flags = NWConvertVCLStateToGTKState(nState);
1549 switch(nType)
1551 case ControlType::Spinbox:
1552 case ControlType::SpinButtons:
1553 context = mpSpinStyle;
1554 renderType = RenderType::Spinbutton;
1555 break;
1556 case ControlType::Editbox:
1557 context = mpEntryStyle;
1558 break;
1559 case ControlType::MultilineEditbox:
1560 context = mpTextViewStyle;
1561 break;
1562 case ControlType::Combobox:
1563 context = mpComboboxStyle;
1564 renderType = RenderType::Combobox;
1565 break;
1566 case ControlType::Listbox:
1567 if (nPart == ControlPart::Focus)
1569 renderType = RenderType::Focus;
1570 context = mpListboxButtonStyle;
1572 else
1574 renderType = RenderType::Combobox;
1575 context = mpListboxStyle;
1577 break;
1578 case ControlType::MenuPopup:
1579 bInMenu = true;
1581 // map selected menu entries in vcl parlance to gtk prelight
1582 if (nPart >= ControlPart::MenuItem && nPart <= ControlPart::SubmenuArrow && (nState & ControlState::SELECTED))
1583 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_PRELIGHT);
1584 flags = static_cast<GtkStateFlags>(flags & ~GTK_STATE_FLAG_ACTIVE);
1585 switch(nPart)
1587 case ControlPart::MenuItem:
1588 context = mpMenuItemStyle;
1589 renderType = RenderType::BackgroundAndFrame;
1590 break;
1591 case ControlPart::MenuItemCheckMark:
1592 context = mpCheckMenuItemCheckStyle;
1593 renderType = RenderType::Check;
1594 nType = ControlType::Checkbox;
1595 if (nState & ControlState::PRESSED)
1597 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
1599 break;
1600 case ControlPart::MenuItemRadioMark:
1601 context = mpRadioMenuItemRadioStyle;
1602 renderType = RenderType::Radio;
1603 nType = ControlType::Radiobutton;
1604 if (nState & ControlState::PRESSED)
1606 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
1608 break;
1609 case ControlPart::Separator:
1610 context = mpSeparatorMenuItemSeparatorStyle;
1611 flags = GtkStateFlags(GTK_STATE_FLAG_BACKDROP | GTK_STATE_FLAG_INSENSITIVE); //GTK_STATE_FLAG_BACKDROP hack ?
1612 renderType = RenderType::MenuSeparator;
1613 break;
1614 case ControlPart::SubmenuArrow:
1615 context = mpMenuItemArrowStyle;
1616 renderType = RenderType::Arrow;
1617 break;
1618 case ControlPart::Entire:
1619 context = mpMenuStyle;
1620 renderType = RenderType::Background;
1621 break;
1622 default: break;
1624 break;
1625 case ControlType::Toolbar:
1626 switch(nPart)
1628 case ControlPart::DrawBackgroundHorz:
1629 case ControlPart::DrawBackgroundVert:
1630 context = mpToolbarStyle;
1631 break;
1632 case ControlPart::Button:
1633 /* For all checkbuttons in the toolbars */
1634 flags = static_cast<GtkStateFlags>(flags |
1635 ( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_CHECKED : GTK_STATE_FLAG_NORMAL));
1636 context = mpToolButtonStyle;
1637 break;
1638 case ControlPart::SeparatorVert:
1639 context = mpToolbarSeparatorStyle;
1640 renderType = RenderType::ToolbarSeparator;
1641 break;
1642 default:
1643 return false;
1645 break;
1646 case ControlType::Radiobutton:
1647 flags = static_cast<GtkStateFlags>(flags |
1648 ( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_CHECKED : GTK_STATE_FLAG_NORMAL));
1649 context = mpRadioButtonRadioStyle;
1650 renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::Radio;
1651 break;
1652 case ControlType::Checkbox:
1653 flags = static_cast<GtkStateFlags>(flags |
1654 ( (rValue.getTristateVal() == ButtonValue::On) ? GTK_STATE_FLAG_CHECKED :
1655 (rValue.getTristateVal() == ButtonValue::Mixed) ? GTK_STATE_FLAG_INCONSISTENT :
1656 GTK_STATE_FLAG_NORMAL));
1657 context = mpCheckButtonCheckStyle;
1658 renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::Check;
1659 break;
1660 case ControlType::Pushbutton:
1661 context = mpButtonStyle;
1662 break;
1663 case ControlType::Scrollbar:
1664 switch(nPart)
1666 case ControlPart::DrawBackgroundVert:
1667 case ControlPart::DrawBackgroundHorz:
1668 context = (nPart == ControlPart::DrawBackgroundVert)
1669 ? mpVScrollbarStyle : mpHScrollbarStyle;
1670 renderType = RenderType::Scrollbar;
1671 break;
1672 default: break;
1674 break;
1675 case ControlType::ListNet:
1676 return true;
1677 break;
1678 case ControlType::TabPane:
1679 context = mpNotebookStyle;
1680 break;
1681 case ControlType::TabBody:
1682 context = mpNotebookStackStyle;
1683 break;
1684 case ControlType::TabHeader:
1685 context = mpNotebookHeaderStyle;
1686 break;
1687 case ControlType::TabItem:
1688 context = mpNotebookHeaderTabsTabStyle;
1689 if (nState & ControlState::SELECTED)
1690 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
1691 renderType = RenderType::TabItem;
1692 break;
1693 case ControlType::WindowBackground:
1694 context = gtk_widget_get_style_context(gtk_widget_get_toplevel(mpWindow));
1695 break;
1696 case ControlType::Frame:
1698 DrawFrameStyle nStyle = static_cast<DrawFrameStyle>(rValue.getNumericVal() & 0x0f);
1699 if (nStyle == DrawFrameStyle::In)
1700 context = mpFrameOutStyle;
1701 else
1702 context = mpFrameInStyle;
1703 break;
1705 case ControlType::Menubar:
1706 if (nPart == ControlPart::MenuItem)
1708 context = mpMenuBarItemStyle;
1710 flags = (!(nState & ControlState::ENABLED)) ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
1711 if (nState & ControlState::SELECTED)
1712 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_PRELIGHT);
1714 else
1716 context = mpMenuBarStyle;
1718 break;
1719 case ControlType::Fixedline:
1720 context = nPart == ControlPart::SeparatorHorz ? mpFixedHoriLineStyle : mpFixedVertLineStyle;
1721 renderType = RenderType::Separator;
1722 break;
1723 case ControlType::ListNode:
1725 context = mpTreeHeaderButtonStyle;
1726 ButtonValue aButtonValue = rValue.getTristateVal();
1727 if (aButtonValue == ButtonValue::On)
1728 flags = static_cast<GtkStateFlags>(flags | GTK_STATE_FLAG_CHECKED);
1729 renderType = RenderType::Expander;
1730 break;
1732 case ControlType::ListHeader:
1733 context = mpTreeHeaderButtonStyle;
1734 if (nPart == ControlPart::Arrow)
1736 const char* icon = (rValue.getNumericVal() & 1) ? "pan-down-symbolic" : "pan-up-symbolic";
1737 GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
1738 pixbuf = gtk_icon_theme_load_icon_for_scale(pIconTheme, icon,
1739 std::max(rControlRegion.GetWidth(), rControlRegion.GetHeight()),
1740 gtk_style_context_get_scale (context),
1741 static_cast<GtkIconLookupFlags>(0), nullptr);
1742 flags = GTK_STATE_FLAG_SELECTED;
1743 renderType = RenderType::Icon;
1745 break;
1746 case ControlType::Progress:
1747 context = mpProgressBarProgressStyle;
1748 renderType = RenderType::Progress;
1749 break;
1750 default:
1751 return false;
1754 cairo_t *cr = getCairoContext(false);
1755 clipRegion(cr);
1756 cairo_translate(cr, rControlRegion.Left(), rControlRegion.Top());
1758 tools::Long nX = 0;
1759 tools::Long nY = 0;
1760 tools::Long nWidth = rControlRegion.GetWidth();
1761 tools::Long nHeight = rControlRegion.GetHeight();
1763 StyleContextSave aContextState;
1764 aContextState.save(context);
1765 style_context_set_state(context, flags);
1767 // apply background in style, if explicitly set
1768 // note: for more complex controls that use multiple styles for their elements,
1769 // background may have to be applied for more of those as well (s. case RenderType::Combobox below)
1770 GtkCssProvider* pBgCssProvider = nullptr;
1771 if (rBackgroundColor != COL_AUTO)
1773 const OUString sColorCss = "* { background-color: #" + rBackgroundColor.AsRGBHexString() + "; }";
1774 const OString aResult = OUStringToOString(sColorCss, RTL_TEXTENCODING_UTF8);
1775 pBgCssProvider = gtk_css_provider_new();
1776 gtk_css_provider_load_from_data(pBgCssProvider, aResult.getStr(), aResult.getLength(), nullptr);
1777 gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(pBgCssProvider),
1778 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1781 switch(renderType)
1783 case RenderType::Background:
1784 case RenderType::BackgroundAndFrame:
1785 gtk_render_background(context, cr, nX, nY, nWidth, nHeight);
1786 if (renderType == RenderType::BackgroundAndFrame)
1788 gtk_render_frame(context, cr, nX, nY, nWidth, nHeight);
1790 break;
1791 case RenderType::Check:
1793 PaintCheck(cr, context, rControlRegion, bInMenu);
1794 break;
1796 case RenderType::Radio:
1798 PaintRadio(cr, context, rControlRegion, bInMenu);
1799 break;
1801 case RenderType::MenuSeparator:
1802 gtk_render_line(context, cr,
1803 0, rControlRegion.GetHeight() / 2,
1804 rControlRegion.GetWidth() - 1, rControlRegion.GetHeight() / 2);
1805 break;
1806 case RenderType::ToolbarSeparator:
1808 draw_vertical_separator(context, cr, rControlRegion);
1809 break;
1811 case RenderType::Separator:
1812 if (nPart == ControlPart::SeparatorHorz)
1813 draw_horizontal_separator(context, cr, rControlRegion);
1814 else
1815 draw_vertical_separator(context, cr, rControlRegion);
1816 break;
1817 case RenderType::Arrow:
1818 gtk_render_arrow(context, cr,
1819 G_PI / 2, 0, 0,
1820 MIN(rControlRegion.GetWidth(), 1 + rControlRegion.GetHeight()));
1821 break;
1822 case RenderType::Expander:
1823 gtk_render_expander(context, cr, -2, -2, nWidth+4, nHeight+4);
1824 break;
1825 case RenderType::Scrollbar:
1826 PaintScrollbar(context, cr, rControlRegion, nPart, rValue);
1827 break;
1828 case RenderType::Spinbutton:
1829 PaintSpinButton(flags, cr, rControlRegion, nPart, rValue);
1830 break;
1831 case RenderType::Combobox:
1832 if (pBgCssProvider)
1834 gtk_style_context_add_provider(mpComboboxEntryStyle, GTK_STYLE_PROVIDER(pBgCssProvider),
1835 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1837 PaintCombobox(flags, cr, rControlRegion, nType, nPart);
1838 if (pBgCssProvider)
1840 gtk_style_context_remove_provider(mpComboboxEntryStyle, GTK_STYLE_PROVIDER(pBgCssProvider));
1842 break;
1843 case RenderType::Icon:
1844 gtk_style_context_save (context);
1845 gtk_style_context_set_scale (context, 1);
1846 gtk_render_icon(context, cr, pixbuf, nX, nY);
1847 gtk_style_context_restore (context);
1848 g_object_unref(pixbuf);
1849 break;
1850 case RenderType::Focus:
1852 if (nType == ControlType::Checkbox ||
1853 nType == ControlType::Radiobutton)
1855 nX -= 2; nY -=2;
1856 nHeight += 4; nWidth += 4;
1858 else
1860 GtkBorder border;
1862 gtk_style_context_get_border(context, flags, &border);
1864 nX += border.left;
1865 nY += border.top;
1866 nWidth -= border.left + border.right;
1867 nHeight -= border.top + border.bottom;
1870 gtk_render_focus(context, cr, nX, nY, nWidth, nHeight);
1872 break;
1874 case RenderType::Progress:
1876 gtk_render_background(mpProgressBarTroughStyle, cr, nX, nY, nWidth, nHeight);
1878 tools::Long nProgressWidth = rValue.getNumericVal();
1879 if (nProgressWidth)
1881 GtkBorder padding;
1882 gtk_style_context_get_padding(context, gtk_style_context_get_state(context), &padding);
1884 nX += padding.left;
1885 nY += padding.top;
1886 nHeight -= (padding.top + padding.bottom);
1887 nProgressWidth -= (padding.left + padding.right);
1888 gtk_render_background(context, cr, nX, nY, nProgressWidth, nHeight);
1889 gtk_render_frame(context, cr, nX, nY, nProgressWidth, nHeight);
1892 gtk_render_frame(mpProgressBarTroughStyle, cr, nX, nY, nWidth, nHeight);
1894 break;
1896 case RenderType::TabItem:
1898 gint initial_gap(0);
1899 gtk_style_context_get_style(mpNotebookStyle,
1900 "initial-gap", &initial_gap,
1901 nullptr);
1903 nX += initial_gap/2;
1904 nWidth -= initial_gap;
1905 tools::Rectangle aRect(Point(nX, nY), Size(nWidth, nHeight));
1906 render_common(mpNotebookHeaderTabsTabStyle, cr, aRect, flags);
1907 break;
1909 default:
1910 break;
1913 if (pBgCssProvider)
1915 gtk_style_context_remove_provider(context, GTK_STYLE_PROVIDER(pBgCssProvider));
1917 aContextState.restore();
1919 cairo_destroy(cr); // unref
1921 if (!rControlRegion.IsEmpty())
1922 mpFrame->damaged(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight());
1924 return true;
1927 static tools::Rectangle GetWidgetSize(const tools::Rectangle& rControlRegion, GtkWidget* widget)
1929 GtkRequisition aReq;
1930 gtk_widget_get_preferred_size(widget, nullptr, &aReq);
1931 tools::Long nHeight = std::max<tools::Long>(rControlRegion.GetHeight(), aReq.height);
1932 return tools::Rectangle(rControlRegion.TopLeft(), Size(rControlRegion.GetWidth(), nHeight));
1935 static tools::Rectangle AdjustRectForTextBordersPadding(GtkStyleContext* pStyle, tools::Long nContentWidth, tools::Long nContentHeight, const tools::Rectangle& rControlRegion)
1937 GtkBorder border;
1938 gtk_style_context_get_border(pStyle, gtk_style_context_get_state(pStyle), &border);
1940 GtkBorder padding;
1941 gtk_style_context_get_padding(pStyle, gtk_style_context_get_state(pStyle), &padding);
1943 gint nWidgetHeight = nContentHeight + padding.top + padding.bottom + border.top + border.bottom;
1944 nWidgetHeight = std::max(std::max<gint>(nWidgetHeight, rControlRegion.GetHeight()), 34);
1946 gint nWidgetWidth = nContentWidth + padding.left + padding.right + border.left + border.right;
1947 nWidgetWidth = std::max<gint>(nWidgetWidth, rControlRegion.GetWidth());
1949 tools::Rectangle aEditRect(rControlRegion.TopLeft(), Size(nWidgetWidth, nWidgetHeight));
1951 return aEditRect;
1954 bool GtkSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState,
1955 const ImplControlValue& rValue, const OUString&,
1956 tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion )
1958 /* TODO: all this functions needs improvements */
1959 tools::Rectangle aEditRect = rControlRegion;
1960 gint indicator_size, indicator_spacing;
1962 if(((nType == ControlType::Checkbox) || (nType == ControlType::Radiobutton)) &&
1963 nPart == ControlPart::Entire)
1965 rNativeBoundingRegion = rControlRegion;
1967 GtkStyleContext *pButtonStyle = (nType == ControlType::Checkbox) ? mpCheckButtonCheckStyle : mpRadioButtonRadioStyle;
1970 gtk_style_context_get_style( pButtonStyle,
1971 "indicator-size", &indicator_size,
1972 "indicator-spacing", &indicator_spacing,
1973 nullptr );
1975 GtkBorder border;
1976 gtk_style_context_get_border(pButtonStyle, gtk_style_context_get_state(pButtonStyle), &border);
1978 GtkBorder padding;
1979 gtk_style_context_get_padding(pButtonStyle, gtk_style_context_get_state(pButtonStyle), &padding);
1982 indicator_size += 2*indicator_spacing + border.left + padding.left + border.right + padding.right;
1983 tools::Rectangle aIndicatorRect( Point( 0,
1984 (rControlRegion.GetHeight()-indicator_size)/2),
1985 Size( indicator_size, indicator_size ) );
1986 rNativeContentRegion = aIndicatorRect;
1988 return true;
1990 else if( nType == ControlType::MenuPopup)
1992 if ((nPart == ControlPart::MenuItemCheckMark) ||
1993 (nPart == ControlPart::MenuItemRadioMark) )
1995 indicator_size = 0;
1997 GtkStyleContext *pMenuItemStyle = (nPart == ControlPart::MenuItemCheckMark ) ? mpCheckMenuItemCheckStyle
1998 : mpRadioMenuItemRadioStyle;
2000 gtk_style_context_get_style( pMenuItemStyle,
2001 "indicator-size", &indicator_size,
2002 nullptr );
2004 gint point = MAX(0, rControlRegion.GetHeight() - indicator_size);
2005 aEditRect = tools::Rectangle( Point( 0, point / 2),
2006 Size( indicator_size, indicator_size ) );
2008 else if (nPart == ControlPart::Separator)
2010 gint separator_height, separator_width, wide_separators;
2012 gtk_style_context_get_style (mpSeparatorMenuItemSeparatorStyle,
2013 "wide-separators", &wide_separators,
2014 "separator-width", &separator_width,
2015 "separator-height", &separator_height,
2016 nullptr);
2018 aEditRect = tools::Rectangle( aEditRect.TopLeft(),
2019 Size( aEditRect.GetWidth(), wide_separators ? separator_height : 1 ) );
2021 else if (nPart == ControlPart::SubmenuArrow)
2023 gfloat arrow_size = getArrowSize(mpMenuItemArrowStyle);
2024 aEditRect = tools::Rectangle( aEditRect.TopLeft(),
2025 Size( arrow_size, arrow_size ) );
2028 else if ( (nType==ControlType::Scrollbar) &&
2029 ((nPart==ControlPart::ButtonLeft) || (nPart==ControlPart::ButtonRight) ||
2030 (nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) ) )
2032 rNativeBoundingRegion = NWGetScrollButtonRect( nPart, rControlRegion );
2033 rNativeContentRegion = rNativeBoundingRegion;
2035 if (!rNativeContentRegion.GetWidth())
2036 rNativeContentRegion.SetRight( rNativeContentRegion.Left() + 1 );
2037 if (!rNativeContentRegion.GetHeight())
2038 rNativeContentRegion.SetBottom( rNativeContentRegion.Top() + 1 );
2040 return true;
2042 else if ( (nType==ControlType::Spinbox) &&
2043 ((nPart==ControlPart::ButtonUp) || (nPart==ControlPart::ButtonDown) ||
2044 (nPart==ControlPart::SubEdit)) )
2046 tools::Rectangle aControlRegion(GetWidgetSize(rControlRegion, gSpinBox));
2047 aEditRect = NWGetSpinButtonRect(nPart, aControlRegion);
2049 else if ( (nType==ControlType::Combobox) &&
2050 ((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
2052 aEditRect = NWGetComboBoxButtonRect(nType, nPart, rControlRegion);
2054 else if ( (nType==ControlType::Listbox) &&
2055 ((nPart==ControlPart::ButtonDown) || (nPart==ControlPart::SubEdit)) )
2057 aEditRect = NWGetComboBoxButtonRect(nType, nPart, rControlRegion);
2059 else if (nType == ControlType::Editbox && nPart == ControlPart::Entire)
2061 aEditRect = GetWidgetSize(rControlRegion, gEntryBox);
2063 else if (nType == ControlType::Listbox && nPart == ControlPart::Entire)
2065 aEditRect = GetWidgetSize(rControlRegion, gListBox);
2067 else if (nType == ControlType::Combobox && nPart == ControlPart::Entire)
2069 aEditRect = GetWidgetSize(rControlRegion, gComboBox);
2071 else if (nType == ControlType::Spinbox && nPart == ControlPart::Entire)
2073 aEditRect = GetWidgetSize(rControlRegion, gSpinBox);
2075 else if (nType == ControlType::TabItem && nPart == ControlPart::Entire)
2077 const TabitemValue& rTabitemValue = static_cast<const TabitemValue&>(rValue);
2078 const tools::Rectangle& rTabitemRect = rTabitemValue.getContentRect();
2080 aEditRect = AdjustRectForTextBordersPadding(mpNotebookHeaderTabsTabStyle, rTabitemRect.GetWidth(),
2081 rTabitemRect.GetHeight(), rControlRegion);
2083 else if (nType == ControlType::Frame && nPart == ControlPart::Border)
2085 aEditRect = rControlRegion;
2087 GtkBorder padding;
2088 gtk_style_context_get_padding(mpFrameInStyle, gtk_style_context_get_state(mpFrameInStyle), &padding);
2090 GtkBorder border;
2091 gtk_style_context_get_border(mpFrameInStyle, gtk_style_context_get_state(mpFrameInStyle), &border);
2093 int x1 = aEditRect.Left();
2094 int y1 = aEditRect.Top();
2095 int x2 = aEditRect.Right();
2096 int y2 = aEditRect.Bottom();
2098 rNativeBoundingRegion = aEditRect;
2099 rNativeContentRegion = tools::Rectangle(x1 + (padding.left + border.left),
2100 y1 + (padding.top + border.top),
2101 x2 - (padding.right + border.right),
2102 y2 - (padding.bottom + border.bottom));
2104 return true;
2106 else
2108 return false;
2111 rNativeBoundingRegion = aEditRect;
2112 rNativeContentRegion = rNativeBoundingRegion;
2114 return true;
2116 /************************************************************************
2117 * helper for GtkSalFrame
2118 ************************************************************************/
2119 static ::Color getColor( const GdkRGBA& rCol )
2121 return ::Color( static_cast<int>(rCol.red * 0xFFFF) >> 8, static_cast<int>(rCol.green * 0xFFFF) >> 8, static_cast<int>(rCol.blue * 0xFFFF) >> 8 );
2124 static vcl::Font getFont(GtkStyleContext* pStyle, const css::lang::Locale& rLocale)
2126 const PangoFontDescription* font = gtk_style_context_get_font(pStyle, gtk_style_context_get_state(pStyle));
2127 return pango_to_vcl(font, rLocale);
2130 vcl::Font pango_to_vcl(const PangoFontDescription* font, const css::lang::Locale& rLocale)
2132 OString aFamily = pango_font_description_get_family( font );
2133 int nPangoHeight = pango_font_description_get_size( font );
2134 PangoStyle eStyle = pango_font_description_get_style( font );
2135 PangoWeight eWeight = pango_font_description_get_weight( font );
2136 PangoStretch eStretch = pango_font_description_get_stretch( font );
2138 psp::FastPrintFontInfo aInfo;
2139 // set family name
2140 aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
2141 // set italic
2142 switch( eStyle )
2144 case PANGO_STYLE_NORMAL: aInfo.m_eItalic = ITALIC_NONE;break;
2145 case PANGO_STYLE_ITALIC: aInfo.m_eItalic = ITALIC_NORMAL;break;
2146 case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = ITALIC_OBLIQUE;break;
2148 // set weight
2149 if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
2150 aInfo.m_eWeight = WEIGHT_ULTRALIGHT;
2151 else if( eWeight <= PANGO_WEIGHT_LIGHT )
2152 aInfo.m_eWeight = WEIGHT_LIGHT;
2153 else if( eWeight <= PANGO_WEIGHT_NORMAL )
2154 aInfo.m_eWeight = WEIGHT_NORMAL;
2155 else if( eWeight <= PANGO_WEIGHT_BOLD )
2156 aInfo.m_eWeight = WEIGHT_BOLD;
2157 else
2158 aInfo.m_eWeight = WEIGHT_ULTRABOLD;
2159 // set width
2160 switch( eStretch )
2162 case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = WIDTH_ULTRA_CONDENSED;break;
2163 case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = WIDTH_EXTRA_CONDENSED;break;
2164 case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = WIDTH_CONDENSED;break;
2165 case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = WIDTH_SEMI_CONDENSED;break;
2166 case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = WIDTH_NORMAL;break;
2167 case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = WIDTH_SEMI_EXPANDED;break;
2168 case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = WIDTH_EXPANDED;break;
2169 case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = WIDTH_EXTRA_EXPANDED;break;
2170 case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = WIDTH_ULTRA_EXPANDED;break;
2173 #if OSL_DEBUG_LEVEL > 1
2174 SAL_INFO("vcl.gtk3", "font name BEFORE system match: \""
2175 << aFamily << "\".");
2176 #endif
2178 // match font to e.g. resolve "Sans"
2179 psp::PrintFontManager::get().matchFont(aInfo, rLocale);
2181 #if OSL_DEBUG_LEVEL > 1
2182 SAL_INFO("vcl.gtk3", "font match "
2183 << (aInfo.m_nID != 0 ? "succeeded" : "failed")
2184 << ", name AFTER: \""
2185 << aInfo.m_aFamilyName
2186 << "\".");
2187 #endif
2189 int nPointHeight = nPangoHeight/PANGO_SCALE;
2191 vcl::Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
2192 if( aInfo.m_eWeight != WEIGHT_DONTKNOW )
2193 aFont.SetWeight( aInfo.m_eWeight );
2194 if( aInfo.m_eWidth != WIDTH_DONTKNOW )
2195 aFont.SetWidthType( aInfo.m_eWidth );
2196 if( aInfo.m_eItalic != ITALIC_DONTKNOW )
2197 aFont.SetItalic( aInfo.m_eItalic );
2198 if( aInfo.m_ePitch != PITCH_DONTKNOW )
2199 aFont.SetPitch( aInfo.m_ePitch );
2200 return aFont;
2203 bool GtkSalGraphics::updateSettings(AllSettings& rSettings)
2205 GtkWidget* pTopLevel = gtk_widget_get_toplevel(mpWindow);
2206 GtkStyleContext* pStyle = gtk_widget_get_style_context(pTopLevel);
2207 StyleContextSave aContextState;
2208 aContextState.save(pStyle);
2209 GtkSettings* pSettings = gtk_widget_get_settings(pTopLevel);
2210 StyleSettings aStyleSet = rSettings.GetStyleSettings();
2211 GdkRGBA color;
2213 // text colors
2214 GdkRGBA text_color;
2215 style_context_set_state(pStyle, GTK_STATE_FLAG_NORMAL);
2216 gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), &text_color);
2217 ::Color aTextColor = getColor( text_color );
2218 aStyleSet.SetDialogTextColor( aTextColor );
2219 aStyleSet.SetButtonTextColor( aTextColor );
2220 aStyleSet.SetDefaultActionButtonTextColor(aTextColor);
2221 aStyleSet.SetActionButtonTextColor(aTextColor);
2222 aStyleSet.SetRadioCheckTextColor( aTextColor );
2223 aStyleSet.SetGroupTextColor( aTextColor );
2224 aStyleSet.SetLabelTextColor( aTextColor );
2225 aStyleSet.SetWindowTextColor( aTextColor );
2226 aStyleSet.SetFieldTextColor( aTextColor );
2228 // background colors
2229 GdkRGBA background_color;
2230 gtk_style_context_get_background_color(pStyle, gtk_style_context_get_state(pStyle), &background_color);
2232 ::Color aBackColor = getColor( background_color );
2233 aStyleSet.BatchSetBackgrounds( aBackColor );
2235 // UI font
2236 vcl::Font aFont(getFont(pStyle, rSettings.GetUILanguageTag().getLocale()));
2238 aStyleSet.BatchSetFonts( aFont, aFont);
2240 aFont.SetWeight( WEIGHT_BOLD );
2241 aStyleSet.SetTitleFont( aFont );
2242 aStyleSet.SetFloatTitleFont( aFont );
2244 // mouse over text colors
2245 style_context_set_state(pStyle, GTK_STATE_FLAG_PRELIGHT);
2246 gtk_style_context_get_color(pStyle, gtk_style_context_get_state(pStyle), &text_color);
2247 aTextColor = getColor(text_color);
2248 aStyleSet.SetDefaultButtonRolloverTextColor(aTextColor);
2249 aStyleSet.SetButtonRolloverTextColor(aTextColor);
2250 aStyleSet.SetDefaultActionButtonRolloverTextColor(aTextColor);
2251 aStyleSet.SetActionButtonRolloverTextColor(aTextColor);
2252 aStyleSet.SetFlatButtonRolloverTextColor(aTextColor);
2253 aStyleSet.SetFieldRolloverTextColor(aTextColor);
2255 aContextState.restore();
2257 // button mouse over colors
2259 GdkRGBA normal_button_rollover_text_color, pressed_button_rollover_text_color;
2260 aContextState.save(mpButtonStyle);
2261 style_context_set_state(mpButtonStyle, GTK_STATE_FLAG_PRELIGHT);
2262 gtk_style_context_get_color(mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &normal_button_rollover_text_color);
2263 aTextColor = getColor(normal_button_rollover_text_color);
2264 aStyleSet.SetButtonRolloverTextColor( aTextColor );
2265 style_context_set_state(mpButtonStyle, static_cast<GtkStateFlags>(GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_ACTIVE));
2266 gtk_style_context_get_color(mpButtonStyle, gtk_style_context_get_state(mpButtonStyle), &pressed_button_rollover_text_color);
2267 aTextColor = getColor(pressed_button_rollover_text_color);
2268 style_context_set_state(mpButtonStyle, GTK_STATE_FLAG_NORMAL);
2269 aStyleSet.SetButtonPressedRolloverTextColor( aTextColor );
2270 aContextState.restore();
2273 // tooltip colors
2275 GtkWidgetPath *pCPath = gtk_widget_path_new();
2276 guint pos = gtk_widget_path_append_type(pCPath, GTK_TYPE_WINDOW);
2277 gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_TOOLTIP);
2278 pos = gtk_widget_path_append_type (pCPath, GTK_TYPE_LABEL);
2279 gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_LABEL);
2280 GtkStyleContext *pCStyle = makeContext (pCPath, nullptr);
2281 aContextState.save(pCStyle);
2283 GdkRGBA tooltip_bg_color, tooltip_fg_color;
2284 style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
2285 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &tooltip_fg_color);
2286 gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &tooltip_bg_color);
2288 aContextState.restore();
2289 g_object_unref( pCStyle );
2291 aStyleSet.SetHelpColor( getColor( tooltip_bg_color ));
2292 aStyleSet.SetHelpTextColor( getColor( tooltip_fg_color ));
2296 // construct style context for text view
2297 GtkWidgetPath *pCPath = gtk_widget_path_new();
2298 gtk_widget_path_append_type( pCPath, GTK_TYPE_TEXT_VIEW );
2299 gtk_widget_path_iter_add_class( pCPath, -1, GTK_STYLE_CLASS_VIEW );
2300 GtkStyleContext *pCStyle = makeContext( pCPath, nullptr );
2301 aContextState.save(pCStyle);
2303 // highlighting colors
2304 style_context_set_state(pCStyle, GTK_STATE_FLAG_SELECTED);
2305 gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
2306 ::Color aHighlightColor = getColor( text_color );
2307 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
2308 ::Color aHighlightTextColor = getColor( text_color );
2309 aStyleSet.SetHighlightColor( aHighlightColor );
2310 aStyleSet.SetHighlightTextColor( aHighlightTextColor );
2311 // make active like highlight, except with a small contrast. Note, see
2312 // a GtkListBoxRow in a GtkStackSidebar for a gtk widget with a
2313 // difference between highlighted and highlighted with focus.
2314 aHighlightColor.IncreaseLuminance(16);
2315 aStyleSet.SetActiveColor( aHighlightColor );
2316 aStyleSet.SetActiveTextColor( aHighlightTextColor );
2318 // field background color
2319 GdkRGBA field_background_color;
2320 style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
2321 gtk_style_context_get_background_color(pCStyle, gtk_style_context_get_state(pCStyle), &field_background_color);
2323 ::Color aBackFieldColor = getColor( field_background_color );
2324 aStyleSet.SetFieldColor( aBackFieldColor );
2325 // This baby is the default page/paper color
2326 aStyleSet.SetWindowColor( aBackFieldColor );
2328 // Cursor width
2329 gfloat caretAspectRatio = 0.04f;
2330 gtk_style_context_get_style( pCStyle, "cursor-aspect-ratio", &caretAspectRatio, nullptr );
2331 // Assume 20px tall for the ratio computation, which should give reasonable results
2332 aStyleSet.SetCursorSize( 20 * caretAspectRatio + 1 );
2334 // Dark shadow color
2335 style_context_set_state(pCStyle, GTK_STATE_FLAG_INSENSITIVE);
2336 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &color);
2337 ::Color aDarkShadowColor = getColor( color );
2338 aStyleSet.SetDarkShadowColor( aDarkShadowColor );
2340 ::Color aShadowColor(aBackColor);
2341 if (aDarkShadowColor.GetLuminance() > aBackColor.GetLuminance())
2342 aShadowColor.IncreaseLuminance(64);
2343 else
2344 aShadowColor.DecreaseLuminance(64);
2345 aStyleSet.SetShadowColor(aShadowColor);
2347 aContextState.restore();
2348 g_object_unref( pCStyle );
2350 // Tab colors
2351 aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color.
2352 aStyleSet.SetInactiveTabColor( aBackColor );
2355 // menu disabled entries handling
2356 aStyleSet.SetSkipDisabledInMenus( true );
2357 aStyleSet.SetPreferredContextMenuShortcuts( false );
2359 aContextState.save(mpMenuItemLabelStyle);
2361 // menu colors
2362 style_context_set_state(mpMenuStyle, GTK_STATE_FLAG_NORMAL);
2363 gtk_style_context_get_background_color( mpMenuStyle, gtk_style_context_get_state(mpMenuStyle), &background_color );
2364 aBackColor = getColor( background_color );
2365 aStyleSet.SetMenuColor( aBackColor );
2367 // menu bar
2368 style_context_set_state(mpMenuBarStyle, GTK_STATE_FLAG_NORMAL);
2369 gtk_style_context_get_background_color( mpMenuBarStyle, gtk_style_context_get_state(mpMenuBarStyle), &background_color );
2370 aBackColor = getColor( background_color );
2371 aStyleSet.SetMenuBarColor( aBackColor );
2372 aStyleSet.SetMenuBarRolloverColor( aBackColor );
2374 style_context_set_state(mpMenuBarItemStyle, GTK_STATE_FLAG_NORMAL);
2375 gtk_style_context_get_color( mpMenuBarItemStyle, gtk_style_context_get_state(mpMenuBarItemStyle), &text_color );
2376 aTextColor = aStyleSet.GetPersonaMenuBarTextColor().value_or( getColor( text_color ) );
2377 aStyleSet.SetMenuBarTextColor( aTextColor );
2378 aStyleSet.SetMenuBarRolloverTextColor( aTextColor );
2380 style_context_set_state(mpMenuBarItemStyle, GTK_STATE_FLAG_PRELIGHT);
2381 gtk_style_context_get_color( mpMenuBarItemStyle, gtk_style_context_get_state(mpMenuBarItemStyle), &text_color );
2382 aTextColor = aStyleSet.GetPersonaMenuBarTextColor().value_or( getColor( text_color ) );
2383 aStyleSet.SetMenuBarHighlightTextColor( aTextColor );
2385 // menu items
2386 style_context_set_state(mpMenuItemLabelStyle, GTK_STATE_FLAG_NORMAL);
2387 gtk_style_context_get_color(mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &color);
2388 aTextColor = getColor(color);
2389 aStyleSet.SetMenuTextColor(aTextColor);
2391 style_context_set_state(mpMenuItemLabelStyle, GTK_STATE_FLAG_PRELIGHT);
2392 gtk_style_context_get_background_color( mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &background_color );
2393 ::Color aHighlightColor = getColor( background_color );
2394 aStyleSet.SetMenuHighlightColor( aHighlightColor );
2396 gtk_style_context_get_color( mpMenuItemLabelStyle, gtk_style_context_get_state(mpMenuItemLabelStyle), &color );
2397 ::Color aHighlightTextColor = getColor( color );
2398 aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
2400 aContextState.restore();
2402 // hyperlink colors
2403 aContextState.save(mpLinkButtonStyle);
2404 style_context_set_state(mpLinkButtonStyle, GTK_STATE_FLAG_LINK);
2405 gtk_style_context_get_color(mpLinkButtonStyle, gtk_style_context_get_state(mpLinkButtonStyle), &text_color);
2406 aStyleSet.SetLinkColor(getColor(text_color));
2407 style_context_set_state(mpLinkButtonStyle, GTK_STATE_FLAG_VISITED);
2408 gtk_style_context_get_color(mpLinkButtonStyle, gtk_style_context_get_state(mpLinkButtonStyle), &text_color);
2409 aStyleSet.SetVisitedLinkColor(getColor(text_color));
2410 aContextState.restore();
2413 GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabLabelStyle;
2414 aContextState.save(pCStyle);
2415 style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
2416 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
2417 aTextColor = getColor( text_color );
2418 aStyleSet.SetTabTextColor(aTextColor);
2419 aStyleSet.SetTabFont(getFont(mpNotebookHeaderTabsTabLabelStyle, rSettings.GetUILanguageTag().getLocale()));
2420 aContextState.restore();
2424 GtkStyleContext *pCStyle = mpToolButtonStyle;
2425 aContextState.save(pCStyle);
2426 style_context_set_state(pCStyle, GTK_STATE_FLAG_NORMAL);
2427 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
2428 aTextColor = getColor( text_color );
2429 aStyleSet.SetToolTextColor(aTextColor);
2430 aStyleSet.SetToolFont(getFont(mpToolButtonStyle, rSettings.GetUILanguageTag().getLocale()));
2431 aContextState.restore();
2434 // mouse over text colors
2436 GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabHoverLabelStyle;
2437 aContextState.save(pCStyle);
2438 style_context_set_state(pCStyle, GTK_STATE_FLAG_PRELIGHT);
2439 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
2440 aTextColor = getColor( text_color );
2441 aStyleSet.SetTabRolloverTextColor(aTextColor);
2442 aContextState.restore();
2446 GtkStyleContext *pCStyle = mpNotebookHeaderTabsTabActiveLabelStyle;
2447 aContextState.save(pCStyle);
2448 style_context_set_state(pCStyle, GTK_STATE_FLAG_CHECKED);
2449 gtk_style_context_get_color(pCStyle, gtk_style_context_get_state(pCStyle), &text_color);
2450 aTextColor = getColor( text_color );
2451 aStyleSet.SetTabHighlightTextColor(aTextColor);
2452 aContextState.restore();
2455 // get cursor blink time
2456 gboolean blink = false;
2458 g_object_get( pSettings, "gtk-cursor-blink", &blink, nullptr );
2459 if( blink )
2461 gint blink_time = static_cast<gint>(STYLE_CURSOR_NOBLINKTIME);
2462 g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, nullptr );
2463 // set the blink_time if there is a setting and it is reasonable
2464 // else leave the default value
2465 if( blink_time > 100 )
2466 aStyleSet.SetCursorBlinkTime( blink_time/2 );
2468 else
2469 aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
2471 MouseSettings aMouseSettings = rSettings.GetMouseSettings();
2472 int iDoubleClickTime, iDoubleClickDistance, iDragThreshold;
2473 static const int MENU_POPUP_DELAY = 225;
2474 g_object_get( pSettings,
2475 "gtk-double-click-time", &iDoubleClickTime,
2476 "gtk-double-click-distance", &iDoubleClickDistance,
2477 "gtk-dnd-drag-threshold", &iDragThreshold,
2478 nullptr );
2479 aMouseSettings.SetDoubleClickTime( iDoubleClickTime );
2480 aMouseSettings.SetDoubleClickWidth( iDoubleClickDistance );
2481 aMouseSettings.SetDoubleClickHeight( iDoubleClickDistance );
2482 aMouseSettings.SetStartDragWidth( iDragThreshold );
2483 aMouseSettings.SetStartDragHeight( iDragThreshold );
2484 aMouseSettings.SetMenuDelay( MENU_POPUP_DELAY );
2485 rSettings.SetMouseSettings( aMouseSettings );
2487 gboolean primarybuttonwarps = false;
2488 g_object_get( pSettings,
2489 "gtk-primary-button-warps-slider", &primarybuttonwarps,
2490 nullptr );
2491 aStyleSet.SetPreferredUseImagesInMenus(false);
2492 aStyleSet.SetPrimaryButtonWarpsSlider(primarybuttonwarps);
2494 // set scrollbar settings
2495 gint min_slider_length = 21;
2497 // Grab some button style attributes
2498 Size aSize;
2499 QuerySize(mpHScrollbarStyle, aSize);
2500 QuerySize(mpHScrollbarContentsStyle, aSize);
2501 QuerySize(mpHScrollbarTroughStyle, aSize);
2502 QuerySize(mpHScrollbarSliderStyle, aSize);
2504 gboolean has_forward, has_forward2, has_backward, has_backward2;
2505 gtk_style_context_get_style(mpHScrollbarStyle,
2506 "has-forward-stepper", &has_forward,
2507 "has-secondary-forward-stepper", &has_forward2,
2508 "has-backward-stepper", &has_backward,
2509 "has-secondary-backward-stepper", &has_backward2, nullptr);
2510 if (has_forward || has_backward || has_forward2 || has_backward2)
2511 QuerySize(mpHScrollbarButtonStyle, aSize);
2513 aStyleSet.SetScrollBarSize(aSize.Height());
2515 gtk_style_context_get(mpVScrollbarSliderStyle, gtk_style_context_get_state(mpVScrollbarSliderStyle),
2516 "min-height", &min_slider_length,
2517 nullptr);
2518 aStyleSet.SetMinThumbSize(min_slider_length);
2520 // preferred icon style
2521 gchar* pIconThemeName = nullptr;
2522 gboolean bDarkIconTheme = false;
2523 g_object_get(pSettings, "gtk-icon-theme-name", &pIconThemeName,
2524 "gtk-application-prefer-dark-theme", &bDarkIconTheme,
2525 nullptr );
2526 OUString sIconThemeName(OUString::createFromAscii(pIconThemeName));
2527 aStyleSet.SetPreferredIconTheme(sIconThemeName, bDarkIconTheme);
2528 g_free( pIconThemeName );
2530 aStyleSet.SetToolbarIconSize( ToolbarIconSize::Large );
2532 // finally update the collected settings
2533 rSettings.SetStyleSettings( aStyleSet );
2534 #if OSL_DEBUG_LEVEL > 1
2535 gchar* pThemeName = NULL;
2536 g_object_get( pSettings, "gtk-theme-name", &pThemeName, nullptr );
2537 SAL_INFO("vcl.gtk3", "Theme name is \""
2538 << pThemeName
2539 << "\".");
2540 g_free(pThemeName);
2541 #endif
2543 return true;
2546 bool GtkSalGraphics::isNativeControlSupported( ControlType nType, ControlPart nPart )
2548 switch(nType)
2550 case ControlType::Pushbutton:
2551 case ControlType::Radiobutton:
2552 case ControlType::Checkbox:
2553 case ControlType::Progress:
2554 case ControlType::ListNode:
2555 case ControlType::ListNet:
2556 if (nPart==ControlPart::Entire || nPart == ControlPart::Focus)
2557 return true;
2558 break;
2560 case ControlType::Scrollbar:
2561 if(nPart==ControlPart::DrawBackgroundHorz || nPart==ControlPart::DrawBackgroundVert ||
2562 nPart==ControlPart::Entire || nPart==ControlPart::HasThreeButtons)
2563 return true;
2564 break;
2566 case ControlType::Editbox:
2567 case ControlType::MultilineEditbox:
2568 if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture)
2569 return true;
2570 break;
2572 case ControlType::Combobox:
2573 if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::AllButtons)
2574 return true;
2575 break;
2577 case ControlType::Spinbox:
2578 if (nPart==ControlPart::Entire || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::AllButtons || nPart == ControlPart::ButtonUp || nPart == ControlPart::ButtonDown)
2579 return true;
2580 break;
2582 case ControlType::SpinButtons:
2583 if (nPart==ControlPart::Entire || nPart==ControlPart::AllButtons)
2584 return true;
2585 break;
2587 case ControlType::Frame:
2588 case ControlType::WindowBackground:
2589 return true;
2591 case ControlType::TabItem:
2592 case ControlType::TabHeader:
2593 case ControlType::TabPane:
2594 case ControlType::TabBody:
2595 if(nPart==ControlPart::Entire || nPart==ControlPart::TabsDrawRtl)
2596 return true;
2597 break;
2599 case ControlType::Listbox:
2600 if (nPart==ControlPart::Entire || nPart==ControlPart::ListboxWindow || nPart==ControlPart::HasBackgroundTexture || nPart == ControlPart::Focus)
2601 return true;
2602 break;
2604 case ControlType::Toolbar:
2605 if( nPart==ControlPart::Entire
2606 // || nPart==ControlPart::DrawBackgroundHorz
2607 // || nPart==ControlPart::DrawBackgroundVert
2608 // || nPart==ControlPart::ThumbHorz
2609 // || nPart==ControlPart::ThumbVert
2610 || nPart==ControlPart::Button
2611 // || nPart==ControlPart::SeparatorHorz
2612 || nPart==ControlPart::SeparatorVert
2614 return true;
2615 break;
2617 case ControlType::Menubar:
2618 if (nPart==ControlPart::Entire || nPart==ControlPart::MenuItem)
2619 return true;
2620 break;
2622 case ControlType::MenuPopup:
2623 if (nPart==ControlPart::Entire
2624 || nPart==ControlPart::MenuItem
2625 || nPart==ControlPart::MenuItemCheckMark
2626 || nPart==ControlPart::MenuItemRadioMark
2627 || nPart==ControlPart::Separator
2628 || nPart==ControlPart::SubmenuArrow
2630 return true;
2631 break;
2633 // case ControlType::Slider:
2634 // if(nPart == ControlPart::TrackHorzArea || nPart == ControlPart::TrackVertArea)
2635 // return true;
2636 // break;
2638 case ControlType::Fixedline:
2639 if (nPart == ControlPart::SeparatorVert || nPart == ControlPart::SeparatorHorz)
2640 return true;
2641 break;
2643 case ControlType::ListHeader:
2644 if (nPart == ControlPart::Button || nPart == ControlPart::Arrow)
2645 return true;
2646 break;
2647 default: break;
2650 SAL_INFO("vcl.gtk", "Unhandled is native supported for Type:" << static_cast<int>(nType) << ", Part" << static_cast<int>(nPart));
2652 return false;
2655 #if ENABLE_CAIRO_CANVAS
2657 bool GtkSalGraphics::SupportsCairo() const
2659 return true;
2662 cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
2664 return std::make_shared<cairo::Gtk3Surface>(rSurface);
2667 cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int x, int y, int width, int height) const
2669 return std::make_shared<cairo::Gtk3Surface>(this, x, y, width, height);
2672 #endif
2674 void GtkSalGraphics::WidgetQueueDraw() const
2676 //request gtk to sync the entire contents
2677 GtkWidget *pWidget = GTK_WIDGET(mpFrame->getFixedContainer());
2678 gtk_widget_queue_draw(pWidget);
2681 namespace {
2683 void getStyleContext(GtkStyleContext** style, GtkWidget* widget)
2685 gtk_container_add(GTK_CONTAINER(gDumbContainer), widget);
2686 *style = gtk_widget_get_style_context(widget);
2687 g_object_ref(*style);
2692 void GtkSalData::initNWF()
2694 ImplSVData* pSVData = ImplGetSVData();
2695 pSVData->maNWFData.mbFlatMenu = true;
2696 pSVData->maNWFData.mbDockingAreaAvoidTBFrames = true;
2697 pSVData->maNWFData.mbCanDrawWidgetAnySize = true;
2698 pSVData->maNWFData.mbDDListBoxNoTextArea = true;
2699 pSVData->maNWFData.mbNoFocusRects = true;
2700 pSVData->maNWFData.mbNoFocusRectsForFlatButtons = true;
2701 pSVData->maNWFData.mbAutoAccel = true;
2703 #if defined(GDK_WINDOWING_WAYLAND)
2704 //gnome#768128 for the car crash that is wayland
2705 //and floating dockable toolbars
2706 GdkDisplay *pDisplay = gdk_display_get_default();
2707 if (DLSYM_GDK_IS_WAYLAND_DISPLAY(pDisplay))
2708 pSVData->maNWFData.mbCanDetermineWindowPosition = false;
2709 #endif
2712 void GtkSalData::deInitNWF()
2714 if (gCacheWindow)
2715 gtk_widget_destroy(gCacheWindow);
2718 GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
2719 : SvpSalGraphics(),
2720 mpFrame( pFrame ),
2721 mpWindow( pWindow )
2723 if (style_loaded)
2724 return;
2726 style_loaded = true;
2728 /* Load the GtkStyleContexts, it might be a bit slow, but usually,
2729 * gtk apps create a lot of widgets at startup, so, it shouldn't be
2730 * too slow */
2732 gCacheWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2733 gDumbContainer = gtk_fixed_new();
2734 gtk_container_add(GTK_CONTAINER(gCacheWindow), gDumbContainer);
2735 gtk_widget_realize(gDumbContainer);
2736 gtk_widget_realize(gCacheWindow);
2738 gEntryBox = gtk_entry_new();
2739 gtk_container_add(GTK_CONTAINER(gDumbContainer), gEntryBox);
2741 mpWindowStyle = createStyleContext(GtkControlPart::ToplevelWindow);
2742 mpEntryStyle = createStyleContext(GtkControlPart::Entry);
2744 getStyleContext(&mpTextViewStyle, gtk_text_view_new());
2746 mpButtonStyle = createStyleContext(GtkControlPart::Button);
2747 mpLinkButtonStyle = createStyleContext(GtkControlPart::LinkButton);
2749 GtkWidget* pToolbar = gtk_toolbar_new();
2750 mpToolbarStyle = gtk_widget_get_style_context(pToolbar);
2751 gtk_style_context_add_class(mpToolbarStyle, GTK_STYLE_CLASS_TOOLBAR);
2753 GtkToolItem *item = gtk_separator_tool_item_new();
2754 gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
2755 mpToolbarSeparatorStyle = gtk_widget_get_style_context(GTK_WIDGET(item));
2757 GtkWidget *pButton = gtk_button_new();
2758 item = gtk_tool_button_new(pButton, nullptr);
2759 gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
2760 mpToolButtonStyle = gtk_widget_get_style_context(GTK_WIDGET(pButton));
2762 mpVScrollbarStyle = createStyleContext(GtkControlPart::ScrollbarVertical);
2763 mpVScrollbarContentsStyle = createStyleContext(GtkControlPart::ScrollbarVerticalContents);
2764 mpVScrollbarTroughStyle = createStyleContext(GtkControlPart::ScrollbarVerticalTrough);
2765 mpVScrollbarSliderStyle = createStyleContext(GtkControlPart::ScrollbarVerticalSlider);
2766 mpVScrollbarButtonStyle = createStyleContext(GtkControlPart::ScrollbarVerticalButton);
2767 mpHScrollbarStyle = createStyleContext(GtkControlPart::ScrollbarHorizontal);
2768 mpHScrollbarContentsStyle = createStyleContext(GtkControlPart::ScrollbarHorizontalContents);
2769 mpHScrollbarTroughStyle = createStyleContext(GtkControlPart::ScrollbarHorizontalTrough);
2770 mpHScrollbarSliderStyle = createStyleContext(GtkControlPart::ScrollbarHorizontalSlider);
2771 mpHScrollbarButtonStyle = createStyleContext(GtkControlPart::ScrollbarHorizontalButton);
2773 mpCheckButtonStyle = createStyleContext(GtkControlPart::CheckButton);
2774 mpCheckButtonCheckStyle = createStyleContext(GtkControlPart::CheckButtonCheck);
2776 mpRadioButtonStyle = createStyleContext(GtkControlPart::RadioButton);
2777 mpRadioButtonRadioStyle = createStyleContext(GtkControlPart::RadioButtonRadio);
2779 /* Spinbutton */
2780 gSpinBox = gtk_spin_button_new(nullptr, 0, 0);
2781 gtk_container_add(GTK_CONTAINER(gDumbContainer), gSpinBox);
2782 mpSpinStyle = createStyleContext(GtkControlPart::SpinButton);
2783 mpSpinUpStyle = createStyleContext(GtkControlPart::SpinButtonUpButton);
2784 mpSpinDownStyle = createStyleContext(GtkControlPart::SpinButtonDownButton);
2786 /* NoteBook */
2787 mpNotebookStyle = createStyleContext(GtkControlPart::Notebook);
2788 mpNotebookStackStyle = createStyleContext(GtkControlPart::NotebookStack);
2789 mpNotebookHeaderStyle = createStyleContext(GtkControlPart::NotebookHeader);
2790 mpNotebookHeaderTabsStyle = createStyleContext(GtkControlPart::NotebookHeaderTabs);
2791 mpNotebookHeaderTabsTabStyle = createStyleContext(GtkControlPart::NotebookHeaderTabsTab);
2792 mpNotebookHeaderTabsTabLabelStyle = createStyleContext(GtkControlPart::NotebookHeaderTabsTabLabel);
2793 mpNotebookHeaderTabsTabActiveLabelStyle = createStyleContext(GtkControlPart::NotebookHeaderTabsTabActiveLabel);
2794 mpNotebookHeaderTabsTabHoverLabelStyle = createStyleContext(GtkControlPart::NotebookHeaderTabsTabHoverLabel);
2796 /* Combobox */
2797 gComboBox = gtk_combo_box_text_new_with_entry();
2798 gtk_container_add(GTK_CONTAINER(gDumbContainer), gComboBox);
2799 mpComboboxStyle = createStyleContext(GtkControlPart::Combobox);
2800 mpComboboxBoxStyle = createStyleContext(GtkControlPart::ComboboxBox);
2801 mpComboboxEntryStyle = createStyleContext(GtkControlPart::ComboboxBoxEntry);
2802 mpComboboxButtonStyle = createStyleContext(GtkControlPart::ComboboxBoxButton);
2803 mpComboboxButtonBoxStyle = createStyleContext(GtkControlPart::ComboboxBoxButtonBox);
2804 mpComboboxButtonArrowStyle = createStyleContext(GtkControlPart::ComboboxBoxButtonBoxArrow);
2806 /* Listbox */
2807 gListBox = gtk_combo_box_text_new();
2808 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gListBox), "sample");
2809 gtk_container_add(GTK_CONTAINER(gDumbContainer), gListBox);
2810 mpListboxStyle = createStyleContext(GtkControlPart::Listbox);
2811 mpListboxBoxStyle = createStyleContext(GtkControlPart::ListboxBox);
2812 mpListboxButtonStyle = createStyleContext(GtkControlPart::ListboxBoxButton);
2813 mpListboxButtonBoxStyle = createStyleContext(GtkControlPart::ListboxBoxButtonBox);
2814 mpListboxButtonArrowStyle = createStyleContext(GtkControlPart::ListboxBoxButtonBoxArrow);
2816 mpMenuBarStyle = createStyleContext(GtkControlPart::MenuBar);
2817 mpMenuBarItemStyle = createStyleContext(GtkControlPart::MenuBarItem);
2819 /* Menu */
2820 mpMenuWindowStyle = createStyleContext(GtkControlPart::MenuWindow);
2821 mpMenuStyle = createStyleContext(GtkControlPart::Menu);
2823 mpMenuItemStyle = createStyleContext(GtkControlPart::MenuItem);
2824 mpMenuItemLabelStyle = createStyleContext(GtkControlPart::MenuItemLabel);
2825 mpMenuItemArrowStyle = createStyleContext(GtkControlPart::MenuItemArrow);
2826 mpCheckMenuItemStyle = createStyleContext(GtkControlPart::CheckMenuItem);
2827 mpCheckMenuItemCheckStyle = createStyleContext(GtkControlPart::CheckMenuItemCheck);
2828 mpRadioMenuItemStyle = createStyleContext(GtkControlPart::RadioMenuItem);
2829 mpRadioMenuItemRadioStyle = createStyleContext(GtkControlPart::RadioMenuItemRadio);
2830 mpSeparatorMenuItemStyle = createStyleContext(GtkControlPart::SeparatorMenuItem);
2831 mpSeparatorMenuItemSeparatorStyle = createStyleContext(GtkControlPart::SeparatorMenuItemSeparator);
2833 /* Frames */
2834 mpFrameOutStyle = mpFrameInStyle = createStyleContext(GtkControlPart::FrameBorder);
2835 getStyleContext(&mpFixedHoriLineStyle, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL));
2836 getStyleContext(&mpFixedVertLineStyle, gtk_separator_new(GTK_ORIENTATION_VERTICAL));
2839 /* Tree List */
2840 gTreeViewWidget = gtk_tree_view_new();
2841 gtk_container_add(GTK_CONTAINER(gDumbContainer), gTreeViewWidget);
2843 GtkTreeViewColumn* firstTreeViewColumn = gtk_tree_view_column_new();
2844 gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
2845 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
2847 GtkTreeViewColumn* middleTreeViewColumn = gtk_tree_view_column_new();
2848 gtk_tree_view_column_set_title(middleTreeViewColumn, "M");
2849 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
2850 gtk_tree_view_set_expander_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
2852 GtkTreeViewColumn* lastTreeViewColumn = gtk_tree_view_column_new();
2853 gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
2854 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
2856 /* Use the middle column's header for our button */
2857 GtkWidget* pTreeHeaderCellWidget = gtk_tree_view_column_get_button(middleTreeViewColumn);
2858 mpTreeHeaderButtonStyle = gtk_widget_get_style_context(pTreeHeaderCellWidget);
2860 /* Progress Bar */
2861 mpProgressBarStyle = createStyleContext(GtkControlPart::ProgressBar);
2862 mpProgressBarTroughStyle = createStyleContext(GtkControlPart::ProgressBarTrough);
2863 mpProgressBarProgressStyle = createStyleContext(GtkControlPart::ProgressBarProgress);
2865 gtk_widget_show_all(gDumbContainer);
2868 void GtkSalGraphics::GetResolution(sal_Int32& rDPIX, sal_Int32& rDPIY)
2870 char* pForceDpi;
2871 if ((pForceDpi = getenv("SAL_FORCEDPI")))
2873 OString sForceDPI(pForceDpi);
2874 rDPIX = rDPIY = sForceDPI.toInt32();
2875 return;
2878 GdkScreen* pScreen = gtk_widget_get_screen(mpWindow);
2879 double fResolution = -1.0;
2880 g_object_get(pScreen, "resolution", &fResolution, nullptr);
2882 if (fResolution > 0.0)
2883 rDPIX = rDPIY = sal_Int32(fResolution);
2884 else
2885 rDPIX = rDPIY = 96;
2888 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */