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 // Using gtk_list_new, which is deprecated since GTK2 
  24 // Using gtk_object_sink, which is deprecated since GTK+-2.9.0 
  25 #ifdef GTK_DISABLE_DEPRECATED 
  26 #undef GTK_DISABLE_DEPRECATED 
  31 #include <gdk/gdkprivate.h> 
  34 #include <X11/Xatom.h> 
  36 #define SHIFT (8*(sizeof(short int)-sizeof(char))) 
  38 // ---------------------------------------------------------------------------- 
  40 // ---------------------------------------------------------------------------- 
  42 struct wxSystemObjects
 
  44     wxColour m_colBtnFace
, 
  51              m_colMenuItemHighlight
, 
  58 static wxSystemObjects gs_objects
; 
  60 // ---------------------------------------------------------------------------- 
  61 // wxSystemSettings implementation 
  62 // ---------------------------------------------------------------------------- 
  64 // kind of widget to use in GetColourFromGTKWidget 
  80 // wxSystemSettings::GetColour() helper: get the colours from a GTK+ 
  81 // widget style, return true if we did get them, false to use defaults 
  82 static bool GetColourFromGTKWidget(int& red
, int& green
, int& blue
, 
  83                                    wxGtkWidgetType type 
= wxGTK_BUTTON
, 
  84                                    GtkStateType state 
= GTK_STATE_NORMAL
, 
  85                                    wxGtkColourType colour 
= wxGTK_BG
) 
  91             wxFAIL_MSG( _T("unexpected GTK widget type") ); 
  95             widget 
= gtk_button_new(); 
  99             widget 
= gtk_list_new(); 
 103             widget 
= gtk_menu_item_new(); 
 106     GtkStyle 
*def 
= gtk_rc_get_style( widget 
); 
 108         def 
= gtk_widget_get_default_style(); 
 117                 wxFAIL_MSG( _T("unexpected GTK colour type") ); 
 133         red 
= col
[state
].red
; 
 134         green 
= col
[state
].green
; 
 135         blue 
= col
[state
].blue
; 
 144     gtk_widget_destroy( widget 
); 
 149 static void GetTooltipColors() 
 151     GtkTooltips
* tooltips 
= gtk_tooltips_new(); 
 152     gtk_tooltips_force_window(tooltips
); 
 153     gtk_widget_ensure_style(tooltips
->tip_window
); 
 154     GdkColor c 
= tooltips
->tip_window
->style
->bg
[GTK_STATE_NORMAL
]; 
 155     gs_objects
.m_colTooltip 
= wxColor(c
.red 
>> SHIFT
, c
.green 
>> SHIFT
, c
.blue 
>> SHIFT
); 
 156     c 
= tooltips
->tip_window
->style
->fg
[GTK_STATE_NORMAL
]; 
 157     gs_objects
.m_colTooltipText 
= wxColor(c
.red 
>> SHIFT
, c
.green 
>> SHIFT
, c
.blue 
>> SHIFT
); 
 158     gtk_object_sink(wx_reinterpret_cast(GtkObject
*, tooltips
)); 
 161 wxColour 
wxSystemSettingsNative::GetColour( wxSystemColour index 
) 
 165         case wxSYS_COLOUR_SCROLLBAR
: 
 166         case wxSYS_COLOUR_BACKGROUND
: 
 167         case wxSYS_COLOUR_INACTIVECAPTION
: 
 168         case wxSYS_COLOUR_MENU
: 
 169         case wxSYS_COLOUR_WINDOWFRAME
: 
 170         case wxSYS_COLOUR_ACTIVEBORDER
: 
 171         case wxSYS_COLOUR_INACTIVEBORDER
: 
 172         case wxSYS_COLOUR_BTNFACE
: 
 173         case wxSYS_COLOUR_MENUBAR
: 
 174         case wxSYS_COLOUR_3DLIGHT
: 
 175             if (!gs_objects
.m_colBtnFace
.Ok()) 
 177                 int red
, green
, blue
; 
 178                 if ( !GetColourFromGTKWidget(red
, green
, blue
) ) 
 185                 gs_objects
