]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/settings.cpp
use WX_DEFINE_ARRAY_INT for an array of ints (bug 1536482)
[wxWidgets.git] / src / gtk1 / settings.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/settings.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Modified by: Mart Raudsepp (GetMetric)
6 // Id: $Id$
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #include "wx/settings.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/cmndata.h"
18 #include "wx/toplevel.h"
19 #endif
20
21 #include "wx/fontutil.h"
22
23 #include <gdk/gdk.h>
24 #include <gdk/gdkx.h>
25 #include <gdk/gdkprivate.h>
26 #include <gtk/gtk.h>
27
28 #include <X11/Xatom.h>
29
30 #define SHIFT (8*(sizeof(short int)-sizeof(char)))
31
32 // ----------------------------------------------------------------------------
33 // wxSystemObjects
34 // ----------------------------------------------------------------------------
35
36 struct wxSystemObjects
37 {
38 wxColour m_colBtnFace,
39 m_colBtnShadow,
40 m_colBtnHighlight,
41 m_colHighlight,
42 m_colHighlightText,
43 m_colListBox,
44 m_colBtnText,
45 m_colMenuItemHighlight,
46 m_colTooltip,
47 m_colTooltipText;
48
49 wxFont m_fontSystem;
50 };
51
52 static wxSystemObjects gs_objects;
53
54 // ----------------------------------------------------------------------------
55 // wxSystemSettings implementation
56 // ----------------------------------------------------------------------------
57
58 // kind of widget to use in GetColourFromGTKWidget
59 enum wxGtkWidgetType
60 {
61 wxGTK_BUTTON,
62 wxGTK_LIST,
63 wxGTK_MENUITEM
64 };
65
66 // the colour we need
67 enum wxGtkColourType
68 {
69 wxGTK_FG,
70 wxGTK_BG,
71 wxGTK_BASE
72 };
73
74 // wxSystemSettings::GetColour() helper: get the colours from a GTK+
75 // widget style, return true if we did get them, false to use defaults
76 static bool GetColourFromGTKWidget(int& red, int& green, int& blue,
77 wxGtkWidgetType type = wxGTK_BUTTON,
78 GtkStateType state = GTK_STATE_NORMAL,
79 wxGtkColourType colour = wxGTK_BG)
80 {
81 GtkWidget *widget;
82 switch ( type )
83 {
84 default:
85 wxFAIL_MSG( _T("unexpected GTK widget type") );
86 // fall through
87
88 case wxGTK_BUTTON:
89 widget = gtk_button_new();
90 break;
91
92 case wxGTK_LIST:
93 widget = gtk_list_new();
94 break;
95
96 case wxGTK_MENUITEM:
97 widget = gtk_menu_item_new();
98 }
99
100 GtkStyle *def = gtk_rc_get_style( widget );
101 if ( !def )
102 def = gtk_widget_get_default_style();
103
104 bool ok;
105 if ( def )
106 {
107 GdkColor *col;
108 switch ( colour )
109 {
110 default:
111 wxFAIL_MSG( _T("unexpected GTK colour type") );
112 // fall through
113
114 case wxGTK_FG:
115 col = def->fg;
116 break;
117
118 case wxGTK_BG:
119 col = def->bg;
120 break;
121
122 case wxGTK_BASE:
123 col = def->base;
124 break;
125 }
126
127 red = col[state].red;
128 green = col[state].green;
129 blue = col[state].blue;
130
131 ok = true;
132 }
133 else
134 {
135 ok = false;
136 }
137
138 gtk_widget_destroy( widget );
139
140 return ok;
141 }
142
143 static void GetTooltipColors()
144 {
145 GtkTooltips* tooltips = gtk_tooltips_new();
146 gtk_tooltips_force_window(tooltips);
147 gtk_widget_ensure_style(tooltips->tip_window);
148 GdkColor c = tooltips->tip_window->style->bg[GTK_STATE_NORMAL];
149 gs_objects.m_colTooltip = wxColor(c.red >> SHIFT, c.green >> SHIFT, c.blue >> SHIFT);
150 c = tooltips->tip_window->style->fg[GTK_STATE_NORMAL];
151 gs_objects.m_colTooltipText = wxColor(c.red >> SHIFT, c.green >> SHIFT, c.blue >> SHIFT);
152 gtk_object_sink(wx_reinterpret_cast(GtkObject*, tooltips));
153 }
154
155 wxColour wxSystemSettingsNative::GetColour( wxSystemColour index )
156 {
157 switch (index)
158 {
159 case wxSYS_COLOUR_SCROLLBAR:
160 case wxSYS_COLOUR_BACKGROUND:
161 case wxSYS_COLOUR_INACTIVECAPTION:
162 case wxSYS_COLOUR_MENU:
163 case wxSYS_COLOUR_WINDOWFRAME:
164 case wxSYS_COLOUR_ACTIVEBORDER:
165 case wxSYS_COLOUR_INACTIVEBORDER:
166 case wxSYS_COLOUR_BTNFACE:
167 case wxSYS_COLOUR_MENUBAR:
168 case wxSYS_COLOUR_3DLIGHT:
169 if (!gs_objects.m_colBtnFace.Ok())
170 {
171 int red, green, blue;
172 if ( !GetColourFromGTKWidget(red, green, blue) )
173 {
174 red =
175 green = 0;
176 blue = 0x9c40;
177 }
178
179 gs_objects.m_colBtnFace = wxColour( red >> SHIFT,
180 green >> SHIFT,
181 blue >> SHIFT );
182 }
183 return gs_objects.m_colBtnFace;
184
185 case wxSYS_COLOUR_WINDOW:
186 return *wxWHITE;
187
188 case wxSYS_COLOUR_3DDKSHADOW:
189 return *wxBLACK;
190
191 case wxSYS_COLOUR_GRAYTEXT:
192 case wxSYS_COLOUR_BTNSHADOW:
193 //case wxSYS_COLOUR_3DSHADOW:
194 if (!gs_objects.m_colBtnShadow.Ok())
195 {
196 wxColour faceColour(GetColour(wxSYS_COLOUR_3DFACE));
197 gs_objects.m_colBtnShadow =
198 wxColour((unsigned char) (faceColour.Red() * 0.666),
199 (unsigned char) (faceColour.Green() * 0.666),
200 (unsigned char) (faceColour.Blue() * 0.666));
201 }
202
203 return gs_objects.m_colBtnShadow;
204
205 case wxSYS_COLOUR_3DHIGHLIGHT:
206 //case wxSYS_COLOUR_BTNHIGHLIGHT:
207 return * wxWHITE;
208
209 case wxSYS_COLOUR_HIGHLIGHT:
210 if (!gs_objects.m_colHighlight.Ok())
211 {
212 int red, green, blue;
213 if ( !GetColourFromGTKWidget(red, green, blue,
214 wxGTK_BUTTON,
215 GTK_STATE_SELECTED) )
216 {
217 red =
218 green = 0;
219 blue = 0x9c40;
220 }
221
222 gs_objects.m_colHighlight = wxColour( red >> SHIFT,
223 green >> SHIFT,
224 blue >> SHIFT );
225 }
226 return gs_objects.m_colHighlight;
227
228 case wxSYS_COLOUR_LISTBOX:
229 if (!gs_objects.m_colListBox.Ok())
230 {
231 int red, green, blue;
232 if ( GetColourFromGTKWidget(red, green, blue,
233 wxGTK_LIST,
234 GTK_STATE_NORMAL,
235 wxGTK_BASE) )
236 {
237 gs_objects.m_colListBox = wxColour( red >> SHIFT,
238 green >> SHIFT,
239 blue >> SHIFT );
240 }
241 else
242 {
243 gs_objects.m_colListBox = wxColour(*wxWHITE);
244 }
245 }
246 return gs_objects.m_colListBox;
247
248 case wxSYS_COLOUR_MENUTEXT:
249 case wxSYS_COLOUR_WINDOWTEXT:
250 case wxSYS_COLOUR_CAPTIONTEXT:
251 case wxSYS_COLOUR_INACTIVECAPTIONTEXT:
252 case wxSYS_COLOUR_BTNTEXT:
253 if (!gs_objects.m_colBtnText.Ok())
254 {
255 int red, green, blue;
256 if ( !GetColourFromGTKWidget(red, green, blue,
257 wxGTK_BUTTON,
258 GTK_STATE_NORMAL,
259 wxGTK_FG) )
260 {
261 red =
262 green =
263 blue = 0;
264 }
265
266 gs_objects.m_colBtnText = wxColour( red >> SHIFT,
267 green >> SHIFT,
268 blue >> SHIFT );
269 }
270 return gs_objects.m_colBtnText;
271
272 case wxSYS_COLOUR_INFOBK:
273 if (!gs_objects.m_colTooltip.Ok()) {
274 GetTooltipColors();
275 }
276 return gs_objects.m_colTooltip;
277
278 case wxSYS_COLOUR_INFOTEXT:
279 if (!gs_objects.m_colTooltipText.Ok()) {
280 GetTooltipColors();
281 }
282 return gs_objects.m_colTooltipText;
283
284 case wxSYS_COLOUR_HIGHLIGHTTEXT:
285 if (!gs_objects.m_colHighlightText.Ok())
286 {
287 wxColour hclr = GetColour(wxSYS_COLOUR_HIGHLIGHT);
288 if (hclr.Red() > 200 && hclr.Green() > 200 && hclr.Blue() > 200)
289 gs_objects.m_colHighlightText = wxColour(*wxBLACK);
290 else
291 gs_objects.m_colHighlightText = wxColour(*wxWHITE);
292 }
293 return gs_objects.m_colHighlightText;
294
295 case wxSYS_COLOUR_APPWORKSPACE:
296 return *wxWHITE; // ?
297
298 case wxSYS_COLOUR_ACTIVECAPTION:
299 case wxSYS_COLOUR_MENUHILIGHT:
300 if (!gs_objects.m_colMenuItemHighlight.Ok())
301 {
302 int red, green, blue;
303 if ( !GetColourFromGTKWidget(red, green, blue,
304 wxGTK_MENUITEM,
305 GTK_STATE_SELECTED,
306 wxGTK_BG) )
307 {
308 red =
309 green =
310 blue = 0;
311 }
312
313 gs_objects.m_colMenuItemHighlight = wxColour( red >> SHIFT,
314 green >> SHIFT,
315 blue >> SHIFT );
316 }
317 return gs_objects.m_colMenuItemHighlight;
318
319 case wxSYS_COLOUR_HOTLIGHT:
320 case wxSYS_COLOUR_GRADIENTACTIVECAPTION:
321 case wxSYS_COLOUR_GRADIENTINACTIVECAPTION:
322 // TODO
323 return *wxBLACK;
324
325 case wxSYS_COLOUR_MAX:
326 default:
327 wxFAIL_MSG( _T("unknown system colour index") );
328 }
329
330 return *wxWHITE;
331 }
332
333 wxFont wxSystemSettingsNative::GetFont( wxSystemFont index )
334 {
335 switch (index)
336 {
337 case wxSYS_OEM_FIXED_FONT:
338 case wxSYS_ANSI_FIXED_FONT:
339 case wxSYS_SYSTEM_FIXED_FONT:
340 {
341 return *wxNORMAL_FONT;
342 }
343 case wxSYS_ANSI_VAR_FONT:
344 case wxSYS_SYSTEM_FONT:
345 case wxSYS_DEVICE_DEFAULT_FONT:
346 case wxSYS_DEFAULT_GUI_FONT:
347 {
348 if (!gs_objects.m_fontSystem.Ok())
349 {
350 gs_objects.m_fontSystem = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL );
351 }
352 return gs_objects.m_fontSystem;
353 }
354
355 default:
356 return wxNullFont;
357 }
358 }
359
360 int wxSystemSettingsNative::GetMetric( wxSystemMetric index, wxWindow* win )
361 {
362 switch (index)
363 {
364 case wxSYS_CURSOR_X:
365 case wxSYS_CURSOR_Y:
366 return 16;
367
368 // MBN: ditto for icons
369 case wxSYS_ICON_X: return 32;
370 case wxSYS_ICON_Y: return 32;
371
372 case wxSYS_SCREEN_X:
373 return gdk_screen_width();
374
375 case wxSYS_SCREEN_Y:
376 return gdk_screen_height();
377
378 case wxSYS_HSCROLL_Y: return 15;
379 case wxSYS_VSCROLL_X: return 15;
380
381 // a gtk1 implementation should be possible too if gtk2 efficiency/convenience functions aren't used
382 #if 0
383 case wxSYS_CAPTION_Y:
384 if (!window)
385 // No realized window specified, and no implementation for that case yet.
386 return -1;
387
388 // Check if wm supports frame extents - we can't know the caption height if it does not.
389 #if GTK_CHECK_VERSION(2,2,0)
390 if (!gtk_check_version(2,2,0))
391 {
392 if (!gdk_x11_screen_supports_net_wm_hint(
393 gdk_drawable_get_screen(window),
394 gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) )
395 return -1;
396 }
397 else
398 #endif
399 {
400 if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false)))
401 return -1;
402 }
403
404 wxASSERT_MSG( wxDynamicCast(win, wxTopLevelWindow),
405 wxT("Asking for caption height of a non toplevel window") );
406
407 // Get the height of the top windowmanager border.
408 // This is the titlebar in most cases. The titlebar might be elsewhere, and
409 // we could check which is the thickest wm border to decide on which side the
410 // titlebar is, but this might lead to interesting behaviours in used code.
411 // Reconsider when we have a way to report to the user on which side it is.
412
413 Atom type;
414 gint format;
415 gulong nitems;
416
417 #if GTK_CHECK_VERSION(2,2,0)
418 if (!gtk_check_version(2,2,0))
419 {
420 gulong bytes_after;
421 success = (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window)),
422 GDK_WINDOW_XWINDOW(window),
423 gdk_x11_get_xatom_by_name_for_display (
424 gdk_drawable_get_display(window),
425 "_NET_FRAME_EXTENTS" ),
426 0, // left, right, top, bottom, CARDINAL[4]/32
427 G_MAXLONG, // size of long
428 false, // do not delete property
429 XA_CARDINAL, // 32 bit
430 &type, &format, &nitems, &bytes_after, &data
431 ) == Success);
432 }
433 #endif
434 if (success)
435 {
436 int caption_height = -1;
437
438 if ((type == XA_CARDINAL) && (format == 32) && (nitems >= 3) && (data))
439 {
440 long *borders;
441 borders = (long*)data;
442 caption_height = borders[2]; // top frame extent
443 }
444
445 if (data)
446 XFree(data);
447
448 return caption_height;
449 }
450
451 // Try a default approach without a window pointer, if possible
452 // ...
453
454 return -1;
455 #endif // gtk2
456
457 case wxSYS_PENWINDOWS_PRESENT:
458 // No MS Windows for Pen computing extension available in X11 based gtk+.
459 return 0;
460
461 default:
462 return -1; // metric is unknown
463 }
464 }
465
466 bool wxSystemSettingsNative::HasFeature(wxSystemFeature index)
467 {
468 switch (index)
469 {
470 case wxSYS_CAN_ICONIZE_FRAME:
471 return false;
472
473 case wxSYS_CAN_DRAW_FRAME_DECORATIONS:
474 return true;
475
476 default:
477 return false;
478 }
479 }