mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-27 11:40:29 +02:00
cocoa: revise window creation approach. the handle returned from CreateHandle method is now window content, rather than window itself. to be done: create either window or panel based on the border style
git-svn-id: trunk@43481 -
This commit is contained in:
parent
faa6ee5f53
commit
863c0b7125
@ -25,7 +25,7 @@ uses
|
||||
Types, Classes, SysUtils,
|
||||
CGGeometry,
|
||||
// Libs
|
||||
MacOSAll, CocoaAll, CocoaUtils, CocoaGDIObjects,
|
||||
CocoaAll, CocoaUtils, CocoaGDIObjects,
|
||||
// LCL
|
||||
LCLType, Controls;
|
||||
|
||||
@ -272,6 +272,37 @@ type
|
||||
procedure sendEvent(event: NSEvent); override;
|
||||
end;
|
||||
|
||||
|
||||
TCocoaWindow = objcclass(NSWindow, NSWindowDelegateProtocol)
|
||||
protected
|
||||
function windowShouldClose(sender : id): LongBool; message 'windowShouldClose:';
|
||||
procedure windowWillClose(notification: NSNotification); message 'windowWillClose:';
|
||||
procedure windowDidBecomeKey(notification: NSNotification); message 'windowDidBecomeKey:';
|
||||
procedure windowDidResignKey(notification: NSNotification); message 'windowDidResignKey:';
|
||||
procedure windowDidResize(notification: NSNotification); message 'windowDidResize:';
|
||||
procedure windowDidMove(notification: NSNotification); message 'windowDidMove:';
|
||||
public
|
||||
callback: IWindowCallback;
|
||||
function acceptsFirstResponder: Boolean; override;
|
||||
function canBecomeKeyWindow: Boolean; override;
|
||||
function becomeFirstResponder: Boolean; override;
|
||||
function resignFirstResponder: Boolean; override;
|
||||
function lclGetCallback: ICommonCallback; override;
|
||||
procedure lclClearCallback; override;
|
||||
// mouse
|
||||
procedure mouseDown(event: NSEvent); override;
|
||||
procedure mouseUp(event: NSEvent); override;
|
||||
procedure rightMouseDown(event: NSEvent); override;
|
||||
procedure rightMouseUp(event: NSEvent); override;
|
||||
procedure otherMouseDown(event: NSEvent); override;
|
||||
procedure otherMouseUp(event: NSEvent); override;
|
||||
procedure mouseDragged(event: NSEvent); override;
|
||||
procedure mouseEntered(event: NSEvent); override;
|
||||
procedure mouseExited(event: NSEvent); override;
|
||||
procedure mouseMoved(event: NSEvent); override;
|
||||
procedure sendEvent(event: NSEvent); override;
|
||||
end;
|
||||
|
||||
{ TCocoaCustomControl }
|
||||
|
||||
TCocoaCustomControl = objcclass(NSControl)
|
||||
@ -302,6 +333,20 @@ type
|
||||
procedure resetCursorRects; override;
|
||||
end;
|
||||
|
||||
{ TCocoaWindowContent }
|
||||
|
||||
TCocoaWindowContent = objcclass(TCocoaCustomControl)
|
||||
public
|
||||
isembedded: Boolean; // true - if the content is inside of another control, false - if the content is in its own window;
|
||||
ownwin: NSWindow;
|
||||
function lclOwnWindow: NSWindow; message 'lclOwnWindow';
|
||||
procedure lclSetFrame(const r: TRect); override;
|
||||
procedure viewDidMoveToSuperview; override;
|
||||
procedure viewDidMoveToWindow; override;
|
||||
procedure viewWillMoveToWindow(newWindow: NSWindow); override;
|
||||
procedure dealloc; override;
|
||||
end;
|
||||
|
||||
{ TCocoaScrollView }
|
||||
|
||||
TCocoaScrollView = objcclass(NSScrollView)
|
||||
@ -433,6 +478,53 @@ begin
|
||||
Result := NSThread.currentThread.isMainThread;
|
||||
end;
|
||||
|
||||
{ TCocoaWindowContent }
|
||||
|
||||
function TCocoaWindowContent.lclOwnWindow: NSWindow;
|
||||
begin
|
||||
if not isembedded then Result:=window
|
||||
else Result:=nil;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindowContent.lclSetFrame(const r: TRect);
|
||||
begin
|
||||
if isembedded then inherited lclSetFrame(r)
|
||||
else window.lclSetFrame(r);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindowContent.viewDidMoveToSuperview;
|
||||
begin
|
||||
|
||||
inherited viewDidMoveToSuperview;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindowContent.viewDidMoveToWindow;
|
||||
begin
|
||||
isembedded:=window.contentView<>self;
|
||||
if isembedded then begin
|
||||
if Assigned(ownwin) then ownwin.close;
|
||||
ownwin:=nil;
|
||||
end else begin
|
||||
ownwin:=window;
|
||||
end;
|
||||
inherited viewDidMoveToWindow;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindowContent.viewWillMoveToWindow(newWindow: NSWindow);
|
||||
begin
|
||||
if not isembedded then begin
|
||||
window.close;
|
||||
ownwin:=nil;
|
||||
isembedded:=false;
|
||||
end;
|
||||
inherited viewWillMoveToWindow(newWindow);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindowContent.dealloc;
|
||||
begin
|
||||
inherited dealloc;
|
||||
end;
|
||||
|
||||
{ TCocoaPanel }
|
||||
|
||||
function TCocoaPanel.windowShouldClose(sender: id): LongBool;
|
||||
@ -601,6 +693,174 @@ begin
|
||||
inherited sendEvent(event);
|
||||
end;
|
||||
|
||||
{ TCocoaWindow }
|
||||
|
||||
function TCocoaWindow.windowShouldClose(sender: id): LongBool;
|
||||
var
|
||||
canClose: Boolean;
|
||||
begin
|
||||
canClose := True;
|
||||
if Assigned(callback) then
|
||||
callback.CloseQuery(canClose);
|
||||
Result := canClose;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.windowWillClose(notification: NSNotification);
|
||||
begin
|
||||
if Assigned(callback) then
|
||||
callback.Close;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.windowDidBecomeKey(notification: NSNotification);
|
||||
begin
|
||||
if Assigned(callback) then
|
||||
callback.Activate;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.windowDidResignKey(notification: NSNotification);
|
||||
begin
|
||||
if Assigned(callback) then
|
||||
callback.Deactivate;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.windowDidResize(notification: NSNotification);
|
||||
begin
|
||||
if Assigned(callback) then
|
||||
callback.Resize;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.windowDidMove(notification: NSNotification);
|
||||
begin
|
||||
if Assigned(callback) then
|
||||
callback.Move;
|
||||
end;
|
||||
|
||||
function TCocoaWindow.acceptsFirstResponder: Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TCocoaWindow.canBecomeKeyWindow: Boolean;
|
||||
begin
|
||||
Result := Assigned(callback) and callback.CanActivate;
|
||||
end;
|
||||
|
||||
function TCocoaWindow.becomeFirstResponder: Boolean;
|
||||
begin
|
||||
Result := inherited becomeFirstResponder;
|
||||
if Assigned(callback) then
|
||||
callback.BecomeFirstResponder;
|
||||
end;
|
||||
|
||||
function TCocoaWindow.resignFirstResponder: Boolean;
|
||||
begin
|
||||
Result := inherited resignFirstResponder;
|
||||
if Assigned(callback) then
|
||||
callback.ResignFirstResponder;
|
||||
end;
|
||||
|
||||
function TCocoaWindow.lclGetCallback: ICommonCallback;
|
||||
begin
|
||||
Result := callback;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.lclClearCallback;
|
||||
begin
|
||||
callback := nil;
|
||||
contentView.lclClearCallback;
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.mouseDown(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
|
||||
inherited mouseDown(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.mouseUp(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
|
||||
inherited mouseUp(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.rightMouseDown(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
|
||||
inherited rightMouseUp(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.rightMouseUp(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
|
||||
inherited rightMouseDown(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.otherMouseDown(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
|
||||
inherited otherMouseDown(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.otherMouseUp(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseUpDownEvent(event) then
|
||||
inherited otherMouseUp(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.mouseDragged(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseMove(event) then
|
||||
inherited mouseDragged(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.mouseEntered(event: NSEvent);
|
||||
begin
|
||||
inherited mouseEntered(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.mouseExited(event: NSEvent);
|
||||
begin
|
||||
inherited mouseExited(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.mouseMoved(event: NSEvent);
|
||||
begin
|
||||
if not Assigned(callback) or not callback.MouseMove(event) then
|
||||
inherited mouseMoved(event);
|
||||
end;
|
||||
|
||||
procedure TCocoaWindow.sendEvent(event: NSEvent);
|
||||
var
|
||||
Message: NSMutableDictionary;
|
||||
Handle: HWND;
|
||||
Msg: Cardinal;
|
||||
WP: WParam;
|
||||
LP: LParam;
|
||||
Result: NSNumber;
|
||||
Obj: NSObject;
|
||||
begin
|
||||
if event.type_ = NSApplicationDefined then
|
||||
begin
|
||||
// event which we get through PostMessage or SendMessage
|
||||
if event.subtype = LCLEventSubTypeMessage then
|
||||
begin
|
||||
// extract message data
|
||||
Message := NSMutableDictionary(event.data1);
|
||||
Handle := NSNumber(Message.objectForKey(NSMessageWnd)).unsignedIntegerValue;
|
||||
Msg := NSNumber(Message.objectForKey(NSMessageMsg)).unsignedLongValue;
|
||||
WP := NSNumber(Message.objectForKey(NSMessageWParam)).integerValue;
|
||||
LP := NSNumber(Message.objectForKey(NSMessageLParam)).integerValue;
|
||||
// deliver message and set result
|
||||
Obj := NSObject(Handle);
|
||||
// todo: check that Obj is still a valid NSView/NSWindow
|
||||
Result := NSNumber.numberWithInteger(Obj.lclDeliverMessage(Msg, WP, LP));
|
||||
Message.setObject_forKey(Result, NSMessageResult);
|
||||
Result.release;
|
||||
end;
|
||||
end
|
||||
else
|
||||
inherited sendEvent(event);
|
||||
end;
|
||||
|
||||
{ TCocoaScrollView }
|
||||
|
||||
function TCocoaScrollView.acceptsFirstResponder: Boolean;
|
||||
|
@ -313,12 +313,15 @@ class function TCocoaWSCustomForm.CreateHandle(const AWinControl: TWinControl;
|
||||
const AParams: TCreateParams): TLCLIntfHandle;
|
||||
var
|
||||
Form: TCustomForm absolute AWinControl;
|
||||
win: TCocoaPanel;
|
||||
cnt: TCocoaCustomControl;
|
||||
win: TCocoaWindow;
|
||||
cnt: TCocoaWindowContent;
|
||||
ns: NSString;
|
||||
R: NSRect;
|
||||
begin
|
||||
win := TCocoaPanel(TCocoaPanel.alloc);
|
||||
//todo: create TCocoaWindow or TCocoaPanel depending on the border style
|
||||
// if parent is specified neither Window nor Panel needs to be created
|
||||
// the only thing that needs to be created is Content
|
||||
win := TCocoaWindow(TCocoaWindow.alloc);
|
||||
|
||||
if not Assigned(win) then
|
||||
begin
|
||||
@ -327,12 +330,11 @@ begin
|
||||
end;
|
||||
|
||||
R := CreateParamsToNSRect(AParams);
|
||||
win := TCocoaPanel(win.initWithContentRect_styleMask_backing_defer(R, GetStyleMaskFor(GetDesigningBorderStyle(Form), Form.BorderIcons), NSBackingStoreBuffered, False));
|
||||
win.setHidesOnDeactivate(False);
|
||||
win := TCocoaWindow(win.initWithContentRect_styleMask_backing_defer(R, GetStyleMaskFor(GetDesigningBorderStyle(Form), Form.BorderIcons), NSBackingStoreBuffered, False));
|
||||
UpdateWindowIcons(win, GetDesigningBorderStyle(Form), Form.BorderIcons);
|
||||
win.setLevel(FormStyleToWindowLevel[Form.FormStyle]);
|
||||
win.enableCursorRects;
|
||||
TCocoaPanel(win).callback := TLCLWindowCallback.Create(win, AWinControl);
|
||||
TCocoaWindow(win).callback := TLCLWindowCallback.Create(win, AWinControl);
|
||||
win.setDelegate(win);
|
||||
ns := NSStringUtf8(AWinControl.Caption);
|
||||
win.setTitle(ns);
|
||||
@ -342,7 +344,7 @@ begin
|
||||
R.origin.x := 0;
|
||||
R.origin.y := 0;
|
||||
|
||||
cnt := TCocoaCustomControl.alloc.initWithFrame(R);
|
||||
cnt := TCocoaWindowContent.alloc.initWithFrame(R);
|
||||
cnt.callback := TCocoaPanel(win).callback;
|
||||
win.setContentView(cnt);
|
||||
|
||||
@ -356,31 +358,47 @@ begin
|
||||
// TODO: docked forms
|
||||
end;
|
||||
|
||||
Result := TLCLIntfHandle(win);
|
||||
Result := TLCLIntfHandle(cnt);
|
||||
end;
|
||||
|
||||
class function TCocoaWSCustomForm.GetText(const AWinControl: TWinControl; var AText: String): Boolean;
|
||||
var
|
||||
win : NSWindow;
|
||||
begin
|
||||
Result := AWinControl.HandleAllocated;
|
||||
if Result then
|
||||
AText := NSStringToString(NSWindow(AWinControl.Handle).title);
|
||||
if Result then begin
|
||||
win := TCocoaWindowContent(AWinControl.Handle).lclOwnWindow;
|
||||
if not Assigned(win) then AText:=''
|
||||
else AText := NSStringToString(win.title);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TCocoaWSCustomForm.GetTextLen(const AWinControl: TWinControl; var ALength: Integer): Boolean;
|
||||
var
|
||||
win : NSWindow;
|
||||
begin
|
||||
Result := AWinControl.HandleAllocated;
|
||||
if Result then
|
||||
ALength := NSWindow(AWinControl.Handle).title.length;
|
||||
if Result then begin
|
||||
win := TCocoaWindowContent(AWinControl.Handle).lclOwnWindow;
|
||||
if Assigned(win) then
|
||||
ALength := NSWindow(AWinControl.Handle).title.length
|
||||
else
|
||||
ALength := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.SetText(const AWinControl: TWinControl; const AText: String);
|
||||
var
|
||||
ns: NSString;
|
||||
win : NSWindow;
|
||||
begin
|
||||
if not AWinControl.HandleAllocated then Exit;
|
||||
ns := NSStringUtf8(AText);
|
||||
NSwindow(AWinControl.Handle).setTitle(ns);
|
||||
ns.release;
|
||||
win:=TCocoaWindowContent(AWinControl.Handle).lclOwnWindow;
|
||||
if Assigned(win) then begin
|
||||
ns := NSStringUtf8(AText);
|
||||
NSwindow(win).setTitle(ns);
|
||||
ns.release;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.CloseModal(const ACustomForm: TCustomForm);
|
||||
@ -396,33 +414,53 @@ begin
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.SetAlphaBlend(const ACustomForm: TCustomForm; const AlphaBlend: Boolean; const Alpha: Byte);
|
||||
var
|
||||
win : NSWindow;
|
||||
begin
|
||||
if ACustomForm.HandleAllocated then
|
||||
if ACustomForm.HandleAllocated then begin
|
||||
win:=TCocoaWindowContent(ACustomForm.Handle).lclOwnWindow;
|
||||
if not Assigned(win) then Exit;
|
||||
if AlphaBlend then
|
||||
NSWindow(ACustomForm.Handle).setAlphaValue(Alpha / 255)
|
||||
win.setAlphaValue(Alpha / 255)
|
||||
else
|
||||
NSWindow(ACustomForm.Handle).setAlphaValue(1);
|
||||
win.setAlphaValue(1);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.SetBorderIcons(const AForm: TCustomForm;
|
||||
const ABorderIcons: TBorderIcons);
|
||||
var
|
||||
win : NSWindow;
|
||||
begin
|
||||
if AForm.HandleAllocated then
|
||||
UpdateWindowMask(NSWindow(AForm.Handle), GetDesigningBorderStyle(AForm), ABorderIcons);
|
||||
if AForm.HandleAllocated then begin
|
||||
win:=TCocoaWindowContent(AForm.Handle).lclOwnWindow;
|
||||
if Assigned(win) then
|
||||
UpdateWindowMask(win, GetDesigningBorderStyle(AForm), ABorderIcons);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.SetFormBorderStyle(const AForm: TCustomForm;
|
||||
const AFormBorderStyle: TFormBorderStyle);
|
||||
var
|
||||
win : NSWindow;
|
||||
begin
|
||||
if AForm.HandleAllocated then
|
||||
UpdateWindowMask(NSWindow(AForm.Handle), AFormBorderStyle, AForm.BorderIcons);
|
||||
if AForm.HandleAllocated then begin
|
||||
win:=TCocoaWindowContent(AForm.Handle).lclOwnWindow;
|
||||
if Assigned(win) then
|
||||
UpdateWindowMask(win, AFormBorderStyle, AForm.BorderIcons);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.SetFormStyle(const AForm: TCustomform;
|
||||
const AFormStyle, AOldFormStyle: TFormStyle);
|
||||
var
|
||||
win : NSWindow;
|
||||
begin
|
||||
if AForm.HandleAllocated then
|
||||
NSWindow(AForm.Handle).setLevel(FormStyleToWindowLevel[AFormStyle]);
|
||||
if AForm.HandleAllocated then begin
|
||||
win:=TCocoaWindowContent(AForm.Handle).lclOwnWindow;
|
||||
if Assigned(win) then
|
||||
win.setLevel(FormStyleToWindowLevel[AFormStyle]);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TCocoaWSCustomForm.SetPopupParent(
|
||||
@ -470,8 +508,9 @@ end;
|
||||
class procedure TCocoaWSCustomForm.SetBounds(const AWinControl: TWinControl;
|
||||
const ALeft, ATop, AWidth, AHeight: Integer);
|
||||
begin
|
||||
if AWinControl.HandleAllocated then
|
||||
if AWinControl.HandleAllocated then begin
|
||||
NSObject(AWinControl.Handle).lclSetFrame(Bounds(ALeft, ATop, AWidth, AHeight));
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user