]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
fixed wrong assert
[wxWidgets.git] / src / gtk / window.cpp
index 8bf4d36bfa6d3ba151fd90a54f79baa0f24020ab..ee398f439a8c5c03e6e6ee44a0f0609f0faa57a1 100644 (file)
 #include "gtk/gtk.h"
 #include "gdk/gdkprivate.h"
 #include "gdk/gdkkeysyms.h"
-#include "gdk/gdkx.h"
 #include "wx/gtk/win_gtk.h"
 
+#include "gdk/gdkx.h"
+
 //-----------------------------------------------------------------------------
 // documentation on internals
 //-----------------------------------------------------------------------------
 extern wxList     wxPendingDelete;
 extern bool       g_blockEventsOnDrag;
 extern bool       g_blockEventsOnScroll;
-static bool       g_capturing = FALSE;
+extern wxCursor   g_globalCursor;
+static wxWindow  *g_captureWindow = (wxWindow*) NULL;
 static wxWindow  *g_focusWindow = (wxWindow*) NULL;
 
 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
@@ -175,6 +177,32 @@ void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window
 
 #endif // Debug
 
+//-----------------------------------------------------------------------------
+// missing gdk functions
+//-----------------------------------------------------------------------------
+
+void
+gdk_window_warp_pointer (GdkWindow      *window,
+                         gint            x,
+                         gint            y)
+{
+  GdkWindowPrivate *priv;
+
+  if (!window)
+    window = (GdkWindow*) &gdk_root_parent;
+
+  priv = (GdkWindowPrivate*) window;
+
+  if (!priv->destroyed)
+  {
+      XWarpPointer (priv->xdisplay,
+                    None,              /* not source window -> move from anywhere */
+                    priv->xwindow,  /* dest window */
+                    0, 0, 0, 0,        /* not source window -> move from anywhere */
+                    x, y );
+  }
+}
+
 //-----------------------------------------------------------------------------
 // idle system
 //-----------------------------------------------------------------------------
@@ -186,6 +214,150 @@ extern bool g_isIdle;
 // key event conversion routines
 //-----------------------------------------------------------------------------
 
