1///////////////////////////////////////////////////////////////////////////// 2// Name: src/gtk1/settings.cpp 3// Purpose: 4// Author: Robert Roebling 5// Modified by: Mart Raudsepp (GetMetric) 6// Id: $Id: settings.cpp 67017 2011-02-25 09:37:28Z JS $ 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 36struct 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 52static wxSystemObjects gs_objects; 53 54// ---------------------------------------------------------------------------- 55// wxSystemSettings implementation 56// ---------------------------------------------------------------------------- 57 58// kind of widget to use in GetColourFromGTKWidget 59enum wxGtkWidgetType 60{ 61 wxGTK_BUTTON, 62 wxGTK_LIST, 63 wxGTK_MENUITEM 64}; 65 66// the colour we need 67enum 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 76static 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 143static 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 155wxColour 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 case wxSYS_COLOUR_LISTBOXTEXT: 254 if (!gs_objects.m_colBtnText.Ok()) 255 { 256 int red, green, blue; 257 if ( !GetColourFromGTKWidget(red, green, blue, 258 wxGTK_BUTTON, 259 GTK_STATE_NORMAL, 260 wxGTK_FG) ) 261 { 262 red = 263 green = 264 blue = 0; 265 } 266 267 gs_objects.m_colBtnText = wxColour( red >> SHIFT, 268 green >> SHIFT, 269 blue >> SHIFT ); 270 } 271 return gs_objects.m_colBtnText; 272 273 case wxSYS_COLOUR_INFOBK: 274 if (!gs_objects.m_colTooltip.Ok()) { 275 GetTooltipColors(); 276 } 277 return gs_objects.m_colTooltip; 278 279 case wxSYS_COLOUR_INFOTEXT: 280 if (!gs_objects.m_colTooltipText.Ok()) { 281 GetTooltipColors(); 282 } 283 return gs_objects.m_colTooltipText; 284 285 case wxSYS_COLOUR_HIGHLIGHTTEXT: 286 case wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT: 287 if (!gs_objects.m_colHighlightText.Ok()) 288 { 289 wxColour hclr = GetColour(wxSYS_COLOUR_HIGHLIGHT); 290 if (hclr.Red() > 200 && hclr.Green() > 200 && hclr.Blue() > 200) 291 gs_objects.m_colHighlightText = wxColour(*wxBLACK); 292 else 293 gs_objects.m_colHighlightText = wxColour(*wxWHITE); 294 } 295 return gs_objects.m_colHighlightText; 296 297 case wxSYS_COLOUR_APPWORKSPACE: 298 return *wxWHITE; // ? 299 300 case wxSYS_COLOUR_ACTIVECAPTION: 301 case wxSYS_COLOUR_MENUHILIGHT: 302 if (!gs_objects.m_colMenuItemHighlight.Ok()) 303 { 304 int red, green, blue; 305 if ( !GetColourFromGTKWidget(red, green, blue, 306 wxGTK_MENUITEM, 307 GTK_STATE_SELECTED, 308 wxGTK_BG) ) 309 { 310 red = 311 green = 312 blue = 0; 313 } 314 315 gs_objects.m_colMenuItemHighlight = wxColour( red >> SHIFT, 316 green >> SHIFT, 317 blue >> SHIFT ); 318 } 319 return gs_objects.m_colMenuItemHighlight; 320 321 case wxSYS_COLOUR_HOTLIGHT: 322 case wxSYS_COLOUR_GRADIENTACTIVECAPTION: 323 case wxSYS_COLOUR_GRADIENTINACTIVECAPTION: 324 // TODO 325 return *wxBLACK; 326 327 case wxSYS_COLOUR_MAX: 328 default: 329 wxFAIL_MSG( _T("unknown system colour index") ); 330 } 331 332 return *wxWHITE; 333} 334 335wxFont wxSystemSettingsNative::GetFont( wxSystemFont index ) 336{ 337 switch (index) 338 { 339 case wxSYS_OEM_FIXED_FONT: 340 case wxSYS_ANSI_FIXED_FONT: 341 case wxSYS_SYSTEM_FIXED_FONT: 342 { 343 return *wxNORMAL_FONT; 344 } 345 case wxSYS_ANSI_VAR_FONT: 346 case wxSYS_SYSTEM_FONT: 347 case wxSYS_DEVICE_DEFAULT_FONT: 348 case wxSYS_DEFAULT_GUI_FONT: 349 { 350 if (!gs_objects.m_fontSystem.Ok()) 351 { 352 gs_objects.m_fontSystem = wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL ); 353 } 354 return gs_objects.m_fontSystem; 355 } 356 357 default: 358 return wxNullFont; 359 } 360} 361 362int wxSystemSettingsNative::GetMetric( wxSystemMetric index, wxWindow* win ) 363{ 364 switch (index) 365 { 366 case wxSYS_CURSOR_X: 367 case wxSYS_CURSOR_Y: 368 return 16; 369 370 // MBN: ditto for icons 371 case wxSYS_ICON_X: return 32; 372 case wxSYS_ICON_Y: return 32; 373 374 case wxSYS_SCREEN_X: 375 return gdk_screen_width(); 376 377 case wxSYS_SCREEN_Y: 378 return gdk_screen_height(); 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 384#if 0 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; 418 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)), 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 433 ) == Success); 434 } 435#endif 436 if (success) 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: 464 return -1; // metric is unknown 465 } 466} 467 468bool wxSystemSettingsNative::HasFeature(wxSystemFeature index) 469{ 470 switch (index) 471 { 472 case wxSYS_CAN_ICONIZE_FRAME: 473 return false; 474 475 case wxSYS_CAN_DRAW_FRAME_DECORATIONS: 476 return true; 477 478 default: 479 return false; 480 } 481} 482