1{
2                  ----------------------------------
3                  gtk2proc.pp  - gtk 2 interface procs
4                  ----------------------------------
5
6 This unit contains procedures/functions needed for the gtk 2 <-> LCL interface
7}
8{
9 *****************************************************************************
10  This file is part of the Lazarus Component Library (LCL)
11
12  See the file COPYING.modifiedLGPL.txt, included in this distribution,
13  for details about the license.
14 *****************************************************************************
15}
16unit Gtk2Proc;
17
18{$mode objfpc}{$H+}
19
20interface
21
22{$I gtk2defines.inc}
23
24uses
25  {$IFDEF windows}
26    // use windows unit first,
27    // if not, Rect and Point are taken from the windows unit instead of classes.
28    Windows, // needed for keyboard handling
29  {$endif}
30  {$IFDEF Unix}
31    unix,
32  {$ENDIF}
33  SysUtils, Classes,
34  {$IFDEF HasX}
35    XAtom, // clipboard
36    X, XLib, // Font retrieval and Keyboard handling
37  {$ENDIF}
38  InterfaceBase,
39  // gtk2
40    glib2, gdk2pixbuf, gdk2, gtk2, Pango,
41    {$ifdef HasGdk2X}
42    gdk2x,
43    {$endif}
44  // Other units
45  Math, // Math after gtk to get the correct Float type
46  Types,
47  // LCL
48  LMessages, LCLProc, LCLIntf, LCLType, Graphics,
49  LResources, Controls, Forms, Buttons, Menus, StdCtrls, ComCtrls, ExtCtrls,
50  Dialogs, ExtDlgs, ImgList, LCLMessageGlue,
51  // LazUtils
52  FileUtil, LazFileUtils, LazStringUtils, LazUtilities, LazLoggerBase, LazTracer,
53  GraphType, Masks, LazUTF8, DynHashArray,
54  // Gtk2
55  Gtk2FontCache, Gtk2Globals, Gtk2Def, Gtk2Extra, {%H-}Gtk2Debug;
56
57const
58  GtkListItemGtkListTag = 'GtkList';
59  GtkListItemLCLListTag = 'LCLList';
60
61
62type
63  PPWaitHandleEventHandler = ^PWaitHandleEventHandler;
64  PWaitHandleEventHandler = ^TWaitHandleEventHandler;
65  TWaitHandleEventHandler = record
66    Handle: THandle;
67    GIOChannel: pgiochannel;
68    GSourceID: guint;
69    UserData: PtrInt;
70    OnEvent: TWaitHandleEvent;
71    PrevHandler: PWaitHandleEventHandler;
72    NextHandler: PWaitHandleEventHandler;
73  end;
74
75{$ifdef UNIX}
76  PPChildSignalEventHandler = ^PChildSignalEventHandler;
77  PChildSignalEventHandler = ^TChildSignalEventHandler;
78  TChildSignalEventHandler = record
79    PID: TPid;
80    UserData: PtrInt;
81    OnEvent: TChildExitEvent;
82    PrevHandler: PChildSignalEventHandler;
83    NextHandler: PChildSignalEventHandler;
84  end;
85
86{$endif}
87
88var
89  GTKAPIWidget_Type: GType = 0;
90
91// GTKCallback.inc headers
92procedure EventTrace(const {%H-}TheMessage: string; {%H-}data: pointer);
93function gtkNoteBookCloseBtnClicked({%H-}Widget: PGtkWidget;
94  Data: Pointer): GBoolean; cdecl;
95function gtkRealizeCB(Widget: PGtkWidget; Data: Pointer): GBoolean; cdecl;
96function gtkRealizeAfterCB(Widget: PGtkWidget; Data: Pointer): GBoolean; cdecl;
97function gtkshowCB( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
98function gtkHideCB( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
99function gtkactivateCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
100function gtkchangedCB( widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
101procedure gtkchanged_editbox_delete_text(Widget: PGtkWidget;
102  {%H-}AStartPos, {%H-}AEndPos: gint; {%H-}data: gPointer); cdecl;
103procedure gtkchanged_editbox_insert_text(Widget: PGtkWidget; {%H-}ANewText: PgChar;
104  {%H-}ANewTextLength: gint; {%H-}APosition: pgint; {%H-}data: gPointer); cdecl;
105function gtkchanged_editbox( widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
106function gtkchanged_editbox_delete({%H-}widget: PGtkWidget;
107  {%H-}AType: TGtkDeleteType; {%H-}APos: gint; {%H-}data: gPointer): GBoolean; cdecl;
108function gtkdaychanged(Widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
109function gtktoggledCB( widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
110function gtkpaste_editbox(Widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
111
112function gtkExposeEvent(Widget: PGtkWidget; Event: PGDKEventExpose;
113  Data: gPointer): GBoolean; cdecl;
114function gtkExposeEventAfter(Widget: PGtkWidget; Event: PGDKEventExpose;
115  Data: gPointer): GBoolean; cdecl;
116function gtkfrmactivateAfter( widget: PGtkWidget; {%H-}Event: PgdkEventFocus;
117  data: gPointer): GBoolean; cdecl;
118function gtkfrmdeactivateAfter( widget: PGtkWidget; {%H-}Event: PgdkEventFocus;
119  data: gPointer): GBoolean; cdecl;
120
121function GTKKeyPress(Widget: PGtkWidget; Event: pgdkeventkey;
122  Data: gPointer): GBoolean; cdecl;
123function GTKKeyPressAfter(Widget: PGtkWidget; Event: pgdkeventkey;
124  Data: gPointer): GBoolean; cdecl;
125function GTKKeyRelease(Widget: PGtkWidget; Event: pgdkeventkey;
126  Data: gPointer): GBoolean; cdecl;
127function GTKKeyReleaseAfter(Widget: PGtkWidget; Event: pgdkeventkey;
128  Data: gPointer): GBoolean; cdecl;
129
130function GTKFocusCB(widget: PGtkWidget; {%H-}event:PGdkEventFocus;
131                    data: gPointer): GBoolean; cdecl;
132function GTKKillFocusCB({%H-}widget: PGtkWidget; {%H-}event:PGdkEventFocus;
133                        {%H-}data: gPointer): GBoolean; cdecl;
134function GTKKillFocusCBAfter(widget: PGtkWidget; {%H-}event:PGdkEventFocus;
135                             data: gPointer): GBoolean; cdecl;
136function gtkdestroyCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
137procedure DestroyWindowFromPointCB(Widget: PGtkWidget; {%H-}data: gPointer); cdecl;
138function gtkdeleteCB({%H-}widget: PGtkWidget; {%H-}event: PGdkEvent;
139                     data: gPointer): GBoolean; cdecl;
140function gtkresizeCB({%H-}widget: PGtkWidget; {%H-}data: gPointer): GBoolean; cdecl;
141function gtkMonthChanged({%H-}Widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
142procedure DeliverMouseMoveMessage({%H-}Widget:PGTKWidget; Event: PGDKEventMotion;
143                                  AWinControl: TWinControl);
144
145function gtkMotionNotify(Widget:PGTKWidget; Event: PGDKEventMotion;
146                         Data: gPointer): GBoolean; cdecl;
147function GTKMotionNotifyAfter(widget:PGTKWidget; event: PGDKEventMotion;
148                              data: gPointer): GBoolean; cdecl;
149
150function DeliverMouseDownMessage({%H-}widget: PGtkWidget; event: pgdkEventButton;
151                                  AWinControl: TWinControl): PtrInt;
152
153function gtk2ScrollBarMouseBtnPress({%H-}widget: PGtkWidget; {%H-}event: pgdkEventButton;
154  {%H-}data: gPointer): GBoolean; cdecl;
155
156function gtk2ScrollBarMouseBtnRelease({%H-}widget: PGtkWidget; {%H-}event: pgdkEventButton;
157  {%H-}data: gPointer): GBoolean; cdecl;
158
159
160function gtkMouseBtnPress(widget: PGtkWidget; event: pgdkEventButton;
161                          data: gPointer): GBoolean; cdecl;
162function gtkMouseBtnPressAfter(widget: PGtkWidget; event: pgdkEventButton;
163                               data: gPointer): GBoolean; cdecl;
164function ControlGetsMouseUpBefore({%H-}AControl: TControl): boolean;
165function DeliverMouseUpMessage(widget: PGtkWidget; event: pgdkEventButton;
166                                AWinControl: TWinControl): boolean;
167function gtkMouseBtnRelease(widget: PGtkWidget; event: pgdkEventButton;
168                            data: gPointer): GBoolean; cdecl;
169function gtkMouseBtnReleaseAfter(widget: PGtkWidget; event: pgdkEventButton;
170                                 data: gPointer): GBoolean; cdecl;
171function gtkclickedCB( widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
172
173function gtkEnterCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
174function gtkLeaveCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
175function gtksize_allocateCB(widget: PGtkWidget; {%H-}size :pGtkAllocation;
176  data: gPointer): GBoolean; cdecl;
177function gtksize_allocate_client({%H-}widget: PGtkWidget; {%H-}size :pGtkAllocation;
178  data: gPointer): GBoolean; cdecl;
179function gtkconfigureevent( widget: PGtkWidget; event: PgdkEventConfigure;
180  data: gPointer): GBoolean; cdecl;
181function gtkInsertText(widget: PGtkWidget; char: pChar; NewTextLength:
182                     Integer; Position: pgint; data: gPointer): GBoolean; cdecl;
183function gtkSetEditable( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
184function gtkMoveWord( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
185function gtkMovePage( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
186function gtkMoveToRow( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
187function gtkMoveToColumn( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
188function gtkKillChar( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
189function gtkKillWord( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
190function gtkKillLine( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
191function gtkCutToClip( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
192function gtkCopyToClip( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
193function gtkPasteFromClip( {%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
194function gtkValueChanged({%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
195function gtkTimerCB(Data: gPointer): gBoolean; cdecl;
196function gtkFocusInNotifyCB (widget: PGtkWidget; {%H-}event: PGdkEvent;
197  data: gpointer): GBoolean; cdecl;
198function gtkFocusOutNotifyCB (widget: PGtkWidget; {%H-}event: PGdkEvent;
199  data: gpointer): GBoolean; cdecl;
200
201// PGtkAdjustment cb
202function GTKHScrollCB(Adjustment: PGTKAdjustment; data: GPointer): GBoolean; cdecl;
203function GTKVScrollCB(Adjustment: PGTKAdjustment;
204  data: GPointer): GBoolean; cdecl;
205
206// PGtkRange cb
207function Gtk2RangeScrollCB(ARange: PGtkRange; AScrollType: TGtkScrollType;
208  AValue: gdouble; AWidgetInfo: PWidgetInfo): gboolean; cdecl;
209function Gtk2RangeScrollPressCB(Widget: PGtkWidget;
210  {%H-}Event: PGdkEventButton; {%H-}Data: gPointer): gboolean; cdecl;
211function Gtk2RangeScrollReleaseCB(Widget: PGtkWidget;
212  {%H-}Event: PGdkEventButton; {%H-}Data: gPointer): gboolean; cdecl;
213function Gtk2RangeUbuntuScrollCB(Adjustment: PGTKAdjustment; data: GPointer): GBoolean; cdecl;
214
215procedure Gtk2RangeValueChanged(ARange: PGTKRange; data: GPointer); cdecl;
216
217function Gtk2ScrolledWindowScrollCB(AScrollWindow: PGtkScrolledWindow;
218  AEvent: PGdkEventScroll; AWidgetInfo: PWidgetInfo): gboolean; cdecl;
219function GTKCheckMenuToggeledCB(AMenuItem: PGTKCheckMenuItem;
220                                AData: gPointer): GBoolean; cdecl;
221function GTKKeySnooper({%H-}Widget: PGtkWidget; Event: PGdkEventKey;
222  FuncData: gPointer): gInt; cdecl;
223function gtkYearChanged({%H-}Widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
224procedure GtkDragDataReceived({%H-}widget:PGtkWidget; context:PGdkDragContext;
225  {%H-}x:gint; {%H-}y:gint; selection_data:PGtkSelectionData; {%H-}info:guint; time:guint; Data: gPointer);cdecl;
226
227
228// clipboard
229procedure ClipboardSelectionReceivedHandler({%H-}TargetWidget: PGtkWidget;
230  SelectionData: PGtkSelectionData; TimeID: guint32; {%H-}Data: Pointer); cdecl;
231procedure ClipboardSelectionRequestHandler({%H-}TargetWidget: PGtkWidget;
232  SelectionData: PGtkSelectionData; {%H-}Info: cardinal; {%H-}TimeID: cardinal;
233  {%H-}Data: Pointer); cdecl;
234function ClipboardSelectionLostOwnershipHandler({%H-}TargetWidget: PGtkWidget;
235  EventSelection: PGdkEventSelection;  {%H-}Data: Pointer): cardinal; cdecl;
236{$IFDEF EventTrace}
237procedure GTKStyleChanged(Widget: PGtkWidget; previous_style :
238  PGTKStyle; Data: Pointer); cdecl;
239procedure GTKStyleChangedAfter(Widget: PGtkWidget; previous_style : PGTKStyle;
240  Data: Pointer); cdecl;
241{$ENDIF}
242function gtkListBoxSelectionChangedAfter(widget: PGtkWidget;
243                                      data: gPointer): GBoolean; cdecl;
244
245// drag callbacks
246function edit_drag_data_received({%H-}widget: pgtkWidget;
247             Context: pGdkDragContext;
248             {%H-}X: Integer;
249             {%H-}Y: Integer;
250             seldata: pGtkSelectionData;
251             {%H-}info: Integer;
252             time: Integer;
253                                  data: pointer): GBoolean; cdecl;
254function edit_source_drag_data_get({%H-}widget: pgtkWidget;
255             {%H-}Context: pGdkDragContext;
256             Selection_data: pGtkSelectionData;
257             info: Integer;
258             {%H-}time: Integer;
259                                  data: pointer): GBoolean; cdecl;
260function Edit_source_drag_data_delete ({%H-}widget: pGtkWidget;
261                   {%H-}context: pGdkDragContext;
262                   {%H-}data: gpointer): gBoolean ; cdecl;
263
264// combobox callbacks
265function gtkComboBoxShowAfter({%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
266function gtkComboBoxHideAfter({%H-}widget: PGtkWidget; data: gPointer): GBoolean; cdecl;
267
268// notebook callbacks
269function PageIconWidgetExposeAfter(Widget: PGtkWidget; Event: PGDKEventExpose;
270  Data: gPointer): GBoolean; cdecl;
271
272// callbacks for menu items
273procedure DrawMenuItemIcon(MenuItem: PGtkCheckMenuItem; Area: PGdkRectangle); cdecl;
274procedure MenuSizeRequest(widget:PGtkWidget; requisition:PGtkRequisition); cdecl;
275
276//==============================================================================
277type
278  TDestroyConnectedWidgetCB = procedure(Widget: PGtkWidget;
279                                      CheckIfDestroying: boolean) of object;
280var
281  DestroyConnectedWidgetCB: TDestroyConnectedWidgetCB; // set by the TGtkWidgetSet
282
283//==============================================================================
284// functions
285
286function RectFromGdkRect(const AGdkRect: TGdkRectangle): TRect;
287function GdkRectFromRect(const R: TRect): TGdkRectangle;
288function AlignToGtkAlign(Align: TAlignment): gfloat;
289function GtkScrollTypeToScrollCode(ScrollType: TGtkScrollType): LongWord;
290function Gtk2TranslateScrollStyle(const SS:TScrollStyle):TPoint;
291
292// debugging
293function GtkWidgetIsA(Widget: PGtkWidget; AType: TGtkType): boolean;
294function GetWidgetClassName(Widget: PGtkWidget): string;
295function GetWidgetDebugReport(Widget: PGtkWidget): string;
296function GetWindowDebugReport(AWindow: PGDKWindow): string;
297function GetStyleDebugReport(AStyle: PGTKStyle): string;
298function GetRCStyleDebugReport(AStyle: PGtkRcStyle): string;
299function GetPangoDescriptionReport(Desc: PPangoFontDescription): string;
300function WidgetFlagsToString(Widget: PGtkWidget): string;
301function GdkColorToStr(Color: PGDKColor): string;
302function GetWidgetStyleReport(Widget: PGtkWidget): string;
303procedure BeginGDKErrorTrap;
304procedure EndGDKErrorTrap;
305function dbgGRect(const ARect: PGDKRectangle): string; overload;
306
307
308// gtk resources
309procedure Set_RC_Name(Sender: TObject; AWidget: PGtkWidget);
310
311// messages
312function DeliverPostMessage(const Target: Pointer; var TheMessage): GBoolean;
313function DeliverMessage(const Target: Pointer; var AMessage): PtrInt;
314
315// PChar
316//function CreatePChar(const s: string): PChar;
317function FindChar(c: char; p:PChar; Max: integer): integer;
318function FindLineLen(p:PChar; Max: integer): integer;
319
320// flags
321function WidgetIsDestroyingHandle(Widget: PGtkWidget): boolean;
322procedure SetWidgetIsDestroyingHandle(Widget: PGtkWidget);
323function ComponentIsDestroyingHandle(AWinControl: TWinControl): boolean;
324function LockOnChange(GtkObject: PGtkObject; LockOffset: integer): integer;
325procedure InvalidateLastWFPResult(AControl: TWinControl; const ABounds: TRect);
326
327// glib
328procedure MoveGListLinkBehind(First, Item, After: PGList);
329procedure MoveGListLink(First: PGList; FromIndex, ToIndex: integer);
330
331// properties
332function ObjectToGTKObject(const AnObject: TObject): PGtkObject;
333function GetMainWidget(const Widget: Pointer): Pointer;
334procedure SetMainWidget(const ParentWidget, ChildWidget: Pointer);
335function GetFixedWidget(const Widget: Pointer): Pointer;
336procedure SetFixedWidget(const ParentWidget, FixedWidget: Pointer);
337function GetControlWindow(Widget: Pointer): PGDKWindow;
338
339function CreateWidgetInfo(const AWidget: Pointer): PWidgetInfo;
340function CreateWidgetInfo(const AWidget: Pointer; const AObject: TObject;
341                          const AParams: TCreateParams): PWidgetInfo;
342function GetWidgetInfo(const AWidget: Pointer): PWidgetInfo;
343function GetOrCreateWidgetInfo(const AWidget: Pointer): PWidgetInfo;
344procedure FreeWidgetInfo(AWidget: Pointer);
345
346procedure DestroyWidget(Widget: PGtkWidget);
347procedure SetLCLObject(const Widget: Pointer; const AnObject: TObject);
348function GetLCLObject(const Widget: Pointer): TObject;
349function GetNearestLCLObject(Widget: PGtkWidget): TObject;
350function GetWinControlWidget(Child: PGtkWidget): PGtkWidget;
351function GetWinControlFixedWidget(Child: PGtkWidget): PGtkWidget;
352function FindFixedChildListItem(ParentFixed: PGtkFixed; Child: PGtkWidget): PGList;
353function FindFixedLastChildListItem(ParentFixed: PGtkFixed): PGList;
354function GetFixedChildListWidget(Item: PGList): PGtkWidget;
355
356// fixed widgets
357function CreateFixedClientWidget(WithWindow: Boolean = true): PGTKWidget;
358procedure FixedMoveControl(Parent, Child: PGTKWidget; Left, Top: Longint);
359procedure FixedPutControl(Parent, Child: PGTKWidget; Left, Top: Longint);
360
361// forms
362procedure SetFormShowInTaskbar(AForm: TCustomForm; const AValue: TShowInTaskbar);
363procedure SetGtkWindowShowInTaskbar(AGtkWindow: PGtkWindow; Value: boolean);
364procedure SetWindowFullScreen(AForm: TCustomForm; const AValue: Boolean);
365procedure GrabKeyBoardToForm(AForm: TCustomForm);
366procedure ReleaseKeyBoardFromForm({%H-}AForm: TCustomForm);
367procedure GrabMouseToForm(AForm: TCustomForm);
368procedure ReleaseMouseFromForm({%H-}AForm: TCustomForm);
369procedure GtkWindowShowModal(AForm: TCustomForm; GtkWindow: PGtkWindow);
370
371// label
372procedure SetLabelAlignment(LabelWidget: PGtkLabel; const NewAlignment: TAlignment);
373
374// paint messages
375function DoDeliverPaintMessage(const Target: TObject; var PaintMsg: TLMPaint): PtrInt;
376function GtkPaintMessageToPaintMessage(var GtkPaintMsg: TLMGtkPaint;
377  FreeGtkPaintMsg: boolean): TLMPaint;
378procedure FinalizePaintMessage(Msg: PLMessage);
379procedure FinalizePaintTagMsg(Msg: PMsg);
380
381// region
382function RegionType(RGN: PGDKRegion): Longint;
383function CreateRectGDKRegion(const ARect: TRect): PGDKRegion;
384function GDKRegionAsString(RGN: PGDKRegion): string;
385
386// color
387procedure FreeGDIColor(GDIColor: PGDIColor);
388procedure AllocGDIColor({%H-}DC: hDC; GDIColor: PGDIColor);
389procedure BuildColorRefFromGDKColor(var GDIColor: TGDIColor);
390procedure SetGDIColorRef(var GDIColor: TGDIColor; NewColorRef: TColorRef);
391procedure EnsureGCColor(DC: hDC; ColorType: TDevContextsColorType;
392  IsSolidBrush, AsBackground: Boolean);
393procedure CopyGDIColor(var SourceGDIColor, DestGDIColor: TGDIColor);
394function AllocGDKColor(const AColor: TColorRef): TGDKColor;
395function TGDKColorToTColor(const value: TGDKColor): TColor;
396function TColortoTGDKColor(const value: TColor): TGDKColor;
397procedure UpdateSysColorMap(Widget: PGtkWidget; Lgs: TLazGtkStyle);
398function IsBackgroundColor(Color: TColor): boolean;
399
400procedure RealizeGDKColor(ColorMap: PGdkColormap; Color: PGDKColor);
401procedure RealizeGtkStyleColor(Style: PGTKStyle; Color: PGDKColor);
402function GetSysGCValues(Color: TColorRef; {%H-}ThemeWidget: PGtkWidget): TGDKGCValues;
403
404function GDKPixel2GDIRGB(Pixel: Longint; Visual: PGDKVisual;
405  Colormap: PGDKColormap): TGDIRGB;
406
407function CompareGDIColor(const Color1, Color2: TGDIColor): boolean;
408function CompareGDIFill(const Fill1, Fill2: TGdkFill): boolean;
409function CompareGDIBrushes(Brush1, Brush2: PGdiObject): boolean;
410
411// palette
412function PaletteIndexExists(Pal: PGDIObject; I: longint): Boolean;
413function PaletteRGBExists(Pal: PGDIObject; RGB: longint): Boolean;
414function PaletteAddIndex(Pal: PGDIObject; I, RGB: Longint): Boolean;
415function PaletteDeleteIndex(Pal: PGDIObject; I: Longint): Boolean;
416function PaletteIndexToRGB(Pal: PGDIObject; I: longint): longint;
417function PaletteRGBToIndex(Pal: PGDIObject; RGB: longint): longint;
418procedure InitializePalette(const Pal: PGDIObject; const Entries: PPaletteEntry;
419                            const RGBCount: Longint);
420function GetIndexAsKey(p: pointer): pointer;
421function GetRGBAsKey(p: pointer): pointer;
422
423
424// Keyboard functions
425type
426  TVKeyUTF8Char = array[0..7] of Char;
427  TVKeyInfo = record
428    KeyCode: array[Boolean] of Byte; // false is primary keycode, true the keycode of the other key when 2 keys exist (like CTRL or extended key)
429    KeySym: array[0..7] of Integer;
430    KeyChar: array[0..3] of TVKeyUTF8Char;
431  end;
432
433const
434  GdkKeymap: PGdkKeymap = nil;
435  GdkKeyMapChangedID: gulong = 0;
436procedure InitKeyboardTables;
437procedure DoneKeyboardTables;
438procedure DisconnectGdkKeymapChangedSignal;
439function GetVKeyInfo(const AVKey: Byte): TVKeyInfo;
440function GTKEventStateToShiftState(KeyState: LongWord): TShiftState;
441procedure gdk_event_key_get_string(Event: PGDKEventKey; var theString: Pointer);
442procedure gdk_event_key_set_string(Event: PGDKEventKey; const NewString: PChar);
443function gdk_event_get_type(Event: Pointer): TGdkEventType;
444
445function HandleGTKKeyUpDown(AWidget: PGtkWidget; AEvent: PGdkEventKey;
446  AData: gPointer; ABeforeEvent, AHandleDown: Boolean; const AEventName: PGChar
447  ) : GBoolean;
448
449// ----
450
451// common dialogs
452procedure StoreCommonDialogSetup(ADialog: TCommonDialog);
453procedure DestroyCommonDialogAddOns(ADialog: TCommonDialog);
454procedure PopulateFileAndDirectoryLists(FileSelection: PGtkFileSelection;
455                                        const Mask: string);
456
457// notebook
458function IsTTabControl(AWidget: PGtkWidget): Boolean;
459procedure UpdateNoteBookClientWidget(ANoteBook: TObject);
460function GetGtkNoteBookPageCount(ANoteBookWidget: PGtkNoteBook): integer;
461procedure UpdateNotebookPageTab(ANoteBook, APage: TObject);
462procedure UpdateNotebookTabFont(APage: TWinControl; AFont: TFont);
463
464// coordinate transformation
465function GetWidgetOrigin(TheWidget: PGtkWidget): TPoint;
466function GetWidgetClientOrigin(TheWidget: PGtkWidget): TPoint;
467function GetWidgetClientRect(TheWidget: PGtkWidget): TRect;
468function TranslateGdkPointToClientArea(SourceWindow: PGdkWindow;
469  SourcePos: TPoint;  DestinationWidget: PGtkWidget): TPoint;
470function SubtractScoll(AWidget: PGtkWidget; APosition: TPoint): TPoint;
471
472// mouse capturing
473function GetDefaultMouseCaptureWidget(Widget: PGtkWidget): PGtkWidget;
474procedure ReleaseMouseCapture;
475procedure ReleaseCaptureWidget(Widget : PGtkWidget);
476
477// window group
478function GetGtkWindowGroup(Widget: PGtkWidget): PGtkWindowGroup;
479
480const
481  // for now return the same value, in the future we may want to return an
482  // offset of -1 so we can use 0 as error (now crDefault = 0)
483  // In the current situation, a TCursor is passed as hCursor. Since both are
484  // ordinals, the compiler won't complain
485  PREDEFINED_CURSOR_OFFSET = 0; //-1;
486
487
488
489// designing
490type
491  TConnectSignalFlag = (
492    csfAfter,            // connect after signal
493    csfConnectRealize,   // auto connect realize handler
494    csfUpdateSignalMask, // extend signal mask for gdkwindow
495    csfDesignOnly        // mark signal as design only
496    );
497  TConnectSignalFlags = set of TConnectSignalFlag;
498
499  TDesignSignalType = (
500    dstUnknown,
501    dstMousePress,
502    dstMouseMotion,
503    dstMouseRelease,
504    dstExposeAfter
505    );
506  TDesignSignalTypes = set of TDesignSignalType;
507
508  TDesignSignalMask = longint;
509
510const
511  DesignSignalBefore: array[TDesignSignalType] of boolean = (
512    true,  // dstUnknown
513    true,  // dstMousePress
514    true,  // dstMouseMotion
515    true,  // dstMouseRelease
516    false  // dstExposeAfter
517    );
518
519  DesignSignalAfter: array[TDesignSignalType] of boolean = (
520    false, // dstUnknown
521    false, // dstMousePress
522    false, // dstMouseMotion
523    false, // dstMouseRelease
524    false  // dstExposeAfter
525    );
526
527  DesignSignalNames: array[TDesignSignalType] of PChar = (
528    '',
529    'button-press-event',
530    'motion-notify-event',
531    'button-release-event',
532    'expose-event'
533    );
534
535  DesignSignalFuncs: array[TDesignSignalType] of Pointer = (
536    nil,
537    @gtkMouseBtnPress,
538    @gtkMotionNotify,
539    @gtkMouseBtnRelease,
540    @gtkExposeEventAfter
541    );
542
543var
544  DesignSignalMasks: array[TDesignSignalType] of TDesignSignalMask;
545
546procedure InitDesignSignalMasks;
547function DesignSignalNameToType(Name: PChar; After: boolean): TDesignSignalType;
548function GetDesignSignalMask(Widget: PGtkWidget): TDesignSignalMask;
549procedure SetDesignSignalMask(Widget: PGtkWidget; NewMask: TDesignSignalMask);
550function GetDesignOnlySignalFlag(Widget: PGtkWidget;
551  DesignSignalType: TDesignSignalType): boolean;
552
553// signals
554// new signal procs, these will obsolete the old ones
555// new signalshandlers are attached locally in the new WSxxx classes
556// they also have PWidgetInfo as data (and not the TControl)
557// signals are now also handled dedicated and locally, so no case statements
558// anymore in signal handlers
559procedure SignalConnect(const AWidget: PGTKWidget; const ASignal: PChar;
560  const AProc: Pointer; const AInfo: PWidgetInfo);
561procedure SignalConnectAfter(const AWidget: PGTKWidget; const ASignal: PChar;
562  const AProc: Pointer; const AInfo: PWidgetInfo);
563
564// old signal procs
565// since they are used in attachcallbacks, and they pass TControl as data
566// One day attachsignals gets removed.
567procedure ConnectSignal(const AnObject: PGTKObject; const ASignal: PChar;
568  const ACallBackProc: Pointer; const ALCLObject: TObject;
569  const AReqSignalMask: TGdkEventMask; const ASFlags: TConnectSignalFlags);
570procedure ConnectSignal(const AnObject: PGTKObject; const ASignal: PChar;
571  const ACallBackProc: Pointer; const ALCLObject: TObject;
572  const AReqSignalMask: TGdkEventMask);
573procedure ConnectSignalAfter(const AnObject:PGTKObject; const ASignal: PChar;
574  const ACallBackProc: Pointer; const ALCLObject: TObject;
575  const AReqSignalMask: TGdkEventMask);
576procedure ConnectSignal(const AnObject:PGTKObject; const ASignal: PChar;
577  const ACallBackProc: Pointer; const ALCLObject: TObject);
578procedure ConnectSignalAfter(const AnObject:PGTKObject; const ASignal: PChar;
579  const ACallBackProc: Pointer; const ALCLObject: TObject);
580
581procedure ConnectInternalWidgetsSignals(AWidget: PGtkWidget;
582  AWinControl: TWinControl);
583
584//--
585
586// accelerators
587function Ampersands2Underscore(Src: PChar): PChar;
588function Ampersands2Underscore(const ASource: String): String;
589function EscapeUnderscores(const Str: String): String; inline;
590procedure LabelFromAmpersands(var AText, APattern: String; var AAccelChar: Char);
591
592function GetAccelGroup(const Widget: PGtkWidget;
593  CreateIfNotExists: boolean): PGTKAccelGroup;
594procedure SetAccelGroup(const Widget: PGtkWidget;
595  const AnAccelGroup: PGTKAccelGroup);
596procedure FreeAccelGroup(const Widget: PGtkWidget);
597procedure RegroupAccelerator(Widget: PGtkWidget);
598procedure ClearAccelKey(Widget: PGtkWidget);
599procedure Accelerate(Component: TComponent; const Widget: PGtkWidget;
600  const Key: guint; Mods: TGdkModifierType; const Signal: string);
601procedure Accelerate(Component: TComponent; const Widget: PGtkWidget;
602  const NewShortCut: TShortCut; const Signal: string);
603procedure ShareWindowAccelGroups(AWindow: PGtkWidget);
604procedure UnshareWindowAccelGroups(AWindow: PGtkWidget);
605
606// pixbuf
607procedure LoadPixbufFromLazResource(const ResourceName: string;
608  var Pixbuf: PGdkPixbuf);
609procedure LoadXPMFromLazResource(const ResourceName: string;
610  Window: PGdkWindow; var PixmapImg, PixmapMask: PGdkPixmap);
611
612function CreatePixbufFromDrawable(ASource: PGdkDrawable; AColorMap:PGdkColormap; AIncludeAplha: Boolean; ASrcX, ASrcY, ADstX, ADstY, AWidth, AHeight :longint): PGdkPixbuf;
613
614
615// pixmaps
616procedure SetGCRasterOperation(TheGC: PGDKGC; Rop: Cardinal);
617procedure MergeClipping(DestinationDC: TGtkDeviceContext; DestinationGC: PGDKGC;
618  X,Y,Width,Height: integer; ClipMergeMask: PGdkBitmap;
619  ClipMergeMaskX, ClipMergeMaskY: integer;
620  out NewClipMask: PGdkBitmap);
621function CreatePixbufFromImageAndMask(ASrc: PGdkDrawable; ASrcX, ASrcY, ASrcWidth,
622  ASrcHeight: integer; ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap): PGdkPixbuf;
623function ScalePixmapAndMask({%H-}AScaleGC: PGDKGC; AScaleMethod: TGdkInterpType;
624  ASrc: PGdkPixmap; ASrcX, ASrcY, ASrcWidth, ASrcHeight: integer;
625  ASrcColorMap: PGdkColormap; ASrcMask: PGdkBitmap;
626  ADstWidth, ADstHeight: Integer; FlipHorz, FlipVert: Boolean;
627  out ADst, ADstMask: PGdkPixmap): Boolean;
628
629// obsolete:
630function GetGdkImageBitsPerPixel(Image: PGdkImage): cardinal;
631function CreateGdkMaskBitmap(AImage, AMask: HBITMAP): PGdkBitmap;
632function CreateGdkMaskBitmap(AImageMask, AMask: PGdkBitmap): PGdkBitmap;
633function ExtractGdkBitmap(Bitmap: PGdkBitmap; const SrcRect: TRect): PGdkBitmap;
634procedure CheckGdkImageBitOrder(AImage: PGdkImage; AData: PByte; ADataCount: Integer);
635
636
637// menus
638function MENU_ITEM_CLASS(widget: PGtkWidget): PGtkMenuItemClass;
639function CHECK_MENU_ITEM_CLASS(widget: PGtkWidget): PGtkCheckMenuItemClass;
640procedure LockRadioGroupOnChange(RadioGroup: PGSList; const ADelta: Integer);
641procedure UpdateRadioGroupChecks(RadioGroup: PGSList);
642procedure UpdateInnerMenuItem(LCLMenuItem: TMenuItem; MenuItemWidget: PGtkWidget);
643procedure UpdateInnerMenuItem(LCLMenuItem: TMenuItem; MenuItemWidget: PGtkWidget;
644                              NewShortCut, ShortCutKey2: TShortCut);
645
646// statusbar
647function CreateStatusBarPanel({%H-}StatusBar: TObject; {%H-}Index: integer): PGtkWidget;
648procedure UpdateStatusBarPanels(StatusBar: TObject;
649                                StatusBarWidget: PGtkWidget);
650procedure UpdateStatusBarPanel(StatusBar: TObject; Index: integer;
651                               StatusPanelWidget: PGtkWidget);
652
653// list
654function gtkListGetSelectionMode(list: PGtkList): TGtkSelectionMode;cdecl;
655
656// sizing
657procedure SaveSizeNotification(Widget: PGtkWidget);
658procedure SaveClientSizeNotification(FixWidget: PGtkWidget);
659procedure SendSizeNotificationToLCL(aWidget: PGtkWidget);
660function CreateTopologicalSortedWidgets(HashArray: TDynHashArray): TFPList;
661procedure GetGTKDefaultWidgetSize(AWinControl: TWinControl;
662  var PreferredWidth, PreferredHeight: integer; {%H-}WithThemeSpace: Boolean);
663procedure SendCachedGtkResizeNotifications;
664procedure ResizeHandle(LCLControl: TWinControl);
665procedure SetWidgetSizeAndPosition(LCLControl: TWinControl);// for child controls
666procedure SetWindowSizeAndPosition(Window: PGtkWindow; AWinControl: TWinControl);// for top level control
667procedure GetWidgetRelativePosition(aWidget: PGtkWidget; out Left, Top: integer);
668procedure UnsetResizeRequest(Widget: PGtkWidget);
669procedure SetResizeRequest(Widget: PGtkWidget);
670function WidgetSizeIsEditable(Widget: PGtkWidget): boolean;
671
672// debug
673procedure ReportNotObsolete(const Texts: String);
674
675// screen
676function GetScreenWidthMM(GdkValue: boolean = false): integer;
677function GetScreenHeightMM(GdkValue: boolean = false): integer;
678
679// clipboard
680function WaitForClipboardAnswer(c: PClipboardEventData): boolean;
681function RequestSelectionData(ClipboardWidget: PGtkWidget;
682  ClipboardType: TClipboardType;  FormatID: PtrUInt): TGtkSelectionData;
683procedure FreeClipboardTargetEntries(ClipboardType: TClipboardType);
684function GdkAtomToStr(const Atom: TGdkAtom): string;
685
686// forms
687function CreateFormContents({%H-}AForm: TCustomForm;
688  var FormWidget: Pointer; AWidgetInfo: PWidgetInfo = nil): Pointer;
689
690// styles
691type
692  PStyleObject = ^TStyleObject;
693  TStyleObject = Record
694    Style: PGTKStyle;
695    Owner: PGtkWidget;  // The widget that we hold a reference to.
696    Widget: PGTKWidget; // This is the style widget.
697    FrameBordersValid: boolean;
698    FrameBorders: TRect;
699  end;
700
701var
702  StandardStyles: array[TLazGtkStyle] of PStyleObject;
703
704function IndexOfStyle(aStyle: TLazGtkStyle): integer;
705function IndexOfStyleWithName(const WName: String): integer;
706procedure ReleaseAllStyles;
707procedure ReleaseStyle(aStyle: TLazGtkStyle);
708procedure ReleaseStyleWithName(const WName: String);
709function GetStyle(aStyle: TLazGtkStyle): PGTKStyle;
710function GetStyleWithName(const WName: String): PGTKStyle;
711function GetStyleWidget(aStyle: TLazGtkStyle): PGTKWidget;
712function GetStyleWidgetWithName(const WName: String): PGTKWidget;
713function GetStyleGroupboxFrameBorders: TRect;
714function GetStyleNotebookFrameBorders: TRect;
715
716function GetStyleFormFrameBorders(WithMenu: boolean): TRect;
717
718procedure StyleFillRectangle(drawable: PGDKDrawable; GC: PGDKGC;
719                             Color: TColorRef; x, y, width, height: gint;
720                             AClipArea: PGdkRectangle);
721function StyleForegroundColor(Color: TColorRef; DefaultColor: PGDKColor): PGDKColor;
722procedure UpdateWidgetStyleOfControl(AWinControl: TWinControl);
723
724// fonts
725function LoadDefaultFont: TGtkIntfFont;
726function FontIsDoubleByteCharsFont(TheFont: TGtkIntfFont): boolean;
727function FontIsMonoSpaceFont(TheFont: TGtkIntfFont): boolean;
728
729function LoadDefaultFontDesc: PPangoFontDescription;
730
731procedure GetTextExtentIgnoringAmpersands(TheFont: TGtkIntfFont;
732  Str: PChar; StrLength: integer;
733  lbearing, rbearing, width, ascent, descent: Pgint);
734function GetDefaultFontName: string;
735{$IFDEF GTK2OLDENUMFONTFAMILIES}
736procedure FillScreenFonts(ScreenFonts: TStrings);
737{$ENDIF}
738function GetTextHeight(DCTextMetric: TDevContextTextMetric): integer;
739{$IFDEF HasX}
740function  XGetWorkarea(out ax,ay,awidth,aheight:gint): gint;
741{$ENDIF}
742
743
744// decoration
745function GetWindowDecorations(AForm: TCustomForm): Longint;
746function GetWindowFunction(AForm: TCustomForm): Longint;
747
748// functions for easier GTK2<->GTK1 Compatibility/Consistency  ---->
749function gtk_widget_get_xthickness(Style: PGTKStyle): gint; overload;
750function gtk_widget_get_ythickness(Style: PGTKStyle): gint; overload;
751
752function gtk_widget_get_xthickness(Widget: PGTKWidget): gint; overload;
753function gtk_widget_get_ythickness(Widget: PGTKWidget): gint; overload;
754function GetGtkContainerBorderWidth(Widget: PGtkContainer): gint;
755
756
757  function gtk_class_get_type(aclass: Pointer): TGtkType;
758
759  //we wrap our own versions to handle nil tests -->
760  function gtk_object_get_class(anobject: Pointer): Pointer;
761  function gtk_window_get_modal(window:PGtkWindow):gboolean;
762
763  //we wrap our own versions to do gtk1 style result = new region -->
764  function gdk_region_union_with_rect(region:PGdkRegion;
765                                      rect:PGdkRectangle): PGdkRegion;
766  function gdk_region_intersect(source1:PGdkRegion;
767                                source2:PGdkRegion): PGdkRegion;
768  function gdk_region_union(source1:PGdkRegion; source2:PGdkRegion): PGdkRegion;
769  function gdk_region_subtract(source1:PGdkRegion;
770                               source2:PGdkRegion): PGdkRegion;
771  function gdk_region_xor(source1:PGdkRegion; source2:PGdkRegion): PGdkRegion;
772
773  //mimic GDKFont Routines With Pango -->
774  procedure gdk_text_extents(TheFont: TGtkIntfFont;
775        Str: PChar; StrLength: integer;
776        lbearing, rbearing, width, ascent, descent: Pgint);
777
778
779{$ifdef HasX}
780// X functions
781function FormToX11Window(const AForm: TCustomForm): X.TWindow;
782{$endif}
783function FindFocusWidget(AWidget: PGtkWidget): PGtkWidget;
784
785const
786  gtkevent_window_state_event = 'window-state-event';
787
788function GTKWindowStateEventCB(widget: PGtkWidget;
789                               state: PGdkEventWindowState;
790                               data: gpointer): gboolean; cdecl;
791
792function gtkMouseWheelCB({%H-}widget: PGtkWidget; event: PGdkEventScroll;
793                         data: gPointer): GBoolean; cdecl;
794
795implementation
796
797uses
798  {$IFDEF StaticXinerama} Xinerama, {$ENDIF}
799  Gtk2WSPrivate, URIParser, Gtk2Int, Gtk2WinApiWindow;
800
801const
802  KCINFO_FLAG_SHIFT         = $01;
803  //KCINFO_FLAG_CTRL          = $02;
804  KCINFO_FLAG_ALTGR         = $04;
805  //KCINFO_FLAG_KEY_MASK      = $07;
806  KCINFO_FLAG_EXT           = $10; // extended key
807  //KCINFO_FLAG_TOGGLE        = $20; // toggle key
808
809  KCINFO_FLAG_SHIFT_XOR_NUM = $40; // second vkey should be used when numlock <>shift
810  //KCINFO_FLAG_MULTI_MASK    = $C0; // key has more than one VK
811
812
813type
814  TKeyCodeInfo = record
815    VKey1: Byte;
816    VKey2: Byte; // second code to be used depending on the type of MULTI_VK flag
817    Flags: Byte; // indicates if Alt | Ctrl | Shift is needed
818                 // extended state
819  end;
820
821var
822  MKeyCodeInfo: array[Byte] of TKeyCodeInfo;
823  MVKeyInfo: array[Byte] of TVKeyInfo;
824
825  // Modifier keys can be set by a modmap and don't have to be the same on all systems
826  // Some defaults are set here incase we didn't find them
827type
828  TModifier = record
829    Mask: TGdkModifierType;    // if UseValue is set, the modifier is set when the masked state matches the value
830    Value: TGdkModifierType;   // otherwise any nonzero value will match
831    UseValue: Boolean;
832  end;
833
834var
835  MModifiers: array[TShiftStateEnum] of TModifier;
836
837{$ifdef UseOwnShiftState}
838{$ifdef HasX}
839  // KeyStateMap is a quick index to scan the results of a XQueryKeymap
840  // which returns for the 256 possible keycodes a boolean bit array (32 bytes)
841  // Shift is set when the mask for the Keymapkeys_return[index] is set
842var
843  MKeyStateMap: array of record
844    Index: Byte; // KeyCode shr 3
845    Mask: Byte;  // 1 shl (KeyCode and 7);
846    Enum: TShiftStateEnum;
847  end;
848{$endif}
849{$endif}
850
851type
852  // TLCLHandledKeyEvent is used to remember, if an gdk key event was already
853  // handled.
854  TLCLHandledKeyEvent = class
855  private
856    fRefCount: integer;
857  public
858    thetype: TGdkEventType;
859    window: PGdkWindow;
860    send_event: gint8;
861    time: guint32;
862    state : guint;
863    keyval: guint;
864    hardware_keycode : guint16;
865    constructor Create(Event: PGdkEventKey);
866    function IsEqual(Event: PGdkEventKey): boolean;
867    procedure AddRef;
868    procedure Release;
869  end;
870
871  TWinControlAccess = class(TWinControl)
872  end;
873
874{ TLCLHandledKeyEvent }
875
876constructor TLCLHandledKeyEvent.Create(Event: PGdkEventKey);
877begin
878  fRefCount:=1;
879  thetype:=gdk_event_get_type(Event);
880  window:=Event^.window;
881  send_event:=Event^.send_event;
882  time:=Event^.time;
883  state:=Event^.state;
884  keyval:=Event^.keyval;
885  // event^.length ?
886  // event^._string ?
887  hardware_keycode:=event^.hardware_keycode;
888end;
889
890function TLCLHandledKeyEvent.IsEqual(Event: PGdkEventKey): boolean;
891begin
892  Result:=(gdk_event_get_type(Event)=thetype)
893      and (window=Event^.window)
894      and (send_event=Event^.send_event)
895      and (time=Event^.time)
896      and (keyval=Event^.keyval)
897      ;
898end;
899
900procedure TLCLHandledKeyEvent.AddRef;
901begin
902  inc(fRefCount);
903end;
904
905procedure TLCLHandledKeyEvent.Release;
906begin
907  dec(fRefCount);
908  if fRefCount=0 then
909    Free;
910end;
911
912var
913  // LCLHandledKeyEvents stores the last handled key event (handled by the LCL)
914  // Reason: The gtk sends the same key event to several widgets. The gtk intf
915  // only wants to send them once to the LCL.
916  LCLHandledKeyEvents: TFPList; // list of TLCLHandledKeyEvent
917  LCLHandledKeyAfterEvents: TFPList; // list of TLCLHandledKeyEvent
918
919var
920  GdkTrapIsSet: Boolean;
921  GdkTrapCalls: Integer;
922
923procedure Set_RC_Name(Sender: TObject; AWidget: PGtkWidget);
924var RCName: string;
925  AComponent: TComponent;
926begin
927  {$IFDEF NoStyle}
928  exit;
929  {$ENDIF}
930  if (AWidget=nil) or (not (Sender is TComponent)) then exit;
931
932  // check if a unique name can be created
933  AComponent:=TComponent(Sender);
934  while (AComponent<>nil) and (AComponent.Name<>'') do begin
935    AComponent:=AComponent.Owner;
936  end;
937  if (AComponent=nil) or (AComponent=TComponent(Application)) then begin
938    // create unique name
939    AComponent:=TComponent(Sender);
940    RCName:=AComponent.Name;
941    while (AComponent<>nil) do begin
942      AComponent:=TComponent(AComponent.Owner);
943      if (AComponent<>nil) and (AComponent.Name<>'') then
944        RCName:=AComponent.Name+'_'+RCName;
945    end;
946    // do not set widget name issue #21661
947    // gtk_widget_set_name(AWidget,PChar(RCName));
948    //debugln('Set_RC_Name ',GetWidgetDebugReport(AWidget),' RCName="',RCName,'"');
949    gtk_widget_set_rc_style(AWidget);
950  end;
951end;
952
953procedure InitGTKProc;
954var
955  lgs: TLazGtkStyle;
956begin
957  //MKeySymToVKMap := TMap.Create(itu4, SizeOf(TVKeyRecord));
958  // UTF8 is max 4 bytes, acombined makes it 8
959  //MSymCharToVKMap := TMap.Create(itu8, SizeOf(TVKeyRecord));
960
961  // fill initial modifier list
962  FillByte(MModifiers, SizeOf(MModifiers), 0);
963  // keyboard
964  {$ifndef UseOwnShiftState}
965  MModifiers[ssCaps].Mask     := GDK_LOCK_MASK;
966  MModifiers[ssNum].Mask      := GDK_MOD3_MASK; //todo: check this I've 2 here,but 3 was the original code
967  MModifiers[ssScroll].Mask   := GDK_MOD5_MASK; //todo: check this I've ssAltGr here, but ssScroll was the original code
968  MModifiers[ssShift].Mask    := GDK_SHIFT_MASK;
969  MModifiers[ssCtrl].Mask     := GDK_CONTROL_MASK;
970  MModifiers[ssAlt].Mask      := GDK_MOD1_MASK;
971  MModifiers[ssSuper].Mask    := GDK_MOD4_MASK;
972  MModifiers[ssAltGr].Mask    := GDK_RELEASE_MASK;
973  {$endif}
974  // mouse
975  MModifiers[ssLeft].Mask     := GDK_BUTTON1_MASK;
976  MModifiers[ssMiddle].Mask   := GDK_BUTTON2_MASK;
977  MModifiers[ssRight].Mask    := GDK_BUTTON3_MASK;
978  MModifiers[ssExtra1].Mask   := GDK_BUTTON4_MASK;
979  MModifiers[ssExtra2].Mask   := GDK_BUTTON5_MASK;
980
981  FillChar(MKeyCodeInfo, SizeOf(MKeyCodeInfo), $FF);
982  FillChar(MVKeyInfo, SizeOf(MVKeyInfo), 0);
983
984
985  GdkTrapIsSet := False;
986  GdkTrapCalls := 0;
987  LCLHandledKeyEvents:=nil;
988  LCLHandledKeyAfterEvents:=nil;
989
990  for lgs:=Low(TLazGtkStyle) to High(TLazGtkStyle) do
991    StandardStyles[lgs]:=nil;
992end;
993
994procedure DoneGTKProc;
995begin
996  DoneKeyboardTables;
997//  FreeAndNil(MKeySymToVKMap);
998//  FreeAndNil(MSymCharToVKMap);
999end;
1000
1001{ Callbacks for events }
1002
1003{$I gtk2proc.inc}
1004{$I gtk2callback.inc}
1005
1006initialization
1007  InitGTKProc;
1008
1009finalization
1010  DoneGTKProc;
1011
1012end.
1013
1014