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