+#if (GTK_MINOR_VERSION == 0)
+/* these functions are copied verbatim from GTK 1.2 */
+static void
+gdkx_XConvertCase (KeySym symbol,
+                   KeySym *lower,
+                   KeySym *upper)
+{
+  register KeySym sym = symbol;
+
+  g_return_if_fail (lower != NULL);
+  g_return_if_fail (upper != NULL);
+
+  *lower = sym;
+  *upper = sym;
+
+  switch (sym >> 8)
+    {
+#if        defined (GDK_A) && defined (GDK_Ooblique)
+    case 0: /* Latin 1 */
+      if ((sym >= GDK_A) && (sym <= GDK_Z))
+        *lower += (GDK_a - GDK_A);
+      else if ((sym >= GDK_a) && (sym <= GDK_z))
+        *upper -= (GDK_a - GDK_A);
+      else if ((sym >= GDK_Agrave) && (sym <= GDK_Odiaeresis))
+        *lower += (GDK_agrave - GDK_Agrave);
+      else if ((sym >= GDK_agrave) && (sym <= GDK_odiaeresis))
+        *upper -= (GDK_agrave - GDK_Agrave);
+      else if ((sym >= GDK_Ooblique) && (sym <= GDK_Thorn))
+        *lower += (GDK_oslash - GDK_Ooblique);
+      else if ((sym >= GDK_oslash) && (sym <= GDK_thorn))
+        *upper -= (GDK_oslash - GDK_Ooblique);
+      break;
+#endif        /* LATIN1 */
+
+#if        defined (GDK_Aogonek) && defined (GDK_tcedilla)
+    case 1: /* Latin 2 */
+      /* Assume the KeySym is a legal value (ignore discontinuities) */
+      if (sym == GDK_Aogonek)
+        *lower = GDK_aogonek;
+      else if (sym >= GDK_Lstroke && sym <= GDK_Sacute)
+        *lower += (GDK_lstroke - GDK_Lstroke);
+      else if (sym >= GDK_Scaron && sym <= GDK_Zacute)
+        *lower += (GDK_scaron - GDK_Scaron);
+      else if (sym >= GDK_Zcaron && sym <= GDK_Zabovedot)
+        *lower += (GDK_zcaron - GDK_Zcaron);
+      else if (sym == GDK_aogonek)
+        *upper = GDK_Aogonek;
+      else if (sym >= GDK_lstroke && sym <= GDK_sacute)
+        *upper -= (GDK_lstroke - GDK_Lstroke);
+      else if (sym >= GDK_scaron && sym <= GDK_zacute)
+        *upper -= (GDK_scaron - GDK_Scaron);
+      else if (sym >= GDK_zcaron && sym <= GDK_zabovedot)
+        *upper -= (GDK_zcaron - GDK_Zcaron);
+      else if (sym >= GDK_Racute && sym <= GDK_Tcedilla)
+        *lower += (GDK_racute - GDK_Racute);
+      else if (sym >= GDK_racute && sym <= GDK_tcedilla)
+        *upper -= (GDK_racute - GDK_Racute);
+      break;
+#endif        /* LATIN2 */
+
+#if        defined (GDK_Hstroke) && defined (GDK_Cabovedot)
+    case 2: /* Latin 3 */
+      /* Assume the KeySym is a legal value (ignore discontinuities) */
+      if (sym >= GDK_Hstroke && sym <= GDK_Hcircumflex)
+        *lower += (GDK_hstroke - GDK_Hstroke);
+      else if (sym >= GDK_Gbreve && sym <= GDK_Jcircumflex)
+        *lower += (GDK_gbreve - GDK_Gbreve);
+      else if (sym >= GDK_hstroke && sym <= GDK_hcircumflex)
+        *upper -= (GDK_hstroke - GDK_Hstroke);
+      else if (sym >= GDK_gbreve && sym <= GDK_jcircumflex)
+        *upper -= (GDK_gbreve - GDK_Gbreve);
+      else if (sym >= GDK_Cabovedot && sym <= GDK_Scircumflex)
+        *lower += (GDK_cabovedot - GDK_Cabovedot);
+      else if (sym >= GDK_cabovedot && sym <= GDK_scircumflex)
+        *upper -= (GDK_cabovedot - GDK_Cabovedot);
+      break;
+#endif        /* LATIN3 */
+
+#if        defined (GDK_Rcedilla) && defined (GDK_Amacron)
+    case 3: /* Latin 4 */
+      /* Assume the KeySym is a legal value (ignore discontinuities) */
+      if (sym >= GDK_Rcedilla && sym <= GDK_Tslash)
+        *lower += (GDK_rcedilla - GDK_Rcedilla);
+      else if (sym >= GDK_rcedilla && sym <= GDK_tslash)
+        *upper -= (GDK_rcedilla - GDK_Rcedilla);
+      else if (sym == GDK_ENG)
+        *lower = GDK_eng;
+      else if (sym == GDK_eng)
+        *upper = GDK_ENG;
+      else if (sym >= GDK_Amacron && sym <= GDK_Umacron)
+        *lower += (GDK_amacron - GDK_Amacron);
+      else if (sym >= GDK_amacron && sym <= GDK_umacron)
+        *upper -= (GDK_amacron - GDK_Amacron);
+      break;
+#endif        /* LATIN4 */
+
+#if        defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
+    case 6: /* Cyrillic */
+      /* Assume the KeySym is a legal value (ignore discontinuities) */
+      if (sym >= GDK_Serbian_DJE && sym <= GDK_Serbian_DZE)
+        *lower -= (GDK_Serbian_DJE - GDK_Serbian_dje);
+      else if (sym >= GDK_Serbian_dje && sym <= GDK_Serbian_dze)
+        *upper += (GDK_Serbian_DJE - GDK_Serbian_dje);
+      else if (sym >= GDK_Cyrillic_YU && sym <= GDK_Cyrillic_HARDSIGN)
+        *lower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
+      else if (sym >= GDK_Cyrillic_yu && sym <= GDK_Cyrillic_hardsign)
+        *upper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu);
+      break;
+#endif        /* CYRILLIC */
+
+#if        defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
+    case 7: /* Greek */
+      /* Assume the KeySym is a legal value (ignore discontinuities) */
+      if (sym >= GDK_Greek_ALPHAaccent && sym <= GDK_Greek_OMEGAaccent)
+        *lower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
+      else if (sym >= GDK_Greek_alphaaccent && sym <= GDK_Greek_omegaaccent &&
+               sym != GDK_Greek_iotaaccentdieresis &&
+               sym != GDK_Greek_upsilonaccentdieresis)
+        *upper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent);
+      else if (sym >= GDK_Greek_ALPHA && sym <= GDK_Greek_OMEGA)
+        *lower += (GDK_Greek_alpha - GDK_Greek_ALPHA);
+      else if (sym >= GDK_Greek_alpha && sym <= GDK_Greek_omega &&
+               sym != GDK_Greek_finalsmallsigma)
+        *upper -= (GDK_Greek_alpha - GDK_Greek_ALPHA);
+      break;
+#endif        /* GREEK */
+    }
+}
+
+static guint
+gdk_keyval_to_upper (guint          keyval)
+{
+  if (keyval)
+    {
+      KeySym lower_val = 0;
+      KeySym upper_val = 0;
+
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
+      return upper_val;
+    }
+  return 0;
+}
+#endif
+
 static long map_to_unmodified_wx_keysym( KeySym keysym )
 {
     guint key_code = 0;
@@ -196,6 +368,12 @@ static long map_to_unmodified_wx_keysym( KeySym keysym )
         case GDK_Shift_R:       key_code = WXK_SHIFT;       break;
         case GDK_Control_L:
         case GDK_Control_R:     key_code = WXK_CONTROL;     break;
+        case GDK_Meta_L:
+        case GDK_Meta_R:
+        case GDK_Alt_L:
+        case GDK_Alt_R:
+        case GDK_Super_L:
+        case GDK_Super_R:       key_code = WXK_ALT;         break;
         case GDK_Menu:          key_code = WXK_MENU;        break;
         case GDK_Help:          key_code = WXK_HELP;        break;
         case GDK_BackSpace:     key_code = WXK_BACK;        break;
@@ -249,7 +427,7 @@ static long map_to_unmodified_wx_keysym( KeySym keysym )
         case GDK_KP_Down:      key_code = WXK_NUMPAD_DOWN;  break;
         case GDK_KP_Prior:     key_code = WXK_NUMPAD_PRIOR; break;
 //      case GDK_KP_Page_Up:   key_code = WXK_NUMPAD_PAGEUP;   break;
-        case GDK_KP_Next:      key_code = WXK_NUMPAD_PRIOR; break;
+        case GDK_KP_Next:      key_code = WXK_NUMPAD_NEXT;  break;
 //      case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
         case GDK_KP_End:       key_code = WXK_NUMPAD_END;   break;
         case GDK_KP_Begin:     key_code = WXK_NUMPAD_BEGIN; break;
@@ -262,7 +440,7 @@ static long map_to_unmodified_wx_keysym( KeySym keysym )
         case GDK_KP_Subtract:  key_code = WXK_NUMPAD_SUBTRACT;  break;
         case GDK_KP_Decimal:   key_code = WXK_NUMPAD_DECIMAL;   break;
         case GDK_KP_Divide:    key_code = WXK_NUMPAD_DIVIDE;    break;
-    
+
         case GDK_F1:            key_code = WXK_F1;          break;
         case GDK_F2:            key_code = WXK_F2;          break;
         case GDK_F3:            key_code = WXK_F3;          break;
@@ -348,7 +526,7 @@ static long map_to_wx_keysym( KeySym keysym )
         case GDK_KP_Down:      key_code = WXK_DOWN;  break;
         case GDK_KP_Prior:     key_code = WXK_PRIOR; break;
 //      case GDK_KP_Page_Up:   key_code = WXK_PAGEUP; break;
-        case GDK_KP_Next:      key_code = WXK_PRIOR;  break;
+        case GDK_KP_Next:      key_code = WXK_NEXT;  break;
 //      case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
         case GDK_KP_End:       key_code = WXK_END;    break;
         case GDK_KP_Begin:     key_code = WXK_HOME;   break;
@@ -361,7 +539,7 @@ static long map_to_wx_keysym( KeySym keysym )
         case GDK_KP_Subtract:  key_code = '-';   break;
         case GDK_KP_Decimal:   key_code = '.';   break;
         case GDK_KP_Divide:    key_code = '/';   break;
-    
+
         case GDK_F1:            key_code = WXK_F1;          break;
         case GDK_F2:            key_code = WXK_F2;          break;
         case GDK_F3:            key_code = WXK_F3;          break;
@@ -386,14 +564,6 @@ static long map_to_wx_keysym( KeySym keysym )
     return (key_code);
 }
 
-static long get_unmodified_wx_keysym( GdkEventKey *event )
-{
-    KeyCode keycode = XKeysymToKeycode( GDK_DISPLAY(), event->keyval );
-    KeySym keysym = XKeycodeToKeysym( GDK_DISPLAY(), keycode, 0 );
-
-    return (map_to_unmodified_wx_keysym( keysym ));
-}
-
 //-----------------------------------------------------------------------------
 // local code (see below)
 //-----------------------------------------------------------------------------
@@ -429,7 +599,7 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
         if (scroll_window->hscrollbar_visible)
         {
             dh += 15;   /* dh += hscrollbar->allocation.height; */
-            dw += scroll_class->scrollbar_spacing;
+            dh += scroll_class->scrollbar_spacing;
         }
     }
 
@@ -522,7 +692,7 @@ static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExp
 
 static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT)
@@ -544,7 +714,7 @@ static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle
 
 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -562,17 +732,19 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
       printf( "ControlUp.\n" );
     printf( "\n" );
 */
-
-    bool ret = FALSE;
-    
     int x = 0;
     int y = 0;
     GdkModifierType state;
     if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
 
-    long key_code = get_unmodified_wx_keysym( gdk_event );
-    
-    wxKeyEvent event( wxEVT_KEY_DOWN );         
+    long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+
+    /* sending unknown key events doesn't really make sense */
+    if (key_code == 0) return FALSE;
+
+    bool ret = FALSE;
+
+    wxKeyEvent event( wxEVT_KEY_DOWN );
     event.SetTimestamp( gdk_event->time );
     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
     event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
