mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2026-02-19 19:56:56 +01:00
- enhanced clipboard to use more text formats - TComboBox.OnDropDown and OnCloseUp partial implementation git-svn-id: trunk@12509 -
460 lines
15 KiB
PHP
460 lines
15 KiB
PHP
{%MainUnit carbonprivate.pp}
|
|
{ $Id: $}
|
|
{
|
|
*****************************************************************************
|
|
* *
|
|
* This file is part of the Lazarus Component Library (LCL) *
|
|
* *
|
|
* See the file COPYING.modifiedLGPL, included in this distribution, *
|
|
* for details about the copyright. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
* *
|
|
*****************************************************************************
|
|
}
|
|
|
|
// ==================================================================
|
|
// H A N D L E R S
|
|
// ==================================================================
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_Dispose
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_Dispose(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
begin
|
|
Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
LCLSendDestroyMsg(AWidget.LCLObject); // widget is disposed in DestroyHandle
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_Draw
|
|
Handles draw event
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_Draw(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
AStruct: PPaintStruct;
|
|
//EraseMsg: TLMEraseBkgnd;
|
|
begin
|
|
{$IFDEF VerbosePaint}
|
|
Debugln('CarbonCommon_Draw ', DbgSName(AWidget.LCLObject));
|
|
{$ENDIF}
|
|
|
|
|
|
AWidget.Context := TCarbonControlContext.Create(AWidget);
|
|
try
|
|
// set canvas context
|
|
if OSError(
|
|
GetEventParameter(AEvent, kEventParamCGContextRef, typeCGContextRef, nil,
|
|
SizeOf(CGContextRef), nil, @(AWidget.Context.CGContext)),
|
|
'CarbonCommon_Draw', SGetEvent, 'kEventParamCGContextRef') then Exit;
|
|
|
|
// erase background
|
|
{EraseMsg.Msg := LM_ERASEBKGND;
|
|
EraseMsg.DC := HDC(AWidget.Context);
|
|
DeliverMessage(AWidget.LCLObject, EraseMsg);}
|
|
|
|
// let carbon draw/update
|
|
Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
if (AWidget is TCarbonControl) and
|
|
(cceDraw in (AWidget as TCarbonControl).GetValidEvents) then
|
|
(AWidget as TCarbonControl).Draw;
|
|
|
|
New(AStruct);
|
|
FillChar(AStruct^, SizeOf(TPaintStruct), 0);
|
|
AStruct^.hdc := HDC(AWidget.Context);
|
|
try
|
|
{$IFDEF VerbosePaint}
|
|
DebugLn('CarbonCommon_Draw LM_PAINT to ', DbgSName(AWidget.LCLObject));
|
|
{$ENDIF}
|
|
LCLSendPaintMsg(AWidget.LCLObject, HDC(AWidget.Context), AStruct);
|
|
finally
|
|
Dispose(AStruct);
|
|
end;
|
|
finally
|
|
FreeAndNil(AWidget.Context);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_BoundsChanged
|
|
Handles bounds changing
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_BoundsChanged(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
begin
|
|
{$IFDEF VerboseCommonEvent}
|
|
DebugLn('CarbonCommon_BoundsChanged ', DbgSName(AWidget.LCLObject));
|
|
{$ENDIF}
|
|
// first let carbon draw/update
|
|
Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
AWidget.BoundsChanged;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_TrackProgress
|
|
Handles all mouse dragging events
|
|
------------------------------------------------------------------------------}
|
|
procedure CarbonCommon_TrackProgress(AControl: ControlRef;
|
|
APartCode: ControlPartCode); {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
Msg: TLMMouseMove;
|
|
P: TPoint;
|
|
Widget: TCarbonWidget;
|
|
begin
|
|
{$IFDEF VerboseMouse}
|
|
DebugLn('CarbonCommon_TrackProgress');
|
|
{$ENDIF}
|
|
|
|
Widget := GetCarbonWidget(AControl);
|
|
|
|
if Widget <> nil then
|
|
begin
|
|
P := Widget.GetMousePos;
|
|
|
|
if Widget is TCarbonControl then
|
|
if cceDoAction in (Widget as TCarbonControl).GetValidEvents then
|
|
(Widget as TCarbonControl).DoAction(APartCode);
|
|
|
|
FillChar(Msg, SizeOf(TLMMouseMove), 0);
|
|
Msg.Msg := LM_MOUSEMOVE;
|
|
Msg.XPos := P.X;
|
|
Msg.YPos := P.Y;
|
|
Msg.Keys := GetCarbonMsgKeyState;
|
|
DeliverMessage(Widget.LCLObject, Msg);
|
|
|
|
NotifyApplicationUserInput(Msg.Msg);
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_Track
|
|
Handles/Creates LM_MOUSEMOVE, LM_MOUSEUP events while dragging
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_Track(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
const
|
|
MSGKIND: array[1..3] of Integer = (LM_LBUTTONUP, LM_RBUTTONUP, LM_MBUTTONUP);
|
|
var
|
|
ActionUPP, OldActionUPP: ControlActionUPP;
|
|
P: TPoint;
|
|
Msg: TLMMouse;
|
|
MouseButton: EventMouseButton;
|
|
ControlPart: ControlPartCode;
|
|
const
|
|
SName = 'CarbonCommon_Track';
|
|
SControlAction = 'kEventParamControlAction';
|
|
begin
|
|
{$IFDEF VerboseMouse}
|
|
DebugLn('CarbonCommon_Track ', DbgSName(AWidget.LCLObject));
|
|
{$ENDIF}
|
|
if OSError(
|
|
GetEventParameter(AEvent, kEventParamControlAction, typeControlActionUPP,
|
|
nil, SizeOf(ActionUPP), nil, @OldActionUPP), SName, SGetEvent,
|
|
SControlAction) then Exit;
|
|
|
|
if OSError(
|
|
GetEventParameter(AEvent, kEventParamMouseButton, typeMouseButton, nil,
|
|
SizeOf(EventMouseButton), nil, @MouseButton), SName, SGetEvent,
|
|
'kEventParamMouseButton') then Exit;
|
|
|
|
ActionUPP := NewControlActionUPP(@CarbonCommon_TrackProgress);
|
|
try
|
|
if OSError(
|
|
SetEventParameter(AEvent, kEventParamControlAction, typeControlActionUPP,
|
|
SizeOf(ActionUPP), @ActionUPP), SName, SSetEvent, SControlAction) then Exit;
|
|
|
|
// this does not return until the mouse is released
|
|
Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
if OSError(
|
|
SetEventParameter(AEvent, kEventParamControlAction, typeControlActionUPP,
|
|
SizeOf(OldActionUPP), @OldActionUPP), SName, SSetEvent, SControlAction) then Exit;
|
|
finally
|
|
DisposeControlActionUPP(ActionUPP);
|
|
end;
|
|
|
|
FillChar(Msg, SizeOf(Msg), 0);
|
|
|
|
if (MouseButton >= Low(MSGKIND)) and (MouseButton <= High(MSGKIND)) then
|
|
Msg.Msg := MSGKIND[MouseButton];
|
|
|
|
P := AWidget.GetMousePos;
|
|
Msg.XPos := P.X;
|
|
Msg.YPos := P.Y;
|
|
Msg.Keys := GetCarbonMsgKeyState;
|
|
|
|
if (AWidget is TCarbonControl) and
|
|
(cceHit in (AWidget as TCarbonControl).GetValidEvents) then
|
|
begin
|
|
if OSError(
|
|
GetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode, nil,
|
|
SizeOf(ControlPartCode), nil, @ControlPart), SName, SGetEvent, SControlPart) then Exit;
|
|
|
|
{$IFDEF VerboseMouse}
|
|
DebugLn('CarbonCommon_Track Control Part ' + DbgS(ControlPart) +
|
|
' Button: ' + DbgS(MouseButton));
|
|
{$ENDIF}
|
|
if (ControlPart > 0) and (ControlPart < 128) then
|
|
begin
|
|
// Mouse up will be fired on hit
|
|
SavedMouseUpMsg := Msg;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
DeliverMessage(AWidget.LCLObject, Msg);
|
|
|
|
NotifyApplicationUserInput(Msg.Msg);
|
|
CarbonWidgetSet.SetCaptureWidget(0); // capture is released
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_CursorChange
|
|
Cursor changing
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_CursorChange(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
ALocation: FPCMacOSAll.Point;
|
|
AModifiers: UInt32;
|
|
ACursorWasSet: Boolean;
|
|
|
|
Widget: TCarbonWidget; //
|
|
Control: ControlRef; // the control we are dealing with
|
|
// or the rootcontrol if none found
|
|
const
|
|
SName = 'CarbonCommon_CursorChange';
|
|
begin
|
|
Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
if OSError(GetEventParameter(AEvent, kEventParamMouseLocation, typeQDPoint, nil,
|
|
SizeOf(ALocation), nil, @ALocation), SName, SGetEvent,
|
|
'kEventParamMouseLocation') then Exit;
|
|
|
|
if OSError(GetEventParameter(AEvent, kEventParamKeyModifiers, typeUInt32, nil,
|
|
SizeOf(AModifiers), nil, @AModifiers), SName, SGetEvent, SKeyModifiers) then Exit;
|
|
|
|
//Find out which control the mouse event should occur for
|
|
Control := nil;
|
|
if OSError(HIViewGetViewForMouseEvent(AWidget.Content, AEvent, Control),
|
|
SName, SViewForMouse) then Exit;
|
|
if Control = nil then Exit;
|
|
|
|
Widget := GetCarbonWidget(Control);
|
|
if Widget = nil then Exit;
|
|
|
|
if Screen.Cursor = crDefault then // we can change cursor
|
|
begin
|
|
ACursorWasSet := False;
|
|
|
|
// if widget has default cursor set - get it from Carbon
|
|
if TCarbonCursor(Widget.Cursor).Default then
|
|
begin
|
|
GlobalToLocal(ALocation);
|
|
|
|
if OSError(HandleControlSetCursor(Control, ALocation, AModifiers, ACursorWasSet),
|
|
SName, 'HandleControlSetCursor') then ACursorWasSet := False;
|
|
end;
|
|
|
|
if not ACursorWasSet then WidgetSet.SetCursor(Widget.Cursor);
|
|
end;
|
|
|
|
Result := noErr;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_ContextualMenuClick
|
|
PopupMenu auto popup support
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_ContextualMenuClick(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
Msg: TLMMouse;
|
|
P: TPoint;
|
|
begin
|
|
{$IFDEF VerboseCommonEvent}
|
|
DebugLn('CarbonCommon_ContextualMenuClick: ', DbgSName(AWidget.LCLObject));
|
|
{$ENDIF}
|
|
// Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
P := AWidget.GetMousePos;
|
|
|
|
FillChar(Msg, SizeOf(TLMMouse), 0);
|
|
Msg.Msg := LM_CONTEXTMENU;
|
|
Msg.Pos.X := P.X;
|
|
Msg.Pos.Y := P.Y;
|
|
|
|
DeliverMessage(AWidget.LCLObject, Msg);
|
|
Result := noErr; // do not propagate
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_SetFocusPart
|
|
Handles set or kill focus
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_SetFocusPart(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
CurrentFocus,
|
|
FocusPart: ControlPartCode;
|
|
const
|
|
SName = 'CarbonCommon_SetFocusPart';
|
|
begin
|
|
if not (AWidget is TCarbonCustomControl) then
|
|
Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
if OSError(
|
|
GetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode, nil,
|
|
SizeOf(ControlPartCode), nil, @FocusPart), SName,
|
|
SGetEvent, SControlPart) then Exit;
|
|
|
|
{$IFDEF VerboseCommonEvent}
|
|
DebugLn('CarbonCommon_SetFocusPart: ', DbgSName(AWidget.LCLObject), ' ' +
|
|
IntToStr(Integer(FocusPart)));
|
|
{$ENDIF}
|
|
|
|
if AWidget is TCarbonCustomControl then
|
|
begin
|
|
OSError(HIViewGetFocusPart(AWidget.Content, CurrentFocus),
|
|
SName, 'HIViewGetFocusPart');
|
|
|
|
case FocusPart of
|
|
kControlFocusPrevPart,
|
|
kControlFocusNextPart:
|
|
if CurrentFocus = kControlNoPart then FocusPart := kControlEditTextPart
|
|
else FocusPart := kControlEditTextPart;
|
|
kControlEditTextPart:;
|
|
else
|
|
FocusPart := kControlNoPart;
|
|
end;
|
|
|
|
OSError(
|
|
SetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode,
|
|
SizeOf(ControlPartCode), @FocusPart), SName, SSetEvent, SControlPart);
|
|
|
|
Result := noErr;
|
|
end;
|
|
|
|
if FocusPart <> kControlFocusNoPart then
|
|
AWidget.FocusSet
|
|
else
|
|
AWidget.FocusKilled;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_GetNextFocusCandidate
|
|
TabOrder and TabStop support
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_GetNextFocusCandidate(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
StartControl, NextControl: ControlRef;
|
|
FocusPart: ControlPartCode;
|
|
TabIndex: Integer;
|
|
TabList: TFPList;
|
|
AControl: TCarbonWidget;
|
|
const
|
|
SName = 'CarbonCommon_GetNextFocusCandidate';
|
|
begin
|
|
{$IFDEF VerboseCommonEvent}
|
|
DebugLn('CarbonCommon_GetNextFocusCandidate: ', DbgSName(AWidget.LCLObject));
|
|
{$ENDIF}
|
|
//Result := CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
if OSError(GetEventParameter(AEvent, kEventParamStartControl, typeControlRef,
|
|
nil, SizeOf(ControlRef), nil, @StartControl), SName, SGetEvent,
|
|
'kEventParamStartControl') then Exit;
|
|
|
|
if OSError(
|
|
GetEventParameter(AEvent, kEventParamControlPart, typeControlPartCode, nil,
|
|
SizeOf(ControlPartCode), nil, @FocusPart), SName, SGetEvent, SControlPart) then Exit;
|
|
|
|
TabIndex := 0;
|
|
TabList := TFPList.Create;
|
|
try
|
|
(AWidget.LCLObject.GetTopParent as TWinControl).GetTabOrderList(TabList);
|
|
AControl := GetCarbonWidget(StartControl);
|
|
|
|
if AControl <> nil then
|
|
begin
|
|
TabIndex := TabList.IndexOf(AControl.LCLObject);
|
|
if TabIndex >= 0 then
|
|
begin
|
|
if FocusPart = kControlFocusNextPart then
|
|
begin
|
|
Inc(TabIndex);
|
|
if TabIndex >= TabList.Count then TabIndex := 0;
|
|
end
|
|
else
|
|
begin
|
|
Dec(TabIndex);
|
|
if TabIndex < 0 then TabIndex := TabList.Count - 1;
|
|
end;
|
|
end
|
|
else TabIndex := 0;
|
|
end;
|
|
|
|
if TabIndex < TabList.Count then
|
|
NextControl := TCarbonControl(TWinControl(TabList[TabIndex]).Handle).Widget
|
|
else
|
|
NextControl := nil;
|
|
|
|
OSError(SetEventParameter(AEvent, kEventParamNextControl, typeControlRef,
|
|
SizeOf(ControlRef), @NextControl), SName, SSetEvent, 'kEventParamNextControl');
|
|
finally
|
|
TabList.Free;
|
|
end;
|
|
|
|
Result := noErr;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Name: CarbonCommon_SetCursor
|
|
Sets cursor
|
|
------------------------------------------------------------------------------}
|
|
function CarbonCommon_SetCursor(ANextHandler: EventHandlerCallRef;
|
|
AEvent: EventRef;
|
|
AWidget: TCarbonWidget): OSStatus; {$IFDEF darwin}mwpascal;{$ENDIF}
|
|
var
|
|
{
|
|
Msg: TLMessage;
|
|
}
|
|
ACursor: TCursor;
|
|
begin
|
|
// too much messages in terminal
|
|
// DebugLn('CarbonCommon_SetCursor: ', AWidget.LCLObject.Name);
|
|
CallNextEventHandler(ANextHandler, AEvent);
|
|
|
|
{
|
|
Paul Ishenin: maybe we should ask control about it cursor via LM_SetCursor ???
|
|
|
|
FillChar(Msg, SizeOf(Msg), 0);
|
|
Msg.msg := LM_SETCURSOR;
|
|
DeliverMessage(AWidget.LCLObject, Msg);
|
|
}
|
|
|
|
ACursor := Screen.Cursor;
|
|
if ACursor = crDefault then
|
|
begin
|
|
ACursor := AWidget.LCLObject.Cursor;
|
|
end;
|
|
WidgetSet.SetCursor(Screen.Cursors[ACursor]);
|
|
|
|
Result := noErr; // cursor was setted
|
|
end;
|