From 5ba8780a48ec27695bd00dfbc9304e2ecdfdbd29 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Fri, 29 Sep 2023 17:23:00 +0800 Subject: [PATCH 1/5] Cocoa: GetCocoaWindowAtPos() added ensure that gets the correct window at mouse pos 1. in Z-Order 2. on the active Space 3. in current App 4. is visible window 5. is not the misc window like Menu Bar --- lcl/interfaces/cocoa/cocoaint.pas | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 8452a74e3d..80ffc9feb1 100644 --- a/lcl/interfaces/cocoa/cocoaint.pas +++ b/lcl/interfaces/cocoa/cocoaint.pas @@ -279,6 +279,8 @@ function CocoaPromptUser(const DialogCaption, DialogMessage: String; EscapeResult: Longint; sheetOfWindow: NSWindow = nil; modalSheet: Boolean = false): Longint; +function GetCocoaWindowAtPos(p: NSPoint): TCocoaWindow; + // The function tries to initialize the proper application class. // The desired application class can be specified in info.plit // by specifying NSPrincipalClass property. @@ -510,6 +512,34 @@ begin end; {$endif} +// ensure that gets the correct window at mouse pos +// 1. in Z-Order +// 2. on the active Space +// 3. in current App +// 4. is visible window +// 5. is not the misc window like Menu Bar +function GetCocoaWindowAtPos(p: NSPoint): TCocoaWindow; +var + windowNumber: NSInteger; + windowNumbers: NSArray; + window: NSWindow; +begin + Result := nil; + + // ensure 1 + windowNumber := NSWindow.windowNumberAtPoint_belowWindowWithWindowNumber(p,0); + windowNumbers := NSWindow.windowNumbersWithOptions(0); + + // ensure 2, 3, 4 + if not windowNumbers.containsObject(NSNumber.numberWithInt(windowNumber)) then + exit; + + // ensure 5 + window := NSApp.windowWithWindowNumber(windowNumber); + if Assigned(window) and window.isKindOfClass(TCocoaWindow) then + Result := TCocoaWindow(window); +end; + procedure ForwardMouseMove(app: NSApplication; theEvent: NSEvent); var w : NSWindow; From 1f82cd542f51f354fd50e5575cb93f0b2821234e Mon Sep 17 00:00:00 2001 From: rich2014 Date: Fri, 29 Sep 2023 17:44:41 +0800 Subject: [PATCH 2/5] Cocoa: simplify ForwardMouseMove() by GetCocoaWindowAtPos() --- lcl/interfaces/cocoa/cocoaint.pas | 54 +++++++++---------------------- 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 80ffc9feb1..df4a3dc858 100644 --- a/lcl/interfaces/cocoa/cocoaint.pas +++ b/lcl/interfaces/cocoa/cocoaint.pas @@ -547,8 +547,6 @@ var ev : NSEvent; p : NSPoint; wfr : NSRect; - windowNumbers : NSArray; - windowNumber : NSNumber; begin kw := app.keyWindow; p := theEvent.mouseLocation; @@ -568,44 +566,24 @@ begin end; end; - // mouse move was consumed by the focused window - if Assigned(kw) and NSPointInRect(p, kw.frame) then + w := GetCocoaWindowAtPos(p); + if (not Assigned(w)) or (w=kw) then exit; - // 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 - w := app.windowWithWindowNumber(windowNumber.integerValue); - if not Assigned(w) then - continue; - - wfr := w.frame; - 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; - p.y := p.y - w.frame.origin.y; - ev := NSEvent.mouseEventWithType_location_modifierFlags_timestamp_windowNumber_context_eventNumber_clickCount_pressure( - theEvent.type_, - p, - theEvent.modifierFlags, - theEvent.timestamp, - w.windowNumber, - theEvent.context, - theEvent.eventNumber, - theEvent.clickCount, - theEvent.pressure - ); - w.sendEvent(ev); - break; - end; + p.x := p.x - w.frame.origin.x; + p.y := p.y - w.frame.origin.y; + ev := NSEvent.mouseEventWithType_location_modifierFlags_timestamp_windowNumber_context_eventNumber_clickCount_pressure( + theEvent.type_, + p, + theEvent.modifierFlags, + theEvent.timestamp, + w.windowNumber, + theEvent.context, + theEvent.eventNumber, + theEvent.clickCount, + theEvent.pressure + ); + w.sendEvent(ev); end; procedure TCocoaApplication.sendEvent(theEvent: NSEvent); From 48990d892ef90bf50cae331bcc2d664f85be6a0d Mon Sep 17 00:00:00 2001 From: rich2014 Date: Fri, 29 Sep 2023 17:46:57 +0800 Subject: [PATCH 3/5] Cocoa: fix TCocoaWidgetSet.WindowFromPoint() by GetCocoaWindowAtPos() --- lcl/interfaces/cocoa/cocoawinapi.inc | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoawinapi.inc b/lcl/interfaces/cocoa/cocoawinapi.inc index 09129d0730..d2474e04d1 100644 --- a/lcl/interfaces/cocoa/cocoawinapi.inc +++ b/lcl/interfaces/cocoa/cocoawinapi.inc @@ -1554,11 +1554,8 @@ end; function TCocoaWidgetSet.WindowFromPoint(Point: TPoint): HWND; var - windows: NSArray; - win: integer; - window, windowbelowpoint: NSWindow; + window:NSWindow; p:NSPoint; - winnr:NSInteger; begin Result := 0; if not assigned(NSApp) then @@ -1566,19 +1563,9 @@ begin p.x:=Point.X; p.y:=NSScreenZeroHeight-Point.Y; - winnr:=NSWindow.windowNumberAtPoint_belowWindowWithWindowNumber(p,0); - windowbelowpoint:=NSWindow(NSApp.windowWithWindowNumber(winnr)); - - windows := NSApp.windows; - for win := 0 to windows.count - 1 do - begin - window:=windows.objectAtIndex(win); - if windowbelowpoint=window then - begin - Result:= HWND(window.contentView); - exit; - end; - end; + window := GetCocoaWindowAtPos(p); + if Assigned(window) then + Result:= HWND(window.contentView); end; From 59ec9c4030e4b45668830337d4cf2212bc5fe7f5 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Fri, 29 Sep 2023 17:48:15 +0800 Subject: [PATCH 4/5] Cocoa: simplify TCocoaWSPopupMenu.Popup() by GetCocoaWindowAtPos() --- lcl/interfaces/cocoa/cocoawsmenus.pas | 33 +++++---------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoawsmenus.pas b/lcl/interfaces/cocoa/cocoawsmenus.pas index b4a95db522..c381dc16dd 100644 --- a/lcl/interfaces/cocoa/cocoawsmenus.pas +++ b/lcl/interfaces/cocoa/cocoawsmenus.pas @@ -949,12 +949,9 @@ end; class procedure TCocoaWSPopupMenu.Popup(const APopupMenu: TPopupMenu; const X, Y: Integer); var - res : Boolean; - mnu : NSMenuItem; view : NSView; w : NSWindow; px, py: Integer; - wi: NSUInteger; begin if Assigned(APopupMenu) and (APopupMenu.Handle<>0) then begin @@ -971,30 +968,10 @@ begin py := y; view := nil; w :=NSApp.keyWindow; - if not Assigned(w) and (NSApp.windows.count>0) then - begin + if not Assigned(w) then // in macOS it's possible to "rightclick" without focusing a window // so let's try to find the window - for wi := 0 to NSApp.windows.count-1 do - begin - w := NSWindow(NSApp.windows.objectAtIndex(wi)); - if not w.isVisible then Continue; - view := w.contentView; - view.lclScreenToLocal(px, py); - if (px >= 0) and (py >= 0) - and (px<=Round(view.frame.size.width)) - and (py<=Round(view.frame.size.height)) - then - begin - px := X; - py := Y; - Break; - end; - w := nil; - px := X; - py := Y; - end; - end; + w := GetCocoaWindowAtPos( NSMakePoint(px, py) ); if Assigned(w) then begin @@ -1007,8 +984,10 @@ begin if not view.isFlipped then py := Round(view.frame.size.height - py); end; - end; - res := TCocoaMenu(APopupMenu.Handle).popUpMenuPositioningItem_atLocation_inView( + end + else + py := Round(NSScreenZeroHeight - py); + TCocoaMenu(APopupMenu.Handle).popUpMenuPositioningItem_atLocation_inView( nil, NSMakePoint(px, py), view); APopupMenu.Close; // notify LCL popup menu end; From cf6abd4c138a84885849bc9d80e11000d4c39ed4 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Fri, 29 Sep 2023 17:51:11 +0800 Subject: [PATCH 5/5] Cocoa: optimize the response time of the Mouse Cursor on Window Active --- lcl/interfaces/cocoa/cocoawindows.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcl/interfaces/cocoa/cocoawindows.pas b/lcl/interfaces/cocoa/cocoawindows.pas index 2524746932..e24a6ae391 100644 --- a/lcl/interfaces/cocoa/cocoawindows.pas +++ b/lcl/interfaces/cocoa/cocoawindows.pas @@ -793,7 +793,7 @@ begin if Assigned(callback) then callback.Activate; - performSelector_withObject_afterDelay( ObjCSelector('DoWindowDidBecomeKey'), nil, 0.1 ); + performSelector_withObject_afterDelay( ObjCSelector('DoWindowDidBecomeKey'), nil, 0 ); end; procedure TCocoaWindow.windowDidResignKey(notification: NSNotification);