diff --git a/Source/colormath/simba.colormath.pas b/Source/colormath/simba.colormath.pas index 6cc3f8bcf..36662610a 100644 --- a/Source/colormath/simba.colormath.pas +++ b/Source/colormath/simba.colormath.pas @@ -38,6 +38,9 @@ interface function AsString: String; end; + TColor = Graphics.TColor; + PColor = ^TColor; + TColorHelper = type helper for TColor function ToBGRA: TColorBGRA; function ToRGB: TColorRGB; diff --git a/Source/components/simba.component_menubar.pas b/Source/components/simba.component_menubar.pas index 86a9738e9..27f308707 100644 --- a/Source/components/simba.component_menubar.pas +++ b/Source/components/simba.component_menubar.pas @@ -51,6 +51,7 @@ TSimbaMainMenuBar = class(TCustomControl) function GetMenus: TPopupMenuArray; public constructor Create(AOwner: TComponent); override; + destructor Destroy; override; property Menus: TPopupMenuArray read GetMenus; procedure AddMenu(Title: String; APopupMenu: TPopupMenu); @@ -235,6 +236,8 @@ procedure TSimbaMainMenuBar.MouseLeave; procedure TSimbaMainMenuBar.DoMenuClose(Sender: TObject); begin + if (FTrackTimer = nil) then + Exit; FTrackTimer.Enabled := False; Application.QueueAsyncCall(@ClearPopupIndex, 0); @@ -286,6 +289,14 @@ constructor TSimbaMainMenuBar.Create(AOwner: TComponent); CalculateSizes(); end; +destructor TSimbaMainMenuBar.Destroy; +begin + Application.RemoveAsyncCalls(Self); + FTrackTimer := nil; + + inherited Destroy(); +end; + procedure TSimbaMainMenuBar.AddMenu(Title: String; APopupMenu: TPopupMenu); var I: Integer; diff --git a/Source/components/simba.component_statusbar.pas b/Source/components/simba.component_statusbar.pas index a96730bc3..35762b564 100644 --- a/Source/components/simba.component_statusbar.pas +++ b/Source/components/simba.component_statusbar.pas @@ -32,7 +32,7 @@ TSimbaStatusBar = class(TCustomControl) procedure Paint; override; procedure PaintPanel(Index: Integer); - procedure InvalidatePanel(Index: Integer); + procedure InvalidatePanelASync(Data: PtrInt); function PanelRect(Index: Integer): TRect; procedure CheckIndex(Index: Integer); @@ -78,10 +78,9 @@ procedure TSimbaStatusBar.SetPanelText(Index: Integer; Value: String); begin if (FPanelText[Index] = Value) then Exit; - FPanelText[Index] := Value; - InvalidatePanel(Index); + Application.QueueAsyncCall(@InvalidatePanelASync, Index); end; procedure TSimbaStatusBar.SetPanelTextMeasure(Index: Integer; Value: String); @@ -194,11 +193,11 @@ procedure TSimbaStatusBar.PaintPanel(Index: Integer); Canvas.TextRect(R, R.Left + 5, R.Top, FPanelText[Index], Style); end; -procedure TSimbaStatusBar.InvalidatePanel(Index: Integer); +procedure TSimbaStatusBar.InvalidatePanelASync(Data: PtrInt); var R: TRect; begin - R := PanelRect(Index); + R := PanelRect(Data); InvalidateRect(Handle, @R, False); end; @@ -226,4 +225,3 @@ function TSimbaStatusBar.PanelRect(Index: Integer): TRect; end; end. - diff --git a/Source/imagebox/simba.imagebox.pas b/Source/imagebox/simba.imagebox.pas index 7e9117807..731235651 100644 --- a/Source/imagebox/simba.imagebox.pas +++ b/Source/imagebox/simba.imagebox.pas @@ -10,7 +10,7 @@ interface uses - Classes, SysUtils, Forms, Controls, Graphics, ComCtrls, LCLType, + Classes, SysUtils, Forms, Controls, Graphics, GraphType, ComCtrls, LCLType, simba.mufasatypes, simba.image, simba.dtm, simba.imagebox_image, simba.colormath; @@ -112,7 +112,7 @@ TSimbaImageBox = class(TWinControl) implementation uses - Math, GraphType, LCLIntf, + Math, LCLIntf, simba.finder, simba.image_lazbridge, simba.windowhandle; procedure TSimbaImageBox_ScrollBox.GetPreferredSize(var PreferredWidth, PreferredHeight: integer; Raw: boolean; WithThemeSpace: boolean); diff --git a/Source/script/imports/simba/simba.import_input.pas b/Source/script/imports/simba/simba.import_input.pas index 48de40768..7ded7585f 100644 --- a/Source/script/imports/simba/simba.import_input.pas +++ b/Source/script/imports/simba/simba.import_input.pas @@ -362,13 +362,23 @@ procedure _LapeInput_KeySend(const Params: PParamArray); LAPE_WRAPPER_CALLING_CO end; (* -TInput.CharToKeyCode -~~~~~~~~~~~~~~~~~~~~ -> function TInput.CharToKeyCode(C: Char): EKeyCode; +TInput.KeyCodeFromChar +~~~~~~~~~~~~~~~~~~~~~~ +> function TInput.KeyCodeFromChar(C: Char): EKeyCode; +*) +procedure _LapeInput_KeyCodeFromChar(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +begin + PKeyCode(Result)^ := PSimbaInput(Params^[0])^.KeyCodeFromChar(PChar(Params^[1])^); +end; + +(* +TInput.KeyModifiersFromChar +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +> procedure TInput.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); *) -procedure _LapeInput_CharToKeyCode(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +procedure _LapeInput_KeyModifiersFromChar(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PKeyCode(Result)^ := PSimbaInput(Params^[0])^.CharToKeyCode(PChar(Params^[1])^); + PSimbaInput(Params^[0])^.KeyModifiersFromChar(PChar(Params^[1])^, PBoolean(Params^[2])^, PBoolean(Params^[3])^, PBoolean(Params^[4])^); end; (* @@ -826,13 +836,13 @@ procedure ImportInput(Compiler: TSimbaScript_Compiler); addInputMethod('procedure TInput.MouseScroll(Scrolls: Integer)', @_LapeInput_MouseScroll); addInputMethod('procedure TInput.MouseMove(Dest: TPoint);', @_LapeInput_MouseMove); + addInputMethod('function TInput.KeyCodeFromChar(C: Char): EKeyCode;', @_LapeInput_KeyCodeFromChar); + addInputMethod('procedure TInput.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean);', @_LapeInput_KeyModifiersFromChar); addInputMethod('procedure TInput.KeySend(Text: String)', @_LapeInput_KeySend); addInputMethod('procedure TInput.KeyPress(Key: EKeyCode)', @_LapeInput_KeyPress); addInputMethod('procedure TInput.KeyDown(Key: EKeyCode)', @_LapeInput_KeyDown); addInputMethod('procedure TInput.KeyUp(Key: EKeyCode)', @_LapeInput_KeyUp); addInputMethod('function TInput.KeyPressed(Key: EKeyCode): Boolean', @_LapeInput_KeyPressed); - - addInputMethod('function TInput.CharToKeyCode(C: Char): EKeyCode', @_LapeInput_CharToKeyCode); end; ImportASyncMouse(Compiler); diff --git a/Source/simba.darwin_axui.pas b/Source/simba.darwin_axui.pas index d944ba34a..fd7d0cac7 100644 --- a/Source/simba.darwin_axui.pas +++ b/Source/simba.darwin_axui.pas @@ -230,7 +230,7 @@ function AXUI_GetWindowInfo(PID: UInt32): TAXUIWindowInfo; end; initialization - SimbaIDEInitialization_AddBeforeShow(@RequestAccessibility, 'RequestAccessibility'); + // SimbaIDEInitialization_AddBeforeShow(@RequestAccessibility, 'RequestAccessibility'); CreateCFStrings(); diff --git a/Source/simba.ide_events.pas b/Source/simba.ide_events.pas index dbe79617f..1989ff5bf 100644 --- a/Source/simba.ide_events.pas +++ b/Source/simba.ide_events.pas @@ -42,14 +42,13 @@ SimbaIDEEvents = class class procedure CallOnEditorModified(Sender: TObject); class procedure CallOnMouseLoggerChange(Sender: TObject); - // Called every 500ms from a script instance while a script is running. + // Called on a seperate thread - synchronize if doing GUI stuff! // Sender = TSimbaScriptInstance class procedure CallOnScriptRunning(Sender: TObject); class procedure RegisterMethodOnScriptRunning(Proc: TNotifyEvent); class procedure UnRegisterMethodOnScriptRunning(Proc: TNotifyEvent); - class procedure RegisterMethodOnScriptStateChange(Proc: TNotifyEvent); class procedure RegisterMethodOnScriptTabChange(Proc: TNotifyEvent); class procedure RegisterOnBeforeTabChange(Proc: TNotifyEvent); diff --git a/Source/simba.input.pas b/Source/simba.input.pas index 92d538c61..2225f119e 100644 --- a/Source/simba.input.pas +++ b/Source/simba.input.pas @@ -24,8 +24,8 @@ interface EMouseEventType = (TELEPORT, MOVING, CLICK, DOWN, UP); {$SCOPEDENUMS OFF} const - DEFAULT_KEY_PRESS_MIN = 30; - DEFAULT_KEY_PRESS_MAX = 140; + DEFAULT_KEY_PRESS_MIN = 25; + DEFAULT_KEY_PRESS_MAX = 130; DEFAULT_CLICK_MIN = 40; DEFAULT_CLICK_MAX = 220; @@ -82,14 +82,14 @@ interface procedure MouseUp(Button: EMouseButton); procedure MouseScroll(Scrolls: Integer); + function KeyCodeFromChar(C: Char): EKeyCode; + procedure KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); procedure KeySend(Text: String); procedure KeyPress(Key: EKeyCode); procedure KeyDown(Key: EKeyCode); procedure KeyUp(Key: EKeyCode); function KeyPressed(Key: EKeyCode): Boolean; - function CharToKeyCode(C: Char): EKeyCode; - function AddOnMouseTeleport(Event: TMouseTeleportEvent): TMouseTeleportEvent; function AddOnMouseMoving(Event: TMouseMovingEvent): TMouseMovingEvent; function AddOnMouseDown(Event: TMouseButtonEvent): TMouseButtonEvent; @@ -130,7 +130,7 @@ TSimbaASyncMouse = class(TSimbaBaseClass) implementation uses - simba.math, simba.nativeinterface, simba.random, simba.threading; + simba.math, simba.nativeinterface, simba.random, simba.threading, simba.target_eios; procedure TSimbaInput.ClearEvent(EventType: EMouseEventType); begin @@ -386,12 +386,86 @@ procedure TSimbaInput.MouseScroll(Scrolls: Integer); Target.MouseScroll(Scrolls); end; +function TSimbaInput.KeyCodeFromChar(C: Char): EKeyCode; +begin + Result := Target.KeyCodeFromChar(C); +end; + +procedure TSimbaInput.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); +begin + Target.KeyModifiersFromChar(Key, Shift, Ctrl, Alt); +end; + procedure TSimbaInput.KeySend(Text: String); +var + ShiftDown, CtrlDown, AltDown: Boolean; + + procedure HandleModifier(const Needed: Boolean; var isDown: Boolean; const KeyCode: EKeyCode); + begin + if (Needed = isDown) then + Exit; + isDown := Needed; + + if Needed then + Target.KeyDown(KeyCode, GetRandomKeyPressTime()) + else + Target.KeyUp(KeyCode, GetRandomKeyPressTime()); + end; + +type + TKeyCodeMap = array[Char] of record + KeyCode: EKeyCode; + ShiftNeeded, CtrlNeeded, AltNeeded: Boolean; + end; var I: Integer; + KeyCodes: TKeyCodeMap; begin + // eios is deprecated but handle it how previous versions used. + if Target.IsEIOSTarget() then + begin + Target.EIOS.SendString(Target.EIOS.Target, PChar(Text), GetRandomKeyPressTime(), GetRandomKeyPressTime()); + Exit; + end; + + KeyCodes := Default(TKeyCodeMap); + for I := 1 to Length(Text) do - Target.KeySend(Text[I], GetRandomKeyPressTime() div 2, GetRandomKeyPressTime() div 2, GetRandomKeyPressTime() div 2, GetRandomKeyPressTime() div 2); + with KeyCodes[Text[I]] do + begin + if (KeyCode = EKeyCode.UNKNOWN) then + begin + KeyCode := Target.KeyCodeFromChar(Text[I]); + + Target.KeyModifiersFromChar( + Text[I], + ShiftNeeded, + CtrlNeeded, + AltNeeded + ); + end; + end; + + ShiftDown := False; + CtrlDown := False; + AltDown := False; + + try + for I := 1 to Length(Text) do + with KeyCodes[Text[I]] do + begin + HandleModifier(ShiftNeeded, ShiftDown, EKeyCode.SHIFT); + HandleModifier(CtrlNeeded, CtrlDown, EKeyCode.CONTROL); + HandleModifier(AltNeeded, AltDown, EKeyCode.MENU); + + Target.KeyDown(KeyCode, GetRandomKeyPressTime()); + Target.KeyUp(KeyCode, GetRandomKeyPressTime()); + end; + finally + HandleModifier(False, ShiftDown, EKeyCode.SHIFT); + HandleModifier(False, CtrlDown, EKeyCode.CONTROL); + HandleModifier(False, AltDown, EKeyCode.MENU); + end; end; procedure TSimbaInput.KeyPress(Key: EKeyCode); @@ -416,49 +490,6 @@ function TSimbaInput.KeyPressed(Key: EKeyCode): Boolean; Result := Target.KeyPressed(Key); end; -function TSimbaInput.CharToKeyCode(C: Char): EKeyCode; -begin - case C of - '0'..'9': Result := EKeyCode(Ord(EKeyCode.NUM_0) + Ord(C) - Ord('0')); - 'a'..'z': Result := EKeyCode(Ord(EKeyCode.A) + Ord(C) - Ord('a')); - 'A'..'Z': Result := EKeyCode(Ord(EKeyCode.A) + Ord(C) - Ord('A')); - #34, #39: Result := EKeyCode.OEM_7; - #32: Result := EKeyCode.SPACE; - '!': Result := EKeyCode.NUM_1; - '#': Result := EKeyCode.NUM_3; - '$': Result := EKeyCode.NUM_4; - '%': Result := EKeyCode.NUM_5; - '&': Result := EKeyCode.NUM_7; - '(': Result := EKeyCode.NUM_9; - ')': Result := EKeyCode.NUM_0; - '*': Result := EKeyCode.NUM_8; - '+': Result := EKeyCode.ADD; - ',': Result := EKeyCode.OEM_COMMA; - '-': Result := EKeyCode.OEM_MINUS; - '.': Result := EKeyCode.OEM_PERIOD; - '/': Result := EKeyCode.OEM_2; - ':': Result := EKeyCode.OEM_1; - ';': Result := EKeyCode.OEM_1; - '<': Result := EKeyCode.OEM_COMMA; - '=': Result := EKeyCode.ADD; - '>': Result := EKeyCode.OEM_PERIOD; - '?': Result := EKeyCode.OEM_2; - '@': Result := EKeyCode.NUM_2; - '[': Result := EKeyCode.OEM_4; - '\': Result := EKeyCode.OEM_5; - ']': Result := EKeyCode.OEM_6; - '^': Result := EKeyCode.NUM_6; - '_': Result := EKeyCode.OEM_MINUS; - '`': Result := EKeyCode.OEM_3; - '{': Result := EKeyCode.OEM_4; - '|': Result := EKeyCode.OEM_5; - '}': Result := EKeyCode.OEM_6; - '~': Result := EKeyCode.OEM_3; - else - Result := EKeyCode.UNKNOWN; - end; -end; - procedure TSimbaInput.CallOnTeleportEvents(P: TPoint); var Method: TMethod; diff --git a/Source/simba.nativeinterface.pas b/Source/simba.nativeinterface.pas index 0dc10d8a5..44675126d 100644 --- a/Source/simba.nativeinterface.pas +++ b/Source/simba.nativeinterface.pas @@ -16,11 +16,6 @@ interface type TSimbaNativeInterface = class public - procedure KeyDownNativeKeyCode(EKeyCode: Integer); virtual; abstract; - procedure KeyUpNativeKeyCode(EKeyCode: Integer); virtual; abstract; - - function GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean; virtual; abstract; - function GetWindowImage(Window: TWindowHandle; X, Y, Width, Height: Integer; var ImageData: PColorBGRA): Boolean; virtual; abstract; function GetWindowBounds(Window: TWindowHandle; out Bounds: TBox): Boolean; virtual; abstract; function GetWindowBounds(Window: TWindowHandle): TBox; virtual; abstract; @@ -34,6 +29,8 @@ TSimbaNativeInterface = class function GetMousePosition: TPoint; virtual; abstract; function GetMousePosition(Window: TWindowHandle): TPoint; virtual; abstract; + function KeyCodeFromChar(Key: Char): EKeyCode; virtual; abstract; + procedure KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); virtual; abstract; function KeyPressed(Key: EKeyCode): Boolean; virtual; abstract; procedure KeyDown(Key: EKeyCode); virtual; abstract; procedure KeyUp(Key: EKeyCode); virtual; abstract; @@ -82,10 +79,6 @@ TSimbaNativeInterface = class procedure OpenFile(Path: String); virtual; procedure OpenURL(URL: String); virtual; - - function GetVirtualKeyCode(Character: Char): Integer; virtual; - - procedure KeySend(Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); virtual; end; var @@ -109,36 +102,6 @@ implementation simba.nativeinterface_darwin; {$ENDIF} -procedure TSimbaNativeInterface.KeySend(Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); -var - NativeKeyCode: Integer; - KeyModifiers: TShiftState; -begin - if not GetNativeKeyCodeAndModifiers(Key, NativeKeyCode, KeyModifiers) then - raise Exception.CreateFmt('TSimbaNativeInterface.SendChar: Unknown key code for "%s"', [Key]); - - if (KeyModifiers <> []) then - begin - if (ssShift in KeyModifiers) then KeyDown(EKeyCode.SHIFT); - if (ssCtrl in KeyModifiers) then KeyDown(EKeyCode.CONTROL); - if (ssAlt in KeyModifiers) then KeyDown(EKeyCode.MENU); - - PreciseSleep(ModifierDownTime); - end; - - KeyDownNativeKeyCode(NativeKeyCode); PreciseSleep(KeyDownTime); - KeyUpNativeKeyCode(NativeKeyCode); PreciseSleep(KeyUpTime); - - if (KeyModifiers <> []) then - begin - if (ssShift in KeyModifiers) then KeyUp(EKeyCode.SHIFT); - if (ssCtrl in KeyModifiers) then KeyUp(EKeyCode.CONTROL); - if (ssAlt in KeyModifiers) then KeyUp(EKeyCode.MENU); - - PreciseSleep(ModifierUpTime); - end; -end; - function TSimbaNativeInterface.WindowHandleToStr(WindowHandle: TWindowHandle): String; begin Result := IntToStr(WindowHandle); @@ -184,50 +147,6 @@ procedure TSimbaNativeInterface.OpenURL(URL: String); LCLIntf.OpenURL(URL); end; -function TSimbaNativeInterface.GetVirtualKeyCode(Character: Char): Integer; -begin - case Character of - '0'..'9': Result := VK_0 + Ord(Character) - Ord('0'); - 'a'..'z': Result := VK_A + Ord(Character) - Ord('a'); - 'A'..'Z': Result := VK_A + Ord(Character) - Ord('A'); - ' ': Result := VK_SPACE; - '!': Result := VK_1; - '"': Result := VK_OEM_7; - '#': Result := VK_3; - '$': Result := VK_4; - '%': Result := VK_5; - '&': Result := VK_7; - '''': Result := VK_OEM_7; - '(': Result := VK_9; - ')': Result := VK_0; - '*': Result := VK_8; - '+': Result := VK_ADD; - ',': Result := VK_OEM_COMMA; - '-': Result := VK_OEM_MINUS; - '.': Result := VK_OEM_PERIOD; - '/': Result := VK_OEM_2; - ':': Result := VK_OEM_1; - ';': Result := VK_OEM_1; - '<': Result := VK_OEM_COMMA; - '=': Result := VK_ADD; - '>': Result := VK_OEM_PERIOD; - '?': Result := VK_OEM_2; - '@': Result := VK_2; - '[': Result := VK_OEM_4; - '\': Result := VK_OEM_5; - ']': Result := VK_OEM_6; - '^': Result := VK_6; - '_': Result := VK_OEM_MINUS; - '`': Result := VK_OEM_3; - '{': Result := VK_OEM_4; - '|': Result := VK_OEM_5; - '}': Result := VK_OEM_6; - '~': Result := VK_OEM_3; - else - Result := VK_UNKNOWN; - end; -end; - initialization SimbaNativeInterface := {$IF DEFINED(WINDOWS)} TSimbaNativeInterface_Windows.Create(); diff --git a/Source/simba.nativeinterface_darwin.pas b/Source/simba.nativeinterface_darwin.pas index 9149ab64c..4e33eeec7 100644 --- a/Source/simba.nativeinterface_darwin.pas +++ b/Source/simba.nativeinterface_darwin.pas @@ -11,8 +11,8 @@ interface uses - classes, sysutils, graphics, macosall, - simba.mufasatypes, simba.nativeinterface, simba.colormath; + Classes, SysUtils, Graphics, MacOSAll, + simba.mufasatypes, simba.nativeinterface; type TVirtualWindow = packed record @@ -28,27 +28,25 @@ TSimbaNativeInterface_Darwin = class(TSimbaNativeInterface) type TKeyMapItem = record Exists: Boolean; - EKeyCode: Integer; + KeyCode: Integer; Modifiers: TShiftState; end; TKeyMap = array[#0..#255] of TKeyMapItem; protected FKeyMap: TKeyMap; + FKeyMapBuilt: Boolean; FVirtualWindowInfo: array of record ClientRect: TBox; ClassStr: ShortString; end; + procedure CheckAccessibility; + procedure BuildKeyMap; function IsVirtualWindow(Window: TWindowHandle; out VirtualWindow: TVirtualWindow): Boolean; function GetVirtualWindowInfoIndex(ClientRect: TBox; ClassStr: ShortString): Integer; public constructor Create; - procedure KeyDownNativeKeyCode(EKeyCode: Integer); override; - procedure KeyUpNativeKeyCode(EKeyCode: Integer); override; - - function GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean; override; - function GetWindowBounds(Window: TWindowHandle; out Bounds: TBox): Boolean; override; function GetWindowBounds(Window: TWindowHandle): TBox; override; overload; procedure SetWindowBounds(Window: TWindowHandle; Bounds: TBox); override; @@ -64,6 +62,8 @@ TKeyMapItem = record procedure MouseTeleport(RelativeWindow: TWindowHandle; P: TPoint); override; function MousePressed(Button: EMouseButton): Boolean; override; + function KeyCodeFromChar(Key: Char): EKeyCode; override; + procedure KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); override; function KeyPressed(Key: EKeyCode): Boolean; override; procedure KeyDown(Key: EKeyCode); override; procedure KeyUp(Key: EKeyCode); override; @@ -303,6 +303,123 @@ function VirtualKeyToNativeKeyCode(VirtualKey: EKeyCode): Integer; end; end; +function NativeKeyCodeToVirtualKeyCode(NativeKeyCode: Integer): EKeyCode; +begin + case NativeKeyCode of + $33: Result := EKeyCode.BACK; + $30: Result := EKeyCode.TAB; + $47: Result := EKeyCode.CLEAR; + $24: Result := EKeyCode.RETURN; + $38: Result := EKeyCode.SHIFT; + $3B: Result := EKeyCode.CONTROL; + $3A: Result := EKeyCode.MENU; + $39: Result := EKeyCode.CAPITAL; + $35: Result := EKeyCode.ESCAPE; + $31: Result := EKeyCode.SPACE; + $74: Result := EKeyCode.PRIOR; + $79: Result := EKeyCode.NEXT; + $77: Result := EKeyCode.END_KEY; + $73: Result := EKeyCode.HOME; + $7B: Result := EKeyCode.LEFT; + $7E: Result := EKeyCode.UP; + $7C: Result := EKeyCode.RIGHT; + $7D: Result := EKeyCode.DOWN; + $75: Result := EKeyCode.DELETE; + $72: Result := EKeyCode.HELP; + $1D: Result := EKeyCode.NUM_0; + $12: Result := EKeyCode.NUM_1; + $13: Result := EKeyCode.NUM_2; + $14: Result := EKeyCode.NUM_3; + $15: Result := EKeyCode.NUM_4; + $17: Result := EKeyCode.NUM_5; + $16: Result := EKeyCode.NUM_6; + $1A: Result := EKeyCode.NUM_7; + $1C: Result := EKeyCode.NUM_8; + $19: Result := EKeyCode.NUM_9; + $00: Result := EKeyCode.A; + $0B: Result := EKeyCode.B; + $08: Result := EKeyCode.C; + $02: Result := EKeyCode.D; + $0E: Result := EKeyCode.E; + $03: Result := EKeyCode.F; + $05: Result := EKeyCode.G; + $04: Result := EKeyCode.H; + $22: Result := EKeyCode.I; + $26: Result := EKeyCode.J; + $28: Result := EKeyCode.K; + $25: Result := EKeyCode.L; + $2E: Result := EKeyCode.M; + $2D: Result := EKeyCode.N; + $1F: Result := EKeyCode.O; + $23: Result := EKeyCode.P; + $0C: Result := EKeyCode.Q; + $0F: Result := EKeyCode.R; + $01: Result := EKeyCode.S; + $11: Result := EKeyCode.T; + $20: Result := EKeyCode.U; + $09: Result := EKeyCode.V; + $0D: Result := EKeyCode.W; + $07: Result := EKeyCode.X; + $10: Result := EKeyCode.Y; + $06: Result := EKeyCode.Z; + $37: Result := EKeyCode.LWIN; + $36: Result := EKeyCode.RWIN; + $3D: Result := EKeyCode.APPS; + $52: Result := EKeyCode.NUMPAD_0; + $53: Result := EKeyCode.NUMPAD_1; + $54: Result := EKeyCode.NUMPAD_2; + $55: Result := EKeyCode.NUMPAD_3; + $56: Result := EKeyCode.NUMPAD_4; + $57: Result := EKeyCode.NUMPAD_5; + $58: Result := EKeyCode.NUMPAD_6; + $59: Result := EKeyCode.NUMPAD_7; + $5B: Result := EKeyCode.NUMPAD_8; + $5C: Result := EKeyCode.NUMPAD_9; + $43: Result := EKeyCode.MULTIPLY; + $45: Result := EKeyCode.ADD; + $2B: Result := EKeyCode.SEPARATOR; + $4E: Result := EKeyCode.SUBTRACT; + $41: Result := EKeyCode.DECIMAL; + $4B: Result := EKeyCode.DIVIDE; + $7A: Result := EKeyCode.F1; + $78: Result := EKeyCode.F2; + $63: Result := EKeyCode.F3; + $76: Result := EKeyCode.F4; + $60: Result := EKeyCode.F5; + $61: Result := EKeyCode.F6; + $62: Result := EKeyCode.F7; + $64: Result := EKeyCode.F8; + $65: Result := EKeyCode.F9; + $6D: Result := EKeyCode.F10; + $67: Result := EKeyCode.F11; + $6F: Result := EKeyCode.F12; + $69: Result := EKeyCode.F13; + $6B: Result := EKeyCode.F14; + $71: Result := EKeyCode.F15; + $6A: Result := EKeyCode.F16; + $40: Result := EKeyCode.F17; + $4F: Result := EKeyCode.F18; + $50: Result := EKeyCode.F19; + $5A: Result := EKeyCode.F20; + $3C: Result := EKeyCode.RSHIFT; + $3E: Result := EKeyCode.RCONTROL; + $4A: Result := EKeyCode.VOLUME_MUTE; + $49: Result := EKeyCode.VOLUME_DOWN; + $48: Result := EKeyCode.VOLUME_UP; + $29: Result := EKeyCode.OEM_1; + $1B: Result := EKeyCode.OEM_MINUS; + $2F: Result := EKeyCode.OEM_PERIOD; + $2C: Result := EKeyCode.OEM_2; + $32: Result := EKeyCode.OEM_3; + $21: Result := EKeyCode.OEM_4; + $2A: Result := EKeyCode.OEM_5; + $1E: Result := EKeyCode.OEM_6; + $27: Result := EKeyCode.OEM_7; + else + Result := EKeyCode.UNKNOWN; + end; +end; + function TSimbaNativeInterface_Darwin.GetWindowBounds(Window: TWindowHandle; out Bounds: TBox): Boolean; var windowIds, windows: CFArrayRef; @@ -514,40 +631,45 @@ function TSimbaNativeInterface_Darwin.MousePressed(Button: EMouseButton): Boolea Result := CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, ClickTypeToMouseButton[Button]) > 0; end; -function TSimbaNativeInterface_Darwin.KeyPressed(Key: EKeyCode): Boolean; +function TSimbaNativeInterface_Darwin.KeyCodeFromChar(Key: Char): EKeyCode; begin - Result := CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, VirtualKeyToNativeKeyCode(Key)) <> 0; -end; + BuildKeyMap(); -procedure TSimbaNativeInterface_Darwin.KeyDown(Key: EKeyCode); -begin - CGPostKeyboardEvent(0, VirtualKeyToNativeKeyCode(Key), 1); + if FKeyMap[Key].Exists then + Result := NativeKeyCodeToVirtualKeyCode(FKeyMap[Key].KeyCode) + else + Result := EKeyCode.UNKNOWN; end; -procedure TSimbaNativeInterface_Darwin.KeyUp(Key: EKeyCode); +procedure TSimbaNativeInterface_Darwin.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); +var + ShiftState: TShiftState; begin - CGPostKeyboardEvent(0, VirtualKeyToNativeKeyCode(Key), 0); + BuildKeyMap(); + + if FKeyMap[Key].Exists then + ShiftState := FKeyMap[Key].Modifiers + else + ShiftState := []; + + Shift := ssShift in ShiftState; + Ctrl := ssCtrl in ShiftState; + Alt := ssAlt in ShiftState; end; -procedure TSimbaNativeInterface_Darwin.KeyDownNativeKeyCode(EKeyCode: Integer); +function TSimbaNativeInterface_Darwin.KeyPressed(Key: EKeyCode): Boolean; begin - CGPostKeyboardEvent(0, EKeyCode, 1); + Result := CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, VirtualKeyToNativeKeyCode(Key)) <> 0; end; -procedure TSimbaNativeInterface_Darwin.KeyUpNativeKeyCode(EKeyCode: Integer); +procedure TSimbaNativeInterface_Darwin.KeyDown(Key: EKeyCode); begin - CGPostKeyboardEvent(0, EKeyCode, 0); + CGPostKeyboardEvent(0, VirtualKeyToNativeKeyCode(Key), 1); end; -function TSimbaNativeInterface_Darwin.GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean; +procedure TSimbaNativeInterface_Darwin.KeyUp(Key: EKeyCode); begin - Result := FKeyMap[Character].Exists; - - if Result then - begin - Code := FKeyMap[Character].EKeyCode; - Modifiers := FKeyMap[Character].Modifiers; - end + CGPostKeyboardEvent(0, VirtualKeyToNativeKeyCode(Key), 0); end; function TSimbaNativeInterface_Darwin.GetProcessStartTime(PID: SizeUInt): TDateTime; @@ -873,30 +995,15 @@ function TSimbaNativeInterface_Darwin.WindowHandleFromStr(Str: String): TWindowH Result := inherited WindowHandleFromStr(Str); end; -function TSimbaNativeInterface_Darwin.IsVirtualWindow(Window: TWindowHandle; out VirtualWindow: TVirtualWindow): Boolean; +procedure TSimbaNativeInterface_Darwin.CheckAccessibility; begin - VirtualWindow := TVirtualWindow(Window); - - Result := VirtualWindow.InfoIndex > 0; -end; - -function TSimbaNativeInterface_Darwin.GetVirtualWindowInfoIndex(ClientRect: TBox; ClassStr: ShortString): Integer; -var - I: Integer; -begin - Result := Length(Self.FVirtualWindowInfo); - for I := 0 to Result - 1 do - if (Self.FVirtualWindowInfo[I].ClientRect = ClientRect) and (Self.FVirtualWindowInfo[I].ClassStr = ClassStr) then - Exit(I); - - SetLength(FVirtualWindowInfo, Result + 1); - FVirtualWindowInfo[Result].ClientRect := ClientRect; - FVirtualWindowInfo[Result].ClassStr := ClassStr; + if not AXIsProcessTrusted() then + SimbaException('Simba needs accessbility privilege on MacOS.' + LineEnding + 'Settings > Security & Privacy Accessibility'); end; -constructor TSimbaNativeInterface_Darwin.Create; +procedure TSimbaNativeInterface_Darwin.BuildKeyMap; - procedure MapKey(EKeyCode: Integer; KeyChar: NSString; Modifiers: TShiftState); + procedure MapKey(KeyCode: Integer; KeyChar: NSString; Modifiers: TShiftState); var Str: String; begin @@ -906,37 +1013,67 @@ constructor TSimbaNativeInterface_Darwin.Create; if FKeyMap[Str[1]].Exists then Exit; - FKeyMap[Str[1]].EKeyCode := EKeyCode; + FKeyMap[Str[1]].KeyCode := KeyCode; FKeyMap[Str[1]].Modifiers := Modifiers; FKeyMap[Str[1]].Exists := True; end; end; var + I: Integer; + KeyboardEvent: CGEventRef; Event: NSEvent; - EKeyCode: Integer; + LocalPool: NSAutoReleasePool; begin - inherited Create(); + if FKeyMapBuilt then + Exit; - SetLength(FVirtualWindowInfo, 1); + CheckAccessibility(); - for EKeyCode := 0 to 255 do + LocalPool := NSAutoReleasePool.alloc.init; + for I := 0 to 255 do begin - Event := NSEvent.eventWithCGEvent(CGEventCreateKeyboardEvent(nil, EKeyCode, 1)); + Event := NSEvent.eventWithCGEvent(CGEventCreateKeyboardEvent(nil, I, 1)); - if (Event <> nil) then + if (Event <> nil) and (Event.Type_ = NSKeyDown) then begin - if (Event.Type_ = NSKeyDown) then - begin - MapKey(EKeyCode, Event.characters, []); - MapKey(EKeyCode, NSEventFix(Event).charactersByApplyingModifiers(NSShiftKeyMask), [ssShift]); - MapKey(EKeyCode, NSEventFix(Event).charactersByApplyingModifiers(NSAlternateKeyMask), [ssAlt]); - MapKey(EKeyCode, NSEventFix(Event).charactersByApplyingModifiers(NSControlKeyMask), [ssCtrl]); - end; - - CFRelease(Event); + MapKey(I, Event.characters, []); + MapKey(I, NSEventFix(Event).charactersByApplyingModifiers(NSShiftKeyMask), [ssShift]); + MapKey(I, NSEventFix(Event).charactersByApplyingModifiers(NSAlternateKeyMask), [ssAlt]); + MapKey(I, NSEventFix(Event).charactersByApplyingModifiers(NSControlKeyMask), [ssCtrl]); end; end; + LocalPool.release; + + FKeyMapBuilt := True; +end; + +function TSimbaNativeInterface_Darwin.IsVirtualWindow(Window: TWindowHandle; out VirtualWindow: TVirtualWindow): Boolean; +begin + VirtualWindow := TVirtualWindow(Window); + + Result := VirtualWindow.InfoIndex > 0; +end; + +function TSimbaNativeInterface_Darwin.GetVirtualWindowInfoIndex(ClientRect: TBox; ClassStr: ShortString): Integer; +var + I: Integer; +begin + Result := Length(Self.FVirtualWindowInfo); + for I := 0 to Result - 1 do + if (Self.FVirtualWindowInfo[I].ClientRect = ClientRect) and (Self.FVirtualWindowInfo[I].ClassStr = ClassStr) then + Exit(I); + + SetLength(FVirtualWindowInfo, Result + 1); + FVirtualWindowInfo[Result].ClientRect := ClientRect; + FVirtualWindowInfo[Result].ClassStr := ClassStr; +end; + +constructor TSimbaNativeInterface_Darwin.Create; +begin + inherited Create(); + + SetLength(FVirtualWindowInfo, 1); timeInfo.numer := 0; timeInfo.denom := 0; diff --git a/Source/simba.nativeinterface_linux.pas b/Source/simba.nativeinterface_linux.pas index 969a06df0..1c9661a4c 100644 --- a/Source/simba.nativeinterface_linux.pas +++ b/Source/simba.nativeinterface_linux.pas @@ -16,11 +16,6 @@ interface type TSimbaNativeInterface_Linux = class(TSimbaNativeInterface) public - procedure KeyDownNativeKeyCode(EKeyCode: Integer); override; - procedure KeyUpNativeKeyCode(EKeyCode: Integer); override; - - function GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean; override; - function GetWindowBounds(Window: TWindowHandle; out Bounds: TBox): Boolean; override; function GetWindowBounds(Window: TWindowHandle): TBox; override; overload; procedure SetWindowBounds(Window: TWindowHandle; Bounds: TBox); override; @@ -36,9 +31,11 @@ TSimbaNativeInterface_Linux = class(TSimbaNativeInterface) procedure MouseTeleport(RelativeWindow: TWindowHandle; P: TPoint); override; function MousePressed(Button: EMouseButton): Boolean; override; - function KeyPressed(Key: EKeyCode): Boolean; override; + function KeyCodeFromChar(Key: Char): EKeyCode; override; + procedure KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); override; procedure KeyDown(Key: EKeyCode); override; procedure KeyUp(Key: EKeyCode); override; + function KeyPressed(Key: EKeyCode): Boolean; override; function GetProcessStartTime(PID: SizeUInt): TDateTime; override; function GetProcessMemUsage(PID: SizeUInt): Int64; override; @@ -226,6 +223,7 @@ function HasWindowProperty(Window: TWindow; Name: String): Boolean; Result := GetWindowProperty(Window, SimbaXLib.XInternAtom(PChar(Name), False)) > 0; end; +{ procedure TSimbaNativeInterface_Linux.KeyDownNativeKeyCode(EKeyCode: Integer); begin SimbaXLib.XTestFakeKeyEvent(EKeyCode, True, 0); @@ -316,6 +314,7 @@ function TSimbaNativeInterface_Linux.GetNativeKeyCodeAndModifiers(Character: Cha end; end; end; +} function TSimbaNativeInterface_Linux.GetWindowBounds(Window: TWindowHandle; out Bounds: TBox): Boolean; var @@ -467,6 +466,16 @@ function TSimbaNativeInterface_Linux.MousePressed(Button: EMouseButton): Boolean Result := ((Event.State and Mask) > 0); end; +function TSimbaNativeInterface_Linux.KeyCodeFromChar(Key: Char): EKeyCode; +begin + +end; + +procedure TSimbaNativeInterface_Linux.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); +begin + +end; + function TSimbaNativeInterface_Linux.KeyPressed(Key: EKeyCode): Boolean; var Code: TKeySym; diff --git a/Source/simba.nativeinterface_windows.pas b/Source/simba.nativeinterface_windows.pas index 4022fd812..fd58195c2 100644 --- a/Source/simba.nativeinterface_windows.pas +++ b/Source/simba.nativeinterface_windows.pas @@ -27,11 +27,6 @@ TSimbaNativeInterface_Windows = class(TSimbaNativeInterface) constructor Create; destructor Destroy; override; - procedure KeyDownNativeKeyCode(EKeyCode: Integer); override; - procedure KeyUpNativeKeyCode(EKeyCode: Integer); override; - - function GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean; override; - function GetWindowBounds(Window: TWindowHandle; out Bounds: TBox): Boolean; override; function GetWindowBounds(Window: TWindowHandle): TBox; override; overload; procedure SetWindowBounds(Window: TWindowHandle; Bounds: TBox); override; @@ -47,6 +42,8 @@ TSimbaNativeInterface_Windows = class(TSimbaNativeInterface) function GetMousePosition: TPoint; override; function GetMousePosition(Window: TWindowHandle): TPoint; override; + function KeyCodeFromChar(Key: Char): EKeyCode; override; + procedure KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); override; function KeyPressed(Key: EKeyCode): Boolean; override; procedure KeyDown(Key: EKeyCode); override; procedure KeyUp(Key: EKeyCode); override; @@ -438,6 +435,11 @@ function TSimbaNativeInterface_Windows.GetMousePosition(Window: TWindowHandle): Result.Y := Result.Y - Bounds.Y1; end; +function TSimbaNativeInterface_Windows.KeyCodeFromChar(Key: Char): EKeyCode; +begin + Result := EKeyCode(VKKeyScan(Key) and $FF); +end; + function TSimbaNativeInterface_Windows.MousePressed(Button: EMouseButton): Boolean; begin Result := False; @@ -456,36 +458,15 @@ function TSimbaNativeInterface_Windows.KeyPressed(Key: EKeyCode): Boolean; Result := (GetAsyncKeyState(Ord(Key)) and $8000 <> 0); //only check if high-order bit is set end; -procedure TSimbaNativeInterface_Windows.KeyDownNativeKeyCode(EKeyCode: Integer); +procedure TSimbaNativeInterface_Windows.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); var - Input: TInput; + Scan: UInt16; begin - Input := Default(TInput); - Input._Type := INPUT_KEYBOARD; - Input.ki.dwFlags := KEYEVENTF_SCANCODE; - Input.ki.wScan := MapVirtualKey(EKeyCode, 0); - - SendInput(1, @Input, SizeOf(Input)); -end; - -procedure TSimbaNativeInterface_Windows.KeyUpNativeKeyCode(EKeyCode: Integer); -var - Input: TInput; -begin - Input := Default(TInput); - Input._Type := INPUT_KEYBOARD; - Input.ki.dwFlags := KEYEVENTF_KEYUP or KEYEVENTF_SCANCODE; - Input.ki.wScan := MapVirtualKey(EKeyCode, 0); - - SendInput(1, @Input, SizeOf(Input)); -end; - -function TSimbaNativeInterface_Windows.GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean; -begin - Result := True; + Scan := VkKeyScan(Key); - Code := VKKeyScan(Character) and $FF; - Modifiers := TShiftState(VKKeyScan(Character) shr 8 and $FF); + Shift := (Scan and $100) > 0; + Ctrl := (Scan and $200) > 0; + Alt := (Scan and $400) > 0; end; procedure TSimbaNativeInterface_Windows.KeyDown(Key: EKeyCode); diff --git a/Source/simba.target.pas b/Source/simba.target.pas index 378dd51a3..f04482c3f 100644 --- a/Source/simba.target.pas +++ b/Source/simba.target.pas @@ -29,9 +29,10 @@ TTargetMethods = record IsFocused: function(Target: Pointer): Boolean; Focus: function(Target: Pointer): Boolean; + KeyCodeFromChar: function(Target: Pointer; C: Char): EKeyCode; + KeyModifiersFromChar: procedure(Target: Pointer; Key: Char; out Shift, Ctrl, Alt: Boolean); KeyDown: procedure(Target: Pointer; Key: EKeyCode); KeyUp: procedure(Target: Pointer; Key: EKeyCode); - KeySend: procedure(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); KeyPressed: function(Target: Pointer; Key: EKeyCode): Boolean; MouseTeleport: procedure(Target: Pointer; P: TPoint); @@ -76,6 +77,8 @@ TTargetMethods = record procedure GetDimensions(out W, H: Integer); public + property EIOS: TEIOSTarget read FTargetEIOS; deprecated 'EIOS is pretty much deprecated'; + function GetWindowTarget: TWindowHandle; function IsWindowTarget: Boolean; overload; function IsWindowTarget(out Window: TWindowHandle): Boolean; overload; @@ -109,9 +112,10 @@ TTargetMethods = record procedure MouseDown(Button: EMouseButton); procedure MouseScroll(Scrolls: Integer); - procedure KeyDown(Key: EKeyCode); - procedure KeyUp(Key: EKeyCode); - procedure KeySend(Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); + function KeyCodeFromChar(C: Char): EKeyCode; + procedure KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); + procedure KeyDown(Key: EKeyCode; SleepAfter: Integer = 0); + procedure KeyUp(Key: EKeyCode; SleepAfter: Integer = 0); function KeyPressed(Key: EKeyCode): Boolean; function ValidateBounds(var ABounds: TBox): Boolean; @@ -326,9 +330,10 @@ procedure TSimbaTarget.SetWindow(Window: TWindowHandle); FMethods.IsFocused := @WindowTarget_IsFocused; FMethods.IsValid := @WindowTarget_IsValid; + FMethods.KeyCodeFromChar := @WindowTarget_KeyCodeFromChar; + FMethods.KeyModifiersFromChar := @WindowTarget_KeyModifiersFromChar; FMethods.KeyDown := @WindowTarget_KeyDown; FMethods.KeyUp := @WindowTarget_KeyUp; - FMethods.KeySend := @WindowTarget_KeySend; FMethods.KeyPressed := @WindowTarget_KeyPressed; FMethods.MouseTeleport := @WindowTarget_MouseTeleport; @@ -363,7 +368,6 @@ procedure TSimbaTarget.SetEIOS(FileName, Args: String); FMethods.KeyDown := @EIOSTarget_KeyDown; FMethods.KeyUp := @EIOSTarget_KeyUp; - FMethods.KeySend := @EIOSTarget_KeySend; FMethods.KeyPressed := @EIOSTarget_KeyPressed; FMethods.MouseTeleport := @EIOSTarget_MouseTeleport; @@ -386,9 +390,10 @@ procedure TSimbaTarget.SetPlugin(FileName, Args: String); FTargetPlugin := LoadPluginTarget(FileName, Args); FTarget := @FTargetPlugin; + FMethods.KeyCodeFromChar := @PluginTarget_KeyCodeFromChar; + FMethods.KeyModifiersFromChar := @PluginTarget_KeyModifiers; FMethods.KeyDown := @PluginTarget_KeyDown; FMethods.KeyUp := @PluginTarget_KeyUp; - FMethods.KeySend := @PluginTarget_KeySend; FMethods.KeyPressed := @PluginTarget_KeyPressed; FMethods.MouseTeleport := @PluginTarget_MouseTeleport; @@ -411,9 +416,10 @@ procedure TSimbaTarget.SetPlugin(FileName, Args: String; out DebugImage: TSimbaE FTargetPlugin := LoadPluginTarget(FileName, Args, DebugImage); FTarget := @FTargetPlugin; + FMethods.KeyCodeFromChar := @PluginTarget_KeyCodeFromChar; + FMethods.KeyModifiersFromChar := @PluginTarget_KeyModifiers; FMethods.KeyDown := @PluginTarget_KeyDown; FMethods.KeyUp := @PluginTarget_KeyUp; - FMethods.KeySend := @PluginTarget_KeySend; FMethods.KeyPressed := @PluginTarget_KeyPressed; FMethods.MouseTeleport := @PluginTarget_MouseTeleport; @@ -479,28 +485,44 @@ procedure TSimbaTarget.MouseScroll(Scrolls: Integer); FMethods.MouseScroll(FTarget, Scrolls); end; -procedure TSimbaTarget.KeyDown(Key: EKeyCode); +function TSimbaTarget.KeyCodeFromChar(C: Char): EKeyCode; begin - CheckAutoFocus(); + if HasMethod(FMethods.KeyCodeFromChar, 'KeyCodeFromChar') then + Result := FMethods.KeyCodeFromChar(FTarget, C); +end; - if HasMethod(FMethods.KeyDown, 'KeyDown') then - FMethods.KeyDown(FTarget, Key); +procedure TSimbaTarget.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean); +begin + Shift := False; + Ctrl := False; + Alt := False; + + if HasMethod(FMethods.KeyModifiersFromChar, 'KeyModifiersFromChar') then + FMethods.KeyModifiersFromChar(FTarget, Key, Shift, Ctrl, Alt); end; -procedure TSimbaTarget.KeyUp(Key: EKeyCode); +procedure TSimbaTarget.KeyDown(Key: EKeyCode; SleepAfter: Integer); begin CheckAutoFocus(); - if HasMethod(FMethods.KeyUp, 'KeyUp') then - FMethods.KeyUp(FTarget, Key); + if HasMethod(FMethods.KeyDown, 'KeyDown') then + begin + FMethods.KeyDown(FTarget, Key); + if (SleepAfter > 0) then + SimbaNativeInterface.PreciseSleep(SleepAfter); + end; end; -procedure TSimbaTarget.KeySend(Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); +procedure TSimbaTarget.KeyUp(Key: EKeyCode; SleepAfter: Integer); begin CheckAutoFocus(); - if HasMethod(FMethods.KeySend, 'KeySend') then - FMethods.KeySend(FTarget, Key, KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime); + if HasMethod(FMethods.KeyUp, 'KeyUp') then + begin + FMethods.KeyUp(FTarget, Key); + if (SleepAfter > 0) then + SimbaNativeInterface.PreciseSleep(SleepAfter); + end; end; function TSimbaTarget.KeyPressed(Key: EKeyCode): Boolean; diff --git a/Source/targets/simba.target_eios.pas b/Source/targets/simba.target_eios.pas index c1570bb9b..1a376cf16 100644 --- a/Source/targets/simba.target_eios.pas +++ b/Source/targets/simba.target_eios.pas @@ -85,7 +85,6 @@ procedure EIOSTarget_GetDimensions(Target: Pointer; out Width, Height: Integer); procedure EIOSTarget_KeyDown(Target: Pointer; Key: EKeyCode); procedure EIOSTarget_KeyUp(Target: Pointer; Key: EKeyCode); -procedure EIOSTarget_KeySend(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); function EIOSTarget_KeyPressed(Target: Pointer; Key: EKeyCode): Boolean; function EIOSTarget_MousePressed(Target: Pointer; Button: EMouseButton): Boolean; @@ -278,14 +277,5 @@ procedure EIOSTarget_KeyUp(Target: Pointer; Key: EKeyCode); end; end; -procedure EIOSTarget_KeySend(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); -begin - with PEIOSTarget(Target)^ do - begin - if Assigned(SendString) then - SendString(Target, PChar(String(Key)), KeyDownTime, ModifierDownTime); - end; -end; - end. diff --git a/Source/targets/simba.target_plugin.pas b/Source/targets/simba.target_plugin.pas index b978fe181..6eb9daad7 100644 --- a/Source/targets/simba.target_plugin.pas +++ b/Source/targets/simba.target_plugin.pas @@ -38,8 +38,9 @@ TSimbaPluginTarget = record KeyDown: procedure(Target: Pointer; Key: Int32); cdecl; KeyUp: procedure(Target: Pointer; Key: Int32); cdecl; - KeySend: procedure(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Int32); cdecl; KeyPressed: function(Target: Pointer; Key: Int32): Boolean; cdecl; + KeyCodeFromChar: function(Target: Pointer; Key: Char): EKeyCode; cdecl; + KeyModifiers: procedure(Target: Pointer; Key: Char; out Shift, Ctrl, Alt: Boolean); cdecl; end; function LoadPluginTarget(FileName, Args: String): TSimbaPluginTarget; overload; @@ -55,9 +56,10 @@ procedure PluginTarget_MouseUp(Target: Pointer; Button: EMouseButton); procedure PluginTarget_MouseDown(Target: Pointer; Button: EMouseButton); procedure PluginTarget_MouseScroll(Target: Pointer; Scrolls: Integer); +function PluginTarget_KeyCodeFromChar(Target: Pointer; Key: Char): EKeyCode; +procedure PluginTarget_KeyModifiers(Target: Pointer; Key: Char; out Shift, Ctrl, Alt: Boolean); procedure PluginTarget_KeyDown(Target: Pointer; Key: EKeyCode); procedure PluginTarget_KeyUp(Target: Pointer; Key: EKeyCode); -procedure PluginTarget_KeySend(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); function PluginTarget_KeyPressed(Target: Pointer; Key: EKeyCode): Boolean; function PluginTarget_IsValid(Target: Pointer): Boolean; @@ -104,7 +106,8 @@ function Load(AFileName: String): TSimbaPluginTarget; Pointer(KeyDown) := GetProcedureAddress(Lib, 'SimbaPluginTarget_KeyDown'); Pointer(KeyUp) := GetProcedureAddress(Lib, 'SimbaPluginTarget_KeyUp'); - Pointer(KeySend) := GetProcedureAddress(Lib, 'SimbaPluginTarget_KeySend'); + Pointer(KeyModifiers) := GetProcedureAddress(Lib, 'SimbaPluginTarget_KeyModifiers'); + Pointer(KeyCodeFromChar) := GetProcedureAddress(Lib, 'SimbaPluginTarget_KeyCodeFromChar'); Pointer(KeyPressed) := GetProcedureAddress(Lib, 'SimbaPluginTarget_KeyPressed'); end; end; @@ -211,33 +214,43 @@ procedure PluginTarget_MouseScroll(Target: Pointer; Scrolls: Integer); end; end; -procedure PluginTarget_KeyDown(Target: Pointer; Key: EKeyCode); +function PluginTarget_KeyCodeFromChar(Target: Pointer; Key: Char): EKeyCode; begin with PSimbaPluginTarget(Target)^ do begin - CheckExported('SimbaPluginTarget_KeyDown', KeyDown); + CheckExported('SimbaPluginTarget_KeyCodeFromChar', KeyCodeFromChar); - KeyDown(Target, Integer(Key)); + Result := KeyCodeFromChar(Target, Key); end; end; -procedure PluginTarget_KeyUp(Target: Pointer; Key: EKeyCode); +procedure PluginTarget_KeyModifiers(Target: Pointer; Key: Char; out Shift, Ctrl, Alt: Boolean); begin with PSimbaPluginTarget(Target)^ do begin - CheckExported('SimbaPluginTarget_KeyUp', KeyUp); + CheckExported('SimbaPluginTarget_KeyModifiers', KeyModifiers); - KeyUp(Target, Integer(Key)); + KeyModifiers(Target, Key, Shift, Ctrl, Alt); end; end; -procedure PluginTarget_KeySend(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); +procedure PluginTarget_KeyDown(Target: Pointer; Key: EKeyCode); begin with PSimbaPluginTarget(Target)^ do begin - CheckExported('SimbaPluginTarget_KeySend', KeySend); + CheckExported('SimbaPluginTarget_KeyDown', KeyDown); - KeySend(Target, Key, KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime); + KeyDown(Target, Integer(Key)); + end; +end; + +procedure PluginTarget_KeyUp(Target: Pointer; Key: EKeyCode); +begin + with PSimbaPluginTarget(Target)^ do + begin + CheckExported('SimbaPluginTarget_KeyUp', KeyUp); + + KeyUp(Target, Integer(Key)); end; end; diff --git a/Source/targets/simba.target_window.pas b/Source/targets/simba.target_window.pas index 162d5710f..e01597518 100644 --- a/Source/targets/simba.target_window.pas +++ b/Source/targets/simba.target_window.pas @@ -15,9 +15,10 @@ function WindowTarget_Focus(Target: Pointer): Boolean; function WindowTarget_IsFocused(Target: Pointer): Boolean; function WindowTarget_IsValid(Target: Pointer): Boolean; +function WindowTarget_KeyCodeFromChar(Target: Pointer; Key: Char): EKeyCode; +procedure WindowTarget_KeyModifiersFromChar(Target: Pointer; Key: Char; out Shift, Ctrl, Alt: Boolean); procedure WindowTarget_KeyDown(Target: Pointer; Key: EKeyCode); procedure WindowTarget_KeyUp(Target: Pointer; Key: EKeyCode); -procedure WindowTarget_KeySend(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); function WindowTarget_KeyPressed(Target: Pointer; Key: EKeyCode): Boolean; procedure WindowTarget_MouseTeleport(Target: Pointer; P: TPoint); @@ -69,6 +70,16 @@ function WindowTarget_IsValid(Target: Pointer): Boolean; Result := SimbaNativeInterface.IsWindowValid(PWindowHandle(Target)^); end; +function WindowTarget_KeyCodeFromChar(Target: Pointer; Key: Char): EKeyCode; +begin + Result := SimbaNativeInterface.KeyCodeFromChar(Key); +end; + +procedure WindowTarget_KeyModifiersFromChar(Target: Pointer; Key: Char; out Shift, Ctrl, Alt: Boolean); +begin + SimbaNativeInterface.KeyModifiersFromChar(Key, Shift, Ctrl, Alt); +end; + procedure WindowTarget_KeyDown(Target: Pointer; Key: EKeyCode); begin SimbaNativeInterface.KeyDown(Key); @@ -79,11 +90,6 @@ procedure WindowTarget_KeyUp(Target: Pointer; Key: EKeyCode); SimbaNativeInterface.KeyUp(Key); end; -procedure WindowTarget_KeySend(Target: Pointer; Key: Char; KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime: Integer); -begin - SimbaNativeInterface.KeySend(Key, KeyDownTime, KeyUpTime, ModifierDownTime, ModifierUpTime); -end; - function WindowTarget_KeyPressed(Target: Pointer; Key: EKeyCode): Boolean; begin Result := SimbaNativeInterface.KeyPressed(Key);