1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        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" 
  16 #include "wx/cmndata.h" 
  17 #include "wx/fontutil.h" 
  18 #include "wx/toplevel.h" 
  20 // Using gtk_list_new, which is deprecated since GTK2 
  21 // Using gtk_object_sink, which is deprecated since GTK+-2.9.0 
  22 #ifdef GTK_DISABLE_DEPRECATED 
  23 #undef GTK_DISABLE_DEPRECATED 
  28 #include <gdk/gdkprivate.h> 
  31 #include <X11/Xatom.h> 
  33 #define SHIFT (8*(sizeof(short int)-sizeof(char))) 
  35 // ---------------------------------------------------------------------------- 
  37 // ---------------------------------------------------------------------------- 
  39 struct wxSystemObjects
 
  41     wxColour m_colBtnFace
, 
  48              m_colMenuItemHighlight
, 
  55 static wxSystemObjects gs_objects
; 
  57 // ---------------------------------------------------------------------------- 
  58 // wxSystemSettings implementation 
  59 // ---------------------------------------------------------------------------- 
  61 // kind of widget to use in GetColourFromGTKWidget 
  77 // wxSystemSettings::GetColour() helper: get the colours from a GTK+ 
  78 // widget style, return true if we did get them, false to use defaults 
  79 static bool GetColourFromGTKWidget(int& red
, int& green
, int& blue
, 
  80                                    wxGtkWidgetType type 
= wxGTK_BUTTON
, 
  81                                    GtkStateType state 
= GTK_STATE_NORMAL
, 
  82                                    wxGtkColourType colour 
= wxGTK_BG
) 
  88             wxFAIL_MSG( _T("unexpected GTK widget type") ); 
  92             widget 
= gtk_button_new(); 
  96             widget 
= gtk_list_new(); 
 100             widget 
= gtk_menu_item_new(); 
 103     GtkStyle 
*def 
= gtk_rc_get_style( widget 
); 
 105         def 
= gtk_widget_get_default_style(); 
 114                 wxFAIL_MSG( _T("unexpected GTK colour type") ); 
 130         red 
= col
[state
].red
; 
 131         green 
= col
[state
].green
; 
 132         blue 
= col
[state
].blue
; 
 141     gtk_widget_destroy( widget 
); 
 146 static void GetTooltipColors() 
 148     GtkTooltips
* tooltips 
= gtk_tooltips_new(); 
 149     gtk_tooltips_force_window(tooltips
); 
 150     gtk_widget_ensure_style(tooltips
->tip_window
); 
 151     GdkColor c 
= tooltips
->tip_window
->style
->bg
[GTK_STATE_NORMAL
]; 
 152     gs_objects
.m_colTooltip 
= wxColor(c
.red 
>> SHIFT
, c
.green 
>> SHIFT
, c
.blue 
>> SHIFT
); 
 153     c 
= tooltips
->tip_window
->style
->fg
[GTK_STATE_NORMAL
]; 
 154     gs_objects
.m_colTooltipText 
= wxColor(c
.red 
>> SHIFT
, c
.green 
>> SHIFT
, c
.blue 
>> SHIFT
); 
 155     gtk_object_sink(wx_reinterpret_cast(GtkObject
*, tooltips
)); 
 158 wxColour 
wxSystemSettingsNative::GetColour( wxSystemColour index 
) 
 162         case wxSYS_COLOUR_SCROLLBAR
: 
 163         case wxSYS_COLOUR_BACKGROUND
: 
 164         case wxSYS_COLOUR_INACTIVECAPTION
: 
 165         case wxSYS_COLOUR_MENU
: 
 166         case wxSYS_COLOUR_WINDOWFRAME
: 
 167         case wxSYS_COLOUR_ACTIVEBORDER
: 
 168         case wxSYS_COLOUR_INACTIVEBORDER
: 
 169         case wxSYS_COLOUR_BTNFACE
: 
 170         case wxSYS_COLOUR_MENUBAR
: 
 171         case wxSYS_COLOUR_3DLIGHT
: 
 172             if (!gs_objects
.m_colBtnFace
.Ok()) 
 174                 int red
, green
, blue
; 
 175                 if ( !GetColourFromGTKWidget(red
, green
, blue
) ) 
 182                 gs_objects
