Merge branch 'composite-contextmenu-event'

Fix event object and ID of wxEVT_CONTEXT_MENU sent from parts of a
composite control.

See https://github.com/wxWidgets/wxWidgets/pull/1698
This commit is contained in:
Vadim Zeitlin
2020-01-09 23:27:17 +01:00
9 changed files with 50 additions and 37 deletions

View File

@@ -1514,6 +1514,12 @@ public:
// Returns true if more idle time is requested. // Returns true if more idle time is requested.
virtual bool SendIdleEvents(wxIdleEvent& event); virtual bool SendIdleEvents(wxIdleEvent& event);
// Send wxContextMenuEvent and return true if it was processed.
//
// Note that the event may end up being sent to a different window, if this
// window is part of a composite control.
bool WXSendContextMenuEvent(const wxPoint& posInScreenCoords);
// get the handle of the window for the underlying window system: this // get the handle of the window for the underlying window system: this
// is only used for wxWin itself or for user code which wants to call // is only used for wxWin itself or for user code which wants to call
// platform-specific APIs // platform-specific APIs

View File

@@ -614,6 +614,8 @@ GridFrame::GridFrame()
grid->SetAttr(11, 11, new wxGridCellAttr); grid->SetAttr(11, 11, new wxGridCellAttr);
grid->SetAttr(11, 11, NULL); grid->SetAttr(11, 11, NULL);
grid->Bind(wxEVT_CONTEXT_MENU, &GridFrame::OnGridContextMenu, this, grid->GetId());
wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
topSizer->Add( grid, topSizer->Add( grid,
1, 1,
@@ -797,6 +799,23 @@ void GridFrame::SetTabCustomHandler(wxCommandEvent&)
grid->Bind(wxEVT_GRID_TABBING, &GridFrame::OnGridCustomTab, this); grid->Bind(wxEVT_GRID_TABBING, &GridFrame::OnGridCustomTab, this);
} }
void GridFrame::OnGridContextMenu(wxContextMenuEvent& event)
{
// This is not supposed to happen: even if the grid consists of different
// subwindows internally, all context menu events should be seen as coming
// from the grid itself.
if ( event.GetEventObject() != grid )
{
wxLogError("Context menu unexpectedly sent from non-grid window.");
}
else
{
wxLogMessage("wxEVT_CONTEXT_MENU in the grid at at (%d, %d)",
event.GetPosition().x, event.GetPosition().y);
}
event.Skip();
}
void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) ) void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) )
{ {

View File

@@ -122,6 +122,8 @@ class GridFrame : public wxFrame
void OnGridCustomTab(wxGridEvent& event); void OnGridCustomTab(wxGridEvent& event);
void OnGridContextMenu(wxContextMenuEvent& event);
public: public:
GridFrame(); GridFrame();
~GridFrame(); ~GridFrame();

View File

@@ -3069,6 +3069,20 @@ wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y)
#endif // wxUSE_MENUS #endif // wxUSE_MENUS
bool wxWindowBase::WXSendContextMenuEvent(const wxPoint& posInScreenCoords)
{
// When the mouse click happens in a subwindow of a composite control,
// the user-visible event should seem to originate from the main window
// and, notably, use its ID and not the (usually auto-generated and so
// not very useful) ID of the subwindow.
wxWindow* const mainWin = GetMainWindowOfCompositeControl();
wxContextMenuEvent
evtCtx(wxEVT_CONTEXT_MENU, mainWin->GetId(), posInScreenCoords);
evtCtx.SetEventObject(mainWin);
return mainWin->HandleWindowEvent(evtCtx);
}
// methods for drawing the sizers in a visible way: this is currently only // methods for drawing the sizers in a visible way: this is currently only
// enabled for "full debug" builds with wxDEBUG_LEVEL==2 as it doesn't work // enabled for "full debug" builds with wxDEBUG_LEVEL==2 as it doesn't work
// that well and also because we don't want to leave it enabled in default // that well and also because we don't want to leave it enabled in default

View File

@@ -1706,12 +1706,8 @@ gtk_window_button_press_callback( GtkWidget* WXUNUSED_IN_GTK3(widget),
// (a) it's a command event and so is propagated to the parent // (a) it's a command event and so is propagated to the parent
// (b) under some ports it can be generated from kbd too // (b) under some ports it can be generated from kbd too
// (c) it uses screen coords (because of (a)) // (c) it uses screen coords (because of (a))
wxContextMenuEvent evtCtx( const wxPoint pos = win->ClientToScreen(event.GetPosition());
wxEVT_CONTEXT_MENU, return win->WXSendContextMenuEvent(pos);
win->GetId(),
win->ClientToScreen(event.GetPosition()));
evtCtx.SetEventObject(win);
return win->GTKProcessEvent(evtCtx);
} }
return FALSE; return FALSE;

