]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
Themes crash fix.
[wxWidgets.git] / src / gtk1 / window.cpp
index 5dc903f0caeae35f7da085299e6d690e792af582..b9df8d107bb77758d899507422e553f9e2b61ee3 100644 (file)
 #include "wx/settings.h"
 #include "wx/log.h"
 
+#ifdef __WXDEBUG__
+    #include "wx/thread.h"
+#endif
+
 #include <math.h>
 
-#include "gdk/gdk.h"
-#include "gtk/gtk.h"
-#include "gdk/gdkprivate.h"
-#include "gdk/gdkkeysyms.h"
-#include "wx/gtk/win_gtk.h"
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+#include <gdk/gdkkeysyms.h>
+#include <wx/gtk/win_gtk.h>
 
-#include "gdk/gdkx.h"
+#include <gdk/gdkx.h>
 
 //-----------------------------------------------------------------------------
 // documentation on internals
@@ -198,12 +202,16 @@ static int        g_sendActivateEvent = -1;
    the last click here */
 static guint32 gs_timeLastClick = 0;
 
+extern bool g_mainThreadLocked;
+
 //-----------------------------------------------------------------------------
 // debug
 //-----------------------------------------------------------------------------
 
 #ifdef __WXDEBUG__
 
+#define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
+
 static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
                                          GdkEvent *WXUNUSED(event),
                                          const wxChar *WXUNUSED(name) )
@@ -327,7 +335,7 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
                          GTK_STATE_NORMAL,
                          GTK_SHADOW_OUT,
                          dx, dy,
-                         win->m_width-dw, win->m_height-dh );
+                         widget->allocation.width-dw, widget->allocation.height-dh );
         return;
     }
 
@@ -338,7 +346,7 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
                          GTK_STATE_NORMAL,
                          GTK_SHADOW_IN,
                          dx, dy,
-                         win->m_width-dw, win->m_height-dh );
+                         widget->allocation.width-dw, widget->allocation.height-dh );
         return;
     }
 
@@ -349,7 +357,7 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
         gdk_gc_set_foreground( gc, &widget->style->black );
         gdk_draw_rectangle( widget->window, gc, FALSE,
                          dx, dy,
-                         win->m_width-dw-1, win->m_height-dh-1 );
+                         widget->allocation.width-dw-1, widget->allocation.height-dh-1 );
         gdk_gc_unref( gc );
         return;
     }
@@ -590,6 +598,8 @@ static long map_to_wx_keysym( KeySym keysym )
 
 static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (!win->m_hasVMT)
         return;
 
@@ -598,9 +608,6 @@ static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExp
                                   gdk_event->area.width,
                                   gdk_event->area.height );
 
-    if (gdk_event->count > 0)
-        return;
-
 /*
     wxPrintf( "OnExpose from " );
     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
@@ -611,6 +618,9 @@ static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExp
                                 (int)gdk_event->area.height );
 */
 
+    if (gdk_event->count > 0)
+        return;
+
     wxEraseEvent eevent( win->GetId() );
     eevent.SetEventObject( win );
     win->GetEventHandler()->ProcessEvent(eevent);
@@ -629,6 +639,8 @@ static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExp
 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget),
                                       GdkRectangle *rect, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -665,6 +677,8 @@ static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget),
 
 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -817,6 +831,8 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
 
 static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -873,6 +889,8 @@ static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk
 
 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -944,8 +962,8 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
 
-    event.m_x = (long)gdk_event->x;
-    event.m_y = (long)gdk_event->y;
+    event.m_x = (wxCoord)gdk_event->x;
+    event.m_y = (wxCoord)gdk_event->y;
 
     // Some control don't have their own X window and thus cannot get
     // any events.
@@ -1037,6 +1055,8 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
 
 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1071,8 +1091,8 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
     event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
-    event.m_x = (long)gdk_event->x;
-    event.m_y = (long)gdk_event->y;
+    event.m_x = (wxCoord)gdk_event->x;
+    event.m_y = (wxCoord)gdk_event->y;
 
     // Some control don't have their own X window and thus cannot get
     // any events.
