Skip to content

Commit

Permalink
Macos
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Oct 8, 2023
1 parent e9489a5 commit 690361a
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 63 deletions.
2 changes: 1 addition & 1 deletion Source/simba.darwin_axui.pas
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ function AXUI_GetWindowInfo(PID: UInt32): TAXUIWindowInfo;
end;

initialization
SimbaIDEInitialization_AddBeforeShow(@RequestAccessibility, 'RequestAccessibility');
// SimbaIDEInitialization_AddBeforeShow(@RequestAccessibility, 'RequestAccessibility');

CreateCFStrings();

Expand Down
252 changes: 190 additions & 62 deletions Source/simba.nativeinterface_darwin.pas
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -28,17 +28,20 @@ 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
Expand Down Expand Up @@ -300,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;
Expand Down Expand Up @@ -513,12 +633,28 @@ function TSimbaNativeInterface_Darwin.MousePressed(Button: EMouseButton): Boolea

function TSimbaNativeInterface_Darwin.KeyCodeFromChar(Key: Char): EKeyCode;
begin
BuildKeyMap();

if FKeyMap[Key].Exists then
Result := NativeKeyCodeToVirtualKeyCode(FKeyMap[Key].KeyCode)
else
Result := EKeyCode.UNKNOWN;
end;

procedure TSimbaNativeInterface_Darwin.KeyModifiersFromChar(Key: Char; out Shift, Ctrl, Alt: Boolean);
var
ShiftState: TShiftState;
begin
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;

function TSimbaNativeInterface_Darwin.KeyPressed(Key: EKeyCode): Boolean;
Expand All @@ -536,29 +672,6 @@ procedure TSimbaNativeInterface_Darwin.KeyUp(Key: EKeyCode);
CGPostKeyboardEvent(0, VirtualKeyToNativeKeyCode(Key), 0);
end;

{
procedure TSimbaNativeInterface_Darwin.KeyDownNativeKeyCode(EKeyCode: Integer);
begin
CGPostKeyboardEvent(0, EKeyCode, 1);
end;
procedure TSimbaNativeInterface_Darwin.KeyUpNativeKeyCode(EKeyCode: Integer);
begin
CGPostKeyboardEvent(0, EKeyCode, 0);
end;
function TSimbaNativeInterface_Darwin.GetNativeKeyCodeAndModifiers(Character: Char; out Code: Integer; out Modifiers: TShiftState): Boolean;
begin
Result := FKeyMap[Character].Exists;
if Result then
begin
Code := FKeyMap[Character].EKeyCode;
Modifiers := FKeyMap[Character].Modifiers;
end
end;
}

function TSimbaNativeInterface_Darwin.GetProcessStartTime(PID: SizeUInt): TDateTime;
var
info: proc_bsdinfo;
Expand Down Expand Up @@ -882,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;
begin
VirtualWindow := TVirtualWindow(Window);

Result := VirtualWindow.InfoIndex > 0;
end;

function TSimbaNativeInterface_Darwin.GetVirtualWindowInfoIndex(ClientRect: TBox; ClassStr: ShortString): Integer;
var
I: Integer;
procedure TSimbaNativeInterface_Darwin.CheckAccessibility;
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
Expand All @@ -915,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;
Expand Down

0 comments on commit 690361a

Please sign in to comment.