@@ -584,28 +756,10 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
     event.m_y = y;
     event.SetEventObject( win );
     ret = win->GetEventHandler()->ProcessEvent( event );
-    
-    key_code = map_to_wx_keysym( gdk_event->keyval );
 
-    /* wxMSW doesn't send char events with Alt pressed */
-    if ((key_code != 0) &&
-        ((gdk_event->state & GDK_MOD1_MASK) == 0) &&
-        ((gdk_event->state & GDK_MOD1_MASK) == 0))
-    {
-        wxKeyEvent event2( wxEVT_CHAR );                 
-        event2.SetTimestamp( gdk_event->time );
-        event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
-        event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
-//        event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
-//        event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
-        event2.m_keyCode = key_code;
-        event2.m_scanCode = gdk_event->keyval;
-        event2.m_x = x;
-        event2.m_y = y;
-        event2.SetEventObject( win );
-        ret = (ret || win->GetEventHandler()->ProcessEvent( event2 ));
-    }
+    key_code = map_to_wx_keysym( gdk_event->keyval );
 
+#if wxUSE_ACCEL
     if (!ret)
     {
         wxWindow *ancestor = win;
@@ -621,8 +775,28 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
             ancestor = ancestor->GetParent();
         }
     }
+#endif // wxUSE_ACCEL
+    /* wxMSW doesn't send char events with Alt pressed */
+    /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
+       will only be sent if it is not a menu accelerator. */
+    if ((key_code != 0) && ! ret )
+    {
+        wxKeyEvent event2( wxEVT_CHAR );
+        event2.SetTimestamp( gdk_event->time );
+        event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
+        event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
+        event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
+        event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
+        event2.m_keyCode = key_code;
+        event2.m_scanCode = gdk_event->keyval;
+        event2.m_x = x;
+        event2.m_y = y;
+        event2.SetEventObject( win );
+        ret = (ret || win->GetEventHandler()->ProcessEvent( event2 ));
+    }
+
 
-    // 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)) &&
          (win->HasFlag(wxTE_PROCESS_TAB) == 0))
@@ -636,6 +810,7 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
         ret = win->GetEventHandler()->ProcessEvent( new_event );
     }
 
+    /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
     if ( (!ret) &&
          (gdk_event->keyval == GDK_Escape) )
     {
@@ -644,6 +819,36 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
         ret = win->GetEventHandler()->ProcessEvent( new_event );
     }
 
+#if (GTK_MINOR_VERSION > 0)
+    /* pressing F10 will activate the menu bar of the top frame */
+    if ( (!ret) &&
+         (gdk_event->keyval == GDK_F10) )
+    {
+        wxWindow *ancestor = win;
+        while (ancestor)
+        {
+            if (wxIsKindOf(ancestor,wxFrame))
+            {
+                wxFrame *frame = (wxFrame*) ancestor;
+                wxMenuBar *menubar = frame->GetMenuBar();
+                if (menubar)
+                {
+                    wxNode *node = menubar->GetMenus().First();
+                    if (node)
+                    {
+                        // doesn't work correctly
+            // wxMenu *firstMenu = (wxMenu*) node->Data();
+                        // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
+                        // ret = TRUE;
+                        break;
+                    }
+                }
+            }
+            ancestor = ancestor->GetParent();
+        }
+    }
+#endif
+
 /*
     Damn, I forgot why this didn't work, but it didn't work.
 
@@ -682,7 +887,7 @@ 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 )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -701,7 +906,10 @@ static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk
     printf( "\n" );
 */
 
-    long key_code = get_unmodified_wx_keysym( gdk_event );
+    long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
+
+    /* sending unknown key events doesn't really make sense */
+    if (key_code == 0) return FALSE;
 
     int x = 0;
     int y = 0;
