Cocoa: show full popup menu by calculating the most appropriate popup position

This commit is contained in:
rich2014 2023-09-30 15:32:18 +08:00
parent aff96ceae0
commit 664c88804c

View File

@ -28,6 +28,7 @@ uses
MacOSAll, MacOSAll,
// RTL // RTL
sysutils, sysutils,
math,
// LCL // LCL
Controls, Forms, Menus, Graphics, LCLType, LMessages, LCLProc, Classes, Controls, Forms, Menus, Graphics, LCLType, LMessages, LCLProc, Classes,
LCLMessageGlue, LCLStrConsts, LCLMessageGlue, LCLStrConsts,
@ -945,28 +946,23 @@ end;
class procedure TCocoaWSPopupMenu.Popup(const APopupMenu: TPopupMenu; const X, class procedure TCocoaWSPopupMenu.Popup(const APopupMenu: TPopupMenu; const X,
Y: Integer); Y: Integer);
var var
menu : TCocoaMenu;
view : NSView; view : NSView;
w : NSWindow; w : NSWindow;
px, py: Integer; px, py: Integer;
menuY: Integer;
begin begin
if Assigned(APopupMenu) and (APopupMenu.Handle<>0) then if (not Assigned(APopupMenu)) or (APopupMenu.Handle=0) then
begin exit;
// old method which doesn't consider position but supports 10.0+ (useless since we target 10.6+)
{w:=NSApp.keyWindow;
if Assigned(w) then
begin
NSMenu.popUpContextMenu_withEvent_forView( TCocoaMenu(APopupMenu.Handle),
NSApp.currentEvent, NSView(w.contentView));
end;}
// New method for 10.6+
px := x; px := x;
py := y; py := y;
menu := TCocoaMenu(APopupMenu.Handle);
view := nil; view := nil;
w :=NSApp.keyWindow; w :=NSApp.keyWindow;
if not Assigned(w) then
// in macOS it's possible to "rightclick" without focusing a window // in macOS it's possible to "rightclick" without focusing a window
// so let's try to find the window // so let's try to find the window
if not Assigned(w) then
w := GetCocoaWindowAtPos( NSMakePoint(px, py) ); w := GetCocoaWindowAtPos( NSMakePoint(px, py) );
if Assigned(w) then if Assigned(w) then
@ -974,6 +970,8 @@ begin
view := w.contentView; view := w.contentView;
if Assigned(view) then if Assigned(view) then
begin begin
menuY := round(w.screen.frame.size.height - w.screen.visibleFrame.origin.y - menu.size.height) - 1;
py := min(py, menuY);
view.lclScreenToLocal(px, py); view.lclScreenToLocal(px, py);
// have to flip again, because popUpMenuPositioningItem expects point // have to flip again, because popUpMenuPositioningItem expects point
// to be in View coordinates and it does respect Flipped flag // to be in View coordinates and it does respect Flipped flag
@ -983,10 +981,9 @@ begin
end end
else else
py := Round(NSScreenZeroHeight - py); py := Round(NSScreenZeroHeight - py);
TCocoaMenu(APopupMenu.Handle).popUpMenuPositioningItem_atLocation_inView(
nil, NSMakePoint(px, py), view); menu.popUpMenuPositioningItem_atLocation_inView(nil, NSMakePoint(px, py), view);
APopupMenu.Close; // notify LCL popup menu APopupMenu.Close; // notify LCL popup menu
end;
end; end;
procedure ShortcutToKeyEquivalent(const AShortCut: TShortcut; out Key: NSString; out shiftKeyMask: NSUInteger); procedure ShortcutToKeyEquivalent(const AShortCut: TShortcut; out Key: NSString; out shiftKeyMask: NSUInteger);