Cocoa: support moving the mouse to HintWindow for operation in the IDE, Merge branch 'cocoa/mousemove'

there was a bug in the IDE before. HintWindow was hidden before the mouse was moved into HintWindow.
This commit is contained in:
rich2014 2024-01-12 22:56:42 +08:00
parent aa458fc479
commit 7157791611
5 changed files with 40 additions and 43 deletions

View File

@ -405,6 +405,9 @@ function THintWindowManager.ShowHint(ScreenPos: TPoint; TheHint: string;
if NewHeight <= 0 then
NewHeight := 200;
{$IFDEF LCLCOCOA}
dec(ScreenPos.Y);
{$ENDIF}
HintRenderWindow.HintRectAdjust := Rect(0, 0, NewWidth, NewHeight);
if MouseOffset then
HintRenderWindow.OffsetHintRect(ScreenPos)

View File

@ -257,7 +257,7 @@ function CocoaPromptUser(const DialogCaption, DialogMessage: String;
EscapeResult: Longint;
sheetOfWindow: NSWindow = nil; modalSheet: Boolean = false): Longint;
function GetCocoaWindowAtPos(p: NSPoint): TCocoaWindow;
function GetCocoaWindowAtPos(p: NSPoint): NSWindow;
// The function tries to initialize the proper application class.
// The desired application class can be specified in info.plit
@ -520,7 +520,7 @@ end;
// 3. in current App
// 4. is visible window
// 5. is not the misc window like Menu Bar
function GetCocoaWindowAtPos(p: NSPoint): TCocoaWindow;
function GetCocoaWindowAtPos(p: NSPoint): NSWindow;
var
windowNumber: NSInteger;
windowNumbers: NSArray;
@ -538,14 +538,13 @@ begin
// ensure 5
window := NSApp.windowWithWindowNumber(windowNumber);
if Assigned(window) and window.isKindOfClass(TCocoaWindow) then
Result := TCocoaWindow(window);
if Assigned(window) and (window.isKindOfClass(TCocoaWindow) or window.isKindOfClass(TCocoaPanel)) then
Result := window;
end;
procedure ForwardMouseMove(app: NSApplication; theEvent: NSEvent);
var
w : NSWindow;
kw : NSWindow;
ev : NSEvent;
p : NSPoint;
wfr : NSRect;
@ -553,13 +552,13 @@ begin
if not app.isActive then
exit;
kw := app.keyWindow;
p := theEvent.mouseLocation;
w := GetCocoaWindowAtPos(p);;
if Assigned(kw) then
if Assigned(w) then
begin
wfr := kw.contentRectForFrameRect(kw.frame);
// if mouse outside of ClientFrame of keyWindow,
wfr := w.contentRectForFrameRect(w.frame);
// if mouse outside of ClientFrame of Window,
// Cursor should be forced to default.
// see also: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40515
if not NSPointInRect(p, wfr) then
@ -571,9 +570,8 @@ begin
end;
end;
w := GetCocoaWindowAtPos(p);
if (not Assigned(w)) or (w=kw) then
exit;
if (not Assigned(w)) or (not Assigned(theEvent.window)) or (w=theEvent.window) then
Exit;
p.x := p.x - w.frame.origin.x;
p.y := p.y - w.frame.origin.y;

View File

@ -42,6 +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 GetScreenPointFromEvent(const event: NSEvent): NSPoint;
function ScreenPointFromLCLToNS(const lclPoint: TPoint): NSPoint;
function ScreenPointFromNSToLCL(const cocoaPoint: NSPoint): TPoint;
function ScreenRectFromLCLToNS(const lclRect: TRect): NSRect;
@ -752,6 +754,19 @@ begin
ns.size.height:=lcl.Bottom-lcl.Top;
end;
function GetScreenPointFromEvent(const event: NSEvent): NSPoint;
var
rect: NSRect;
begin
Result:= event.locationInWindow;
if not Assigned(event.window) then
Exit;
rect.origin:= Result;
rect.size:= NSZeroSize;
rect:= event.window.convertRectToScreen( rect );
Result:= rect.origin;
end;
function ScreenPointFromLCLToNS(const lclPoint: TPoint): NSPoint;
begin
Result.x:= lclPoint.x;

View File

@ -91,10 +91,7 @@ type
procedure windowDidMove(notification: NSNotification); message 'windowDidMove:';
public
callback: IWindowCallback;
function acceptsFirstResponder: LCLObjCBoolean; override;
function canBecomeKeyWindow: LCLObjCBoolean; override;
function becomeFirstResponder: LCLObjCBoolean; override;
function resignFirstResponder: LCLObjCBoolean; override;
function lclGetCallback: ICommonCallback; override;
procedure lclClearCallback; override;
// mouse
@ -579,28 +576,9 @@ begin
callback.Move;
end;
function TCocoaPanel.acceptsFirstResponder: LCLObjCBoolean;
begin
Result := True;
end;
function TCocoaPanel.canBecomeKeyWindow: LCLObjCBoolean;
begin
Result := Assigned(callback) and callback.CanActivate;
end;
function TCocoaPanel.becomeFirstResponder: LCLObjCBoolean;
begin
Result := inherited becomeFirstResponder;
// if Assigned(callback) then
// callback.BecomeFirstResponder;
end;
function TCocoaPanel.resignFirstResponder: LCLObjCBoolean;
begin
Result := inherited resignFirstResponder;
// if Assigned(callback) then
// callback.ResignFirstResponder;
Result := false;
end;
function TCocoaPanel.lclGetCallback: ICommonCallback;

View File

@ -1109,14 +1109,13 @@ var
MouseTargetLookup: Boolean;
srchPt: TPoint;
begin
Result:= true;
if not NSApp.isActive then
exit;
if Assigned(Owner) and not NSObjectIsLCLEnabled(Owner) then
begin
Result := True; // Cocoa should not handle the message.
Exit; // LCL should get the notification either.
end;
exit; // LCL should get the notification either.
// If LCL control is provided and it's in designing state.
// The default resolution: Notify LCL about event, but don't let Cocoa
@ -1144,6 +1143,9 @@ begin
end
else
begin
if Event.window<>GetCocoaWindowAtPos(GetScreenPointFromEvent(Event)) then
exit( true );
rect:=Target.BoundsRect;
OffsetRect(rect, -rect.Left, -rect.Top);
if (event.type_ = NSMouseMoved) and (not Types.PtInRect(rect, bndPt)) then
@ -1203,8 +1205,9 @@ begin
//debugln('MouseMove x='+dbgs(MousePos.X)+' y='+dbgs(MousePos.Y)+' Target='+Target.Name);
NotifyApplicationUserInput(Target, Msg.Msg);
Result := DeliverMessage(Msg) <> 0;
if BlockCocoaMouseMove then Result := true;
// LCL/LM_MOUSEMOVE always return false, so we should discard return value
DeliverMessage(Msg);
Result:= true;
// if Screen.Cursor set, LCL won't call TCocoaWSWinControl.SetCursor().
// we need to set the cursor ourselves
@ -1805,14 +1808,14 @@ begin
if Screen.Cursor<>crDefault
then exit;
// control cursor only should be set when mouse in the keyWindow.
// control cursor only should be set when mouse in the keyWindow or hintWindow.
// for the MacOS system automatic restore cursor feature(also an issue),
// it is more appropriate to set the default cursor when the mouse is out
// of the keyWindow, which has been set in TLCLCommonCallback.MouseMove().
// the keyWindow here refers to the Client Frame, excluding TitleBar.
// see also: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40515
topParent:= AWinControl.GetTopParent;
if topParent is TCustomForm then
if (topParent is TCustomForm) and not (topParent is THintWindow) then
begin
if NSView(TCustomForm(topParent).handle).window <> NSApp.keyWindow then
exit;