.m_colBtnFace 
= wxColour( red   
>> SHIFT
, 
 189             return gs_objects
.m_colBtnFace
; 
 191         case wxSYS_COLOUR_WINDOW
: 
 194         case wxSYS_COLOUR_3DDKSHADOW
: 
 197         case wxSYS_COLOUR_GRAYTEXT
: 
 198         case wxSYS_COLOUR_BTNSHADOW
: 
 199         //case wxSYS_COLOUR_3DSHADOW: 
 200             if (!gs_objects
.m_colBtnShadow
.Ok()) 
 202                 wxColour 
faceColour(GetColour(wxSYS_COLOUR_3DFACE
)); 
 203                 gs_objects
.m_colBtnShadow 
= 
 204                    wxColour((unsigned char) (faceColour
.Red() * 0.666), 
 205                             (unsigned char) (faceColour
.Green() * 0.666), 
 206                             (unsigned char) (faceColour
.Blue() * 0.666)); 
 209             return gs_objects
.m_colBtnShadow
; 
 211         case wxSYS_COLOUR_3DHIGHLIGHT
: 
 212         //case wxSYS_COLOUR_BTNHIGHLIGHT: 
 215         case wxSYS_COLOUR_HIGHLIGHT
: 
 216             if (!gs_objects
.m_colHighlight
.Ok()) 
 218                 int red
, green
, blue
; 
 219                 if ( !GetColourFromGTKWidget(red
, green
, blue
, 
 221                                              GTK_STATE_SELECTED
) ) 
 228                 gs_objects
.m_colHighlight 
= wxColour( red   
>> SHIFT
, 
 232             return gs_objects
.m_colHighlight
; 
 234         case wxSYS_COLOUR_LISTBOX
: 
 235             if (!gs_objects
.m_colListBox
.Ok()) 
 237                 int red
, green
, blue
; 
 238                 if ( GetColourFromGTKWidget(red
, green
, blue
, 
 243                     gs_objects
.m_colListBox 
= wxColour( red   
>> SHIFT
, 
 249                     gs_objects
.m_colListBox 
= wxColour(*wxWHITE
); 
 252             return gs_objects
.m_colListBox
; 
 254         case wxSYS_COLOUR_MENUTEXT
: 
 255         case wxSYS_COLOUR_WINDOWTEXT
: 
 256         case wxSYS_COLOUR_CAPTIONTEXT
: 
 257         case wxSYS_COLOUR_INACTIVECAPTIONTEXT
: 
 258         case wxSYS_COLOUR_BTNTEXT
: 
 259             if (!gs_objects
.m_colBtnText
.Ok()) 
 261                 int red
, green
, blue
; 
 262                 if ( !GetColourFromGTKWidget(red
, green
, blue
, 
 272                 gs_objects
.m_colBtnText 
= wxColour( red   
>> SHIFT
, 
 276             return gs_objects
.m_colBtnText
; 
 278         case wxSYS_COLOUR_INFOBK
: 
 279             if (!gs_objects
.m_colTooltip
.Ok()) { 
 282             return gs_objects
.m_colTooltip
; 
 284         case wxSYS_COLOUR_INFOTEXT
: 
 285             if (!gs_objects
.m_colTooltipText
.Ok()) { 
 288             return gs_objects
.m_colTooltipText
; 
 290         case wxSYS_COLOUR_HIGHLIGHTTEXT
: 
 291             if (!gs_objects
.m_colHighlightText
.Ok()) 
 293                 wxColour hclr 
= GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
 294                 if (hclr
.Red() > 200 && hclr
.Green() > 200 && hclr
.Blue() > 200) 
 295                     gs_objects
.m_colHighlightText 
= wxColour(*wxBLACK
); 
 297                     gs_objects
.m_colHighlightText 
= wxColour(*wxWHITE
); 
 299             return gs_objects
.m_colHighlightText
; 
 301         case wxSYS_COLOUR_APPWORKSPACE
: 
 302             return *wxWHITE
;    // ? 
 304         case wxSYS_COLOUR_ACTIVECAPTION
: 
 305         case wxSYS_COLOUR_MENUHILIGHT
: 
 306             if (!gs_objects
.m_colMenuItemHighlight
.Ok()) 
 308                 int red
, green
, blue
; 
 309                 if ( !GetColourFromGTKWidget(red
, green
, blue
, 
 319                 gs_objects
.m_colMenuItemHighlight 
= wxColour( red  
>> SHIFT
, 
 323             return gs_objects
.m_colMenuItemHighlight
; 
 325         case wxSYS_COLOUR_HOTLIGHT
: 
 326         case wxSYS_COLOUR_GRADIENTACTIVECAPTION
: 
 327         case wxSYS_COLOUR_GRADIENTINACTIVECAPTION
: 
 331         case wxSYS_COLOUR_MAX
: 
 333             wxFAIL_MSG( _T("unknown system colour index") ); 
 339 wxFont 
wxSystemSettingsNative::GetFont( wxSystemFont index 
) 
 343         case wxSYS_OEM_FIXED_FONT
: 
 344         case wxSYS_ANSI_FIXED_FONT
: 
 345         case wxSYS_SYSTEM_FIXED_FONT
: 
 347             return *wxNORMAL_FONT
; 
 349         case wxSYS_ANSI_VAR_FONT
: 
 350         case wxSYS_SYSTEM_FONT
: 
 351         case wxSYS_DEVICE_DEFAULT_FONT
: 
 352         case wxSYS_DEFAULT_GUI_FONT
: 
 354             if (!gs_objects
.m_fontSystem
.Ok()) 
 356                 GtkWidget 
*widget 
= gtk_button_new(); 
 357                 GtkStyle 
*def 
= gtk_rc_get_style( widget 
); 
 358                 if ( !def 
|| !def
->font_desc 
) 
 359                     def 
= gtk_widget_get_default_style(); 
 360                 if ( def 
&& def
->font_desc 
) 
 362                     wxNativeFontInfo info
; 
 364                         pango_font_description_copy(def
->font_desc
); 
 365                     gs_objects
.m_fontSystem 
= wxFont(info
); 
 369                     GtkSettings 
*settings 
= gtk_settings_get_default(); 
 370                     gchar 
*font_name 
= NULL
; 
 371                     g_object_get ( settings
, 
 376                         gs_objects
.m_fontSystem 
= wxFont( 12, wxSWISS
, wxNORMAL
, wxNORMAL 
); 
 378                         gs_objects
.m_fontSystem 
= wxFont(wxString::FromAscii(font_name
)); 
 381                 gtk_widget_destroy( widget 
); 
 383             return gs_objects
.m_fontSystem
; 
 391 int wxSystemSettingsNative::GetMetric( wxSystemMetric index
, wxWindow
* win 
) 
 393     bool success 
= false; 
 396     GdkWindow 
*window 
= NULL
; 
 397     if(win 
&& GTK_WIDGET_REALIZED(win
->GetHandle())) 
 398         window 
= win
->GetHandle()->window
; 
 406         case wxSYS_FRAMESIZE_X
: 
 407         case wxSYS_FRAMESIZE_Y
: 
 408             // If a window is specified/realized, and it is a toplevel window, we can query from wm. 
 409             // The returned border thickness is outside the client area in that case. 
 412                 wxTopLevelWindow 
*tlw 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 414                     return -1; // not a tlw, not sure how to approach 
 417                     // Check if wm supports frame extents - we can't know 
 418                     // the border widths if it does not. 
 419 #if GTK_CHECK_VERSION(2,2,0) 
 420                     if (!gtk_check_version(2,2,0)) 
 422                         if (!gdk_x11_screen_supports_net_wm_hint( 
 423                                 gdk_drawable_get_screen(window
), 
 424                                 gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) ) 
 430                         if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false))) 
 434                     // Get the frame extents from the windowmanager. 
 435                     // In most cases the top extent is the titlebar, so we use the bottom extent 
 442 #if GTK_CHECK_VERSION(2,2,0) 
 443                     if (!gtk_check_version(2,2,0)) 
 446                         success 
= (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window
)), 
 447                                             GDK_WINDOW_XWINDOW(window
), 
 448                                             gdk_x11_get_xatom_by_name_for_display ( 
 449                                                     gdk_drawable_get_display(window
), 
 450                                                     "_NET_FRAME_EXTENTS" ), 
 451                                             0, // left, right, top, bottom, CARDINAL[4]/32 
 452                                             G_MAXLONG
, // size of long 
 453                                             false, // do not delete property 
 454                                             XA_CARDINAL
, // 32 bit 
 455                                             &type
, &format
, &nitems
, &bytes_after
, &data
 
 461                         int border_return 
= -1; 
 463                         if ((type 
== XA_CARDINAL
) && (format 
== 32) && (nitems 
>= 4) && (data
)) 
 466                             borders 
= (long*)data
; 
 471                                 case wxSYS_FRAMESIZE_X
: 
 472                                     border_return 
= borders
[1]; // width of right extent 
 475                                     border_return 
= borders
[3]; // height of bottom extent 
 483                         return border_return
; 
 488             return -1; // no window specified 
 493             if (!gtk_check_version(2,4,0)) 
 496                     return gdk_display_get_default_cursor_size(gdk_drawable_get_display(window
)); 
 498                     return gdk_display_get_default_cursor_size(gdk_display_get_default()); 
 506             gint dclick_distance
; 
 507 #if GTK_CHECK_VERSION(2,2,0) 
 508             if (window 
&& !gtk_check_version(2,2,0)) 
 509                 g_object_get(gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)), 
 510                                 "gtk-double-click-distance", &dclick_distance
, NULL
); 
 513                 g_object_get(gtk_settings_get_default(), 
 514                                 "gtk-double-click-distance", &dclick_distance
, NULL
); 
 516             return dclick_distance 
* 2; 
 521 #if GTK_CHECK_VERSION(2,2,0) 
 522             if (window 
&& !gtk_check_version(2,2,0)) 
 525                         gtk_settings_get_for_screen(gdk_drawable_get_screen(window
)), 
 526                         "gtk-dnd-drag-threshold", 
 527                         &drag_threshold
, NULL
); 
 532                 g_object_get(gtk_settings_get_default(), 
 533                              "gtk-dnd-drag-threshold", &drag_threshold
, NULL
); 
 536             return drag_threshold 
* 2; 
 538         // MBN: ditto for icons 
 539         case wxSYS_ICON_X
:     return 32; 
 540         case wxSYS_ICON_Y
:     return 32; 
 543 #if GTK_CHECK_VERSION(2,2,0) 
 544             if (window 
&& !gtk_check_version(2,2,0)) 
 545                 return gdk_screen_get_width(gdk_drawable_get_screen(window
)); 
 548                 return gdk_screen_width(); 
 551 #if GTK_CHECK_VERSION(2,2,0) 
 552             if (window 
&& !gtk_check_version(2,2,0)) 
 553                 return gdk_screen_get_height(gdk_drawable_get_screen(window
)); 
 556                 return gdk_screen_height(); 
 558         case wxSYS_HSCROLL_Y
:  return 15; 
 559         case wxSYS_VSCROLL_X
:  return 15; 
 561         case wxSYS_CAPTION_Y
: 
 563                 // No realized window specified, and no implementation for that case yet. 
 566             // Check if wm supports frame extents - we can't know the caption height if it does not. 
 567 #if GTK_CHECK_VERSION(2,2,0) 
 568             if (!gtk_check_version(2,2,0)) 
 570                 if (!gdk_x11_screen_supports_net_wm_hint( 
 571                         gdk_drawable_get_screen(window
), 
 572                         gdk_atom_intern("_NET_FRAME_EXTENTS", false) ) ) 
 578                 if (!gdk_net_wm_supports(gdk_atom_intern("_NET_FRAME_EXTENTS", false))) 
 582             wxASSERT_MSG( wxDynamicCast(win
, wxTopLevelWindow
), 
 583                           wxT("Asking for caption height of a non toplevel window") ); 
 585             // Get the height of the top windowmanager border. 
 586             // This is the titlebar in most cases. The titlebar might be elsewhere, and 
 587             // we could check which is the thickest wm border to decide on which side the 
 588             // titlebar is, but this might lead to interesting behaviours in used code. 
 589             // Reconsider when we have a way to report to the user on which side it is. 
 595 #if GTK_CHECK_VERSION(2,2,0) 
 596             if (!gtk_check_version(2,2,0)) 
 599                 success 
= (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(window
)), 
 600                                     GDK_WINDOW_XWINDOW(window
), 
 601                                     gdk_x11_get_xatom_by_name_for_display ( 
 602                                             gdk_drawable_get_display(window
), 
 603                                             "_NET_FRAME_EXTENTS" ), 
 604                                     0, // left, right, top, bottom, CARDINAL[4]/32 
 605                                     G_MAXLONG
, // size of long 
 606                                     false, // do not delete property 
 607                                     XA_CARDINAL
, // 32 bit 
 608                                     &type
, &format
, &nitems
, &bytes_after
, &data
 
 614                 int caption_height 
= -1; 
 616                 if ((type 
== XA_CARDINAL
) && (format 
== 32) && (nitems 
>= 3) && (data
)) 
 619                     borders 
= (long*)data
; 
 620                     caption_height 
= borders
[2]; // top frame extent 
 626                 return caption_height
; 
 629             // Try a default approach without a window pointer, if possible 
 634         case wxSYS_PENWINDOWS_PRESENT
: 
 635             // No MS Windows for Pen computing extension available in X11 based gtk+. 
 639             return -1;   // metric is unknown 
 643 bool wxSystemSettingsNative::HasFeature(wxSystemFeature index
) 
 647         case wxSYS_CAN_ICONIZE_FRAME
: 
 650         case wxSYS_CAN_DRAW_FRAME_DECORATIONS
: