]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
Re-enabled dynamic library code in wxFileName so
[wxWidgets.git] / src / gtk1 / window.cpp
index d3fc1c023d09ade04e4a44011ee649b63a22bf88..6f4e94d4e7737d39afc704611f3d2568e2530238 100644 (file)
@@ -25,6 +25,7 @@
 #include "wx/utils.h"
 #include "wx/dialog.h"
 #include "wx/msgdlg.h"
+#include "wx/module.h"
 
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
@@ -39,7 +40,7 @@
 #endif // wxUSE_CARET
 
 #if wxUSE_TEXTCTRL
-#include "wx/textctrl.h"
+    #include "wx/textctrl.h"
 #endif
 
 #include "wx/menu.h"
     #endif
 #endif
 
+#ifdef __WXGTK20__
+extern GtkContainerClass *pizza_parent_class;
+#endif
+
 //-----------------------------------------------------------------------------
 // documentation on internals
 //-----------------------------------------------------------------------------
@@ -480,6 +485,11 @@ gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_even
 
     draw_frame( widget, win );
 
+#ifdef __WXGTK20__
+
+    (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
+
+#endif
     return TRUE;
 }
 
@@ -504,7 +514,7 @@ static long map_to_unmodified_wx_keysym( GdkEventKey *event )
 {
     // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
     //     but only event->keyval which is quite useless to us, so remember
-    //     the last character from GDK_KEY_PRESS and resue it as last resort
+    //     the last character from GDK_KEY_PRESS and reuse it as last resort
     //
     // NB: should be MT-neutral as always called from main thread only
     static struct
@@ -769,10 +779,6 @@ static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
 
-#ifdef __WXGTK20__
-extern GtkContainerClass *pizza_parent_class;
-#endif
-
 static int gtk_window_expose_callback( GtkWidget *widget,
                                        GdkEventExpose *gdk_event,
                                        wxWindow *win )
@@ -824,12 +830,12 @@ static int gtk_window_expose_callback( GtkWidget *widget,
 
     // Actual redrawing takes place in idle time.
     win->Update();
-    
+
 #ifdef __WXGTK20__
 
     (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, gdk_event);
-    
-#endif    
+
+#endif
 
     return TRUE;
 }
@@ -929,7 +935,7 @@ static void gtk_window_draw_callback( GtkWidget *widget,
     win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
 
     // Actual redrawing takes place in idle time.
-    
+
     win->Update();
 
 #ifndef __WXUNIVERSAL__
@@ -955,21 +961,24 @@ static void gtk_window_draw_callback( GtkWidget *widget,
 // "key_press_event" from any window
 //-----------------------------------------------------------------------------
 
-// turn on to see the key event codes on the console
-#undef DEBUG_KEY_EVENTS
+// set WXTRACE to this to see the key event codes on the console
+#define TRACE_KEYS  _T("keyevent")
 
-static gint gtk_window_key_press_callback( GtkWidget *widget,
-                                           GdkEventKey *gdk_event,
-                                           wxWindow *win )
+static bool
+wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
+                           wxWindowGTK *win,
+                           GdkEventKey *gdk_event)
 {
-    DEBUG_MAIN_THREAD
-
-    if (g_isIdle)
-        wxapp_install_idle_handler();
+    long key_code = map_to_unmodified_wx_keysym( gdk_event );
 
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return FALSE;
+    wxLogTrace(TRACE_KEYS, _T("Key %s event: %d => %ld"),
+               event.GetEventType() == wxEVT_KEY_UP ? _T("release")
+                                                    : _T("press"),
+               gdk_event->keyval, key_code);
 
+    // sending unknown key events doesn't really make sense
+    if (key_code == 0)
+        return FALSE;
 
     int x = 0;
     int y = 0;
@@ -977,30 +986,42 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     if (gdk_event->window)
         gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
 
-    bool ret = FALSE;
-
-    long key_code = map_to_unmodified_wx_keysym( gdk_event );
-
-#ifdef DEBUG_KEY_EVENTS
-    wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event->keyval, key_code);
-#endif // DEBUG_KEY_EVENTS
-
-    /* sending unknown key events doesn't really make sense */
-    if (key_code == 0)
-        return 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);
-    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
-    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
+    event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK) != 0;
+    event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK) != 0;
+    event.m_altDown = (gdk_event->state & GDK_MOD1_MASK) != 0;
+    event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK) != 0;
     event.m_keyCode = key_code;
     event.m_scanCode = gdk_event->keyval;
+    event.m_rawCode = (wxUint32) gdk_event->keyval;
+    event.m_rawFlags = 0;
     event.m_x = x;
     event.m_y = y;
     event.SetEventObject( win );
