]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Adapt MSW's renderer's alignment to use column header's alignment by default
[wxWidgets.git] / src / gtk / window.cpp
index 6fd61448e0f9a8533dbec1d793b77d693dc57102..5b92e382246a559dc4b781e48f14d36c7fc51a61 100644 (file)
@@ -185,9 +185,11 @@ extern wxCursor   g_globalCursor;
 static wxWindowGTK  *g_captureWindow = (wxWindowGTK*) NULL;
 static bool g_captureWindowHasMouse = false;
 
-// The window that currently has focus or is scheduled to get it in the next
-// event loop iteration
-static wxWindowGTK *gs_focusWindow = NULL;
+// The window that currently has focus:
+static wxWindowGTK *gs_currentFocus = NULL;
+// The window that is scheduled to get focus in the next event loop iteration
+// or NULL if there's no pending focus change:
+static wxWindowGTK *gs_pendingFocus = NULL;
 
 // the window that has deferred focus-out event pending, if any (see
 // GTKAddDeferredFocusOut() for details)
@@ -869,8 +871,18 @@ gtk_window_key_press_callback( GtkWidget *widget,
             int command = ancestor->GetAcceleratorTable()->GetCommand( event );
             if (command != -1)
             {
-                wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
-                ret = ancestor->HandleWindowEvent( command_event );
+                wxCommandEvent menu_event( wxEVT_COMMAND_MENU_SELECTED, command );
+                ret = ancestor->HandleWindowEvent( menu_event );
+
+                if ( !ret )
+                {
+                    // if the accelerator wasn't handled as menu event, try
+                    // it as button click (for compatibility with other
+                    // platforms):
+                    wxCommandEvent button_event( wxEVT_COMMAND_BUTTON_CLICKED, command );
+                    ret = ancestor->HandleWindowEvent( button_event );
+                }
+
                 break;
             }
             if (ancestor->IsTopLevel())
@@ -1372,7 +1384,7 @@ gtk_window_button_press_callback( GtkWidget *widget,
         return TRUE;
 
     if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() &&
-        (gs_focusWindow != win) /* && win->IsFocusable() */)
+        (gs_currentFocus != win) /* && win->IsFocusable() */)
     {
         win->SetFocus();
     }
@@ -1891,8 +1903,9 @@ public:
 
 wxWindow *wxWindowBase::DoFindFocus()
 {
+    wxWindowGTK *focus = gs_pendingFocus ? gs_pendingFocus : gs_currentFocus;
     // the cast is necessary when we compile in wxUniversal mode
-    return wx_static_cast(wxWindow*, gs_focusWindow);
+    return wx_static_cast(wxWindow*, focus);
 }
 
 //-----------------------------------------------------------------------------
@@ -2127,6 +2140,8 @@ bool wxWindowGTK::Create( wxWindow *parent,
 
     m_focusWidget = m_wxwindow;
 
+    SetCanFocus(AcceptsFocus());
+
     PostCreation();
 
     return true;
@@ -2136,8 +2151,10 @@ wxWindowGTK::~wxWindowGTK()
 {
     SendDestroyEvent();
 
-    if (gs_focusWindow == this)
-        gs_focusWindow = NULL;
+    if (gs_currentFocus == this)
+        gs_currentFocus = NULL;
+    if (gs_pendingFocus == this)
+        gs_pendingFocus = NULL;
 
     if ( gs_deferredFocusOut == this )
         gs_deferredFocusOut = NULL;
@@ -2907,9 +2924,8 @@ bool wxWindowGTK::GTKHandleFocusIn()
     if (m_imData)
         gtk_im_context_focus_in(m_imData->context);
 
-    // NB: SetFocus() does this assignment too, but not all focus changes
-    //     originate from SetFocus() call
-    gs_focusWindow = this;
+    gs_currentFocus = this;
+    gs_pendingFocus = NULL;
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
@@ -2971,22 +2987,22 @@ void wxWindowGTK::GTKHandleFocusOutNoDeferring()
     if (m_imData)
         gtk_im_context_focus_out(m_imData->context);
 
-    if ( gs_focusWindow != this )
+    if ( gs_currentFocus != this )
     {
-        // Something is terribly wrong, gs_focusWindow is out of sync with the
+        // Something is terribly wrong, gs_currentFocus is out of sync with the
         // real focus. We will reset it to NULL anyway, because after this
         // focus-out event is handled, one of the following with happen:
         //
         // * either focus will go out of the app altogether, in which case
-        //   gs_focusWindow _should_ be NULL
+        //   gs_currentFocus _should_ be NULL
         //
         // * or it goes to another control, in which case focus-in event will
-        //   follow immediately and it will set gs_focusWindow to the right
+        //   follow immediately and it will set gs_currentFocus to the right
         //   value
         wxLogDebug("window %s(%p, %s) lost focus even though it didn't have it",
                    GetClassInfo()->GetClassName(), this, GetLabel());
     }
-    gs_focusWindow = NULL;
+    gs_currentFocus = NULL;
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
@@ -3037,7 +3053,7 @@ void wxWindowGTK::SetFocus()
     // Because we want to FindFocus() call immediately following
     // foo->SetFocus() to return foo, we have to keep track of "pending" focus
     // ourselves.
-    gs_focusWindow = this;
+    gs_pendingFocus = this;
 
     GtkWidget *widget = m_wxwindow ? m_wxwindow : m_focusWidget;
 
@@ -3833,13 +3849,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 
 #if wxUSE_MENUS_NATIVE
 
-extern "C" WXDLLIMPEXP_CORE
-void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting  )
-{
-    *is_waiting = false;
-}
-
-WXDLLIMPEXP_CORE void SetInvokingWindow( wxMenu *menu, wxWindow* win )
+static void SetInvokingWindow( wxMenu *menu, wxWindow* win )
 {
     menu->SetInvokingWindow( win );
 
@@ -3856,7 +3866,8 @@ WXDLLIMPEXP_CORE void SetInvokingWindow( wxMenu *menu, wxWindow* win )
     }
 }
 
