diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 8452a74e3d..df4a3dc858 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; @@ -517,8 +547,6 @@ var ev : NSEvent; p : NSPoint; wfr : NSRect; - windowNumbers : NSArray; - windowNumber : NSNumber; begin kw := app.keyWindow; p := theEvent.mouseLocation; @@ -538,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); 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; 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); 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;