1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/settings.cpp 
   4 // Author:      Robert Roebling 
   5 // Modified by: Mart Raudsepp (GetMetric) 
   7 // Copyright:   (c) 1998 Robert Roebling 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // For compilers that support precompilation, includes "wx.h". 
  12 #include "wx/wxprec.h" 
  14 #include "wx/settings.h" 
  17     #include "wx/cmndata.h" 
  18     #include "wx/toplevel.h" 
  21 #include "wx/fontutil.h" 
  23 #include <gtk/gtkversion.h> 
  24 #if GTK_CHECK_VERSION(2, 9, 0) 
  26     #undef GTK_DISABLE_DEPRECATED 
  30 bool wxGetFrameExtents(GdkWindow
* window
, int* left
, int* right
, int* top
, int* bottom
); 
  32 // ---------------------------------------------------------------------------- 
  34 // ---------------------------------------------------------------------------- 
  36 struct wxSystemObjects
 
  38     wxColour m_colBtnFace
, 
  47              m_colMenuItemHighlight
, 
  55 static wxSystemObjects gs_objects
; 
  57 void wxClearGtkSystemObjects() 
  59     gs_objects
.m_colBtnFace 
= wxColour(); 
  60     gs_objects
.m_colBtnShadow 
= wxColour(); 
  61     gs_objects
.m_colBtnHighlight 
= wxColour(); 
  62     gs_objects
.m_colHighlightText 
= wxColour(); 
  63     gs_objects
.m_colListBox 
= wxColour(); 
  64     gs_objects
.m_colWindow 
= wxColour(); 
  65     gs_objects
.m_colWindowText 
= wxColour(); 
  66     gs_objects
.m_colBtnText 
= wxColour(); 
  67     gs_objects
.m_colMenuItemHighlight 
= wxColour(); 
  68     gs_objects
.m_colTooltip 
= wxColour(); 
  69     gs_objects
.m_colTooltipText 
= wxColour(); 
  70     gs_objects
.m_colMenubarBg 
= wxColour(); 
  71     gs_objects
.m_fontSystem 
= wxNullFont
; 
  74 // ---------------------------------------------------------------------------- 
  75 // wxSystemSettings implementation 
  76 // ---------------------------------------------------------------------------- 
  78 // kind of widget to use in GetColourFromGTKWidget 
  96 // wxSystemSettings::GetColour() helper: get the colours from a GTK+ 
  97 // widget style, return true if we did get them 
  98 static bool GetColourFromGTKWidget(GdkColor
& gdkColor
, 
  99                                    wxGtkWidgetType type 
= wxGTK_BUTTON
, 
 100                                    GtkStateType state 
= GTK_STATE_NORMAL
, 
 101                                    wxGtkColourType colour 
= wxGTK_BG
) 
 107             wxFAIL_MSG( _T("unexpected GTK widget type") ); 
 111             widget 
= gtk_button_new(); 
 115             widget 
= gtk_text_view_new(); 
 119             widget 
= gtk_tree_view_new_with_model( 
 120                 (GtkTreeModel
*)gtk_list_store_new(1, G_TYPE_INT
)); 
 124             widget 
= gtk_menu_item_new(); 
 128             widget 
= gtk_menu_bar_new(); 
 132     GtkStyle 
*def 
= gtk_rc_get_style( widget 
); 
 134         def 
= gtk_widget_get_default_style(); 
 136     const bool ok 
= def 
!= NULL
; 
 142                 wxFAIL_MSG( _T("unexpected GTK colour type") ); 
 146                 gdkColor 
= def
->fg
[state
]; 
 150                 gdkColor 
= def
->bg
[state
]; 
 154                 gdkColor 
= def
->base
[state
]; 
 159     gtk_object_sink((GtkObject
*)widget
); 
 164 static void GetTooltipColors() 
 166     GtkWidget
* widget 
= gtk_window_new(GTK_WINDOW_POPUP
); 
 167     const char* name 
= "gtk-tooltip"; 
 168     if (gtk_check_version(2, 11, 0)) 
 169         name 
= "gtk-tooltips"; 
 170     gtk_widget_set_name(widget
, name
); 
 171     gtk_widget_ensure_style(widget
); 
 173     GdkColor c 
= widget
->style
->bg
[GTK_STATE_NORMAL
]; 
 174     gs_objects