@@ -1155,6 +1175,8 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
 
 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1191,8 +1213,8 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
     event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
     event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
 
-    event.m_x = (long)gdk_event->x;
-    event.m_y = (long)gdk_event->y;
+    event.m_x = (wxCoord)gdk_event->x;
+    event.m_y = (wxCoord)gdk_event->y;
 
     // Some control don't have their own X window and thus cannot get
     // any events.
@@ -1275,6 +1297,8 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
 
 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1335,6 +1359,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(
 
 static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1378,6 +1404,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
 
 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1406,8 +1434,8 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
     event.m_middleDown = (state & GDK_BUTTON2_MASK);
     event.m_rightDown = (state & GDK_BUTTON3_MASK);
 
-    event.m_x = (long)x;
-    event.m_y = (long)y;
+    event.m_x = x;
+    event.m_y = y;
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
@@ -1424,6 +1452,8 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1452,8 +1482,8 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
     event.m_middleDown = (state & GDK_BUTTON2_MASK);
     event.m_rightDown = (state & GDK_BUTTON3_MASK);
 
-    event.m_x = (long)x;
-    event.m_y = (long)y;
+    event.m_x = x;
+    event.m_y = y;
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
@@ -1470,6 +1500,8 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
 static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1504,6 +1536,8 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
 
 static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1537,6 +1571,8 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
 
 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1557,6 +1593,8 @@ static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxW
 
 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1579,6 +1617,8 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
                                                  GdkEventButton *WXUNUSED(gdk_event),
                                                  wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1600,6 +1640,8 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
                                                    GdkEventButton *WXUNUSED(gdk_event),
                                                    wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
 
 //  don't test here as we can release the mouse while being over
 //  a different window than the slider
@@ -1631,12 +1673,11 @@ wxWindow *wxWindowBase::FindFocus()
 static gint
 gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    if (win->m_delayedFont)
-        win->SetFont( win->GetFont() );
-
     if (win->m_delayedBackgroundColour)
         win->SetBackgroundColour( win->GetBackgroundColour() );
 
@@ -1654,9 +1695,18 @@ gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
 // "size_allocate"
 //-----------------------------------------------------------------------------
 
+#ifdef HAVE_XIM
+    #define WXUNUSED_UNLESS_XIM(param)  param
+#else
+    #define WXUNUSED_UNLESS_XIM(param)  WXUNUSED(param)
+#endif
+
 /* Resize XIM window */
 
-static void gtk_wxwindow_size_callback( GtkWidget *widget, GtkAllocation* alloc, wxFrame *win )
+static
+void gtk_wxwindow_size_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
+                                 GtkAllocation * WXUNUSED_UNLESS_XIM(alloc),
+                                 wxFrame * WXUNUSED_UNLESS_XIM(win) )
 {
     if (g_isIdle)
         wxapp_install_idle_handler();
@@ -1669,7 +1719,7 @@ static void gtk_wxwindow_size_callback( GtkWidget *widget, GtkAllocation* alloc,
     {
         gint width, height;
 
-       gdk_window_get_size (widget->window, &width, &height);
+        gdk_window_get_size (widget->window, &width, &height);
         win->m_icattr->preedit_area.width = width;
         win->m_icattr->preedit_area.height = height;
         gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
@@ -1684,7 +1734,8 @@ static void gtk_wxwindow_size_callback( GtkWidget *widget, GtkAllocation* alloc,
 /* Initialize XIM support */
 
 static gint
-gtk_wxwindow_realized_callback( GtkWidget *widget, wxWindow *win )
+gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
+                                wxWindow * WXUNUSED_UNLESS_XIM(win) )
 {
     if (g_isIdle)
         wxapp_install_idle_handler();
@@ -1701,7 +1752,7 @@ gtk_wxwindow_realized_callback( GtkWidget *widget, wxWindow *win )
     GdkEventMask mask;
     GdkColormap *colormap;
     GdkICAttr *attr = win->m_icattr;
-    GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
+    unsigned attrmask = GDK_IC_ALL_REQ;
     GdkIMStyle style;
     GdkIMStyle supported_style = (GdkIMStyle)
                                   (GDK_IM_PREEDIT_NONE |
@@ -1751,7 +1802,7 @@ gtk_wxwindow_realized_callback( GtkWidget *widget, wxWindow *win )
          break;
     }
        
-      win->m_ic = gdk_ic_new (attr, attrmask);
+      win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
      
       if (win->m_ic == NULL)
        g_warning ("Can't create input context.");
@@ -2193,6 +2244,11 @@ bool wxWindow::Destroy()
     return wxWindowBase::Destroy();
 }
 
+void wxWindow::DoMoveWindow(int x, int y, int width, int height)
+{
+    gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
+}
+    
 void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
@@ -2253,12 +2309,10 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
             bottom_border = 5;
         }
 
-        gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow),
-                              m_widget,
-                              m_x-border,
-                              m_y-border,
-                              m_width+2*border,
-                              m_height+border+bottom_border );
+        DoMoveWindow( m_x-border,
+                      m_y-border,
+                      m_width+2*border,
+                      m_height+border+bottom_border );
     }
 
 /*
@@ -2766,8 +2820,7 @@ void wxWindow::WarpPointer( int x, int y )
 
 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
 {
-    wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
+    if (!m_widget) return;
     if (!m_widget->window) return;
 
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
@@ -2880,7 +2933,8 @@ bool wxWindow::SetBackgroundColour( const wxColour &colour )
         return TRUE;
     }
 
-    if (m_wxwindow)
+    if ((m_wxwindow) &&
+        (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)))
     {
         /* wxMSW doesn't clear the window here. I don't do that either to
           provide compatibility. call Clear() to do the job. */