-extern "C" WXDLLIMPEXP_CORE
+extern "C" {
+static
 void wxPopupMenuPositionCallback( GtkMenu *menu,
                                   gint *x, gint *y,
                                   gboolean * WXUNUSED(whatever),
@@ -3875,6 +3886,12 @@ void wxPopupMenuPositionCallback( GtkMenu *menu,
     *x = pos->x < xmax ? pos->x : xmax;
     *y = pos->y < ymax ? pos->y : ymax;
 }
+}
+
+void wxWindowGTK::DoPopupMenuUpdateUI(wxMenu* menu)
+{
+    menu->UpdateUI();
+}
 
 bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 {
@@ -3882,13 +3899,9 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 
     wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") );
 
-    // NOTE: if you change this code, you need to update
-    //       the same code in taskbar.cpp as well. This
-    //       is ugly code duplication, I know.
-
     SetInvokingWindow( menu, this );
 
-    menu->UpdateUI();
+    DoPopupMenuUpdateUI(menu);
 
     wxPoint pos;
     gpointer userdata;
@@ -4300,16 +4313,68 @@ GdkWindow* wxWindowGTK::GTKGetDrawingWindow() const
 // freeze/thaw
 // ----------------------------------------------------------------------------
 
+extern "C"
+{
+
+// this is called if we attempted to freeze unrealized widget when it finally
+// is realized (and so can be frozen):
+static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data))
+{
+    wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) );
+    wxASSERT( GTK_WIDGET_REALIZED(w) );
+
+    g_signal_handlers_disconnect_by_func
+    (
+        w,
+        (void*)wx_frozen_widget_realize,
+        NULL
+    );
+
+    gdk_window_freeze_updates(w->window);
+}
+
+} // extern "C"
+
 void wxWindowGTK::GTKFreezeWidget(GtkWidget *w)
 {
-    if ( w && !GTK_WIDGET_NO_WINDOW(w) )
-        gdk_window_freeze_updates(w->window);
+    if ( !w || GTK_WIDGET_NO_WINDOW(w) )
+        return; // window-less widget, cannot be frozen
+
+    if ( !GTK_WIDGET_REALIZED(w) )
+    {
+        // we can't thaw unrealized widgets because they don't have GdkWindow,
+        // so set it up to be done immediately after realization:
+        g_signal_connect_after
+        (
+            w,
+            "realize",
+            G_CALLBACK(wx_frozen_widget_realize),
+            NULL
+        );
+        return;
+    }
+
+    gdk_window_freeze_updates(w->window);
 }
 
 void wxWindowGTK::GTKThawWidget(GtkWidget *w)
 {
-    if ( w && !GTK_WIDGET_NO_WINDOW(w) )
-        gdk_window_thaw_updates(w->window);
+    if ( !w || GTK_WIDGET_NO_WINDOW(w) )
+        return; // window-less widget, cannot be frozen
+
+    if ( !GTK_WIDGET_REALIZED(w) )
+    {
+        // the widget wasn't realized yet, no need to thaw
+        g_signal_handlers_disconnect_by_func
+        (
+            w,
+            (void*)wx_frozen_widget_realize,
+            NULL
+        );
+        return;
+    }
+
+    gdk_window_thaw_updates(w->window);
 }
 
 void wxWindowGTK::DoFreeze()