]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
Compile fix.
[wxWidgets.git] / src / gtk1 / window.cpp
index 7460101617e7d90783b1e0dc290eb176878cdd4d..c12e2fad49b8c4689ca166ebab05835f4e0d02d8 100644 (file)
@@ -54,6 +54,7 @@
 #endif
 
 #include <math.h>
+#include <ctype.h>
 
 #include "wx/gtk/private.h"
 #include <gdk/gdkprivate.h>
@@ -274,6 +275,9 @@ extern bool g_mainThreadLocked;
 #define DEBUG_MAIN_THREAD
 #endif // Debug
 
+// the trace mask used for the focus debugging messages
+#define TRACE_FOCUS _T("focus")
+
 //-----------------------------------------------------------------------------
 // missing gdk functions
 //-----------------------------------------------------------------------------
@@ -509,9 +513,13 @@ static int gtk_window_expose_callback( GtkWidget *widget,
                                   gdk_event->area.y,
                                   gdk_event->area.width,
                                   gdk_event->area.height );
+    win->m_clearRegion.Union( gdk_event->area.x,
+                                  gdk_event->area.y,
+                                  gdk_event->area.width,
+                                  gdk_event->area.height );
 
     // Actual redrawing takes place in idle time.
-    win->GtkUpdate();
+    // win->GtkUpdate();
 
 #ifdef __WXGTK20__
 
@@ -604,20 +612,12 @@ static void gtk_window_draw_callback( GtkWidget *widget,
                             (char *)"base",
                             0, 0, -1, -1);
     }
-
-
-    if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
-         (pizza->clear_on_draw))
-    {
-        gdk_window_clear_area( pizza->bin_window,
-                               rect->x, rect->y, rect->width, rect->height);
-    }
 #endif
 
+    win->m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height );
     win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
 
-    // Actual redrawing takes place in idle time.
-
+    // Update immediately, not in idle time.
     win->GtkUpdate();
 
 #ifndef __WXUNIVERSAL__
@@ -946,7 +946,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
 
     KeySym keysym = gdk_event->keyval;
 
-    wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %d"),
+    wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %ld"),
                event.GetEventType() == wxEVT_KEY_UP ? _T("release")
                                                     : _T("press"),
                keysym);
@@ -1016,7 +1016,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
         }
     }
 
-    wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %d"), key_code);
+    wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %ld"), key_code);
 
     // sending unknown key events doesn't really make sense
     if ( !key_code )
@@ -1059,6 +1059,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     if (g_blockEventsOnDrag)
         return FALSE;
 
+
     wxKeyEvent event( wxEVT_KEY_DOWN );
     if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
     {
@@ -1066,6 +1067,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         return FALSE;
     }
 
+    // Emit KEY_DOWN event
     bool ret = win->GetEventHandler()->ProcessEvent( event );
 
 #if wxUSE_ACCEL
@@ -1088,10 +1090,11 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     }
 #endif // wxUSE_ACCEL
 
-    /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
-       will only be sent if it is not in an accelerator table. */
-    if ( !ret )
+    // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
+    // will only be sent if it is not in an accelerator table.
+    if (!ret)
     {
+        // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
         KeySym keysym = gdk_event->keyval;
         long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
         if ( !key_code )
@@ -1111,16 +1114,27 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         {
             wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
 
-            // reuse the same event object, just change its type and use the
-            // translated keycode instead of the raw one
-            event.SetEventType(wxEVT_CHAR);
             event.m_keyCode = key_code;
+            
+            // Implement OnCharHook by checking ancesteror top level windows
+            wxWindow *parent = win;
+            while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+            if (parent)
+            {
+                event.SetEventType( wxEVT_CHAR_HOOK );
+                ret = parent->GetEventHandler()->ProcessEvent( event );
+            }
 
-            ret = win->GetEventHandler()->ProcessEvent( event );
+            if (!ret)
+            {
+                event.SetEventType(wxEVT_CHAR);
+                ret = win->GetEventHandler()->ProcessEvent( event );
+            }
         }
     }
 
