]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
made unzip.c accept / and \ in filenames as equal
[wxWidgets.git] / src / gtk / window.cpp
index 312ecb5854f81af2995926641e48634bd3cae260..c12549013e45d8471db958267e60df16d0aa8cb3 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
@@ -185,7 +189,8 @@ extern bool       g_blockEventsOnDrag;
 extern bool       g_blockEventsOnScroll;
 extern wxCursor   g_globalCursor;
 static wxWindow  *g_captureWindow = (wxWindow*) NULL;
-static wxWindow  *g_focusWindow = (wxWindow*) NULL;
+
+/* extern */ wxWindow  *g_focusWindow = (wxWindow*) NULL;
 
 // if we detect that the app has got/lost the focus, we set this variable to
 // either TRUE or FALSE and an activate event will be sent during the next
@@ -197,12 +202,20 @@ static int        g_sendActivateEvent = -1;
    the last click here */
 static guint32 gs_timeLastClick = 0;
 
+extern bool g_mainThreadLocked;
+
 //-----------------------------------------------------------------------------
 // debug
 //-----------------------------------------------------------------------------
 
 #ifdef __WXDEBUG__
 
+#if wxUSE_THREADS
+#   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
+#else
+#   define DEBUG_MAIN_THREAD
+#endif
+
 static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
                                          GdkEvent *WXUNUSED(event),
                                          const wxChar *WXUNUSED(name) )
@@ -222,18 +235,25 @@ static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
 
 void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
 {
-    wxString tmp = name;
-    tmp += wxT(" FROM ");
-    tmp += window;
+    // suppress warnings about gtk_debug_focus_in_callback being unused with
+    // this "if ( 0 )"
+    if ( 0 )
+    {
+        wxString tmp = name;
+        tmp += wxT(" FROM ");
+        tmp += window;
 
-    wxChar *s = new wxChar[tmp.Length()+1];
+        wxChar *s = new wxChar[tmp.Length()+1];
 
-    wxStrcpy( s, tmp );
+        wxStrcpy( s, tmp );
 
-    gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
-      GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
+        gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
+          GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
+    }
 }
 
+#else
+#define DEBUG_MAIN_THREAD
 #endif // Debug
 
 //-----------------------------------------------------------------------------
@@ -281,29 +301,35 @@ static void draw_frame( GtkWidget *widget, wxWindow *win )
     int dw = 0;
     int dh = 0;
 
-    if (win->HasScrolling())
+    if (win->m_hasScrolling)
     {
-        GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
-        GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
+            GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
+            
+            GtkRequisition vscroll_req;
+            vscroll_req.width = 2;
+            vscroll_req.height = 2;
+            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+                (scroll_window->vscrollbar, &vscroll_req );
+                
+            GtkRequisition hscroll_req;
+            hscroll_req.width = 2;
+            hscroll_req.height = 2;
+            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+                (scroll_window->hscrollbar, &hscroll_req );
 
-/*
-            GtkWidget *hscrollbar = scroll_window->hscrollbar;
-            GtkWidget *vscrollbar = scroll_window->vscrollbar;
-
-            we use this instead:  range.slider_width = 11 + 2*2pts edge
-*/
+            GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
 
-        if (scroll_window->vscrollbar_visible)
-        {
-            dw += 15;   /* dw += vscrollbar->allocation.width; */
-            dw += scroll_class->scrollbar_spacing;
-        }
+            if (scroll_window->vscrollbar_visible)
+            {
+                dw += vscroll_req.width;
+                dw += scroll_class->scrollbar_spacing;
+            }
 
-        if (scroll_window->hscrollbar_visible)
-        {
-            dh += 15;   /* dh += hscrollbar->allocation.height; */
-            dh += scroll_class->scrollbar_spacing;
-        }
+            if (scroll_window->hscrollbar_visible)
+            {
+                dh += hscroll_req.height;
+                dh += scroll_class->scrollbar_spacing;
+            }
     }
 
     int dx = 0;
@@ -321,7 +347,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;
     }
 
@@ -332,7 +358,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;
     }
 
@@ -343,7 +369,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;
     }
@@ -584,6 +610,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;
 