.m_colBtnFace 
= wxColour( red   
>> SHIFT
, 
 186             return gs_objects
.m_colBtnFace
; 
 188         case wxSYS_COLOUR_WINDOW
: 
 191         case wxSYS_COLOUR_3DDKSHADOW
: 
 194         case wxSYS_COLOUR_GRAYTEXT
: 
 195         case wxSYS_COLOUR_BTNSHADOW
: 
 196         //case wxSYS_COLOUR_3DSHADOW: 
 197             if (!gs_objects
.m_colBtnShadow
.Ok()) 
 199                 wxColour 
faceColour(GetColour(wxSYS_COLOUR_3DFACE
)); 
 200                 gs_objects
.m_colBtnShadow 
= 
 201                    wxColour((unsigned char) (faceColour
.Red() * 0.666), 
 202                             (unsigned char) (faceColour
.Green() * 0.666), 
 203                             (unsigned char) (faceColour
.Blue() * 0.666)); 
 206             return gs_objects
.m_colBtnShadow
; 
 208         case wxSYS_COLOUR_3DHIGHLIGHT
: 
 209         //case wxSYS_COLOUR_BTNHIGHLIGHT: 
 212         case wxSYS_COLOUR_HIGHLIGHT
: 
 213             if (!gs_objects
.m_colHighlight
.Ok()) 
 215                 int red
, green
, blue
; 
 216                 if ( !GetColourFromGTKWidget(red
, green
, blue
, 
 218                                              GTK_STATE_SELECTED
) ) 
 225                 gs_objects
.m_colHighlight 
= wxColour( red   
>> SHIFT
, 
 229             return gs_objects
.m_colHighlight
; 
 231         case wxSYS_COLOUR_LISTBOX
: 
 232             if (!gs_objects
.m_colListBox
.Ok()) 
 234                 int red
, green
, blue
; 
 235                 if ( GetColourFromGTKWidget(red
, green
, blue
, 
 240                     gs_objects
.m_colListBox 
= wxColour( red   
>> SHIFT
, 
 246                     gs_objects
.m_colListBox 
= wxColour(*wxWHITE
); 
 249             return gs_objects
.m_colListBox
; 
 251         case wxSYS_COLOUR_MENUTEXT
: 
 252         case wxSYS_COLOUR_WINDOWTEXT
: 
 253         case wxSYS_COLOUR_CAPTIONTEXT
: 
 254         case wxSYS_COLOUR_INACTIVECAPTIONTEXT
: 
 255         case wxSYS_COLOUR_BTNTEXT
: 
 256             if (!gs_objects
.m_colBtnText
.Ok()) 
 258                 int red
, green
, blue
; 
 259                 if ( !GetColourFromGTKWidget(red
, green
, blue
, 
 269                 gs_objects
.m_colBtnText 
= wxColour( red   
>> SHIFT
, 
 273             return gs_objects
.m_colBtnText
; 
 275         case wxSYS_COLOUR_INFOBK
: 
 276             if (!gs_objects
.m_colTooltip
.Ok()) { 
 279             return gs_objects
.m_colTooltip
; 
 281         case wxSYS_COLOUR_INFOTEXT
: 
 282             if (!gs_objects
.m_colTooltipText
.Ok()) { 
 285             return gs_objects
.m_colTooltipText
; 
 287         case wxSYS_COLOUR_HIGHLIGHTTEXT
: 
 288             if (!gs_objects
.m_colHighlightText
.Ok()) 
 290                 wxColour hclr 
= GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
 291                 if (hclr
.Red() > 200 && hclr
.Green() > 200 && hclr
.Blue() > 200) 
 292                     gs_objects
.m_colHighlightText 
= wxColour(*wxBLACK
); 
 294                     gs_objects
.m_colHighlightText 
= wxColour(*wxWHITE
); 
 296             return gs_objects
.m_colHighlightText
; 
 298         case wxSYS_COLOUR_APPWORKSPACE
: 
 299             return *wxWHITE
;    // ? 
 301         case wxSYS_COLOUR_ACTIVECAPTION
: 
 302         case wxSYS_COLOUR_MENUHILIGHT
: 
 303             if (!gs_objects
.m_colMenuItemHighlight
.Ok()) 
 305                 int red
, green
, blue
; 
 306                 if ( !GetColourFromGTKWidget(red
, green
, blue
, 
 316                 gs_objects
.m_colMenuItemHighlight 
= wxColour( red  
>> SHIFT
, 
 320             return gs_objects
.m_colMenuItemHighlight
; 
 322         case wxSYS_COLOUR_HOTLIGHT
: 
 323         case wxSYS_COLOUR_GRADIENTACTIVECAPTION
: 
 324         case wxSYS_COLOUR_GRADIENTINACTIVECAPTION
: 
 328         case wxSYS_COLOUR_MAX
: 
 330             wxFAIL_MSG( _T("unknown system colour index") ); 
 336 wxFont 
wxSystemSettingsNative::GetFont( wxSystemFont index 
) 
 340         case wxSYS_OEM_FIXED_FONT
: 
 341         case wxSYS_ANSI_FIXED_FONT
: 
 342         case wxSYS_SYSTEM_FIXED_FONT
: 
 344             return *wxNORMAL_FONT
; 
 346         case wxSYS_ANSI_VAR_FONT
: 
 347         case wxSYS_SYSTEM_FONT
: 
 348         case wxSYS_DEVICE_DEFAULT_FONT
: 
 349         case wxSYS_DEFAULT_GUI_FONT
: 
 351             if (!gs_objects
.m_fontSystem
.Ok()) 
 353                 GtkWidget 
*widget 
= gtk_button_new(); 
 354                 GtkStyle 
*def 
= gtk_rc_get_style( widget 
); 
 355                 if ( !def 
|| !def
->font_desc 
) 
 356                     def 
= gtk_widget_get_default_style(); 
 357                 if ( def 
&& def
->font_desc 
) 
 359                     wxNativeFontInfo info
; 
 361                         pango_font_description_copy(def
->font_desc
); 
 362                     gs_objects
.m_fontSystem 
= wxFont(info
); 
 366                     GtkSettings 
*settings 
= gtk_settings_get_default(); 
 367                     gchar 
*font_name 
= NULL
; 
 368                     g_object_get ( settings
, 
 373                         gs_objects
.m_fontSystem 
= wxFont( 12, wxSWISS
, wxNORMAL
, wxNORMAL 
); 
 375                         gs_objects
.m_fontSystem 
= wxFont(wxString::FromAscii(font_name
)); 
 378                 gtk_widget_destroy( widget 
); 
 380             return gs_objects
.m_fontSystem
; 
 388 int wxSystemSettingsNative::GetMetric( wxSystemMetric index
, wxWindow
* win 
) 
 390     bool success 
= false; 
 393     GdkWindow 
*window 
= NULL
; 
 394     if(win 
&& GTK_WIDGET_REALIZED(win
->GetHandle())) 
 395         window 
= win
->GetHandle()->window
; 
 403         case wxSYS_FRAMESIZE_X
: 
 404         case wxSYS_FRAMESIZE_Y
: 
 405             // If a window is specified/realized, and it is a toplevel window, we can query from wm. 
 406             // The returned border thickness is outside the client area in that case. 
 409                 wxTopLevelWindow 
*tlw 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 411                     return -1; // not a tlw, not sure how to approach 
 414                     // Check if wm supports frame extents - we can't know 
 415                     // the border widths if it does not. 
 416 #if GTK_CHECK_VERSION(2,2,0) 
 417                     if (!gtk_check_version(2,2,0)) 
 419                         if (!gdk_x11_screen_supports_net_wm_hint( 
 420                                 gdk_drawable_get_screen(window
), 
 421                                 gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) ) 
 427                         if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false))) 
 431                     // Get the frame extents from the windowmanager. 
 432                     // In most cases the top extent is the titlebar, so we use the bottom extent 
 439 #if GTK_CHECK_VERSION(2,2,0) 
 440                     if (!gtk_check_version(2,2,0)) 
 443                         success 
= (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window
)), 
 444                                             GDK_WINDOW_XWINDOW(window
), 
 445                                             gdk_x11_get_xatom_by_name_for_display ( 
 446                                                     gdk_drawable_get_display(window
), 
 447                                                     "_NET_FRAME_EXTENTS" ), 
 448                                             0, // left, right, top, bottom, CARDINAL[4]/32 
 449                                             G_MAXLONG
, // size of long 
 450                                             false, // do not delete property 
 451                                             XA_CARDINAL
, // 32 bit 
 452                                             &type
, &format
, &nitems
, &bytes_after
, &data
 
 458                         int border_return 
= -1; 
 460                         if ((type 
== XA_CARDINAL
) && (format 
== 32) && (nitems 
>= 4) && (data
)) 
 463                             borders 
= (long*)data
; 
 468                                 case wxSYS_FRAMESIZE_X
: 
 469                                     border_return 
= borders
[1]; // width of right extent 
 472                                     border_return 
= borders
[3]; // height of bottom extent 
 480                         return border_return
; 
 485             return -1; // no window specified 
 490             if (!gtk_check_version(2,4,0)) 
 493                     return gdk_display_get_default_cursor_size(gdk_drawable_get_display(window
)); 
 495                     return gdk_display_get_default_cursor_size(gdk_display_get_default()); 
 503             gint dclick_distance
; 
 504 #if GTK_CHECK_VERSION(2,2,0) 
 505             if (window 
&& !gtk_check_version(2,2,0)) 
 506                 g_object_get(gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)), 
 507                                 "gtk-double-click-distance", &dclick_distance
, NULL
); 
 510                 g_object_get(gtk_settings_get_default(), 
 511                                 "gtk-double-click-distance", &dclick_distance
, NULL
); 
 513             return dclick_distance 
* 2; 
 518 #if GTK_CHECK_VERSION(2,2,0) 
 519             if (window 
&& !gtk_check_version(2,2,0)) 
 522                         gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)), 
 523                         "gtk-dnd-drag-threshold", 
 524                         &drag_threshold
, NULL
); 
 529                 g_object_get(gtk_settings_get_default(), 
 530                              "gtk-dnd-drag-threshold", &drag_threshold
, NULL
); 
 533             return drag_threshold 
* 2; 
 535         // MBN: ditto for icons 
 536         case wxSYS_ICON_X
:     return 32; 
 537         case wxSYS_ICON_Y
:     return 32; 
 540 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,2,0) 
 541             if (window 
&& !gtk_check_version(2,2,0)) 
 542                 return gdk_screen_get_width(gdk_drawable_get_screen(window
)); 
 545                 return gdk_screen_width(); 
 548 #if defined(__WXGTK20__) && GTK_CHECK_VERSION(2,2,0) 
 549             if (window 
&& !gtk_check_version(2,2,0)) 
 550                 return gdk_screen_get_height(gdk_drawable_get_screen(window
)); 
 553                 return gdk_screen_height(); 
 555         case wxSYS_HSCROLL_Y
:  return 15; 
 556         case wxSYS_VSCROLL_X
:  return 15; 
 558         case wxSYS_CAPTION_Y
: 
 560                 // No realized window specified, and no implementation for that case yet. 
 563             // Check if wm supports frame extents - we can't know the caption height if it does not. 
 564 #if GTK_CHECK_VERSION(2,2,0) 
 565             if (!gtk_check_version(2,2,0)) 
 567                 if (!gdk_x11_screen_supports_net_wm_hint( 
 568                         gdk_drawable_get_screen(window
), 
 569                         gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) ) 
 575                 if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false))) 
 579             wxASSERT_MSG( wxDynamicCast(win
, wxTopLevelWindow
), 
 580                           wxT("Asking for caption height of a non toplevel window") ); 
 582             // Get the height of the top windowmanager border. 
 583             // This is the titlebar in most cases. The titlebar might be elsewhere, and 
 584             // we could check which is the thickest wm border to decide on which side the 
 585             // titlebar is, but this might lead to interesting behaviours in used code. 
 586             // Reconsider when we have a way to report to the user on which side it is. 
 592 #if GTK_CHECK_VERSION(2,2,0) 
 593             if (!gtk_check_version(2,2,0)) 
 596                 success 
= (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window
)), 
 597                                     GDK_WINDOW_XWINDOW(window
), 
 598                                     gdk_x11_get_xatom_by_name_for_display ( 
 599                                             gdk_drawable_get_display(window
), 
 600                                             "_NET_FRAME_EXTENTS" ), 
 601                                     0, // left, right, top, bottom, CARDINAL[4]/32 
 602                                     G_MAXLONG
, // size of long 
 603                                     false, // do not delete property 
 604                                     XA_CARDINAL
, // 32 bit 
 605                                     &type
, &format
, &nitems
, &bytes_after
, &data
 
 611                 int caption_height 
= -1; 
 613                 if ((type 
== XA_CARDINAL
) && (format 
== 32) && (nitems 
>= 3) && (data
)) 
 616                     borders 
= (long*)data
; 
 617                     caption_height 
= borders
[2]; // top frame extent 
 623                 return caption_height
; 
 626             // Try a default approach without a window pointer, if possible 
 631         case wxSYS_PENWINDOWS_PRESENT
: 
 632             // No MS Windows for Pen computing extension available in X11 based gtk+. 
 636             return -1;   // metric is unknown 
 640 bool wxSystemSettingsNative::HasFeature(wxSystemFeature index
) 
 644         case wxSYS_CAN_ICONIZE_FRAME
: 
 647         case wxSYS_CAN_DRAW_FRAME_DECORATIONS
: