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