Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / unx / gtk3 / gdi / gtk3salnativewidgets-gtk.cxx
blob90d87342632300d581e6587c11588db7fa55a321
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sal/config.h>
12 #include <basegfx/range/b2ibox.hxx>
13 #include <unx/gtk/gtkframe.hxx>
14 #include <unx/gtk/gtkdata.hxx>
15 #include <unx/gtk/gtkinst.hxx>
16 #include <unx/gtk/gtkgdi.hxx>
17 #include <vcl/decoview.hxx>
18 #include <vcl/settings.hxx>
19 #include "fontmanager.hxx"
20 #include "gtk3cairotextrender.hxx"
21 #include "cairo_gtk3_cairo.hxx"
23 GtkStyleContext* GtkSalGraphics::mpButtonStyle = NULL;
24 GtkStyleContext* GtkSalGraphics::mpEntryStyle = NULL;
25 GtkStyleContext* GtkSalGraphics::mpTextViewStyle = NULL;
26 GtkStyleContext* GtkSalGraphics::mpVScrollbarStyle = NULL;
27 GtkStyleContext* GtkSalGraphics::mpHScrollbarStyle = NULL;
28 GtkStyleContext* GtkSalGraphics::mpToolbarStyle = NULL;
29 GtkStyleContext* GtkSalGraphics::mpToolButtonStyle = NULL;
30 GtkStyleContext* GtkSalGraphics::mpToolbarSeperatorStyle = NULL;
31 GtkStyleContext* GtkSalGraphics::mpCheckButtonStyle = NULL;
32 GtkStyleContext* GtkSalGraphics::mpMenuBarStyle = NULL;
33 GtkStyleContext* GtkSalGraphics::mpMenuBarItemStyle = NULL;
34 GtkStyleContext* GtkSalGraphics::mpMenuStyle = NULL;
35 GtkStyleContext* GtkSalGraphics::mpCheckMenuItemStyle = NULL;
36 GtkStyleContext* GtkSalGraphics::mpSpinStyle = NULL;
37 GtkStyleContext* GtkSalGraphics::mpComboboxStyle = NULL;
38 GtkStyleContext* GtkSalGraphics::mpComboboxButtonStyle = NULL;
39 GtkStyleContext* GtkSalGraphics::mpListboxStyle = NULL;
40 GtkStyleContext* GtkSalGraphics::mpListboxButtonStyle = NULL;
41 GtkStyleContext* GtkSalGraphics::mpNoteBookStyle = NULL;
42 GtkStyleContext* GtkSalGraphics::mpFrameInStyle = NULL;
43 GtkStyleContext* GtkSalGraphics::mpFrameOutStyle = NULL;
44 GtkStyleContext* GtkSalGraphics::mpFixedHoriLineStyle = NULL;
45 GtkStyleContext* GtkSalGraphics::mpFixedVertLineStyle = NULL;
46 GtkStyleContext* GtkSalGraphics::mpTreeHeaderButtonStyle = NULL;
47 GtkStyleContext* GtkSalGraphics::mpProgressBarStyle = NULL;
49 bool GtkSalGraphics::style_loaded = false;
50 /************************************************************************
51 * State conversion
52 ************************************************************************/
53 static void NWConvertVCLStateToGTKState( ControlState nVCLState,
54 GtkStateFlags* nGTKState, GtkShadowType* nGTKShadow )
56 *nGTKShadow = GTK_SHADOW_OUT;
57 *nGTKState = GTK_STATE_FLAG_NORMAL;
59 if (!( nVCLState & ControlState::ENABLED ))
61 *nGTKState = GTK_STATE_FLAG_INSENSITIVE;
64 if ( nVCLState & ControlState::PRESSED )
66 *nGTKState = (GtkStateFlags) (*nGTKState | GTK_STATE_FLAG_ACTIVE);
67 *nGTKShadow = GTK_SHADOW_IN;
70 if ( nVCLState & ControlState::ROLLOVER )
72 *nGTKState = (GtkStateFlags) (*nGTKState | GTK_STATE_FLAG_PRELIGHT);
75 if ( nVCLState & ControlState::SELECTED )
76 *nGTKState = (GtkStateFlags) (*nGTKState | GTK_STATE_FLAG_SELECTED);
78 if ( nVCLState & ControlState::FOCUSED )
79 *nGTKState = (GtkStateFlags) (*nGTKState | GTK_STATE_FLAG_FOCUSED);
81 if (AllSettings::GetLayoutRTL())
83 *nGTKState = (GtkStateFlags) (*nGTKState | GTK_STATE_FLAG_DIR_RTL);
87 enum {
88 RENDER_BACKGROUND_AND_FRAME = 1,
89 RENDER_CHECK = 2,
90 RENDER_BACKGROUND = 3,
91 RENDER_MENU_SEPERATOR = 4,
92 RENDER_TOOLBAR_SEPERATOR = 5,
93 RENDER_SEPERATOR = 6,
94 RENDER_ARROW = 7,
95 RENDER_RADIO = 8,
96 RENDER_SCROLLBAR = 9,
97 RENDER_SPINBUTTON = 10,
98 RENDER_COMBOBOX = 11,
99 RENDER_EXPANDER = 12,
100 RENDER_ICON = 13,
101 RENDER_PROGRESS = 14,
102 RENDER_FOCUS = 15,
105 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow )
107 // Size the arrow appropriately
108 Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 );
109 rArrow.SetSize( aSize );
111 rArrow.SetPos( Point(
112 rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2,
113 rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2
114 ) );
117 Rectangle GtkSalGraphics::NWGetSpinButtonRect( ControlPart nPart, Rectangle aAreaRect)
119 gtk_style_context_save(mpSpinStyle);
120 gtk_style_context_add_class(mpSpinStyle, GTK_STYLE_CLASS_BUTTON);
122 gint w, h;
123 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
124 gint icon_size = std::max(w, h);
126 GtkBorder padding, border;
127 gtk_style_context_get_padding(mpSpinStyle, GTK_STATE_FLAG_NORMAL, &padding);
128 gtk_style_context_get_border(mpSpinStyle, GTK_STATE_FLAG_NORMAL, &border);
130 gint buttonWidth = icon_size + padding.left + padding.right +
131 border.left + border.right;
133 gint buttonHeight = icon_size + padding.top + padding.bottom +
134 border.top + border.bottom;
136 Rectangle buttonRect;
137 buttonRect.SetSize(Size(buttonWidth, buttonHeight));
138 buttonRect.setY(aAreaRect.Top());
139 buttonRect.Bottom() = buttonRect.Top() + aAreaRect.GetHeight();
140 Rectangle partRect(buttonRect);
141 if ( nPart == PART_BUTTON_UP )
143 if (AllSettings::GetLayoutRTL())
144 partRect.setX(aAreaRect.Left());
145 else
146 partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()));
148 else if( nPart == PART_BUTTON_DOWN )
150 if (AllSettings::GetLayoutRTL())
151 partRect.setX(aAreaRect.Left() + buttonRect.GetWidth());
152 else
153 partRect.setX(aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth()));
155 else
157 if (AllSettings::GetLayoutRTL())
159 partRect.Right() = aAreaRect.Left() + aAreaRect.GetWidth();
160 partRect.Left() = aAreaRect.Left() + (2 * buttonRect.GetWidth()) - 1;
162 else
164 partRect.Right() = (aAreaRect.Left() + (aAreaRect.GetWidth() - 2 * buttonRect.GetWidth())) - 1;
165 partRect.Left() = aAreaRect.Left();
167 partRect.Top() = aAreaRect.Top();
168 partRect.Bottom() = aAreaRect.Bottom();
171 gtk_style_context_restore(mpSpinStyle);
173 return partRect;
176 Rectangle GtkSalGraphics::NWGetScrollButtonRect( ControlPart nPart, Rectangle aAreaRect )
178 GtkStyleContext* pScrollbarStyle = NULL;
179 if ((nPart == PART_BUTTON_LEFT) || (nPart == PART_BUTTON_RIGHT))
180 pScrollbarStyle = mpHScrollbarStyle;
181 else // (nPart == PART_BUTTON_UP) || (nPart == PART_BUTTON_DOWN)
182 pScrollbarStyle = mpVScrollbarStyle;
184 gint slider_width;
185 gint stepper_size;
186 gint stepper_spacing;
187 gint trough_border;
189 // Grab some button style attributes
190 gtk_style_context_get_style( pScrollbarStyle,
191 "slider-width", &slider_width,
192 "stepper-size", &stepper_size,
193 "trough-border", &trough_border,
194 "stepper-spacing", &stepper_spacing, (char *)NULL );
196 gboolean has_forward;
197 gboolean has_forward2;
198 gboolean has_backward;
199 gboolean has_backward2;
201 gtk_style_context_get_style( pScrollbarStyle,
202 "has-forward-stepper", &has_forward,
203 "has-secondary-forward-stepper", &has_forward2,
204 "has-backward-stepper", &has_backward,
205 "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
206 gint buttonWidth;
207 gint buttonHeight;
208 Rectangle buttonRect;
210 gint nFirst = 0;
211 gint nSecond = 0;
213 if ( has_forward ) nSecond += 1;
214 if ( has_forward2 ) nFirst += 1;
215 if ( has_backward ) nFirst += 1;
216 if ( has_backward2 ) nSecond += 1;
218 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) )
220 buttonWidth = slider_width + 2 * trough_border;
221 buttonHeight = stepper_size + trough_border + stepper_spacing;
223 else
225 buttonWidth = stepper_size + trough_border + stepper_spacing;
226 buttonHeight = slider_width + 2 * trough_border;
229 if ( nPart == PART_BUTTON_UP )
231 buttonHeight *= nFirst;
232 buttonHeight -= 1;
233 buttonRect.setX( aAreaRect.Left() );
234 buttonRect.setY( aAreaRect.Top() );
236 else if ( nPart == PART_BUTTON_LEFT )
238 buttonWidth *= nFirst;
239 buttonWidth -= 1;
240 buttonRect.setX( aAreaRect.Left() );
241 buttonRect.setY( aAreaRect.Top() );
243 else if ( nPart == PART_BUTTON_DOWN )
245 buttonHeight *= nSecond;
246 buttonRect.setX( aAreaRect.Left() );
247 buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight );
249 else if ( nPart == PART_BUTTON_RIGHT )
251 buttonWidth *= nSecond;
252 buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth );
253 buttonRect.setY( aAreaRect.Top() );
256 buttonRect.SetSize( Size( buttonWidth, buttonHeight ) );
258 return buttonRect;
261 void GtkSalGraphics::PaintScrollbar(GtkStyleContext *context,
262 cairo_t *cr,
263 const Rectangle& rControlRectangle,
264 ControlType nType,
265 ControlPart nPart,
266 const ImplControlValue& rValue )
268 (void)nType;
269 OSL_ASSERT( rValue.getType() == CTRL_SCROLLBAR );
270 const ScrollbarValue& rScrollbarVal = static_cast<const ScrollbarValue&>(rValue);
271 Rectangle scrollbarRect;
272 GtkStateFlags stateFlags;
273 GtkShadowType shadowType;
274 GtkOrientation scrollbarOrientation;
275 Rectangle thumbRect = rScrollbarVal.maThumbRect;
276 Rectangle button11BoundRect = rScrollbarVal.maButton1Rect; // backward
277 Rectangle button22BoundRect = rScrollbarVal.maButton2Rect; // forward
278 Rectangle button12BoundRect = rScrollbarVal.maButton1Rect; // secondary forward
279 Rectangle button21BoundRect = rScrollbarVal.maButton2Rect; // secondary backward
280 gdouble arrow1Angle; // backward
281 gdouble arrow2Angle; // forward
282 Rectangle arrowRect;
283 const gchar* button1StyleClass = NULL;
284 const gchar* button2StyleClass = NULL;
285 gint slider_width = 0;
286 gint stepper_size = 0;
287 gint stepper_spacing = 0;
288 gint trough_border = 0;
289 gint min_slider_length = 0;
291 // make controlvalue rectangles relative to area
292 thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
293 button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
294 button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
295 button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
296 button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() );
298 // Find the overall bounding rect of the control
299 scrollbarRect = rControlRectangle;
300 scrollbarRect.SetSize( Size( scrollbarRect.GetWidth() + 1,
301 scrollbarRect.GetHeight() + 1 ) );
303 if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) )
304 return;
306 // Grab some button style attributes
307 gtk_style_context_get_style( context,
308 "slider_width", &slider_width,
309 "stepper_size", &stepper_size,
310 "trough_border", &trough_border,
311 "stepper_spacing", &stepper_spacing,
312 "min_slider_length", &min_slider_length, (char *)NULL );
313 gboolean has_forward;
314 gboolean has_forward2;
315 gboolean has_backward;
316 gboolean has_backward2;
318 gtk_style_context_get_style( context,
319 "has-forward-stepper", &has_forward,
320 "has-secondary-forward-stepper", &has_forward2,
321 "has-backward-stepper", &has_backward,
322 "has-secondary-backward-stepper", &has_backward2, (char *)NULL );
323 gint magic = trough_border ? 1 : 0;
324 gint nFirst = 0;
325 gint slider_side = slider_width + (trough_border * 2);
327 if ( has_backward ) nFirst += 1;
328 if ( has_forward2 ) nFirst += 1;
330 if ( nPart == PART_DRAW_BACKGROUND_HORZ )
332 scrollbarRect.Move( 0, (scrollbarRect.GetHeight() - slider_side) / 2 );
333 scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), slider_side ) );
335 scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL;
336 arrow1Angle = G_PI * 3 / 2;
337 arrow2Angle = G_PI / 2;
338 button1StyleClass = GTK_STYLE_CLASS_LEFT;
339 button2StyleClass = GTK_STYLE_CLASS_RIGHT;
341 if ( has_backward )
343 button12BoundRect.Move( stepper_size - trough_border,
344 (scrollbarRect.GetHeight() - slider_width) / 2 );
347 button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 );
348 button11BoundRect.SetSize( Size( stepper_size, slider_width ) );
349 button12BoundRect.SetSize( Size( stepper_size, slider_width ) );
351 if ( has_backward2 )
353 button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
354 button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
356 else
358 button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 );
361 button21BoundRect.SetSize( Size( stepper_size, slider_width ) );
362 button22BoundRect.SetSize( Size( stepper_size, slider_width ) );
364 thumbRect.Bottom() = thumbRect.Top() + slider_width - 1;
365 // Make sure the thumb is at least the default width (so we don't get tiny thumbs),
366 // but if the VCL gives us a size smaller than the theme's default thumb size,
367 // honor the VCL size
368 thumbRect.Right() += magic;
369 // Center vertically in the track
370 thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 );
372 else
374 scrollbarRect.Move( (scrollbarRect.GetWidth() - slider_side) / 2, 0 );
375 scrollbarRect.SetSize( Size( slider_side, scrollbarRect.GetHeight() ) );
377 scrollbarOrientation = GTK_ORIENTATION_VERTICAL;
378 arrow1Angle = 0;
379 arrow2Angle = G_PI;
380 button1StyleClass = GTK_STYLE_CLASS_TOP;
381 button2StyleClass = GTK_STYLE_CLASS_BOTTOM;
383 if ( has_backward )
385 button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2,
386 stepper_size + trough_border );
388 button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border );
389 button11BoundRect.SetSize( Size( slider_width, stepper_size ) );
390 button12BoundRect.SetSize( Size( slider_width, stepper_size ) );
392 if ( has_backward2 )
394 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 );
395 button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
397 else
399 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 );
402 button21BoundRect.SetSize( Size( slider_width, stepper_size ) );
403 button22BoundRect.SetSize( Size( slider_width, stepper_size ) );
405 thumbRect.Right() = thumbRect.Left() + slider_width - 1;
407 thumbRect.Bottom() += magic;
408 // Center horizontally in the track
409 thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 );
412 bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 );
414 // ----------------- TROUGH
415 gtk_style_context_save(context);
416 gtk_style_context_add_class(context, GTK_STYLE_CLASS_TROUGH);
417 gtk_render_background(context, cr, 0, 0,
418 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
419 gtk_render_frame(context, cr, 0, 0,
420 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() );
422 gtk_style_context_restore(context);
424 // ----------------- THUMB
425 if ( has_slider )
427 NWConvertVCLStateToGTKState( rScrollbarVal.mnThumbState, &stateFlags, &shadowType );
428 if ( rScrollbarVal.mnThumbState & ControlState::PRESSED )
429 stateFlags = (GtkStateFlags) (stateFlags | GTK_STATE_PRELIGHT);
431 gtk_style_context_save(context);
432 gtk_style_context_set_state(context, stateFlags);
433 gtk_style_context_add_class(context, GTK_STYLE_CLASS_SLIDER);
435 GtkBorder margin;
436 gtk_style_context_get_margin(context, stateFlags, &margin);
439 gtk_render_slider(context, cr,
440 thumbRect.Left() + margin.left, thumbRect.Top() + margin.top,
441 thumbRect.GetWidth() - margin.left - margin.right,
442 thumbRect.GetHeight() - margin.top - margin.bottom,
443 scrollbarOrientation);
445 gtk_style_context_restore(context);
448 bool backwardButtonInsensitive =
449 rScrollbarVal.mnCur == rScrollbarVal.mnMin;
450 bool forwardButtonInsensitive = rScrollbarVal.mnMax == 0 ||
451 rScrollbarVal.mnCur + rScrollbarVal.mnVisibleSize >= rScrollbarVal.mnMax;
453 // ----------------- BUTTON 1
454 if ( has_backward )
456 NWConvertVCLStateToGTKState( rScrollbarVal.mnButton1State, &stateFlags, &shadowType );
457 if ( backwardButtonInsensitive )
458 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
460 gtk_style_context_save(context);
461 gtk_style_context_set_state(context, stateFlags);
462 gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
463 gtk_style_context_add_class(context, button1StyleClass);
465 gtk_render_background(context, cr,
466 button11BoundRect.Left(), button11BoundRect.Top(),
467 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
468 gtk_render_frame(context, cr,
469 button11BoundRect.Left(), button11BoundRect.Top(),
470 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() );
472 // ----------------- ARROW 1
473 NWCalcArrowRect( button11BoundRect, arrowRect );
474 gtk_render_arrow(context, cr,
475 arrow1Angle,
476 arrowRect.Left(), arrowRect.Top(),
477 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
479 gtk_style_context_restore(context);
481 if ( has_forward2 )
483 NWConvertVCLStateToGTKState( rScrollbarVal.mnButton2State, &stateFlags, &shadowType );
484 if ( forwardButtonInsensitive )
485 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
487 gtk_style_context_save(context);
488 gtk_style_context_set_state(context, stateFlags);
489 gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
490 gtk_style_context_add_class(context, button1StyleClass);
492 gtk_render_background(context, cr,
493 button12BoundRect.Left(), button12BoundRect.Top(),
494 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
495 gtk_render_frame(context, cr,
496 button12BoundRect.Left(), button12BoundRect.Top(),
497 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() );
499 // ----------------- ARROW 1
500 NWCalcArrowRect( button12BoundRect, arrowRect );
501 gtk_render_arrow(context, cr,
502 arrow2Angle,
503 arrowRect.Left(), arrowRect.Top(),
504 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
506 gtk_style_context_restore(context);
508 // ----------------- BUTTON 2
509 if ( has_backward2 )
511 NWConvertVCLStateToGTKState( rScrollbarVal.mnButton1State, &stateFlags, &shadowType );
512 if ( backwardButtonInsensitive )
513 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
515 gtk_style_context_save(context);
516 gtk_style_context_set_state(context, stateFlags);
517 gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
518 gtk_style_context_add_class(context, button2StyleClass);
520 gtk_render_background(context, cr,
521 button21BoundRect.Left(), button21BoundRect.Top(),
522 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
523 gtk_render_frame(context, cr,
524 button21BoundRect.Left(), button21BoundRect.Top(),
525 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() );
527 // ----------------- ARROW 2
528 NWCalcArrowRect( button21BoundRect, arrowRect );
529 gtk_render_arrow(context, cr,
530 arrow1Angle,
531 arrowRect.Left(), arrowRect.Top(),
532 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
534 gtk_style_context_restore(context);
536 if ( has_forward )
538 NWConvertVCLStateToGTKState( rScrollbarVal.mnButton2State, &stateFlags, &shadowType );
539 if ( forwardButtonInsensitive )
540 stateFlags = GTK_STATE_FLAG_INSENSITIVE;
542 gtk_style_context_save(context);
543 gtk_style_context_set_state(context, stateFlags);
544 gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
545 gtk_style_context_add_class(context, button2StyleClass);
547 gtk_render_background(context, cr,
548 button22BoundRect.Left(), button22BoundRect.Top(),
549 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
550 gtk_render_frame(context, cr,
551 button22BoundRect.Left(), button22BoundRect.Top(),
552 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() );
554 // ----------------- ARROW 2
555 NWCalcArrowRect( button22BoundRect, arrowRect );
556 gtk_render_arrow(context, cr,
557 arrow2Angle,
558 arrowRect.Left(), arrowRect.Top(),
559 MIN(arrowRect.GetWidth(), arrowRect.GetHeight()) );
561 gtk_style_context_restore(context);
565 void GtkSalGraphics::PaintOneSpinButton( GtkStyleContext *context,
566 cairo_t *cr,
567 ControlType nType,
568 ControlPart nPart,
569 Rectangle aAreaRect,
570 ControlState nState )
572 (void)nType;
573 Rectangle buttonRect;
574 GtkStateFlags stateFlags;
575 GtkShadowType shadowType;
576 GtkBorder padding, border;
578 NWConvertVCLStateToGTKState( nState, &stateFlags, &shadowType );
579 buttonRect = NWGetSpinButtonRect( nPart, aAreaRect );
581 gtk_style_context_save(context);
582 gtk_style_context_set_state(context, stateFlags);
583 gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
585 gtk_style_context_get_padding(context, GTK_STATE_FLAG_NORMAL, &padding);
586 gtk_style_context_get_border(context, GTK_STATE_FLAG_NORMAL, &border);
588 gtk_render_background(context, cr,
589 buttonRect.Left(), buttonRect.Top(),
590 buttonRect.GetWidth(), buttonRect.GetHeight() );
591 gtk_render_frame(context, cr,
592 buttonRect.Left(), buttonRect.Top(),
593 buttonRect.GetWidth(), buttonRect.GetHeight() );
595 gint iconWidth = (buttonRect.GetWidth() - padding.left - padding.right - border.left - border.right);
596 gint iconHeight = (buttonRect.GetHeight() - padding.top - padding.bottom - border.top - border.bottom);
598 const char* icon = (nPart == PART_BUTTON_UP) ? "list-add-symbolic" : "list-remove-symbolic";
599 GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
601 GtkIconInfo *info = gtk_icon_theme_lookup_icon(pIconTheme, icon, std::min(iconWidth, iconHeight),
602 static_cast<GtkIconLookupFlags>(0));
604 GdkPixbuf *pixbuf = gtk_icon_info_load_symbolic_for_context
605 (info,
606 context,
607 NULL,
608 NULL);
609 iconWidth = gdk_pixbuf_get_width(pixbuf);
610 iconHeight = gdk_pixbuf_get_height(pixbuf);
611 Rectangle arrowRect;
612 arrowRect.SetSize(Size(iconWidth, iconHeight));
613 arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 );
614 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 );
616 gtk_render_icon(context, cr, pixbuf, arrowRect.Left(), arrowRect.Top());
617 g_object_unref(pixbuf);
618 gtk_icon_info_free(info);
620 gtk_style_context_restore(context);
623 void GtkSalGraphics::PaintSpinButton(GtkStyleContext *context,
624 cairo_t *cr,
625 const Rectangle& rControlRectangle,
626 ControlType nType,
627 ControlPart /*nPart*/,
628 const ImplControlValue& rValue )
630 Rectangle areaRect;
631 const SpinbuttonValue *pSpinVal = (rValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue *>(&rValue) : NULL;
632 ControlPart upBtnPart = PART_BUTTON_UP;
633 ControlState upBtnState = ControlState::NONE;
634 ControlPart downBtnPart = PART_BUTTON_DOWN;
635 ControlState downBtnState = ControlState::NONE;
637 if ( pSpinVal )
639 upBtnPart = pSpinVal->mnUpperPart;
640 upBtnState = pSpinVal->mnUpperState;
642 downBtnPart = pSpinVal->mnLowerPart;
643 downBtnState = pSpinVal->mnLowerState;
646 areaRect = rControlRectangle;
648 gtk_render_background(context, cr,
649 0, 0,
650 areaRect.GetWidth(), areaRect.GetHeight() );
651 gtk_render_frame(context, cr,
652 0, 0,
653 areaRect.GetWidth(), areaRect.GetHeight() );
655 // CTRL_SPINBUTTONS pass their area in pSpinVal, not in rControlRectangle
656 if (pSpinVal)
658 areaRect = pSpinVal->maUpperRect;
659 areaRect.Union( pSpinVal->maLowerRect );
662 PaintOneSpinButton(context, cr, nType, upBtnPart, areaRect, upBtnState );
663 PaintOneSpinButton(context, cr, nType, downBtnPart, areaRect, downBtnState );
666 #define ARROW_SIZE 11 * 0.85
667 Rectangle GtkSalGraphics::NWGetComboBoxButtonRect( ControlType nType,
668 ControlPart nPart,
669 Rectangle aAreaRect )
671 (void)nType;
672 (void)nPart;
673 Rectangle aButtonRect;
674 gint nArrowWidth;
675 gint nButtonWidth;
676 GtkBorder padding;
678 gtk_style_context_get_padding( mpButtonStyle, GTK_STATE_FLAG_NORMAL, &padding);
680 nArrowWidth = ARROW_SIZE;
681 nButtonWidth = nArrowWidth + padding.left + padding.right;
682 if( nPart == PART_BUTTON_DOWN )
684 Point aPos = Point(aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, aAreaRect.Top());
685 if (AllSettings::GetLayoutRTL())
686 aPos.X() = aAreaRect.Left();
687 aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) );
688 aButtonRect.SetPos(aPos);
690 else if( nPart == PART_SUB_EDIT )
692 gint adjust_left = padding.left;
693 gint adjust_top = padding.top;
694 gint adjust_right = padding.right;
695 gint adjust_bottom = padding.bottom;
697 aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - (adjust_left + adjust_right),
698 aAreaRect.GetHeight() - (adjust_top + adjust_bottom)) );
699 Point aEditPos = aAreaRect.TopLeft();
700 if (AllSettings::GetLayoutRTL())
701 aEditPos.X() += nButtonWidth;
702 else
703 aEditPos.X() += adjust_left;
704 aEditPos.Y() += adjust_top;
705 aButtonRect.SetPos( aEditPos );
708 return aButtonRect;
711 void GtkSalGraphics::PaintCombobox( GtkStateFlags flags, cairo_t *cr,
712 const Rectangle& rControlRectangle,
713 ControlType nType,
714 ControlPart nPart,
715 const ImplControlValue& /*rValue*/ )
717 Rectangle areaRect;
718 Rectangle buttonRect;
719 Rectangle arrowRect;
721 // Find the overall bounding rect of the buttons's drawing area,
722 // plus its actual draw rect excluding adornment
723 areaRect = rControlRectangle;
725 buttonRect = NWGetComboBoxButtonRect( nType, PART_BUTTON_DOWN, areaRect );
726 if( nPart == PART_BUTTON_DOWN )
727 buttonRect.Left() += 1;
729 Rectangle aEditBoxRect( areaRect );
730 aEditBoxRect.SetSize( Size( areaRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) );
731 if (AllSettings::GetLayoutRTL())
732 aEditBoxRect.SetPos( Point( areaRect.Left() + buttonRect.GetWidth(), areaRect.Top() ) );
734 arrowRect.SetSize( Size( (gint)(ARROW_SIZE),
735 (gint)(ARROW_SIZE) ) );
736 arrowRect.SetPos( Point( buttonRect.Left() + (gint)((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2),
737 buttonRect.Top() + (gint)((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) );
740 if ( nType == CTRL_COMBOBOX )
742 gtk_style_context_save(mpComboboxButtonStyle);
743 gtk_style_context_set_state(mpComboboxButtonStyle, flags);
745 if( nPart == PART_ENTIRE_CONTROL )
747 gtk_style_context_save(mpEntryStyle);
748 gtk_style_context_set_state(mpEntryStyle, flags);
749 if (AllSettings::GetLayoutRTL())
750 gtk_style_context_set_junction_sides(mpEntryStyle, GTK_JUNCTION_LEFT);
751 else
752 gtk_style_context_set_junction_sides(mpEntryStyle, GTK_JUNCTION_RIGHT);
754 gtk_render_background(mpComboboxStyle, cr,
755 0, 0,
756 areaRect.GetWidth(), areaRect.GetHeight());
757 gtk_render_frame(mpComboboxStyle, cr,
758 0, 0,
759 areaRect.GetWidth(), areaRect.GetHeight());
760 gtk_render_background(mpEntryStyle, cr,
761 (aEditBoxRect.Left() - areaRect.Left()),
762 (aEditBoxRect.Top() - areaRect.Top()),
763 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
764 gtk_render_frame(mpEntryStyle, cr,
765 (aEditBoxRect.Left() - areaRect.Left()),
766 (aEditBoxRect.Top() - areaRect.Top()),
767 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() );
769 gtk_style_context_restore(mpEntryStyle);
772 gtk_render_background(mpComboboxButtonStyle, cr,
773 (buttonRect.Left() - areaRect.Left()),
774 (buttonRect.Top() - areaRect.Top()),
775 buttonRect.GetWidth(), buttonRect.GetHeight() );
776 gtk_render_frame(mpComboboxButtonStyle, cr,
777 (buttonRect.Left() - areaRect.Left()),
778 (buttonRect.Top() - areaRect.Top()),
779 buttonRect.GetWidth(), buttonRect.GetHeight() );
781 gtk_render_arrow(mpComboboxStyle, cr,
782 G_PI,
783 (arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
784 arrowRect.GetWidth() );
786 gtk_style_context_restore(mpComboboxButtonStyle);
788 else if (nType == CTRL_LISTBOX)
790 if( nPart == PART_WINDOW )
792 /* render the popup window with the menu style */
793 gtk_render_frame(mpMenuStyle, cr,
794 0, 0,
795 areaRect.GetWidth(), areaRect.GetHeight());
797 else
799 gtk_style_context_save(mpListboxButtonStyle);
800 gtk_style_context_set_state(mpListboxButtonStyle, flags);
802 gtk_render_background(mpListboxStyle, cr,
803 0, 0,
804 areaRect.GetWidth(), areaRect.GetHeight());
805 gtk_render_frame(mpListboxStyle, cr,
806 0, 0,
807 areaRect.GetWidth(), areaRect.GetHeight());
809 gtk_render_background(mpListboxButtonStyle, cr,
810 0, 0,
811 areaRect.GetWidth(), areaRect.GetHeight());
812 gtk_render_frame(mpListboxButtonStyle, cr,
813 0, 0,
814 areaRect.GetWidth(), areaRect.GetHeight());
816 gtk_render_arrow(mpListboxStyle, cr,
817 G_PI,
818 (arrowRect.Left() - areaRect.Left()), (arrowRect.Top() - areaRect.Top()),
819 arrowRect.GetWidth() );
821 gtk_style_context_restore(mpListboxButtonStyle);
826 void GtkSalGraphics::PaintCheckOrRadio(GtkStyleContext *context,
827 cairo_t *cr,
828 const Rectangle& rControlRectangle,
829 ControlType nType)
831 gint indicator_size;
832 gtk_style_context_get_style(mpCheckButtonStyle,
833 "indicator-size", &indicator_size,
834 NULL);
836 gint x = (rControlRectangle.GetWidth() - indicator_size) / 2;
837 gint y = (rControlRectangle.GetHeight() - indicator_size) / 2;
839 if (nType == CTRL_CHECKBOX)
840 gtk_render_check(context, cr, x, y, indicator_size, indicator_size);
841 else if (nType == CTRL_RADIOBUTTON)
842 gtk_render_option(context, cr, x, y, indicator_size, indicator_size);
845 #if GTK_CHECK_VERSION(3,14,0)
846 # define CHECKED GTK_STATE_FLAG_CHECKED
847 #else
848 # define CHECKED GTK_STATE_FLAG_ACTIVE
849 #endif
851 static GtkWidget* gCacheWindow;
852 static GtkWidget* gDumbContainer;
853 static GtkWidget* gSpinBox;
854 static GtkWidget* gEntryBox;
855 static GtkWidget* gComboBox;
856 static GtkWidget* gComboBoxButtonWidget;
857 static GtkWidget* gComboBoxEntryWidget;
858 static GtkWidget* gListBox;
859 static GtkWidget* gListBoxButtonWidget;
860 static GtkWidget* gFrameIn;
861 static GtkWidget* gFrameOut;
862 static GtkWidget* gMenuBarWidget;
863 static GtkWidget* gMenuItemMenuBarWidget;
864 static GtkWidget* gCheckMenuItemWidget;
865 static GtkWidget* gTreeViewWidget;
867 bool GtkSalGraphics::drawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
868 ControlState nState, const ImplControlValue& rValue,
869 const OUString& )
871 GtkStateFlags flags;
872 GtkShadowType shadow;
873 gint renderType = nPart == PART_FOCUS ? RENDER_FOCUS : RENDER_BACKGROUND_AND_FRAME;
874 GtkStyleContext *context = NULL;
875 const gchar *styleClass = NULL;
876 GdkPixbuf *pixbuf = NULL;
878 NWConvertVCLStateToGTKState(nState, &flags, &shadow);
880 switch(nType)
882 case CTRL_SPINBOX:
883 case CTRL_SPINBUTTONS:
884 context = mpSpinStyle;
885 renderType = RENDER_SPINBUTTON;
886 break;
887 case CTRL_EDITBOX:
888 context = mpEntryStyle;
889 break;
890 case CTRL_MULTILINE_EDITBOX:
891 context = mpTextViewStyle;
892 break;
893 case CTRL_COMBOBOX:
894 context = mpComboboxStyle;
895 renderType = RENDER_COMBOBOX;
896 break;
897 case CTRL_LISTBOX:
898 context = mpListboxStyle;
899 renderType = nPart == PART_FOCUS ? RENDER_FOCUS : RENDER_COMBOBOX;
900 break;
901 case CTRL_MENU_POPUP:
903 // map selected menu entries in vcl parlance to gtk prelight
904 if (nPart >= PART_MENU_ITEM && nPart <= PART_MENU_SUBMENU_ARROW && (nState & ControlState::SELECTED))
905 flags = (GtkStateFlags) (flags | GTK_STATE_FLAG_PRELIGHT);
907 switch(nPart)
909 case PART_MENU_ITEM:
910 styleClass = GTK_STYLE_CLASS_MENUITEM;
911 context = mpCheckMenuItemStyle;
912 renderType = RENDER_BACKGROUND_AND_FRAME;
913 break;
914 case PART_MENU_ITEM_CHECK_MARK:
915 styleClass = GTK_STYLE_CLASS_CHECK;
916 context = mpCheckMenuItemStyle;
917 renderType = RENDER_CHECK;
918 nType = CTRL_CHECKBOX;
919 if (nState & ControlState::PRESSED)
920 flags = (GtkStateFlags)(flags | CHECKED);
921 break;
922 case PART_MENU_ITEM_RADIO_MARK:
923 styleClass = GTK_STYLE_CLASS_RADIO;
924 context = mpCheckMenuItemStyle;
925 renderType = RENDER_RADIO;
926 nType = CTRL_RADIOBUTTON;
927 if (nState & ControlState::PRESSED)
928 flags = (GtkStateFlags)(flags | CHECKED);
929 break;
930 case PART_MENU_SEPARATOR:
931 styleClass = GTK_STYLE_CLASS_SEPARATOR;
932 context = mpCheckMenuItemStyle;
933 renderType = RENDER_MENU_SEPERATOR;
934 break;
935 case PART_MENU_SUBMENU_ARROW:
936 styleClass = GTK_STYLE_CLASS_ARROW;
937 context = mpCheckMenuItemStyle;
938 renderType = RENDER_ARROW;
939 break;
940 case PART_ENTIRE_CONTROL:
941 context = mpMenuStyle;
942 renderType = RENDER_BACKGROUND;
943 break;
945 break;
946 case CTRL_TOOLBAR:
947 switch(nPart)
949 case PART_DRAW_BACKGROUND_HORZ:
950 context = mpToolbarStyle;
951 break;
952 case PART_BUTTON:
953 /* For all checkbuttons in the toolbars */
954 flags = (GtkStateFlags)(flags |
955 ( (rValue.getTristateVal() == BUTTONVALUE_ON) ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL));
956 context = mpToolButtonStyle;
957 break;
958 case PART_SEPARATOR_VERT:
959 context = mpToolbarSeperatorStyle;
960 renderType = RENDER_TOOLBAR_SEPERATOR;
961 break;
962 default:
963 return false;
965 break;
966 case CTRL_CHECKBOX:
967 flags = (GtkStateFlags)(flags |
968 ( (rValue.getTristateVal() == BUTTONVALUE_ON) ? CHECKED :
969 (rValue.getTristateVal() == BUTTONVALUE_MIXED) ? GTK_STATE_FLAG_INCONSISTENT :
970 GTK_STATE_FLAG_NORMAL));
971 context = mpCheckButtonStyle;
972 styleClass = GTK_STYLE_CLASS_CHECK;
973 renderType = nPart == PART_FOCUS ? RENDER_FOCUS : RENDER_CHECK;
974 break;
975 case CTRL_RADIOBUTTON:
976 flags = (GtkStateFlags)(flags |
977 ( (rValue.getTristateVal() == BUTTONVALUE_ON) ? CHECKED : GTK_STATE_FLAG_NORMAL));
978 context = mpCheckButtonStyle;
979 styleClass = GTK_STYLE_CLASS_RADIO;
980 renderType = nPart == PART_FOCUS ? RENDER_FOCUS : RENDER_RADIO;
981 break;
982 case CTRL_PUSHBUTTON:
983 context = mpButtonStyle;
984 break;
985 case CTRL_SCROLLBAR:
986 switch(nPart)
988 case PART_DRAW_BACKGROUND_VERT:
989 case PART_DRAW_BACKGROUND_HORZ:
990 context = (nPart == PART_DRAW_BACKGROUND_VERT)
991 ? mpVScrollbarStyle : mpHScrollbarStyle;
992 renderType = RENDER_SCROLLBAR;
993 break;
995 break;
996 case CTRL_LISTNET:
997 case CTRL_TAB_BODY:
998 return true;
999 break;
1000 case CTRL_TAB_PANE:
1001 context = mpNoteBookStyle;
1002 break;
1003 case CTRL_TAB_HEADER:
1004 context = mpNoteBookStyle;
1005 styleClass = GTK_STYLE_CLASS_HEADER;
1006 break;
1007 case CTRL_TAB_ITEM:
1008 context = mpNoteBookStyle;
1009 if (nState & ControlState::SELECTED)
1010 flags = (GtkStateFlags) (flags | GTK_STATE_FLAG_ACTIVE);
1012 break;
1013 case CTRL_WINDOW_BACKGROUND:
1014 context = gtk_widget_get_style_context(mpWindow);
1015 break;
1016 case CTRL_FRAME:
1018 DrawFrameStyle nStyle = static_cast<DrawFrameStyle>(rValue.getNumericVal() & 0x0f);
1019 if (nStyle == DrawFrameStyle::In)
1020 context = mpFrameOutStyle;
1021 else
1022 context = mpFrameInStyle;
1023 break;
1025 case CTRL_MENUBAR:
1026 if (nPart == PART_MENU_ITEM)
1028 context = mpMenuBarItemStyle;
1029 styleClass = GTK_STYLE_CLASS_MENUBAR;
1031 flags = (!(nState & ControlState::ENABLED)) ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
1032 if (nState & ControlState::SELECTED)
1033 flags = (GtkStateFlags) (flags | GTK_STATE_FLAG_PRELIGHT);
1035 else
1037 context = gtk_widget_get_style_context(gMenuBarWidget);
1038 styleClass = GTK_STYLE_CLASS_BACKGROUND;
1040 break;
1041 case CTRL_FIXEDLINE:
1042 context = nPart == PART_SEPARATOR_HORZ ? mpFixedHoriLineStyle : mpFixedVertLineStyle;
1043 renderType = RENDER_SEPERATOR;
1044 break;
1045 case CTRL_LISTNODE:
1047 context = mpTreeHeaderButtonStyle;
1048 ButtonValue aButtonValue = rValue.getTristateVal();
1049 if (aButtonValue == BUTTONVALUE_ON)
1050 flags = (GtkStateFlags) (flags | CHECKED);
1051 renderType = RENDER_EXPANDER;
1052 styleClass = GTK_STYLE_CLASS_EXPANDER;
1053 break;
1055 case CTRL_LISTHEADER:
1056 context = mpTreeHeaderButtonStyle;
1057 if (nPart == PART_ARROW)
1059 const char* icon = (rValue.getNumericVal() & 1) ? "pan-down-symbolic" : "pan-up-symbolic";
1060 GtkIconTheme *pIconTheme = gtk_icon_theme_get_for_screen(gtk_widget_get_screen(mpWindow));
1061 pixbuf = gtk_icon_theme_load_icon(pIconTheme, icon,
1062 std::max(rControlRegion.GetWidth(), rControlRegion.GetHeight()),
1063 static_cast<GtkIconLookupFlags>(0), NULL);
1064 flags = GTK_STATE_FLAG_SELECTED;
1065 renderType = RENDER_ICON;
1066 styleClass = GTK_STYLE_CLASS_ARROW;
1068 break;
1069 case CTRL_PROGRESS:
1070 context = mpProgressBarStyle;
1071 renderType = RENDER_PROGRESS;
1072 styleClass = GTK_STYLE_CLASS_TROUGH;
1073 break;
1074 default:
1075 return false;
1078 cairo_t *cr = getCairoContext();
1079 clipRegion(cr);
1080 cairo_translate(cr, rControlRegion.Left(), rControlRegion.Top());
1082 long nX = 0;
1083 long nY = 0;
1084 long nWidth = rControlRegion.GetWidth();
1085 long nHeight = rControlRegion.GetHeight();
1087 gtk_style_context_save(context);
1088 gtk_style_context_set_state(context, flags);
1089 if (nType == CTRL_TAB_ITEM)
1092 const TabitemValue& rTabitemValue = static_cast<const TabitemValue&>(rValue);
1094 GtkRegionFlags eFlags(GTK_REGION_EVEN);
1095 if (rTabitemValue.isFirst() && rTabitemValue.isLast())
1096 eFlags = GTK_REGION_ONLY;
1097 else if (rTabitemValue.isFirst())
1098 eFlags = GTK_REGION_FIRST;
1099 else if (rTabitemValue.isLast())
1100 eFlags = GTK_REGION_LAST;
1102 gtk_style_context_add_region(mpNoteBookStyle, GTK_STYLE_REGION_TAB, eFlags);
1103 gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOP);
1105 gint initial_gap(0);
1106 gtk_style_context_get_style(mpNoteBookStyle,
1107 "initial-gap", &initial_gap,
1108 NULL);
1110 nX += initial_gap/2;
1111 nWidth -= initial_gap;
1113 if (styleClass)
1115 gtk_style_context_add_class(context, styleClass);
1117 if (nType == CTRL_TAB_HEADER || nType == CTRL_TAB_PANE)
1119 gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME);
1122 switch(renderType)
1124 case RENDER_BACKGROUND:
1125 case RENDER_BACKGROUND_AND_FRAME:
1126 gtk_render_background(context, cr, nX, nY, nWidth, nHeight);
1127 if (renderType == RENDER_BACKGROUND_AND_FRAME)
1129 gtk_render_frame(context, cr, nX, nY, nWidth, nHeight);
1131 break;
1132 case RENDER_CHECK:
1133 case RENDER_RADIO:
1134 PaintCheckOrRadio(context, cr, rControlRegion, nType);
1135 break;
1136 case RENDER_MENU_SEPERATOR:
1137 gtk_render_line(context, cr,
1138 3, rControlRegion.GetHeight() / 2,
1139 rControlRegion.GetWidth() - 3, rControlRegion.GetHeight() / 2);
1140 break;
1141 case RENDER_TOOLBAR_SEPERATOR:
1142 gtk_render_line(context, cr,
1143 rControlRegion.GetWidth() / 2, rControlRegion.GetHeight() * 0.2,
1144 rControlRegion.GetWidth() / 2, rControlRegion.GetHeight() * 0.8 );
1145 break;
1146 case RENDER_SEPERATOR:
1147 if (nPart == PART_SEPARATOR_HORZ)
1148 gtk_render_line(context, cr, 0, nHeight / 2, nWidth - 1, nHeight / 2);
1149 else
1150 gtk_render_line(context, cr, nWidth / 2, 0, nWidth / 2, nHeight - 1);
1151 break;
1152 case RENDER_ARROW:
1153 gtk_render_arrow(context, cr,
1154 G_PI / 2, 0, 0,
1155 MIN(rControlRegion.GetWidth(), 1 + rControlRegion.GetHeight()));
1156 break;
1157 case RENDER_EXPANDER:
1158 gtk_render_expander(context, cr, -2, -2, nWidth+4, nHeight+4);
1159 break;
1160 case RENDER_SCROLLBAR:
1161 PaintScrollbar(context, cr, rControlRegion, nType, nPart, rValue);
1162 break;
1163 case RENDER_SPINBUTTON:
1164 PaintSpinButton(context, cr, rControlRegion, nType, nPart, rValue);
1165 break;
1166 case RENDER_COMBOBOX:
1167 PaintCombobox(flags, cr, rControlRegion, nType, nPart, rValue);
1168 break;
1169 case RENDER_ICON:
1170 gtk_render_icon(context, cr, pixbuf, nX, nY);
1171 g_object_unref(pixbuf);
1172 break;
1173 case RENDER_FOCUS:
1175 if (nType != CTRL_CHECKBOX)
1177 GtkBorder border;
1179 gtk_style_context_get_border(context, flags, &border);
1181 nX += border.left;
1182 nY += border.top;
1183 nWidth -= border.left + border.right;
1184 nHeight -= border.top + border.bottom;
1187 gtk_render_focus(context, cr, nX, nY, nWidth, nHeight);
1189 break;
1191 case RENDER_PROGRESS:
1193 gtk_render_background(context, cr, nX, nY, nWidth, nHeight);
1194 gtk_render_frame(context, cr, nX, nY, nWidth, nHeight);
1195 long nProgressWidth = rValue.getNumericVal();
1196 if (nProgressWidth)
1198 GtkBorder padding;
1199 gtk_style_context_get_padding(context, GTK_STATE_FLAG_NORMAL, &padding);
1201 gtk_style_context_remove_class(context, GTK_STYLE_CLASS_TROUGH);
1202 gtk_style_context_add_class(context, GTK_STYLE_CLASS_PROGRESSBAR);
1203 gtk_style_context_add_class(context, GTK_STYLE_CLASS_PULSE);
1204 nX += padding.left;
1205 nY += padding.top;
1206 nHeight -= (padding.top + padding.bottom);
1207 nProgressWidth -= (padding.left + padding.right);
1208 gtk_render_background(context, cr, nX, nY, nProgressWidth, nHeight);
1209 gtk_render_frame(context, cr, nX, nY, nProgressWidth, nHeight);
1212 break;
1214 default:
1215 break;
1218 gtk_style_context_restore(context);
1219 cairo_surface_flush(cairo_get_target(cr));
1220 cairo_destroy(cr); // unref
1221 mpFrame->damaged(basegfx::B2IBox(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.Right(), rControlRegion.Bottom()));
1223 return true;
1226 Rectangle GetWidgetSize(const Rectangle& rControlRegion, GtkWidget* widget)
1228 GtkRequisition aReq;
1229 gtk_widget_get_preferred_size(widget, NULL, &aReq);
1230 long nHeight = (rControlRegion.GetHeight() > aReq.height) ? rControlRegion.GetHeight() : aReq.height;
1231 return Rectangle(rControlRegion.TopLeft(), Size(rControlRegion.GetWidth(), nHeight));
1234 Rectangle AdjustRectForTextBordersPadding(GtkStyleContext* pStyle, long nContentWidth, long nContentHeight, const Rectangle& rControlRegion)
1236 gtk_style_context_save(pStyle);
1238 GtkBorder border;
1239 gtk_style_context_get_border(pStyle, GTK_STATE_FLAG_NORMAL, &border);
1241 GtkBorder padding;
1242 gtk_style_context_get_padding(pStyle, GTK_STATE_FLAG_NORMAL, &padding);
1244 gint nWidgetHeight = nContentHeight + padding.top + padding.bottom + border.top + border.bottom;
1245 nWidgetHeight = std::max<gint>(nWidgetHeight, rControlRegion.GetHeight());
1247 gint nWidgetWidth = nContentWidth + padding.left + padding.right + border.left + border.right;
1248 nWidgetWidth = std::max<gint>(nWidgetWidth, rControlRegion.GetWidth());
1250 Rectangle aEditRect(rControlRegion.TopLeft(), Size(nWidgetWidth, nWidgetHeight));
1252 gtk_style_context_restore(pStyle);
1254 return aEditRect;
1257 bool GtkSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState,
1258 const ImplControlValue& rValue, const OUString&,
1259 Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion )
1261 /* TODO: all this funcions needs improvements */
1262 Rectangle aEditRect = rControlRegion;
1263 gint indicator_size, indicator_spacing, point;
1265 if(((nType == CTRL_CHECKBOX) || (nType == CTRL_RADIOBUTTON)) &&
1266 nPart == PART_ENTIRE_CONTROL)
1268 rNativeBoundingRegion = rControlRegion;
1270 gtk_style_context_get_style( mpCheckButtonStyle,
1271 "indicator-size", &indicator_size,
1272 "indicator-spacing", &indicator_spacing,
1273 (char *)NULL );
1275 GtkBorder border;
1276 gtk_style_context_get_border(mpCheckButtonStyle, GTK_STATE_FLAG_NORMAL, &border);
1278 GtkBorder padding;
1279 gtk_style_context_get_padding(mpCheckButtonStyle, GTK_STATE_FLAG_NORMAL, &padding);
1282 indicator_size += 2*indicator_spacing + border.left + padding.left + border.right + padding.right;
1283 Rectangle aIndicatorRect( Point( 0,
1284 (rControlRegion.GetHeight()-indicator_size)/2),
1285 Size( indicator_size, indicator_size ) );
1286 rNativeContentRegion = aIndicatorRect;
1288 return true;
1290 else if( nType == CTRL_MENU_POPUP)
1292 if (((nPart == PART_MENU_ITEM_CHECK_MARK) ||
1293 (nPart == PART_MENU_ITEM_RADIO_MARK) ))
1295 indicator_size = 0;
1297 gtk_style_context_get_style( mpCheckMenuItemStyle,
1298 "indicator-size", &indicator_size,
1299 (char *)NULL );
1301 point = MAX(0, rControlRegion.GetHeight() - indicator_size);
1302 aEditRect = Rectangle( Point( 0, point / 2),
1303 Size( indicator_size, indicator_size ) );
1305 else if (nPart == PART_MENU_SEPARATOR)
1307 gint separator_height, separator_width, wide_separators;
1309 gtk_style_context_get_style (mpCheckMenuItemStyle,
1310 "wide-separators", &wide_separators,
1311 "separator-width", &separator_width,
1312 "separator-height", &separator_height,
1313 NULL);
1315 aEditRect = Rectangle( aEditRect.TopLeft(),
1316 Size( aEditRect.GetWidth(), wide_separators ? separator_height : 1 ) );
1318 else if (nPart == PART_MENU_SUBMENU_ARROW)
1320 gfloat arrow_scaling, arrow_size;
1322 arrow_scaling = 0;
1323 gtk_style_context_get_style (mpCheckMenuItemStyle,
1324 "arrow-scaling", &arrow_scaling,
1325 NULL);
1327 arrow_size = 11 * arrow_scaling;
1328 aEditRect = Rectangle( aEditRect.TopLeft(),
1329 Size( arrow_size, arrow_size ) );
1332 else if ( (nType==CTRL_SCROLLBAR) &&
1333 ((nPart==PART_BUTTON_LEFT) || (nPart==PART_BUTTON_RIGHT) ||
1334 (nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) ) )
1336 rNativeBoundingRegion = NWGetScrollButtonRect( nPart, rControlRegion );
1337 rNativeContentRegion = rNativeBoundingRegion;
1339 if (!rNativeContentRegion.GetWidth())
1340 rNativeContentRegion.Right() = rNativeContentRegion.Left() + 1;
1341 if (!rNativeContentRegion.GetHeight())
1342 rNativeContentRegion.Bottom() = rNativeContentRegion.Top() + 1;
1344 return true;
1346 if( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL) )
1348 aEditRect = GetWidgetSize(rControlRegion, gMenuBarWidget);
1350 else if ( (nType==CTRL_SPINBOX) &&
1351 ((nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) ||
1352 (nPart==PART_SUB_EDIT)) )
1354 Rectangle aControlRegion(GetWidgetSize(rControlRegion, gSpinBox));
1355 aEditRect = NWGetSpinButtonRect(nPart, aControlRegion);
1357 else if ( (nType==CTRL_COMBOBOX) &&
1358 ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
1360 aEditRect = NWGetComboBoxButtonRect( nType, nPart, rControlRegion );
1362 else if ( (nType==CTRL_LISTBOX) &&
1363 ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) )
1365 aEditRect = NWGetComboBoxButtonRect( nType, nPart, rControlRegion );
1367 else if (nType == CTRL_EDITBOX && nPart == PART_ENTIRE_CONTROL)
1369 aEditRect = GetWidgetSize(rControlRegion, gEntryBox);
1371 else if (nType == CTRL_LISTBOX && nPart == PART_ENTIRE_CONTROL)
1373 aEditRect = GetWidgetSize(rControlRegion, gListBox);
1375 else if (nType == CTRL_COMBOBOX && nPart == PART_ENTIRE_CONTROL)
1377 aEditRect = GetWidgetSize(rControlRegion, gComboBox);
1379 else if (nType == CTRL_SPINBOX && nPart == PART_ENTIRE_CONTROL)
1381 aEditRect = GetWidgetSize(rControlRegion, gSpinBox);
1383 else if (nType == CTRL_TAB_ITEM && nPart == PART_ENTIRE_CONTROL)
1385 gtk_style_context_save(mpNoteBookStyle);
1387 gtk_style_context_add_region(mpNoteBookStyle, GTK_STYLE_REGION_TAB, GTK_REGION_ONLY);
1388 gtk_style_context_add_class(mpNoteBookStyle, GTK_STYLE_CLASS_TOP);
1390 const TabitemValue& rTabitemValue = static_cast<const TabitemValue&>(rValue);
1391 const Rectangle& rTabitemRect = rTabitemValue.getContentRect();
1393 aEditRect = AdjustRectForTextBordersPadding(mpNoteBookStyle, rTabitemRect.GetWidth(),
1394 rTabitemRect.GetHeight(), rControlRegion);
1396 gtk_style_context_restore(mpNoteBookStyle);
1398 else if (nType == CTRL_FRAME && nPart == PART_BORDER)
1400 aEditRect = rControlRegion;
1401 DrawFrameFlags nStyle = static_cast<DrawFrameFlags>(rValue.getNumericVal() & 0xfff0);
1402 if (nStyle & DrawFrameFlags::NoDraw)
1404 gtk_style_context_save(mpFrameInStyle);
1405 gtk_style_context_add_class(mpFrameInStyle, GTK_STYLE_CLASS_FRAME);
1407 GtkBorder padding;
1408 gtk_style_context_get_padding(mpFrameInStyle, GTK_STATE_FLAG_NORMAL, &padding);
1410 GtkBorder border;
1411 gtk_style_context_get_border(mpFrameInStyle, GTK_STATE_FLAG_NORMAL, &border);
1413 int x1 = aEditRect.Left();
1414 int y1 = aEditRect.Top();
1415 int x2 = aEditRect.Right();
1416 int y2 = aEditRect.Bottom();
1418 rNativeBoundingRegion = aEditRect;
1419 rNativeContentRegion = Rectangle(x1 + (padding.left + border.left),
1420 y1 + (padding.top + border.top),
1421 x2 - (padding.right + border.right),
1422 y2 - (padding.bottom + border.bottom));
1424 gtk_style_context_restore(mpFrameInStyle);
1425 return true;
1427 else
1428 rNativeContentRegion = rControlRegion;
1430 else
1432 return false;
1435 rNativeBoundingRegion = aEditRect;
1436 rNativeContentRegion = rNativeBoundingRegion;
1438 return true;
1440 /************************************************************************
1441 * helper for GtkSalFrame
1442 ************************************************************************/
1443 static inline ::Color getColor( const GdkRGBA& rCol )
1445 return ::Color( (int)(rCol.red * 0xFFFF) >> 8, (int)(rCol.green * 0xFFFF) >> 8, (int)(rCol.blue * 0xFFFF) >> 8 );
1448 static inline ::Color getColorFromColor( const GdkColor& rCol )
1450 return ::Color( rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 );
1453 void GtkSalGraphics::updateSettings( AllSettings& rSettings )
1455 GdkScreen* pScreen = gtk_widget_get_screen( mpWindow );
1456 GtkStyleContext* pStyle = gtk_widget_get_style_context( mpWindow );
1457 GtkSettings* pSettings = gtk_widget_get_settings( mpWindow );
1458 StyleSettings aStyleSet = rSettings.GetStyleSettings();
1459 GdkRGBA color;
1461 // text colors
1462 GdkRGBA text_color;
1463 gtk_style_context_get_color(pStyle, GTK_STATE_FLAG_NORMAL, &text_color);
1464 ::Color aTextColor = getColor( text_color );
1465 aStyleSet.SetDialogTextColor( aTextColor );
1466 aStyleSet.SetButtonTextColor( aTextColor );
1467 aStyleSet.SetRadioCheckTextColor( aTextColor );
1468 aStyleSet.SetGroupTextColor( aTextColor );
1469 aStyleSet.SetLabelTextColor( aTextColor );
1470 aStyleSet.SetInfoTextColor( aTextColor );
1471 aStyleSet.SetWindowTextColor( aTextColor );
1472 aStyleSet.SetFieldTextColor( aTextColor );
1474 // mouse over text colors
1475 gtk_style_context_get_color(pStyle, GTK_STATE_FLAG_PRELIGHT, &text_color);
1476 aTextColor = getColor( text_color );
1477 aStyleSet.SetButtonRolloverTextColor( aTextColor );
1478 aStyleSet.SetFieldRolloverTextColor( aTextColor );
1480 // background colors
1481 GdkRGBA background_color;
1482 gtk_style_context_get_background_color(pStyle, GTK_STATE_FLAG_NORMAL, &background_color);
1484 ::Color aBackColor = getColor( background_color );
1485 aStyleSet.Set3DColors( aBackColor );
1486 aStyleSet.SetFaceColor( aBackColor );
1487 aStyleSet.SetDialogColor( aBackColor );
1488 aStyleSet.SetWorkspaceColor( aBackColor );
1489 aStyleSet.SetCheckedColorSpecialCase( );
1491 // tooltip colors
1493 GtkStyleContext *pCStyle = gtk_style_context_new();
1494 gtk_style_context_set_screen( pCStyle, gtk_window_get_screen( GTK_WINDOW( mpWindow ) ) );
1495 GtkWidgetPath *pCPath = gtk_widget_path_new();
1496 guint pos = gtk_widget_path_append_type(pCPath, GTK_TYPE_WINDOW);
1497 gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_TOOLTIP);
1498 pos = gtk_widget_path_append_type (pCPath, GTK_TYPE_LABEL);
1499 #if GTK_CHECK_VERSION(3,16,0)
1500 gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_LABEL);
1501 #endif
1502 pCStyle = gtk_style_context_new();
1503 gtk_style_context_set_path(pCStyle, pCPath);
1504 gtk_widget_path_free(pCPath);
1506 GdkRGBA tooltip_bg_color, tooltip_fg_color;
1507 gtk_style_context_get_color(pCStyle, GTK_STATE_FLAG_NORMAL, &tooltip_fg_color);
1508 gtk_style_context_get_background_color(pCStyle, GTK_STATE_FLAG_NORMAL, &tooltip_bg_color);
1509 g_object_unref( pCStyle );
1511 aStyleSet.SetHelpColor( getColor( tooltip_bg_color ));
1512 aStyleSet.SetHelpTextColor( getColor( tooltip_fg_color ));
1516 // construct style context for text view
1517 GtkStyleContext *pCStyle = gtk_style_context_new();
1518 gtk_style_context_set_screen( pCStyle, gtk_window_get_screen( GTK_WINDOW( mpWindow ) ) );
1519 GtkWidgetPath *pCPath = gtk_widget_path_new();
1520 gtk_widget_path_append_type( pCPath, GTK_TYPE_TEXT_VIEW );
1521 gtk_widget_path_iter_add_class( pCPath, -1, GTK_STYLE_CLASS_VIEW );
1522 gtk_style_context_set_path( pCStyle, pCPath );
1523 gtk_widget_path_free( pCPath );
1525 // highlighting colors
1526 gtk_style_context_get_background_color(pCStyle, GTK_STATE_FLAG_SELECTED, &text_color);
1527 ::Color aHighlightColor = getColor( text_color );
1528 gtk_style_context_get_color(pCStyle, GTK_STATE_FLAG_SELECTED, &text_color);
1529 ::Color aHighlightTextColor = getColor( text_color );
1530 aStyleSet.SetHighlightColor( aHighlightColor );
1531 aStyleSet.SetHighlightTextColor( aHighlightTextColor );
1533 // field background color
1534 GdkRGBA field_background_color;
1535 gtk_style_context_get_background_color(pCStyle, GTK_STATE_FLAG_NORMAL, &field_background_color);
1536 g_object_unref( pCStyle );
1538 ::Color aBackFieldColor = getColor( field_background_color );
1539 aStyleSet.SetFieldColor( aBackFieldColor );
1540 // This baby is the default page/paper color
1541 aStyleSet.SetWindowColor( aBackFieldColor );
1544 // menu disabled entries handling
1545 aStyleSet.SetSkipDisabledInMenus( true );
1546 aStyleSet.SetAcceleratorsInContextMenus( false );
1548 // menu colors
1549 gtk_style_context_get_background_color( mpMenuStyle, GTK_STATE_FLAG_NORMAL, &background_color );
1550 aBackColor = getColor( background_color );
1551 aStyleSet.SetMenuColor( aBackColor );
1553 // menu bar
1554 gtk_style_context_get_background_color( mpMenuBarStyle, GTK_STATE_FLAG_NORMAL, &background_color );
1555 aBackColor = getColor( background_color );
1556 aStyleSet.SetMenuBarColor( aBackColor );
1557 aStyleSet.SetMenuBarRolloverColor( aBackColor );
1559 gtk_style_context_get_color( mpMenuBarItemStyle, GTK_STATE_FLAG_NORMAL, &text_color );
1560 aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( text_color ) );
1561 aStyleSet.SetMenuBarTextColor( aTextColor );
1562 aStyleSet.SetMenuBarRolloverTextColor( aTextColor );
1564 gtk_style_context_get_color( mpMenuBarItemStyle, GTK_STATE_FLAG_PRELIGHT, &text_color );
1565 aTextColor = aStyleSet.GetPersonaMenuBarTextColor().get_value_or( getColor( text_color ) );
1566 aStyleSet.SetMenuBarHighlightTextColor( aTextColor );
1568 // menu items
1569 gtk_style_context_get_color( mpMenuStyle, GTK_STATE_FLAG_NORMAL, &color );
1570 aTextColor = getColor( color );
1571 aStyleSet.SetMenuTextColor( aTextColor );
1573 // Awful hack for menu separators in the Sonar and similar themes.
1574 // If the menu color is not too dark, and the menu text color is lighter,
1575 // make the "light" color lighter than the menu color and the "shadow"
1576 // color darker than it.
1577 if ( aStyleSet.GetMenuColor().GetLuminance() >= 32 &&
1578 aStyleSet.GetMenuColor().GetLuminance() <= aStyleSet.GetMenuTextColor().GetLuminance() )
1580 ::Color temp = aStyleSet.GetMenuColor();
1581 temp.IncreaseLuminance( 8 );
1582 aStyleSet.SetLightColor( temp );
1583 temp = aStyleSet.GetMenuColor();
1584 temp.DecreaseLuminance( 16 );
1585 aStyleSet.SetShadowColor( temp );
1588 gtk_style_context_get_background_color( mpCheckMenuItemStyle, GTK_STATE_FLAG_PRELIGHT, &background_color );
1589 ::Color aHighlightColor = getColor( background_color );
1590 aStyleSet.SetMenuHighlightColor( aHighlightColor );
1592 gtk_style_context_get_color( mpCheckMenuItemStyle, GTK_STATE_FLAG_PRELIGHT, &color );
1593 ::Color aHighlightTextColor = getColor( color );
1594 aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor );
1596 // hyperlink colors
1597 GdkColor *link_color = NULL;
1598 gtk_style_context_get_style(pStyle,
1599 "link-color", &link_color,
1600 NULL);
1601 if (link_color) {
1602 aStyleSet.SetLinkColor(getColorFromColor(*link_color));
1603 gdk_color_free(link_color);
1606 link_color = NULL;
1607 gtk_style_context_get_style(pStyle,
1608 "visited-link-color", &link_color,
1609 NULL);
1610 if (link_color) {
1611 aStyleSet.SetVisitedLinkColor(getColorFromColor(*link_color));
1612 gdk_color_free(link_color);
1616 GtkStyleContext *pCStyle = gtk_style_context_new();
1617 gtk_style_context_set_screen( pCStyle, gtk_window_get_screen( GTK_WINDOW( mpWindow ) ) );
1618 GtkWidgetPath *pCPath = gtk_widget_path_new();
1619 guint pos = gtk_widget_path_append_type(pCPath, GTK_TYPE_NOTEBOOK);
1620 gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_NOTEBOOK);
1621 gtk_widget_path_iter_add_region(pCPath, pos, GTK_STYLE_REGION_TAB, static_cast<GtkRegionFlags>(GTK_REGION_EVEN | GTK_REGION_FIRST));
1622 pos = gtk_widget_path_append_type (pCPath, GTK_TYPE_LABEL);
1623 #if GTK_CHECK_VERSION(3,16,0)
1624 gtk_widget_path_iter_add_class(pCPath, pos, GTK_STYLE_CLASS_LABEL);
1625 #endif
1626 pCStyle = gtk_style_context_new();
1627 gtk_style_context_set_path(pCStyle, pCPath);
1628 gtk_widget_path_free(pCPath);
1630 gtk_style_context_get_color(pCStyle, GTK_STATE_FLAG_NORMAL, &text_color);
1631 aTextColor = getColor( text_color );
1632 aStyleSet.SetTabTextColor(aTextColor);
1634 // mouse over text colors
1635 gtk_style_context_add_class(pCStyle, "prelight-page");
1636 gtk_style_context_get_color(pCStyle, GTK_STATE_FLAG_PRELIGHT, &text_color);
1637 gtk_style_context_remove_class(pCStyle, "prelight-page");
1638 aTextColor = getColor( text_color );
1639 aStyleSet.SetTabRolloverTextColor(aTextColor);
1641 gtk_style_context_add_class(pCStyle, "active-page");
1642 gtk_style_context_get_color(pCStyle, GTK_STATE_FLAG_ACTIVE, &text_color);
1643 gtk_style_context_remove_class(pCStyle, "active-page");
1644 aTextColor = getColor( text_color );
1645 aStyleSet.SetTabHighlightTextColor(aTextColor);
1647 g_object_unref( pCStyle );
1650 // UI font
1651 const PangoFontDescription* font = gtk_style_context_get_font(pStyle, GTK_STATE_FLAG_NORMAL);
1652 OString aFamily = pango_font_description_get_family( font );
1653 int nPangoHeight = pango_font_description_get_size( font );
1654 PangoStyle eStyle = pango_font_description_get_style( font );
1655 PangoWeight eWeight = pango_font_description_get_weight( font );
1656 PangoStretch eStretch = pango_font_description_get_stretch( font );
1658 psp::FastPrintFontInfo aInfo;
1659 // set family name
1660 aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 );
1661 // set italic
1662 switch( eStyle )
1664 case PANGO_STYLE_NORMAL: aInfo.m_eItalic = ITALIC_NONE;break;
1665 case PANGO_STYLE_ITALIC: aInfo.m_eItalic = ITALIC_NORMAL;break;
1666 case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = ITALIC_OBLIQUE;break;
1668 // set weight
1669 if( eWeight <= PANGO_WEIGHT_ULTRALIGHT )
1670 aInfo.m_eWeight = WEIGHT_ULTRALIGHT;
1671 else if( eWeight <= PANGO_WEIGHT_LIGHT )
1672 aInfo.m_eWeight = WEIGHT_LIGHT;
1673 else if( eWeight <= PANGO_WEIGHT_NORMAL )
1674 aInfo.m_eWeight = WEIGHT_NORMAL;
1675 else if( eWeight <= PANGO_WEIGHT_BOLD )
1676 aInfo.m_eWeight = WEIGHT_BOLD;
1677 else
1678 aInfo.m_eWeight = WEIGHT_ULTRABOLD;
1679 // set width
1680 switch( eStretch )
1682 case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = WIDTH_ULTRA_CONDENSED;break;
1683 case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = WIDTH_EXTRA_CONDENSED;break;
1684 case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = WIDTH_CONDENSED;break;
1685 case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = WIDTH_SEMI_CONDENSED;break;
1686 case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = WIDTH_NORMAL;break;
1687 case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = WIDTH_SEMI_EXPANDED;break;
1688 case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = WIDTH_EXPANDED;break;
1689 case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = WIDTH_EXTRA_EXPANDED;break;
1690 case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = WIDTH_ULTRA_EXPANDED;break;
1693 #if OSL_DEBUG_LEVEL > 1
1694 fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() );
1695 #endif
1697 // match font to e.g. resolve "Sans"
1698 psp::PrintFontManager::get().matchFont( aInfo, rSettings.GetUILanguageTag().getLocale() );
1700 #if OSL_DEBUG_LEVEL > 1
1701 fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
1702 aInfo.m_nID != 0 ? "succeeded" : "failed",
1703 OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1704 #endif
1706 int nPointHeight = 0;
1707 /*sal_Int32 nDispDPIY = GetDisplay()->GetResolution().B();
1708 static gboolean(*pAbso)(const PangoFontDescription*) =
1709 (gboolean(*)(const PangoFontDescription*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "pango_font_description_get_size_is_absolute" );
1711 if( pAbso && pAbso( font ) )
1712 nPointHeight = (nPangoHeight * 72 + nDispDPIY*PANGO_SCALE/2) / (nDispDPIY * PANGO_SCALE);
1713 else*/
1714 nPointHeight = nPangoHeight/PANGO_SCALE;
1716 vcl::Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
1717 if( aInfo.m_eWeight != WEIGHT_DONTKNOW )
1718 aFont.SetWeight( aInfo.m_eWeight );
1719 if( aInfo.m_eWidth != WIDTH_DONTKNOW )
1720 aFont.SetWidthType( aInfo.m_eWidth );
1721 if( aInfo.m_eItalic != ITALIC_DONTKNOW )
1722 aFont.SetItalic( aInfo.m_eItalic );
1723 if( aInfo.m_ePitch != PITCH_DONTKNOW )
1724 aFont.SetPitch( aInfo.m_ePitch );
1726 aStyleSet.SetAppFont( aFont );
1727 aStyleSet.SetHelpFont( aFont );
1728 aStyleSet.SetMenuFont( aFont );
1729 aStyleSet.SetToolFont( aFont );
1730 aStyleSet.SetLabelFont( aFont );
1731 aStyleSet.SetInfoFont( aFont );
1732 aStyleSet.SetRadioCheckFont( aFont );
1733 aStyleSet.SetPushButtonFont( aFont );
1734 aStyleSet.SetFieldFont( aFont );
1735 aStyleSet.SetIconFont( aFont );
1736 aStyleSet.SetGroupFont( aFont );
1738 aFont.SetWeight( WEIGHT_BOLD );
1739 aStyleSet.SetTabFont( aFont ); //pull from notebook style + GTK_STYLE_REGION_TAB ?
1740 aStyleSet.SetTitleFont( aFont );
1741 aStyleSet.SetFloatTitleFont( aFont );
1742 // get cursor blink time
1743 gboolean blink = false;
1745 g_object_get( pSettings, "gtk-cursor-blink", &blink, (char *)NULL );
1746 if( blink )
1748 gint blink_time = static_cast<gint>(STYLE_CURSOR_NOBLINKTIME);
1749 g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, (char *)NULL );
1750 // set the blink_time if there is a setting and it is reasonable
1751 // else leave the default value
1752 if( blink_time > 100 && blink_time != gint(STYLE_CURSOR_NOBLINKTIME) )
1753 aStyleSet.SetCursorBlinkTime( blink_time/2 );
1755 else
1756 aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME );
1758 MouseSettings aMouseSettings = rSettings.GetMouseSettings();
1759 int iDoubleClickTime, iDoubleClickDistance, iDragThreshold;
1760 static const int MENU_POPUP_DELAY = 225;
1761 g_object_get( pSettings,
1762 "gtk-double-click-time", &iDoubleClickTime,
1763 "gtk-double-click-distance", &iDoubleClickDistance,
1764 "gtk-dnd-drag-threshold", &iDragThreshold,
1765 (char *)NULL );
1766 aMouseSettings.SetDoubleClickTime( iDoubleClickTime );
1767 aMouseSettings.SetDoubleClickWidth( iDoubleClickDistance );
1768 aMouseSettings.SetDoubleClickHeight( iDoubleClickDistance );
1769 aMouseSettings.SetStartDragWidth( iDragThreshold );
1770 aMouseSettings.SetStartDragHeight( iDragThreshold );
1771 aMouseSettings.SetMenuDelay( MENU_POPUP_DELAY );
1772 rSettings.SetMouseSettings( aMouseSettings );
1774 gboolean primarybuttonwarps = false;
1775 g_object_get( pSettings,
1776 "gtk-primary-button-warps-slider", &primarybuttonwarps,
1777 (char *)NULL );
1778 aStyleSet.SetPreferredUseImagesInMenus(false);
1779 aStyleSet.SetPrimaryButtonWarpsSlider(primarybuttonwarps);
1781 // set scrollbar settings
1782 gint slider_width = 14;
1783 gint trough_border = 1;
1784 gint min_slider_length = 21;
1786 // Grab some button style attributes
1787 gtk_style_context_get_style( mpVScrollbarStyle,
1788 "slider-width", &slider_width,
1789 "trough-border", &trough_border,
1790 "min-slider-length", &min_slider_length,
1791 (char *)NULL );
1792 gint magic = trough_border ? 1 : 0;
1793 aStyleSet.SetScrollBarSize( slider_width + 2*trough_border );
1794 aStyleSet.SetMinThumbSize( min_slider_length - magic );
1796 // preferred icon style
1797 gchar* pIconThemeName = NULL;
1798 g_object_get( pSettings, "gtk-icon-theme-name", &pIconThemeName, (char *)NULL );
1799 aStyleSet.SetPreferredIconTheme( OUString::createFromAscii( pIconThemeName ) );
1800 g_free( pIconThemeName );
1802 aStyleSet.SetToolbarIconSize( ToolbarIconSize::Large );
1804 const cairo_font_options_t* pNewOptions = gdk_screen_get_font_options(pScreen);
1805 aStyleSet.SetCairoFontOptions( pNewOptions );
1806 // finally update the collected settings
1807 rSettings.SetStyleSettings( aStyleSet );
1808 gchar* pThemeName = NULL;
1809 g_object_get( pSettings, "gtk-theme-name", &pThemeName, (char *)NULL );
1810 #if OSL_DEBUG_LEVEL > 1
1811 fprintf( stderr, "Theme name is \"%s\"\n", pThemeName );
1812 #endif
1816 bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
1818 switch(nType)
1820 case CTRL_TOOLTIP:
1821 return false; //shaped, punt that problem for now
1823 case CTRL_PUSHBUTTON:
1824 case CTRL_RADIOBUTTON:
1825 case CTRL_CHECKBOX:
1826 case CTRL_PROGRESS:
1827 case CTRL_LISTNODE:
1828 case CTRL_LISTNET:
1829 if (nPart==PART_ENTIRE_CONTROL || nPart == PART_FOCUS)
1830 return true;
1831 break;
1833 case CTRL_SCROLLBAR:
1834 if(nPart==PART_DRAW_BACKGROUND_HORZ || nPart==PART_DRAW_BACKGROUND_VERT ||
1835 nPart==PART_ENTIRE_CONTROL || nPart==HAS_THREE_BUTTONS)
1836 return true;
1837 break;
1839 case CTRL_EDITBOX:
1840 case CTRL_MULTILINE_EDITBOX:
1841 if (nPart==PART_ENTIRE_CONTROL || nPart==HAS_BACKGROUND_TEXTURE)
1842 return true;
1843 break;
1845 case CTRL_COMBOBOX:
1846 if (nPart==PART_ENTIRE_CONTROL || nPart==HAS_BACKGROUND_TEXTURE || nPart == PART_ALL_BUTTONS)
1847 return true;
1848 break;
1850 case CTRL_SPINBOX:
1851 if (nPart==PART_ENTIRE_CONTROL || nPart==HAS_BACKGROUND_TEXTURE || nPart == PART_ALL_BUTTONS || nPart == PART_BUTTON_UP || nPart == PART_BUTTON_DOWN)
1852 return true;
1853 break;
1855 case CTRL_SPINBUTTONS:
1856 if (nPart==PART_ENTIRE_CONTROL || nPart==PART_ALL_BUTTONS)
1857 return true;
1858 break;
1860 case CTRL_FRAME:
1861 case CTRL_WINDOW_BACKGROUND:
1862 return true;
1864 case CTRL_TAB_ITEM:
1865 case CTRL_TAB_HEADER:
1866 case CTRL_TAB_PANE:
1867 case CTRL_TAB_BODY:
1868 if(nPart==PART_ENTIRE_CONTROL || nPart==PART_TABS_DRAW_RTL)
1869 return true;
1870 break;
1872 case CTRL_LISTBOX:
1873 if (nPart==PART_ENTIRE_CONTROL || nPart==PART_WINDOW || nPart==HAS_BACKGROUND_TEXTURE || nPart == PART_FOCUS)
1874 return true;
1875 break;
1877 case CTRL_TOOLBAR:
1878 if( nPart==PART_ENTIRE_CONTROL
1879 // || nPart==PART_DRAW_BACKGROUND_HORZ
1880 // || nPart==PART_DRAW_BACKGROUND_VERT
1881 // || nPart==PART_THUMB_HORZ
1882 // || nPart==PART_THUMB_VERT
1883 || nPart==PART_BUTTON
1884 // || nPart==PART_SEPARATOR_HORZ
1885 || nPart==PART_SEPARATOR_VERT
1887 return true;
1888 break;
1890 case CTRL_MENUBAR:
1891 if (nPart==PART_ENTIRE_CONTROL || nPart==PART_MENU_ITEM)
1892 return true;
1893 break;
1895 case CTRL_MENU_POPUP:
1896 if (nPart==PART_ENTIRE_CONTROL
1897 || nPart==PART_MENU_ITEM
1898 || nPart==PART_MENU_ITEM_CHECK_MARK
1899 || nPart==PART_MENU_ITEM_RADIO_MARK
1900 || nPart==PART_MENU_SEPARATOR
1901 || nPart==PART_MENU_SUBMENU_ARROW
1903 return true;
1904 break;
1906 // case CTRL_SLIDER:
1907 // if(nPart == PART_TRACK_HORZ_AREA || nPart == PART_TRACK_VERT_AREA)
1908 // return true;
1909 // break;
1911 case CTRL_FIXEDLINE:
1912 if (nPart == PART_SEPARATOR_VERT || nPart == PART_SEPARATOR_HORZ)
1913 return true;
1914 break;
1916 case CTRL_LISTHEADER:
1917 if (nPart == PART_BUTTON || nPart == PART_ARROW)
1918 return true;
1919 break;
1922 SAL_INFO("vcl.gtk", "Unhandled is native supported for Type:" << nType << ", Part" << nPart);
1924 return false;
1927 bool GtkSalGraphics::SupportsCairo() const
1929 return true;
1932 cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
1934 return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(rSurface));
1937 cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int x, int y, int width, int height) const
1939 return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(this, x, y, width, height));
1942 void GtkSalGraphics::WidgetQueueDraw() const
1944 //request gtk to sync the entire contents
1945 gtk_widget_queue_draw(mpWindow);
1948 namespace {
1950 void getStyleContext(GtkStyleContext** style, GtkWidget* widget)
1952 gtk_container_add(GTK_CONTAINER(gDumbContainer), widget);
1953 *style = gtk_widget_get_style_context(widget);
1954 g_object_ref(*style);
1959 void GtkData::initNWF()
1961 ImplSVData* pSVData = ImplGetSVData();
1962 pSVData->maNWFData.mbFlatMenu = true;
1963 pSVData->maNWFData.mbCheckBoxNeedsErase = true;
1964 pSVData->maNWFData.mbCanDrawWidgetAnySize = true;
1965 pSVData->maNWFData.mbDDListBoxNoTextArea = true;
1966 pSVData->maNWFData.mbNoFocusRects = true;
1967 pSVData->maNWFData.mbNoFocusRectsForFlatButtons = true;
1970 void GtkData::deInitNWF()
1972 if (gCacheWindow)
1973 gtk_widget_destroy(gCacheWindow);
1976 static void get_combo_box_entry_inner_widgets(GtkWidget *widget, gpointer)
1978 if (GTK_IS_TOGGLE_BUTTON(widget))
1980 gComboBoxButtonWidget = widget;
1982 else if (GTK_IS_ENTRY(widget))
1984 gComboBoxEntryWidget = widget;
1988 void get_combo_box_inner_button(GtkWidget *widget, gpointer)
1990 if (GTK_IS_TOGGLE_BUTTON(widget))
1992 gListBoxButtonWidget = widget;
1996 GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
1997 : SvpSalGraphics(),
1998 mpFrame( pFrame ),
1999 mpWindow( pWindow )
2001 m_xTextRenderImpl.reset(new GtkCairoTextRender(*this));
2003 if(style_loaded)
2004 return;
2006 style_loaded = true;
2007 gtk_init(NULL, NULL);
2008 /* Load the GtkStyleContexts, it might be a bit slow, but usually,
2009 * gtk apps create a lot of widgets at startup, so, it shouldn't be
2010 * too slow */
2011 gCacheWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2012 gDumbContainer = gtk_fixed_new();
2013 gtk_container_add(GTK_CONTAINER(gCacheWindow), gDumbContainer);
2014 gtk_widget_realize(gDumbContainer);
2015 gtk_widget_realize(gCacheWindow);
2017 gEntryBox = gtk_entry_new();
2018 getStyleContext(&mpEntryStyle, gEntryBox);
2019 getStyleContext(&mpTextViewStyle, gtk_text_view_new());
2020 getStyleContext(&mpButtonStyle, gtk_button_new());
2022 GtkWidget* pToolbar = gtk_toolbar_new();
2023 mpToolbarStyle = gtk_widget_get_style_context(pToolbar);
2024 gtk_style_context_add_class(mpToolbarStyle, GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
2025 gtk_style_context_add_class(mpToolbarStyle, GTK_STYLE_CLASS_TOOLBAR);
2027 GtkToolItem *item = gtk_separator_tool_item_new();
2028 gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
2029 mpToolbarSeperatorStyle = gtk_widget_get_style_context(GTK_WIDGET(item));
2031 GtkWidget *pButton = gtk_button_new();
2032 item = gtk_tool_button_new(pButton, NULL);
2033 gtk_toolbar_insert(GTK_TOOLBAR(pToolbar), item, -1);
2034 mpToolButtonStyle = gtk_widget_get_style_context(GTK_WIDGET(pButton));
2036 getStyleContext(&mpVScrollbarStyle, gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL));
2037 gtk_style_context_add_class(mpVScrollbarStyle, GTK_STYLE_CLASS_SCROLLBAR);
2038 getStyleContext(&mpHScrollbarStyle, gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL));
2039 gtk_style_context_add_class(mpHScrollbarStyle, GTK_STYLE_CLASS_SCROLLBAR);
2041 getStyleContext(&mpCheckButtonStyle, gtk_check_button_new());
2043 /* Menu bar */
2044 gMenuBarWidget = gtk_menu_bar_new();
2045 gMenuItemMenuBarWidget = gtk_menu_item_new_with_label( "b" );
2046 gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget), gMenuItemMenuBarWidget);
2047 getStyleContext(&mpMenuBarStyle, gMenuBarWidget);
2048 mpMenuBarItemStyle = gtk_widget_get_style_context(gMenuItemMenuBarWidget);
2050 /* Menu */
2051 GtkWidget *menu = gtk_menu_new();
2052 mpMenuStyle = gtk_widget_get_style_context(menu);
2053 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuItemMenuBarWidget), menu);
2055 /* Menu Items */
2056 gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
2057 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gCheckMenuItemWidget);
2058 mpCheckMenuItemStyle = gtk_widget_get_style_context(gCheckMenuItemWidget);
2060 /* Spinbutton */
2061 gSpinBox = gtk_spin_button_new(NULL, 0, 0);
2062 getStyleContext(&mpSpinStyle, gSpinBox);
2064 /* NoteBook */
2065 getStyleContext(&mpNoteBookStyle, gtk_notebook_new());
2067 /* Combobox */
2068 gComboBox = gtk_combo_box_text_new_with_entry();
2069 getStyleContext(&mpComboboxStyle, gComboBox);
2070 /* Get ComboBox Entry and Button */
2071 gtk_container_forall(GTK_CONTAINER(gComboBox),
2072 get_combo_box_entry_inner_widgets,
2073 NULL);
2074 mpComboboxButtonStyle = gtk_widget_get_style_context(gComboBoxButtonWidget);
2076 /* Listbox */
2077 gListBox = gtk_combo_box_text_new();
2078 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(gListBox), "sample");
2079 getStyleContext(&mpListboxStyle, gListBox);
2080 /* Get ComboBox Button */
2081 gtk_container_forall(GTK_CONTAINER(gListBox),
2082 get_combo_box_inner_button,
2083 NULL);
2084 mpListboxButtonStyle = gtk_widget_get_style_context(gListBoxButtonWidget);
2086 /* Frames */
2087 gFrameIn = gtk_frame_new(NULL);
2088 gtk_frame_set_shadow_type(GTK_FRAME(gFrameIn), GTK_SHADOW_IN);
2090 gFrameOut = gtk_frame_new(NULL);
2091 gtk_frame_set_shadow_type(GTK_FRAME(gFrameOut), GTK_SHADOW_OUT);
2093 getStyleContext(&mpFrameInStyle, gFrameIn);
2094 getStyleContext(&mpFrameOutStyle, gFrameOut);
2095 getStyleContext(&mpFixedHoriLineStyle, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL));
2096 getStyleContext(&mpFixedVertLineStyle, gtk_separator_new(GTK_ORIENTATION_VERTICAL));
2099 /* Tree List */
2100 gTreeViewWidget = gtk_tree_view_new();
2101 gtk_container_add(GTK_CONTAINER(gDumbContainer), gTreeViewWidget);
2103 GtkTreeViewColumn* firstTreeViewColumn = gtk_tree_view_column_new();
2104 gtk_tree_view_column_set_title(firstTreeViewColumn, "M");
2105 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn);
2107 GtkTreeViewColumn* middleTreeViewColumn = gtk_tree_view_column_new();
2108 gtk_tree_view_column_set_title(middleTreeViewColumn, "M");
2109 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
2110 gtk_tree_view_set_expander_column(GTK_TREE_VIEW(gTreeViewWidget), middleTreeViewColumn);
2112 GtkTreeViewColumn* lastTreeViewColumn = gtk_tree_view_column_new();
2113 gtk_tree_view_column_set_title(lastTreeViewColumn, "M");
2114 gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn);
2116 /* Use the middle column's header for our button */
2117 GtkWidget* pTreeHeaderCellWidget = gtk_tree_view_column_get_button(middleTreeViewColumn);
2118 mpTreeHeaderButtonStyle = gtk_widget_get_style_context(pTreeHeaderCellWidget);
2120 /* Progress Bar */
2121 getStyleContext(&mpProgressBarStyle, gtk_progress_bar_new());
2123 gtk_widget_show_all(gDumbContainer);
2126 cairo_t* GtkSalGraphics::getCairoContext() const
2128 return mpFrame->getCairoContext();
2131 void GtkSalGraphics::GetResolution(sal_Int32& rDPIX, sal_Int32& rDPIY)
2133 GdkScreen* pScreen = gtk_widget_get_screen(mpWindow);
2134 double fResolution = -1.0;
2135 g_object_get(pScreen, "resolution", &fResolution, nullptr);
2137 int nScaleFactor = 1;
2139 #if GTK_CHECK_VERSION(3, 10, 0)
2140 nScaleFactor = gdk_window_get_scale_factor(widget_get_window(mpWindow));
2141 #endif
2143 if (fResolution > 0.0)
2144 rDPIX = rDPIY = sal_Int32(fResolution * nScaleFactor);
2145 else
2146 rDPIX = rDPIY = 96;
2149 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */