Carbon: Support a WS_POPUP type floating window. Issue #21746, patch from David Jenkins and AlexeyT.

git-svn-id: trunk@54966 -
This commit is contained in:
juha 2017-05-18 10:00:29 +00:00
parent d88911aefa
commit 8bcb1a543e
5 changed files with 170 additions and 19 deletions

View File

@ -7499,7 +7499,7 @@ begin
TWSWinControlClass(WidgetSetClass).ConstraintsChange(Self);
//WriteClientRect('A');
if Assigned(Parent) then
if Assigned(Parent) and (Params.Style and WS_POPUP = 0) then
AddControl
else
if ParentWindow <> 0 then

View File

@ -74,6 +74,7 @@ type
function GetContent: ControlRef; virtual; abstract;
procedure UpdateLCLClientRect; virtual;
public
FPopupWin: WindowRef;
FNeedFree: Boolean;
procedure BeginEventProc;
procedure EndEventProc;

View File

@ -121,6 +121,7 @@ type
TCarbonCustomControl = class(TCarbonControl)
private
FForceEmbedded: Boolean;
FScrollView: HIViewRef;
FScrollOrigin: HIPoint;
FScrollSize: TPoint;
@ -763,9 +764,109 @@ end;
Creates Carbon custom control
------------------------------------------------------------------------------}
procedure TCarbonCustomControl.CreateWidget(const AParams: TCreateParams);
procedure RegisterWindowEvents(AWindowRef: WindowRef);
var
MouseSpec: array [0..6] of EventTypeSpec;
TmpSpec: EventTypeSpec;
KeySpecs: array[0..3] of EventTypeSpec;
ActivateSpecs: array[0..1] of EventTypeSpec;
ShowWindowSpecs: array[0..2] of EventTypeSpec;
WinContent: HIViewRef;
begin
// Window Events
TmpSpec := MakeEventSpec(kEventClassWindow, kEventWindowClose);
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonWindow_Close),
1, @TmpSpec, Pointer(Self), nil);
TmpSpec := MakeEventSpec(kEventClassWindow, kEventWindowClosed);
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonCommon_Dispose),
1, @TmpSpec, Pointer(Self), nil);
MouseSpec[0].eventClass := kEventClassMouse;
MouseSpec[0].eventKind := kEventMouseDown;
MouseSpec[1].eventClass := kEventClassMouse;
MouseSpec[1].eventKind := kEventMouseUp;
MouseSpec[2].eventClass := kEventClassMouse;
MouseSpec[2].eventKind := kEventMouseMoved;
MouseSpec[3].eventClass := kEventClassMouse;
MouseSpec[3].eventKind := kEventMouseDragged;
MouseSpec[4].eventClass := kEventClassMouse;
MouseSpec[4].eventKind := kEventMouseEntered;
MouseSpec[5].eventClass := kEventClassMouse;
MouseSpec[5].eventKind := kEventMouseExited;
MouseSpec[6].eventClass := kEventClassMouse;
MouseSpec[6].eventKind := kEventMouseWheelMoved;
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonWindow_MouseProc),
7, @MouseSpec[0], Pointer(Self), nil);
KeySpecs[0].eventClass := kEventClassKeyboard;
KeySpecs[0].eventKind := kEventRawKeyDown;
KeySpecs[1].eventClass := kEventClassKeyboard;
KeySpecs[1].eventKind := kEventRawKeyRepeat;
KeySpecs[2].eventClass := kEventClassKeyboard;
KeySpecs[2].eventKind := kEventRawKeyUp;
KeySpecs[3].eventClass := kEventClassKeyboard;
KeySpecs[3].eventKind := kEventRawKeyModifiersChanged;
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonWindow_KeyboardProc),
4, @KeySpecs[0], Pointer(Self), nil);
ActivateSpecs[0].eventClass := kEventClassWindow;
ActivateSpecs[0].eventKind := kEventWindowActivated;
ActivateSpecs[1].eventClass := kEventClassWindow;
ActivateSpecs[1].eventKind := kEventWindowDeactivated;
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonWindow_ActivateProc),
2, @ActivateSpecs[0], Pointer(Self), nil);
ShowWindowSpecs[0].eventClass := kEventClassWindow;
ShowWindowSpecs[0].eventKind := kEventWindowCollapsed;
ShowWindowSpecs[1].eventClass := kEventClassWindow;
ShowWindowSpecs[1].eventKind := kEventWindowExpanded;
ShowWindowSpecs[2].eventClass := kEventClassWindow;
ShowWindowSpecs[2].eventKind := kEventWindowZoomed;
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonWindow_ShowWindow),
3, @ShowWindowSpecs[0], Pointer(Self), nil);
TmpSpec := MakeEventSpec(kEventClassWindow, kEventWindowBoundsChanged);
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonCommon_BoundsChanged),
1, @TmpSpec, Pointer(Self), nil);
// cursor change
TmpSpec := MakeEventSpec(kEventClassWindow, kEventWindowCursorChange);
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonCommon_CursorChange),
1, @TmpSpec, Pointer(Self), nil);
// user messages
TmpSpec := MakeEventSpec(LCLCarbonEventClass, LCLCarbonEventKindUser);
InstallWindowEventHandler(AWindowRef,
RegisterEventHandler(@CarbonCommon_User),
1, @TmpSpec, Pointer(Self), nil);
// paint content message
if (HIViewFindByID( HIViewGetRoot(AWindowRef), kHIViewWindowContentID, WinContent) = noErr) then
begin
TmpSpec := MakeEventSpec(kEventClassControl, kEventControlDraw);
InstallControlEventHandler(WinContent,
RegisterEventHandler(@CarbonWindow_ContentDraw),
1, @TmpSpec, Pointer(Self), nil);
end;
end;
var
TmpSpec: EventTypeSpec;
AStyle: TControlStyle;
ContentViewRef: HIViewRef;
begin
AStyle := LCLObject.ControlStyle;
@ -781,6 +882,11 @@ begin
RegisterEventHandler(@CarbonScrollable_GetInfo),
1, @TmpSpec, Pointer(Self), nil);
FForceEmbedded := True;
if (AParams.Style and WS_POPUP <> 0) and
(AParams.Style and (WS_VSCROLL or WS_HSCROLL) = 0) then
FForceEmbedded := False;
FScrollView := EmbedInScrollView(AParams);
FScrollSize := Classes.Point(0, 0);
FScrollMin := Classes.Point(0, 0);
@ -788,7 +894,18 @@ begin
FScrollOrigin := GetHIPoint(0, 0);
FMulX := 1;
FMulY := 1;
if AParams.Style and WS_POPUP <> 0 then begin
CreateNewWindow(kFloatingWindowClass,
kWindowOpaqueForEventsAttribute or kWindowNoTitleBarAttribute or kWindowCompositingAttribute or kWindowStandardHandlerAttribute,
GetCarbonRect(0, 0, 0, 0),
FPopupWin);
RegisterWindowEvents(FPopupWin);
HIViewFindByID(HIViewGetRoot(FPopupWin), kHIViewWindowContentID, ContentViewRef);
OSError(HIViewAddSubview(ContentViewRef, FScrollView), Self, 'AddToWidget',
SViewAddView);
end
else
if LCLObject.ClassNameIs('TSynEdit') then
FTextFractional := False
else
@ -828,7 +945,7 @@ end;
function TCarbonCustomControl.GetForceEmbedInScrollView:Boolean;
begin
Result:=True;
Result := FForceEmbedded;
end;
{------------------------------------------------------------------------------

View File

@ -1189,6 +1189,10 @@ begin
GetClientRect(before{%H-});
OSError(SendEventToEventTarget(Event, GetControlEventTarget(FScrollView)),
Self, SName, 'SendEventToEventTarget');
if Assigned(FPopupWin) then
InvalidPaint:=True; // Needed to get scrollbars updated
GetClientRect(after{%H-});
if not CompareRect(@before, @after) then
UpdateLCLClientRect;
@ -1372,6 +1376,9 @@ begin
Exit;
end;
if Assigned(FPopupWin) then
GetWindowBounds(FPopupWin, kWindowContentRgn, BoundsRect);
ARect := SortRect(CarbonRectToRect(BoundsRect));
Result := True;
end;
@ -1432,12 +1439,24 @@ end;
function TCarbonControl.SetBounds(const ARect: TRect): Boolean;
var
B :CGRect;
T: TRect;
begin
Result := False;
if (IsDrawEvent > 0) then HIViewGetBounds(Frames[0], B{%H-});
if (IsDrawEvent > 0) then
if Assigned(FPopupWin) then
HIWindowGetBounds(FPopupWin, kWindowContentRgn, kHICoordSpaceWindow, B)
else
HIViewGetBounds(Frames[0], B{%H-});
if OSError(HIViewSetFrame(Frames[0], RectToCGRect(ARect)),
T := ARect;
if Assigned(FPopupWin) then
begin
SetWindowBounds(FPopupWin, kWindowContentRgn, GetCarbonRect(ARect));
T := Classes.Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top);
end;
if OSError(HIViewSetFrame(Frames[0], RectToCGRect(T)),
Self, SSetBounds, SViewFrame) then Exit;
// ensure bounds are send back to LCL once after creation
BoundsChanged;
@ -1588,6 +1607,9 @@ begin
OSError(HIViewSetVisible(Frames[I], AVisible or (csDesigning in LCLobject.ComponentState)),
Self, 'ShowHide', SViewVisible);
if Assigned(FPopupWin) then
MacOSAll.ShowHide(FPopupWin, AVisible);
if (IsDrawEvent > 0) and (AVisible <> v) and (AVisible or (csDesigning in LCLobject.ComponentState)) and (GetFrameCount>0) then
InvalidPaint := true;
end;
@ -1678,6 +1700,9 @@ var
begin
Window := LCLObject.GetTopParent;
if Assigned(FPopupWin) then
Result := FPopupWin
else
if (Window is TWinControl) and (Window.Parent = nil) and (TWinControl(Window).ParentWindow <> 0) then
Result := TCarbonControl(TWinControl(Window).ParentWindow).GetTopParentWindow
else

View File

@ -915,21 +915,29 @@ begin
Result := EventNotHandledErr;
Control := nil;
if OSError(GetKeyboardFocus( TCarbonWindow(AWidget).fWindowRef, Control), SName,
SGetKeyboardFocus) then Exit;
if Control = nil then Control := AWidget.Content;
// if a control other than root is found, send the message
// to the control instead of the window
// if a lower control without widget is found, use its parent
Widget := nil;
while Control <> AWidget.Content do
if Assigned(AWidget.FPopupWin) then
begin
Widget := GetCarbonControl(Pointer(Control));
if Widget <> nil then Break;
Control := HIViewGetSuperview(Control);
end;
if (Widget = nil) or (Control = AWidget.Content) then Widget := AWidget;
if OSError(GetKeyboardFocus(AWidget.FPopupWin, Control), SName, SGetKeyboardFocus) then Exit;
Widget := AWidget;
end
else
begin
if OSError(GetKeyboardFocus( TCarbonWindow(AWidget).fWindowRef, Control), SName,
SGetKeyboardFocus) then Exit;
if Control = nil then Control := AWidget.Content;
// if a control other than root is found, send the message
// to the control instead of the window
// if a lower control without widget is found, use its parent
Widget := nil;
while Control <> AWidget.Content do
begin
Widget := GetCarbonControl(Pointer(Control));
if Widget <> nil then Break;
Control := HIViewGetSuperview(Control);
end;
if (Widget = nil) or (Control = AWidget.Content) then Widget := AWidget;
end;
Widget.BeginEventProc;
try