]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
wxControl and wxDialog coded and supporting module def file.
[wxWidgets.git] / src / gtk / window.cpp
index aa212c4d05b8d2860397a869f1b7e941b8c3f9f2..753c10c86d05d7ffd1099d10a8afda4e9f92ca28 100644 (file)
     #pragma implementation "window.h"
 #endif
 
+#ifdef __VMS
+#define XWarpPointer XWARPPOINTER
+#endif
+
 #include "wx/defs.h"
 #include "wx/window.h"
 #include "wx/dc.h"
@@ -215,7 +219,9 @@ extern bool g_mainThreadLocked;
 // debug
 //-----------------------------------------------------------------------------
 
+#ifndef __WXGTK20__
 #define DISABLE_STYLE_IF_BROKEN_THEME 1
+#endif
 
 #ifdef __WXDEBUG__
 
@@ -316,7 +322,8 @@ extern bool g_isIdle;
 //-----------------------------------------------------------------------------
 
 // returns the child of win which currently has focus or NULL if not found
-static wxWindow *FindFocusedChild(wxWindow *win)
+// Note: can't be static, needed by textctrl.cpp.
+/* static */ wxWindow *FindFocusedChild(wxWindow *win)
 {
     wxWindow *winFocus = wxWindow::FindFocus();
     if ( !winFocus )
@@ -651,6 +658,21 @@ static long map_to_wx_keysym( KeySym keysym )
     return (key_code);
 }
 
+//-----------------------------------------------------------------------------
+// "size_request" of m_widget
+//-----------------------------------------------------------------------------
+
+static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
+{
+    int w,h;
+    win->GetSize( &w, &h );
+    if (w < 2) w = 2;
+    if (h < 2) h = 2;
+    
+    requisition->height = h;
+    requisition->width = w;
+}
+
 //-----------------------------------------------------------------------------
 // "expose_event" of m_wxwindow
 //-----------------------------------------------------------------------------
@@ -675,31 +697,47 @@ static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_ev
     }
 */
                                 
-        win->GetUpdateRegion().Union( gdk_event->area.x,
-                                      gdk_event->area.y,
-                                      gdk_event->area.width,
-                                      gdk_event->area.height );
+    GtkPizza *pizza = GTK_PIZZA (widget);
 
-        if (gdk_event->count == 0)
-        {
-            wxEraseEvent eevent( win->GetId() );
-            eevent.SetEventObject( win );
-            win->GetEventHandler()->ProcessEvent(eevent);
+    if (win->GetThemeEnabled())
+    {
+        wxWindow *parent = win->GetParent();
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+        if (!parent)
+            parent = win;
 
-            wxPaintEvent event( win->GetId() );
-            event.SetEventObject( win );
-            win->GetEventHandler()->ProcessEvent( event );
+        gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+                   GTK_SHADOW_NONE, &gdk_event->area, parent->m_widget, "base", 0, 0, -1, -1);
+    }
+        
+    win->GetUpdateRegion().Union( gdk_event->area.x,
+                                  gdk_event->area.y,
+                                  gdk_event->area.width,
+                                  gdk_event->area.height );
 
-            win->GetUpdateRegion().Clear();
-        }
+    if (gdk_event->count == 0)
+    {
+        win->m_clipPaintRegion = TRUE;
+    
+        wxEraseEvent eevent( win->GetId() );
+        eevent.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent(eevent);
+
+        wxPaintEvent event( win->GetId() );
+        event.SetEventObject( win );
+        win->GetEventHandler()->ProcessEvent( event );
+        
+        win->GetUpdateRegion().Clear();
+        
+        win->m_clipPaintRegion = FALSE;
+    }
     
         /* The following code will result in all window-less widgets
            being redrawn if the wxWindows class is given a chance to
            paint *anything* because it will then be allowed to paint
            over the window-less widgets */
        
-        GtkPizza *pizza = GTK_PIZZA (widget);
-        
         GList *children = pizza->children;
         while (children)
         {
@@ -757,7 +795,13 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW
 
     if (g_isIdle)
         wxapp_install_idle_handler();
-        
+
+    if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
+        (win->GetChildren().GetCount() == 0))
+    {
+        return;
+    }
+
 /*
     if (win->GetName() == wxT("panel"))
     {
@@ -772,34 +816,47 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW
 */
    
     GtkPizza *pizza = GTK_PIZZA (widget);
+
+    if (win->GetThemeEnabled())
+    {
+        wxWindow *parent = win->GetParent();
+        while (parent && !parent->IsTopLevel())
+            parent = parent->GetParent();
+        if (!parent)
+            parent = win;
+
+        gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
+                   GTK_SHADOW_NONE, rect, parent->m_widget, "base", 0, 0, -1, -1);
+    }
         
-        if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
-             (pizza->clear_on_draw))
-        {
-            gdk_window_clear_area( pizza->bin_window,
+        
+    if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
+         (pizza->clear_on_draw))
+    {
+        gdk_window_clear_area( pizza->bin_window,
                                rect->x, rect->y, rect->width, rect->height);
-        }
+    }
     
-        win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
+    win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
 
-        win->m_clipPaintRegion = TRUE;
+    win->m_clipPaintRegion = TRUE;
     