.m_colTooltip 
= wxColor(c
); 
 175     c 
= widget
->style
->fg
[GTK_STATE_NORMAL
]; 
 176     gs_objects
.m_colTooltipText 
= wxColor(c
); 
 178     gtk_widget_destroy(widget
); 
 181 wxColour 
wxSystemSettingsNative::GetColour( wxSystemColour index 
) 
 187         case wxSYS_COLOUR_SCROLLBAR
: 
 188         case wxSYS_COLOUR_BACKGROUND
: 
 189         case wxSYS_COLOUR_INACTIVECAPTION
: 
 190         case wxSYS_COLOUR_MENU
: 
 191         case wxSYS_COLOUR_WINDOWFRAME
: 
 192         case wxSYS_COLOUR_ACTIVEBORDER
: 
 193         case wxSYS_COLOUR_INACTIVEBORDER
: 
 194         case wxSYS_COLOUR_BTNFACE
: 
 195         case wxSYS_COLOUR_3DLIGHT
: 
 196             if (!gs_objects
.m_colBtnFace
.Ok()) 
 200                 gdkColor
.blue 
= 0x9c40; 
 201                 GetColourFromGTKWidget(gdkColor
); 
 202                 gs_objects
.m_colBtnFace 
= wxColor(gdkColor
); 
 204             color 
= gs_objects
.m_colBtnFace
; 
 207         case wxSYS_COLOUR_WINDOW
: 
 208             if (!gs_objects
.m_colWindow
.Ok()) 
 212                 gdkColor
.blue 
= 0xFFFF; 
 213                 GetColourFromGTKWidget(gdkColor
, wxGTK_TEXTCTRL
, GTK_STATE_NORMAL
, wxGTK_BASE
); 
 214                 gs_objects
.m_colWindow 
= wxColor(gdkColor
); 
 216             color 
= gs_objects
.m_colWindow
; 
 220         case wxSYS_COLOUR_MENUBAR
: 
 221             if (!gs_objects
.m_colMenubarBg
.Ok()) 
 225                 gdkColor
.blue 
= 0x9c40; 
 226                 GetColourFromGTKWidget(gdkColor
,wxGTK_MENUBAR
); 
 227                 gs_objects
.m_colMenubarBg 
= wxColor(gdkColor
); 
 229             color 
= gs_objects
.m_colMenubarBg
; 
 232         case wxSYS_COLOUR_3DDKSHADOW
: 
 236         case wxSYS_COLOUR_GRAYTEXT
: 
 237         case wxSYS_COLOUR_BTNSHADOW
: 
 238         //case wxSYS_COLOUR_3DSHADOW: 
 239             if (!gs_objects
.m_colBtnShadow
.Ok()) 
 241                 wxColour 
faceColour(GetColour(wxSYS_COLOUR_3DFACE
)); 
 242                 gs_objects
.m_colBtnShadow 
= 
 243                    wxColour((unsigned char) (faceColour
.Red() * 2 / 3), 
 244                             (unsigned char) (faceColour
.Green() * 2 / 3), 
 245                             (unsigned char) (faceColour
.Blue() * 2 / 3)); 
 247             color 
= gs_objects
.m_colBtnShadow
; 
 250         case wxSYS_COLOUR_3DHIGHLIGHT
: 
 251         //case wxSYS_COLOUR_BTNHIGHLIGHT: 
 255         case wxSYS_COLOUR_HIGHLIGHT
: 
 256             if (!gs_objects
.m_colHighlight
.Ok()) 
 260                 gdkColor
.blue 
= 0x9c40; 
 261                 GetColourFromGTKWidget( 
 262                     gdkColor
, wxGTK_BUTTON
, GTK_STATE_SELECTED
); 
 263                 gs_objects
.m_colHighlight 
= wxColour(gdkColor
); 
 265             color 
= gs_objects
.m_colHighlight
; 
 268         case wxSYS_COLOUR_LISTBOX