@@ -735,7 +943,7 @@ 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 )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
 /*
@@ -819,7 +1027,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
     // Some control don't have their own X window and thus cannot get
     // any events.
 
-    if (!g_capturing)
+    if (!g_captureWindow)
     {
         wxNode *node = win->GetChildren().First();
         while (node)
@@ -889,7 +1097,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton
 
 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -929,7 +1137,7 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
     // Some control don't have their own X window and thus cannot get
     // any events.
 
-    if (!g_capturing)
+    if (!g_captureWindow)
     {
         wxNode *node = win->GetChildren().First();
         while (node)
@@ -997,7 +1205,7 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
 
 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -1040,7 +1248,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
     // Some control don't have their own X window and thus cannot get
     // any events.
 
-    if (!g_capturing)
+    if (!g_captureWindow)
     {
         wxNode *node = win->GetChildren().First();
         while (node)
@@ -1108,7 +1316,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
 
 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -1158,7 +1366,7 @@ 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 )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -1195,7 +1403,7 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
 
 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
@@ -1203,11 +1411,10 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
-    if (widget->window && win->GetCursor().Ok() )
-        gdk_window_set_cursor( widget->window, win->GetCursor().GetCursor() );
-
     wxMouseEvent event( wxEVT_ENTER_WINDOW );
+#if (GTK_MINOR_VERSION > 0)
     event.SetTimestamp( gdk_event->time );
+#endif
     event.SetEventObject( win );
 
     int x = 0;
@@ -1242,19 +1449,18 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (!win->m_hasVMT) return FALSE;
     if (g_blockEventsOnDrag) return FALSE;
 
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
-    
-    if (widget->window && win->GetCursor().Ok() )
-        gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
 
     wxMouseEvent event( wxEVT_LEAVE_WINDOW );
+#if (GTK_MINOR_VERSION > 0)
     event.SetTimestamp( gdk_event->time );
+#endif
     event.SetEventObject( win );
 
     int x = 0;
@@ -1289,7 +1495,7 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
 static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (g_blockEventsOnDrag) return;
@@ -1333,7 +1539,7 @@ static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *
 
 static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (g_blockEventsOnDrag) return;
@@ -1376,7 +1582,7 @@ static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *
 
 static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (g_blockEventsOnDrag) return;
@@ -1396,7 +1602,7 @@ static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxW
 
 static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (g_blockEventsOnDrag) return;
@@ -1418,7 +1624,7 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
                                                  GdkEventButton *WXUNUSED(gdk_event),
                                                  wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
 //  don't test here as we can release the mouse while being over
@@ -1477,7 +1683,7 @@ wxWindow *wxWindowBase::FindFocus()
 static gint
 gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
 {
-    if (g_isIdle) 
+    if (g_isIdle)
         wxapp_install_idle_handler();
 
     if (win->m_delayedFont)
@@ -1491,6 +1697,10 @@ gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
 
     win->SetCursor( win->GetCursor() );
 
+    wxWindowCreateEvent event( win );
+    event.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( event );
+
     return FALSE;
 }
 
@@ -1569,7 +1779,7 @@ void wxWindow::Init()
     m_scrollGC = (GdkGC*) NULL;
     m_widgetStyle = (GtkStyle*) NULL;
 
-    m_insertCallback = wxInsertChildInWindow;
+    m_insertCallback = (wxInsertChildFunction) NULL;
 
     m_isStaticBox = FALSE;
     m_acceptsFocus = FALSE;
@@ -1595,6 +1805,8 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
 {
     PreCreation( parent, id, pos, size, style, name );
 
+    m_insertCallback = wxInsertChildInWindow;
+
     m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
     GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
 
@@ -1750,25 +1962,25 @@ wxWindow::~wxWindow()
     if (m_widgetStyle)
     {
         gtk_style_unref( m_widgetStyle );
-       m_widgetStyle = (GtkStyle*) NULL;
+        m_widgetStyle = (GtkStyle*) NULL;
     }
 
     if (m_scrollGC)
     {
         gdk_gc_unref( m_scrollGC );
-       m_scrollGC = (GdkGC*) NULL;
+        m_scrollGC = (GdkGC*) NULL;
     }
 
     if (m_wxwindow)
     {
         gtk_widget_destroy( m_wxwindow );
-       m_wxwindow = (GtkWidget*) NULL;
+        m_wxwindow = (GtkWidget*) NULL;
     }
 
     if (m_widget)
     {
         gtk_widget_destroy( m_widget );
-       m_widget = (GtkWidget*) NULL;
+        m_widget = (GtkWidget*) NULL;
     }
 }
 
@@ -1837,7 +2049,7 @@ void wxWindow::PostCreation()
    /*  we cannot set colours, fonts and cursors before the widget has
        been realized, so we do this directly after realization */
     gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
