]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/window.cpp
updated i18n sample, french translations are now in the "fr" subdirectory.
[wxWidgets.git] / src / gtk1 / window.cpp
index f35ab5fb869801f73d8b078e211efb7dfd5cac75..f49fb9cf9bfb3063dd44b74f41a6ad7c91d5da12 100644 (file)
 #include "wx/utils.h"
 #include "wx/dialog.h"
 #include "wx/msgdlg.h"
-#include "wx/dcclient.h"
+#if wxUSE_DRAG_AND_DROP
 #include "wx/dnd.h"
+#endif
 #include "wx/menu.h"
 #include "wx/statusbr.h"
 #include "wx/intl.h"
 #include "wx/settings.h"
 #include "wx/log.h"
-#include "gdk/gdkprivate.h"
-#include "gdk/gdkkeysyms.h"
 
 #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"
+
 //-----------------------------------------------------------------------------
 // documentation on internals
 //-----------------------------------------------------------------------------
 #endif
 #endif
 
+//-----------------------------------------------------------------------------
+// (debug)
+//-----------------------------------------------------------------------------
+
+#ifdef __WXDEBUG__
+
+static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget), 
+                                         GdkEvent *WXUNUSED(event), 
+                                        const char *name )
+{
+    printf( "FOCUS NOW AT: " );
+    printf( name );
+    printf( "\n" );
+    
+    return FALSE;
+}
+
+void debug_focus_in( GtkWidget* widget, const char* name, const char *window )
+{
+    return;
+
+    wxString tmp = name;
+    tmp += " FROM ";
+    tmp += window;
+    
+    char *s = new char[tmp.Length()+1];
+    
+    strcpy( s, WXSTRINGCAST tmp );
+
+    gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
+      GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
+}
+
+#endif
+
 //-----------------------------------------------------------------------------
 // data
 //-----------------------------------------------------------------------------
 
-extern wxList wxPendingDelete;
-extern wxList wxTopLevelWindows;
-extern bool   g_blockEventsOnDrag;
-extern bool   g_blockEventsOnScroll;
-static bool   g_capturing = FALSE;
+extern wxList     wxPendingDelete;
+extern wxList     wxTopLevelWindows;
+extern bool       g_blockEventsOnDrag;
+extern bool       g_blockEventsOnScroll;
+static bool       g_capturing = FALSE;
+static wxWindow  *g_focusWindow = (wxWindow*) NULL;
 
 // hack: we need something to pass to gtk_menu_popup, so we store the time of
 // the last click here
@@ -181,7 +222,7 @@ static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle
 }
 
 //-----------------------------------------------------------------------------
-// "key_press_event"
+// "key_press_event" from any window
 //-----------------------------------------------------------------------------
 
 static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
@@ -303,11 +344,41 @@ static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_e
             ancestor = ancestor->GetParent();
         }
     }
-
+    
+    // win is a control: tab can be propagated up
+    if ((!ret) && (gdk_event->keyval == GDK_Tab))
+    {
+        wxNavigationKeyEvent new_event;
+        new_event.SetDirection( !(gdk_event->state & GDK_SHIFT_MASK) );
+       new_event.SetWindowChange( FALSE );
+        new_event.SetCurrentFocus( win );
+       ret = win->GetEventHandler()->ProcessEvent( new_event );
+    }
+    
+/*
+    // win is a panel: up can be propagated to the panel
+    if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
+        (gdk_event->keyval == GDK_Up))
+    {
+        win->m_parent->SetFocus();
+       ret = TRUE;
+    }
+    
+    // win is a panel: left/right can be propagated to the panel
+    if ((!ret) && (win->m_wxwindow) && 
+        ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) || 
+         (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
+    {
+        wxNavigationKeyEvent new_event;
+        new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
+        new_event.SetCurrentFocus( win );
+       ret = win->GetEventHandler()->ProcessEvent( new_event );
+    }
+*/
+    
     if (ret)
     {
-        if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
-            gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
+        gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
     }
 
     return ret;
