Just return zero without failing for unknown metrics, like the other
[wxWidgets.git] / src / gtk / settings.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/settings.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
12 #pragma implementation "settings.h"
13 #endif
14
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #include "wx/settings.h"
19 #include "wx/debug.h"
20 #include "wx/cmndata.h"
21 #include "wx/fontutil.h"
22
23 #include <gdk/gdk.h>
24 #include <gdk/gdkprivate.h>
25 #include <gtk/gtk.h>
26
27 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
28
29 // ----------------------------------------------------------------------------
30 // wxSystemObjects
31 // ----------------------------------------------------------------------------
32
33 struct wxSystemObjects
34 {
35 wxColour m_colBtnFace,
36 m_colBtnShadow,
37 m_colBtnHighlight,
38 m_colHighlight,
39 m_colHighlightText,
40 m_colListBox,
41 m_colBtnText;
42
43 wxFont m_fontSystem;
44 };
45
46 static wxSystemObjects gs_objects;
47
48 // ----------------------------------------------------------------------------
49 // wxSystemSettings implementation
50 // ----------------------------------------------------------------------------
51
52 // kind of widget to use in GetColourFromGTKWidget
53 enum wxGtkWidgetType
54 {
55 wxGTK_BUTTON,
56 wxGTK_LIST
57 };
58
59 // the colour we need
60 enum wxGtkColourType
61 {
62 wxGTK_FG,
63 wxGTK_BG,
64 wxGTK_BASE
65 };
66
67 // wxSystemSettings::GetColour() helper: get the colours from a GTK+
68 // widget style, return true if we did get them, false to use defaults
69 static bool GetColourFromGTKWidget(int& red, int& green, int& blue,
70 wxGtkWidgetType type = wxGTK_BUTTON,
71 GtkStateType state = GTK_STATE_NORMAL,
72 wxGtkColourType colour = wxGTK_BG)
73 {
74 GtkWidget *widget;
75 switch ( type )
76 {
77 default:
78 wxFAIL_MSG( _T("unexpected GTK widget type") );
79 // fall through
80
81 case wxGTK_BUTTON:
82 widget = gtk_button_new();
83 break;
84
85 case wxGTK_LIST:
86 widget = gtk_list_new();
87 }
88
89 GtkStyle *def = gtk_rc_get_style( widget );
90 if ( !def )
91 def = gtk_widget_get_default_style();
92
93 bool ok;
94 if ( def )
95 {
96 GdkColor *col;
97 switch ( colour )
98 {
99 default:
100 wxFAIL_MSG( _T("unexpected GTK colour type") );
101 // fall through
102
103 case wxGTK_FG:
104 col = def->fg;
105 break;
106
107 case wxGTK_BG:
108 col = def->bg;
109 break;
110
111 case wxGTK_BASE:
112 col = def->base;
113 break;
114 }
115
116 red = col[state].red;
117 green = col[state].green;
118 blue = col[state].blue;
119
120 ok = TRUE;
121 }
122 else
123 {
124 ok = FALSE;
125 }
126
127 gtk_widget_destroy( widget );
128
129 return ok;
130 }
131
132 wxColour wxSystemSettingsNative::GetColour( wxSystemColour index )
133 {
134 switch (index)
135 {
136 case wxSYS_COLOUR_SCROLLBAR:
137 case wxSYS_COLOUR_BACKGROUND:
138 case wxSYS_COLOUR_ACTIVECAPTION:
139 case wxSYS_COLOUR_INACTIVECAPTION:
140 case wxSYS_COLOUR_MENU:
141 case wxSYS_COLOUR_WINDOWFRAME:
142 case wxSYS_COLOUR_ACTIVEBORDER:
143 case wxSYS_COLOUR_INACTIVEBORDER:
144 case wxSYS_COLOUR_BTNFACE:
145 case wxSYS_COLOUR_MENUBAR:
146 case wxSYS_COLOUR_3DLIGHT:
147 if (!gs_objects.m_colBtnFace.Ok())
148 {
149 int red, green, blue;
150 if ( !GetColourFromGTKWidget(red, green, blue) )
151 {
152 red =
153 green = 0;
154 blue = 0x9c40;
155 }
156
157 gs_objects.m_colBtnFace = wxColour( red >> SHIFT,
158 green >> SHIFT,
159 blue >> SHIFT );
160 }
161 return gs_objects.m_colBtnFace;
162
163 case wxSYS_COLOUR_WINDOW:
164 return *wxWHITE;
165
166 case wxSYS_COLOUR_3DDKSHADOW:
167 return *wxBLACK;
168
169 case wxSYS_COLOUR_GRAYTEXT:
170 case wxSYS_COLOUR_BTNSHADOW:
171 //case wxSYS_COLOUR_3DSHADOW:
172 if (!gs_objects.m_colBtnShadow.Ok())
173 {
174 wxColour faceColour(GetColour(wxSYS_COLOUR_3DFACE));
175 gs_objects.m_colBtnShadow =
176 wxColour((unsigned char) (faceColour.Red() * 0.666),
177 (unsigned char) (faceColour.Green() * 0.666),
178 (unsigned char) (faceColour.Blue() * 0.666));
179 }
180
181 return gs_objects.m_colBtnShadow;
182
183 case wxSYS_COLOUR_3DHIGHLIGHT:
184 //case wxSYS_COLOUR_BTNHIGHLIGHT:
185 return * wxWHITE;
186
187 case wxSYS_COLOUR_HIGHLIGHT:
188 if (!gs_objects.m_colHighlight.Ok())
189 {
190 int red, green, blue;
191 if ( !GetColourFromGTKWidget(red, green, blue,
192 wxGTK_BUTTON,
193 GTK_STATE_SELECTED) )
194 {
195 red =
196 green = 0;
197 blue = 0x9c40;
198 }
199
200 gs_objects.m_colHighlight = wxColour( red >> SHIFT,
201 green >> SHIFT,
202 blue >> SHIFT );
203 }
204 return gs_objects.m_colHighlight;
205
206 case wxSYS_COLOUR_LISTBOX:
207 if (!gs_objects.m_colListBox.Ok())
208 {
209 int red, green, blue;
210 if ( GetColourFromGTKWidget(red, green, blue,
211 wxGTK_LIST,
212 GTK_STATE_NORMAL,
213 wxGTK_BASE) )
214 {
215 gs_objects.m_colListBox = wxColour( red >> SHIFT,
216 green >> SHIFT,
217 blue >> SHIFT );
218 }
219 else
220 {
221 gs_objects.m_colListBox = wxColour(*wxWHITE);
222 }
223 }
224 return gs_objects.m_colListBox;
225
226 case wxSYS_COLOUR_MENUTEXT:
227 case wxSYS_COLOUR_WINDOWTEXT:
228 case wxSYS_COLOUR_CAPTIONTEXT:
229 case wxSYS_COLOUR_INACTIVECAPTIONTEXT:
230 case wxSYS_COLOUR_BTNTEXT:
231 case wxSYS_COLOUR_INFOTEXT:
232 if (!gs_objects.m_colBtnText.Ok())
233 {
234 int red, green, blue;
235 if ( !GetColourFromGTKWidget(red, green, blue,
236 wxGTK_BUTTON,
237 GTK_STATE_NORMAL,
238 wxGTK_FG) )
239 {
240 red =
241 green =
242 blue = 0;
243 }
244
245 gs_objects.m_colBtnText = wxColour( red >> SHIFT,
246 green >> SHIFT,
247 blue >> SHIFT );
248 }
249 return gs_objects.m_colBtnText;
250
251 // this (as well as wxSYS_COLOUR_INFOTEXT above) is used for
252 // tooltip windows - Robert, please change this code to use the
253 // real GTK tooltips when/if you can (TODO)
254 case wxSYS_COLOUR_INFOBK:
255 return wxColour(255, 255, 225);
256
257 case wxSYS_COLOUR_HIGHLIGHTTEXT:
258 if (!gs_objects.m_colHighlightText.Ok())
259 {
260 wxColour hclr = GetColour(wxSYS_COLOUR_HIGHLIGHT);
261 if (hclr.Red() > 200 && hclr.Green() > 200 && hclr.Blue() > 200)
262 gs_objects.m_colHighlightText = wxColour(*wxBLACK);
263 else
264 gs_objects.m_colHighlightText = wxColour(*wxWHITE);
265 }
266 return gs_objects.m_colHighlightText;
267
268 case wxSYS_COLOUR_APPWORKSPACE:
269 return *wxWHITE; // ?
270
271 case wxSYS_COLOUR_HOTLIGHT:
272 case wxSYS_COLOUR_GRADIENTACTIVECAPTION:
273 case wxSYS_COLOUR_GRADIENTINACTIVECAPTION:
274 case wxSYS_COLOUR_MENUHILIGHT:
275 // TODO
276 return *wxBLACK;
277
278 case wxSYS_COLOUR_MAX:
279 default:
280 wxFAIL_MSG( _T("unknown system colour index") );
281 }
282
283 return *wxWHITE;
284 }
285
286 wxFont wxSystemSettingsNative::GetFont( wxSystemFont index )
287 {
288 switch (index)
289 {
290 case wxSYS_OEM_FIXED_FONT:
291 case wxSYS_ANSI_FIXED_FONT:
292 case wxSYS_SYSTEM_FIXED_FONT:
293 {
294 return *wxNORMAL_FONT;
295 }
296 case wxSYS_ANSI_VAR_FONT:
297 case wxSYS_SYSTEM_FONT:
298 case wxSYS_DEVICE_DEFAULT_FONT:
299 case wxSYS_DEFAULT_GUI_FONT:
300 {
301 if (!gs_objects.m_fontSystem.Ok())
302 {
303 #ifdef __WXGTK20__
304 GtkWidget *widget = gtk_button_new();
305 GtkStyle *def = gtk_rc_get_style( widget );
306 if ( !def || !def->font_desc )
307 def = gtk_widget_get_default_style();
308 if ( def && def->font_desc )
309 {
310 wxNativeFontInfo info;
311 info.description =
312 pango_font_description_copy(def->font_desc);
313 gs_objects.m_fontSystem = wxFont(info);
314 }
315 else
316 {
317 GtkSettings *settings = gtk_settings_get_default();
318 gchar *font_name = NULL;
319 g_object_get ( settings,
320 "gtk-font-name",
321 &font_name,
322 NULL);
323 if (!font_name)
324 gs_objects.m_fontSystem = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
325 else
326 gs_objects.m_fontSystem = wxFont(wxString::FromAscii(font_name));
327 g_free (font_name);
328 }
329 gtk_widget_destroy( widget );
330 #else
331 gs_objects.m_fontSystem = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
332 #endif
333 }
334 return gs_objects.m_fontSystem;
335 }
336
337 default:
338 return wxNullFont;
339 }
340 }
341
342 int wxSystemSettingsNative::GetMetric( wxSystemMetric index )
343 {
344 switch (index)
345 {
346 case wxSYS_SCREEN_X: return gdk_screen_width();
347 case wxSYS_SCREEN_Y: return gdk_screen_height();
348 case wxSYS_HSCROLL_Y: return 15;
349 case wxSYS_VSCROLL_X: return 15;
350
351 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 4, 0)
352 case wxSYS_DCLICK_X:
353 case wxSYS_DCLICK_Y:
354 gint dclick_distance;
355 g_object_get(gtk_settings_get_default(), "gtk-double-click-distance", &dclick_distance, NULL);
356 return dclick_distance * 2;
357 #endif
358
359 #if defined(__WXGTK20__)
360 case wxSYS_DRAG_X:
361 case wxSYS_DRAG_Y:
362 gint drag_threshold;
363 g_object_get(gtk_settings_get_default(), "gtk-dnd-drag-threshold", &drag_threshold, NULL);
364 return drag_threshold * 2;
365 #endif
366
367 // VZ: is there any way to get the cursor size with GDK?
368 // Mart Raudsepp: Yes, there is a way to get the default cursor size for a display ever since GDK 2.4
369 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2, 4, 0)
370 case wxSYS_CURSOR_X:
371 case wxSYS_CURSOR_Y:
372 return gdk_display_get_default_cursor_size(gdk_display_get_default());
373 #else
374 case wxSYS_CURSOR_X: return 16;
375 case wxSYS_CURSOR_Y: return 16;
376 #endif
377 // MBN: ditto for icons
378 case wxSYS_ICON_X: return 32;
379 case wxSYS_ICON_Y: return 32;
380 default:
381 return 0; // metric is unknown
382 }
383 }
384
385 bool wxSystemSettingsNative::HasFeature(wxSystemFeature index)
386 {
387 switch (index)
388 {
389 case wxSYS_CAN_ICONIZE_FRAME:
390 return FALSE;
391 break;
392 case wxSYS_CAN_DRAW_FRAME_DECORATIONS:
393 return TRUE;
394 break;
395 default:
396 return FALSE;
397 }
398 }