Cocoa: Multi Displays fully supported, Merge branch 'cocoa/MultiDisplay'

This commit is contained in:
rich2014 2023-10-18 00:09:19 +08:00
parent 13c1f3497b
commit d93c85c98d
4 changed files with 36 additions and 37 deletions

View File

@ -1,7 +1,7 @@
unit CocoaUtils;
{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$modeswitch objectivec2}
interface
@ -42,7 +42,8 @@ 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 NSScreenZeroHeight: CGFloat;
function NSPrimaryScreenHeight: CGFloat;
function NSGlobalScreenHeight: CGFloat;
function CreateParamsToNSRect(const params: TCreateParams): NSRect;
@ -751,11 +752,25 @@ begin
ns.size.height:=lcl.Bottom-lcl.Top;
end;
function NSScreenZeroHeight: CGFloat;
// the height of primary display
function NSPrimaryScreenHeight: CGFloat;
begin
Result := NSScreen(NSScreen.screens.objectAtIndex(0)).frame.size.height;
end;
// the height of global full virtual display
function NSGlobalScreenHeight: CGFloat;
var
globalFrame: NSRect;
screen: NSScreen;
begin
globalFrame:= NSZeroRect;
for screen in NSScreen.screens do begin
globalFrame:= NSUnionRect( globalFrame, screen.frame );
end;
Result:= globalFrame.size.height;
end;
function CreateParamsToNSRect(const params: TCreateParams): NSRect;
begin
with params do Result:=GetNSRect(X,Y,Width,Height);

View File

@ -1066,7 +1066,7 @@ begin
SPI_GETWORKAREA:
begin
NSToLCLRect(NSScreen(NSScreen.screens.objectAtIndex(0)).visibleFrame
, NSScreenZeroHeight
, NSPrimaryScreenHeight
, TRect(pvParam^));
end;
else
@ -1164,7 +1164,7 @@ begin
begin
lpPoint.x := Round(x);
// cocoa returns cursor with inverted y coordinate
lpPoint.y := Round(NSScreenZeroHeight-y);
lpPoint.y := Round(NSGlobalScreenHeight-y);
end;
//debugln('GetCursorPos='+DbgS(lpPoint));
Result := True;
@ -1172,7 +1172,7 @@ end;
function TCocoaWidgetSet.GetMonitorInfo(hMonitor: HMONITOR; lpmi: PMonitorInfo): Boolean;
var
Scr0Height: CGFloat;
globalScreenHeight: CGFloat;
ScreenID: NSScreen;
idx : NSUInteger;
begin
@ -1182,10 +1182,10 @@ begin
Result := (idx < NSScreen.screens.count);
if not Result then Exit;
Scr0Height := NSScreenZeroHeight;
globalScreenHeight := NSGlobalScreenHeight;
ScreenID := NSScreen(NSScreen.screens.objectAtIndex(idx));
NSToLCLRect(ScreenID.frame, Scr0Height, lpmi^.rcMonitor);
NSToLCLRect(ScreenID.visibleFrame, Scr0Height, lpmi^.rcWork);
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
@ -1495,7 +1495,7 @@ begin
Exit;
p.x:=Point.X;
p.y:=NSScreenZeroHeight-Point.Y;
p.y:=NSGlobalScreenHeight-Point.Y;
window := GetCocoaWindowAtPos(p);
if Assigned(window) then
Result:= HWND(window.contentView);

View File

@ -480,7 +480,7 @@ begin
begin
//Window bounds should return "client rect" in screen coordinates
if Assigned(window.screen) then
NSToLCLRect(window.frame, NSScreenZeroHeight, wfrm)
NSToLCLRect(window.frame, NSGlobalScreenHeight, wfrm)
else
wfrm := NSRectToRect(frame);
Types.OffsetRect(Result, -Result.Left+wfrm.Left, -Result.Top+wfrm.Top);
@ -1278,7 +1278,7 @@ begin
begin
f:=frame;
Left := Round(f.origin.x);
Top := Round(NSScreenZeroHeight - f.size.height - f.origin.y);
Top := Round(NSGlobalScreenHeight - f.size.height - f.origin.y);
//debugln('Top:'+dbgs(Top));
end;
end;
@ -1291,7 +1291,7 @@ begin
begin
f := frame;
inc(X, Round(f.origin.x));
inc(Y, Round(NSScreenZeroHeight - f.size.height - f.origin.y));
inc(Y, Round(NSGlobalScreenHeight - f.size.height - f.origin.y));
end;
end;
@ -1303,7 +1303,7 @@ begin
begin
f := frame;
dec(X, Round(f.origin.x));
dec(Y, Round(screen.frame.size.height - f.size.height - f.origin.y));
dec(Y, Round(NSGlobalScreenHeight - f.size.height - f.origin.y));
end;
end;
@ -1314,7 +1314,7 @@ begin
else
begin
if Assigned(screen) then
NSToLCLRect(frame, NSScreenZeroHeight, Result)
NSToLCLRect(frame, NSGlobalScreenHeight, Result)
else
Result := NSRectToRect(frame);
end;
@ -1333,29 +1333,12 @@ begin
Point.y := contentView.bounds.size.height - Point.y;
end;
procedure NSScreenGetRect(sc: NSScreen; mainScreenHeight: double; out r: TRect);
var
fr : NSRect;
begin
fr := sc.frame;
r := Bounds(
Round(fr.origin.x),
Round(fr.origin.y - fr.size.height + mainScreenHeight),
Round(fr.size.width), Round(fr.size.height)
);
end;
procedure NSScreenGetRect(sc: NSScreen; out r: TRect);
begin
NSScreenGetRect(sc, NSScreen.mainScreen.frame.size.height, r);
end;
procedure LCLWindowExtension.lclSetFrame(const r: TRect);
var
ns : NSRect;
h : integer;
begin
LCLToNSRect(r, NSScreenZeroHeight, ns);
LCLToNSRect(r, NSGlobalScreenHeight, ns);
// add topbar height
h:=lclGetTopBarHeight;

View File

@ -963,24 +963,25 @@ begin
// 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, py) );
w := GetCocoaWindowAtPos( NSMakePoint(px, Round(NSGlobalScreenHeight) - py) );
if Assigned(w) then
begin
view := w.contentView;
if Assigned(view) then
begin
menuY := round(w.screen.frame.size.height - w.screen.visibleFrame.origin.y - menu.size.height) - 1;
// 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);
py := Round(view.frame.size.height) - py;
end;
end
else
py := Round(NSScreenZeroHeight - py);
py := Round(NSGlobalScreenHeight) - py;
menu.popUpMenuPositioningItem_atLocation_inView(nil, NSMakePoint(px, py), view);
APopupMenu.Close; // notify LCL popup menu