Fix popup menu position on non-primary displays in wxGTK
If the popup menu position was explicitly specified, it wasn't taken into account correctly in wxGTK code as it always clamped it to the primary display boundaries, even if the window showing the menu wasn't on this monitor at all, typically resulting in the menu shown at the left or right edge of the monitor instead of the correct position. Fix this by using the display containing the window instead. This requires passing the window, or rather the menu from which it can be retrieved, to wxPopupMenuPositionCallback too, so add a helper struct to pass both the position and the menu to it. Closes https://github.com/wxWidgets/wxWidgets/pull/1621
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
#include "wx/math.h"
|
#include "wx/math.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "wx/display.h"
|
||||||
#include "wx/dnd.h"
|
#include "wx/dnd.h"
|
||||||
#include "wx/tooltip.h"
|
#include "wx/tooltip.h"
|
||||||
#include "wx/caret.h"
|
#include "wx/caret.h"
|
||||||
@@ -5678,6 +5679,12 @@ void wxWindowGTK::GTKFindWindow(GtkWidget* widget, wxArrayGdkWindows& windows)
|
|||||||
|
|
||||||
#if wxUSE_MENUS_NATIVE
|
#if wxUSE_MENUS_NATIVE
|
||||||
|
|
||||||
|
struct wxPopupMenuPositionCallbackData
|
||||||
|
{
|
||||||
|
wxPoint pos;
|
||||||
|
wxMenu *menu;
|
||||||
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static
|
static
|
||||||
void wxPopupMenuPositionCallback( GtkMenu *menu,
|
void wxPopupMenuPositionCallback( GtkMenu *menu,
|
||||||
@@ -5685,7 +5692,7 @@ void wxPopupMenuPositionCallback( GtkMenu *menu,
|
|||||||
gboolean * WXUNUSED(whatever),
|
gboolean * WXUNUSED(whatever),
|
||||||
gpointer user_data )
|
gpointer user_data )
|
||||||
{
|
{
|
||||||
// ensure that the menu appears entirely on screen
|
// ensure that the menu appears entirely on the same display as the window
|
||||||
GtkRequisition req;
|
GtkRequisition req;
|
||||||
#ifdef __WXGTK3__
|
#ifdef __WXGTK3__
|
||||||
gtk_widget_get_preferred_size(GTK_WIDGET(menu), &req, NULL);
|
gtk_widget_get_preferred_size(GTK_WIDGET(menu), &req, NULL);
|
||||||
@@ -5693,14 +5700,24 @@ void wxPopupMenuPositionCallback( GtkMenu *menu,
|
|||||||
gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req);
|
gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wxSize sizeScreen = wxGetDisplaySize();
|
const wxPopupMenuPositionCallbackData&
|
||||||
wxPoint *pos = (wxPoint*)user_data;
|
data = *static_cast<wxPopupMenuPositionCallbackData*>(user_data);
|
||||||
|
|
||||||
gint xmax = sizeScreen.x - req.width,
|
const wxRect
|
||||||
ymax = sizeScreen.y - req.height;
|
rect = wxDisplay(data.menu->GetInvokingWindow()).GetClientArea();
|
||||||
|
|
||||||
*x = pos->x < xmax ? pos->x : xmax;
|
wxPoint pos = data.pos;
|
||||||
*y = pos->y < ymax ? pos->y : ymax;
|
if ( pos.x < rect.x )
|
||||||
|
pos.x = rect.x;
|
||||||
|
if ( pos.y < rect.y )
|
||||||
|
pos.y = rect.y;
|
||||||
|
if ( pos.x + req.width > rect.GetRight() )
|
||||||
|
pos.x = rect.GetRight() - req.width;
|
||||||
|
if ( pos.y + req.height > rect.GetBottom() )
|
||||||
|
pos.y = rect.GetBottom() - req.height;
|
||||||
|
|
||||||
|
*x = pos.x;
|
||||||
|
*y = pos.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5708,7 +5725,7 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
|
|||||||
{
|
{
|
||||||
wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
|
wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
|
||||||
|
|
||||||
wxPoint pos;
|
wxPopupMenuPositionCallbackData data;
|
||||||
gpointer userdata;
|
gpointer userdata;
|
||||||
GtkMenuPositionFunc posfunc;
|
GtkMenuPositionFunc posfunc;
|
||||||
if ( x == -1 && y == -1 )
|
if ( x == -1 && y == -1 )
|
||||||
@@ -5719,8 +5736,9 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos = ClientToScreen(wxPoint(x, y));
|
data.pos = ClientToScreen(wxPoint(x, y));
|
||||||
userdata = &pos;
|
data.menu = menu;
|
||||||
|
userdata = &data;
|
||||||
posfunc = wxPopupMenuPositionCallback;
|
posfunc = wxPopupMenuPositionCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user