@@ -592,9 +620,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())
@@ -605,6 +630,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);
@@ -623,6 +651,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();
 
@@ -659,6 +689,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();
 
@@ -666,17 +698,12 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
     if (g_blockEventsOnDrag) return FALSE;
 
 /*
+    wxString tmp;
+    tmp += (char)gdk_event->keyval;
+    printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
     printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
-    if (gdk_event->state & GDK_SHIFT_MASK)
-      printf( "ShiftDown.\n" );
-    else
-      printf( "ShiftUp.\n" );
-    if (gdk_event->state & GDK_CONTROL_MASK)
-      printf( "ControlDown.\n" );
-    else
-      printf( "ControlUp.\n" );
-    printf( "\n" );
 */
+    
     int x = 0;
     int y = 0;
     GdkModifierType state;
@@ -751,13 +778,13 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
          (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
     {
         wxNavigationKeyEvent new_event;
-        new_event.SetEventObject( win );
+        new_event.SetEventObject( win->GetParent() );
         /* 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 */
         new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
         new_event.SetCurrentFocus( win );
-        ret = win->GetEventHandler()->ProcessEvent( new_event );
+        ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
     }
 
     /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
@@ -816,6 +843,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();
 
@@ -872,6 +901,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();
 
@@ -943,8 +974,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.
@@ -1036,6 +1067,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();
 
@@ -1070,8 +1103,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.
@@ -1154,6 +1187,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();
 
@@ -1190,8 +1225,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.
@@ -1274,6 +1309,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();
 
@@ -1311,6 +1348,11 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(
         panel->SetLastFocus(win);
     }
 
+#ifdef HAVE_XIM
+    if (win->m_ic)
+        gdk_im_begin(win->m_ic, win->m_wxwindow->window);
+#endif
+
     wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
     event.SetEventObject( win );
 
@@ -1329,6 +1371,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();
 
@@ -1349,6 +1393,11 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
     printf( ".\n" );
 */
 
+#ifdef HAVE_XIM
+    if (win->m_ic)
+        gdk_im_end();
+#endif
+
     wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
     event.SetEventObject( win );
 
@@ -1367,6 +1416,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();
 
@@ -1395,8 +1446,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 ))
     {
@@ -1413,6 +1464,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();
 
@@ -1441,8 +1494,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 ))
     {
@@ -1459,6 +1512,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();
 
@@ -1493,6 +1548,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();
 
@@ -1526,6 +1583,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();
 
@@ -1546,6 +1605,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();
 
@@ -1566,8 +1627,10 @@ static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxW
 
 static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
                                                  GdkEventButton *WXUNUSED(gdk_event),
-                                                 wxWindow *win )
+                                                 wxWindow *win)
 {
+    DEBUG_MAIN_THREAD
+
     if (g_isIdle)
         wxapp_install_idle_handler();
 
@@ -1576,7 +1639,8 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
 //
 //    if (gdk_event->window != widget->slider) return FALSE;
 
-    win->SetScrolling( TRUE );
+    g_blockEventsOnScroll = TRUE;
+    win->m_isScrolling = TRUE;
 
     return FALSE;
 }
@@ -1585,17 +1649,43 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
 // "button_release_event" from scrollbar
 //-----------------------------------------------------------------------------
 
-static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
+static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
                                                    GdkEventButton *WXUNUSED(gdk_event),
-                                                   wxWindow *win )
+                                                   wxWindow *win)
 {
+    DEBUG_MAIN_THREAD
+
 
 //  don't test here as we can release the mouse while being over
 //  a different window than the slider
 //
 //    if (gdk_event->window != widget->slider) return FALSE;
 
-    win->SetScrolling( FALSE );
+    wxASSERT( win->m_isScrolling );
+
+    g_blockEventsOnScroll = FALSE;
+    win->m_isScrolling = FALSE;
+
+    wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
+    int value = -1;
+    int dir = -1;
+    
+    GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
+    if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
+    {
+        value = (int)(win->m_hAdjust->value+0.5);
+        dir = wxHORIZONTAL;
+    }
+    if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
+    {
+        value = (int)(win->m_vAdjust->value+0.5);
+        dir = wxVERTICAL;
+    }
+
+    wxScrollWinEvent event( command, value, dir );
+    event.SetScrolling( FALSE );
+    event.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( event );
 
     return FALSE;
 }
@@ -1614,18 +1704,17 @@ wxWindow *wxWindowBase::FindFocus()
 // "realize" from m_widget
 //-----------------------------------------------------------------------------
 
-/* we cannot set colours and fonts before the widget has
-   been realized, so we do this directly after realization */
+/* We cannot set colours and fonts before the widget has
+   been realized, so we do this directly after realization. */
 
 static gint
-gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
+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() );
 
@@ -1639,6 +1728,163 @@ gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
     return FALSE;
 }
 
+//-----------------------------------------------------------------------------
+// "size_allocate"
+//-----------------------------------------------------------------------------
+
+static
+void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
+                               GtkAllocation *WXUNUSED(alloc),
+                               wxWindow *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+    
+    if (!win->m_hasScrolling) return;
+    
+    int client_width = 0;
+    int client_height = 0;
+    win->GetClientSize( &client_width, &client_height );
+    if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
+        return;
+        
+    win->m_oldClientWidth = client_width;
+    win->m_oldClientHeight = client_height;
+    
+    if (!win->m_nativeSizeEvent)
+    {
+        wxSizeEvent event( win->GetSize(), win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
+    }
+}
+
+
+#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* WXUNUSED_UNLESS_XIM(widget),
+                                 GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
+                                 wxWindow* WXUNUSED_UNLESS_XIM(win) )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+        
+#ifdef HAVE_XIM
+    if (!win->m_ic)
+        return;
+
+    if  (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
+    {
+        gint 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);
+    }
+#endif // HAVE_XIM
+}
+
+//-----------------------------------------------------------------------------
+// "realize" from m_wxwindow
+//-----------------------------------------------------------------------------
+
+/* Initialize XIM support */
+
+static gint
+gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
+                                wxWindow * WXUNUSED_UNLESS_XIM(win) )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+#ifdef HAVE_XIM
+    if (win->m_ic) return FALSE;
+    if (!widget) return FALSE;
+    if (!gdk_im_ready()) return FALSE;
+
+    win->m_icattr = gdk_ic_attr_new();
+    if (!win->m_icattr) return FALSE;
+    
+    gint width, height;
+    GdkEventMask mask;
+    GdkColormap *colormap;
+    GdkICAttr *attr = win->m_icattr;
+    unsigned attrmask = GDK_IC_ALL_REQ;
+    GdkIMStyle style;
+    GdkIMStyle supported_style = (GdkIMStyle)
+                                  (GDK_IM_PREEDIT_NONE |
+                                  GDK_IM_PREEDIT_NOTHING |
+                                  GDK_IM_PREEDIT_POSITION |
+                                  GDK_IM_STATUS_NONE |
+                                  GDK_IM_STATUS_NOTHING);
+
+    if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+       supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
+
+    attr->style = style = gdk_im_decide_style (supported_style);
+    attr->client_window = widget->window;
+
+    if ((colormap = gtk_widget_get_colormap (widget)) !=
+           gtk_widget_get_default_colormap ())
+    {
+       attrmask |= GDK_IC_PREEDIT_COLORMAP;
+       attr->preedit_colormap = colormap;
+    }
+    
+    attrmask |= GDK_IC_PREEDIT_FOREGROUND;
+    attrmask |= GDK_IC_PREEDIT_BACKGROUND;
+    attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
+    attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
+
+    switch (style & GDK_IM_PREEDIT_MASK)
+    {
+       case GDK_IM_PREEDIT_POSITION:
+         if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
+           {
+             g_warning ("over-the-spot style requires fontset");
+             break;
+           }
+
+         gdk_window_get_size (widget->window, &width, &height);
+
+         attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
+         attr->spot_location.x = 0;
+         attr->spot_location.y = height;
+         attr->preedit_area.x = 0;
+         attr->preedit_area.y = 0;
+         attr->preedit_area.width = width;
+         attr->preedit_area.height = height;
+         attr->preedit_fontset = widget->style->font;
+
+         break;
+    }
+       
+      win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
+     
+      if (win->m_ic == NULL)
+       g_warning ("Can't create input context.");
+      else
+       {
+         mask = gdk_window_get_events (widget->window);
+         mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
+         gdk_window_set_events (widget->window, mask);
+
+         if (GTK_WIDGET_HAS_FOCUS(widget))
+           gdk_im_begin (win->m_ic, widget->window);
+       }
+#endif
+
+    return FALSE;
+}
+
 //-----------------------------------------------------------------------------
 // InsertChild for wxWindow.
 //-----------------------------------------------------------------------------
