From b90ff1c48b53025d9e83f28ad7193d371eadab4e Mon Sep 17 00:00:00 2001 From: freq Date: Fri, 7 Feb 2014 13:16:50 +0000 Subject: [PATCH] Cocoa: Enable MouseCapture git-svn-id: trunk@43939 - --- lcl/interfaces/cocoa/cocoaint.pas | 2 + lcl/interfaces/cocoa/cocoaobject.inc | 1 + lcl/interfaces/cocoa/cocoawinapi.inc | 15 +++++ lcl/interfaces/cocoa/cocoawinapih.inc | 6 +- lcl/interfaces/cocoa/cocoawscommon.pas | 77 +++++++++++++++++++------- 5 files changed, 77 insertions(+), 24 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoaint.pas b/lcl/interfaces/cocoa/cocoaint.pas index 1c782e55d6..f00babd361 100644 --- a/lcl/interfaces/cocoa/cocoaint.pas +++ b/lcl/interfaces/cocoa/cocoaint.pas @@ -64,6 +64,7 @@ type pool: NSAutoreleasePool; FNSApp: NSApplication; FCurrentCursor: HCursor; + FCaptureControl: HWND; delegate: TCocoaAppDelegate; protected FStockNullBrush: HBRUSH; @@ -129,6 +130,7 @@ type function GetImagePixelData(AImage: CGImageRef; out bitmapByteCount: PtrUInt): Pointer; property NSApp: NSApplication read FNSApp; property CurrentCursor: HCursor read FCurrentCursor write FCurrentCursor; + property CaptureControl: HWND read FCaptureControl; // the winapi compatibility methods {$I cocoawinapih.inc} // the extra LCL interface methods diff --git a/lcl/interfaces/cocoa/cocoaobject.inc b/lcl/interfaces/cocoa/cocoaobject.inc index 1290425694..5ff5a5769e 100644 --- a/lcl/interfaces/cocoa/cocoaobject.inc +++ b/lcl/interfaces/cocoa/cocoaobject.inc @@ -87,6 +87,7 @@ begin inherited Create; FTerminating := False; FCurrentCursor:= 0; + FCaptureControl:= 0; { Creates the AutoreleasePool } pool := NSAutoreleasePool.alloc.init; diff --git a/lcl/interfaces/cocoa/cocoawinapi.inc b/lcl/interfaces/cocoa/cocoawinapi.inc index 59056d3f25..9e28e9cfa0 100644 --- a/lcl/interfaces/cocoa/cocoawinapi.inc +++ b/lcl/interfaces/cocoa/cocoawinapi.inc @@ -557,6 +557,11 @@ begin Result := CLR_INVALID; end; +function TCocoaWidgetSet.GetCapture: HWND; +begin + Result:=FCaptureControl; +end; + function TCocoaWidgetSet.GetCaretPos(var lpPoint: TPoint): Boolean; begin Result := CocoaCaret.GetCaretPos(lpPoint); @@ -1686,6 +1691,11 @@ begin Result := 0; end; +function TCocoaWidgetSet.SetCapture(AHandle: HWND): HWND; +begin + FCaptureControl:= AHandle; +end; + function TCocoaWidgetSet.SetCaretPos(X, Y: Integer): Boolean; begin Result := CocoaCaret.SetCaretPos(X, Y); @@ -1720,6 +1730,11 @@ begin Result := IntersectRect(R, ARect, CGRectToRect(ClipBox)); end; +function TCocoaWidgetSet.ReleaseCapture : Boolean; +begin + FCaptureControl:=0; +end; + function TCocoaWidgetSet.ReleaseDC(hWnd: HWND; DC: HDC): Integer; var ctx: TCocoaContext; diff --git a/lcl/interfaces/cocoa/cocoawinapih.inc b/lcl/interfaces/cocoa/cocoawinapih.inc index dd74426111..12fbaaee4b 100644 --- a/lcl/interfaces/cocoa/cocoawinapih.inc +++ b/lcl/interfaces/cocoa/cocoawinapih.inc @@ -83,7 +83,7 @@ function FrameRect(DC: HDC; const ARect: TRect; hBr: HBRUSH): Integer; override; function GetActiveWindow: HWND; override; {function GetBitmapBits(Bitmap: HBITMAP; Count: Longint; Bits: Pointer): Longint; override;} function GetBkColor(DC: HDC): TColorRef; override; -{function GetCapture: HWND; override;} +function GetCapture: HWND; override; function GetCaretPos(var lpPoint: TPoint): Boolean; override; function GetCaretRespondToFocus(handle: HWND; var ShowHideOnFocus: boolean): Boolean; override; function GetClientBounds(handle : HWND; var ARect : TRect) : Boolean; override; @@ -147,7 +147,7 @@ function PostMessage(Handle: HWND; Msg: Cardinal; wParam: WParam; lParam: LParam function Rectangle(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean; override; function RectVisible(dc : hdc; const ARect: TRect) : Boolean; override; -{function ReleaseCapture : Boolean; override;} +function ReleaseCapture : Boolean; override; function ReleaseDC(hWnd: HWND; DC: HDC): Integer; override; function RestoreDC(DC: HDC; SavedDC: Integer): Boolean; override; function RoundRect(DC: HDC; X1, Y1, X2, Y2: Integer; RX, RY : Integer): Boolean; override; @@ -160,7 +160,7 @@ function SendMessage(Handle: HWND; Msg: Cardinal; WParam: WParam; LParam: LParam function SetActiveWindow(Handle: HWND): HWND; override; function SetBKColor(DC: HDC; Color: TColorRef): TColorRef; override; function SetBkMode(DC: HDC; bkMode : Integer) : Integer; override; -{function SetCapture(AHandle: HWND): HWND; override;} +function SetCapture(AHandle: HWND): HWND; override; function SetCaretPos(X, Y: Integer): Boolean; override; function SetCaretPosEx(Handle: HWnd; X, Y: Integer): Boolean; override; function SetCaretRespondToFocus(handle: HWND; ShowHideOnFocus: boolean): Boolean; override; diff --git a/lcl/interfaces/cocoa/cocoawscommon.pas b/lcl/interfaces/cocoa/cocoawscommon.pas index 0d4ab5943a..26f765d547 100644 --- a/lcl/interfaces/cocoa/cocoawscommon.pas +++ b/lcl/interfaces/cocoa/cocoawscommon.pas @@ -29,6 +29,7 @@ type FTarget: TWinControl; FBoundsReportedToChildren: boolean; FIsOpaque:boolean; + FIsEventRouting:boolean; function CheckMouseButtonDown(Event: NSEvent; AButton: Integer): Cardinal; function GetHasCaret: Boolean; procedure SetHasCaret(AValue: Boolean); @@ -250,6 +251,7 @@ begin FPropStorage.Duplicates := dupAccept; FBoundsReportedToChildren:=false; FIsOpaque:=false; + FIsEventRouting:=false; end; destructor TLCLCommonCallback.Destroy; @@ -685,6 +687,8 @@ var MsgContext: TLMContextMenu; MousePos: NSPoint; MButton: NSInteger; + obj:NSObject; + callback: ICommonCallback; begin Result := False; // allow cocoa to handle message @@ -692,6 +696,20 @@ begin if Assigned(Target) and (not (csDesigning in Target.ComponentState) and not Owner.lclIsEnabled) then Exit; + //debugln('MouseUpDownEvent '+Target.name); + if CocoaWidgetSet.CaptureControl<>0 then // check if to route event to capture control + begin + obj:=NSObject(CocoaWidgetSet.CaptureControl); + if (obj<>Owner) and not FIsEventRouting then + begin + FIsEventRouting:=true; + callback:=obj.lclGetCallback; + Result:=callback.MouseUpDownEvent(Event); + FIsEventRouting:=false; + exit; + end; + end; + // idea of multi click implementation is taken from gtk FillChar(Msg, SizeOf(Msg), #0); @@ -775,32 +793,49 @@ begin rect:=Owner.lclClientFrame; targetControl:=nil; - if assigned(Target.Parent) and not PtInRect(rect, mp) then - targetControl:=Target.Parent // outside myself then go to parent - else - for i:=Target.ComponentCount-1 downto 0 do // otherwise check, if over child - if Target.Components[i] is TWinControl then - begin - childControl:=TWinControl(Target.Components[i]); - rect:=childControl.BoundsRect; - if PtInRect(rect, mp) then - begin - targetControl:=childControl; - break; - end; - end; + if CocoaWidgetSet.CaptureControl<>0 then // check if to route event to capture control + begin + obj:=NSObject(CocoaWidgetSet.CaptureControl); + if (obj<>Owner) and not FIsEventRouting then + begin + FIsEventRouting:=true; + callback:=obj.lclGetCallback; + result:=callback.MouseMove(Event); + FIsEventRouting:=false; + exit; + end; + end + else + begin + if assigned(Target.Parent) and not PtInRect(rect, mp) then + targetControl:=Target.Parent // outside myself then route to parent + else + for i:=Target.ComponentCount-1 downto 0 do // otherwise check, if over child and route to child + if Target.Components[i] is TWinControl then + begin + childControl:=TWinControl(Target.Components[i]); + rect:=childControl.BoundsRect; + if PtInRect(rect, mp) then + begin + targetControl:=childControl; + break; + end; + end; + end; - if assigned(targetControl) then + if assigned(targetControl) and not FIsEventRouting then begin - //debugln(Target.name+' -> '+targetControl.Name+'- is parent:'+dbgs(targetControl=Target.Parent)+' Point: '+dbgs(mp)+' Rect'+dbgs(rect)); - obj:=NSView(targetControl.Handle); - callback:=obj.lclGetCallback; - result:=callback.MouseMove(Event); - exit; + FIsEventRouting:=true; + // debugln(Target.name+' -> '+targetControl.Name+'- is parent:'+dbgs(targetControl=Target.Parent)+' Point: '+dbgs(mp)+' Rect'+dbgs(rect)); + obj:=NSView(targetControl.Handle); + callback:=obj.lclGetCallback; + result:=callback.MouseMove(Event); + FIsEventRouting:=false; + exit; end; - //debugln('Send to: '+Target.name+' Point: '+dbgs(mp)); + // debugln('Send to: '+Target.name+' Point: '+dbgs(mp)); FillChar(Msg, SizeOf(Msg), #0); Msg.Msg := LM_MOUSEMOVE;