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