: 
 269             if (!gs_objects
.m_colListBox
.Ok()) 
 271                 if ( GetColourFromGTKWidget(gdkColor
, 
 276                     gs_objects
.m_colListBox 
= wxColour(gdkColor
); 
 280                     gs_objects
.m_colListBox 
= *wxWHITE
; 
 283             color 
= gs_objects
.m_colListBox
; 
 286         case wxSYS_COLOUR_MENUTEXT
: 
 287         case wxSYS_COLOUR_WINDOWTEXT
: 
 288         case wxSYS_COLOUR_CAPTIONTEXT
: 
 289         case wxSYS_COLOUR_INACTIVECAPTIONTEXT
: 
 290         case wxSYS_COLOUR_BTNTEXT
: 
 291             if (!gs_objects
.m_colBtnText
.Ok()) 
 296                 GetColourFromGTKWidget( 
 297                     gdkColor
, wxGTK_BUTTON
, GTK_STATE_NORMAL
, wxGTK_FG
); 
 298                 gs_objects
.m_colBtnText 
= wxColour(gdkColor
); 
 300             color 
= gs_objects
.m_colBtnText
; 
 303         case wxSYS_COLOUR_INFOBK
: 
 304             if (!gs_objects
.m_colTooltip
.Ok()) { 
 307             color 
= gs_objects
.m_colTooltip
; 
 310         case wxSYS_COLOUR_INFOTEXT
: 
 311             if (!gs_objects
.m_colTooltipText
.Ok()) { 
 314             color 
= gs_objects
.m_colTooltipText
; 
 317         case wxSYS_COLOUR_HIGHLIGHTTEXT
: 
 318             if (!gs_objects
.m_colHighlightText
.Ok()) 
 320                 wxColour hclr 
= GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
 321                 if (hclr
.Red() > 200 && hclr
.Green() > 200 && hclr
.Blue() > 200) 
 322                     gs_objects
.m_colHighlightText 
= *wxBLACK
; 
 324                     gs_objects
.m_colHighlightText 
= *wxWHITE
; 
 326             color 
= gs_objects
.m_colHighlightText
; 
 329         case wxSYS_COLOUR_APPWORKSPACE
: 
 330             color 
= *wxWHITE
;    // ? 
 333         case wxSYS_COLOUR_ACTIVECAPTION
: 
 334         case wxSYS_COLOUR_MENUHILIGHT
: 
 335             if (!gs_objects
.m_colMenuItemHighlight
.Ok()) 
 340                 GetColourFromGTKWidget( 
 341                     gdkColor
, wxGTK_MENUITEM
, GTK_STATE_SELECTED
, wxGTK_BG
); 
 342                 gs_objects
.m_colMenuItemHighlight 
= wxColour(gdkColor
); 
 344             color 
= gs_objects
.m_colMenuItemHighlight
; 
 347         case wxSYS_COLOUR_HOTLIGHT
: 
 348         case wxSYS_COLOUR_GRADIENTACTIVECAPTION
: 
 349         case wxSYS_COLOUR_GRADIENTINACTIVECAPTION
: 
 354         case wxSYS_COLOUR_MAX
: 
 356             wxFAIL_MSG( _T("unknown system colour index") ); 
 364 wxFont 
wxSystemSettingsNative::GetFont( wxSystemFont index 
) 
 369         case wxSYS_OEM_FIXED_FONT
: 
 370         case wxSYS_ANSI_FIXED_FONT
: 
 371         case wxSYS_SYSTEM_FIXED_FONT
: 
 372             font 
= *wxNORMAL_FONT
; 
 375         case wxSYS_ANSI_VAR_FONT
: 
 376         case wxSYS_SYSTEM_FONT
: 
 377         case wxSYS_DEVICE_DEFAULT_FONT
: 
 378         case wxSYS_DEFAULT_GUI_FONT
: 
 379             if (!gs_objects
.m_fontSystem
.Ok()) 
 381                 GtkWidget 
*widget 
= gtk_button_new(); 
 382                 GtkStyle 
*def 
= gtk_rc_get_style( widget 
); 
 383                 if ( !def 
|| !def
->font_desc 
) 
 384                     def 
= gtk_widget_get_default_style(); 
 385                 if ( def 
&& def
->font_desc 
) 
 387                     wxNativeFontInfo info
; 
 389                         pango_font_description_copy(def
->font_desc
); 
 390                     gs_objects
.m_fontSystem 
= wxFont(info
); 
 394                     GtkSettings 
*settings 
= gtk_settings_get_default(); 
 395                     gchar 
*font_name 
= NULL
; 
 396                     g_object_get ( settings
, 
 401                         gs_objects
.m_fontSystem 
= wxFont( 12, wxSWISS
, wxNORMAL
, wxNORMAL 
); 
 403                         gs_objects
.m_fontSystem 
= wxFont(wxString::FromAscii(font_name
)); 
 406                 gtk_object_sink((GtkObject
*)widget
); 
 408             font 
= gs_objects
.m_fontSystem
; 
 417 // helper: return the GtkSettings either for the screen the current window is 
 418 // on or for the default screen if window is NULL 
 419 static GtkSettings 
*GetSettingsForWindowScreen(GdkWindow 
*window
) 
 421     return window 
? gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)) 
 422                   : gtk_settings_get_default(); 
 425 int wxSystemSettingsNative::GetMetric( wxSystemMetric index
, wxWindow
* win 
) 
 427     GdkWindow 
*window 
= NULL
; 
 428     if(win 
&& GTK_WIDGET_REALIZED(win
->GetHandle())) 
 429         window 
= win
->GetHandle()->window
; 
 437         case wxSYS_FRAMESIZE_X
: 
 438         case wxSYS_FRAMESIZE_Y
: 
 439             // If a window is specified/realized, and it is a toplevel window, we can query from wm. 
 440             // The returned border thickness is outside the client area in that case. 
 443                 wxTopLevelWindow 
*tlw 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 445                     return -1; // not a tlw, not sure how to approach 
 448                     // Get the frame extents from the windowmanager. 
 449                     // In most cases the top extent is the titlebar, so we use the bottom extent 
 452                     if (wxGetFrameExtents(window
, NULL
, &right
, NULL
, &bottom
)) 
 458                             case wxSYS_FRAMESIZE_X
: 
 459                                 return right
; // width of right extent 
 461                                 return bottom
; // height of bottom extent 
 467             return -1; // no window specified 
 471                 return gdk_display_get_default_cursor_size( 
 472                             window 
? gdk_drawable_get_display(window
) 
 473                                    : gdk_display_get_default()); 
 477             gint dclick_distance
; 
 478             g_object_get(GetSettingsForWindowScreen(window
), 
 479                             "gtk-double-click-distance", &dclick_distance
, NULL
); 
 481             return dclick_distance 
* 2; 
 483         case wxSYS_DCLICK_MSEC
: 
 485             g_object_get(GetSettingsForWindowScreen(window
), 
 486                             "gtk-double-click-time", &dclick
, NULL
); 
 492             g_object_get(GetSettingsForWindowScreen(window
), 
 493                             "gtk-dnd-drag-threshold", &drag_threshold
, NULL
); 
 495             // The correct thing here would be to double the value 
 496             // since that is what the API wants. But the values 
 497             // are much bigger under GNOME than under Windows and 
 498             // just seem to much in many cases to be useful. 
 499             // drag_threshold *= 2; 
 501             return drag_threshold
; 
 509                 return gdk_screen_get_width(gdk_drawable_get_screen(window
)); 
 511                 return gdk_screen_width(); 
 515                 return gdk_screen_get_height(gdk_drawable_get_screen(window
)); 
 517                 return gdk_screen_height(); 
 519         case wxSYS_HSCROLL_Y
: 
 520         case wxSYS_VSCROLL_X
: 
 523         case wxSYS_CAPTION_Y
: 
 525                 // No realized window specified, and no implementation for that case yet. 
 528             wxASSERT_MSG( wxDynamicCast(win
, wxTopLevelWindow
), 
 529                           wxT("Asking for caption height of a non toplevel window") ); 
 531             // Get the height of the top windowmanager border. 
 532             // This is the titlebar in most cases. The titlebar might be elsewhere, and 
 533             // we could check which is the thickest wm border to decide on which side the 
 534             // titlebar is, but this might lead to interesting behaviours in used code. 
 535             // Reconsider when we have a way to report to the user on which side it is. 
 538                 if (wxGetFrameExtents(window
, NULL
, NULL
, &top
, NULL
)) 
 540                     return top
; // top frame extent 
 544             // Try a default approach without a window pointer, if possible 
 549         case wxSYS_PENWINDOWS_PRESENT
: 
 550             // No MS Windows for Pen computing extension available in X11 based gtk+. 
 554             return -1;   // metric is unknown 
 558 bool wxSystemSettingsNative::HasFeature(wxSystemFeature index
) 
 562         case wxSYS_CAN_ICONIZE_FRAME
: 
 565         case wxSYS_CAN_DRAW_FRAME_DECORATIONS
: