]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Implement wxGauge
[wxWidgets.git] / src / gtk / window.cpp
index 538dda645dedc98f09ae8c7118053839e18fbf77..b966d46d21fe387c401dfd58778cf55c6f867306 100644 (file)
@@ -8,15 +8,17 @@
 /////////////////////////////////////////////////////////////////////////////
 
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "window.h"
 #endif
 
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
 #ifdef __VMS
 #define XWarpPointer XWARPPOINTER
 #endif
 
-#include "wx/defs.h"
 #include "wx/window.h"
 #include "wx/dcclient.h"
 #include "wx/frame.h"
@@ -255,9 +257,9 @@ wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL;
 // send any activate events at all
 static int        g_sendActivateEvent = -1;
 
-/* hack: we need something to pass to gtk_menu_popup, so we store the time of
-   the last click here */
-static guint32 gs_timeLastClick = 0;
+// hack: we need something to pass to gtk_menu_popup, so we store the time of
+// the last click here
+static guint32 gs_timeLastClick = 0; 
 
 extern bool g_mainThreadLocked;
 
@@ -345,7 +347,7 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win)
     if ( winFocus == win )
         return (wxWindow *)win;
 
-    for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+    for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
           node;
           node = node->GetNext() )
     {
@@ -477,12 +479,18 @@ static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNU
 // "size_request" of m_widget
 //-----------------------------------------------------------------------------
 
-static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
+// make it extern because wxStatitText needs to disconnect this one
+extern "C"
+void wxgtk_window_size_request_callback(GtkWidget *widget,
+                                        GtkRequisition *requisition,
+                                        wxWindow *win)
 {
-    int w,h;
+    int w, h;
     win->GetSize( &w, &h );
-    if (w < 2) w = 2;
-    if (h < 2) h = 2;
+    if (w < 2)
+        w = 2;
+    if (h < 2)
+        h = 2;
 
     requisition->height = h;
     requisition->width = w;
@@ -1065,7 +1073,7 @@ wxTranslateGTKKeyEventToWx(wxKeyEvent& event,
     return TRUE;
 }
 
-#ifndef __WXGTK20__
+
 static gint gtk_window_key_press_callback( GtkWidget *widget,
                                            GdkEventKey *gdk_event,
                                            wxWindow *win )
@@ -1115,42 +1123,58 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     // will only be sent if it is not in an accelerator table.
     if (!ret)
     {
-        // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+        long key_code;
         KeySym keysym = gdk_event->keyval;
-        long key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
-        if ( !key_code )
+#ifdef __WXGTK20__
+        // In GTK 2.0, we need to hand over the key event to an input method
+        // and the IM will emit a "commit" event containing the actual utf8
+        // character.  In that case the EVT_CHAR events will be sent from
+        // there.  But only do it this way for non-KeySym keys.
+        key_code = wxTranslateKeySymToWXKey(gdk_event->keyval, FALSE /* isChar */);
+        if ( !key_code && win->m_imContext )
         {
-            if ( gdk_event->length == 1 )
-            {
-                key_code = (unsigned char)gdk_event->string[0];
-            }
-            else if ( wxIsAsciiKeysym(keysym) )
-            {
-                // ASCII key
-                key_code = (unsigned char)keysym;
-            }
+            gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
+            ret = TRUE;
         }
-
-        if ( key_code )
+        else
+#endif
         {
-            wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
-
-            event.m_keyCode = key_code;
-
-            // Implement OnCharHook by checking ancesteror top level windows
-            wxWindow *parent = win;
-            while (parent && !parent->IsTopLevel())
-            parent = parent->GetParent();
-            if (parent)
+            // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
+            key_code = wxTranslateKeySymToWXKey(keysym, TRUE /* isChar */);
+            if ( !key_code )
             {
-                event.SetEventType( wxEVT_CHAR_HOOK );
-                ret = parent->GetEventHandler()->ProcessEvent( event );
+                if ( gdk_event->length == 1 )
+                {
+                    key_code = (unsigned char)gdk_event->string[0];
+                }
+                else if ( wxIsAsciiKeysym(keysym) )
+                {
+                    // ASCII key
+                    key_code = (unsigned char)keysym;
+                }
             }
 
-            if (!ret)
+            if ( key_code )
             {
-                event.SetEventType(wxEVT_CHAR);
-                ret = win->GetEventHandler()->ProcessEvent( event );
+                wxLogTrace(TRACE_KEYS, _T("Char event: %ld"), key_code);
+
+                event.m_keyCode = key_code;
+
+                // Implement OnCharHook by checking ancesteror top level windows
+                wxWindow *parent = win;
+                while (parent && !parent->IsTopLevel())
+                    parent = parent->GetParent();
+                if (parent)
+                {
+                    event.SetEventType( wxEVT_CHAR_HOOK );
+                    ret = parent->GetEventHandler()->ProcessEvent( event );
+                }
+
+                if (!ret)
+                {
+                    event.SetEventType(wxEVT_CHAR);
+                    ret = win->GetEventHandler()->ProcessEvent( event );
+                }
             }
         }
     }
@@ -1221,132 +1245,8 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
 
     return FALSE;
 }
-#endif
 
 #ifdef __WXGTK20__
-static gint gtk_window_key_press_callback( GtkWidget *widget,
-                                           GdkEventKey *gdk_event,
-                                           wxWindow *win )
-{
-    if (g_isIdle)
-        wxapp_install_idle_handler();
-
-    if (!win->m_hasVMT)
-        return FALSE;
-    if (g_blockEventsOnDrag)
-        return FALSE;
-
-    bool ret = FALSE;
-    bool dont_use_IM = FALSE;
-
-    wxKeyEvent event( wxEVT_KEY_DOWN );
-    long keycode = wxTranslateKeySymToWXKey( gdk_event->keyval, FALSE );
-    if (keycode)
-    {
-        // We were able to decode the key press without
-        // any input method, so don't use it.
-        dont_use_IM = TRUE;
-
-        // now fill all the other fields
-        int x = 0;
-        int y = 0;
-        GdkModifierType state;
-        if (gdk_event->window)
-            gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
-
-        event.SetTimestamp( gdk_event->time );
-        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 = keycode;
-        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 );
-
-        // send key down event
-        ret = win->GetEventHandler()->ProcessEvent( event );
-
-        if (!ret)
-        {
-            // Implement OnCharHook by checking ancesteror top level windows
-            wxWindow *parent = win;
-            while (parent && !parent->IsTopLevel())
-            parent = parent->GetParent();
-            if (parent)
-            {
-                event.SetEventType( wxEVT_CHAR_HOOK );
-                ret = parent->GetEventHandler()->ProcessEvent( event );
-            }
-
-            if (!ret)
-            {
-                event.SetEventType(wxEVT_CHAR);
-                ret = win->GetEventHandler()->ProcessEvent( event );
-            }
-        }
-
-        // win is a control: tab can be propagated up
-        if ( !ret &&
-             ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
-            win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
-        {
-            wxNavigationKeyEvent new_event;
-            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->GetParent()->GetEventHandler()->ProcessEvent( new_event );
-        }
-
-        if ( !ret &&
-             (gdk_event->keyval == GDK_Escape) )
-        {
-            wxWindow *winForCancel = win, *btnCancel = NULL;
-            while ( winForCancel )
-            {
-                btnCancel = winForCancel->FindWindow(wxID_CANCEL);
-                if ( btnCancel ) break;
-
-                if ( winForCancel->IsTopLevel() ) break;
-
-                winForCancel = winForCancel->GetParent();
-            }
-
-            if ( btnCancel )
-            {
-                wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
-                event.SetEventObject(btnCancel);
-                ret = btnCancel->GetEventHandler()->ProcessEvent(event);
-            }
-        }
-    }
-
-    if (ret)
-    {
-        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
-        return TRUE;
-    }
-
-    if (!dont_use_IM && win->m_imContext)
-    {
-        // In GTK 2.0, we need to hand over the key
-        // event to an input method and the IM will
-        // emit a "commit" event containing the
-        // actual utf8 character.
-        gtk_im_context_filter_keypress ( (GtkIMContext*) win->m_imContext, gdk_event );
-
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
 static void gtk_wxwindow_commit_cb (GtkIMContext *context,
                                                   const gchar  *str,
                                                   wxWindow     *window)
@@ -1369,23 +1269,25 @@ static void gtk_wxwindow_commit_cb (GtkIMContext *context,
     event.m_keyCode = uniChar;
 #endif
 
-    if (!ret)
-    {
-        // Implement OnCharHook by checking ancesteror top level windows
-        wxWindow *parent = window;
-        while (parent && !parent->IsTopLevel())
+
+    // TODO:  We still need to set all the extra attributes of the
+    //        event, modifiers and such...
+
+
+    // Implement OnCharHook by checking ancestor top level windows
+    wxWindow *parent = window;
+    while (parent && !parent->IsTopLevel())
         parent = parent->GetParent();
-        if (parent)
-        {
-            event.SetEventType( wxEVT_CHAR_HOOK );
-            ret = parent->GetEventHandler()->ProcessEvent( event );
-        }
+    if (parent)
+    {
+        event.SetEventType( wxEVT_CHAR_HOOK );
+        ret = parent->GetEventHandler()->ProcessEvent( event );
+    }
 
-        if (!ret)
-        {
-            event.SetEventType(wxEVT_CHAR);
-            ret = window->GetEventHandler()->ProcessEvent( event );
-        }
+    if (!ret)
+    {
+        event.SetEventType(wxEVT_CHAR);
+        ret = window->GetEventHandler()->ProcessEvent( event );
     }
 }
 #endif
@@ -1511,7 +1413,7 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
         yy += pizza->yoffset;
     }
 
-    wxWindowList::Node  *node = win->GetChildren().GetFirst();
+    wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
     while (node)
     {
         wxWindowGTK *child = node->GetData();
@@ -1526,7 +1428,7 @@ wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
             int xx1 = child->m_x;
             int yy1 = child->m_y;
             int xx2 = child->m_x + child->m_width;
-            int yy2 = child->m_x + child->m_height;
+            int yy2 = child->m_y + child->m_height;
 
             // left
             if (((xx >= xx1) && (xx <= xx1+10) && (yy >= yy1) && (yy <= yy2)) ||
@@ -1835,10 +1737,10 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget,
     {
         // synthetize a mouse enter or leave event if needed
         GdkWindow *winUnderMouse = gdk_window_at_pointer(NULL, NULL);
-        // This seems to be necessary and actually been added to 
+        // This seems to be necessary and actually been added to
         // GDK itself in version 2.0.X
         gdk_flush();
-        
+
         bool hasMouse = winUnderMouse == gdk_event->window;
         if ( hasMouse != g_captureWindowHasMouse )
         {
@@ -2064,7 +1966,7 @@ gint gtk_window_enter_callback( GtkWidget *widget,
 
     // Event was emitted after a grab
     if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
-    
+
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
     int x = 0;
@@ -2104,7 +2006,7 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
     // Event was emitted after an ungrab
     if (gdk_event->mode != GDK_CROSSING_NORMAL) return FALSE;
-    
+
     if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
 
     wxMouseEvent event( wxEVT_LEAVE_WINDOW );
@@ -2300,11 +2202,11 @@ gtk_window_realized_callback( GtkWidget *m_widget, wxWindow *win )
 
     if (g_isIdle)
         wxapp_install_idle_handler();
-
-    if (win->m_delayedBackgroundColour)
+        
+    if (win->m_delayedBackgroundColour && !win->GetThemeEnabled())
         win->GtkSetBackgroundColour( win->GetBackgroundColour() );
 
-    if (win->m_delayedForegroundColour)
+    if (win->m_delayedForegroundColour && !win->GetThemeEnabled())
         win->GtkSetForegroundColour( win->GetForegroundColour() );
 
 #ifdef __WXGTK20__
@@ -2556,8 +2458,10 @@ void wxWindowGTK::Init()
 
     m_hAdjust = (GtkAdjustment*) NULL;
     m_vAdjust = (GtkAdjustment*) NULL;
-    m_oldHorizontalPos = 0.0;
+    m_oldHorizontalPos =
     m_oldVerticalPos = 0.0;
+    m_oldClientWidth =
+    m_oldClientHeight = 0;
 
     m_resizing = FALSE;
     m_widgetStyle = (GtkStyle*) NULL;
@@ -2901,7 +2805,7 @@ void wxWindowGTK::PostCreation()
                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
     }
 
-    if (!GTK_IS_COMBO(m_widget))
+    if ( !GTK_IS_COMBO(m_widget))
     {
         // This is needed if we want to add our windows into native
         // GTK control, such as the toolbar. With this callback, the
@@ -2909,7 +2813,8 @@ void wxWindowGTK::PostCreation()
         // programmer). Sadly, it misbehaves for wxComboBox. FIXME
         // when moving to GTK 2.0.
         gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
-                            GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
+                            GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback),
+                            (gpointer) this );
     }
 
     m_hasVMT = TRUE;
@@ -3126,7 +3031,8 @@ void wxWindowGTK::OnInternalIdle()
         }
     }
 
-    UpdateWindowUI();
+    if (wxUpdateUIEvent::CanUpdate(this))
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
 
 void wxWindowGTK::DoGetSize( int *width, int *height ) const
@@ -3377,7 +3283,7 @@ static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
     // Recurse, so that children have the opportunity to Do The Right Thing
     // and reset colours that have been messed up by a parent's (really ancestor's)
     // Enable call
-    for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
+    for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
           node;
           node = node->GetNext() )
     {
@@ -3711,6 +3617,18 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
     if (g_isIdle)
         wxapp_install_idle_handler();
 
+    wxRect myRect(0,0,0,0);
+    if (m_wxwindow && rect)
+    {
+        myRect.SetSize(wxSize( m_wxwindow->allocation.width,
+                               m_wxwindow->allocation.height));
+        myRect.Intersect(*rect);
+        if (!myRect.width || !myRect.height)
+            // nothing to do, rectangle is empty
+            return;
+        rect = &myRect;
+    }
+
     if (eraseBackground && m_wxwindow && m_wxwindow->window)
     {
         if (rect)
@@ -3944,7 +3862,7 @@ void wxWindowGTK::GtkSendPaintEvents()
     m_updateRegion.Clear();
 }
 
-void wxWindowGTK::Clear()
+void wxWindowGTK::ClearBackground()
 {
     wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
 
@@ -4141,7 +4059,7 @@ void wxWindowGTK::SetWidgetStyle()
     {
 #ifdef __WXGTK20__
         pango_font_description_free( style->font_desc );
-        pango_font_description_copy( m_font.GetNativeFontInfo()->description );
+        style->font_desc = pango_font_description_copy( m_font.GetNativeFontInfo()->description );
 #else
         gdk_font_unref( style->font );
         style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
@@ -4232,7 +4150,7 @@ void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting  )
 static void SetInvokingWindow( wxMenu *menu, wxWindowGTK *win )
 {
     menu->SetInvokingWindow( win );
-    wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+    wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
     while (node)
     {
         wxMenuItem *menuitem = node->GetData();
@@ -4301,13 +4219,16 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
                   wxPopupMenuPositionCallback,  // function to position it
                   NULL,                         // client data
                   0,                            // button used to activate it
+#ifdef __WXGTK20__
+                  gtk_get_current_event_time()
+#else
                   gs_timeLastClick              // the time of activation
+#endif
                 );
 
     while (is_waiting)
     {
-        while (gtk_events_pending())
-            gtk_main_iteration();
+        gtk_main_iteration();
     }
 
     return TRUE;