View File

@@ -1629,12 +1629,8 @@ static gint gtk_window_button_press_callback( GtkWidget *widget,
// (a) it's a command event and so is propagated to the parent // (a) it's a command event and so is propagated to the parent
// (b) under some ports it can be generated from kbd too // (b) under some ports it can be generated from kbd too
// (c) it uses screen coords (because of (a)) // (c) it uses screen coords (because of (a))
wxContextMenuEvent evtCtx( const wxPoint pos = win->ClientToScreen(event.GetPosition());
wxEVT_CONTEXT_MENU, return win->WXSendContextMenuEvent(pos);
win->GetId(),
win->ClientToScreen(event.GetPosition()));
evtCtx.SetEventObject(win);
return win->HandleWindowEvent(evtCtx);
} }
return FALSE; return FALSE;

View File

@@ -3636,8 +3636,6 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
// the event may be handled by a parent window // the event may be handled by a parent window
wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
// we could have got an event from our child, reflect it back // we could have got an event from our child, reflect it back
// to it if this is the case // to it if this is the case
wxWindowMSW *win = NULL; wxWindowMSW *win = NULL;
@@ -3650,8 +3648,7 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
if ( !win ) if ( !win )
win = this; win = this;
evtCtx.SetEventObject(win); processed = win->WXSendContextMenuEvent(pt);
processed = win->HandleWindowEvent(evtCtx);
if ( !processed ) if ( !processed )
{ {

View File

@@ -2338,20 +2338,7 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
{ {
if ( event.GetEventType() == wxEVT_RIGHT_DOWN ) if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
{ {
// copied from wxGTK : CS if ( !WXSendContextMenuEvent(ClientToScreen(event.GetPosition())) )
// VZ: shouldn't we move this to base class then?
// generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
// except that:
//
// (a) it's a command event and so is propagated to the parent
// (b) under MSW it can be generated from kbd too
// (c) it uses screen coords (because of (a))
wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
this->GetId(),
this->ClientToScreen(event.GetPosition()));
evtCtx.SetEventObject(this);
if ( ! HandleWindowEvent(evtCtx) )
event.Skip() ; event.Skip() ;
} }
else else

View File

@@ -1619,15 +1619,11 @@ bool wxWindowQt::QtHandleCloseEvent ( QWidget *handler, QCloseEvent *WXUNUSED( e
bool wxWindowQt::QtHandleContextMenuEvent ( QWidget *WXUNUSED( handler ), QContextMenuEvent *event ) bool wxWindowQt::QtHandleContextMenuEvent ( QWidget *WXUNUSED( handler ), QContextMenuEvent *event )
{ {
wxContextMenuEvent e( wxEVT_CONTEXT_MENU, GetId() ); const wxPoint pos =
e.SetPosition(
event->reason() == QContextMenuEvent::Keyboard event->reason() == QContextMenuEvent::Keyboard
? wxDefaultPosition ? wxDefaultPosition
: wxQtConvertPoint( event->globalPos() ) : wxQtConvertPoint( event->globalPos() );
); return WXSendContextMenuEvent(pos);
e.SetEventObject(this);
return ProcessWindowEvent( e );
} }
bool wxWindowQt::QtHandleFocusEvent ( QWidget *WXUNUSED( handler ), QFocusEvent *event ) bool wxWindowQt::QtHandleFocusEvent ( QWidget *WXUNUSED( handler ), QFocusEvent *event )