mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2026-01-04 18:30:32 +01:00
MouseAndKeyInput: Support Cocoa. Based on patch by Sammarco Francesco.
This commit is contained in:
parent
bd2b087fa7
commit
60178cd372
255
components/mouseandkeyinput/cocoakeyinput.pas
Normal file
255
components/mouseandkeyinput/cocoakeyinput.pas
Normal file
@ -0,0 +1,255 @@
|
||||
{ CocoaKeyInput
|
||||
|
||||
Copyright (C) 2019 Sammarco Francesco
|
||||
|
||||
This source is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
A copy of the GNU General Public License is available on the World Wide Web at
|
||||
<http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
|
||||
}
|
||||
unit CocoaKeyInput;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
MacOSAll,
|
||||
Classes, SysUtils, Controls, Forms,
|
||||
CocoaUtils, CGEventSource, CGEvent, CGEventTypes, CGRemoteOperation, CFBase,
|
||||
KeyInputIntf;
|
||||
|
||||
type
|
||||
|
||||
{ TCocoaKeyInput }
|
||||
|
||||
TCocoaKeyInput = class(TKeyInput)
|
||||
protected
|
||||
procedure DoDown(Key: Word); override;
|
||||
procedure DoUp(Key: Word); override;
|
||||
end;
|
||||
|
||||
function InitializeKeyInput: TKeyInput;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
LCLType;
|
||||
|
||||
function InitializeKeyInput: TKeyInput;
|
||||
begin
|
||||
Result := TCocoaKeyInput.Create;
|
||||
end;
|
||||
|
||||
function VKToMacCode(AKey: Word): Word;
|
||||
begin
|
||||
case AKey of
|
||||
VK_A : Result := kVK_ANSI_A;
|
||||
VK_S : Result := kVK_ANSI_S;
|
||||
VK_D : Result := kVK_ANSI_D;
|
||||
VK_F : Result := kVK_ANSI_F;
|
||||
VK_H : Result := kVK_ANSI_H;
|
||||
VK_G : Result := kVK_ANSI_G;
|
||||
VK_Z : Result := kVK_ANSI_Z;
|
||||
VK_X : Result := kVK_ANSI_X;
|
||||
VK_C : Result := kVK_ANSI_C;
|
||||
VK_V : Result := kVK_ANSI_V;
|
||||
|
||||
//kVK_ISO_Section // ISO keyboard only
|
||||
|
||||
VK_B : Result := kVK_ANSI_B;
|
||||
VK_Q : Result := kVK_ANSI_Q;
|
||||
VK_W : Result := kVK_ANSI_W;
|
||||
VK_E : Result := kVK_ANSI_E;
|
||||
VK_R : Result := kVK_ANSI_R;
|
||||
VK_Y : Result := kVK_ANSI_Y;
|
||||
VK_T : Result := kVK_ANSI_T;
|
||||
VK_1 : Result := kVK_ANSI_1;
|
||||
VK_2 : Result := kVK_ANSI_2;
|
||||
VK_3 : Result := kVK_ANSI_3;
|
||||
VK_4 : Result := kVK_ANSI_4;
|
||||
VK_6 : Result := kVK_ANSI_6;
|
||||
VK_5 : Result := kVK_ANSI_5;
|
||||
VK_LCL_EQUAL : Result := kVK_ANSI_Equal; // aka VK_EQUAL = 187 = $BB;
|
||||
VK_9 : Result := kVK_ANSI_9;
|
||||
VK_7 : Result := kVK_ANSI_7;
|
||||
VK_OEM_MINUS : Result := kVK_ANSI_Minus;
|
||||
VK_8 : Result := kVK_ANSI_8;
|
||||
VK_0 : Result := kVK_ANSI_0;
|
||||
VK_OEM_6 : Result := kVK_ANSI_RightBracket;
|
||||
VK_O : Result := kVK_ANSI_O;
|
||||
VK_U : Result := kVK_ANSI_U;
|
||||
VK_LCL_OPEN_BRAKET : Result := kVK_ANSI_LeftBracket;
|
||||
VK_I : Result := kVK_ANSI_I;
|
||||
VK_P : Result := kVK_ANSI_P;
|
||||
|
||||
VK_RETURN : Result := kVK_Return;
|
||||
|
||||
VK_L : Result := kVK_ANSI_L;
|
||||
VK_J : Result := kVK_ANSI_J;
|
||||
VK_LCL_QUOTE : Result := kVK_ANSI_Quote;
|
||||
VK_K : Result := kVK_ANSI_K;
|
||||
VK_LCL_SEMI_COMMA : Result := kVK_ANSI_Semicolon;
|
||||
VK_LCL_BACKSLASH : Result := kVK_ANSI_Backslash;
|
||||
VK_LCL_COMMA : Result := kVK_ANSI_Comma;
|
||||
VK_LCL_SLASH : Result := kVK_ANSI_Slash;
|
||||
VK_N : Result := kVK_ANSI_N;
|
||||
VK_M : Result := kVK_ANSI_M;
|
||||
VK_LCL_POINT : Result := kVK_ANSI_Period;
|
||||
|
||||
VK_TAB : Result := kVK_Tab;
|
||||
VK_SPACE : Result := kVK_Space;
|
||||
|
||||
VK_LCL_TILDE : Result := kVK_ANSI_Grave;
|
||||
|
||||
VK_BACK : Result := kVK_Delete;
|
||||
VK_DELETE : Result := kVK_Delete; //Added from Francesco Sammarco
|
||||
|
||||
VK_ESCAPE : Result := kVK_Escape;
|
||||
VK_LWIN : Result := kVK_Command;
|
||||
// todo: Application.ExtendedKeysSupport must be true!
|
||||
|
||||
VK_SHIFT : Result := kVK_Shift; //Added from Francesco Sammarco
|
||||
VK_MENU : Result := kVK_Option; //Added from Francesco Sammarco
|
||||
VK_CONTROL : Result := kVK_Control; //Added from Francesco Sammarco
|
||||
|
||||
|
||||
VK_LSHIFT : Result := kVK_Shift;
|
||||
VK_CAPITAL : Result := kVK_CapsLock;
|
||||
VK_LMENU : Result := kVK_Option;
|
||||
VK_LCONTROL : Result := kVK_Control;
|
||||
VK_RSHIFT : Result := kVK_RightShift;
|
||||
VK_RMENU : Result := kVK_RightOption;
|
||||
VK_RCONTROL : Result := kVK_RightControl;
|
||||
//kVK_Function : Result := VK_; todo:
|
||||
VK_F17 : Result := kVK_F17;
|
||||
|
||||
VK_DECIMAL : Result := kVK_ANSI_KeypadDecimal;
|
||||
VK_MULTIPLY : Result := kVK_ANSI_KeypadMultiply;
|
||||
VK_ADD : Result := kVK_ANSI_KeypadPlus;
|
||||
VK_NUMLOCK : Result := kVK_ANSI_KeypadClear;
|
||||
|
||||
VK_VOLUME_UP : Result := kVK_VolumeUp;
|
||||
VK_VOLUME_DOWN : Result := kVK_VolumeDown;
|
||||
VK_VOLUME_MUTE : Result := kVK_Mute;
|
||||
|
||||
VK_DIVIDE : Result := kVK_ANSI_KeypadDivide;
|
||||
//VK_RETURN : Result := kVK_ANSI_KeypadEnter; //Commented from Francesco Sammarco (duplicate VK_RETURN)
|
||||
VK_SUBTRACT : Result := kVK_ANSI_KeypadMinus;
|
||||
|
||||
VK_F18 : Result := kVK_F18;
|
||||
VK_F19 : Result := kVK_F19;
|
||||
|
||||
//kVK_ANSI_KeypadEquals : Result := VK_;
|
||||
VK_NUMPAD0 : Result := kVK_ANSI_Keypad0;
|
||||
VK_NUMPAD1 : Result := kVK_ANSI_Keypad1;
|
||||
VK_NUMPAD2 : Result := kVK_ANSI_Keypad2;
|
||||
VK_NUMPAD3 : Result := kVK_ANSI_Keypad3;
|
||||
VK_NUMPAD4 : Result := kVK_ANSI_Keypad4;
|
||||
VK_NUMPAD5 : Result := kVK_ANSI_Keypad5;
|
||||
VK_NUMPAD6 : Result := kVK_ANSI_Keypad6;
|
||||
VK_NUMPAD7 : Result := kVK_ANSI_Keypad7;
|
||||
|
||||
VK_F20 : Result := kVK_F20;
|
||||
|
||||
VK_NUMPAD8 : Result := kVK_ANSI_Keypad8;
|
||||
VK_NUMPAD9 : Result := kVK_ANSI_Keypad9;
|
||||
|
||||
//kVK_JIS_Yen = $5D;
|
||||
//kVK_JIS_Underscore = $5E;
|
||||
//kVK_JIS_KeypadComma = $5F;
|
||||
|
||||
VK_F5 : Result := kVK_F5;
|
||||
VK_F6 : Result := kVK_F6;
|
||||
VK_F7 : Result := kVK_F7;
|
||||
VK_F3 : Result := kVK_F3;
|
||||
VK_F8 : Result := kVK_F8;
|
||||
VK_F9 : Result := kVK_F9;
|
||||
|
||||
//kVK_JIS_Eisu = $66;
|
||||
VK_KANA : Result := kVK_JIS_Kana;
|
||||
|
||||
VK_F11 : Result := kVK_F11;
|
||||
|
||||
VK_SNAPSHOT : Result := kVK_F13;
|
||||
VK_F16 : Result := kVK_F16;
|
||||
VK_SCROLL : Result := kVK_F14;
|
||||
VK_F10 : Result := kVK_F10;
|
||||
|
||||
VK_APPS : Result := kVK_SubMenu;
|
||||
|
||||
VK_F12 : Result := kVK_F12;
|
||||
VK_PAUSE : Result := kVK_F15;
|
||||
VK_HELP : Result := kVK_Help; //VK_INSERT; // todo!
|
||||
VK_HOME : Result := kVK_Home;
|
||||
VK_PRIOR : Result := kVK_PageUp;
|
||||
//VK_DELETE : Result := kVK_ForwardDelete; // Commented from Francesco Sammarco
|
||||
VK_F4 : Result := kVK_F4;
|
||||
VK_END : Result := kVK_End;
|
||||
VK_F2 : Result := kVK_F2;
|
||||
VK_NEXT : Result := kVK_PageDown;
|
||||
VK_F1 : Result := kVK_F1;
|
||||
VK_LEFT : Result := kVK_LeftArrow;
|
||||
VK_RIGHT : Result := kVK_RightArrow;
|
||||
VK_DOWN : Result := kVK_DownArrow;
|
||||
VK_UP : Result := kVK_UpArrow;
|
||||
|
||||
else
|
||||
Result := VK_UNKNOWN;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SendKeyInput(Key: Word; Down: Boolean);
|
||||
var
|
||||
EventSourceRef : CGEventSourceRef;
|
||||
KeyDownRef, KeyUpRef: CGEventRef;
|
||||
begin
|
||||
|
||||
EventSourceRef := CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
if EventSourceRef = nil then RaiseLastOSError;
|
||||
try
|
||||
|
||||
if Down then
|
||||
begin
|
||||
KeyDownRef := CGEventCreateKeyboardEvent(EventSourceRef, VKToMacCode(Key), 1); //1 = key down
|
||||
if KeyDownRef = nil then RaiseLastOSError;
|
||||
CGEventSetFlags(KeyDownRef, CGEventGetFlags(KeyDownRef)); //combine flags
|
||||
CGEventPost(kCGHIDEventTap, KeyDownRef);
|
||||
end else begin
|
||||
KeyUpRef := CGEventCreateKeyboardEvent(EventSourceRef, VKToMacCode(Key), 0); //0 = key up
|
||||
if KeyUpRef = nil then RaiseLastOSError;
|
||||
CGEventSetFlags(KeyDownRef, CGEventGetFlags(KeyDownRef)); //combine flags
|
||||
CGEventPost(kCGHIDEventTap, KeyUpRef);
|
||||
end;
|
||||
|
||||
finally
|
||||
if Down then
|
||||
if KeyDownRef <> nil then CFRelease(KeyDownRef)
|
||||
else
|
||||
if KeyUpRef <> nil then CFRelease(KeyUpRef);
|
||||
CFRelease(EventSourceRef);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
{ TCocoaKeyInput }
|
||||
procedure TCocoaKeyInput.DoDown(Key: Word);
|
||||
begin
|
||||
SendKeyInput(Key, True);
|
||||
end;
|
||||
|
||||
procedure TCocoaKeyInput.DoUp(Key: Word);
|
||||
begin
|
||||
SendKeyInput(Key, False);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
90
components/mouseandkeyinput/cocoamouseinput.pas
Normal file
90
components/mouseandkeyinput/cocoamouseinput.pas
Normal file
@ -0,0 +1,90 @@
|
||||
{ CocoaMouseInput
|
||||
|
||||
Copyright (C) 2019 Sammarco Francesco
|
||||
|
||||
This source is free software; you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
A copy of the GNU General Public License is available on the World Wide Web at
|
||||
<http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.
|
||||
}
|
||||
unit CocoaMouseInput;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Controls, Forms,
|
||||
CocoaUtils, CocoaAll, CGGeometry, CGEvent, CGEventTypes, CFBase,
|
||||
MouseInputIntf;
|
||||
|
||||
type
|
||||
|
||||
{ TCocoaMouseInput }
|
||||
|
||||
TCocoaMouseInput = class(TMouseInput)
|
||||
protected
|
||||
procedure DoDown(Button: TMouseButton); override;
|
||||
procedure DoMove(ScreenX, ScreenY: Integer); override;
|
||||
procedure DoUp(Button: TMouseButton); override;
|
||||
end;
|
||||
|
||||
function InitializeMouseInput: TMouseInput;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
function InitializeMouseInput: TMouseInput;
|
||||
begin
|
||||
Result := TCocoaMouseInput.Create;
|
||||
end;
|
||||
|
||||
const
|
||||
MouseButtonToCocoaButton: array [TMouseButton] of Integer =
|
||||
(kCGMouseButtonLeft, kCGMouseButtonRight, kCGMouseButtonCenter,3,4);
|
||||
|
||||
|
||||
{ TCocoaMouseInput }
|
||||
|
||||
procedure TCocoaMouseInput.DoDown(Button: TMouseButton);
|
||||
var
|
||||
MyMouseEvent : CGEventRef;
|
||||
begin
|
||||
if Button = mbLeft then
|
||||
MyMouseEvent := CGEventCreateMouseEvent(nil, 1, CGPointMake(Mouse.CursorPos.x, Mouse.CursorPos.y), MouseButtonToCocoaButton[Button])
|
||||
else
|
||||
MyMouseEvent := CGEventCreateMouseEvent(nil, 3, CGPointMake(Mouse.CursorPos.x, Mouse.CursorPos.y), MouseButtonToCocoaButton[Button]);
|
||||
CGEventPost(kCGHIDEventTap,MyMouseEvent);
|
||||
CFRelease(MyMouseEvent);
|
||||
end;
|
||||
|
||||
procedure TCocoaMouseInput.DoMove(ScreenX, ScreenY: Integer);
|
||||
var
|
||||
MyMouseEvent : CGEventRef;
|
||||
begin
|
||||
MyMouseEvent := CGEventCreateMouseEvent(nil, 5, CGPointMake(ScreenX, ScreenY), MouseButtonToCocoaButton[mbLeft]);
|
||||
CGEventPost(kCGHIDEventTap,MyMouseEvent);
|
||||
CFRelease(MyMouseEvent);
|
||||
end;
|
||||
|
||||
procedure TCocoaMouseInput.DoUp(Button: TMouseButton);
|
||||
var
|
||||
MyMouseEvent : CGEventRef;
|
||||
begin
|
||||
if Button = mbLeft then
|
||||
MyMouseEvent := CGEventCreateMouseEvent(nil, 2, CGPointMake(Mouse.CursorPos.x, Mouse.CursorPos.y), MouseButtonToCocoaButton[Button])
|
||||
else
|
||||
MyMouseEvent := CGEventCreateMouseEvent(nil, 4, CGPointMake(Mouse.CursorPos.x, Mouse.CursorPos.y), MouseButtonToCocoaButton[Button]);
|
||||
CGEventPost(kCGHIDEventTap,MyMouseEvent);
|
||||
CFRelease(MyMouseEvent);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -22,62 +22,71 @@
|
||||
"/>
|
||||
<License Value="GPL
|
||||
"/>
|
||||
<Version Minor="1"/>
|
||||
<Files Count="9">
|
||||
<Item1>
|
||||
<Version Minor="9"/>
|
||||
<Files>
|
||||
<Item>
|
||||
<Filename Value="carbonkeyinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="CarbonKeyInput"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="carbonmouseinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="CarbonMouseInput"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="cocoakeyinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="CocoaKeyInput"/>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="cocoamouseinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="CocoaMouseInput"/>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="keyinputintf.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="KeyInputIntf"/>
|
||||
</Item3>
|
||||
<Item4>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="mouseandkeyinput.pas"/>
|
||||
<UnitName Value="MouseAndKeyInput"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="mouseinputintf.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="MouseInputIntf"/>
|
||||
</Item5>
|
||||
<Item6>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="winkeyinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="WinKeyInput"/>
|
||||
</Item6>
|
||||
<Item7>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="winmouseinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="WinMouseInput"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="xkeyinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="XKeyInput"/>
|
||||
</Item8>
|
||||
<Item9>
|
||||
</Item>
|
||||
<Item>
|
||||
<Filename Value="xmouseinput.pas"/>
|
||||
<AddToUsesPkgSection Value="False"/>
|
||||
<UnitName Value="XMouseInput"/>
|
||||
</Item9>
|
||||
</Item>
|
||||
</Files>
|
||||
<CompatibilityMode Value="True"/>
|
||||
<RequiredPkgs Count="2">
|
||||
<Item1>
|
||||
<RequiredPkgs>
|
||||
<Item>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
</Item>
|
||||
<Item>
|
||||
<PackageName Value="FCL"/>
|
||||
<MinVersion Major="1" Valid="True"/>
|
||||
</Item2>
|
||||
</Item>
|
||||
</RequiredPkgs>
|
||||
<UsageOptions>
|
||||
<UnitPath Value="$(PkgOutDir)"/>
|
||||
|
||||
@ -26,9 +26,12 @@ uses
|
||||
WinKeyInput,
|
||||
{$ENDIF}
|
||||
{$IFDEF UNIX}
|
||||
{$IFDEF LCLcarbon}
|
||||
{$IF DEFINED(LCLcarbon)}
|
||||
CarbonMouseInput,
|
||||
CarbonKeyInput,
|
||||
{$ELSEIF DEFINED(LCLcocoa)}
|
||||
CocoaMouseInput,
|
||||
CocoaKeyInput,
|
||||
{$ELSE}
|
||||
XMouseInput,
|
||||
XKeyInput,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user