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