-                           GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
+                            GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
 
     m_hasVMT = TRUE;
 }
@@ -1899,7 +2111,7 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
     }
     else
     {
-        if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
+        if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
         {
             if (x != -1) m_x = x;
             if (y != -1) m_y = y;
@@ -1930,40 +2142,42 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
         if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
 
         int border = 0;
+        int bottom_border = 0;
 
-        if (GTK_WIDGET_HAS_DEFAULT(m_widget))
-       {
-           /* the default button has a border around it */
-           border = 5;
-       }
-
-       /* this is the result of hours of debugging: the following code
-          means that if we have a m_wxwindow and we set the size of
-          m_widget, m_widget (which is a GtkScrolledWindow) does NOT
-          automatically propagate its size down to its m_wxwindow,
-          which is its client area. therefore, we have to tell the
-          client area directly that it has to resize itself.
-          this will lead to that m_widget (GtkScrolledWindow) will
-          calculate how much size it needs for scrollbars etc and
-          it will then call XXX_size_allocate of its child, which
-          is m_wxwindow. m_wxwindow in turn will do the same with its
-          children and so on. problems can arise if this happens
-          before all the children have been realized as some widgets
-          stupidy need to be realized during XXX_size_allocate (e.g.
-          GtkNotebook) and they will segv if called otherwise. this
-          emergency is tested in gtk_myfixed_size_allocate. Normally
-          this shouldn't be needed and only gtk_widget_queue_resize()
-          should be enough to provoke a resize at the next appropriate
-          moment, but this seems to fail, e.g. when a wxNotebook contains
-          a wxSplitterWindow: the splitter window's children won't
-          show up properly resized then. */
-          
-        gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow), 
-                             m_widget, 
-                             m_x-border, 
-                             m_y-border,
-                             m_width+2*border, 
-                             m_height+2*border );
+        if (GTK_WIDGET_CAN_DEFAULT(m_widget))
+        {
+            /* the default button has a border around it */
+            border = 6;
+            bottom_border = 5;
+        }
+
+        /* this is the result of hours of debugging: the following code
+           means that if we have a m_wxwindow and we set the size of
+           m_widget, m_widget (which is a GtkScrolledWindow) does NOT
+           automatically propagate its size down to its m_wxwindow,
+           which is its client area. therefore, we have to tell the
+           client area directly that it has to resize itself.
+           this will lead to that m_widget (GtkScrolledWindow) will
+           calculate how much size it needs for scrollbars etc and
+           it will then call XXX_size_allocate of its child, which
+           is m_wxwindow. m_wxwindow in turn will do the same with its
+           children and so on. problems can arise if this happens
+           before all the children have been realized as some widgets
+           stupidy need to be realized during XXX_size_allocate (e.g.
+           GtkNotebook) and they will segv if called otherwise. this
+           emergency is tested in gtk_myfixed_size_allocate. Normally
+           this shouldn't be needed and only gtk_widget_queue_resize()
+           should be enough to provoke a resize at the next appropriate
+           moment, but this seems to fail, e.g. when a wxNotebook contains
+           a wxSplitterWindow: the splitter window's children won't
+           show up properly resized then. */
+
+        gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
+                              m_widget,
+                              m_x-border,
+                              m_y-border,
+                              m_width+2*border,
+                              m_height+border+bottom_border );
     }
 
     m_sizeSet = TRUE;
@@ -1977,6 +2191,19 @@ void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
 
 void wxWindow::OnInternalIdle()
 {
+        GdkWindow *window = GetConnectWidget()->window;
+        if (window)
+        {
+            wxCursor cursor = m_cursor;
+            if (g_globalCursor.Ok()) cursor = g_globalCursor;
+
+            if (cursor.Ok() && m_currentGdkCursor != cursor)
+            {
+                gdk_window_set_cursor( window, cursor.GetCursor() );
+                m_currentGdkCursor = cursor;
+            }
+        }
+
     UpdateWindowUI();
 }
 
@@ -2043,7 +2270,7 @@ void wxWindow::DoSetClientSize( int width, int height )
             if (scroll_window->hscrollbar_visible)
             {
                 dh += 15;   /* dh += hscrollbar->allocation.height; */
-                dw += scroll_class->scrollbar_spacing;
+                dh += scroll_class->scrollbar_spacing;
             }
        }
 