@@ -563,6 +634,17 @@ static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButto
 
 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
 {
+    if (gdk_event->is_hint) 
+    {
+       int x = 0;
+       int y = 0;
+       GdkModifierType state;
+       gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
+       gdk_event->x = x;
+       gdk_event->y = y;
+       gdk_event->state = state;
+    }
+    
     if (!win->IsOwnGtkWindow( gdk_event->window )) return TRUE;
 
     if (g_blockEventsOnDrag) return TRUE;
@@ -575,7 +657,7 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
       printf( win->GetClassInfo()->GetClassName() );
     printf( ".\n" );
-*/    
+*/
 
     wxMouseEvent event( wxEVT_MOTION );
     event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
@@ -658,6 +740,9 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion
 static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
 {
     if (g_blockEventsOnDrag) return TRUE;
+    
+    g_focusWindow = win;
+    
     if (win->m_wxwindow)
     {
         if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
@@ -729,10 +814,13 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED
 
 static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
 {
-    if (widget->window != gdk_event->window) return TRUE;
-
     if (g_blockEventsOnDrag) return TRUE;
 
+    if ((widget->window) && (win->m_cursor))
+        gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
+
+    if (widget->window != gdk_event->window) return TRUE;
+
     if (!win->HasVMT()) return TRUE;
 
 /*
@@ -742,9 +830,6 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
     printf( ".\n" );
 */
 
-    if ((widget->window) && (win->m_cursor))
-        gdk_window_set_cursor( widget->window, win->m_cursor->GetCursor() );
-
     wxMouseEvent event( wxEVT_ENTER_WINDOW );
     event.SetEventObject( win );
     
@@ -777,10 +862,13 @@ static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_
 
 static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
 {
-    if (widget->window != gdk_event->window) return TRUE;
-
     if (g_blockEventsOnDrag) return TRUE;
 
+    if ((widget->window) && (win->m_cursor))
+        gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
+
+    if (widget->window != gdk_event->window) return TRUE;
+
     if (!win->HasVMT()) return TRUE;
 
 /*
@@ -790,9 +878,6 @@ static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_
     printf( ".\n" );
 */
 
-    if ((widget->window) && (win->m_cursor))
-        gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
-
     wxMouseEvent event( wxEVT_LEAVE_WINDOW );
     event.SetEventObject( win );
 
@@ -1032,6 +1117,15 @@ static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
                          child->m_height );
 }
 
+//-----------------------------------------------------------------------------
+// global functions
+//-----------------------------------------------------------------------------
+
+wxWindow* wxGetActiveWindow()
+{
+  return g_focusWindow;
+}
+
 //-----------------------------------------------------------------------------
 // wxWindow
 //-----------------------------------------------------------------------------
@@ -1093,7 +1187,9 @@ wxWindow::wxWindow()
     m_isShown = FALSE;
     m_isEnabled = TRUE;
 
+#if wxUSE_DRAG_AND_DROP
     m_dropTarget = (wxDropTarget*) NULL;
+#endif
     m_resizing = FALSE;
     m_scrollGC = (GdkGC*) NULL;
     m_widgetStyle = (GtkStyle*) NULL;
@@ -1104,6 +1200,7 @@ wxWindow::wxWindow()
     m_clientData = NULL;
     
     m_isStaticBox = FALSE;
+    m_acceptsFocus = FALSE;
 }
 
 wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
@@ -1126,9 +1223,18 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
 
     m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
     GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
+    
+#ifdef __WXDEBUG__
+    debug_focus_in( m_widget, "wxWindow::m_widget", name );
+#endif
 
     GtkScrolledWindow *s_window = GTK_SCROLLED_WINDOW(m_widget);
 
+#ifdef __WXDEBUG__
+    debug_focus_in( s_window->hscrollbar, "wxWindow::hsrcollbar", name );
+    debug_focus_in( s_window->vscrollbar, "wxWindow::vsrcollbar", name );
+#endif
+
     GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
     scroll_class->scrollbar_spacing = 0;
 
@@ -1142,6 +1248,10 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
 
     m_wxwindow = gtk_myfixed_new();
 
+#ifdef __WXDEBUG__
+    debug_focus_in( m_wxwindow, "wxWindow::m_wxwindow", name );
+#endif
+
 #ifdef NEW_GTK_SCROLL_CODE
     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(m_widget), m_wxwindow );
     GtkViewport *viewport = GTK_VIEWPORT(s_window->child);
@@ -1150,6 +1260,10 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
     GtkViewport *viewport = GTK_VIEWPORT(s_window->viewport);
 #endif
 
+#ifdef __WXDEBUG__
+    debug_focus_in( GTK_WIDGET(viewport), "wxWindow::viewport", name );
+#endif
+
     if (m_windowStyle & wxRAISED_BORDER)
     {
         gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
@@ -1163,10 +1277,16 @@ bool wxWindow::Create( wxWindow *parent, wxWindowID id,
         gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
     }
 
-    if (m_windowStyle & wxTAB_TRAVERSAL == wxTAB_TRAVERSAL)
+    if ((m_windowStyle & wxTAB_TRAVERSAL) != 0)
+    {
         GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
+        m_acceptsFocus = FALSE;
+    }
     else
+    {
         GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
+        m_acceptsFocus = TRUE;
+    }
 
     // shut the viewport up
     gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
@@ -1235,7 +1355,9 @@ wxWindow::~wxWindow()
 {
     m_hasVMT = FALSE;
 
+#if wxUSE_DRAG_AND_DROP
     if (m_dropTarget) delete m_dropTarget;
+#endif
 
     if (m_parent) m_parent->RemoveChild( this );
     if (m_widget) Show( FALSE );
@@ -1354,7 +1476,9 @@ void wxWindow::PreCreation( wxWindow *parent, wxWindowID id,
     m_isShown = FALSE;
     m_isEnabled = TRUE;
 
+#if wxUSE_DRAG_AND_DROP
     m_dropTarget = (wxDropTarget *) NULL;
+#endif
     m_resizing = FALSE;
     m_windowValidator = (wxValidator *) NULL;
     m_scrollGC = (GdkGC*) NULL;
@@ -1523,8 +1647,8 @@ void wxWindow::SetSize( int x, int y, int width, int height, int sizeFlags )
 
         if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
         if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
-        if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
-        if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
+        if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
+        if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
 
         wxPoint pt( m_parent->GetClientAreaOrigin() );
         gtk_myfixed_move( GTK_MYFIXED(m_parent->m_wxwindow), m_widget, m_x+pt.x, m_y+pt.y );
@@ -1902,17 +2026,34 @@ void wxWindow::MakeModal( bool modal )
 void wxWindow::SetFocus()
 {
     wxCHECK_RET( (m_widget != NULL), "invalid window" );
-
+    
     GtkWidget *connect_widget = GetConnectWidget();
     if (connect_widget)
     {
-        if (GTK_WIDGET_CAN_FOCUS(connect_widget) && !GTK_WIDGET_HAS_FOCUS (connect_widget) )
+        if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
         {
             gtk_widget_grab_focus (connect_widget);
         }
+       else if (GTK_IS_CONTAINER(connect_widget))
+       {
+           gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
+       }
+       else
+       {
+       }
     }
 }
 
+wxWindow *wxWindow::FindFocus()
+{
+    return g_focusWindow;
+}
+
+bool wxWindow::AcceptsFocus() const
+{
+    return IsEnabled() && IsShown() && m_acceptsFocus;
+}
+
 bool wxWindow::OnClose()
 {
     return TRUE;
@@ -2080,6 +2221,11 @@ void wxWindow::SetCursor( const wxCursor &cursor )
          gdk_window_set_cursor( m_wxwindow->window, m_cursor->GetCursor() );
 }
 
+void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
+{
+  // TODO
+}
+
 void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
 {
     wxCHECK_RET( (m_widget != NULL), "invalid window" );
@@ -2164,14 +2310,6 @@ void wxWindow::SetBackgroundColour( const wxColour &colour )
 
     if (m_backgroundColour == colour) return;
 
-    wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
-    if (sysbg.Red() == colour.Red() && 
-        sysbg.Green() == colour.Green() && 
-        sysbg.Blue() == colour.Blue())
-    {
-        return;
-    } 
-
     m_backgroundColour = colour;
     if (!m_backgroundColour.Ok()) return;
 
@@ -2183,7 +2321,19 @@ void wxWindow::SetBackgroundColour( const wxColour &colour )
         gdk_window_clear( window );
     }
 
-    ApplyWidgetStyle();
+    wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
+    if (sysbg.Red() == colour.Red() && 
+        sysbg.Green() == colour.Green() && 
+        sysbg.Blue() == colour.Blue())
+    {
+        m_backgroundColour = wxNullColour;
+        ApplyWidgetStyle();
+       m_backgroundColour = sysbg;
+    } 
+    else
+    {
+        ApplyWidgetStyle();
+    }
 }
 
 wxColour wxWindow::GetForegroundColour() const
@@ -2200,7 +2350,19 @@ void wxWindow::SetForegroundColour( const wxColour &colour )
     m_foregroundColour = colour;
     if (!m_foregroundColour.Ok()) return;
 
-    ApplyWidgetStyle();
+    wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
+    if (sysbg.Red() == colour.Red() && 
+        sysbg.Green() == colour.Green() && 
+        sysbg.Blue() == colour.Blue())
+    {
+        m_backgroundColour = wxNullColour;
+        ApplyWidgetStyle();
+       m_backgroundColour = sysbg;
+    } 
+    else
+    {
+        ApplyWidgetStyle();
+    }
 }
 
 GtkStyle *wxWindow::GetWidgetStyle()
@@ -2353,6 +2515,8 @@ bool wxWindow::PopupMenu( wxMenu *menu, int WXUNUSED(x), int WXUNUSED(y) )
     return TRUE;
 }
 
+#if wxUSE_DRAG_AND_DROP
+
 void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
 {
     wxCHECK_RET( m_widget != NULL, "invalid window" );
@@ -2372,6 +2536,8 @@ wxDropTarget *wxWindow::GetDropTarget() const
     return m_dropTarget;
 }
 
+#endif
+
 GtkWidget* wxWindow::GetConnectWidget()
 {
     GtkWidget *connect_widget = m_widget;
@@ -2395,7 +2561,19 @@ void wxWindow::SetFont( const wxFont &font )
     else
         m_font = *wxSWISS_FONT;
 
-    ApplyWidgetStyle();
+    wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
+    if (sysbg.Red() == m_backgroundColour.Red() && 
+        sysbg.Green() == m_backgroundColour.Green() && 
+        sysbg.Blue() == m_backgroundColour.Blue())
+    {
+        m_backgroundColour = wxNullColour;
+        ApplyWidgetStyle();
+       m_backgroundColour = sysbg;
+    } 
+    else
+    {
+        ApplyWidgetStyle();
+    }
 }
 
 void wxWindow::SetWindowStyleFlag( long flag )
@@ -3126,8 +3304,8 @@ void wxWindow::GetClientSizeConstraint(int *w, int *h) const
 
 void wxWindow::GetPositionConstraint(int *x, int *y) const
 {
 wxLayoutConstraints *constr = GetConstraints();
-  if (constr)
+ wxLayoutConstraints *constr = GetConstraints();
+    if (constr)
   {
     *x = constr->left.GetValue();
     *y = constr->top.GetValue();
@@ -3136,12 +3314,7 @@ void wxWindow::GetPositionConstraint(int *x, int *y) const
     GetPosition(x, y);
 }
 
-bool wxWindow::AcceptsFocus() const
-{
-  return IsEnabled() && IsShown();
-}
-
 void wxWindow::OnIdle(wxIdleEvent& WXUNUSED(event) )
 {
-  UpdateWindowUI();
+    UpdateWindowUI();
 }