@@ -2889,17 +2943,7 @@ bool wxWindow::SetBackgroundColour( const wxColour &colour )
         gdk_window_set_background( window, m_backgroundColour.GetColor() );
     }
 
-    wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
-    if (sysbg == m_backgroundColour)
-    {
-        m_backgroundColour = wxNullColour;
-        ApplyWidgetStyle();
-        m_backgroundColour = sysbg;
-    }
-    else
-    {
-        ApplyWidgetStyle();
-    }
+    ApplyWidgetStyle();
 
     return TRUE;
 }
@@ -2932,26 +2976,22 @@ bool wxWindow::SetForegroundColour( const wxColour &colour )
         return TRUE;
     }
 
-    wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
-    if ( sysbg == m_backgroundColour )
-    {
-        m_backgroundColour = wxNullColour;
-        ApplyWidgetStyle();
-        m_backgroundColour = sysbg;
-    }
-    else
-    {
-        ApplyWidgetStyle();
-    }
+    ApplyWidgetStyle();
 
     return TRUE;
 }
 
 GtkStyle *wxWindow::GetWidgetStyle()
 {
-    if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
+    if (m_widgetStyle) return m_widgetStyle;
+
+    GtkStyle *def = gtk_rc_get_style( m_widget );
+
+    if (!def)
+        def = gtk_widget_get_default_style();
 
-    m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
+    m_widgetStyle = gtk_style_copy( def );
+    m_widgetStyle->klass = def->klass;
 
     return m_widgetStyle;
 }
@@ -2960,28 +3000,37 @@ void wxWindow::SetWidgetStyle()
 {
     GtkStyle *style = GetWidgetStyle();
 
-    gdk_font_unref( style->font );
-    style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
+    if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
+    {
+        gdk_font_unref( style->font );
+        style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
+    }
 
     if (m_foregroundColour.Ok())
     {
         m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
-        style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
-        style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
-        style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
+        if (m_foregroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT))
+        {
+            style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
+            style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
+            style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
+        }
     }
 
     if (m_backgroundColour.Ok())
     {
         m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
-        style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
-        style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
-        style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
-        style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
-        style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
-        style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
-        style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
-        style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+        if (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE))
+        {
+            style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
+            style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
+            style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
+            style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
+            style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
+            style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
+            style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+            style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
+       }
     }
 }
 
@@ -3320,6 +3369,10 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
 
+/*
+    printf( "ScrollWindow: %d %d\n", dx, dy );
+*/
+
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
 
 /*