-    ret = win->GetEventHandler()->ProcessEvent( event );
+
+    return TRUE;
+}
+
+static gint gtk_window_key_press_callback( GtkWidget *widget,
+                                           GdkEventKey *gdk_event,
+                                           wxWindow *win )
+{
+    DEBUG_MAIN_THREAD
+
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (!win->m_hasVMT) return FALSE;
+    if (g_blockEventsOnDrag) return FALSE;
+
+    wxKeyEvent event( wxEVT_KEY_DOWN );
+    if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
+    {
+        // unknown key pressed, ignore (the event would be useless anyhow
+        return FALSE;
+    }
+
+    bool ret = win->GetEventHandler()->ProcessEvent( event );
 
 #if wxUSE_ACCEL
     if (!ret)
@@ -1026,15 +1047,13 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
        will only be sent if it is not in an accelerator table. */
     if ( !ret )
     {
-        key_code = map_to_wx_keysym( gdk_event );
+        long key_code = map_to_wx_keysym( gdk_event );
 
         if ( key_code )
         {
-#ifdef DEBUG_KEY_EVENTS
-            wxPrintf(_T("Char event: %ld\n"), key_code);
-#endif // DEBUG_KEY_EVENTS
+            wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
 
-            // reuse the ame event object, just change its type and use the
+            // 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;
@@ -1116,50 +1135,33 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 // "key_release_event" from any window
 //-----------------------------------------------------------------------------
 
-static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindowGTK *win )
+static gint gtk_window_key_release_callback( GtkWidget *widget,
+                                             GdkEventKey *gdk_event,
+                                             wxWindowGTK *win )
 {
     DEBUG_MAIN_THREAD
 
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    if (!win->m_hasVMT) return FALSE;
-    if (g_blockEventsOnDrag) return FALSE;
-
-    long key_code = map_to_unmodified_wx_keysym( gdk_event );
-
-#ifdef DEBUG_KEY_EVENTS
-    wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event->keyval, key_code);
-#endif // DEBUG_KEY_EVENTS
-
-    /* sending unknown key events doesn't really make sense */
-    if (key_code == 0) return FALSE;
+    if (!win->m_hasVMT)
+        return FALSE;
 
-    int x = 0;
-    int y = 0;
-    GdkModifierType state;
-    if (gdk_event->window)
-        gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+    if (g_blockEventsOnDrag)
+        return FALSE;
 
     wxKeyEvent event( wxEVT_KEY_UP );
-    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_keyCode = key_code;
-    event.m_scanCode = gdk_event->keyval;
-    event.m_x = x;
-    event.m_y = y;
-    event.SetEventObject( win );
-
-    if (win->GetEventHandler()->ProcessEvent( event ))
+    if ( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
     {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
-        return TRUE;
+        // unknown key pressed, ignore (the event would be useless anyhow
+        return FALSE;
     }
 
-    return FALSE;
+    if ( !win->GetEventHandler()->ProcessEvent( event ) )
+        return FALSE;
+
+    gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
+    return TRUE;
 }
 
 // ============================================================================
@@ -1862,13 +1864,13 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     gdk_window_get_pointer( widget->window, &x, &y, &state );
 
-    event.m_shiftDown = (state & GDK_SHIFT_MASK);
-    event.m_controlDown = (state & GDK_CONTROL_MASK);
-    event.m_altDown = (state & GDK_MOD1_MASK);
-    event.m_metaDown = (state & GDK_MOD2_MASK);
-    event.m_leftDown = (state & GDK_BUTTON1_MASK);
-    event.m_middleDown = (state & GDK_BUTTON2_MASK);
-    event.m_rightDown = (state & GDK_BUTTON3_MASK);
+    event.m_shiftDown = (state & GDK_SHIFT_MASK) != 0;
+    event.m_controlDown = (state & GDK_CONTROL_MASK) != 0;
+    event.m_altDown = (state & GDK_MOD1_MASK) != 0;
+    event.m_metaDown = (state & GDK_MOD2_MASK) != 0;
+    event.m_leftDown = (state & GDK_BUTTON1_MASK) != 0;
+    event.m_middleDown = (state & GDK_BUTTON2_MASK) != 0;
+    event.m_rightDown = (state & GDK_BUTTON3_MASK) != 0;
 
     wxPoint pt = win->GetClientAreaOrigin();
     event.m_x = x + pt.x;
@@ -2346,6 +2348,9 @@ bool wxWindowGTK::Create( wxWindow *parent,
     }
 
     m_insertCallback = wxInsertChildInWindow;
+    
+    // always needed for background clearing
+    m_delayedBackgroundColour = TRUE; 
 
     m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
     GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
@@ -2361,7 +2366,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
     m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
 
     m_wxwindow = gtk_pizza_new();
-    
+
 #ifndef __WXUNIVERSAL__
     GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
 
@@ -2542,7 +2547,7 @@ void wxWindowGTK::PostCreation()
 #ifndef __WXGTK20__
             gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
                 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
-                
+
             if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
             {
                 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
@@ -2768,7 +2773,7 @@ void wxWindowGTK::OnInternalIdle()
 {
     // Update invalidated regions.
     Update();
-    
+
     // Synthetize activate events.
     if ( g_sendActivateEvent != -1 )
     {
@@ -3382,18 +3387,23 @@ void wxWindowGTK::GtkSendPaintEvents()
     {
         wxWindowDC dc( (wxWindow*)this );
         dc.SetClippingRegion( m_clearRegion );
-        
+
         wxEraseEvent erase_event( GetId(), &dc );
         erase_event.SetEventObject( this );
-    
+
         if (!GetEventHandler()->ProcessEvent(erase_event))
         {
+            if (!g_eraseGC)
+            {
+                g_eraseGC = gdk_gc_new( GTK_PIZZA(m_wxwindow)->bin_window );
+                gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
+            }
             gdk_gc_set_foreground( g_eraseGC, m_backgroundColour.GetColor() );
-        
+
             wxRegionIterator upd( m_clearRegion );
             while (upd)
             {
-                gdk_draw_rectangle( GTK_PIZZA(m_wxwindow)->bin_window, g_eraseGC, 0,
+                gdk_draw_rectangle( GTK_PIZZA(m_wxwindow)->bin_window, g_eraseGC, 1,
                                        upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() );
                 upd ++;
             }
@@ -3416,9 +3426,9 @@ void wxWindowGTK::GtkSendPaintEvents()
     // The following code will result in all window-less widgets
     // 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)
     {
@@ -3430,12 +3440,12 @@ void wxWindowGTK::GtkSendPaintEvents()
         {
             // Get intersection of widget area and update region
             wxRegion region( m_updateRegion );
-            
+
             GdkEventExpose gdk_event;
             gdk_event.type = GDK_EXPOSE;
             gdk_event.window = pizza->bin_window;
             gdk_event.count = 0;
-            
+
             wxRegionIterator upd( m_updateRegion );
             while (upd)
             {
@@ -3444,12 +3454,12 @@ void wxWindowGTK::GtkSendPaintEvents()
                 rect.y = upd.GetY();
                 rect.width = upd.GetWidth();
                 rect.height = upd.GetHeight();
-                
+
                 if (gtk_widget_intersect (child->widget, &rect, &gdk_event.area))
                 {
                     gtk_widget_event (child->widget, (GdkEvent*) &gdk_event);
                 }
-                
+
                 upd ++;
             }
         }
@@ -3468,7 +3478,7 @@ void wxWindowGTK::Clear()
 
     if (m_wxwindow && m_wxwindow->window)
     {
-//        gdk_window_clear( m_wxwindow->window );
+        gdk_window_clear( m_wxwindow->window );
     }
 }
 
@@ -3512,6 +3522,12 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
         m_delayedBackgroundColour = TRUE;
     }
 
+    if (window)
+    {
+        // We need the pixel value e.g. for background clearing.
+        m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
+    }
+    
     if ((m_wxwindow) &&
         (m_wxwindow->window) &&
         (m_backgroundColour != wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)))
@@ -3519,7 +3535,6 @@ bool wxWindowGTK::SetBackgroundColour( const wxColour &colour )
         /* wxMSW doesn't clear the window here. I don't do that either to
           provide compatibility. call Clear() to do the job. */
 
-        m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
         gdk_window_set_background( window, m_backgroundColour.GetColor() );
     }
 
@@ -4058,42 +4073,42 @@ void wxWindowGTK::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
 
     // No scrolling requested.
     if ((dx == 0) && (dy == 0)) return;
-    
+
 #ifndef __WXGTK20__
     if (!m_updateRegion.IsEmpty())
     {
         m_updateRegion.Offset( dx, dy );
-        
+
         int cw = 0;
         int ch = 0;
         GetClientSize( &cw, &ch );
         m_updateRegion.Intersect( 0, 0, cw, ch );
     }
-    
+
     if (!m_clearRegion.IsEmpty())
     {
         m_clearRegion.Offset( dx, dy );
-        
+
         int cw = 0;
         int ch = 0;
         GetClientSize( &cw, &ch );
         m_clearRegion.Intersect( 0, 0, cw, ch );
     }
-    
+
     m_clipPaintRegion = TRUE;
-    
+
     gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
-    
+
     m_clipPaintRegion = FALSE;
 #else
 
-    gdk_window_scroll( GTK_PIZZA(m_wxwindow)->bin_window, -dx, -dy );
-    
-    GTK_PIZZA(m_wxwindow)->xoffset -= dx;
-    GTK_PIZZA(m_wxwindow)->yoffset -= dy;
-    
-#endif    
-   
+    gdk_window_scroll( GTK_PIZZA(m_wxwindow)->bin_window, dx, dy );
+
+    GTK_PIZZA(m_wxwindow)->xoffset += dx;
+    GTK_PIZZA(m_wxwindow)->yoffset += dy;
+
+#endif
+
 }
 
 
@@ -4156,14 +4171,15 @@ IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule)
 
 bool wxWinModule::OnInit()
 {
-    g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
-    gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
-    
+    // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
+    // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
+
     return TRUE;
 }
 
 void wxWinModule::OnExit()
 {
-    gdk_gc_unref( g_eraseGC );
+    if (g_eraseGC)
+        gdk_gc_unref( g_eraseGC );
 }