]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/settings.cpp
don't waste time sending out update UI events for separators, they can't be updated...
[wxWidgets.git] / src / gtk / settings.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
e7c80f9e 2// Name: src/gtk/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
WS
16#ifndef WX_PRECOMP
17 #include "wx/cmndata.h"
1832043f 18 #include "wx/toplevel.h"
ce5d92e1
WS
19#endif
20
2b5f62a0 21#include "wx/fontutil.h"
d06b34a7 22
aed8ac3f 23#include <gtk/gtk.h>
83624f79 24
166b4de7 25bool wxGetFrameExtents(GdkWindow* window, int* left, int* right, int* top, int* bottom);
9b0b5ba7 26
0ab5e0e8 27// ----------------------------------------------------------------------------
0d0b57ac 28// wxSystemSettings implementation
0ab5e0e8
VS
29// ----------------------------------------------------------------------------
30
0d0b57ac
PC
31static wxFont gs_fontSystem;
32
33static GtkContainer* ContainerWidget()
a51d7c4b 34{
0d0b57ac
PC
35 static GtkContainer* s_widget;
36 if (s_widget == NULL)
37 {
38 s_widget = GTK_CONTAINER(gtk_fixed_new());
39 GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
40 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(s_widget));
41 }
42 return s_widget;
a51d7c4b
JS
43}
44
0d0b57ac
PC
45extern "C" {
46static void style_set(GtkWidget*, GtkStyle*, void*)
643ccf62 47{
0d0b57ac
PC
48 gs_fontSystem = wxNullFont;
49}
50}
51
52static const GtkStyle* ButtonStyle()
643ccf62 53{
0d0b57ac
PC
54 static GtkWidget* s_widget;
55 if (s_widget == NULL)
dbcbe229 56 {
0d0b57ac
PC
57 s_widget = gtk_button_new();
58 gtk_container_add(ContainerWidget(), s_widget);
59 gtk_widget_ensure_style(s_widget);
60 g_signal_connect(s_widget, "style_set", G_CALLBACK(style_set), NULL);
dbcbe229 61 }
0d0b57ac
PC
62 return s_widget->style;
63}
dbcbe229 64
0d0b57ac
PC
65static const GtkStyle* ListStyle()
66{
67 static GtkWidget* s_widget;
68 if (s_widget == NULL)
69 {
70 s_widget = gtk_tree_view_new_with_model(
71 GTK_TREE_MODEL(gtk_list_store_new(1, G_TYPE_INT)));
72 gtk_container_add(ContainerWidget(), s_widget);
73 gtk_widget_ensure_style(s_widget);
74 }
75 return s_widget->style;
76}
643ccf62 77
0d0b57ac
PC
78static const GtkStyle* TextCtrlStyle()
79{
80 static GtkWidget* s_widget;
81 if (s_widget == NULL)
643ccf62 82 {
0d0b57ac
PC
83 s_widget = gtk_text_view_new();
84 gtk_container_add(ContainerWidget(), s_widget);
85 gtk_widget_ensure_style(s_widget);
643ccf62 86 }
0d0b57ac
PC
87 return s_widget->style;
88}
643ccf62 89
0d0b57ac
PC
90static const GtkStyle* MenuItemStyle()
91{
92 static GtkWidget* s_widget;
93 if (s_widget == NULL)
94 {
95 s_widget = gtk_menu_item_new();
96 gtk_container_add(ContainerWidget(), s_widget);
97 gtk_widget_ensure_style(s_widget);
98 }
99 return s_widget->style;
100}
643ccf62 101
0d0b57ac
PC
102static const GtkStyle* MenuBarStyle()
103{
104 static GtkWidget* s_widget;
105 if (s_widget == NULL)
106 {
107 s_widget = gtk_menu_bar_new();
108 gtk_container_add(ContainerWidget(), s_widget);
109 gtk_widget_ensure_style(s_widget);
110 }
111 return s_widget->style;
643ccf62
VZ
112}
113
0d0b57ac 114static const GtkStyle* ToolTipStyle()
c05cc2c7 115{
0d0b57ac
PC
116 static GtkWidget* s_widget;
117 if (s_widget == NULL)
118 {
119 s_widget = gtk_window_new(GTK_WINDOW_POPUP);
120 const char* name = "gtk-tooltip";
121 if (gtk_check_version(2, 11, 0))
122 name = "gtk-tooltips";
123 gtk_widget_set_name(s_widget, name);
124 gtk_widget_ensure_style(s_widget);
125 }
126 return s_widget->style;
c05cc2c7
RR
127}
128
0ab5e0e8 129wxColour wxSystemSettingsNative::GetColour( wxSystemColour index )
c801d85f 130{
b0ae510a 131 wxColor color;
db434467 132 switch (index)
c801d85f 133 {
db434467
RR
134 case wxSYS_COLOUR_SCROLLBAR:
135 case wxSYS_COLOUR_BACKGROUND:
0d0b57ac 136 //case wxSYS_COLOUR_DESKTOP:
db434467
RR
137 case wxSYS_COLOUR_INACTIVECAPTION:
138 case wxSYS_COLOUR_MENU:
139 case wxSYS_COLOUR_WINDOWFRAME:
140 case wxSYS_COLOUR_ACTIVEBORDER:
141 case wxSYS_COLOUR_INACTIVEBORDER:
142 case wxSYS_COLOUR_BTNFACE:
0d0b57ac 143 //case wxSYS_COLOUR_3DFACE:
5b211fbf 144 case wxSYS_COLOUR_3DLIGHT:
0d0b57ac 145 color = wxColor(ButtonStyle()->bg[GTK_STATE_NORMAL]);
b0ae510a 146 break;
643ccf62 147
db434467 148 case wxSYS_COLOUR_WINDOW:
0d0b57ac 149 color = wxColor(TextCtrlStyle()->base[GTK_STATE_NORMAL]);
b0ae510a 150 break;
643ccf62 151
3ab6b7e6 152 case wxSYS_COLOUR_MENUBAR:
0d0b57ac 153 color = wxColor(MenuBarStyle()->bg[GTK_STATE_NORMAL]);
3ab6b7e6
VZ
154 break;
155
37d403aa 156 case wxSYS_COLOUR_3DDKSHADOW:
b0ae510a
PC
157 color = *wxBLACK;
158 break;
643ccf62 159
db434467
RR
160 case wxSYS_COLOUR_GRAYTEXT:
161 case wxSYS_COLOUR_BTNSHADOW:
37d403aa 162 //case wxSYS_COLOUR_3DSHADOW:
37d403aa 163 {
984152a6 164 wxColour faceColour(GetColour(wxSYS_COLOUR_3DFACE));
0d0b57ac 165 color =
b0ae510a
PC
166 wxColour((unsigned char) (faceColour.Red() * 2 / 3),
167 (unsigned char) (faceColour.Green() * 2 / 3),
168 (unsigned char) (faceColour.Blue() * 2 / 3));
db434467 169 }
b0ae510a 170 break;
643ccf62 171
0d0b57ac
PC
172 case wxSYS_COLOUR_BTNHIGHLIGHT:
173 //case wxSYS_COLOUR_BTNHILIGHT:
174 //case wxSYS_COLOUR_3DHIGHLIGHT:
175 //case wxSYS_COLOUR_3DHILIGHT:
b0ae510a
PC
176 color = *wxWHITE;
177 break;
643ccf62 178
db434467 179 case wxSYS_COLOUR_HIGHLIGHT:
0d0b57ac 180 color = wxColor(ButtonStyle()->bg[GTK_STATE_SELECTED]);
b0ae510a 181 break;
643ccf62 182
74f55195 183 case wxSYS_COLOUR_LISTBOX:
0d0b57ac 184 color = wxColor(ListStyle()->base[GTK_STATE_NORMAL]);
b0ae510a 185 break;
643ccf62
VZ
186
187 case wxSYS_COLOUR_MENUTEXT:
188 case wxSYS_COLOUR_WINDOWTEXT:
189 case wxSYS_COLOUR_CAPTIONTEXT:
190 case wxSYS_COLOUR_INACTIVECAPTIONTEXT:
191 case wxSYS_COLOUR_BTNTEXT:
0d0b57ac 192 color = wxColor(ButtonStyle()->fg[GTK_STATE_NORMAL]);
b0ae510a 193 break;
643ccf62 194
17d61cbf 195 case wxSYS_COLOUR_INFOBK:
0d0b57ac 196 color = wxColor(ToolTipStyle()->bg[GTK_STATE_NORMAL]);
b0ae510a 197 break;
c05cc2c7
RR
198
199 case wxSYS_COLOUR_INFOTEXT:
0d0b57ac 200 color = wxColor(ToolTipStyle()->fg[GTK_STATE_NORMAL]);
b0ae510a 201 break;
17d61cbf 202
643ccf62 203 case wxSYS_COLOUR_HIGHLIGHTTEXT:
0d0b57ac 204 color = wxColor(ButtonStyle()->fg[GTK_STATE_SELECTED]);
b0ae510a 205 break;
643ccf62 206
643ccf62 207 case wxSYS_COLOUR_APPWORKSPACE:
b0ae510a
PC
208 color = *wxWHITE; // ?
209 break;
221ed576 210
9d6a9fdd
RR
211 case wxSYS_COLOUR_ACTIVECAPTION:
212 case wxSYS_COLOUR_MENUHILIGHT:
0d0b57ac 213 color = wxColor(MenuItemStyle()->bg[GTK_STATE_SELECTED]);
b0ae510a 214 break;
9d6a9fdd 215
221ed576
VZ
216 case wxSYS_COLOUR_HOTLIGHT:
217 case wxSYS_COLOUR_GRADIENTACTIVECAPTION:
218 case wxSYS_COLOUR_GRADIENTINACTIVECAPTION:
221ed576 219 // TODO
b0ae510a
PC
220 color = *wxBLACK;
221 break;
221ed576
VZ
222
223 case wxSYS_COLOUR_MAX:
224 default:
225 wxFAIL_MSG( _T("unknown system colour index") );
b0ae510a
PC
226 color = *wxWHITE;
227 break;
e24b680c 228 }
643ccf62 229
b0ae510a 230 return color;
ff7b1510 231}
c801d85f 232
0ab5e0e8 233wxFont wxSystemSettingsNative::GetFont( wxSystemFont index )
c801d85f 234{
b0ae510a 235 wxFont font;
2d17d68f 236 switch (index)
c801d85f 237 {
2d17d68f
RR
238 case wxSYS_OEM_FIXED_FONT:
239 case wxSYS_ANSI_FIXED_FONT:
240 case wxSYS_SYSTEM_FIXED_FONT:
b0ae510a
PC
241 font = *wxNORMAL_FONT;
242 break;
243
2d17d68f
RR
244 case wxSYS_ANSI_VAR_FONT:
245 case wxSYS_SYSTEM_FONT:
246 case wxSYS_DEVICE_DEFAULT_FONT:
247 case wxSYS_DEFAULT_GUI_FONT:
0d0b57ac 248 if (!gs_fontSystem.Ok())
d06b34a7 249 {
0d0b57ac
PC
250 wxNativeFontInfo info;
251 info.description = ButtonStyle()->font_desc;
252 gs_fontSystem = wxFont(info);
253 info.description = NULL;
d06b34a7 254 }
0d0b57ac 255 font = gs_fontSystem;
b0ae510a 256 break;
c801d85f 257
0ab5e0e8 258 default:
b0ae510a 259 break;
0ab5e0e8 260 }
b0ae510a 261 return font;
c801d85f 262}
c801d85f 263
ff654490
VZ
264// helper: return the GtkSettings either for the screen the current window is
265// on or for the default screen if window is NULL
266static GtkSettings *GetSettingsForWindowScreen(GdkWindow *window)
267{
268 return window ? gtk_settings_get_for_screen(gdk_drawable_get_screen(window))
269 : gtk_settings_get_default();
270}
271
b0ae510a
PC
272int wxSystemSettingsNative::GetMetric( wxSystemMetric index, wxWindow* win )
273{
9b0b5ba7
RR
274 GdkWindow *window = NULL;
275 if(win && GTK_WIDGET_REALIZED(win->GetHandle()))
276 window = win->GetHandle()->window;
9b0b5ba7 277
1ecc4d80
RR
278 switch (index)
279 {
9b0b5ba7
RR
280 case wxSYS_BORDER_X:
281 case wxSYS_BORDER_Y:
282 case wxSYS_EDGE_X:
283 case wxSYS_EDGE_Y:
284 case wxSYS_FRAMESIZE_X:
285 case wxSYS_FRAMESIZE_Y:
286 // If a window is specified/realized, and it is a toplevel window, we can query from wm.
287 // The returned border thickness is outside the client area in that case.
288 if (window)
289 {
290 wxTopLevelWindow *tlw = wxDynamicCast(win, wxTopLevelWindow);
291 if (!tlw)
292 return -1; // not a tlw, not sure how to approach
293 else
294 {
9b0b5ba7
RR
295 // Get the frame extents from the windowmanager.
296 // In most cases the top extent is the titlebar, so we use the bottom extent
297 // for the heights.
37cafc6a 298 int right, bottom;
166b4de7 299 if (wxGetFrameExtents(window, NULL, &right, NULL, &bottom))
9b0b5ba7 300 {
37cafc6a 301 switch (index)
9b0b5ba7 302 {
37cafc6a
PC
303 case wxSYS_BORDER_X:
304 case wxSYS_EDGE_X:
305 case wxSYS_FRAMESIZE_X:
306 return right; // width of right extent
307 default:
308 return bottom; // height of bottom extent
9b0b5ba7 309 }
9b0b5ba7
RR
310 }
311 }
312 }
313
314 return -1; // no window specified
315
316 case wxSYS_CURSOR_X:
317 case wxSYS_CURSOR_Y:
ff654490
VZ
318 return gdk_display_get_default_cursor_size(
319 window ? gdk_drawable_get_display(window)
320 : gdk_display_get_default());
17d61cbf 321
44fd6f72
VS
322 case wxSYS_DCLICK_X:
323 case wxSYS_DCLICK_Y:
324 gint dclick_distance;
ff654490
VZ
325 g_object_get(GetSettingsForWindowScreen(window),
326 "gtk-double-click-distance", &dclick_distance, NULL);
9b0b5ba7
RR
327
328 return dclick_distance * 2;
44fd6f72 329
5595181f
VZ
330 case wxSYS_DCLICK_MSEC:
331 gint dclick;
ff654490 332 g_object_get(GetSettingsForWindowScreen(window),
5595181f
VZ
333 "gtk-double-click-time", &dclick, NULL);
334 return dclick;
335
44fd6f72
VS
336 case wxSYS_DRAG_X:
337 case wxSYS_DRAG_Y:
338 gint drag_threshold;
ff654490
VZ
339 g_object_get(GetSettingsForWindowScreen(window),
340 "gtk-dnd-drag-threshold", &drag_threshold, NULL);
44fd6f72 341
9fcdfe05
RR
342 // The correct thing here would be to double the value
343 // since that is what the API wants. But the values
344 // are much bigger under GNOME than under Windows and
345 // just seem to much in many cases to be useful.
f4322df6 346 // drag_threshold *= 2;
9fcdfe05 347
1e7373d0 348 return drag_threshold;
9b0b5ba7 349
ff654490
VZ
350 case wxSYS_ICON_X:
351 case wxSYS_ICON_Y:
352 return 32;
9b0b5ba7
RR
353
354 case wxSYS_SCREEN_X:
ff654490 355 if (window)
9b0b5ba7
RR
356 return gdk_screen_get_width(gdk_drawable_get_screen(window));
357 else
9b0b5ba7
RR
358 return gdk_screen_width();
359
360 case wxSYS_SCREEN_Y:
ff654490 361 if (window)
9b0b5ba7
RR
362 return gdk_screen_get_height(gdk_drawable_get_screen(window));
363 else
9b0b5ba7
RR
364 return gdk_screen_height();
365
ff654490
VZ
366 case wxSYS_HSCROLL_Y:
367 case wxSYS_VSCROLL_X:
368 return 15;
9b0b5ba7 369
9b0b5ba7
RR
370 case wxSYS_CAPTION_Y:
371 if (!window)
372 // No realized window specified, and no implementation for that case yet.
373 return -1;
374
9b0b5ba7
RR
375 wxASSERT_MSG( wxDynamicCast(win, wxTopLevelWindow),
376 wxT("Asking for caption height of a non toplevel window") );
377
378 // Get the height of the top windowmanager border.
379 // This is the titlebar in most cases. The titlebar might be elsewhere, and
380 // we could check which is the thickest wm border to decide on which side the
381 // titlebar is, but this might lead to interesting behaviours in used code.
382 // Reconsider when we have a way to report to the user on which side it is.
9b0b5ba7 383 {
37cafc6a 384 int top;
166b4de7 385 if (wxGetFrameExtents(window, NULL, NULL, &top, NULL))
9b0b5ba7 386 {
37cafc6a 387 return top; // top frame extent
9b0b5ba7 388 }
9b0b5ba7
RR
389 }
390
391 // Try a default approach without a window pointer, if possible
392 // ...
393
394 return -1;
9b0b5ba7
RR
395
396 case wxSYS_PENWINDOWS_PRESENT:
397 // No MS Windows for Pen computing extension available in X11 based gtk+.
398 return 0;
399
400 default:
1d451c5b 401 return -1; // metric is unknown
1ecc4d80 402 }
c67daf87 403}
253293c1 404
0ab5e0e8 405bool wxSystemSettingsNative::HasFeature(wxSystemFeature index)
253293c1
VS
406{
407 switch (index)
408 {
17a1ebd1 409 case wxSYS_CAN_ICONIZE_FRAME:
e7c80f9e 410 return false;
17a1ebd1 411
253293c1 412 case wxSYS_CAN_DRAW_FRAME_DECORATIONS:
e7c80f9e 413 return true;
17a1ebd1 414
253293c1 415 default:
e7c80f9e 416 return false;
253293c1
VS
417 }
418}