-    /* win is a control: tab can be propagated up */
+    // win is a control: tab can be propagated up
     if ( !ret &&
          ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
@@ -1133,15 +1147,15 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     {
         wxNavigationKeyEvent new_event;
         new_event.SetEventObject( win->GetParent() );
-        /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
+        // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
         new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
-        /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
+        // CTRL-TAB changes the (parent) window, i.e. switch notebook page
         new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
         new_event.SetCurrentFocus( win );
         ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
     }
 
-    /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
+    // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
     if ( !ret &&
          (gdk_event->keyval == GDK_Escape) )
     {
@@ -1150,9 +1164,9 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         ret = win->GetEventHandler()->ProcessEvent( new_event );
     }
 
-    /* Doesn't work. */
-#if 0 // (GTK_MINOR_VERSION > 0)
-    /* Pressing F10 will activate the menu bar of the top frame. */
+    // Doesn't work.
+#if 0 
+    // Pressing F10 will activate the menu bar of the top frame
     if ( (!ret) &&
          (gdk_event->keyval == GDK_F10) )
     {
@@ -1185,7 +1199,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
         return TRUE;
     }
-
+    
     return FALSE;
 }
 
@@ -1226,27 +1240,36 @@ static gint gtk_window_key_release_callback( GtkWidget *widget,
 // the mouse events
 // ============================================================================
 
-// init wxMouseEvent with the info from gdk_event
-#define InitMouseEvent(win, event, gdk_event) \
-    { \
-    event.SetTimestamp( gdk_event->time ); \
-    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
-    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
-    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
-    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
-    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); \
-\
-    wxPoint pt = win->GetClientAreaOrigin(); \
-    event.m_x = (wxCoord)gdk_event->x - pt.x; \
-    event.m_y = (wxCoord)gdk_event->y - pt.y; \
-    }
-
 // ----------------------------------------------------------------------------
-// mouse event processing helper
+// mouse event processing helpers
 // ----------------------------------------------------------------------------
 
+// init wxMouseEvent with the info from gdk_event
+//
+// NB: this has to be a macro as gdk_event type is different for different
+//     events we're used with
+#define InitMouseEvent(/* wxWindowGTK * */ win,                               \
+                       /* wxMouseEvent& */ event,                             \
+                       /* GdkEventXXX * */ gdk_event)                         \
+{                                                                             \
+    event.SetTimestamp( gdk_event->time );                                    \
+    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);                  \
+    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);              \
+    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);                     \
+    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);                    \
+    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);                \
+                                                                              \
+    wxPoint pt = win->GetClientAreaOrigin();                                  \
+    event.m_x = (wxCoord)gdk_event->x - pt.x;                                 \
+    event.m_y = (wxCoord)gdk_event->y - pt.y;                                 \
+                                                                              \
+    event.SetEventObject( win );                                              \
+    event.SetId( win->GetId() );                                              \
+    event.SetTimestamp( gdk_event->time );                                    \
+}                                                                             \
+
 static void AdjustEventButtonState(wxMouseEvent& event)
 {
     // GDK reports the old state of the button for a button press event, but
@@ -1279,11 +1302,79 @@ static void AdjustEventButtonState(wxMouseEvent& event)
     }
 }
 
+// find the window to send the mouse event too
+static
+wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
+{
+    wxCoord xx = x;
+    wxCoord yy = y;
+
+    if (win->m_wxwindow)
+    {
+        GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
+        xx += pizza->xoffset;
+        yy += pizza->yoffset;
+    }
+
+    wxNode *node = win->GetChildren().First();
+    while (node)
+    {
+        wxWindowGTK *child = (wxWindowGTK*)node->Data();
+
+        node = node->Next();
+        if (!child->IsShown())
+            continue;
+
+        if (child->IsTransparentForMouse())
+        {
+            // wxStaticBox is transparent in the box itself
+            int xx1 = child->m_x;
+            int yy1 = child->m_y;
+            int xx2 = child->m_x + child->m_width;
+            int yy2 = child->m_x + child->m_height;
+
+            // left
+            if (((xx >= xx1) && (xx <= xx1+10) && (yy >= yy1) && (yy <= yy2)) ||
+            // right
+                ((xx >= xx2-10) && (xx <= xx2) && (yy >= yy1) && (yy <= yy2)) ||
+            // top
+                ((xx >= xx1) && (xx <= xx2) && (yy >= yy1) && (yy <= yy1+10)) ||
+            // bottom
+                ((xx >= xx1) && (xx <= xx2) && (yy >= yy2-1) && (yy <= yy2)))
+            {
+                win = child;
+                x -= child->m_x;
+                y -= child->m_y;
+                break;
+            }
+
+        }
+        else
+        {
+            if ((child->m_wxwindow == (GtkWidget*) NULL) &&
+                (child->m_x <= xx) &&
+                (child->m_y <= yy) &&
+                (child->m_x+child->m_width  >= xx) &&
+                (child->m_y+child->m_height >= yy))
+            {
+                win = child;
+                x -= child->m_x;
+                y -= child->m_y;
+                break;
+            }
+        }
+    }
+
+    return win;
+}
+
 //-----------------------------------------------------------------------------
 // "button_press_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindowGTK *win )
+static gint gtk_window_button_press_callback( GtkWidget *widget,
+                                              GdkEventButton *gdk_event,
+                                              wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1354,79 +1445,15 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
 
     AdjustEventButtonState(event);
 
-    // wxListBox actually get mouse events from the item
+    // wxListBox actually get mouse events from the item, so we need to give it
+    // a chance to correct this
+    win->FixUpMouseEvent(widget, event.m_x, event.m_y);
 
-    if (win->m_isListBox)
-    {
-        event.m_x += widget->allocation.x;
-        event.m_y += widget->allocation.y;
-    }
-
-    // Some control don't have their own X window and thus cannot get
-    // any events.
-
-    if (!g_captureWindow)
-    {
-        wxCoord x = event.m_x;
-        wxCoord y = event.m_y;
-        if (win->m_wxwindow)
-        {
-            GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
-            x += pizza->xoffset;
-            y += pizza->yoffset;
-        }
-
-        wxNode *node = win->GetChildren().First();
-        while (node)
-        {
-            wxWindowGTK *child = (wxWindowGTK*)node->Data();
-
-            node = node->Next();
-            if (!child->IsShown())
-                continue;
-
-            if (child->m_isStaticBox)
-            {
-                // wxStaticBox is transparent in the box itself
-                int xx1 = child->m_x;
-                int yy1 = child->m_y;
-                int xx2 = child->m_x + child->m_width;
-                int yy2 = child->m_x + child->m_height;
-
-                // left
-                if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
-                // right
-                    ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
-                // top
-                    ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
-                // bottom
-                    ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
-                {
-                    win = child;
-                    event.m_x -= child->m_x;
-                    event.m_y -= child->m_y;
-                    break;
-                }
-
-            }
-            else
-            {
-                if ((child->m_wxwindow == (GtkWidget*) NULL) &&
-                    (child->m_x <= x) &&
-                    (child->m_y <= y) &&
-                    (child->m_x+child->m_width  >= x) &&
-                    (child->m_y+child->m_height >= y))
-                {
-                    win = child;
-                    event.m_x -= child->m_x;
-                    event.m_y -= child->m_y;
-                    break;
-                }
-            }
-        }
-    }
-
-    event.SetEventObject( win );
+    // find the correct window to send the event too: it may be a different one
+    // from the one which got it at GTK+ level because some control don't have
+    // their own X window and thus cannot get any events.
+    if ( !g_captureWindow )
+        win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
 
     gs_timeLastClick = gdk_event->time;
 
@@ -1485,79 +1512,11 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
 
     AdjustEventButtonState(event);
 
-    // wxListBox actually get mouse events from the item
+    // same wxListBox hack as above
+    win->FixUpMouseEvent(widget, event.m_x, event.m_y);
 
-    if (win->m_isListBox)
-    {
-        event.m_x += widget->allocation.x;
-        event.m_y += widget->allocation.y;
-    }
-
-    // Some control don't have their own X window and thus cannot get
-    // any events.
-
-    if (!g_captureWindow)
-    {
-        wxCoord x = event.m_x;
-        wxCoord y = event.m_y;
-        if (win->m_wxwindow)
-        {
-            GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
-            x += pizza->xoffset;
-            y += pizza->yoffset;
-        }
-
-        wxNode *node = win->GetChildren().First();
-        while (node)
-        {
-            wxWindowGTK *child = (wxWindowGTK*)node->Data();
-
-            node = node->Next();
-            if (!child->IsShown())
-                continue;
-
-            if (child->m_isStaticBox)
-            {
-                // wxStaticBox is transparent in the box itself
-                int xx1 = child->m_x;
-                int yy1 = child->m_y;
-                int xx2 = child->m_x + child->m_width;
-                int yy2 = child->m_x + child->m_height;
-
-                // left
-                if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
-                // right
-                    ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
-                // top
-                    ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
-                // bottom
-                    ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
-                {
-                    win = child;
-                    event.m_x -= child->m_x;
-                    event.m_y -= child->m_y;
-                    break;
-                }
-
-            }
-            else
-            {
-                if ((child->m_wxwindow == (GtkWidget*) NULL) &&
-                    (child->m_x <= x) &&
-                    (child->m_y <= y) &&
-                    (child->m_x+child->m_width  >= x) &&
-                    (child->m_y+child->m_height >= y))
-                {
-                    win = child;
-                    event.m_x -= child->m_x;
-                    event.m_y -= child->m_y;
-                    break;
-                }
-            }
-        }
-    }
-
-    event.SetEventObject( win );
+    if ( !g_captureWindow )
+        win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
 
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
@@ -1626,70 +1585,9 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
     }
     else // no capture
     {
-        // Some control don't have their own X window and thus cannot get
-        // any events.
-
-        wxCoord x = event.m_x;
-        wxCoord y = event.m_y;
-        if (win->m_wxwindow)
-        {
-            GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
-            x += pizza->xoffset;
-            y += pizza->yoffset;
-        }
-
-        wxNode *node = win->GetChildren().First();
-        while (node)
-        {
-            wxWindowGTK *child = (wxWindowGTK*)node->Data();
-
-            node = node->Next();
-            if (!child->IsShown())
-                continue;
-
-            if (child->m_isStaticBox)
-            {
-                // wxStaticBox is transparent in the box itself
-                int xx1 = child->m_x;
-                int yy1 = child->m_y;
-                int xx2 = child->m_x + child->m_width;
-                int yy2 = child->m_x + child->m_height;
-
-                // left
-                if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
-                // right
-                    ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
-                // top
-                    ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
-                // bottom
-                    ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
-                {
-                    win = child;
-                    event.m_x -= child->m_x;
-                    event.m_y -= child->m_y;
-                    break;
-                }
-
-            }
-            else
-            {
-                if ((child->m_wxwindow == (GtkWidget*) NULL) &&
-                    (child->m_x <= x) &&
-                    (child->m_y <= y) &&
-                    (child->m_x+child->m_width  >= x) &&
-                    (child->m_y+child->m_height >= y))
-                {
-                    win = child;
-                    event.m_x -= child->m_x;
-                    event.m_y -= child->m_y;
-                    break;
-                }
-            }
-        }
+        win = FindWindowForMouseEvent(win, event.m_x, event.m_y);
     }
 