@@ -1723,6 +1969,11 @@ void wxWindow::Init()
     m_acceptsFocus = FALSE;
 
     m_cursor = *wxSTANDARD_CURSOR;
+    
+#ifdef HAVE_XIM
+    m_ic = (GdkIC*) NULL;
+    m_icattr = (GdkICAttr*) NULL;
+#endif
 }
 
 wxWindow::wxWindow()
@@ -1898,6 +2149,13 @@ wxWindow::~wxWindow()
     if (m_parent)
         m_parent->RemoveChild( this );
 
+#ifdef HAVE_XIM
+    if (m_ic)
+        gdk_ic_destroy (m_ic);
+    if (m_icattr)
+        gdk_ic_attr_destroy (m_icattr);
+#endif
+
     if (m_widgetStyle)
     {
         gtk_style_unref( m_widgetStyle );
@@ -1975,15 +2233,50 @@ void wxWindow::PostCreation()
 #endif
     }
 
+    if (m_wxwindow && m_needParent)
+    {
+        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
+            GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
+            GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+    }
+    else
+    {
+        // For dialogs and frames, we are interested mainly in
+       // m_widget's focus.
+       
+        gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
+            GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
+
+        gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
+            GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
+    }
+
     GtkWidget *connect_widget = GetConnectWidget();
 
     ConnectWidget( connect_widget );
 
-   /*  we cannot set colours, fonts and cursors before the widget has
+    /* 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 );
+    if (m_wxwindow)
+    {
+        /* Catch native resize events. */
+        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
+                            GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
+                            
+        /* Initialize XIM support. */
+        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
+                            GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
 
+        /* And resize XIM window. */
+        gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
+                            GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
+    }
+    
     m_hasVMT = TRUE;
 }
 
@@ -2004,12 +2297,6 @@ void wxWindow::ConnectWidget( GtkWidget *widget )
     gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
       GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
 
-    gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
-      GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
-
-    gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
-      GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
-
     gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
       GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
 
@@ -2026,6 +2313,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") );
@@ -2086,12 +2378,15 @@ 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 );
+    }
+
+    if (m_hasScrolling)
+    {
+        GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
     }
 
 /*
@@ -2184,24 +2479,6 @@ void wxWindow::DoSetClientSize( int width, int height )
         int dw = 0;
         int dh = 0;
 
-#if (GTK_MINOR_VERSION == 0)
-        if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
-        {
-            if (HasScrolling())
-            {
-                GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-#if 0 // unused - if this is ok, just remove this line (VZ)
-                GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
-#endif // 0
-
-                GtkWidget *viewport = scroll_window->viewport;
-                GtkStyleClass *viewport_class = viewport->style->klass;
-
-                dw += 2 * viewport_class->xthickness;
-                dh += 2 * viewport_class->ythickness;
-            }
-        }
-#else
         if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
         {
             /* when using GTK 1.2 we set the shadow border size to 2 */
@@ -2214,32 +2491,37 @@ void wxWindow::DoSetClientSize( int width, int height )
             dw += 1 * 2;
             dh += 1 * 2;
         }
-#endif
 
-        if (HasScrolling())
+        if (m_hasScrolling)
         {
-/*
-            GtkWidget *hscrollbar = scroll_window->hscrollbar;
-            GtkWidget *vscrollbar = scroll_window->vscrollbar;
-
-            we use this instead:  range.slider_width = 11 + 2*2pts edge
-*/
-
             GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
+            
+            GtkRequisition vscroll_req;
+            vscroll_req.width = 2;
+            vscroll_req.height = 2;
+            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+                (scroll_window->vscrollbar, &vscroll_req );
+                
+            GtkRequisition hscroll_req;
+            hscroll_req.width = 2;
+            hscroll_req.height = 2;
+            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+                (scroll_window->hscrollbar, &hscroll_req );
+
             GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
 
             if (scroll_window->vscrollbar_visible)
             {
-                dw += 15;   /* dw += vscrollbar->allocation.width; */
+                dw += vscroll_req.width;
                 dw += scroll_class->scrollbar_spacing;
             }
 
             if (scroll_window->hscrollbar_visible)
             {
-                dh += 15;   /* dh += hscrollbar->allocation.height; */
+                dh += hscroll_req.height;
                 dh += scroll_class->scrollbar_spacing;
             }
-       }
+        }
 
        SetSize( width+dw, height+dh );
     }