-        wxEraseEvent eevent( win->GetId() );
-        eevent.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent(eevent);
+    wxEraseEvent eevent( win->GetId() );
+    eevent.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent(eevent);
 
-        wxPaintEvent event( win->GetId() );
-        event.SetEventObject( win );
-        win->GetEventHandler()->ProcessEvent( event );
+    wxPaintEvent event( win->GetId() );
+    event.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( event );
 
-        win->GetUpdateRegion().Clear();
+    win->GetUpdateRegion().Clear();
     
-        win->m_clipPaintRegion = FALSE;
+    win->m_clipPaintRegion = FALSE;
     
     
-        GList *children = pizza->children;
-        while (children)
-        {
+    GList *children = pizza->children;
+    while (children)
+    {
             GtkPizzaChild *child = (GtkPizzaChild*) children->data;
             children = children->next;
 
@@ -808,7 +865,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW
             {
                 gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
             }
-        }
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -1039,25 +1096,29 @@ static void AdjustEventButtonState(wxMouseEvent& event)
     // for compatibility with MSW and common sense we want m_leftDown be TRUE
     // for a LEFT_DOWN event, not FALSE, so we will invert
     // left/right/middleDown for the corresponding click events
-    switch ( event.GetEventType() )
+    
+    if ((event.GetEventType() == wxEVT_LEFT_DOWN) ||
+        (event.GetEventType() == wxEVT_LEFT_DCLICK) ||
+        (event.GetEventType() == wxEVT_LEFT_UP))
     {
-        case wxEVT_LEFT_DOWN:
-        case wxEVT_LEFT_DCLICK:
-        case wxEVT_LEFT_UP:
-            event.m_leftDown = !event.m_leftDown;
-            break;
+        event.m_leftDown = !event.m_leftDown;
+        return;
+    }
 
-        case wxEVT_MIDDLE_DOWN:
-        case wxEVT_MIDDLE_DCLICK:
-        case wxEVT_MIDDLE_UP:
-            event.m_middleDown = !event.m_middleDown;
-            break;
+    if ((event.GetEventType() == wxEVT_MIDDLE_DOWN) ||
+        (event.GetEventType() == wxEVT_MIDDLE_DCLICK) ||
+        (event.GetEventType() == wxEVT_MIDDLE_UP))
+    {
+        event.m_middleDown = !event.m_middleDown;
+        return;
+    }
 
-        case wxEVT_RIGHT_DOWN:
-        case wxEVT_RIGHT_DCLICK:
-        case wxEVT_RIGHT_UP:
-            event.m_rightDown = !event.m_rightDown;
-            break;
+    if ((event.GetEventType() == wxEVT_RIGHT_DOWN) ||
+        (event.GetEventType() == wxEVT_RIGHT_DCLICK) ||
+        (event.GetEventType() == wxEVT_RIGHT_UP))
+    {
+        event.m_rightDown = !event.m_rightDown;
+        return;
     }
 }
 
@@ -2276,6 +2337,9 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
 
 wxWindow::~wxWindow()
 {
+    if (g_focusWindow == this)
+        g_focusWindow = NULL;
+
     m_isBeingDeleted = TRUE;
     m_hasVMT = FALSE;
 
@@ -2361,14 +2425,17 @@ void wxWindow::PostCreation()
             
             gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
 
-            gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
-                GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
-
             gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
                 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
 
             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",
+                    GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
+            }
         }
 
 #if (GTK_MINOR_VERSION > 0)
@@ -2412,19 +2479,30 @@ void wxWindow::PostCreation()
 
     if (m_wxwindow)
     {
-        /* Catch native resize events. */
+        // 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. */
+        // Initialize XIM support
         gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
                             GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
 
-        /* And resize XIM window. */
+        // And resize XIM window
         gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
                             GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
     }
 
+    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
+        // 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.
+        gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
+                            GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
+    }
+                           
     m_hasVMT = TRUE;
 }
 
@@ -3749,3 +3827,45 @@ void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
     }
 */
 }
+
+// Find the wxWindow at the current mouse position, also returning the mouse
+// position.
+wxWindow* wxFindWindowAtPointer(wxPoint& pt)
+{
+    pt = wxGetMousePosition();
+    wxWindow* found = wxFindWindowAtPoint(pt);
+    return found;
+}
+
+// Get the current mouse position.
+wxPoint wxGetMousePosition()
+{
+  /* This crashes when used within wxHelpContext,
+     so we have to use the X-specific implementation below.
+    gint x, y;
+    GdkModifierType *mask;
+    (void) gdk_window_get_pointer(NULL, &x, &y, mask);
+
+    return wxPoint(x, y);
+  */
+
+    int x, y;
+    GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
+    if (!windowAtPtr)
+      return wxPoint(-999, -999);
+
+    Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
+    Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
+    Window rootReturn, childReturn;
+    int rootX, rootY, winX, winY;
+    unsigned int maskReturn;
+
+    XQueryPointer (display,
+                  rootWindow,
+                  &rootReturn,
+                   &childReturn,
+                   &rootX, &rootY, &winX, &winY, &maskReturn);
+    return wxPoint(rootX, rootY);
+
+}
+