-    event.SetEventObject( win );
-
     if (win->GetEventHandler()->ProcessEvent( event ))
     {
         gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
@@ -1747,9 +1645,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
     g_focusWindowLast =
     g_focusWindow = win;
 
-#if 0
-    printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() );
-#endif
+    wxLogTrace(TRACE_FOCUS,
+               _T("%s: focus in"), win->GetName().c_str());
 
 #ifdef HAVE_XIM
     if (win->m_ic)
@@ -1789,10 +1686,17 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
         //    return TRUE;
     }
 
-    if ( DoSendFocusEvents(win) )
+    // does the window itself think that it has the focus?
+    if ( !win->m_hasFocus )
     {
-       gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
-       return TRUE;
+        // not yet, notify it
+        win->m_hasFocus = TRUE;
+
+        if ( DoSendFocusEvents(win) )
+        {
+           gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
+           return TRUE;
+        }
     }
 
     return FALSE;
@@ -1812,9 +1716,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
     if (!win->m_hasVMT) return FALSE;
     if (g_blockEventsOnDrag) return FALSE;
 
-#if 0
-    wxLogDebug( wxT("OnKillFocus from %s"), win->GetName().c_str() );
-#endif
+    wxLogTrace( TRACE_FOCUS,
+                _T("%s: focus out"), win->GetName().c_str() );
 
     if ( !g_activeFrameLostFocus && g_activeFrame )
     {
@@ -1823,7 +1726,7 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
         //     always) and makes using Mahogany quite annoying
 #if 0
         wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame,
-                        wxT("unfocusing window that hasn't gained focus properly") )
+                        wxT("unfocusing window that hasn't gained focus properly") );
 #endif // 0
 
         g_activeFrameLostFocus = TRUE;
@@ -1854,13 +1757,20 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
     }
 #endif // wxUSE_CARET
 
