]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
cgimagecreate from wxbitmap crashes 10.2 - turn off. Put in right click handler to...
[wxWidgets.git] / src / gtk1 / window.cpp
index 00c74805d15eb2bf429d5f196184151ddd56caac..e6a12132c279b24bb8a412e31693fefc51c3ca06 100644 (file)
@@ -28,6 +28,7 @@
 #include "wx/dialog.h"
 #include "wx/msgdlg.h"
 #include "wx/module.h"
+#include "wx/combobox.h"
 
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
@@ -476,6 +477,34 @@ void wxgtk_window_size_request_callback(GtkWidget *widget,
     requisition->width = w;
 }
 
+
+extern "C"
+void wxgtk_combo_size_request_callback(GtkWidget *widget,
+                                       GtkRequisition *requisition,
+                                       wxComboBox *win)
+{
+    // This callback is actually hooked into the text entry
+    // of the combo box, not the GtkHBox.
+    
+    int w, h;
+    win->GetSize( &w, &h );
+    if (w < 2)
+        w = 2;
+    if (h < 2)
+        h = 2;
+
+    GtkCombo *gcombo = GTK_COMBO(win->m_widget);
+    
+    GtkRequisition entry_req;
+    entry_req.width = 2;
+    entry_req.height = 2;
+    (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(gcombo->button) )->size_request )
+        (gcombo->button, &entry_req );
+    
+    requisition->width = w - entry_req.width;
+    requisition->height = entry_req.height+4;  // TODO: why +4?
+}
+
 //-----------------------------------------------------------------------------
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
@@ -971,6 +1000,8 @@ static void wxFillOtherKeyEventFields(wxKeyEvent& event,
 #if wxUSE_UNICODE
     event.m_uniChar = gdk_keyval_to_unicode(gdk_event->keyval);
 #endif
+    wxGetMousePosition( &x, &y );
+    win->ScreenToClient( &x, &y );
     event.m_x = x;
     event.m_y = y;
     event.SetEventObject( win );
@@ -1111,29 +1142,27 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         return FALSE;
     if (g_blockEventsOnDrag)
         return FALSE;
-    
+
+
+    wxKeyEvent event( wxEVT_KEY_DOWN );
+    bool ret = false;
+    bool return_after_IM = false;
+
+    if( wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
+    {
+        // Emit KEY_DOWN event
+        ret = win->GetEventHandler()->ProcessEvent( event );
+    }
+    else 
+    {
+        // Return after IM processing as we cannot do
+        // anything with it anyhow.
+        return_after_IM = true;
+    }
+
 #ifdef __WXGTK20__
-#if 0
-    // We have to pass key press events through GTK+'s Input Method context
-    // object in order to get correct characters. By doing so, we lose the
-    // ability to let other GTK+'s handlers (namely, widgets' default signal
-    // handlers) handle the signal by returning false from this callback.
-    // Because GTK+ sends the events to parent widgets as well, we can't
-    // afford losing it, otherwise native widgets inserted into wxPanel
-    // would break in subtle ways (e.g. spacebar would no longer toggle
-    // wxCheckButton's state). Therefore, we only pass the event to IM if it
-    // originated in this window's widget, which we detect by checking if we've
-    // seen the same event before (no events from children are lost this way,
-    // because gtk_window_key_press_callback is installed for native controls
-    // as well and the wxKeyEvent it creates propagates upwards).
-    static GdkEventKey s_lastEvent;
-    bool useIM = (win->m_imData != NULL) &&
-                 memcmp(gdk_event, &s_lastEvent, sizeof(GdkEventKey)) != 0;
-    s_lastEvent = *gdk_event;
-#else
     // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw):
-    // There is no need to store lastEvent. The original code makes GTK+ IM 
-    // dysfunction. When we get a key_press event here, it could be originate
+    // When we get a key_press event here, it could be originate
     // from the current widget or its child widgets.  However, only the widget
     // with the INPUT FOCUS can generate the INITIAL key_press event.  That is, 
     // if the CURRENT widget doesn't have the FOCUS at all, this event definitely
@@ -1143,30 +1172,27 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     // widgets has both IM context and input focus, the event should be filtered 
     // by gtk_im_context_filter_keypress().
     // Then, we should, according to GTK+ 2.0 API doc, return whatever it returns.
-    bool useIM = (win->m_imData != NULL) && ( wxWindow::FindFocus() == win );
-#endif
-
-#endif
-    
-    bool IM_ret = FALSE;
-#ifdef __WXGTK20__
-    // 2005.01.26 modified by Hong Jen Yee (hzysoft@sina.com.tw):
-    // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
-    // docs, if IM filter returns true, no further processing should be done.
-    // wWe should send the key_down event anyway. 
-    if (useIM)
+    if ((!ret) && (win->m_imData != NULL) && ( wxWindow::FindFocus() == win ))
     {
-        // it may be useful for the input method, though:
-        IM_ret = gtk_im_context_filter_keypress(win->m_imData->context, gdk_event);
+        // We should let GTK+ IM filter key event first. According to GTK+ 2.0 API
+        // docs, if IM filter returns true, no further processing should be done.
+        // we should send the key_down event anyway. 
+        bool intercepted_by_IM = gtk_im_context_filter_keypress(win->m_imData->context, gdk_event);
         win->m_imData->lastKeyEvent = NULL;
-        if (IM_ret)
+        if (intercepted_by_IM)
+        {
             wxLogTrace(TRACE_KEYS, _T("Key event intercepted by IM"));
+            return true;
+        }
     }
 #endif
+    if (return_after_IM)
+        return true;
 
-    wxKeyEvent event( wxEVT_KEY_DOWN );
-    bool ret = FALSE;
-
+#ifndef __WXGTK20__     
+    // This is for GTK+ 1.2 only. The char event generatation for GTK+ 2.0 is done
+    // in the "commit" handler.
+    
     // 2005.02.02 modified by Hong Jen Yee (hzysoft@sina.com.tw).
     // In GTK+ 1.2, strings sent by IMs are also regarded as key_press events whose 
     // keyCodes cannot be recognized by wxWidgets. These MBCS strings, however, are 
@@ -1183,10 +1209,6 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
     // When using Input Methods to support internationalized text input, the composed
     // characters appear here after the pre-editing has been completed.
 
-#ifndef __WXGTK20__     
-    // This is for GTK+ 1.2 only. The char event generatation for
-    // GTK+ 2.0 is done in the emit handler.
-    
     if ( (!ret) && (gdk_event->length > 1) ) // If this event contains a pre-edited string from IM.
     {
         // We should translate this key event into wxEVT_CHAR not wxEVT_KEY_DOWN.
@@ -1199,11 +1221,11 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         #endif
 
         // Implement OnCharHook by checking ancesteror top level windows
-        wxWindow *parent = window;
+        wxWindow *parent = win;
         while (parent && !parent->IsTopLevel())
             parent = parent->GetParent();
 
-        for( wxChar* pstr = string; *pstr; pstr++ )
+        for( const wxChar* pstr = string; *pstr; pstr++ )
         {
         #if wxUSE_UNICODE
             event.m_uniChar = *pstr;
@@ -1220,28 +1242,14 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
             if (!ret)
             {
                 event.SetEventType(wxEVT_CHAR);
-                window->GetEventHandler()->ProcessEvent( event );
+                win->GetEventHandler()->ProcessEvent( event );
             }
         }
         return true;
     }
-    // Only translate the key event when it's not sent with a pre-edited string.
-    else 
+    
 #endif  // #ifndef  __WXGTK20__
 
-    if( !wxTranslateGTKKeyEventToWx(event, win, gdk_event) )
-    {
-        // unknown key pressed, ignore (the event would be useless anyhow)
-        return false;
-    }
-    else // This event doesn't contain a pre-edited string and is not an invalid key either.
-    {
-        // Emit KEY_DOWN event
-        ret = win->GetEventHandler()->ProcessEvent( event );
-    }
-    if (IM_ret)
-        return false;
-
 #if wxUSE_ACCEL
     if (!ret)
     {
@@ -1308,6 +1316,10 @@ static gint gtk_window_key_press_callback( GtkWidget *widget,
         }
     }
 
+
+
+
+
     // win is a control: tab can be propagated up
     if ( !ret &&
          ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
@@ -2948,13 +2960,20 @@ void wxWindowGTK::PostCreation()
                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
     }
 
-    if ( !GTK_IS_COMBO(m_widget))
+    if (GTK_IS_COMBO(m_widget))
+    {
+        GtkCombo *gcombo = GTK_COMBO(m_widget);
+    
+        gtk_signal_connect( GTK_OBJECT(gcombo->entry), "size_request",
+                            GTK_SIGNAL_FUNC(wxgtk_combo_size_request_callback),
+                            (gpointer) this );
+    }
+    else
     {
         // This is needed if we want to add our windows into native
-        // GTK control, such as the toolbar. With this callback, the
+        // GTK controls, such as the toolbar. With this callback, the
         // toolbar gets to know the correct size (the one set by the
-        // programmer). Sadly, it misbehaves for wxComboBox. FIXME
-        // when moving to GTK 2.0.
+        // programmer). Sadly, it misbehaves for wxComboBox.
         gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
                             GTK_SIGNAL_FUNC(wxgtk_window_size_request_callback),
                             (gpointer) this );
@@ -3083,22 +3102,37 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags
         if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
         if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
 
-        int border = 0;
+        int left_border = 0;
+        int right_border = 0;
+        int top_border = 0;
         int bottom_border = 0;
 
-#ifndef __WXGTK20__
+        /* the default button has a border around it */
         if (GTK_WIDGET_CAN_DEFAULT(m_widget))
         {
-            /* the default button has a border around it */
-            border = 6;
+#ifdef __WXGTK20__
+            GtkBorder *default_outside_border = NULL;
+            gtk_widget_style_get( m_widget, "default_outside_border", &default_outside_border, NULL );
+            if (default_outside_border)
+            {
+                left_border += default_outside_border->left;
+                right_border += default_outside_border->right;
+                top_border += default_outside_border->top;
+                bottom_border += default_outside_border->bottom;
+                g_free( default_outside_border );
+            }
+#else
+            left_border = 6;
+            right_border = 6;
+            top_border = 6;
             bottom_border = 5;
-        }
 #endif
+        }
 
-        DoMoveWindow( m_x-border,
-                      m_y-border,
-                      m_width+2*border,
-                      m_height+border+bottom_border );
+        DoMoveWindow( m_x-top_border,
+                      m_y-left_border,
+                      m_width+left_border+right_border,
+                      m_height+top_border+bottom_border );
     }
 
     if (m_hasScrolling)
@@ -3924,6 +3958,12 @@ void wxWindowGTK::Refresh( bool eraseBackground, const wxRect *rect )
 void wxWindowGTK::Update()
 {
     GtkUpdate();
+
+    // when we call Update() we really want to update the window immediately on
+    // screen, even if itmeans flushing the entire queue and hence slowing down
+    // everything -- but it should still be done, it's just that Update() should
+    // be called very rarely
+    gdk_flush();
 }
 
 void wxWindowGTK::GtkUpdate()
@@ -3954,12 +3994,10 @@ void wxWindowGTK::GtkSendPaintEvents()
     // widget to draw on
     GtkPizza *pizza = GTK_PIZZA (m_wxwindow);
 
-    if (GetThemeEnabled() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM)
+    if (GetThemeEnabled() && (GetBackgroundStyle() == wxBG_STYLE_SYSTEM))
     {
         // find ancestor from which to steal background
-        wxWindow *parent = GetParent();
-        while (parent && !parent->IsTopLevel())
-            parent = parent->GetParent();
+        wxWindow *parent = wxGetTopLevelParent((wxWindow *)this);
         if (!parent)
             parent = (wxWindow*)this;