1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/settings.cpp
4 // Author: Robert Roebling
5 // Modified by: Mart Raudsepp (GetMetric)
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
14 #include "wx/settings.h"
17 #include "wx/cmndata.h"
20 #include "wx/fontutil.h"
21 #include "wx/toplevel.h"
23 // Using gtk_list_new, which is deprecated since GTK2
24 // Using gtk_object_sink, which is deprecated since GTK+-2.9.0
25 #ifdef GTK_DISABLE_DEPRECATED
26 #undef GTK_DISABLE_DEPRECATED
31 #include <gdk/gdkprivate.h>
34 #include <X11/Xatom.h>
36 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 struct wxSystemObjects
44 wxColour m_colBtnFace
,
51 m_colMenuItemHighlight
,
58 static wxSystemObjects gs_objects
;
60 // ----------------------------------------------------------------------------
61 // wxSystemSettings implementation
62 // ----------------------------------------------------------------------------
64 // kind of widget to use in GetColourFromGTKWidget
80 // wxSystemSettings::GetColour() helper: get the colours from a GTK+
81 // widget style, return true if we did get them, false to use defaults
82 static bool GetColourFromGTKWidget(int& red
, int& green
, int& blue
,
83 wxGtkWidgetType type
= wxGTK_BUTTON
,
84 GtkStateType state
= GTK_STATE_NORMAL
,
85 wxGtkColourType colour
= wxGTK_BG
)
91 wxFAIL_MSG( _T("unexpected GTK widget type") );
95 widget
= gtk_button_new();
99 widget
= gtk_list_new();
103 widget
= gtk_menu_item_new();
106 GtkStyle
*def
= gtk_rc_get_style( widget
);
108 def
= gtk_widget_get_default_style();
117 wxFAIL_MSG( _T("unexpected GTK colour type") );
133 red
= col
[state
].red
;
134 green
= col
[state
].green
;
135 blue
= col
[state
].blue
;
144 gtk_widget_destroy( widget
);
149 static void GetTooltipColors()
151 GtkTooltips
* tooltips
= gtk_tooltips_new();
152 gtk_tooltips_force_window(tooltips
);
153 gtk_widget_ensure_style(tooltips
->tip_window
);
154 GdkColor c
= tooltips
->tip_window
->style
->bg
[GTK_STATE_NORMAL
];
155 gs_objects
.m_colTooltip
= wxColor(c
.red
>> SHIFT
, c
.green
>> SHIFT
, c
.blue
>> SHIFT
);
156 c
= tooltips
->tip_window
->style
->fg
[GTK_STATE_NORMAL
];
157 gs_objects
.m_colTooltipText
= wxColor(c
.red
>> SHIFT
, c
.green
>> SHIFT
, c
.blue
>> SHIFT
);
158 gtk_object_sink(wx_reinterpret_cast(GtkObject
*, tooltips
));
161 wxColour
wxSystemSettingsNative::GetColour( wxSystemColour index
)
165 case wxSYS_COLOUR_SCROLLBAR
:
166 case wxSYS_COLOUR_BACKGROUND
:
167 case wxSYS_COLOUR_INACTIVECAPTION
:
168 case wxSYS_COLOUR_MENU
:
169 case wxSYS_COLOUR_WINDOWFRAME
:
170 case wxSYS_COLOUR_ACTIVEBORDER
:
171 case wxSYS_COLOUR_INACTIVEBORDER
:
172 case wxSYS_COLOUR_BTNFACE
:
173 case wxSYS_COLOUR_MENUBAR
:
174 case wxSYS_COLOUR_3DLIGHT
:
175 if (!gs_objects
.m_colBtnFace
.Ok())
177 int red
, green
, blue
;
178 if ( !GetColourFromGTKWidget(red
, green
, blue
) )
185 gs_objects
.m_colBtnFace
= wxColour( red
>> SHIFT
,
189 return gs_objects
.m_colBtnFace
;
191 case wxSYS_COLOUR_WINDOW
:
194 case wxSYS_COLOUR_3DDKSHADOW
:
197 case wxSYS_COLOUR_GRAYTEXT
:
198 case wxSYS_COLOUR_BTNSHADOW
:
199 //case wxSYS_COLOUR_3DSHADOW:
200 if (!gs_objects
.m_colBtnShadow
.Ok())
202 wxColour
faceColour(GetColour(wxSYS_COLOUR_3DFACE
));
203 gs_objects
.m_colBtnShadow
=
204 wxColour((unsigned char) (faceColour
.Red() * 0.666),
205 (unsigned char) (faceColour
.Green() * 0.666),
206 (unsigned char) (faceColour
.Blue() * 0.666));
209 return gs_objects
.m_colBtnShadow
;
211 case wxSYS_COLOUR_3DHIGHLIGHT
:
212 //case wxSYS_COLOUR_BTNHIGHLIGHT:
215 case wxSYS_COLOUR_HIGHLIGHT
:
216 if (!gs_objects
.m_colHighlight
.Ok())
218 int red
, green
, blue
;
219 if ( !GetColourFromGTKWidget(red
, green
, blue
,
221 GTK_STATE_SELECTED
) )
228 gs_objects
.m_colHighlight
= wxColour( red
>> SHIFT
,
232 return gs_objects
.m_colHighlight
;
234 case wxSYS_COLOUR_LISTBOX
:
235 if (!gs_objects
.m_colListBox
.Ok())
237 int red
, green
, blue
;
238 if ( GetColourFromGTKWidget(red
, green
, blue
,
243 gs_objects
.m_colListBox
= wxColour( red
>> SHIFT
,
249 gs_objects
.m_colListBox
= wxColour(*wxWHITE
);
252 return gs_objects
.m_colListBox
;
254 case wxSYS_COLOUR_MENUTEXT
:
255 case wxSYS_COLOUR_WINDOWTEXT
:
256 case wxSYS_COLOUR_CAPTIONTEXT
:
257 case wxSYS_COLOUR_INACTIVECAPTIONTEXT
:
258 case wxSYS_COLOUR_BTNTEXT
:
259 if (!gs_objects
.m_colBtnText
.Ok())
261 int red
, green
, blue
;
262 if ( !GetColourFromGTKWidget(red
, green
, blue
,
272 gs_objects
.m_colBtnText
= wxColour( red
>> SHIFT
,
276 return gs_objects
.m_colBtnText
;
278 case wxSYS_COLOUR_INFOBK
:
279 if (!gs_objects
.m_colTooltip
.Ok()) {
282 return gs_objects
.m_colTooltip
;
284 case wxSYS_COLOUR_INFOTEXT
:
285 if (!gs_objects
.m_colTooltipText
.Ok()) {
288 return gs_objects
.m_colTooltipText
;
290 case wxSYS_COLOUR_HIGHLIGHTTEXT
:
291 if (!gs_objects
.m_colHighlightText
.Ok())
293 wxColour hclr
= GetColour(wxSYS_COLOUR_HIGHLIGHT
);
294 if (hclr
.Red() > 200 && hclr
.Green() > 200 && hclr
.Blue() > 200)
295 gs_objects
.m_colHighlightText
= wxColour(*wxBLACK
);
297 gs_objects
.m_colHighlightText
= wxColour(*wxWHITE
);
299 return gs_objects
.m_colHighlightText
;
301 case wxSYS_COLOUR_APPWORKSPACE
:
302 return *wxWHITE
; // ?
304 case wxSYS_COLOUR_ACTIVECAPTION
:
305 case wxSYS_COLOUR_MENUHILIGHT
:
306 if (!gs_objects
.m_colMenuItemHighlight
.Ok())
308 int red
, green
, blue
;
309 if ( !GetColourFromGTKWidget(red
, green
, blue
,
319 gs_objects
.m_colMenuItemHighlight
= wxColour( red
>> SHIFT
,
323 return gs_objects
.m_colMenuItemHighlight
;
325 case wxSYS_COLOUR_HOTLIGHT
:
326 case wxSYS_COLOUR_GRADIENTACTIVECAPTION
:
327 case wxSYS_COLOUR_GRADIENTINACTIVECAPTION
:
331 case wxSYS_COLOUR_MAX
:
333 wxFAIL_MSG( _T("unknown system colour index") );
339 wxFont
wxSystemSettingsNative::GetFont( wxSystemFont index
)
343 case wxSYS_OEM_FIXED_FONT
:
344 case wxSYS_ANSI_FIXED_FONT
:
345 case wxSYS_SYSTEM_FIXED_FONT
:
347 return *wxNORMAL_FONT
;
349 case wxSYS_ANSI_VAR_FONT
:
350 case wxSYS_SYSTEM_FONT
:
351 case wxSYS_DEVICE_DEFAULT_FONT
:
352 case wxSYS_DEFAULT_GUI_FONT
:
354 if (!gs_objects
.m_fontSystem
.Ok())
356 GtkWidget
*widget
= gtk_button_new();
357 GtkStyle
*def
= gtk_rc_get_style( widget
);
358 if ( !def
|| !def
->font_desc
)
359 def
= gtk_widget_get_default_style();
360 if ( def
&& def
->font_desc
)
362 wxNativeFontInfo info
;
364 pango_font_description_copy(def
->font_desc
);
365 gs_objects
.m_fontSystem
= wxFont(info
);
369 GtkSettings
*settings
= gtk_settings_get_default();
370 gchar
*font_name
= NULL
;
371 g_object_get ( settings
,
376 gs_objects
.m_fontSystem
= wxFont( 12, wxSWISS
, wxNORMAL
, wxNORMAL
);
378 gs_objects
.m_fontSystem
= wxFont(wxString::FromAscii(font_name
));
381 gtk_widget_destroy( widget
);
383 return gs_objects
.m_fontSystem
;
391 int wxSystemSettingsNative::GetMetric( wxSystemMetric index
, wxWindow
* win
)
393 bool success
= false;
396 GdkWindow
*window
= NULL
;
397 if(win
&& GTK_WIDGET_REALIZED(win
->GetHandle()))
398 window
= win
->GetHandle()->window
;
406 case wxSYS_FRAMESIZE_X
:
407 case wxSYS_FRAMESIZE_Y
:
408 // If a window is specified/realized, and it is a toplevel window, we can query from wm.
409 // The returned border thickness is outside the client area in that case.
412 wxTopLevelWindow
*tlw
= wxDynamicCast(win
, wxTopLevelWindow
);
414 return -1; // not a tlw, not sure how to approach
417 // Check if wm supports frame extents - we can't know
418 // the border widths if it does not.
419 #if GTK_CHECK_VERSION(2,2,0)
420 if (!gtk_check_version(2,2,0))
422 if (!gdk_x11_screen_supports_net_wm_hint(
423 gdk_drawable_get_screen(window
),
424 gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) )
430 if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false)))
434 // Get the frame extents from the windowmanager.
435 // In most cases the top extent is the titlebar, so we use the bottom extent
442 #if GTK_CHECK_VERSION(2,2,0)
443 if (!gtk_check_version(2,2,0))
446 success
= (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window
)),
447 GDK_WINDOW_XWINDOW(window
),
448 gdk_x11_get_xatom_by_name_for_display (
449 gdk_drawable_get_display(window
),
450 "_NET_FRAME_EXTENTS" ),
451 0, // left, right, top, bottom, CARDINAL[4]/32
452 G_MAXLONG
, // size of long
453 false, // do not delete property
454 XA_CARDINAL
, // 32 bit
455 &type
, &format
, &nitems
, &bytes_after
, &data
461 int border_return
= -1;
463 if ((type
== XA_CARDINAL
) && (format
== 32) && (nitems
>= 4) && (data
))
466 borders
= (long*)data
;
471 case wxSYS_FRAMESIZE_X
:
472 border_return
= borders
[1]; // width of right extent
475 border_return
= borders
[3]; // height of bottom extent
483 return border_return
;
488 return -1; // no window specified
493 if (!gtk_check_version(2,4,0))
496 return gdk_display_get_default_cursor_size(gdk_drawable_get_display(window
));
498 return gdk_display_get_default_cursor_size(gdk_display_get_default());
506 gint dclick_distance
;
507 #if GTK_CHECK_VERSION(2,2,0)
508 if (window
&& !gtk_check_version(2,2,0))
509 g_object_get(gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)),
510 "gtk-double-click-distance", &dclick_distance
, NULL
);
513 g_object_get(gtk_settings_get_default(),
514 "gtk-double-click-distance", &dclick_distance
, NULL
);
516 return dclick_distance
* 2;
521 #if GTK_CHECK_VERSION(2,2,0)
522 if (window
&& !gtk_check_version(2,2,0))
525 gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)),
526 "gtk-dnd-drag-threshold",
527 &drag_threshold
, NULL
);
532 g_object_get(gtk_settings_get_default(),
533 "gtk-dnd-drag-threshold", &drag_threshold
, NULL
);
536 return drag_threshold
* 2;
538 // MBN: ditto for icons
539 case wxSYS_ICON_X
: return 32;
540 case wxSYS_ICON_Y
: return 32;
543 #if GTK_CHECK_VERSION(2,2,0)
544 if (window
&& !gtk_check_version(2,2,0))
545 return gdk_screen_get_width(gdk_drawable_get_screen(window
));
548 return gdk_screen_width();
551 #if GTK_CHECK_VERSION(2,2,0)
552 if (window
&& !gtk_check_version(2,2,0))
553 return gdk_screen_get_height(gdk_drawable_get_screen(window
));
556 return gdk_screen_height();
558 case wxSYS_HSCROLL_Y
: return 15;
559 case wxSYS_VSCROLL_X
: return 15;
561 case wxSYS_CAPTION_Y
:
563 // No realized window specified, and no implementation for that case yet.
566 // Check if wm supports frame extents - we can't know the caption height if it does not.
567 #if GTK_CHECK_VERSION(2,2,0)
568 if (!gtk_check_version(2,2,0))
570 if (!gdk_x11_screen_supports_net_wm_hint(
571 gdk_drawable_get_screen(window
),
572 gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) )
578 if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false)))
582 wxASSERT_MSG( wxDynamicCast(win
, wxTopLevelWindow
),
583 wxT("Asking for caption height of a non toplevel window") );
585 // Get the height of the top windowmanager border.
586 // This is the titlebar in most cases. The titlebar might be elsewhere, and
587 // we could check which is the thickest wm border to decide on which side the
588 // titlebar is, but this might lead to interesting behaviours in used code.
589 // Reconsider when we have a way to report to the user on which side it is.
595 #if GTK_CHECK_VERSION(2,2,0)
596 if (!gtk_check_version(2,2,0))
599 success
= (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window
)),
600 GDK_WINDOW_XWINDOW(window
),
601 gdk_x11_get_xatom_by_name_for_display (
602 gdk_drawable_get_display(window
),
603 "_NET_FRAME_EXTENTS" ),
604 0, // left, right, top, bottom, CARDINAL[4]/32
605 G_MAXLONG
, // size of long
606 false, // do not delete property
607 XA_CARDINAL
, // 32 bit
608 &type
, &format
, &nitems
, &bytes_after
, &data
614 int caption_height
= -1;
616 if ((type
== XA_CARDINAL
) && (format
== 32) && (nitems
>= 3) && (data
))
619 borders
= (long*)data
;
620 caption_height
= borders
[2]; // top frame extent
626 return caption_height
;
629 // Try a default approach without a window pointer, if possible
634 case wxSYS_PENWINDOWS_PRESENT
:
635 // No MS Windows for Pen computing extension available in X11 based gtk+.
639 return -1; // metric is unknown
643 bool wxSystemSettingsNative::HasFeature(wxSystemFeature index
)
647 case wxSYS_CAN_ICONIZE_FRAME
:
650 case wxSYS_CAN_DRAW_FRAME_DECORATIONS
: