1{
2 *****************************************************************************
3  This file is part of the Lazarus Component Library (LCL)
4
5  See the file COPYING.modifiedLGPL.txt, included in this distribution,
6  for details about the license.
7 *****************************************************************************
8}
9unit Gtk2Globals;
10
11{$mode objfpc}{$H+}
12
13interface
14
15uses
16  // RTL
17  SysUtils, Classes,
18  Pango, glib2, gdk2, gtk2,
19  // LCL
20  InterfaceBase,
21  LMessages, LCLProc, Controls, ComCtrls, Forms, LCLIntf, LCLType,
22  // LazUtils
23  DynHashArray;
24
25{$I dragicons.inc}
26
27const
28  GtkNil = nil;
29
30var
31  // gtk-interface options
32  UseTransientForModalWindows: boolean;
33  UpdatingTransientWindows: boolean;
34
35  // mouse --------------------------------------------------------------------
36var
37  //drag icons
38  //TrashCan_Open : PgdkPixmap;
39  //TrashCan_Open_Mask : PGdkPixmap;
40  //TrashCan_Closed : PGdkPixmap;
41  //TrashCan_Closed_Mask : PGdkPixmap;
42  //Drag_Icon : PgdkPixmap;
43  //Drag_Mask : PgdkPixmap;
44
45  //Dragging : Boolean;
46
47  MouseCaptureWidget: PGtkWidget;
48  MouseCaptureIndex: cardinal;
49  MousePosition: TPoint;
50  MousePositionTime: TDateTime;
51
52  // cache for WindowFromPoint
53  LastWFPMousePos: TPoint;
54  LastWFPResult: HWND;
55
56const
57  DblClickTime = 250;// 250 miliseconds or less between clicks is a double click
58  DblClickThreshold = 3;// max Movement between two clicks of a DblClick
59
60var
61  LastMouse: TLastMouseInfo;
62
63var
64  im_context: PGtkIMContext = nil;
65  im_context_widget: PGtkWidget = nil;
66  im_context_skipdelete: Boolean = False;
67  im_context_use: Boolean = False;
68  im_context_string: string = '';
69  im_context_string_commit: string = '';
70  im_context_string_preedit: string = '';
71
72procedure ResetDefaultIMContext;
73{$IFDEF WITH_GTK2_IM}
74procedure IM_Context_Set_Cursor_Pos(X, Y: gint);
75{$ENDIF}
76
77var
78  LastFileSelectRow : gint;
79
80
81var
82  Styles : TStrings;
83
84const
85  //(bsNone, bsSingle, bsSizeable, bsDialog, bsToolWindow, bsSizeToolWin);
86  GtkWindowTypeHints: array[TFormBorderStyle] of TGdkWindowTypeHint = (
87  GDK_WINDOW_TYPE_HINT_NOTIFICATION,
88  GDK_WINDOW_TYPE_HINT_NORMAL,
89  GDK_WINDOW_TYPE_HINT_NORMAL,
90  GDK_WINDOW_TYPE_HINT_DIALOG,
91  GDK_WINDOW_TYPE_HINT_UTILITY,
92  GDK_WINDOW_TYPE_HINT_UTILITY
93  );
94
95var
96  DefaultPangoLayout: PPangoLayout = nil;
97
98const
99  KEYMAP_VKUNKNOWN = $10000;
100  KEYMAP_TOGGLE    = $20000;
101  KEYMAP_EXTENDED  = $40000;
102
103// PDB: note this is a hack. Windows maintains a system wide
104//      system color table we will have to have our own
105//      to be able to do the translations required from
106//      window manager to window manager this means every
107//      application will carry its own color table
108//      we set the defaults here to reduce the initial
109//      processing of creating a default table
110// MWE: Naaaaah, not a hack, just something temporary
111const
112  SysColorMap: array [0..MAX_SYS_COLORS] of DWORD = (
113    $C0C0C0,     {COLOR_SCROLLBAR}
114    $808000,     {COLOR_BACKGROUND}
115    $800000,     {COLOR_ACTIVECAPTION}
116    $808080,     {COLOR_INACTIVECAPTION}
117    $C0C0C0,     {COLOR_MENU}
118    $FFFFFF,     {COLOR_WINDOW}
119    $000000,     {COLOR_WINDOWFRAME}
120    $000000,     {COLOR_MENUTEXT}
121    $000000,     {COLOR_WINDOWTEXT}
122    $FFFFFF,     {COLOR_CAPTIONTEXT}
123    $C0C0C0,     {COLOR_ACTIVEBORDER}
124    $C0C0C0,     {COLOR_INACTIVEBORDER}
125    $808080,     {COLOR_APPWORKSPACE}
126    $800000,     {COLOR_HIGHLIGHT}
127    $FFFFFF,     {COLOR_HIGHLIGHTTEXT}
128    $D0D0D0,     {COLOR_BTNFACE}
129    $808080,     {COLOR_BTNSHADOW}
130    $808080,     {COLOR_GRAYTEXT}
131    $000000,     {COLOR_BTNTEXT}
132    $C0C0C0,     {COLOR_INACTIVECAPTIONTEXT}
133    $F0F0F0,     {COLOR_BTNHIGHLIGHT}
134    $000000,     {COLOR_3DDKSHADOW}
135    $C0C0C0,     {COLOR_3DLIGHT}
136    $000000,     {COLOR_INFOTEXT}
137    $AEF3F3,     {COLOR_INFOBK}
138    $000000,     {unassigned}
139    $000000,     {COLOR_HOTLIGHT}
140    $800000,     {COLOR_GRADIENTACTIVECAPTION}
141    $808080,     {COLOR_GRADIENTINACTIVECAPTION}
142    $800000,     {COLOR_MENUHILIGHT}
143    $D0D0D0,     {COLOR_MENUBAR}
144    $D0D0D0      {COLOR_FORM}
145  ); {end _SysColors}
146
147const
148  GTK_WINDOW_DIALOG=GTK_WINDOW_TOPLEVEL;
149  FormStyleMap : array[TFormBorderStyle] of TGtkWindowType = (
150    // GTK_WINDOW_DIALOG for stay on top forms
151    GTK_WINDOW_DIALOG,  // bsNone
152    GTK_WINDOW_TOPLEVEL,// bsSingle
153    GTK_WINDOW_TOPLEVEL,// bsSizeable
154    GTK_WINDOW_DIALOG,  // bsDialog
155    GTK_WINDOW_TOPLEVEL,  // bsToolWindow
156    GTK_WINDOW_TOPLEVEL   // bsSizeToolWin
157  );
158  FormResizableMap : array[TFormBorderStyle] of gint = (
159    0, // bsNone
160    0, // bsSingle
161    1, // bsSizeable
162    0, // bsDialog
163    0, // bsToolWindow
164    1  // bsSizeToolWin
165  );
166
167  BorderStyleShadowMap: array[TBorderStyle] of TGtkShadowType =
168  (
169{ bsNone   } GTK_SHADOW_NONE,
170{ bsSingle } GTK_SHADOW_ETCHED_IN
171  );
172
173  BorderShadowWidth: array[TBorderStyle] of gint = (0, 1);
174
175  // signals ------------------------------------------------------------------
176type
177
178  //Defined in gtksignal.c
179  PGtkHandler = ^TGtkHandler;
180  TGtkHandler = record
181    id:               guint;
182    next:             PGtkHandler;
183    prev:             PGtkHandler;
184    flags:            guint; // -->  blocked : 20 bits,
185                             //      object_signal : 1 bit,
186                             //      after : 1 bit,
187                             //      no_marshal : 1 bit
188    ref_count:        guint16;
189    signal_id:        guint16;
190    func:             TGtkSignalFunc;
191    func_data:        gpointer;
192    destroy_func:     TGtkSignalFunc;
193  end;
194
195const
196  bmSignalAfter = $00200000;
197
198type
199  { lazarus GtkInterface definition for additional timer data, not in gtk }
200  PGtkITimerInfo = ^TGtkITimerinfo;
201  TGtkITimerInfo = record
202    TimerHandle: guint;        // the gtk handle for this timer
203    TimerFunc  : TWSTimerProc; // owner function to handle timer
204  end;
205
206var
207  // FTimerData contains the currently running timers
208  FTimerData : TFPList;   // list of PGtkITimerinfo
209
210var
211  gtk_handler_quark: TGQuark;
212
213
214// Internal Paint message:
215const
216  LM_GTKPAINT         = LM_INTERFACEFIRST + 0;
217
218  GtkPaint_LCLWidget = 1;
219  GtkPaint_GtkWidget = 2;
220
221type
222  TLMGtkPaintData = class
223  public
224    Widget: PGtkWidget;
225    State: integer; // see GtkPaint_xxx
226    RepaintAll: boolean;
227    Rect: TRect;
228  end;
229
230  TLMGtkPaint = record
231    Msg: Cardinal;
232    Data: TLMGtkPaintData; // WParam
233    Unused: LPARAM;       // LParam
234    Result: LRESULT;
235  end;
236
237var
238  CurrentSentPaintMessageTarget: TObject;
239
240const
241  TARGET_STRING = 1;
242  TARGET_ROOTWIN = 2;
243
244// clipboard
245type
246  TClipboardEventData = record
247    TimeID: guint32;
248    Waiting: boolean;
249    Stopping: boolean;
250    Data: TGtkSelectionData;
251  end;
252  PClipboardEventData = ^TClipboardEventData;
253
254  TGtkClipboardFormat = (
255    gfCLASS, gfCOMPOUND_TEXT, gfDELETE, gfFILE_NAME, gfHOST_NAME, gfLENGTH,
256    gfMULTIPLE, gfNAME, gfOWNER_OS, gfPROCESS, gfSTRING, gfTARGETS, gfTEXT,
257    gfTIMESTAMP, gfUSER, gfUTF8_STRING);
258
259  TGtkClipboardFormats = set of TGtkClipboardFormat;
260
261const
262  GtkClipboardFormatName: array[TGtkClipboardFormat] of string = (
263      'CLASS', 'COMPOUND_TEXT', 'DELETE', 'FILE_NAME', 'HOST_NAME', 'LENGTH',
264      'MULTIPLE', 'NAME', 'OWNER_OS', 'PROCESS', 'STRING', 'TARGETS', 'TEXT',
265      'TIMESTAMP', 'USER', 'UTF8_STRING'
266    );
267
268{off $DEFINE DEBUG_CLIPBOARD}
269var
270  // All clipboard events are handled by only one widget - the ClipboardWidget
271  // This widget is typically the main form
272  ClipboardWidget: PGtkWidget;
273  // each selection has an gtk identifier (an atom)
274  ClipboardTypeAtoms: array[TClipboardType] of TGdkAtom;
275  // each active request will procduce an TClipboardEventData stored in this list
276  ClipboardSelectionData: TFPList; // list of PClipboardEventData
277  // each selection can have an user defined handler (normally set by the lcl)
278  ClipboardHandler: array[TClipboardType] of TClipboardRequestEvent;
279  // boolean array, telling what gtk format is automatically supported by
280  // gtk interface and not by the program (the lcl)
281  ClipboardExtraGtkFormats: array[TClipboardType,TGtkClipboardFormat] of boolean;
282  // lists of supported targets
283  ClipboardTargetEntries: array[TClipboardType] of PGtkTargetEntry;
284  ClipboardTargetEntryCnt: array[TClipboardType] of integer;
285
286  // each main widget that was resized by the gtk is stored here
287  // (hasharray of PGtkWidget)
288  FWidgetsResized: TDynHashArray;
289  // each fixed widget that was resized by the gtk is stored here
290  // (hasharray of PGtkWidget)
291  FFixWidgetsResized: TDynHashArray;
292  // each widget that should be to the LCL bounds is stored here
293  // (hasharray of PGtkWidget)
294  FWidgetsWithResizeRequest: TDynHashArray; // hasharray of PGtkWidget
295
296const
297  aGtkJustification: array[TAlignment] of TGTKJustification =
298  (
299{taLeftJustify } GTK_JUSTIFY_LEFT,
300{taRightJustify} GTK_JUSTIFY_RIGHT,
301{taCenter      } GTK_JUSTIFY_CENTER
302  );
303
304  aGtkSelectionMode: array[Boolean] of TGtkSelectionMode =
305  (
306    GTK_SELECTION_SINGLE,
307    GTK_SELECTION_EXTENDED
308  );
309
310  aGtkShadowFromBevel: array[TStatusPanelBevel] of TGtkShadowType =
311  (
312{ pbNone    } GTK_SHADOW_NONE,
313{ pbLowered } GTK_SHADOW_IN,
314{ pbRaised  } GTK_SHADOW_OUT
315  );
316
317  { file dialog }
318
319type
320  PFileSelHistoryEntry = ^TFileSelHistoryEntry;
321  TFileSelHistoryEntry = record
322    Filename: PChar; // UTF-8 encoding
323    MenuItem: PGtkWidget;
324  end;
325
326  { TFileSelFilterEntry }
327
328  TFileSelFilterEntry = class
329  public
330    Description: PChar;
331    Mask: PChar;
332    FilterIndex: integer;
333    MenuItem: PGtkWidget;
334    constructor Create(const ADescription, AMask: string);
335    destructor Destroy; override;
336  end;
337
338  { Menu }
339
340type
341  TCheckMenuItemDrawProc =
342    procedure (check_menu_item:PGtkCheckMenuItem; area:PGdkRectangle); cdecl;
343
344  TMenuSizeRequestProc =
345    procedure (widget:PGtkWidget; requisition:PGtkRequisition); cdecl;
346
347const
348  OldCheckMenuItemDrawProc: TCheckMenuItemDrawProc = nil;
349  OldMenuSizeRequestProc: TMenuSizeRequestProc = nil;
350  OldCheckMenuItemToggleSize: integer = 0;
351
352
353  { Accelerators }
354type
355  PAcceleratorKey = ^TAcceleratorKey;
356  TAcceleratorKey = record
357    Key: guint;
358    Mods: TGdkModifierType;
359    Signal: string;
360    Realized: boolean;
361  end;
362
363  // modal windows
364var
365  ModalWindows: TFPList; // list of PGtkWindow
366
367
368// gtk object data names
369const
370  odnScrollArea = 'scroll_area'; // the gtk_scrolled_window of a widget
371                                 // used by TCustomForm and TScrollbox
372  odnScrollBar = 'ScrollBar'; // Gives the scrollbar the tgtkrange is belonging to
373                              // Used by TScrollbar, TScrollbox and TWinApiWidget
374  odnScrollBarLastPos = 'ScrollBarLastPos';
375
376const
377  CallBackDefaultReturn = false;
378
379
380// font
381var
382  AvgFontCharsBuffer: array[#32..#127] of char;
383  AvgFontCharsBufLen: integer;
384
385type
386  Charsetstr=string[15];
387  PCharSetEncodingRec=^TCharSetEncodingRec;
388  TCharSetEncodingRec=record
389    CharSet: byte;              // winapi charset value
390    CharSetReg:CharSetStr;      // Charset Registry Pattern
391    CharSetCod:CharSetStr;      // Charset Encoding Pattern
392    EnumMap: boolean;           // this mapping is meanful when enumerating fonts?
393    CharsetRegPart: boolean;    // is CharsetReg a partial pattern?
394    CharsetCodPart: boolean;    // is CharsetCod a partial pattern?
395  end;
396
397var
398  CharSetEncodingList: TList;
399
400  procedure AddCharsetEncoding(CharSet: Byte; CharSetReg, CharSetCod: CharSetStr;
401    ToEnum:boolean=true; CrPart:boolean=false; CcPart:boolean=false);
402  procedure ClearCharsetEncodings;
403  procedure CreateDefaultCharsetEncodings;
404
405
406implementation
407
408
409procedure InternalInit;
410var
411  c: char;
412begin
413  for c:=Low(AvgFontCharsBuffer) to High(AvgFontCharsBuffer) do
414    AvgFontCharsBuffer[c]:=c;
415  AvgFontCharsBufLen:=ord(High(AvgFontCharsBuffer))-ord(Low(AvgFontCharsBuffer));
416  AvgFontCharsBuffer[high(AvgFontCharsBuffer)]:=#0;
417  ModalWindows:=nil;
418  UseTransientForModalWindows:=true;
419  UpdatingTransientWindows:=false;
420  CurrentSentPaintMessageTarget:=nil;
421end;
422
423procedure ResetDefaultIMContext;
424begin
425  if (im_context<>nil) then
426  begin
427    gtk_im_context_reset(im_context);
428    gtk_im_context_set_client_window(im_context,nil);
429  end;
430  im_context_widget:=nil;
431  im_context_use:=False;
432  im_context_skipdelete:=True;
433  im_context_string:='';
434  im_context_string_commit:='';
435end;
436
437{$IFDEF WITH_GTK2_IM}
438procedure IM_Context_Set_Cursor_Pos(X, Y: gint);
439var
440  CurPos: TGdkRectangle;
441begin
442  CurPos.x:=X;
443  CurPos.y:=Y;
444  CurPos.width:=0; // fix invalid candidate window position
445  CurPos.height:=0;
446  gtk_im_context_set_cursor_location(im_context,@CurPos);
447end;
448{$ENDIF}
449
450procedure AddCharsetEncoding(CharSet: Byte; CharSetReg, CharSetCod: CharSetStr;
451  ToEnum:boolean=true; CrPart:boolean=false; CcPart:boolean=false);
452var
453  Rec: PCharsetEncodingRec;
454begin
455   New(Rec);
456   Rec^.Charset := CharSet;
457   Rec^.CharsetReg := CharSetReg;
458   Rec^.CharsetCod := CharSetCod;
459   Rec^.EnumMap := ToEnum;
460   Rec^.CharsetRegPart := CrPart;
461   Rec^.CharsetCodPart := CcPart;
462   CharSetEncodingList.Add(Rec);
463end;
464
465procedure ClearCharsetEncodings;
466var
467  Rec: PCharsetEncodingRec;
468  i: Integer;
469begin
470  for i:=0 to CharsetEncodingList.Count-1 do begin
471    Rec := CharsetEncodingList[i];
472    if Rec<>nil then
473      Dispose(Rec);
474  end;
475  CharsetEncodingList.Clear;
476end;
477
478procedure CreateDefaultCharsetEncodings;
479begin
480  ClearCharsetEncodings;
481
482  AddCharsetEncoding(ANSI_CHARSET,        'iso8859',  '1',    false);
483  AddCharsetEncoding(ANSI_CHARSET,        'iso8859',  '3',    false);
484  AddCharsetEncoding(ANSI_CHARSET,        'iso8859',  '15',   false);
485  AddCharsetEncoding(ANSI_CHARSET,        'ansi',     '0');
486  AddCharsetEncoding(ANSI_CHARSET,        '*',        'cp1252');
487  AddCharsetEncoding(ANSI_CHARSET,        'iso8859',  '*');
488  AddCharsetEncoding(DEFAULT_CHARSET,     '*',        '*');
489  AddCharsetEncoding(SYMBOL_CHARSET,      '*',        'fontspecific');
490  AddCharsetEncoding(MAC_CHARSET,         '*',        'cpxxxx'); // todo
491  AddCharsetEncoding(SHIFTJIS_CHARSET,    'jis',      '0',    true, true);
492  AddCharsetEncoding(SHIFTJIS_CHARSET,    '*',        'cp932');
493  AddCharsetEncoding(HANGEUL_CHARSET,     '*',        'cp949');
494  AddCharsetEncoding(JOHAB_CHARSET,       '*',        'cp1361');
495  AddCharsetEncoding(GB2312_CHARSET,      'gb2312',   '0',    true, true);
496  AddCharsetEncoding(CHINESEBIG5_CHARSET, 'big5',     '0',    true, true);
497  AddCharsetEncoding(CHINESEBIG5_CHARSET, '*',        'cp950');
498  AddCharsetEncoding(GREEK_CHARSET,       'iso8859',  '7');
499  AddCharsetEncoding(GREEK_CHARSET,       '*',        'cp1253');
500  AddCharsetEncoding(TURKISH_CHARSET,     'iso8859',  '9');
501  AddCharsetEncoding(TURKISH_CHARSET,     '*',        'cp1254');
502  AddCharsetEncoding(VIETNAMESE_CHARSET,  '*',        'cp1258');
503  AddCharsetEncoding(HEBREW_CHARSET,      'iso8859',  '8');
504  AddCharsetEncoding(HEBREW_CHARSET,      '*',        'cp1255');
505  AddCharsetEncoding(ARABIC_CHARSET,      'iso8859',  '6');
506  AddCharsetEncoding(ARABIC_CHARSET,      '*',        'cp1256');
507  AddCharsetEncoding(BALTIC_CHARSET,      'iso8859',  '13');
508  AddCharsetEncoding(BALTIC_CHARSET,      'iso8859',  '4');  // northern europe
509  AddCharsetEncoding(BALTIC_CHARSET,      'iso8859',  '14'); // CELTIC_CHARSET
510  AddCharsetEncoding(BALTIC_CHARSET,      '*',        'cp1257');
511  AddCharsetEncoding(RUSSIAN_CHARSET,     'iso8859',  '5');
512  AddCharsetEncoding(RUSSIAN_CHARSET,     'koi8',     '*');
513  AddCharsetEncoding(RUSSIAN_CHARSET,     '*',        'cp1251');
514  AddCharsetEncoding(THAI_CHARSET,        'iso8859',  '11');
515  AddCharsetEncoding(THAI_CHARSET,        'tis620',   '*',  true, true);
516  AddCharsetEncoding(THAI_CHARSET,        '*',        'cp874');
517  AddCharsetEncoding(EASTEUROPE_CHARSET,  'iso8859',  '2');
518  AddCharsetEncoding(EASTEUROPE_CHARSET,  '*',        'cp1250');
519  AddCharsetEncoding(OEM_CHARSET,         'ascii',    '0');
520  AddCharsetEncoding(OEM_CHARSET,         'iso646',   '*',  true, true);
521  AddCharsetEncoding(FCS_ISO_10646_1,     'iso10646', '1');
522  AddCharsetEncoding(FCS_ISO_8859_1,      'iso8859',  '1');
523  AddCharsetEncoding(FCS_ISO_8859_2,      'iso8859',  '2');
524  AddCharsetEncoding(FCS_ISO_8859_3,      'iso8859',  '3');
525  AddCharsetEncoding(FCS_ISO_8859_4,      'iso8859',  '4');
526  AddCharsetEncoding(FCS_ISO_8859_5,      'iso8859',  '5');
527  AddCharsetEncoding(FCS_ISO_8859_6,      'iso8859',  '6');
528  AddCharsetEncoding(FCS_ISO_8859_7,      'iso8859',  '7');
529  AddCharsetEncoding(FCS_ISO_8859_8,      'iso8859',  '8');
530  AddCharsetEncoding(FCS_ISO_8859_9,      'iso8859',  '9');
531  AddCharsetEncoding(FCS_ISO_8859_10,     'iso8859',  '10');
532  AddCharsetEncoding(FCS_ISO_8859_15,     'iso8859',  '15');
533end;
534
535{ TFileSelFilterEntry }
536
537constructor TFileSelFilterEntry.Create(const ADescription, AMask: string);
538begin
539  Description:=StrAlloc(length(ADescription)+1);
540  StrPCopy(Description, ADescription);
541  Mask:=StrAlloc(length(AMask)+1);
542  StrPCopy(Mask, AMask);
543end;
544
545destructor TFileSelFilterEntry.Destroy;
546begin
547  StrDispose(Description);
548  Description:=nil;
549  StrDispose(Mask);
550  Mask:=nil;
551  inherited Destroy;
552end;
553
554initialization
555  InternalInit;
556
557end.
558