mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-17 04:29:25 +02:00
Cocoa/Display: Merge branch 'cocoa/display', fix and improve Display related
This commit is contained in:
parent
eb2b425869
commit
1d09fd6361
@ -1144,11 +1144,7 @@ begin
|
||||
params.isFirstCall:= not hasMarkedText();
|
||||
|
||||
rect:= imeHandler.IMEGetTextBound( params );
|
||||
|
||||
if isFlipped then
|
||||
Result:= RectToNSRect( rect )
|
||||
else
|
||||
LCLToNSRect( rect, NSScreen.mainScreen.frame.size.height, Result );
|
||||
LCLToNSRect( rect, NSGlobalScreenHeight, Result );
|
||||
end;
|
||||
|
||||
procedure TCocoaFullControlEdit.unmarkText;
|
||||
|
@ -42,7 +42,14 @@ function NSRectToRect(const NS: NSRect): TRect;
|
||||
procedure NSToLCLRect(const ns: NSRect; ParentHeight: Single; out lcl: TRect);
|
||||
procedure LCLToNSRect(const lcl: TRect; ParentHeight: Single; out ns: NSRect);
|
||||
|
||||
function NSPrimaryScreenHeight: CGFloat;
|
||||
function IndexToHMonitor(i: NSUInteger): HMonitor;
|
||||
function HMonitorToIndex(h: HMonitor): NSUInteger;
|
||||
function getScreenFromHMonitor(h: HMonitor): NSScreen;
|
||||
|
||||
function NSPrimaryScreen: NSScreen;
|
||||
function NSPrimaryScreenFrame: NSRect;
|
||||
function NSGlobalScreenFrame: NSRect;
|
||||
function NSGlobalScreenLCLFrame: NSRect;
|
||||
function NSGlobalScreenHeight: CGFloat;
|
||||
|
||||
function CreateParamsToNSRect(const params: TCreateParams): NSRect;
|
||||
@ -752,14 +759,50 @@ begin
|
||||
ns.size.height:=lcl.Bottom-lcl.Top;
|
||||
end;
|
||||
|
||||
// the height of primary display
|
||||
function NSPrimaryScreenHeight: CGFloat;
|
||||
// According to the documentation of NSScreen.screen It's recommended
|
||||
// not to cache NSScreen objects stored in the array. As those might change.
|
||||
// However, according to the same documentation, the objects can change
|
||||
// only with a notificatio sent out. BUT while using a macincloud (remote desktop)
|
||||
// services, it was identified that NSScreen object CAN change without any notification.
|
||||
// So, instead of passing NSScreen as HMonitor, only INDEX+1 in NSScreen.screen
|
||||
// is used.
|
||||
function IndexToHMonitor(i: NSUInteger): HMonitor;
|
||||
begin
|
||||
Result := NSScreen(NSScreen.screens.objectAtIndex(0)).frame.size.height;
|
||||
if i = NSIntegerMax then Result := 0
|
||||
else Result := i + 1;
|
||||
end;
|
||||
|
||||
// the height of global full virtual display
|
||||
function NSGlobalScreenHeight: CGFloat;
|
||||
function HMonitorToIndex(h: HMonitor): NSUInteger;
|
||||
begin
|
||||
if h = 0 then Result := NSIntegerMax
|
||||
else Result := NSUInteger(h)-1;
|
||||
end;
|
||||
|
||||
function getScreenFromHMonitor(h: HMonitor): NSScreen;
|
||||
var
|
||||
index: NSUInteger;
|
||||
begin
|
||||
Result:= nil;
|
||||
index:= HMonitorToIndex( h );
|
||||
if index>=NSScreen.screens.count then
|
||||
Exit;
|
||||
Result:= NSScreen( NSScreen.screens.objectAtIndex(index) );
|
||||
end;
|
||||
|
||||
// primary display
|
||||
function NSPrimaryScreen: NSScreen;
|
||||
begin
|
||||
Result := NSScreen(NSScreen.screens.objectAtIndex(0));
|
||||
end;
|
||||
|
||||
// the frame of primary display
|
||||
function NSPrimaryScreenFrame: NSRect;
|
||||
begin
|
||||
Result := NSPrimaryScreen.frame;
|
||||
end;
|
||||
|
||||
// the frame of global full virtual display, in LCL coordinate (left,bottom)
|
||||
function NSGlobalScreenFrame: NSRect;
|
||||
var
|
||||
globalFrame: NSRect;
|
||||
screen: NSScreen;
|
||||
@ -768,7 +811,20 @@ begin
|
||||
for screen in NSScreen.screens do begin
|
||||
globalFrame:= NSUnionRect( globalFrame, screen.frame );
|
||||
end;
|
||||
Result:= globalFrame.size.height;
|
||||
Result:= globalFrame;
|
||||
end;
|
||||
|
||||
// the frame of global full virtual display, in LCL coordinate (left,top)
|
||||
function NSGlobalScreenLCLFrame: NSRect;
|
||||
begin
|
||||
Result:= NSGlobalScreenFrame;
|
||||
Result.origin.y:= NSPrimaryScreenFrame.size.height - NSMaxY(Result);
|
||||
end;
|
||||
|
||||
// the height of global full virtual display
|
||||
function NSGlobalScreenHeight: CGFloat;
|
||||
begin
|
||||
Result:= NSGlobalScreenFrame.size.height;
|
||||
end;
|
||||
|
||||
function CreateParamsToNSRect(const params: TCreateParams): NSRect;
|
||||
|
@ -740,25 +740,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// According to the documentation of NSScreen.screen It's recommended
|
||||
// not to cache NSScreen objects stored in the array. As those might change.
|
||||
// However, according to the same documentation, the objects can change
|
||||
// only with a notificatio sent out. BUT while using a macincloud (remote desktop)
|
||||
// services, it was identified that NSScreen object CAN change without any notification.
|
||||
// So, instead of passing NSScreen as HMonitor, only INDEX+1 in NSScreen.screen
|
||||
// is used.
|
||||
function IndexToHMonitor(i: NSUInteger): HMonitor;
|
||||
begin
|
||||
if i = NSIntegerMax then Result := 0
|
||||
else Result := i + 1;
|
||||
end;
|
||||
|
||||
function HMonitorToIndex(h: HMonitor): NSUInteger;
|
||||
begin
|
||||
if h = 0 then Result := NSIntegerMax
|
||||
else Result := NSUInteger(h)-1;
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.EnumDisplayMonitors(hdc: HDC; lprcClip: PRect;
|
||||
lpfnEnum: MonitorEnumProc; dwData: LPARAM): LongBool;
|
||||
var
|
||||
@ -973,9 +954,6 @@ var
|
||||
lCocoaWin: TCocoaWindow = nil;
|
||||
lWinContent: TCocoaWindowContent = nil;
|
||||
disableFS : Boolean;
|
||||
const
|
||||
NSFullScreenWindowMask = 1 shl 14;
|
||||
|
||||
begin
|
||||
Result:=true;
|
||||
{$ifdef VerboseCocoaWinAPI}
|
||||
@ -1065,9 +1043,9 @@ begin
|
||||
SPI_GETWHEELSCROLLLINES: PDword(pvPAram)^ := 1;
|
||||
SPI_GETWORKAREA:
|
||||
begin
|
||||
NSToLCLRect(NSScreen(NSScreen.screens.objectAtIndex(0)).visibleFrame
|
||||
, NSPrimaryScreenHeight
|
||||
, TRect(pvParam^));
|
||||
NSToLCLRect( NSPrimaryScreen.visibleFrame,
|
||||
NSPrimaryScreenFrame.size.height,
|
||||
TRect(pvParam^) );
|
||||
end;
|
||||
else
|
||||
Result := False;
|
||||
@ -1085,21 +1063,21 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
function TCocoaWidgetSet.GetWindowRect(Handle: hwnd; var ARect: TRect): Integer;
|
||||
var
|
||||
dx, dy: Integer;
|
||||
contentView: TCocoaWindowContent;
|
||||
begin
|
||||
if Handle <> 0 then
|
||||
begin
|
||||
ARect := NSObject(Handle).lclFrame;
|
||||
if not NSObject(Handle).isKindOfClass_(NSWindow) then
|
||||
begin
|
||||
dx := 0;
|
||||
dy := 0;
|
||||
NSObject(Handle).lclLocalToScreen(dx, dy);
|
||||
MoveRect(ARect, dx, dy);
|
||||
end;
|
||||
Result := 1;
|
||||
end else
|
||||
Result := 0;
|
||||
Result := 0;
|
||||
if Handle=0 then
|
||||
exit;
|
||||
|
||||
if not NSObject(Handle).isKindOfClass(TCocoaWindowContent) then
|
||||
exit;
|
||||
|
||||
contentView := TCocoaWindowContent(Handle);
|
||||
if (not contentView.isembedded) and Assigned(contentView.window) then
|
||||
NSToLCLRect(contentView.window.frame, NSGlobalScreenHeight, ARect)
|
||||
else
|
||||
ARect := contentView.lclFrame;
|
||||
Result := 1;
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.IsWindowEnabled(Handle: HWND): boolean;
|
||||
@ -1174,21 +1152,19 @@ function TCocoaWidgetSet.GetMonitorInfo(hMonitor: HMONITOR; lpmi: PMonitorInfo):
|
||||
var
|
||||
globalScreenHeight: CGFloat;
|
||||
ScreenID: NSScreen;
|
||||
idx : NSUInteger;
|
||||
begin
|
||||
Result := (lpmi <> nil) and (lpmi^.cbSize >= SizeOf(TMonitorInfo));
|
||||
if not Result then Exit;
|
||||
idx := HMonitorToIndex(hMonitor);
|
||||
Result := (idx < NSScreen.screens.count);
|
||||
ScreenID := getScreenFromHMonitor( hMonitor );
|
||||
Result := Assigned(ScreenID);
|
||||
if not Result then Exit;
|
||||
|
||||
globalScreenHeight := NSGlobalScreenHeight;
|
||||
ScreenID := NSScreen(NSScreen.screens.objectAtIndex(idx));
|
||||
NSToLCLRect(ScreenID.frame, globalScreenHeight, lpmi^.rcMonitor);
|
||||
NSToLCLRect(ScreenID.visibleFrame, globalScreenHeight, lpmi^.rcWork);
|
||||
// according to the documentation the primary (0,0 coord screen)
|
||||
// is always and index 0
|
||||
if idx = 0 then
|
||||
if HMonitorToIndex(hMonitor) = 0 then
|
||||
lpmi^.dwFlags := MONITORINFOF_PRIMARY
|
||||
else
|
||||
lpmi^.dwFlags := 0;
|
||||
@ -1364,6 +1340,12 @@ begin
|
||||
NSObject(handle).lclRelativePos(Left, Top);
|
||||
end;
|
||||
|
||||
// 1. not only for Window, but also for other controls
|
||||
// 2. for a Window, according to this function specification, Width and Height
|
||||
// should be returned. but ClientWidth and ClientHeight were returned
|
||||
// actually before.
|
||||
// 3. after the LCL FORM specification determined, corresponding modifications
|
||||
// need to be made.
|
||||
function TCocoaWidgetSet.GetWindowSize(Handle: hwnd; var Width, Height: Integer): boolean;
|
||||
var
|
||||
r: TRect;
|
||||
@ -1887,6 +1869,29 @@ begin
|
||||
Result := CocoaRegionTypeToWin32Map[TCocoaRegion(RGN).GetType];
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.MonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWord): HMONITOR;
|
||||
var
|
||||
point: NSPoint;
|
||||
screen: NSScreen;
|
||||
i: Integer;
|
||||
begin
|
||||
Result:= 0;
|
||||
point:= LCLToNSPoint( ptScreenCoords, NSGlobalScreenHeight );
|
||||
if point.y>=1 then // NSPointInRect is (upper,left) inside
|
||||
point.y:= point.y-1; // (lower,right) outside
|
||||
|
||||
for i := 0 to NSScreen.screens.count - 1 do begin
|
||||
screen:= NSScreen( NSScreen.screens.objectAtIndex(i) );
|
||||
if NSPointInRect(point, screen.frame) then begin
|
||||
Result:= IndexToHMonitor( i );
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if dwFlags<>MONITOR_DEFAULTTONULL then
|
||||
Result:= IndexToHMonitor( 0 );
|
||||
end;
|
||||
|
||||
function TCocoaWidgetSet.MoveToEx(DC: HDC; X, Y: Integer; OldPoint: PPoint): Boolean;
|
||||
var
|
||||
ctx: TCocoaContext;
|
||||
@ -2614,13 +2619,19 @@ begin
|
||||
SM_CYVSCROLL:
|
||||
Result := Round(NSScroller.scrollerWidthForControlSize(NSRegularControlSize));
|
||||
SM_CXSCREEN,
|
||||
SM_CXVIRTUALSCREEN,
|
||||
SM_CXFULLSCREEN: Result := Round(NSScreen.mainScreen.frame.size.width);
|
||||
SM_CXFULLSCREEN:
|
||||
Result := Round(NSPrimaryScreenFrame.size.width);
|
||||
SM_CYSCREEN,
|
||||
SM_CYVIRTUALSCREEN,
|
||||
SM_CYFULLSCREEN: Result := Round(NSScreen.mainScreen.frame.size.height);
|
||||
SM_XVIRTUALSCREEN: Result := Round(NSScreen.mainScreen.frame.origin.x);
|
||||
SM_YVIRTUALSCREEN: Result := Round(NSScreen.mainScreen.frame.origin.y);
|
||||
SM_CYFULLSCREEN:
|
||||
Result := Round(NSPrimaryScreenFrame.size.height);
|
||||
SM_CXVIRTUALSCREEN:
|
||||
Result := Round(NSGlobalScreenLCLFrame.size.width);
|
||||
SM_CYVIRTUALSCREEN:
|
||||
Result := Round(NSGlobalScreenLCLFrame.size.height);
|
||||
SM_XVIRTUALSCREEN:
|
||||
Result := Round(NSGlobalScreenLCLFrame.origin.x);
|
||||
SM_YVIRTUALSCREEN:
|
||||
Result := Round(NSGlobalScreenLCLFrame.origin.y);
|
||||
SM_CXSMICON,
|
||||
SM_CYSMICON:
|
||||
Result := 16;
|
||||
|
@ -140,6 +140,8 @@ function LPtoDP(DC: HDC; var Points; Count: Integer): BOOL; override;
|
||||
|
||||
function OffsetRgn(RGN: HRGN; nXOffset, nYOffset: Integer): Integer; override;
|
||||
|
||||
function MonitorFromPoint(ptScreenCoords: TPoint; dwFlags: DWord): HMONITOR; override;
|
||||
|
||||
{function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: Cardinal): integer; override;}
|
||||
function MoveToEx(DC: HDC; X, Y: Integer; OldPoint: PPoint): Boolean; override;
|
||||
|
||||
|
@ -218,9 +218,7 @@ type
|
||||
preventKeyOnShow: Boolean;
|
||||
ownwin: NSWindow;
|
||||
fswin: NSWindow; // window that was used as a content prior to switching to old-school fullscreen
|
||||
popup_parent: HWND; // if not 0, indicates that we should set the popup parent
|
||||
function performKeyEquivalent(event: NSEvent): LCLObjCBoolean; override;
|
||||
procedure resolvePopupParent(); message 'resolvePopupParent';
|
||||
function lclOwnWindow: NSWindow; message 'lclOwnWindow';
|
||||
procedure lclSetFrame(const r: TRect); override;
|
||||
function lclFrame: TRect; override;
|
||||
@ -424,37 +422,6 @@ begin
|
||||
Result := inherited performKeyEquivalent(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindowContent.resolvePopupParent();
|
||||
var
|
||||
lWindow: NSWindow;
|
||||
isfront: Boolean;
|
||||
begin
|
||||
lWindow := nil;
|
||||
if (popup_parent <> 0) then
|
||||
begin
|
||||
if (NSObject(popup_parent).isKindOfClass(TCocoaWindowContent)) then
|
||||
begin
|
||||
if (not TCocoaWindowContent(popup_parent).isembedded) then
|
||||
lWindow := NSWindow(TCocoaWindowContent(popup_parent).window);
|
||||
end
|
||||
else
|
||||
begin
|
||||
lWindow := NSWindow(popup_parent);
|
||||
end;
|
||||
end;
|
||||
if lWindow <> nil then
|
||||
begin
|
||||
isfront:=NSApplication(NSApp).mainWindow=self.window;
|
||||
|
||||
lWindow.addChildWindow_ordered(Self.window, NSWindowAbove);
|
||||
|
||||
// adding a window as a child, would bring the "child" form to the bottom
|
||||
// of Zorder. need to restore the order.
|
||||
if isfront then self.window.makeKeyAndOrderFront(nil);
|
||||
end;
|
||||
popup_parent := 0;
|
||||
end;
|
||||
|
||||
function TCocoaWindowContent.lclOwnWindow: NSWindow;
|
||||
begin
|
||||
if not isembedded then
|
||||
@ -479,10 +446,7 @@ begin
|
||||
if not isembedded then
|
||||
begin
|
||||
//Window bounds should return "client rect" in screen coordinates
|
||||
if Assigned(window.screen) then
|
||||
NSToLCLRect(window.frame, NSGlobalScreenHeight, wfrm)
|
||||
else
|
||||
wfrm := NSRectToRect(frame);
|
||||
NSToLCLRect(window.frame, NSGlobalScreenHeight, wfrm);
|
||||
Types.OffsetRect(Result, -Result.Left+wfrm.Left, -Result.Top+wfrm.Top);
|
||||
end;
|
||||
end;
|
||||
@ -1272,39 +1236,30 @@ end;
|
||||
|
||||
procedure LCLWindowExtension.lclRelativePos(var Left, Top: Integer);
|
||||
var
|
||||
f: NSRect;
|
||||
f: NSRect;
|
||||
begin
|
||||
if Assigned(screen) then
|
||||
begin
|
||||
f:=frame;
|
||||
Left := Round(f.origin.x);
|
||||
Top := Round(NSGlobalScreenHeight - f.size.height - f.origin.y);
|
||||
//debugln('Top:'+dbgs(Top));
|
||||
end;
|
||||
f:=frame;
|
||||
Left := Round(f.origin.x);
|
||||
Top := Round(NSGlobalScreenHeight - NSMaxY(f));
|
||||
//debugln('Top:'+dbgs(Top));
|
||||
end;
|
||||
|
||||
procedure LCLWindowExtension.lclLocalToScreen(var X, Y:Integer);
|
||||
var
|
||||
f: NSRect;
|
||||
begin
|
||||
if Assigned(screen) then
|
||||
begin
|
||||
f := frame;
|
||||
inc(X, Round(f.origin.x));
|
||||
inc(Y, Round(NSGlobalScreenHeight - f.size.height - f.origin.y));
|
||||
end;
|
||||
f := frame;
|
||||
inc(X, Round(f.origin.x));
|
||||
inc(Y, Round(NSGlobalScreenHeight - NSMaxY(f)));
|
||||
end;
|
||||
|
||||
procedure LCLWindowExtension.lclScreenToLocal(var X, Y: Integer);
|
||||
var
|
||||
f: NSRect;
|
||||
begin
|
||||
if Assigned(screen) then
|
||||
begin
|
||||
f := frame;
|
||||
dec(X, Round(f.origin.x));
|
||||
dec(Y, Round(NSGlobalScreenHeight - f.size.height - f.origin.y));
|
||||
end;
|
||||
f := frame;
|
||||
dec(X, Round(f.origin.x));
|
||||
dec(Y, Round(NSGlobalScreenHeight - NSMaxY(f)));
|
||||
end;
|
||||
|
||||
function LCLWindowExtension.lclFrame: TRect;
|
||||
@ -1312,12 +1267,7 @@ begin
|
||||
if Assigned(contentView) then
|
||||
Result:=contentView.lclFrame
|
||||
else
|
||||
begin
|
||||
if Assigned(screen) then
|
||||
NSToLCLRect(frame, NSGlobalScreenHeight, Result)
|
||||
else
|
||||
Result := NSRectToRect(frame);
|
||||
end;
|
||||
NSToLCLRect(frame, NSGlobalScreenHeight, Result);
|
||||
end;
|
||||
|
||||
function LCLWindowExtension.lclGetTopBarHeight:integer;
|
||||
|
@ -789,11 +789,6 @@ begin
|
||||
cnt.wincallback := TCocoaWindow(win).callback;
|
||||
win.setContentView(cnt);
|
||||
|
||||
// Don't call addChildWindow_ordered here because this function can cause
|
||||
// events to arrive for this window, creating a second call to TCocoaWSCustomForm.CreateHandle
|
||||
// while the first didn't finish yet, instead delay the call
|
||||
cnt.popup_parent := AParams.WndParent;
|
||||
|
||||
win.makeFirstResponder(doc);
|
||||
end
|
||||
else
|
||||
@ -945,11 +940,6 @@ begin
|
||||
if (not fullscreen) and (lWinContent.window.isKindOfClass(TCocoaWindow)) then
|
||||
fullscreen := TCocoaWindow(lWinContent.window).lclIsFullScreen;
|
||||
|
||||
// A window opening in full screen doesn't like to be added as someones popup
|
||||
// Thus resolvePopupParent should only be used for non full-screens forms
|
||||
//if (lWinContent <> nil) and (not fullscreen) then
|
||||
//lWinContent.resolvePopupParent();
|
||||
|
||||
CocoaWidgetSet.CurModalForm := lWinContent.lclOwnWindow;
|
||||
// LCL initialization code would cause the custom form to be disabled
|
||||
// (due to the fact, ShowModal() has not been called yet, and a previous form
|
||||
|
@ -946,44 +946,28 @@ end;
|
||||
class procedure TCocoaWSPopupMenu.Popup(const APopupMenu: TPopupMenu; const X,
|
||||
Y: Integer);
|
||||
var
|
||||
menu : TCocoaMenu;
|
||||
view : NSView;
|
||||
w : NSWindow;
|
||||
px, py: Integer;
|
||||
menuY: Integer;
|
||||
menu: TCocoaMenu;
|
||||
point: TPoint;
|
||||
screen: NSScreen;
|
||||
mouseY: CGFloat;
|
||||
menuY: CGFloat;
|
||||
begin
|
||||
if (not Assigned(APopupMenu)) or (APopupMenu.Handle=0) then
|
||||
exit;
|
||||
|
||||
px := x;
|
||||
py := y;
|
||||
menu := TCocoaMenu(APopupMenu.Handle);
|
||||
view := nil;
|
||||
w :=NSApp.keyWindow;
|
||||
// in macOS it's possible to "rightclick" without focusing a window
|
||||
// so let's try to find the window
|
||||
if not Assigned(w) then
|
||||
w := GetCocoaWindowAtPos( NSMakePoint(px, Round(NSGlobalScreenHeight) - py) );
|
||||
point:= TPoint.Create( x, y );
|
||||
screen:= getScreenFromHMonitor( CocoaWidgetSet.MonitorFromPoint(point, MONITOR_DEFAULTTONULL) );
|
||||
|
||||
if Assigned(w) then
|
||||
begin
|
||||
view := w.contentView;
|
||||
if Assigned(view) then
|
||||
begin
|
||||
// LCL Screen coordinate
|
||||
menuY := Round(NSGlobalScreenHeight - w.screen.visibleFrame.origin.y - menu.size.height) - 1;
|
||||
py := min(py, menuY);
|
||||
view.lclScreenToLocal(px, py);
|
||||
// have to flip again, because popUpMenuPositioningItem expects point
|
||||
// to be in View coordinates and it does respect Flipped flag
|
||||
if not view.isFlipped then
|
||||
py := Round(view.frame.size.height) - py;
|
||||
end;
|
||||
end
|
||||
else
|
||||
py := Round(NSGlobalScreenHeight) - py;
|
||||
mouseY:= NSGlobalScreenHeight - y;
|
||||
if Assigned(screen) then begin
|
||||
menuY:= screen.visibleFrame.origin.y + menu.size.height + 1;
|
||||
menuY:= max( mouseY, MenuY );
|
||||
end else begin
|
||||
menuY:= mouseY;
|
||||
end;
|
||||
|
||||
menu.popUpMenuPositioningItem_atLocation_inView(nil, NSMakePoint(px, py), view);
|
||||
menu.popUpMenuPositioningItem_atLocation_inView(nil, NSMakePoint(x,menuY), nil);
|
||||
APopupMenu.Close; // notify LCL popup menu
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user