@@ -2123,7 +2350,7 @@ void wxWindow::DoGetPosition( int *x, int *y ) const
     if (y) (*y) = m_y;
 }
 
-void wxWindow::ClientToScreen( int *x, int *y ) const
+void wxWindow::DoClientToScreen( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
 
@@ -2152,7 +2379,7 @@ void wxWindow::ClientToScreen( int *x, int *y ) const
     if (y) *y += org_y;
 }
 
-void wxWindow::ScreenToClient( int *x, int *y ) const
+void wxWindow::DoScreenToClient( int *x, int *y ) const
 {
     wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
 
@@ -2285,16 +2512,42 @@ bool wxWindow::AcceptsFocus() const
 
 bool wxWindow::Reparent( wxWindow *newParent )
 {
-    wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, _T("invalid window") );
+    wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
 
-    gtk_widget_unparent( m_widget );
+    wxWindow *oldParent = m_parent;
 
     if ( !wxWindowBase::Reparent(newParent) )
         return FALSE;
 
+    if (oldParent)
+    {
+        gtk_container_remove( GTK_CONTAINER(oldParent->m_wxwindow), m_widget );
+    }
+
+    if (newParent)
+    {
+        /* insert GTK representation */
+        (*(newParent->m_insertCallback))(newParent, this);
+    }
+
     return TRUE;
 }
 
+void wxWindow::DoAddChild(wxWindow *child)
+{
+    wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
+
+    wxASSERT_MSG( (child != NULL), _T("invalid child window") );
+
+    wxASSERT_MSG( (m_insertCallback != NULL), _T("invalid child insertion function") );
+
+    /* add to list */
+    AddChild( child );
+
+    /* insert GTK representation */
+    (*m_insertCallback)(this, child);
+}
+
 void wxWindow::Raise()
 {
     wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
@@ -2323,32 +2576,36 @@ bool wxWindow::SetCursor( const wxCursor &cursor )
         // been realized
         if (!m_delayedCursor) return FALSE;
     }
-    
+
     GtkWidget *connect_widget = GetConnectWidget();
     if (!connect_widget->window)
     {
         // indicate that a new style has been set
-       // but it couldn't get applied as the
-       // widget hasn't been realized yet.
-       m_delayedCursor = TRUE;
-       
-       // pretend we have done something
+        // but it couldn't get applied as the
+        // widget hasn't been realized yet.
+        m_delayedCursor = TRUE;
+
+        // pretend we have done something
         return TRUE;
     }
 
-        if ((m_widget) && (m_widget->window))
-             gdk_window_set_cursor( m_widget->window, GetCursor().GetCursor() );
-
-        if ((m_wxwindow) && (m_wxwindow->window))
-             gdk_window_set_cursor( m_wxwindow->window, GetCursor().GetCursor() );
+//    gdk_window_set_cursor( connect_widget->window, GetCursor().GetCursor() );
 
     // cursor was set
     return TRUE;
 }
 
-void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
+void wxWindow::WarpPointer( int x, int y )
 {
-    // TODO
+    wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
+
+    GtkWidget *connect_widget = GetConnectWidget();
+    if (connect_widget->window)
+    {
+        /* we provide this function ourselves as it is
+           missing in GDK */
+        gdk_window_warp_pointer( connect_widget->window, x, y );
+    }
 }
 
 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
@@ -2416,7 +2673,7 @@ void wxWindow::DoSetToolTip( wxToolTip *tip )
 
 void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
 {
-    gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConv_current->cWX2MB(tip), (gchar*) NULL );
+    gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
 }
 #endif // wxUSE_TOOLTIPS
 
@@ -2430,16 +2687,16 @@ bool wxWindow::SetBackgroundColour( const wxColour &colour )
         // been realized
         if (!m_delayedBackgroundColour) return FALSE;
     }
-    
+
     GtkWidget *connect_widget = GetConnectWidget();
     if (!connect_widget->window)
     {
         // indicate that a new style has been set
-       // but it couldn't get applied as the
-       // widget hasn't been realized yet.
-       m_delayedBackgroundColour = TRUE;
-       
-       // pretend we have done something
+        // but it couldn't get applied as the
+        // widget hasn't been realized yet.
+        m_delayedBackgroundColour = TRUE;
+
+        // pretend we have done something
         return TRUE;
     }
 
@@ -2453,7 +2710,6 @@ bool wxWindow::SetBackgroundColour( const wxColour &colour )
     }
 
     wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
-
     if (sysbg == m_backgroundColour)
     {
         m_backgroundColour = wxNullColour;
@@ -2478,21 +2734,21 @@ bool wxWindow::SetForegroundColour( const wxColour &colour )
         // been realized
         if (!m_delayedForegroundColour) return FALSE;
     }
