1 {
2 /***************************************************************************
3 CustomDrawnInt.pas - CustomDrawn Interface Object
4 -------------------
5
6 ***************************************************************************/
7
8 *****************************************************************************
9 This file is part of the Lazarus Component Library (LCL)
10
11 See the file COPYING.modifiedLGPL.txt, included in this distribution,
12 for details about the license.
13 *****************************************************************************
14 }
15
16 unit CustomDrawnInt;
17
18 {$mode objfpc}{$H+}
19
20 {$I customdrawndefines.inc}
21
22 interface
23
24 uses
25 // RTL
26 // for CD_Cocoa Types needs to be after the platform-specif units or else Mac
27 // will catch MacOSAll.Rect/Size/Point
28 {$ifndef CD_Cocoa}Types,{$endif}Classes, SysUtils, Math,
29 fpimage, fpcanvas, fpimgcanv, ctypes, dateutils,
30 // XML
31 XMLRead, Dom,
32 // Platform specific
33 {$ifdef CD_Windows}Windows, customdrawn_WinProc, customdrawn_winextra,{$endif}
34 {$ifdef CD_Cocoa}MacOSAll, CocoaAll, customdrawn_cocoaproc, CocoaGDIObjects,Types,{$endif}
35 {$ifdef CD_X11}X, XLib, XUtil, BaseUnix, customdrawn_x11proc,{$ifdef CD_UseNativeText}xft, fontconfig,{$endif}{$endif}
36 {$ifdef CD_Android}
37 customdrawn_androidproc, jni, bitmap, log, keycodes,
38 {$endif}
39 {$ifdef WinCE}aygshell,{$endif}
40 // LazUtils
41 LazFileUtils, lazutf8,
42 {$ifndef CD_UseNativeText}
43 // LazFreeType
44 LazFreeTypeIntfDrawer, LazFreeType, EasyLazFreeType, IniFiles,
45 {$endif}
46 // Widgetset
47 customdrawnproc, customdrawnthemes,
48 // LCL
49 customdrawn_common, customdrawncontrols, customdrawndrawers,
50 lazcanvas, lazregions, lazdeviceapis,
51 LCLPlatformDef, InterfaceBase, Themes, Dialogs, Buttons,
52 Controls, Forms, lclproc, IntfGraphics, GraphType,
53 LCLType, LMessages, Graphics, LCLStrConsts, Menus, LazLoggerBase;
54
55 type
56 {$ifdef CD_Windows}
57 TWinCETitlePolicy = (tpAlwaysUseOKButton, tpOKButtonOnlyOnDialogs, tpControlWithBorderIcons);
58
59 PPPipeEventInfo = ^PPipeEventInfo;
60 PPipeEventInfo = ^TPipeEventInfo;
61 TPipeEventInfo = record
62 Handle: THandle;
63 UserData: PtrInt;
64 OnEvent: TPipeEvent;
65 Prev: PPipeEventInfo;
66 Next: PPipeEventInfo;
67 end;
68
69 TWaitHandler = record
70 ListIndex: pdword;
71 UserData: PtrInt;
72 OnEvent: TWaitHandleEvent;
73 end;
74
Socketnull75 TSocketEvent = function(ASocket: THandle; Flags: dword): Integer of object;
76 {$endif}
77 {$ifdef CD_Cocoa}
78
79 TCDTimerObject=objcclass(NSObject)
80 func : TWSTimerProc;
81 procedure timerEvent; message 'timerEvent';
initWithFuncnull82 class function initWithFunc(afunc: TWSTimerProc): TCDTimerObject; message 'initWithFunc:';
83 end;
84
85 TCDAppDelegate = objcclass(NSObject, NSApplicationDelegateProtocol)
applicationShouldTerminatenull86 function applicationShouldTerminate(sender: NSApplication): NSApplicationTerminateReply; message 'applicationShouldTerminate:';
87 end;
88 {$endif}
89 {$ifdef CD_X11}
90 // Just in case...
91 {$endif}
92
93 // Return true to disable the form background drawing
94 TDisableFormBackgroundDrawingProc = function (AForm: TCustomForm): Boolean of object;
95
96 { TLazCDCustomFont }
97
98 TLazCDCustomFont = class(TFPCustomFont)
99 public
100 {$ifndef CD_UseNativeText}
101 FTFont: TFreeTypeFont;
102 {$endif}
103 constructor Create; override;
104 destructor Destroy; override;
105 end;
106
107 { TCDWidgetSet }
108
109 TCDWidgetSet = class(TWidgetSet)
110 private
111 FTerminating: Boolean;
112
113 // Clipboard support
114 FClipBoardFormats: TStringList;
115
116 {$ifdef CD_WINDOWS}
117 // In win32 it is: The parent of all windows, represents the button of the taskbar
118 // In wince it is just an invisible window, but retains the following functions:
119 // * This window is also the owner of the clipboard.
120 // * Assoc. windowproc also acts as handler for popup menus
121 // * It is indispensable for popupmenus and thread synchronization
122 FAppHandle: THandle;
123
124 FMetrics: TNonClientMetrics;
125 FMetricsFailed: Boolean;
126
127 FStatusFont: HFONT;
128 FMessageFont: HFONT;
129
130 FWaitHandleCount: dword;
131 FWaitHandles: array of HANDLE;
132 FWaitHandlers: array of TWaitHandler;
133 FWaitPipeHandlers: PPipeEventInfo;
134
135 FOnAsyncSocketMsg: TSocketEvent;
136
WinRegisternull137 function WinRegister: Boolean;
138 procedure CreateAppHandle;
139 {$endif}
140 public
141 {$ifdef CD_X11}
142 FDisplayName: string;
143 FDisplay: PDisplay;
144 FScreen: longint;
145 FVisual: TVisual; // Visual from X11
146
147 LeaderWindow: X.TWindow;
148 ClientLeaderAtom: TAtom;
149
150 FWMProtocols: TAtom; // Atom for "WM_PROTOCOLS"
151 FWMDeleteWindow: TAtom; // Atom for "WM_DELETE_WINDOW"
152 FWMHints: TAtom; // Atom for "_MOTIF_WM_HINTS"
153 FWMPaint: TAtom; // Atom for "WM_PAINT"
154
155 // For composing character events
156 ComposeBuffer: string;
157 ComposeStatus: TStatus;
158 InputMethod: xlib.PXIM;
159 InputContext: PXIC;
160 LastKeySym: TKeySym; // Used for KeyRelease event
161 LastKey: Word; // Used for KeyRelease event
162
163 ShiftState: TShiftState; // Keeps ShiftState from X
164
165 // XConnections list
166 XConnections: TFPList;
167 // Windows Info List
168 XWindowList: TStringList;
169 // Timer queue head
170 {$ifdef CD_X11_UseNewTimer}
171 XTimerListHead: customdrawn_x11proc.TCDX11Timer;
172 {$endif}
173
174 // Functions to keep track of windows needing repaint
CheckInvalidateWindowForXnull175 function CheckInvalidateWindowForX(XWIndowID: X.TWindow): Boolean;
176 procedure WindowUpdated(XWIndowID: X.TWindow);
177
FindWindowByXIDnull178 function FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
179 procedure AppProcessMessage;
180 procedure AppProcessInvalidates;
XStateToLCLStatenull181 function XStateToLCLState(XKeyState: cuint): TShiftState;
182 {$endif}
183 {$ifdef CD_Android}
184 CombiningAccent: Cardinal;
185 {$IFnDEF WithOldDebugln}
186 procedure AndroidDebugLn(ASender: TObject; AStr: string; var AHandled: Boolean;
187 Target: TLazLoggerWriteTarget; Data: Pointer);
188 {$ELSE}
189 procedure AndroidDebugLn(AStr: string);
190 {$ENDIF}
AndroidKeyCodeToLCLKeyCodenull191 function AndroidKeyCodeToLCLKeyCode(AAndroidKeyCode: Integer): Word;
DoOpenURLWidgetsetImplementationnull192 function DoOpenURLWidgetsetImplementation(AURL: string): Boolean;
DoOpenDocumentWidgetsetImplementationnull193 function DoOpenDocumentWidgetsetImplementation(APath: string): Boolean;
DoOpenAndroidURInull194 function DoOpenAndroidURI(AURI: JObject; AMimeType: string): Boolean;
GetMimeTypeFromFileNamenull195 function GetMimeTypeFromFileName(AFileName: string): string;
196 procedure ShowListViewDialog(ATitle: string; ATitles,
197 ADescriptions: array of string;
198 AColorOddRow: jint = $ff292C29; AColorEvenRow: jint = $ff424542);
199 {$endif}
200 {$ifdef CD_Cocoa}
201 pool : NSAutoreleasePool;
202 NSApp : NSApplication;
203 delegate : TCDAppDelegate;
204 ScreenBitmapContext: CGContextRef;
205 {$endif}
206 // For generic methods added in customdrawn
207 // They are used internally in LCL-CustomDrawn, LCL app should not use them
208 public
209 {$ifndef CD_UseNativeText}
210 // Font Path List
211 FFontPaths: TstringList;
212 FFontList: THashedStringList;
213 // default fonts availability
214 LiberationFont: Boolean;
215 LuxiFont: Boolean;
216 {$endif}
217 // Stock objects
218 FStockBlackBrush: TFPCustomBrush;
219 FStockDKGrayBrush: TFPCustomBrush;
220 FStockGrayBrush: TFPCustomBrush;
221 FStockLtGrayBrush: TFPCustomBrush;
222 FStockNullBrush: TFPCustomBrush;
223 FStockWhiteBrush: TFPCustomBrush;
224
225 FStockBlackPen: TFPCustomPen;
226 FStockNullPen: TFPCustomPen;
227 FStockWhitePen: TFPCustomPen;
228
229 DefaultFontSize: Integer;
230 FDefaultGUIFont: TFPCustomFont;
231 //
232 AccumulatedStr: string;
233 // The currently focused control
234 FocusedControl: TWinControl;
235 FocusedIntfControl: TWinControl;
236 // Default Fonts
237 DefaultFont: TFPCustomFont;
238 DefaultFontAndroidSize: Integer;
239 // Mobile emulator and mobile mode
240 MobileMainForm: TLCLIntfHandle;
241 // For unusual implementations of DebugLn/DebugOut
242 {$IFnDEF WithOldDebugln}
243 procedure AccumulatingDebugOut(ASender: TObject; AStr: string; var AHandled: Boolean;
244 Target: TLazLoggerWriteTarget; Data: Pointer);
245 {$ELSE}
246 procedure AccumulatingDebugOut(AStr: string);
247 {$ENDIF}
248 //
249 procedure CDSetFocusToControl(ALCLControl, AIntfControl: TWinControl);
250 //
251 protected
CreateThemeServicesnull252 function CreateThemeServices: TThemeServices; override;
GetAppHandlenull253 function GetAppHandle: THandle; override; //BackendSpecific
254 //procedure SetAppHandle(const AValue: THandle); override;
255 //
256 procedure BackendCreate;
257 procedure BackendDestroy;
258 //
259 procedure GenericAppInit;
260 public
261 // ScreenDC and Image for doing Canvas operations outside the Paint event
262 // and also for text drawing operations
263 ScreenDC: TLazCanvas;
264 ScreenBitmapRawImage: TRawImage;
265 ScreenBitmapHeight: Integer;
266 ScreenBitmapWidth: Integer;
267 ScreenImage: TLazIntfImage;
268 ScreenFormat: TLazCanvasImageFormat;
269
270 // Android Activity callbacks
271 ActivityOnCreate: TProcedure;
272 ActivityClassName: string;
273
274 constructor Create; override;
275 destructor Destroy; override;
276
LCLPlatformnull277 function LCLPlatform: TLCLPlatform; override;
GetLCLCapabilitynull278 function GetLCLCapability(ACapability: TLCLCapability): PtrUInt; override;
279
280 { Initialize the API }
281 procedure AppInit(var ScreenInfo: TScreenInfo); override;
282 procedure AppRun(const ALoop: TApplicationMainLoop); override;
283 procedure AppWaitMessage; override;
284 procedure AppProcessMessages; override;
285 procedure AppTerminate; override;
286 procedure AppMinimize; override;
287 procedure AppRestore; override;
288 procedure AppBringToFront; override;
289 procedure AppSetIcon(const Small, Big: HICON); override;
290 procedure AppSetTitle(const ATitle: string); override;
291 procedure AppSetVisible(const AVisible: Boolean); override;
AppRemoveStayOnTopFlagsnull292 function AppRemoveStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; override;
AppRestoreStayOnTopFlagsnull293 function AppRestoreStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; override;
294 procedure AppSetMainFormOnTaskBar(const DoSet: Boolean); override;
295
InitStockFontnull296 //function InitStockFont(AFont: TObject; AStockFont: TStockFont): Boolean; override;
297
298 procedure DCSetPixel(CanvasHandle: HDC; X, Y: integer; AColor: TGraphicsColor); override;
DCGetPixelnull299 function DCGetPixel(CanvasHandle: HDC; X, Y: integer): TGraphicsColor; override;
300 procedure DCRedraw(CanvasHandle: HDC); override;
301 procedure DCSetAntialiasing(CanvasHandle: HDC; AEnabled: Boolean); override;
302 procedure SetDesigning(AComponent: TComponent); override;
303
304 // create and destroy
CreateTimernull305 function CreateTimer(Interval: integer; TimerFunc: TWSTimerProc): THandle; override;
DestroyTimernull306 function DestroyTimer(TimerHandle: THandle): boolean; override;
307
308 {$I customdrawnwinapih.inc}
309 {$I customdrawnlclintfh.inc}
310 public
311 { Variables to be set by the user }
312 {$ifdef WinCE}
313 WinCETitlePolicy: TWinCETitlePolicy;
314 {$endif}
315
316 // This callback might be set to provide a routine which will select for
317 // which forms the drawing of the background should be disabled
318 // This is provided for speeding up the drawing
319 //
320 // Only use it if you are 100% sure that you are filling the entire buffer
321 // in the form paint event. Note that the form might sometimes be smaller
322 // then the buffer in Android so fill the entire Canvas area, not only the form size
323 DisableFormBackgroundDrawingProc: TDisableFormBackgroundDrawingProc;
324 end;
325
326 var
327 CDWidgetSet: TCDWidgetSet absolute WidgetSet;
328
CDMessageBoxFunctionnull329 function CDMessageBoxFunction(Text, Caption : PChar; Flags : Longint) : Integer;
330
331 {$ifdef CD_WINDOWS}
WindowProcnull332 function WindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
333 LParam: Windows.LParam): LResult; {$ifdef WinCE}cdecl;{$else}stdcall;{$endif}
334 {$endif}
335 {$ifdef CD_X11}
336 procedure MyXConnectionWatchProc(display: PDisplay; client_data: TXPointer;
337 fd: cint; opening: XLib.TBool; watch_data: PXPointer); cdecl;
338 {$endif}
339 {$ifdef CD_Android}
Java_com_pascal_lclproject_LCLActivity_LCLOnTouchnull340 function Java_com_pascal_lclproject_LCLActivity_LCLOnTouch(env:PJNIEnv;this:jobject; x, y: single; action: jint): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmapnull341 function Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap(
342 env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnCreatenull343 function Java_com_pascal_lclproject_LCLActivity_LCLOnCreate(
344 env:PJNIEnv; this:jobject; alclactivity: jobject): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinishednull345 function Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished(
346 env:PJNIEnv; this:jobject; AResult, ADialogType: jint): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnKeynull347 function Java_com_pascal_lclproject_LCLActivity_LCLOnKey(
348 env:PJNIEnv; this:jobject; AKind: jint; AKeyCode: jint;
349 AEvent: jobject; AChar: jint): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnTimernull350 function Java_com_pascal_lclproject_LCLActivity_LCLOnTimer(
351 env:PJNIEnv; this:jobject; ATimer: jobject; ATimerIDIndex: jint): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnConfigurationChangednull352 function Java_com_pascal_lclproject_LCLActivity_LCLOnConfigurationChanged(
353 env:PJNIEnv; this:jobject; ANewDPI, ANewWidth: jint): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnSensorChangednull354 function Java_com_pascal_lclproject_LCLActivity_LCLOnSensorChanged(
355 env:PJNIEnv; this:jobject; ASensorKind: jint; AValues: JDoubleArray): jint; cdecl;
Java_com_pascal_lclproject_LCLActivity_LCLOnMenuActionnull356 function Java_com_pascal_lclproject_LCLActivity_LCLOnMenuAction(
357 env:PJNIEnv; this:jobject; kind, itemIndex: jint): jint; cdecl;
JNI_OnLoadnull358 function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
359 procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl;
360
361 var
362 javaVMRef: PJavaVM=nil;
363 javaEnvRef: PJNIEnv=nil;
364 javaActivityClass: JClass = nil;
365 javaActivityObject: jobject = nil;
366
367 // The SDK Version
368 android_os_Build_VERSION_SDK_INT: jint;
369
370 // Other classes and objects
371 javaAndroidAppActivityClass: JClass = nil;
372 javaJavaLangSystemClass: JClass = nil;
373 javaAndroidOSBuildClass: JClass = nil;
374 javaAndroidOSVibratorClass: JClass = nil;
375 javaAndroidContentContextClass: JClass = nil;
376 javaJavaLangStringClass: JClass = nil;
377 javaAndroidOSBuildVERSIONClass: JClass = nil;
378
379 // Other fields
380 javaField_VERSION_SDK_INT: JFieldID = nil;
381 // Fields of our Activity
382 // Strings
383 javaField_lcltext: JfieldID=nil;
384 javaField_lcltitle: JfieldID=nil;
385 javaField_lclbutton1str: JfieldID=nil;
386 javaField_lclbutton2str: JfieldID=nil;
387 javaField_lclbutton3str: JfieldID=nil;
388 // Integers
389 javaField_lclwidth: JfieldID=nil;
390 javaField_lclheight: JfieldID=nil;
391 javaField_lclbutton1: JfieldID=nil;
392 javaField_lclbutton2: JfieldID=nil;
393 javaField_lclbutton3: JfieldID=nil;
394 javaField_lclbitmap: JfieldID=nil;
395 javaField_lcltextsize: JfieldID=nil;
396 // Text metrics
397 javaField_lcltextascent: JfieldID=nil;
398 javaField_lcltextbottom: JfieldID=nil;
399 javaField_lcltextdescent: JfieldID=nil;
400 javaField_lcltextleading: JfieldID=nil;
401 javaField_lcltexttop: JfieldID=nil;
402 javaField_lclmaxwidth: JfieldID=nil;
403 javaField_lclmaxcount: JfieldID=nil;
404 javaField_lclpartialwidths: JfieldID=nil;
405 // Timer
406 javaField_lcltimerinterval: JfieldID=nil;
407 javaField_lcltimerid: JfieldID=nil;
408 // Screen Metrics
409 javaField_lclxdpi: JfieldID=nil;
410 javaField_lclydpi: JfieldID=nil;
411 javaField_lclformwidth: JfieldID=nil;
412 javaField_lclformheight: JfieldID=nil;
413 javaField_lclscreenwidth: JfieldID=nil;
414 javaField_lclscreenheight: JfieldID=nil;
415 // For LazDeviceAPIs
416 javaField_lcldestination: JfieldID=nil;
417 javaField_lclkind: JfieldID=nil;
418
419 // Methods of our Activity
420 javaMethod_LCLDoGetTextBounds: jmethodid = nil;
421 javaMethod_LCLDoGetTextPartialWidths: jmethodid = nil;
422 javaMethod_LCLDoDrawText: jmethodid = nil;
423 javaMethod_LCLDoShowMessageBox: jmethodid = nil;
424 javaMethod_LCLDoCreateTimer: jmethodid = nil;
425 javaMethod_LCLDoDestroyTimer: jmethodid = nil;
426 javaMethod_LCLDoHideVirtualKeyboard: jmethodid = nil;
427 javaMethod_LCLDoShowVirtualKeyboard: jmethodid = nil;
428 javaMethod_LCLDoStartReadingAccelerometer: jmethodid = nil;
429 javaMethod_LCLDoStopReadingAccelerometer: jmethodid = nil;
430 javaMethod_LCLDoSendMessage: jmethodid = nil;
431 javaMethod_LCLDoRequestPositionInfo: jmethodid = nil;
432 // Methods from android.app.Activity
433 javaMethod_Activity_finish: jmethodid = nil;
434 // Methods from java.lang.System
435 javaMethod_System_exit: jmethodid = nil;
436 // Generic methods from Context
437 javaMethod_getSystemService: jmethodid = nil;
438
439 // This is utilized to store the information such as invalidate requests in events
440 eventResult: jint;
441 {$endif}
442
443 implementation
444
445 uses
446 WsControls, lclintf,
447 CustomDrawnWSFactory,
448 CustomDrawnWSForms,
449 { Win32WSButtons,
450 Win32WSMenus,
451 Win32WSStdCtrls,
452 Win32WSDialogs,
453 Win32Themes,
454 ////////////////////////////////////////////////////
455 Win32Extra,}
456 customdrawnprivate,
457 LCLMessageGlue;
458
459 {$ifdef CD_Windows}
460 const
461 CDBackendNativeHandle = nhtWindowsHWND;
462 {$define CD_HasNativeFormHandle}
463 {$endif}
464 {$ifdef CD_X11}
465 const
466 CDBackendNativeHandle = nhtX11TWindow;
467 {$define CD_HasNativeFormHandle}
468 {$endif}
469 {$ifdef CD_Cocoa}
470 const
471 CDBackendNativeHandle = nhtCocoaNSWindow;
472 {$define CD_HasNativeFormHandle}
473 {$endif}
474
475 { TLazCDCustomFont }
476
477 constructor TLazCDCustomFont.Create;
478 begin
479 inherited Create;
480 {$ifndef CD_UseNativeText}
481 FTFont := TFreeTypeFont.Create;
482 {$endif}
483 end;
484
485 destructor TLazCDCustomFont.Destroy;
486 begin
487 {$ifndef CD_UseNativeText}
488 FTFont.Free;
489 {$endif}
490 inherited Destroy;
491 end;
492
493 {$I customdrawnobject.inc}
494
495 {$I customdrawnwinapi.inc}
496 {$I customdrawnlclintf.inc}
497
498 {$ifdef CD_Windows}
499 {$include wincallback.inc}
500 {$I customdrawnobject_win.inc}
501 {$I customdrawnwinapi_win.inc}
502 {$I customdrawnlclintf_win.inc}
503 {$endif}
504 {$ifdef CD_Cocoa}
505 {$I customdrawnobject_cocoa.inc}
506 {$I customdrawnwinapi_cocoa.inc}
507 {$I customdrawnlclintf_cocoa.inc}
508 {$endif}
509 {$ifdef CD_X11}
510 {$I customdrawnobject_x11.inc}
511 {$I customdrawnwinapi_x11.inc}
512 {$I customdrawnlclintf_x11.inc}
513 {$endif}
514 {$ifdef CD_Android}
515 {$I customdrawnobject_android.inc}
516 {$I customdrawnwinapi_android.inc}
517 {$I customdrawnlclintf_android.inc}
518 {$endif}
519
520 end.
521