mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-19 04:39:13 +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;
|
ev : NSEvent;
|
||||||
p : NSPoint;
|
p : NSPoint;
|
||||||
wfr : NSRect;
|
wfr : NSRect;
|
||||||
|
windowNumbers : NSArray;
|
||||||
|
windowNumber : NSNumber;
|
||||||
begin
|
begin
|
||||||
kw := app.keyWindow;
|
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
|
// mouse move was consumed by the focused window
|
||||||
if Assigned(kw) and NSPointInRect( theEvent.mouseLocation, kw.frame) then
|
if Assigned(kw) and NSPointInRect(p, kw.frame) then
|
||||||
Exit;
|
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
|
begin
|
||||||
if w = kw then Continue;
|
w := app.windowWithWindowNumber(windowNumber.integerValue);
|
||||||
if not w.isVisible then Continue;
|
if not Assigned(w) then
|
||||||
// todo: check for enabled windows? modal windows?
|
continue;
|
||||||
|
|
||||||
wfr := w.frame;
|
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 := theEvent.mouseLocation;
|
||||||
p.x := p.x - w.frame.origin.x;
|
p.x := p.x - w.frame.origin.x;
|
||||||
@ -548,6 +574,7 @@ begin
|
|||||||
theEvent.pressure
|
theEvent.pressure
|
||||||
);
|
);
|
||||||
w.sendEvent(ev);
|
w.sendEvent(ev);
|
||||||
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -2526,8 +2526,10 @@ end;
|
|||||||
|
|
||||||
function TCocoaWidgetSet.SetCursor(ACursor: HCURSOR): HCURSOR;
|
function TCocoaWidgetSet.SetCursor(ACursor: HCURSOR): HCURSOR;
|
||||||
begin
|
begin
|
||||||
if ACursor = 0 then ACursor:= Screen.Cursors[crDefault];
|
if (ACursor=0) or (ACursor=Screen.Cursors[crDefault]) then
|
||||||
TCocoaCursor(ACursor).SetCursor;
|
CursorHelper.SetCursorAtMousePos
|
||||||
|
else
|
||||||
|
CursorHelper.SetNewCursor( TCocoaCursor(ACursor) );
|
||||||
Result := 0;
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1019,15 +1019,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// return proper focused responder by kind of class of NSResponder
|
// 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
|
begin
|
||||||
if aResponder<>nil then
|
if aResponder<>nil then
|
||||||
Result := aResponder
|
Result := aResponder
|
||||||
else
|
else
|
||||||
Result:= NSApp.keyWindow;
|
Result:= win;
|
||||||
|
|
||||||
if Result.isKindOfClass(NSWindow) then
|
if Result.isKindOfClass(TCocoaWindow) then
|
||||||
Result:= TCocoaWindowContent(NSWindow(Result).contentView).documentView;
|
Result:= TCocoaWindowContent(TCocoaWindow(Result).contentView).documentView;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// return responder callback by kind of class of NSResponder
|
// return responder callback by kind of class of NSResponder
|
||||||
@ -1080,7 +1080,7 @@ begin
|
|||||||
inc( makeFirstResponderCount );
|
inc( makeFirstResponderCount );
|
||||||
try
|
try
|
||||||
lastResponder := self.firstResponder;
|
lastResponder := self.firstResponder;
|
||||||
newResponder := getProperFocusedResponder( aResponder );
|
newResponder := getProperFocusedResponder( self, aResponder );
|
||||||
if lastResponder = newResponder then exit;
|
if lastResponder = newResponder then exit;
|
||||||
|
|
||||||
// do toggle Focused Control
|
// do toggle Focused Control
|
||||||
|
@ -24,11 +24,12 @@ type
|
|||||||
_lastCursor: NSCursor;
|
_lastCursor: NSCursor;
|
||||||
public
|
public
|
||||||
procedure SetNewCursor( newCursor:TCocoaCursor );
|
procedure SetNewCursor( newCursor:TCocoaCursor );
|
||||||
|
procedure ForceSetDefaultCursor;
|
||||||
|
procedure SetCursorOnActive;
|
||||||
|
procedure SetScreenCursor;
|
||||||
|
procedure SetScreenCursorWhenNotDefault;
|
||||||
public
|
public
|
||||||
class procedure SetCursorOnActive;
|
|
||||||
class procedure SetCursorAtMousePos;
|
class procedure SetCursorAtMousePos;
|
||||||
class procedure SetScreenCursor;
|
|
||||||
class procedure SetScreenCursorWhenNotDefault;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLCLCommonCallback }
|
{ TLCLCommonCallback }
|
||||||
@ -380,9 +381,18 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TCursorHelper.SetCursorOnActive;
|
procedure TCursorHelper.ForceSetDefaultCursor;
|
||||||
|
var
|
||||||
|
newCursor: TCocoaCursor;
|
||||||
begin
|
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
|
if Screen.Cursor<>crDefault then
|
||||||
SetScreenCursor
|
SetScreenCursor
|
||||||
else
|
else
|
||||||
@ -411,15 +421,16 @@ begin
|
|||||||
rect.origin, 0, 0,
|
rect.origin, 0, 0,
|
||||||
window.windowNumber, nil, 0, 0, 0);
|
window.windowNumber, nil, 0, 0, 0);
|
||||||
|
|
||||||
window.lclGetCallback.MouseMove(event);
|
NSApp.postEvent_atStart(event, true);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TCursorHelper.SetScreenCursor;
|
procedure TCursorHelper.SetScreenCursor;
|
||||||
begin
|
begin
|
||||||
|
_lastCursor:= nil;
|
||||||
TCocoaCursor(Screen.Cursors[Screen.Cursor]).SetCursor;
|
TCocoaCursor(Screen.Cursors[Screen.Cursor]).SetCursor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TCursorHelper.SetScreenCursorWhenNotDefault;
|
procedure TCursorHelper.SetScreenCursorWhenNotDefault;
|
||||||
begin
|
begin
|
||||||
if Screen.Cursor<>crDefault then
|
if Screen.Cursor<>crDefault then
|
||||||
SetScreenCursor;
|
SetScreenCursor;
|
||||||
@ -1887,6 +1898,7 @@ class procedure TCocoaWSWinControl.SetCursor(const AWinControl: TWinControl;
|
|||||||
const ACursor: HCursor);
|
const ACursor: HCursor);
|
||||||
var
|
var
|
||||||
control: TControl;
|
control: TControl;
|
||||||
|
topParent: TControl;
|
||||||
begin
|
begin
|
||||||
//debugln('SetCursor '+AWinControl.name+' '+dbgs(ACursor));
|
//debugln('SetCursor '+AWinControl.name+' '+dbgs(ACursor));
|
||||||
|
|
||||||
@ -1894,6 +1906,19 @@ begin
|
|||||||
if Screen.Cursor<>crDefault
|
if Screen.Cursor<>crDefault
|
||||||
then exit;
|
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.
|
// control cursor only need be set when mouse in AWinControl.
|
||||||
// suppose there is a Button, which is to set a Cursor of a ListBox.
|
// 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
|
// 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
|
// events to arrive for this window, creating a second call to TCocoaWSCustomForm.CreateHandle
|
||||||
// while the first didn't finish yet, instead delay the call
|
// while the first didn't finish yet, instead delay the call
|
||||||
cnt.popup_parent := AParams.WndParent;
|
cnt.popup_parent := AParams.WndParent;
|
||||||
|
|
||||||
|
win.makeFirstResponder(doc);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user