-    wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
-    event.SetEventObject( win );
-
-    if (win->GetEventHandler()->ProcessEvent( event ))
+    // don't send the window a kill focus event if it thinks that it doesn't
+    // have focus already
+    if ( win->m_hasFocus )
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
-        return TRUE;
+        win->m_hasFocus = FALSE;
+
+        wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
+        event.SetEventObject( win );
+
+        if (win->GetEventHandler()->ProcessEvent( event ))
+        {
+            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
+            return TRUE;
+        }
     }
 
     return FALSE;
@@ -1870,7 +1780,10 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
 // "enter_notify_event"
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindowGTK *win )
+static
+gint gtk_window_enter_callback( GtkWidget *widget,
+                                GdkEventCrossing *gdk_event,
+                                wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
@@ -1882,16 +1795,13 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
-    wxMouseEvent event( wxEVT_ENTER_WINDOW );
-    event.SetTimestamp( gdk_event->time );
-    event.SetEventObject( win );
-
     int x = 0;
     int y = 0;
     GdkModifierType state = (GdkModifierType)0;
 
     gdk_window_get_pointer( widget->window, &x, &y, &state );
 
+    wxMouseEvent event( wxEVT_ENTER_WINDOW );
     InitMouseEvent(win, event, gdk_event);
     wxPoint pt = win->GetClientAreaOrigin();
     event.m_x = x + pt.x;
@@ -1975,7 +1885,8 @@ static void gtk_window_vscroll_callback( GtkAdjustment *adjust,
 
     win->m_oldVerticalPos = adjust->value;
 
-    wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget));
+    GtkScrolledWindow   *sw = GTK_SCROLLED_WINDOW(win->m_widget);
+    wxEventType         command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->vscrollbar));
 
     int value = (int)(adjust->value+0.5);
 
@@ -2003,7 +1914,8 @@ static void gtk_window_hscroll_callback( GtkAdjustment *adjust,
     float diff = adjust->value - win->m_oldHorizontalPos;
     if (fabs(diff) < 0.2) return;
 
-    wxEventType command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win->m_widget));
+    GtkScrolledWindow   *sw = GTK_SCROLLED_WINDOW(win->m_widget);
+    wxEventType         command = GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw->hscrollbar));
 
     win->m_oldHorizontalPos = adjust->value;
 
@@ -2094,6 +2006,22 @@ wxWindow *wxWindowBase::FindFocus()
     return (wxWindow *)g_focusWindow;
 }
 
+//-----------------------------------------------------------------------------
+// "destroy" event
+//-----------------------------------------------------------------------------
+
+// VZ: Robert commented the code using out so it generates warnings: should
+//     be either fixed or removed completely
+#if 0
+
+static void gtk_window_destroy_callback( GtkWidget* widget, wxWindow *win )
+{
+    wxWindowDestroyEvent event(win);
+    win->GetEventHandler()->ProcessEvent(event);
+}
+
+#endif // 0
+
 //-----------------------------------------------------------------------------
 // "realize" from m_widget
 //-----------------------------------------------------------------------------
@@ -2312,8 +2240,7 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
 
 wxWindow *wxGetActiveWindow()
 {
-    // the cast is necessary when we compile in wxUniversal mode
-    return (wxWindow *)g_focusWindow;
+    return wxWindow::FindFocus();
 }
 
 //-----------------------------------------------------------------------------
@@ -2365,11 +2292,8 @@ void wxWindowGTK::Init()
 
     m_insertCallback = (wxInsertChildFunction) NULL;
 
-    m_isStaticBox = FALSE;
-    m_isRadioButton = FALSE;
-    m_isListBox = FALSE;
-    m_isFrame = FALSE;
     m_acceptsFocus = FALSE;
+    m_hasFocus = FALSE;
 
     m_clipPaintRegion = FALSE;
 
@@ -2524,6 +2448,9 @@ wxWindowGTK::~wxWindowGTK()
     if (g_activeFrame == this)
         g_activeFrame = NULL;
 
+    if ( g_delayedFocus == this )
+        g_delayedFocus = NULL;
+
     m_isBeingDeleted = TRUE;
     m_hasVMT = FALSE;
 
@@ -2569,17 +2496,17 @@ bool wxWindowGTK::PreCreation( wxWindowGTK *parent, const wxPoint &pos,  const w
 {
     wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
 
-    /* this turns -1 into 20 so that a minimal window is
-       visible even although -1,-1 has been given as the
-       size of the window. the same trick is used in other
-       ports and should make debugging easier */
-    m_width = WidthDefault(size.x);
+    // This turns -1 into 30 so that a minimal window is
+    // visible even although -1,-1 has been given as the
+    // size of the window. the same trick is used in other
+    // ports and should make debugging easier.
+    m_width = WidthDefault(size.x) ;
     m_height = HeightDefault(size.y);
 
     m_x = (int)pos.x;
     m_y = (int)pos.y;
 
-    /* some reasonable defaults */
+    // some reasonable defaults
     if (!parent)
     {
         if (m_x == -1)
@@ -2709,6 +2636,11 @@ void wxWindowGTK::ConnectWidget( GtkWidget *widget )
 
     gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
       GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
+      
+    // This keeps crashing on me. RR.
+    //
+    // gtk_signal_connect( GTK_OBJECT(widget), "destroy",
+    //  GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this );
 }
 
 bool wxWindowGTK::Destroy()
@@ -2760,16 +2692,14 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         {
             if (x != -1) m_x = x + pizza->xoffset;
             if (y != -1) m_y = y + pizza->yoffset;
-            if (width != -1) m_width = width;
-            if (height != -1) m_height = height;
         }
         else
         {
             m_x = x + pizza->xoffset;
             m_y = y + pizza->yoffset;
-            m_width = width;
-            m_height = height;
         }
+        if (width != -1) m_width = width;
+        if (height != -1) m_height = height;
 
         if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
         {
@@ -3210,7 +3140,7 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
     wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
     GdkFont *font = fontToUse.GetInternalFont( 1.0 );
-    if (x) (*x) = gdk_string_width( font, string.mbc_str() );
+    if (x) (*x) = gdk_string_width( font, wxGTK_CONV( string ) );
     if (y) (*y) = font->ascent + font->descent;
     if (descent) (*descent) = font->descent;
     if (externalLeading) (*externalLeading) = 0;  // ??
@@ -3218,7 +3148,13 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
 
 void wxWindowGTK::SetFocus()
 {
-    wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
+    wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
+
+    if ( m_hasFocus )
+    {
+        // don't do anything if we already have focus
+        return;
+    }
 
     if (m_wxwindow)
     {
@@ -3233,16 +3169,19 @@ void wxWindowGTK::SetFocus()
         {
             if (!GTK_WIDGET_REALIZED(m_widget))
             {
-                wxLogTrace(_T("focus"),
-                           _T("Delaying setting focus to %s(%s)\n"),
+                // we can't set the focus to the widget now so we remember that
+                // it should be focused and will do it later, during the idle
+                // time, as soon as we can
+                wxLogTrace(TRACE_FOCUS,
+                           _T("Delaying setting focus to %s(%s)"),
                            GetClassInfo()->GetClassName(), GetLabel().c_str());
 
                 g_delayedFocus = this;
             }
             else
             {
-                wxLogTrace(_T("focus"),
-                           _T("Setting focus to %s(%s)\n"),
+                wxLogTrace(TRACE_FOCUS,
+                           _T("Setting focus to %s(%s)"),
                            GetClassInfo()->GetClassName(), GetLabel().c_str());
 
                 gtk_widget_grab_focus (m_widget);
@@ -3254,11 +3193,11 @@ void wxWindowGTK::SetFocus()
         }
         else
         {
-           // ?
+           wxLogTrace(TRACE_FOCUS,
+                      _T("Can't set focus to %s(%s)"),
+                      GetClassInfo()->GetClassName(), GetLabel().c_str());
         }
     }
-
-    (void)DoSendFocusEvents(this);
 }
 
 bool wxWindowGTK::AcceptsFocus() const
@@ -3368,11 +3307,12 @@ void wxWindowGTK::WarpPointer( int x, int y )
         gdk_window_warp_pointer( window, x, y );
 }
 
+
 void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 {
     if (!m_widget) return;
     if (!m_widget->window) return;
-
+    
 #ifndef __WXGTK20__
     if (g_isIdle)
         wxapp_install_idle_handler();
@@ -3467,62 +3407,76 @@ void wxWindowGTK::GtkSendPaintEvents()
         return;
     }
 
+    // widget to draw on
+    GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
+            
+    // Clip to paint region in wxClientDC
     m_clipPaintRegion = TRUE;
+
+#ifndef __WXGTK20__    
+    if (GetThemeEnabled())
+    {
+        // find ancestor from which to steal background
+        wxWindow *parent = GetParent();
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+        if (!parent)
+            parent = (wxWindow*)this;
     
-    // if (!m_clearRegion.IsEmpty())   // always send an erase event
+        wxRegionIterator upd( m_updateRegion );
+        while (upd)
+        {
+            GdkRectangle rect;
+            rect.x = upd.GetX();
+            rect.y = upd.GetY();
+            rect.width = upd.GetWidth();
+            rect.height = upd.GetHeight();
+                    
+            gtk_paint_flat_box( parent->m_widget->style,
+                        pizza->bin_window,
+                        GTK_STATE_NORMAL,
+                        GTK_SHADOW_NONE,
+                        &rect,
+                        parent->m_widget,
+                        (char *)"base",
+                        0, 0, -1, -1 );
+                        
+            upd ++;
+        }
+    }
+    else
+#endif
+#ifdef __WXGTK20__    
+    if (!m_clearRegion.IsEmpty())   // Always send an erase event under GTK 1.2
+#endif
     {
         wxWindowDC dc( (wxWindow*)this );
-        dc.SetClippingRegion( m_clearRegion );
+        if (m_clearRegion.IsEmpty())
+            dc.SetClippingRegion( m_updateRegion );
+        else
+            dc.SetClippingRegion( m_clearRegion );
 
         wxEraseEvent erase_event( GetId(), &dc );
         erase_event.SetEventObject( this );
 
         if (!GetEventHandler()->ProcessEvent(erase_event))
         {
+#ifndef __WXGTK20__    
             if (!g_eraseGC)
             {
-                g_eraseGC = gdk_gc_new( GTK_PIZZA(m_wxwindow)->bin_window );
+                g_eraseGC = gdk_gc_new( pizza->bin_window );
                 gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
             }
             gdk_gc_set_foreground( g_eraseGC, m_backgroundColour.GetColor() );
 
-            // widget to draw on
-            GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
-            
-            // find ancestor from which to steal background
-            wxWindow *parent = GetParent();
-            while (parent && !parent->IsTopLevel())
-                parent = parent->GetParent();
-            if (!parent)
-                parent = this;
-    
             wxRegionIterator upd( m_clearRegion );
             while (upd)
             {
-                if (GetThemeEnabled())
-                { 
-                    GdkRectangle rect;
-                    rect.x = upd.GetX();
-                    rect.y = upd.GetY();
-                    rect.width = upd.GetWidth();
-                    rect.height = upd.GetHeight();
-                    
-                    gtk_paint_flat_box( parent->m_widget->style,
-                        pizza->bin_window,
-                        GTK_STATE_NORMAL,
-                        GTK_SHADOW_NONE,
-                        &rect,
-                        parent->m_widget,
-                        (char *)"base",
-                        0, 0, -1, -1 );
-                }
-                else
-                {
-                    gdk_draw_rectangle( pizza->bin_window, g_eraseGC, 1,
-                                        upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
-                }
+                gdk_draw_rectangle( pizza->bin_window, g_eraseGC, 1,
+                                    upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
                 upd ++;
             }
+#endif
         }
         m_clearRegion.Clear();
     }
@@ -3543,8 +3497,6 @@ void wxWindowGTK::GtkSendPaintEvents()
     // being redrawn because the wxWindows class is allowed to
     // paint over the window-less widgets.
 
-    GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
-
     GList *children = pizza->children;
     while (children)
     {
@@ -3629,12 +3581,9 @@ void wxWindowGTK::GtkSetBackgroundColour( const wxColour &colour )
     // We need the pixel value e.g. for background clearing.
     m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
     
-    if ((m_wxwindow) &&
-        (m_backgroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)))
+    if (m_wxwindow)
     {
-        /* wxMSW doesn't clear the window here. I don't do that either to
-          provide compatibility. call Clear() to do the job. */
-
+        // wxMSW doesn't clear the window here, either.
         gdk_window_set_background( window, m_backgroundColour.GetColor() );
     }
 
@@ -4212,7 +4161,7 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
     wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
-
+    
     // No scrolling requested.
     if ((dx == 0) && (dy == 0)) return;
 
@@ -4236,7 +4185,6 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
         GetClientSize( &cw, &ch );
         m_clearRegion.Intersect( 0, 0, cw, ch );
     }
-
     m_clipPaintRegion = TRUE;
 
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
@@ -4325,3 +4273,4 @@ void wxWinModule::OnExit()
         gdk_gc_unref( g_eraseGC );
 }
 
+// vi:sts=4:sw=4:et