@@ -2259,24 +2541,6 @@ void wxWindow::DoGetClientSize( int *width, int *height ) const
         int dw = 0;
         int dh = 0;
 
-#if (GTK_MINOR_VERSION == 0)
-        if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
-        {
-            if (HasScrolling())
-            {
-                GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
-#if 0 // unused - if this is ok, just remove this line (VZ)
-                GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
-#endif // 0
-
-                GtkWidget *viewport = scroll_window->viewport;
-                GtkStyleClass *viewport_class = viewport->style->klass;
-
-                dw += 2 * viewport_class->xthickness;
-                dh += 2 * viewport_class->ythickness;
-            }
-        }
-#else
         if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
         {
             /* when using GTK 1.2 we set the shadow border size to 2 */
@@ -2289,28 +2553,34 @@ void wxWindow::DoGetClientSize( int *width, int *height ) const
             dw += 1 * 2;
             dh += 1 * 2;
         }
-#endif
-        if (HasScrolling())
-        {
-/*
-            GtkWidget *hscrollbar = scroll_window->hscrollbar;
-            GtkWidget *vscrollbar = scroll_window->vscrollbar;
-
-            we use this instead:  range.slider_width = 11 + 2*2pts edge
-*/
 
+        if (m_hasScrolling)
+        {
             GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
+            
+            GtkRequisition vscroll_req;
+            vscroll_req.width = 2;
+            vscroll_req.height = 2;
+            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->vscrollbar)->klass )->size_request )
+                (scroll_window->vscrollbar, &vscroll_req );
+                
+            GtkRequisition hscroll_req;
+            hscroll_req.width = 2;
+            hscroll_req.height = 2;
+            (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window->hscrollbar)->klass )->size_request )
+                (scroll_window->hscrollbar, &hscroll_req );
+
             GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
 
             if (scroll_window->vscrollbar_visible)
             {
-                dw += 15;   /* dw += vscrollbar->allocation.width; */
+                dw += vscroll_req.width;
                 dw += scroll_class->scrollbar_spacing;
             }
 
             if (scroll_window->hscrollbar_visible)
             {
-                dh += 15;   /* dh += hscrollbar->allocation.height; */
+                dh += hscroll_req.height;
                 dh += scroll_class->scrollbar_spacing;
             }
         }
@@ -2474,7 +2744,7 @@ void wxWindow::GetTextExtent( const wxString& string,
 void wxWindow::SetFocus()
 {
     wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
-
+    
     if (m_wxwindow)
     {
         if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
@@ -2599,8 +2869,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)
@@ -2713,7 +2982,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. */
@@ -2722,17 +2992,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;
 }
@@ -2765,26 +3025,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;
 }
@@ -2793,28 +3049,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();
+       }
     }
 }
 
@@ -3095,20 +3360,13 @@ void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
         m_vAdjust->value = fpos;
     }
 
-/*
-    if (!m_isScrolling)
+    if (m_wxwindow->window)
     {
-*/
-        if (m_wxwindow->window)
-        {
-            if (orient == wxHORIZONTAL)
-                gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
-            else
-                gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
-        }
-/*
+        if (orient == wxHORIZONTAL)
+            gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
+        else
+            gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
     }
-*/
 }
 
 int wxWindow::GetScrollThumb( int orient ) const
@@ -3153,6 +3411,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 );
 
 /*
@@ -3207,8 +3469,3 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
     }
 */
 }
-
-void wxWindow::SetScrolling(bool scroll)
-{
-    m_isScrolling = g_blockEventsOnScroll = scroll;
-}