// Purpose: Test events propagation
// Author: Vadim Zeitlin
// Created: 2009-01-16
-// RCS-ID: $Id$
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "wx/menu.h"
#include "wx/scopedptr.h"
#include "wx/scopeguard.h"
+#include "wx/toolbar.h"
+#include "wx/uiaction.h"
+
+// FIXME: Currently under OS X testing paint event doesn't work because neither
+// calling Refresh()+Update() nor even sending wxPaintEvent directly to
+// the window doesn't result in calls to its event handlers, so disable
+// some tests there. But this should be fixed and the tests reenabled
+// because wxPaintEvent propagation in wxScrolledWindow is a perfect
+// example of fragile code that could be broken under OS X.
+#ifndef __WXOSX__
+ #define CAN_TEST_PAINT_EVENTS
+#endif
namespace
{
Connect(wxEVT_PAINT, wxPaintEventHandler(TestScrollWindow::OnPaint));
}
+ void GeneratePaintEvent()
+ {
+#ifdef __WXGTK__
+ // We need to map the window, otherwise we're not going to get any
+ // paint events for it.
+ wxYield();
+
+ // Ignore events generated during the initial mapping.
+ g_str.clear();
+#endif // __WXGTK__
+
+ Refresh();
+ Update();
+ }
+
virtual void OnDraw(wxDC& WXUNUSED(dc))
{
g_str += 'D'; // draw
CPPUNIT_TEST( ScrollWindowWithHandler );
CPPUNIT_TEST( MenuEvent );
CPPUNIT_TEST( DocView );
+ WXUISIM_TEST( ContextMenuEvent );
CPPUNIT_TEST_SUITE_END();
void OneHandler();
void ScrollWindowWithHandler();
void MenuEvent();
void DocView();
+ void ContextMenuEvent();
DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
};
TestScrollWindow * const win = new TestScrollWindow(parent);
-#if !defined(__WXOSX__) && !defined(__WXGTK3__)
- wxPaintEvent event(win->GetId());
- win->ProcessWindowEvent(event);
+#ifdef CAN_TEST_PAINT_EVENTS
+ win->GeneratePaintEvent();
CPPUNIT_ASSERT_EQUAL( "PD", g_str );
#endif
+
g_str.clear();
wxCommandEvent eventCmd(TEST_EVT);
win->HandleWindowEvent(eventCmd);
TestScrollWindow * const win = new TestScrollWindow(parent);
-#if !defined(__WXOSX__) && !defined(__WXGTK3__)
+#ifdef CAN_TEST_PAINT_EVENTS
TestPaintEvtHandler h('h');
win->PushEventHandler(&h);
wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
- wxPaintEvent event(win->GetId());
- win->ProcessWindowEvent(event);
+ win->GeneratePaintEvent();
CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
#endif
wxDocument* const doc = docTemplate.CreateDocument("");
wxView* const view = doc->GetFirstView();
- wxScopedPtr<wxFrame>
+ wxScopedPtr<wxMDIChildFrame>
child(new wxDocMDIChildFrame(doc, view, parent.get(), wxID_ANY, "Child"));
wxMenu* const menuChild = CreateTestMenu(child.get());
+ // Ensure that the child that we've just created is the active one.
+ child->Activate();
+
#ifdef __WXGTK__
// There are a lot of hacks related to child frame menu bar handling in
// wxGTK and, in particular, the code in src/gtk/mdi.cpp relies on getting
// Check that wxDocument, wxView, wxDocManager, child frame and the parent
// get the event in order.
ASSERT_MENU_EVENT_RESULT( menuChild, "advmcpA" );
+
+
+#if wxUSE_TOOLBAR
+ // Also check that toolbar events get forwarded to the active child.
+ wxToolBar* const tb = parent->CreateToolBar(wxTB_NOICONS);
+ tb->AddTool(wxID_APPLY, "Apply", wxNullBitmap);
+ tb->Realize();
+
+ // As in CheckMenuEvent(), use toolbar method actually sending the event
+ // instead of bothering with wxUIActionSimulator which would have been
+ // trickier.
+ g_str.clear();
+ tb->OnLeftClick(wxID_APPLY, true /* doesn't matter */);
+
+ CPPUNIT_ASSERT_EQUAL( "advmcpA", g_str );
+#endif // wxUSE_TOOLBAR
}
+
+#if wxUSE_UIACTIONSIMULATOR
+
+class ContextMenuTestWindow : public wxWindow
+{
+public:
+ ContextMenuTestWindow(wxWindow *parent, char tag)
+ : wxWindow(parent, wxID_ANY),
+ m_tag(tag)
+ {
+ Connect(wxEVT_CONTEXT_MENU,
+ wxContextMenuEventHandler(ContextMenuTestWindow::OnMenu));
+ }
+
+private:
+ void OnMenu(wxContextMenuEvent& event)
+ {
+ g_str += m_tag;
+
+ event.Skip();
+ }
+
+ const char m_tag;
+
+ wxDECLARE_NO_COPY_CLASS(ContextMenuTestWindow);
+};
+
+void EventPropagationTestCase::ContextMenuEvent()
+{
+ ContextMenuTestWindow * const
+ parent = new ContextMenuTestWindow(wxTheApp->GetTopWindow(), 'p');
+ wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
+
+ ContextMenuTestWindow * const
+ child = new ContextMenuTestWindow(parent, 'c');
+ parent->SetSize(100, 100);
+ child->SetSize(0, 0, 50, 50);
+ child->SetFocus();
+
+ wxUIActionSimulator sim;
+ const wxPoint origin = parent->ClientToScreen(wxPoint(0, 0));
+
+ // Right clicking in the child should generate an event for it and the
+ // parent.
+ g_str.clear();
+ sim.MouseMove(origin + wxPoint(10, 10));
+ sim.MouseClick(wxMOUSE_BTN_RIGHT);
+
+ // At least with MSW, for WM_CONTEXTMENU to be synthesized by the system
+ // from the right mouse click event, we must dispatch the mouse messages.
+ wxYield();
+
+ CPPUNIT_ASSERT_EQUAL( "cp", g_str );
+
+ // Right clicking outside the child should generate the event just in the
+ // parent.
+ g_str.clear();
+ sim.MouseMove(origin + wxPoint(60, 60));
+ sim.MouseClick(wxMOUSE_BTN_RIGHT);
+ wxYield();
+ CPPUNIT_ASSERT_EQUAL( "p", g_str );
+}
+
+#endif // wxUSE_UIACTIONSIMULATOR