-    
+
     GtkWidget *connect_widget = GetConnectWidget();
     if (!connect_widget->window)
     {
         // indicate that a new style has been set
-       // but it couldn't get applied as the
-       // widget hasn't been realized yet.
-       m_delayedForegroundColour = TRUE;
-       
-       // pretend we have done something
+        // but it couldn't get applied as the
+        // widget hasn't been realized yet.
+        m_delayedForegroundColour = TRUE;
+
+        // pretend we have done something
         return TRUE;
     }
 
     wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
-    if (sysbg == m_foregroundColour)
+    if ( sysbg == m_backgroundColour )
     {
         m_backgroundColour = wxNullColour;
         ApplyWidgetStyle();
@@ -2634,7 +2890,7 @@ bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
 
 bool wxWindow::SetFont( const wxFont &font )
 {
-    wxCHECK_MSG( m_widget != NULL, FALSE, _T(  "invalid window") );
+    wxCHECK_MSG( m_widget != NULL, FALSE, _T(        "invalid window") );
 
     if (!wxWindowBase::SetFont(font))
     {
@@ -2642,16 +2898,16 @@ bool wxWindow::SetFont( const wxFont &font )
         // been realized
         if (!m_delayedFont) return FALSE;
     }
-    
+
     GtkWidget *connect_widget = GetConnectWidget();
     if (!connect_widget->window)
     {
         // indicate that a new style has been set
-       // but it couldn't get applied as the
-       // widget hasn't been realized yet.
-       m_delayedFont = TRUE;
-       
-       // pretend we have done something
+        // but it couldn't get applied as the
+        // widget hasn't been realized yet.
+        m_delayedFont = TRUE;
+
+        // pretend we have done something
         return TRUE;
     }
 
@@ -2674,35 +2930,33 @@ void wxWindow::CaptureMouse()
 {
     wxCHECK_RET( m_widget != NULL, _T("invalid window") );
 
-    wxCHECK_RET( g_capturing == FALSE, _T("CaptureMouse called twice") );
+    wxCHECK_RET( g_captureWindow == NULL, _T("CaptureMouse called twice") );
 
     GtkWidget *connect_widget = GetConnectWidget();
     if (!connect_widget->window) return;
-    
-    gtk_grab_add( connect_widget );
+
     gdk_pointer_grab( connect_widget->window, FALSE,
                       (GdkEventMask)
                          (GDK_BUTTON_PRESS_MASK |
                           GDK_BUTTON_RELEASE_MASK |
                           GDK_POINTER_MOTION_MASK),
                       (GdkWindow *) NULL,
-                      (GdkCursor *) NULL,
+                      m_cursor.GetCursor(),
                       GDK_CURRENT_TIME );
-    g_capturing = TRUE;
+    g_captureWindow = this;
 }
 
 void wxWindow::ReleaseMouse()
 {
     wxCHECK_RET( m_widget != NULL, _T("invalid window") );
 
-    wxCHECK_RET( g_capturing == TRUE, _T("ReleaseMouse called twice") );
+    wxCHECK_RET( g_captureWindow, _T("ReleaseMouse called twice") );
 
     GtkWidget *connect_widget = GetConnectWidget();
     if (!connect_widget->window) return;
-    
-    gtk_grab_remove( connect_widget );
+
     gdk_pointer_ungrab ( GDK_CURRENT_TIME );
-    g_capturing = FALSE;
+    g_captureWindow = (wxWindow*) NULL;
 }
 
 bool wxWindow::IsRetained() const
@@ -2861,12 +3115,23 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
         gdk_gc_set_exposures( m_scrollGC, TRUE );
     }
 
+    wxNode *node = m_children.First();
+    while (node)
+    {
+        wxWindow *child = (wxWindow*) node->Data();
+        int sx = 0;
+        int sy = 0;
+        child->GetSize( &sx, &sy );
+        child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
+        node = node->Next();
+    }
+
     int cw = 0;
     int ch = 0;
     GetClientSize( &cw, &ch );
     int w = cw - abs(dx);
     int h = ch - abs(dy);
-    
+
     if ((h < 0) || (w < 0))
     {
         Refresh();
@@ -2893,14 +3158,6 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
         Refresh( TRUE, &rect );
     }
-    
-    wxNode *node = m_children.First();
-    while (node)
-    {
-        wxWindow *child = (wxWindow*) node->Data();
-       child->Move( child->m_x + dx, child->m_y + dy );
-       node = node->Next();
-    }
 }
 
 void wxWindow::SetScrolling(bool scroll)