mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-21 23:19:29 +02:00
Cocoa/Cursor: fix #40515 and others, Merge branch 'cocoa/cursor'
This commit is contained in:
parent
427111b63e
commit
abdd01e9b9
@ -517,21 +517,47 @@ var
|
||||
ev : NSEvent;
|
||||
p : NSPoint;
|
||||
wfr : NSRect;
|
||||
windowNumbers : NSArray;
|
||||
windowNumber : NSNumber;
|
||||
begin
|
||||
kw := app.keyWindow;
|
||||
p := theEvent.mouseLocation;
|
||||
|
||||
if Assigned(kw) then
|
||||
begin
|
||||
wfr := kw.contentRectForFrameRect(kw.frame);
|
||||
// if mouse outside of ClientFrame of keyWindow,
|
||||
// Cursor should be forced to default.
|
||||
// see also: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40515
|
||||
if not NSPointInRect(p, wfr) then
|
||||
begin
|
||||
if Screen.Cursor=crDefault then
|
||||
CursorHelper.ForceSetDefaultCursor
|
||||
else
|
||||
CursorHelper.SetScreenCursor;
|
||||
end;
|
||||
end;
|
||||
|
||||
// mouse move was consumed by the focused window
|
||||
if Assigned(kw) and NSPointInRect( theEvent.mouseLocation, kw.frame) then
|
||||
Exit;
|
||||
if Assigned(kw) and NSPointInRect(p, kw.frame) then
|
||||
exit;
|
||||
|
||||
for w in app.windows do
|
||||
// windowNumbersWithOptions() shoulde be used here.
|
||||
// because windowNumbersWithOptions() return windowsNumber of visible windows
|
||||
// from front to back, and NSAPP.windows return all windows not ordered.
|
||||
windowNumbers := NSWindow.windowNumbersWithOptions(0);
|
||||
for windowNumber in windowNumbers do
|
||||
begin
|
||||
if w = kw then Continue;
|
||||
if not w.isVisible then Continue;
|
||||
// todo: check for enabled windows? modal windows?
|
||||
w := app.windowWithWindowNumber(windowNumber.integerValue);
|
||||
if not Assigned(w) then
|
||||
continue;
|
||||
|
||||
wfr := w.frame;
|
||||
if not NSPointInRect( theEvent.mouseLocation, wfr) then Continue;
|
||||
if not NSPointInRect( theEvent.mouseLocation, wfr) then
|
||||
continue;
|
||||
|
||||
if not w.isKindOfClass(TCocoaWindow) then
|
||||
break;
|
||||
|
||||
p := theEvent.mouseLocation;
|
||||
p.x := p.x - w.frame.origin.x;
|
||||
@ -548,6 +574,7 @@ begin
|
||||
theEvent.pressure
|
||||
);
|
||||
w.sendEvent(ev);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -2526,8 +2526,10 @@ end;
|
||||
|
||||
function TCocoaWidgetSet.SetCursor(ACursor: HCURSOR): HCURSOR;
|
||||
begin
|
||||
if ACursor = 0 then ACursor:= Screen.Cursors[crDefault];
|
||||
TCocoaCursor(ACursor).SetCursor;
|
||||
if (ACursor=0) or (ACursor=Screen.Cursors[crDefault]) then
|
||||
CursorHelper.SetCursorAtMousePos
|
||||
else
|
||||
CursorHelper.SetNewCursor( TCocoaCursor(ACursor) );
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
|
@ -1019,15 +1019,15 @@ begin
|
||||
end;
|
||||
|
||||
// return proper focused responder by kind of class of NSResponder
|
||||
function getProperFocusedResponder( const aResponder : NSResponder ): NSResponder;
|
||||
function getProperFocusedResponder( const win : NSWindow; const aResponder : NSResponder ): NSResponder;
|
||||
begin
|
||||
if aResponder<>nil then
|
||||
Result := aResponder
|
||||
else
|
||||
Result:= NSApp.keyWindow;
|
||||
Result:= win;
|
||||
|
||||
if Result.isKindOfClass(NSWindow) then
|
||||
Result:= TCocoaWindowContent(NSWindow(Result).contentView).documentView;
|
||||
if Result.isKindOfClass(TCocoaWindow) then
|
||||
Result:= TCocoaWindowContent(TCocoaWindow(Result).contentView).documentView;
|
||||
end;
|
||||
|
||||
// return responder callback by kind of class of NSResponder
|
||||
@ -1080,7 +1080,7 @@ begin
|
||||
inc( makeFirstResponderCount );
|
||||
try
|
||||
lastResponder := self.firstResponder;
|
||||
newResponder := getProperFocusedResponder( aResponder );
|
||||
newResponder := getProperFocusedResponder( self, aResponder );
|
||||
if lastResponder = newResponder then exit;
|
||||
|
||||
// do toggle Focused Control
|
||||
|
@ -24,11 +24,12 @@ type
|
||||
_lastCursor: NSCursor;
|
||||
public
|
||||
procedure SetNewCursor( newCursor:TCocoaCursor );
|
||||
procedure ForceSetDefaultCursor;
|
||||
procedure SetCursorOnActive;
|
||||
procedure SetScreenCursor;
|
||||
procedure SetScreenCursorWhenNotDefault;
|
||||
public
|
||||
class procedure SetCursorOnActive;
|
||||
class procedure SetCursorAtMousePos;
|
||||
class procedure SetScreenCursor;
|
||||
class procedure SetScreenCursorWhenNotDefault;
|
||||
end;
|
||||
|
||||
{ TLCLCommonCallback }
|
||||
@ -380,9 +381,18 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCursorHelper.SetCursorOnActive;
|
||||
procedure TCursorHelper.ForceSetDefaultCursor;
|
||||
var
|
||||
newCursor: TCocoaCursor;
|
||||
begin
|
||||
CursorHelper._lastCursor:= nil;
|
||||
newCursor:= TCocoaCursor(Screen.Cursors[crDefault]);
|
||||
newCursor.SetCursor;
|
||||
_lastCursor:= newCursor.Cursor;
|
||||
end;
|
||||
|
||||
procedure TCursorHelper.SetCursorOnActive;
|
||||
begin
|
||||
_lastCursor:= NSCursor.arrowCursor;
|
||||
if Screen.Cursor<>crDefault then
|
||||
SetScreenCursor
|
||||
else
|
||||
@ -411,15 +421,16 @@ begin
|
||||
rect.origin, 0, 0,
|
||||
window.windowNumber, nil, 0, 0, 0);
|
||||
|
||||
window.lclGetCallback.MouseMove(event);
|
||||
NSApp.postEvent_atStart(event, true);
|
||||
end;
|
||||
|
||||
class procedure TCursorHelper.SetScreenCursor;
|
||||
procedure TCursorHelper.SetScreenCursor;
|
||||
begin
|
||||
_lastCursor:= nil;
|
||||
TCocoaCursor(Screen.Cursors[Screen.Cursor]).SetCursor;
|
||||
end;
|
||||
|
||||
class procedure TCursorHelper.SetScreenCursorWhenNotDefault;
|
||||
procedure TCursorHelper.SetScreenCursorWhenNotDefault;
|
||||
begin
|
||||
if Screen.Cursor<>crDefault then
|
||||
SetScreenCursor;
|
||||
@ -1887,6 +1898,7 @@ class procedure TCocoaWSWinControl.SetCursor(const AWinControl: TWinControl;
|
||||
const ACursor: HCursor);
|
||||
var
|
||||
control: TControl;
|
||||
topParent: TControl;
|
||||
begin
|
||||
//debugln('SetCursor '+AWinControl.name+' '+dbgs(ACursor));
|
||||
|
||||
@ -1894,6 +1906,19 @@ begin
|
||||
if Screen.Cursor<>crDefault
|
||||
then exit;
|
||||
|
||||
// control cursor only should be set when mouse in the keyWindow.
|
||||
// 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
|
||||
begin
|
||||
if NSView(TCustomForm(topParent).handle).window <> NSApp.keyWindow then
|
||||
exit;
|
||||
end;
|
||||
|
||||
// control cursor only need be set when mouse in AWinControl.
|
||||
// suppose there is a Button, which is to set a Cursor of a ListBox.
|
||||
// without the code here, it will be set to the Cursor of the ListBox
|
||||
|
@ -793,6 +793,8 @@ begin
|
||||
// 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
|
||||
begin
|
||||
|
Loading…
Reference in New Issue
Block a user