23
22
*****************************************************************************
27
{------------------------------------------------------------------------------
28
Method: TCocoaWidgetSet.AppInit
31
Initialize Carbon Widget Set
32
------------------------------------------------------------------------------}
33
procedure TCocoaWidgetSet.AppInit(var ScreenInfo: TScreenInfo);
35
{$IFDEF VerboseObject}
36
DebugLn('TCocoaWidgetSet.AppInit');
39
delegate:=TCocoaAppDelegate.alloc;
41
{ Creates the application NSApp object }
42
FNsApp := NSApplication.sharedApplication;
43
FNSApp.setDelegate(delegate);
46
{------------------------------------------------------------------------------
47
Method: TCocoaWidgetSet.AppRun
49
------------------------------------------------------------------------------}
50
procedure TCocoaWidgetSet.AppRun(const ALoop: TApplicationMainLoop);
52
{$IFDEF VerboseObject}
53
DebugLn('TCocoaWidgetSet.AppRun');
56
{ Enters main message loop }
60
{------------------------------------------------------------------------------
61
Method: TCocoaWidgetSet.AppProcessMessages
63
Handle all pending messages
64
------------------------------------------------------------------------------}
65
procedure TCocoaWidgetSet.AppProcessMessages;
69
{$IFDEF VerboseObject}
70
DebugLn('TCocoaWidgetSet.AppProcessMessages');
73
event := NSApp.nextEventMatchingMask_untilDate_inMode_dequeue(NSAnyEventMask, nil, NSDefaultRunLoopMode, true);
74
NSApp.sendEvent(event);
76
{$IFDEF VerboseObject}
77
DebugLn('TCocoaWidgetSet.AppProcessMessages END');
81
{------------------------------------------------------------------------------
82
Method: TCocoaWidgetSet.AppWaitMessage
84
Passes execution control to Cocoa
85
------------------------------------------------------------------------------}
86
procedure TCocoaWidgetSet.AppWaitMessage;
90
{$IFDEF VerboseObject}
91
DebugLn('TCocoaWidgetSet.AppWaitMessage');
93
event := NSApp.nextEventMatchingMask_untilDate_inMode_dequeue(NSAnyEventMask, NSDate.distantFuture, NSDefaultRunLoopMode, true);
94
NSApp.sendEvent(event);
97
{------------------------------------------------------------------------------
98
Method: TCocoaWidgetSet.Create
100
Constructor for the class
101
------------------------------------------------------------------------------}
102
constructor TCocoaWidgetSet.Create;
104
CocoaWidgetSet := Self;
106
FTerminating := False;
108
{ Creates the AutoreleasePool }
109
pool := NSAutoreleasePool.alloc.init;
111
NSMessageWnd := NSStringUTF8('HWND');
112
NSMessageMsg := NSStringUTF8('MSG');
113
NSMessageWParam := NSStringUTF8('WPARAM');
114
NSMessageLParam := NSStringUTF8('LPARAM');
115
NSMessageResult := NSStringUTF8('RESULT');
120
{------------------------------------------------------------------------------
121
Method: TCocoaWidgetSet.Destroy
123
Destructor for the class
124
------------------------------------------------------------------------------}
125
destructor TCocoaWidgetSet.Destroy;
132
CocoaWidgetSet := nil;
134
{ Releases the AutoreleasePool }
138
{------------------------------------------------------------------------------
139
Method: TCocoaWidgetSet.AppTerminate
141
Tells Carbon to halt the application
142
------------------------------------------------------------------------------}
143
procedure TCocoaWidgetSet.AppTerminate;
145
if FTerminating then Exit;
146
NSApp.terminate(nil);
149
{------------------------------------------------------------------------------
150
Method: TCocoaWidgetSet.AppMinimize
152
Minimizes the whole application to the taskbar
153
------------------------------------------------------------------------------}
154
procedure TCocoaWidgetSet.AppMinimize;
159
{------------------------------------------------------------------------------
160
Method: TCocoaWidgetSet.AppRestore
162
Restores the whole minimized application from the taskbar
163
------------------------------------------------------------------------------}
164
procedure TCocoaWidgetSet.AppRestore;
169
{------------------------------------------------------------------------------
170
Method: TCocoaWidgetSet.AppBringToFront
172
Brings the entire application on top of all other non-topmost programs
173
------------------------------------------------------------------------------}
174
procedure TCocoaWidgetSet.AppBringToFront;
176
NSApp.activateIgnoringOtherApps(True);
179
procedure TCocoaWidgetSet.AppSetIcon(const Small, Big: HICON);
182
NSApp.setApplicationIconImage(TCocoaBitmap(Big).image)
184
NSApp.setApplicationIconImage(nil);
187
{------------------------------------------------------------------------------
188
Method: TCocoaWidgetSet.AppSetTitle
189
Params: ATitle - New application title
191
Changes the application title
192
------------------------------------------------------------------------------}
193
procedure TCocoaWidgetSet.AppSetTitle(const ATitle: string);
197
if not Assigned(NSApp.dockTile) then Exit;
198
//todo: setBadgeLabel is for 10.5 only, should be removed
199
if NSApp.dockTile.respondsToSelector_(objcselector('setBadgeLabel:')) then
201
ns := NSStringUtf8(ATitle);
202
NSApp.dockTile.setBadgeLabel(NSStringUtf8(ATitle));
207
function TCocoaWidgetSet.GetLCLCapability(ACapability: TLCLCapability): PtrUInt;
210
lcCanDrawOutsideOnPaint,
211
lcNeedMininimizeAppWithMainForm,
215
lcReceivesLMClearCutCopyPasteReliably:
216
Result := LCL_CAPABILITY_NO;
217
lcAntialiasingEnabledByDefault:
218
Result := LCL_CAPABILITY_YES;
224
function TCocoaWidgetSet.CreateTimer(Interval: integer; TimerFunc: TWSTimerProc): THandle;
227
user : TCocoaTimerObject;
229
{$IFDEF VerboseObject}
230
DebugLn('TCocoaWidgetSet.CreateTimer');
232
user:=TCocoaTimerObject.initWithFunc(TimerFunc);
234
timer:=NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats(
235
Interval/1000, user, objcselector(user.timerEvent), user, True);
237
NSRunLoop.currentRunLoop.addTimer_forMode(timer, NSDefaultRunLoopMode);
239
{user is retained (twice, because it's target), by the timer and }
240
{released (twice) on timer invalidation}
243
Result:=THandle(timer);
246
function TCocoaWidgetSet.DestroyTimer(TimerHandle: THandle): boolean;
250
{$IFDEF VerboseObject}
251
DebugLn('TCocoaWidgetSet.DestroyTimer');
253
obj:=NSObject(TimerHandle);
255
Result:= Assigned(obj) and obj.isKindOfClass_(NSTimer);
259
if not Result then Exit;
260
NSTimer(obj).invalidate;
263
function TCocoaWidgetSet.PrepareUserEventInfo(Handle: HWND; Msg: Cardinal;
264
wParam: WParam; lParam: LParam): NSMutableDictionary;
266
LocalPool: NSAutoReleasePool;
267
Keys, Objs: NSMutableArray;
269
// create a dinctionary
270
LocalPool := NSAutoReleasePool.alloc.init;
271
Keys := NSMutableArray.arrayWithObjects(
278
Objs := NSMutableArray.arrayWithObjects(
279
NSNumber.numberWithUnsignedInteger(Handle),
280
NSNumber.numberWithUnsignedLong(Msg),
281
NSNumber.numberWithInteger(wParam),
282
NSNumber.numberWithInteger(lParam),
283
NSNumber.numberWithInteger(0),
285
Result := NSMutableDictionary.dictionaryWithObjects_forKeys(Objs, Keys);
287
// release everything
291
function TCocoaWidgetSet.PrepareUserEvent(Handle: HWND; Info: NSDictionary): NSEvent;
296
Obj := NSObject(Handle);
297
if Obj.isKindOfClass(NSWindow) then
300
if Obj.isKindOfClass(NSView) then
301
Win := NSView(Handle).window
304
Result := NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2(
305
NSApplicationDefined,
311
LCLEventSubTypeMessage,
316
procedure TCocoaWidgetSet.InitStockItems;
321
FillChar(LogBrush, SizeOf(TLogBrush),0);
322
LogBrush.lbStyle := BS_NULL;
323
FStockNullBrush := HBrush(TCocoaBrush.Create(LogBrush, True));
325
LogBrush.lbStyle := BS_SOLID;
326
LogBrush.lbColor := $000000;
327
FStockBlackBrush := HBrush(TCocoaBrush.Create(LogBrush, True));
329
LogBrush.lbColor := $C0C0C0;
330
FStockLtGrayBrush := HBrush(TCocoaBrush.Create(LogBrush, True));
332
LogBrush.lbColor := $808080;
333
FStockGrayBrush := HBrush(TCocoaBrush.Create(LogBrush, True));
335
LogBrush.lbColor := $404040;
336
FStockDkGrayBrush := HBrush(TCocoaBrush.Create(LogBrush, True));
338
LogBrush.lbColor := $FFFFFF;
339
FStockWhiteBrush := HBrush(TCocoaBrush.Create(LogBrush, True));
341
LogPen.lopnStyle := PS_NULL;
342
LogPen.lopnWidth := Types.Point(0, 0); // create cosmetic pens
343
LogPen.lopnColor := $FFFFFF;
344
FStockNullPen := HPen(TCocoaPen.Create(LogPen, True));
346
LogPen.lopnStyle := PS_SOLID;
347
FStockWhitePen := HPen(TCocoaPen.Create(LogPen, True));
349
LogPen.lopnColor := $000000;
350
FStockBlackPen := HPen(TCocoaPen.Create(LogPen, True));
352
FStockSystemFont := HFont(TCocoaFont.CreateDefault(True));
353
FStockFixedFont := HFont(TCocoaFont.Create(NSFont.userFixedPitchFontOfSize(0), True));
356
procedure TCocoaWidgetSet.FreeStockItems;
358
procedure DeleteAndNilObject(var h: HGDIOBJ);
361
TCocoaGDIObject(h).Global := False;
367
DeleteAndNilObject(FStockNullBrush);
368
DeleteAndNilObject(FStockBlackBrush);
369
DeleteAndNilObject(FStockLtGrayBrush);
370
DeleteAndNilObject(FStockGrayBrush);
371
DeleteAndNilObject(FStockDkGrayBrush);
372
DeleteAndNilObject(FStockWhiteBrush);
374
DeleteAndNilObject(FStockNullPen);
375
DeleteAndNilObject(FStockBlackPen);
376
DeleteAndNilObject(FStockWhitePen);
378
DeleteAndNilObject(FStockSystemFont);
379
DeleteAndNilObject(FStockFixedFont);
382
procedure TCocoaWidgetSet.FreeSysColorBrushes;
384
procedure DeleteAndNilObject(var h: HBrush);
396
for i := Low(FSysColorBrushes) to High(FSysColorBrushes) do
397
DeleteAndNilObject(FSysColorBrushes[i]);
400
{------------------------------------------------------------------------------
401
Method: TCocoaWidgetSet.GetAppHandle
402
Returns: Returns NSApp object, created via NSApplication.sharedApplication
403
------------------------------------------------------------------------------}
404
function TCocoaWidgetSet.GetAppHandle: THandle;
406
Result:=THandle(NSApp);
409
function TCocoaWidgetSet.DCGetPixel(CanvasHandle: HDC; X, Y: integer): TGraphicsColor;
414
procedure TCocoaWidgetSet.DCSetPixel(CanvasHandle: HDC; X, Y: integer; AColor: TGraphicsColor);
419
procedure TCocoaWidgetSet.DCRedraw(CanvasHandle: HDC);
421
if CanvasHandle <> 0 then
422
TCocoaContext(CanvasHandle).ctx.flushGraphics;
425
procedure TCocoaWidgetSet.DCSetAntialiasing(CanvasHandle: HDC; AEnabled: Boolean);
427
if CanvasHandle <> 0 then
428
TCocoaContext(CanvasHandle).SetAntialiasing(AEnabled);
431
procedure TCocoaWidgetSet.SetDesigning(AComponent: TComponent);
436
{------------------------------------------------------------------------------
437
Method: TCocoaWidgetSet.LCLPlatform
438
Returns: lpCocoa - enum value for Cocoa widgetset
439
------------------------------------------------------------------------------}
440
function TCocoaWidgetSet.LCLPlatform: TLCLPlatform;
445
procedure InternalInit;
449
procedure InternalFinal;
451
if Assigned(ScreenContext) then ScreenContext.Free;
455
{ TCocoaAppDelegate }
457
function TCocoaAppDelegate.applicationShouldTerminate(sender: NSApplication): NSApplicationTerminateReply;
459
Result := NSTerminateNow;
462
{ TCocoaTimerObject }
464
procedure TCocoaTimerObject.timerEvent;
466
if Assigned(@func) then func;
469
class function TCocoaTimerObject.initWithFunc(afunc: TWSTimerProc): TCocoaTimerObject;
475
{------------------------------------------------------------------------------
476
Method: TCarbonWidgetSet.RawImage_DescriptionFromCarbonBitmap
478
Creates a rawimage description for a carbonbitmap
479
------------------------------------------------------------------------------}
480
function TCocoaWidgetSet.RawImage_DescriptionFromCocoaBitmap(out ADesc: TRawImageDescription; ABitmap: TCocoaBitmap): Boolean;
482
Prec, Shift, BPR: Byte;
486
case ABitmap.BitmapType of
487
cbtMono, cbtGray: ADesc.Format := ricfGray;
489
ADesc.Format := ricfRGBA;
492
with ABitmap.image.size do
494
ADesc.Width := Round(width);
495
ADesc.Height := Round(Height);
498
//ADesc.PaletteColorCount := 0;
500
ADesc.BitOrder := riboReversedBits;
501
ADesc.ByteOrder := riboMSBFirst;
503
BPR := ABitmap.BytesPerRow;
504
if BPR and $F = 0 then ADesc.LineEnd := rileDQWordBoundary // 128bit aligned
505
else if BPR and $7 = 0 then ADesc.LineEnd := rileQWordBoundary // 64bit aligned
506
else if BPR and $3 = 0 then ADesc.LineEnd := rileWordBoundary // 32bit aligned
507
else if BPR and $1 = 0 then ADesc.LineEnd := rileByteBoundary // 8bit aligned
508
else ADesc.LineEnd := rileTight;
510
ADesc.LineOrder := riloTopToBottom;
511
ADesc.BitsPerPixel := ABitmap.BitsPerPixel;
513
ADesc.MaskBitOrder := riboReversedBits;
514
ADesc.MaskBitsPerPixel := 1;
515
ADesc.MaskLineEnd := rileByteBoundary;
516
// ADesc.MaskShift := 0;
518
ADesc.Depth := ABitmap.Depth;
519
Prec := ABitmap.BitsPerSample;
521
ADesc.RedPrec := Prec;
522
ADesc.GreenPrec := Prec;
523
ADesc.BluePrec := Prec;
526
if ADesc.Format = ricfGray then Exit;
529
if ABitmap.BitmapType in [cbtARGB, cbtRGBA, cbtBGRA] then
530
ADesc.AlphaPrec := Prec;
532
case ABitmap.BitmapType of
535
ADesc.RedShift := Shift;
537
ADesc.GreenShift := Shift;
539
ADesc.BlueShift := Shift;
543
ADesc.BlueShift := Shift;
545
ADesc.GreenShift := Shift;
547
ADesc.RedShift := Shift;
551
ADesc.AlphaShift := Shift;
553
ADesc.RedShift := Shift;
555
ADesc.GreenShift := Shift;
557
ADesc.BlueShift := Shift;
561
ADesc.RedShift := Shift;
563
ADesc.GreenShift := Shift;
565
ADesc.BlueShift := Shift;
567
ADesc.AlphaShift := Shift;
571
ADesc.BlueShift := Shift;
573
ADesc.GreenShift := Shift;
575
ADesc.RedShift := Shift;
577
ADesc.AlphaShift := Shift;
584
{------------------------------------------------------------------------------
585
Method: TCarbonWidgetSet.RawImage_FromCarbonBitmap
587
Creates a rawimage description for a carbonbitmap
588
------------------------------------------------------------------------------}
589
function TCocoaWidgetSet.RawImage_FromCocoaBitmap(out ARawImage: TRawImage; ABitmap, AMask: TCocoaBitmap; ARect: PRect = nil): Boolean;
591
FillChar(ARawImage, SizeOf(ARawImage), 0);
592
RawImage_DescriptionFromCocoaBitmap(ARawImage.Description, ABitmap);
594
ARawImage.DataSize := ABitmap.DataSize;
595
ReAllocMem(ARawImage.Data, ARawImage.DataSize);
596
if ARawImage.DataSize > 0 then
597
System.Move(ABitmap.Data^, ARawImage.Data^, ARawImage.DataSize);
603
ARawImage.Description.MaskBitsPerPixel := 0;
609
DebugLn('[WARNING] RawImage_FromCarbonBitmap: AMask.Depth > 1');
613
ARawImage.MaskSize := AMask.DataSize;
614
ReAllocMem(ARawImage.Mask, ARawImage.MaskSize);
615
if ARawImage.MaskSize > 0 then
616
System.Move(AMask.Data^, ARawImage.Mask^, ARawImage.MaskSize);
619
function TCocoaWidgetSet.RawImage_DescriptionToBitmapType(
620
ADesc: TRawImageDescription;
621
out bmpType: TCocoaBitmapType): Boolean;
625
if ADesc.Format = ricfGray
628
if ADesc.Depth = 1 then bmpType := cbtMono
629
else bmpType := cbtGray;
631
else if ADesc.Depth = 1
632
then bmpType := cbtMono
633
else if ADesc.AlphaPrec <> 0
635
if ADesc.ByteOrder = riboMSBFirst
637
if (ADesc.AlphaShift = 24)
638
and (ADesc.RedShift = 16)
639
and (ADesc.GreenShift = 8 )
640
and (ADesc.BlueShift = 0 )
641
then bmpType := cbtARGB
643
if (ADesc.AlphaShift = 0)
644
and (ADesc.RedShift = 24)
645
and (ADesc.GreenShift = 16 )
646
and (ADesc.BlueShift = 8 )
647
then bmpType := cbtRGBA
649
if (ADesc.AlphaShift = 0 )
650
and (ADesc.RedShift = 8 )
651
and (ADesc.GreenShift = 16)
652
and (ADesc.BlueShift = 24)
653
then bmpType := cbtBGRA
657
if (ADesc.AlphaShift = 24)
658
and (ADesc.RedShift = 16)
659
and (ADesc.GreenShift = 8 )
660
and (ADesc.BlueShift = 0 )
661
then bmpType := cbtBGRA
663
if (ADesc.AlphaShift = 0 )
664
and (ADesc.RedShift = 8 )
665
and (ADesc.GreenShift = 16)
666
and (ADesc.BlueShift = 24)
667
then bmpType := cbtARGB
669
if (ADesc.AlphaShift = 24 )
670
and (ADesc.RedShift = 0 )
671
and (ADesc.GreenShift = 8)
672
and (ADesc.BlueShift = 16)
673
then bmpType := cbtRGBA