From 42c8e0fbea42fd6c16a8a496f3347d30e59ed282 Mon Sep 17 00:00:00 2001 From: marc Date: Sat, 18 Jul 2009 16:10:55 +0000 Subject: [PATCH] * Removed own shiftstate tracking since it doesn't work when the app looses focus. Either X or windows is queried now. Fixes issue #14102 Also removed the EnableGtkShiftState conditional (r20870), since it is not an ubunto only problem, the concept was faulty itself git-svn-id: trunk@20888 - --- lcl/interfaces/gtk/gtkcallback.inc | 31 ------------ lcl/interfaces/gtk/gtkdefines.inc | 6 +-- lcl/interfaces/gtk/gtkproc.inc | 77 ++++++++++++++++++++++++++++-- lcl/interfaces/gtk/gtkproc.pp | 14 ++++-- 4 files changed, 87 insertions(+), 41 deletions(-) diff --git a/lcl/interfaces/gtk/gtkcallback.inc b/lcl/interfaces/gtk/gtkcallback.inc index e3818c268c..0a7b843e33 100644 --- a/lcl/interfaces/gtk/gtkcallback.inc +++ b/lcl/interfaces/gtk/gtkcallback.inc @@ -2478,14 +2478,6 @@ var KeyStateList.Remove(Pointer(PtrInt(AVKeyCode))); end; end; - {$ifdef UseOwnShiftState} - procedure UpdateShiftState(AShift: TShiftStateEnum; AInclude: Boolean); - begin - if AInclude - then Include(MShiftState, AShift) - else Exclude(MShiftState, AShift); - end; - {$endif} const STATE_MAP: array[0..3] of TShiftStateEnum = ( @@ -2523,29 +2515,6 @@ begin Exit; end; - {$ifdef UseOwnShiftState} - case Event^.KeyVal of - GDK_Key_Shift_L, - GDK_Key_Shift_R: UpdateShiftState(ssShift, Pressed); - GDK_KEY_Control_L, - GDK_KEY_Control_R: UpdateShiftState(ssCtrl, Pressed); - GDK_KEY_Meta_L, - GDK_KEY_Meta_R: UpdateShiftState(ssMeta, Pressed); - GDK_KEY_Alt_L, - GDK_KEY_Alt_R: UpdateShiftState(ssAlt, Pressed); - GDK_KEY_Super_L, - GDK_KEY_Super_R: UpdateShiftState(ssSuper, Pressed); - GDK_KEY_Hyper_L, - GDK_KEY_Hyper_R: UpdateShiftState(ssHyper, Pressed); - GDK_KEY_ISO_Level3_Shift: UpdateShiftState(ssAltGr, Pressed); - // Num, scroll, caps lock can be toggled, use modmap in this case - // GDK_KEY_Num_Lock: UpdateShiftState(ssNum, Pressed); - // GDK_KEY_Scroll_Lock: UpdateShiftState(ssScroll, Pressed); - // GDK_KEY_Caps_Lock, - // GDK_KEY_Shift_Lock: UpdateShiftState(ssCaps, Pressed); - end; - {$endif} - {$ifdef gtk1} KeyCode := XKeysymToKeycode(gdk_display, Event^.keyval); {$else} diff --git a/lcl/interfaces/gtk/gtkdefines.inc b/lcl/interfaces/gtk/gtkdefines.inc index 549a7621fb..bf03089f5d 100644 --- a/lcl/interfaces/gtk/gtkdefines.inc +++ b/lcl/interfaces/gtk/gtkdefines.inc @@ -40,9 +40,7 @@ keyboardlayouts are used. With UseOwnShiftState we keep track of the shiftate ourself *) -{$IFNDEF EnableGtkShiftState} {$define UseOwnShiftState} -{$ENDIF} (* keep track of keystates instead of using OS @@ -92,6 +90,8 @@ {$IFDEF Gtk2} -{$DEFINE EnabledGtkThreading} // see http://bugs.freepascal.org/view.php?id=12145. Turn it off is something happen. +// see http://bugs.freepascal.org/view.php?id=12145. +// Turn it off if something happens. +{$DEFINE EnabledGtkThreading} {$define GTK_2_8} {$ENDIF} diff --git a/lcl/interfaces/gtk/gtkproc.inc b/lcl/interfaces/gtk/gtkproc.inc index f1c60eda86..c81d97deb2 100644 --- a/lcl/interfaces/gtk/gtkproc.inc +++ b/lcl/interfaces/gtk/gtkproc.inc @@ -2273,7 +2273,6 @@ begin Flags := 0; SysKey := False; ShiftState := GTKEventStateToShiftState(AEvent^.state); - //DebugLn(['HandleGTKKeyUpDown AEvent^.state=',hexstr(AEvent^.state,4),' ',dbgs(ShiftState)]); {$ifdef gtk1} KeyCode := XKeysymToKeycode(gdk_display, AEvent^.keyval); {$else} @@ -3104,12 +3103,12 @@ type GDK_KEY_Shift_Lock: ShiftState := ssCaps; GDK_KEY_Num_Lock: ShiftState := ssNum; GDK_KEY_Scroll_Lock: ShiftState := ssScroll; - {$ifndef UseOwnShiftState} - // UseOwnShiftState will track these, so we don't have to put them in the modmap GDK_Key_Shift_L, GDK_Key_Shift_R: ShiftState := ssShift; GDK_KEY_Control_L, GDK_KEY_Control_R: ShiftState := ssCtrl; + {$ifndef UseOwnShiftState} + // UseOwnShiftState will track these, so we don't have to put them in the modmap GDK_KEY_Meta_L, GDK_KEY_Meta_R: ShiftState := ssMeta; GDK_KEY_Alt_L, @@ -3133,6 +3132,32 @@ type {$endif} end; + + {$ifdef UseOwnShiftState} + procedure UpdateKeyStateMap(var AIndex: integer; AKeyCode: Byte; AKeySym: Cardinal); + var + Enum: TShiftStateEnum; + begin + case AKeySym of + GDK_KEY_Alt_L, GDK_KEY_Alt_R: Enum := ssAlt; + GDK_KEY_Meta_L, GDK_KEY_Meta_R: Enum := ssMeta; + GDK_KEY_Super_L, GDK_KEY_Super_R: Enum := ssSuper; + GDK_KEY_Hyper_L, GDK_KEY_Hyper_R: Enum := ssHyper; + GDK_KEY_ISO_Level3_Shift: Enum := ssAltGr; + else + Exit; + end; + + if High(MKeyStateMap) < AIndex + then SetLength(MKeyStateMap, AIndex + 8); + + MKeyStateMap[AIndex].Index := AKeyCode shr 3; + MKeyStateMap[AIndex].Mask := 1 shl (AKeyCode and 7); + MKeyStateMap[AIndex].Enum := Enum; + Inc(AIndex) + end; + {$endif UseOwnShiftState} + {$endif HasX} const @@ -3159,6 +3184,9 @@ var XDisplay: Pointer; ModMap: TModMap; {$endif} +{$ifdef UseOwnShiftState} + KeyStateMapIndex: Integer; +{$endif} KeyCode: Byte; m: Integer; @@ -3171,6 +3199,7 @@ begin XDisplay := gdk_display; if XDisplay = nil then Exit; + FillByte(MKeyStateMap, SizeOF(MKeyStateMap), 0); SetupModifiers(XDisplay, ModMap); {$endif} @@ -3217,6 +3246,9 @@ begin HiKey := 255; {$endif} +{$ifdef UseOwnShiftState} + KeyStateMapIndex := 0; +{$endif} FreeVK := VK_FIRST_OEM; for KeyCode := LoKey to HiKey do begin @@ -3266,6 +3298,9 @@ begin begin if KeySyms[m] = 0 then Continue; UpdateModifierMap(ModMap, KeyCode, KeySyms[m]); + {$ifdef UseOwnShiftState} + UpdateKeyStateMap(KeyStateMapIndex, KeyCode, KeySyms[m]); + {$endif} Break; end; {$endif} @@ -3360,6 +3395,9 @@ begin Move(KeySymChars[0], MVKeyInfo[VKey].KeyChar[m], SizeOf(TVKeyUTF8Char)); end; end; +{$ifdef UseOwnShiftState} + SetLength(MKeyStateMap, KeyStateMapIndex); +{$endif} {$ifdef gtk1} XFree(KeySymStart); @@ -3412,11 +3450,42 @@ end; GTKEventStateToShiftState converts a GTK event state to a LCL/Delphi TShiftState ------------------------------------------------------------------------------} function GTKEventStateToShiftState(KeyState: Word): TShiftState; + {$ifdef HasX} + function GetState: TShiftState; + var + Keys: chararr32; + n: Integer; + begin + Result := []; + XQueryKeyMap(gdk_display, Keys); + for n := Low(MKeyStateMap) to High(MKeyStateMap) do + begin + if Ord(Keys[MKeyStateMap[n].Index]) and MKeyStateMap[n].Mask = 0 then Continue; + Include(Result, MKeyStateMap[n].Enum); + Break; + end; + end; + {$else} + {$ifdef windows} + function GetState: TShiftState; + begin + Result := []; + if GetKeyState(VK_ALT) < 0 then Include(Result, ssAlt); + if GetKeyState(VK_WIN) < 0 then Include(Result, ssMeta); + end; + {$else} + function GetState: TShiftState; + begin + Result := []; + end; + {$endif} + {$endif} + var State: TShiftStateEnum; begin {$ifdef UseOwnShiftState} - Result := MShiftState; + Result := GetState; {$else} Result := []; {$endif} diff --git a/lcl/interfaces/gtk/gtkproc.pp b/lcl/interfaces/gtk/gtkproc.pp index 5c7305e4d9..2b9a2889c4 100644 --- a/lcl/interfaces/gtk/gtkproc.pp +++ b/lcl/interfaces/gtk/gtkproc.pp @@ -813,7 +813,7 @@ var MVKeyInfo: array[Byte] of TVKeyInfo; // Modifier keys can be set by a modmap and don't have to be the same on all systems - // Some defaults are set here in case we didn't find them + // Some defaults are set here incase we didn't find them type TModifier = record Mask: TGdkModifierType; // if UseValue is set, the modifier is set when the masked state matches the value @@ -823,10 +823,18 @@ type var MModifiers: array[TShiftStateEnum] of TModifier; - + {$ifdef UseOwnShiftState} +{$ifdef HasX} + // KeyStateMap is a quick index to scan the results of a XQueryKeymap + // Shift is set when the mask for the Keymapkeys_return[index] is set var - MShiftState: TShiftState = []; + MKeyStateMap: array of record + Index: Byte; + Mask: Byte; + Enum: TShiftStateEnum; + end; +{$endif} {$endif} type