mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-14 03:19:32 +02:00
Advances keyboard events in Android and X11. Simple key down/up can already be received in both
git-svn-id: trunk@34207 -
This commit is contained in:
parent
fb0efe6763
commit
05cd46835f
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -3357,6 +3357,7 @@ examples/anchordocking/minide/unit1.lfm svneol=native#text/plain
|
||||
examples/anchordocking/minide/unit1.pas svneol=native#text/plain
|
||||
examples/androidlcl/android/AndroidManifest.xml svneol=native#text/plain
|
||||
examples/androidlcl/android/build.properties svneol=native#text/plain
|
||||
examples/androidlcl/android/build.sh svneol=native#text/plain
|
||||
examples/androidlcl/android/build.xml svneol=native#text/plain
|
||||
examples/androidlcl/android/default.properties svneol=native#text/plain
|
||||
examples/androidlcl/android/local.properties svneol=native#text/plain
|
||||
|
4
examples/androidlcl/android/build.sh
Executable file
4
examples/androidlcl/android/build.sh
Executable file
@ -0,0 +1,4 @@
|
||||
ant debug
|
||||
~/Programas/android-sdk-linux/platform-tools/adb uninstall com.pascal.lcltest
|
||||
~/Programas/android-sdk-linux/platform-tools/adb install bin/LCLExample-debug.apk
|
||||
~/Programas/android-sdk-linux/platform-tools/adb logcat
|
@ -8,6 +8,7 @@ object Form1: TForm1
|
||||
ClientWidth = 220
|
||||
OnClick = FormClick
|
||||
OnCreate = FormCreate
|
||||
OnKeyDown = Button1KeyDown
|
||||
OnMouseMove = FormMouseMove
|
||||
OnPaint = FormPaint
|
||||
LCLVersion = '0.9.31'
|
||||
@ -28,6 +29,7 @@ object Form1: TForm1
|
||||
Width = 116
|
||||
Caption = 'Move Progress'
|
||||
OnClick = Button1Click
|
||||
OnKeyDown = Button1KeyDown
|
||||
TabOrder = 1
|
||||
end
|
||||
object ProgressBar1: TProgressBar
|
||||
|
@ -30,6 +30,8 @@ type
|
||||
procedure Arrow1MouseUp(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure Button1Click(Sender: TObject);
|
||||
procedure Button1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
|
||||
);
|
||||
procedure Button2Click(Sender: TObject);
|
||||
procedure Button3Click(Sender: TObject);
|
||||
procedure FormClick(Sender: TObject);
|
||||
@ -140,6 +142,13 @@ begin
|
||||
ProgressBar1.Position := ProgressBar1.Position + 10;
|
||||
end;
|
||||
|
||||
procedure TForm1.Button1KeyDown(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
begin
|
||||
DebugLn('[TForm1.Button1KeyDown] '+ LCLProc.DbgsVKCode(Key));
|
||||
Caption := LCLProc.DbgsVKCode(Key);
|
||||
end;
|
||||
|
||||
procedure TForm1.Button2Click(Sender: TObject);
|
||||
begin
|
||||
Application.OnMessageDialogFinished := @HandleMessageDialogFinished;
|
||||
|
@ -49,9 +49,6 @@
|
||||
</CompilerOptions>
|
||||
</Item2>
|
||||
<Item3 Name="NotCustomDrawn">
|
||||
<MacroValues Count="1">
|
||||
<Macro1 Name="LCLWidgetType" Value="carbon"/>
|
||||
</MacroValues>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<Target>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
|
||||
ComCtrls;
|
||||
ComCtrls, ExtCtrls;
|
||||
|
||||
type
|
||||
|
||||
@ -15,6 +15,7 @@ type
|
||||
TForm2 = class(TForm)
|
||||
Button1: TButton;
|
||||
Edit1: TEdit;
|
||||
Image1: TImage;
|
||||
procedure Button1Click(Sender: TObject);
|
||||
private
|
||||
{ private declarations }
|
||||
|
@ -134,6 +134,13 @@ type
|
||||
FWMDeleteWindow: TAtom; // Atom for "WM_DELETE_WINDOW"
|
||||
FWMHints: TAtom; // Atom for "_MOTIF_WM_HINTS"
|
||||
|
||||
// For composing character events
|
||||
ComposeBuffer: string;
|
||||
ComposeStatus: TStatus;
|
||||
InputMethod: xlib.PXIM;
|
||||
InputContext: PXIC;
|
||||
LastKeySym: TKeySym; // Used for KeyRelease event
|
||||
|
||||
function FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
|
||||
{$endif}
|
||||
{$ifdef CD_Android}
|
||||
@ -146,13 +153,14 @@ type
|
||||
AccumulatedStr: string;
|
||||
// The currently focused control
|
||||
FocusedControl: TWinControl;
|
||||
FocusedIntfControl: TWinControl;
|
||||
// Default Fonts
|
||||
DefaultFont: TFPCustomFont;
|
||||
DefaultFontAndroidSize: Integer;
|
||||
// For unusual implementations of DebugLn/DebugOut
|
||||
procedure AccumulatingDebugOut(AStr: string);
|
||||
//
|
||||
procedure CDSetFocusToControl(ALCLControl: TWinControl);
|
||||
procedure CDSetFocusToControl(ALCLControl, AIntfControl: TWinControl);
|
||||
//
|
||||
protected
|
||||
{function CreateThemeServices: TThemeServices; override;}
|
||||
@ -161,6 +169,7 @@ type
|
||||
//
|
||||
procedure BackendCreate;
|
||||
procedure BackendDestroy;
|
||||
procedure BackendInit;
|
||||
public
|
||||
// ScreenDC and Image for doing Canvas operations outside the Paint event
|
||||
// and also for text drawing operations
|
||||
|
@ -20,7 +20,7 @@ begin
|
||||
AccumulatedStr := AccumulatedStr + AStr;
|
||||
end;
|
||||
|
||||
procedure TCDWidgetSet.CDSetFocusToControl(ALCLControl: TWinControl);
|
||||
procedure TCDWidgetSet.CDSetFocusToControl(ALCLControl, AIntfControl: TWinControl);
|
||||
begin
|
||||
if (CDWidgetset.FocusedControl <> ALCLControl) then
|
||||
begin
|
||||
@ -29,6 +29,12 @@ begin
|
||||
LCLSendKillFocusMsg(CDWidgetset.FocusedControl);
|
||||
CDWidgetset.FocusedControl := ALCLControl;
|
||||
LCLSendSetFocusMsg(ALCLControl);
|
||||
|
||||
// The same for intf controls
|
||||
if CDWidgetset.FocusedIntfControl <> nil then
|
||||
LCLSendKillFocusMsg(CDWidgetset.FocusedIntfControl);
|
||||
CDWidgetset.FocusedIntfControl := AIntfControl;
|
||||
if AIntfControl <> nil then LCLSendSetFocusMsg(AIntfControl);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -42,25 +42,17 @@ begin
|
||||
eventResult := 0;
|
||||
|
||||
lCurForm := GetCurrentForm();
|
||||
lTarget := FindControlWhichReceivedEvent(lCurForm.LCLForm, lCurForm.Children, Round(X), Round(Y));
|
||||
lEventPos := FormPosToControlPos(lTarget, Round(X), Round(Y));
|
||||
|
||||
case action of
|
||||
ACTION_DOWN:
|
||||
begin
|
||||
lCurForm.LastMouseDownControl := lTarget;
|
||||
LCLSendMouseDownMsg(lTarget, lEventPos.X, lEventPos.Y, mbLeft, []);
|
||||
CallbackMouseDown(lCurForm, Round(X), Round(Y), mbLeft, []);
|
||||
end;
|
||||
ACTION_UP:
|
||||
begin
|
||||
if lCurForm.LastMouseDownControl <> nil then lTarget := lCurForm.LastMouseDownControl;
|
||||
LCLSendMouseUpMsg(lTarget, lEventPos.X, lEventPos.Y, mbLeft, []);
|
||||
LCLSendClickedMsg(lTarget);
|
||||
|
||||
// If the target is focusable, a mouse up will give it focus
|
||||
CDWidgetset.CDSetFocusToControl(lTarget);
|
||||
CallbackMouseUp(lCurForm, Round(X), Round(Y), mbLeft, []);
|
||||
end;
|
||||
ACTION_MOVE: LCLSendMouseMoveMsg(lTarget, lEventPos.X, lEventPos.Y, []);
|
||||
ACTION_MOVE: CallbackMouseMove(lCurForm, Round(X), Round(Y), []);
|
||||
end;
|
||||
|
||||
// This sends messages like Invalidate requests
|
||||
@ -156,36 +148,33 @@ begin
|
||||
eventResult := 0;
|
||||
|
||||
lCurForm := GetCurrentForm();
|
||||
lTarget := lCurForm.GetFocusedControl();
|
||||
lKey := CDWidgetset.AndroidKeyCodeToLCLKeyCode(AKeyCode);
|
||||
|
||||
case AKind of
|
||||
ACTION_DOWN:
|
||||
begin
|
||||
LCLSendKeyDownEvent(lTarget, lKey, 0, False, False);
|
||||
end;
|
||||
ACTION_DOWN: CallbackKeyDown(lCurForm, lKey);
|
||||
ACTION_UP:
|
||||
begin
|
||||
LCLSendKeyUpEvent(lTarget, lKey, 0, False, False);
|
||||
CallbackKeyUp(lCurForm, lKey);
|
||||
if AChar <> 0 then
|
||||
begin
|
||||
LCLSendCharEvent(lTarget, lKey, 0, False, False, True);
|
||||
SetLength(AWideText, 1);
|
||||
AWideText[1] := WideChar(AChar);
|
||||
AUTF8Text := UTF16ToUTF8(AWideText);
|
||||
AUTF8Char := AUTF8Text;
|
||||
LCLSendUTF8KeyPress(lTarget, AUTF8Char, False);
|
||||
CallbackKeyChar(lCurForm, lKey, AUTF8Char);
|
||||
end;
|
||||
|
||||
// Handle the Back hardware key
|
||||
if AKeyCode = AKEYCODE_BACK then
|
||||
begin
|
||||
// The back hardware key hides the current form and shows the one bellow it
|
||||
lForm := GetCurrentForm();
|
||||
HideForm(lForm);
|
||||
// If all forms got hidden, exit the application
|
||||
lForm := GetCurrentForm();
|
||||
if lForm = nil then eventResult := eventResult or 2;
|
||||
lForm := lCurForm;
|
||||
//DebugLn(Format('CallbackKeyUp D lForm=%x', [PtrInt(lForm)]));
|
||||
// If this is the main form, then go back to desktop
|
||||
if (Application.MainForm <> nil) and (lForm = TCDForm(Application.MainForm.Handle)) then
|
||||
eventResult := eventResult or 2
|
||||
// for other forms, hide them
|
||||
else HideForm(lForm);
|
||||
end;
|
||||
end;
|
||||
//ACTION_MULTIPLE:
|
||||
@ -405,9 +394,9 @@ begin
|
||||
AKEYCODE_NUM = 78;
|
||||
AKEYCODE_HEADSETHOOK = 79;
|
||||
AKEYCODE_FOCUS = 80; // *Camera* focus
|
||||
AKEYCODE_PLUS = 81;
|
||||
AKEYCODE_MENU = 82;
|
||||
AKEYCODE_NOTIFICATION = 83;
|
||||
AKEYCODE_PLUS = 81;}
|
||||
AKEYCODE_MENU: Result := VK_MENU;
|
||||
{ AKEYCODE_NOTIFICATION = 83;
|
||||
AKEYCODE_SEARCH = 84;
|
||||
AKEYCODE_MEDIA_PLAY_PAUSE = 85;
|
||||
AKEYCODE_MEDIA_STOP = 86;
|
||||
@ -506,6 +495,11 @@ begin
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TCDWidgetSet.BackendInit;
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TWinCEWidgetSet.AppInit
|
||||
Params: None
|
||||
|
@ -18,7 +18,12 @@
|
||||
*****************************************************************************
|
||||
}
|
||||
|
||||
function TCDWidgetSet.FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
|
||||
|
||||
// redefines:
|
||||
|
||||
function XOpenIM(para1: PDisplay; para2: PXrmHashBucketRec; para3: Pchar; para4: Pchar): PXIM; cdecl; external;
|
||||
function XCreateIC(para1: PXIM; para2: array of const): PXIC; cdecl; external;function TCDWidgetSet.FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
EndSubSearch: Boolean; { Necessary to quit the recursion }
|
||||
@ -70,6 +75,15 @@ procedure TCDWidgetSet.BackendDestroy;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TCDWidgetSet.BackendInit;
|
||||
begin
|
||||
InputMethod := XOpenIM(FDisplay, nil, nil, nil);
|
||||
if InputMethod <> nil then
|
||||
InputContext := XCreateIC(InputMethod, [XNInputStyle, XIMPreeditNothing or XIMStatusNothing, nil]);
|
||||
|
||||
if InputContext = nil then DebugLn('[TCDWidgetSet.BackendInit] Failed to initialize the Keyboard handling!');
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TWinCEWidgetSet.AppInit
|
||||
Params: None
|
||||
@ -94,6 +108,8 @@ begin
|
||||
if not Assigned(FDisplay) then
|
||||
raise Exception.Create('[TCDWidgetSet.AppInit] XOpenDisplay failed');
|
||||
|
||||
BackendInit();
|
||||
|
||||
//if (not (woX11SkipWMHints in WindowOptions)) and (woWindow in WindowOptions) then
|
||||
//begin
|
||||
LeaderWindow := XCreateSimpleWindow(FDisplay, XDefaultRootWindow(FDisplay), 0, 0, 1, 1, 0, 0, 0);
|
||||
|
@ -9,7 +9,7 @@ uses
|
||||
Types, Classes, SysUtils,
|
||||
// LCL
|
||||
Controls, Graphics, stdctrls, extctrls, comctrls,
|
||||
customdrawnproc, customdrawncontrols;
|
||||
customdrawnproc, customdrawncontrols, lcltype, lclproc;
|
||||
|
||||
type
|
||||
{ TCDIntfButton }
|
||||
@ -17,8 +17,6 @@ type
|
||||
TCDIntfButton = class(TCDButton)
|
||||
public
|
||||
LCLControl: TButton;
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
procedure HandleOnClick(Sender: TObject);
|
||||
end;
|
||||
|
||||
// These are default message handlers which backends might use to simplify their code
|
||||
@ -26,6 +24,10 @@ type
|
||||
procedure CallbackMouseUp(AWindowHandle: TCDForm; x, y: Integer; Button: TMouseButton; ShiftState: TShiftState = []);
|
||||
procedure CallbackMouseDown(AWindowHandle: TCDForm; x, y: Integer; Button: TMouseButton; ShiftState: TShiftState = []);
|
||||
procedure CallbackMouseMove(AWindowHandle: TCDForm; x, y: Integer; ShiftState: TShiftState = []);
|
||||
procedure CallbackKeyDown(AWindowHandle: TCDForm; AKey: Word);
|
||||
procedure CallbackKeyUp(AWindowHandle: TCDForm; AKey: Word);
|
||||
procedure CallbackKeyChar(AWindowHandle: TCDForm; AKey: Word; AChar: TUTF8Char);
|
||||
function IsIntfControl(AControl: TWinControl): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
@ -43,21 +45,40 @@ begin
|
||||
lEventPos := FormPosToControlPos(lTarget, x, y);
|
||||
LCLSendMouseUpMsg(lTarget, lEventPos.x, lEventPos.y, Button, ShiftState);
|
||||
LCLSendClickedMsg(lTarget);
|
||||
|
||||
// If this is a interface control, send the message to the main LCL control too
|
||||
if IsIntfControl(lTarget) then
|
||||
begin
|
||||
lTarget := lTarget.Parent;
|
||||
LCLSendMouseUpMsg(lTarget, lEventPos.x, lEventPos.y, Button, ShiftState);
|
||||
LCLSendClickedMsg(lTarget);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CallbackMouseDown(AWindowHandle: TCDForm; x, y: Integer; Button: TMouseButton; ShiftState: TShiftState = []);
|
||||
var
|
||||
lTarget: TWinControl;
|
||||
lIntfTarget: TWinControl = nil;
|
||||
lEventPos: TPoint;
|
||||
begin
|
||||
lTarget := FindControlWhichReceivedEvent(AWindowHandle.LCLForm, AWindowHandle.Children, x, y);
|
||||
AWindowHandle.LastMouseDownControl := lTarget;
|
||||
AWindowHandle.FocusedControl := lTarget;
|
||||
lEventPos := FormPosToControlPos(lTarget, x, y);
|
||||
|
||||
// If the target is focusable, a mouse down will give it focus
|
||||
CDWidgetset.CDSetFocusToControl(lTarget);
|
||||
|
||||
LCLSendMouseDownMsg(lTarget, lEventPos.x, lEventPos.y, Button, ShiftState);
|
||||
|
||||
// If this is a interface control, send the message to the main LCL control too
|
||||
if IsIntfControl(lTarget) then
|
||||
begin
|
||||
lIntfTarget := lTarget;
|
||||
lTarget := lTarget.Parent;
|
||||
|
||||
LCLSendMouseDownMsg(lTarget, lEventPos.x, lEventPos.y, Button, ShiftState);
|
||||
end;
|
||||
|
||||
// If the target is focusable, a mouse down will give it focus
|
||||
CDWidgetset.CDSetFocusToControl(lTarget, lIntfTarget);
|
||||
end;
|
||||
|
||||
procedure CallbackMouseMove(AWindowHandle: TCDForm; x, y: Integer; ShiftState: TShiftState = []);
|
||||
@ -72,20 +93,82 @@ begin
|
||||
|
||||
lEventPos := FormPosToControlPos(lTarget, x, y);
|
||||
LCLSendMouseMoveMsg(lTarget, lEventPos.x, lEventPos.y, ShiftState);
|
||||
|
||||
// If this is a interface control, send the message to the main LCL control too
|
||||
if IsIntfControl(lTarget) then
|
||||
begin
|
||||
lTarget := lTarget.Parent;
|
||||
|
||||
LCLSendMouseMoveMsg(lTarget, lEventPos.x, lEventPos.y, ShiftState);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TCDIntfButton }
|
||||
|
||||
constructor TCDIntfButton.Create(AOwner: TComponent);
|
||||
procedure CallbackKeyDown(AWindowHandle: TCDForm; AKey: Word);
|
||||
var
|
||||
lTarget: TWinControl;
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
OnClick := @HandleOnClick;
|
||||
lTarget := AWindowHandle.GetFocusedControl();
|
||||
{$ifdef VerboseCDEvents}
|
||||
DebugLn(Format('CallbackKeyDown FocusedControl=%s:%s AKey=%x', [lTarget.Name, lTarget.ClassName, AKey]));
|
||||
{$endif}
|
||||
|
||||
LCLSendKeyDownEvent(lTarget, AKey, 0, True, False);
|
||||
|
||||
// If this is a interface control, send the message to the main LCL control too
|
||||
if IsIntfControl(lTarget) then
|
||||
begin
|
||||
lTarget := lTarget.Parent;
|
||||
{$ifdef VerboseCDEvents}
|
||||
DebugLn(Format('CallbackKeyDown IsIntfControl, sending msg to Parent=%s:%s', [lTarget.Name, lTarget.ClassName]));
|
||||
{$endif}
|
||||
LCLSendKeyDownEvent(lTarget, AKey, 0, True, False);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCDIntfButton.HandleOnClick(Sender: TObject);
|
||||
procedure CallbackKeyUp(AWindowHandle: TCDForm; AKey: Word);
|
||||
var
|
||||
lTarget: TWinControl;
|
||||
begin
|
||||
if Assigned(LCLControl.OnClick) then
|
||||
LCLControl.OnClick(LCLControl);
|
||||
lTarget := AWindowHandle.GetFocusedControl();
|
||||
{$ifdef VerboseCDEvents}
|
||||
DebugLn(Format('CallbackKeyUp FocusedControl=%s:%s', [lTarget.Name, lTarget.ClassName]));
|
||||
{$endif}
|
||||
|
||||
LCLSendKeyUpEvent(lTarget, AKey, 0, True, False);
|
||||
|
||||
// If this is a interface control, send the message to the main LCL control too
|
||||
if IsIntfControl(lTarget) then
|
||||
begin
|
||||
lTarget := lTarget.Parent;
|
||||
LCLSendKeyUpEvent(lTarget, AKey, 0, True, False);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CallbackKeyChar(AWindowHandle: TCDForm; AKey: Word; AChar: TUTF8Char);
|
||||
var
|
||||
lTarget: TWinControl;
|
||||
begin
|
||||
lTarget := AWindowHandle.GetFocusedControl();
|
||||
{$ifdef VerboseCDEvents}
|
||||
DebugLn(Format('CallbackKeyChar FocusedControl=%s:%s', [lTarget.Name, lTarget.ClassName]));
|
||||
{$endif}
|
||||
|
||||
LCLSendCharEvent(lTarget, AKey, 0, True, False, True);
|
||||
LCLSendUTF8KeyPress(lTarget, AChar, False);
|
||||
|
||||
// If this is a interface control, send the message to the main LCL control too
|
||||
if IsIntfControl(lTarget) then
|
||||
begin
|
||||
lTarget := lTarget.Parent;
|
||||
LCLSendCharEvent(lTarget, AKey, 0, True, False, True);
|
||||
LCLSendUTF8KeyPress(lTarget, AChar, False);
|
||||
end;
|
||||
end;
|
||||
|
||||
function IsIntfControl(AControl: TWinControl): Boolean;
|
||||
begin
|
||||
Result := (AControl <> nil) and (AControl.Parent <> nil) and
|
||||
((AControl is TCDIntfButton) {or ...});
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -50,6 +50,7 @@ type
|
||||
NativeHandle: HWND;
|
||||
//
|
||||
LastMouseDownControl: TWinControl; // Stores the control which should receive the next MouseUp
|
||||
FocusedControl: TWinControl; // The control focused in the form
|
||||
// Counter to keep track of when we requested Invalidate
|
||||
// Some systems like X11 and Win32 will keep sending unnecessary paint messages
|
||||
// so for them we just throw the previously painted image
|
||||
@ -225,7 +226,7 @@ begin
|
||||
if lCurrentForm = ACDForm then
|
||||
begin
|
||||
lCurrentForm := FindTopMostVisibleForm();
|
||||
LCLIntf.InvalidateRect(lCurrentForm.NativeHandle, nil, True);
|
||||
LCLIntf.InvalidateRect(HWND(lCurrentForm), nil, True);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -648,7 +649,7 @@ end;
|
||||
|
||||
function TCDForm.GetFocusedControl: TWinControl;
|
||||
begin
|
||||
if LastMouseDownControl <> nil then Result := LastMouseDownControl
|
||||
if FocusedControl <> nil then Result := FocusedControl
|
||||
else Result := LCLForm;
|
||||
end;
|
||||
|
||||
|
@ -2884,8 +2884,9 @@ end;*)
|
||||
------------------------------------------------------------------------------}
|
||||
function TCDWidgetSet.GetFocus: HWND;
|
||||
begin
|
||||
if FocusedControl = nil then Result := 0
|
||||
else Result := FocusedControl.Handle;
|
||||
Result := 0;
|
||||
if FocusedIntfControl <> nil then Result := FocusedIntfControl.Handle
|
||||
else if FocusedControl <> nil then Result := FocusedControl.Handle;
|
||||
end;
|
||||
|
||||
(*function TQtWidgetSet.GetKeyState(nVirtKey: Integer): Smallint;
|
||||
@ -4632,7 +4633,7 @@ var
|
||||
lControl: TWinControl;
|
||||
begin
|
||||
{$ifdef VerboseCDDrawing}
|
||||
WriteLn('[WinAPI InvalidateRect]');
|
||||
DebugLn('[WinAPI InvalidateRect]');
|
||||
{$endif}
|
||||
if AHandle = 0 then exit(False);
|
||||
|
||||
|
@ -44,7 +44,7 @@ uses
|
||||
customdrawncontrols,
|
||||
// Widgetset
|
||||
InterfaceBase, WSForms, WSProc, WSLCLClasses, LCLMessageGlue,
|
||||
customdrawnwscontrols, customdrawnint, customdrawnproc;
|
||||
customdrawnwscontrols, customdrawnint, customdrawnproc, customdrawnprivate;
|
||||
|
||||
type
|
||||
{ TCDWSScrollingWinControl }
|
||||
@ -128,6 +128,9 @@ type
|
||||
var Event: TXConfigureEvent);
|
||||
class procedure EvClientMessage(const AWinControl: TWinControl;
|
||||
AWindowInfo: TX11WindowInfo; var Event: TXClientMessageEvent);
|
||||
// Key routines
|
||||
class function StartComposing(const Event: TXKeyEvent): TKeySym;
|
||||
class function X11KeyToLCLKey(AX11Key: TKeySym): Word;
|
||||
{$endif}
|
||||
published
|
||||
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
|
||||
|
@ -1,5 +1,9 @@
|
||||
{$MainForm customdrawnwsforms.pp}
|
||||
|
||||
// redefines:
|
||||
function XmbLookupString(p1: PXIC; ev: PXKeyPressedEvent; str: PChar; len: longword; ks: PKeySym; stat: PStatus): longint; cdecl; external;
|
||||
function Xutf8LookupString(p1: PXIC; ev: PXKeyPressedEvent; str: PChar; len: longword; ks: PKeySym; stat: PStatus): longint; cdecl; external;
|
||||
|
||||
{ TCDWSCustomForm }
|
||||
|
||||
class procedure TCDWSCustomForm.UpdateMotifWMHints(const AWinControl: TWinControl; CanMaximize: Boolean);
|
||||
@ -480,14 +484,18 @@ end;
|
||||
|
||||
class procedure TCDWSCustomForm.EvKeyPressed(const AWinControl: TWinControl;
|
||||
AWindowInfo: TX11WindowInfo; var Event: TXKeyEvent);
|
||||
{var
|
||||
KeySym: TKeySym;}
|
||||
var
|
||||
lKey: Word;
|
||||
lForm: TCDForm;
|
||||
KeySym: TKeySym;
|
||||
begin
|
||||
{ KeySym := StartComposing(FXEvent^);
|
||||
lForm := TCDForm(AWinControl.Handle);
|
||||
KeySym := StartComposing(Event);
|
||||
|
||||
inherited EvKeyPressed(AKey);
|
||||
lKey := X11KeyToLCLKey(KeySym);
|
||||
CallbackKeyDown(lForm, lKey);
|
||||
|
||||
if (FXEvent^.xkey.state and (ControlMask or Mod1Mask)) = 0 then EndComposing;}
|
||||
//if (FXEvent^.xkey.state and (ControlMask or Mod1Mask)) = 0 then EndComposing;
|
||||
end;
|
||||
|
||||
class procedure TCDWSCustomForm.EvKeyReleased(const AWinControl: TWinControl;
|
||||
@ -506,19 +514,10 @@ class procedure TCDWSCustomForm.EvMousePressed(const AWinControl: TWinControl; A
|
||||
var Event: TXButtonEvent);
|
||||
var
|
||||
MouseButton: TMouseButton;
|
||||
lTarget: TWinControl;
|
||||
lEventPos: TPoint;
|
||||
begin
|
||||
lTarget := FindControlWhichReceivedEvent(TCustomForm(AWinControl), AWindowInfo.Children, Event.x, Event.y);
|
||||
AWindowInfo.LastMouseDownControl := lTarget;
|
||||
lEventPos := FormPosToControlPos(lTarget, Event.x, Event.y);
|
||||
|
||||
// If the target is focusable, a mouse down will give it focus
|
||||
CDWidgetset.CDSetFocusToControl(lTarget);
|
||||
|
||||
if XButtonToMouseButton(Event.button, MouseButton) then
|
||||
begin
|
||||
LCLSendMouseDownMsg(lTarget, lEventPos.x, lEventPos.y, MouseButton, [])
|
||||
CallbackMouseDown(TCDForm(AWinControl.Handle), Event.x, Event.y, MouseButton, []);
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -704,6 +703,184 @@ begin
|
||||
DebugLn(Format('LCL-CustomDrawn-X11: Unknown client message: %d', [Event.message_type]));
|
||||
end;
|
||||
|
||||
class function TCDWSCustomForm.StartComposing(const Event: TXKeyEvent): TKeySym;
|
||||
var
|
||||
len: integer;
|
||||
begin
|
||||
SetLength(CDWidgetset.ComposeBuffer, 20);
|
||||
// Xutf8LookupString returns the size of FComposeBuffer in bytes.
|
||||
len := Xutf8LookupString(CDWidgetset.InputContext, @Event, @CDWidgetset.ComposeBuffer[1],
|
||||
Length(CDWidgetset.ComposeBuffer), @Result, @CDWidgetset.ComposeStatus);
|
||||
SetLength(CDWidgetset.ComposeBuffer, len);
|
||||
// if overflow occured, then previous SetLength() would have fixed the buffer
|
||||
// size, so run Xutf8LookupString again to read correct value.
|
||||
if CDWidgetset.ComposeStatus = XBufferOverflow then
|
||||
Xutf8LookupString(CDWidgetset.InputContext, @Event, @CDWidgetset.ComposeBuffer[1],
|
||||
Length(CDWidgetset.ComposeBuffer), @Result, @CDWidgetset.ComposeStatus);
|
||||
end;
|
||||
|
||||
class function TCDWSCustomForm.X11KeyToLCLKey(AX11Key: TKeySym): Word;
|
||||
{const
|
||||
Table_20aX: array[$20a0..$20ac] of Word = (keyEcuSign, keyColonSign,
|
||||
keyCruzeiroSign, keyFFrancSign, keyLiraSign, keyMillSign, keyNairaSign,
|
||||
keyPesetaSign, keyRupeeSign, keyWonSign, keyNewSheqelSign, keyDongSign,
|
||||
keyEuroSign);
|
||||
Table_feXX: array[$fe50..$fe60] of Word = (keyDeadGrave, keyDeadAcute,
|
||||
keyDeadCircumflex, keyDeadTilde, keyDeadMacron,keyDeadBreve,
|
||||
keyDeadAbovedot, keyDeadDiaeresis, keyDeadRing, keyDeadDoubleacute,
|
||||
keyDeadCaron, keyDeadCedilla, keyDeadOgonek, keyDeadIota,
|
||||
keyDeadVoicedSound, keyDeadSemivoicedSound, keyDeadBelowdot);
|
||||
Table_ff5X: array[$ff50..$ff58] of Word = (keyHome, keyLeft, keyUp, keyRight,
|
||||
keyDown, keyPrior, keyNext, keyEnd, keyBegin);
|
||||
Table_ff6X: array[$ff60..$ff6b] of Word = (keySelect, keyPrintScreen,
|
||||
keyExecute, keyInsert, keyNIL, keyUndo, keyRedo, keyMenu, keyFind,
|
||||
keyCancel, keyHelp, keyBreak);
|
||||
Table_ff9X: array[$ff91..$ff9f] of Word = (keyPF1, keyPF2, keyPF3, keyPF4,
|
||||
keyP7, keyP4, keyP8, keyP6, keyP2, keyP9, keyP3, keyP1, keyP5, keyP0,
|
||||
keyPDecimal);
|
||||
Table_ffeX: array[$ffe1..$ffee] of Word = (keyShiftL, keyShiftR, keyCtrlL,
|
||||
keyCtrlR, keyCapsLock, keyShiftLock, keyMetaL, keyMetaR, keyAltL, keyAltR,
|
||||
keySuperL, keySuperR, keyHyperL, keyHyperR); }
|
||||
begin
|
||||
case AX11Key of
|
||||
$20: Result := VK_SPACE;
|
||||
{ 0x0021 U0021 . # exclam
|
||||
0x0022 U0022 . # quotedbl
|
||||
0x0023 U0023 . # numbersign
|
||||
0x0024 U0024 . # dollar
|
||||
0x0025 U0025 . # percent
|
||||
0x0026 U0026 . # ampersand
|
||||
0x0027 U0027 . # apostrophe
|
||||
0x0027 U0027 . # quoteright /* deprecated */
|
||||
0x0028 U0028 . # parenleft
|
||||
0x0029 U0029 . # parenright
|
||||
0x002a U002a . # asterisk
|
||||
0x002b U002b . # plus
|
||||
0x002c U002c . # comma
|
||||
0x002d U002d . # minus
|
||||
0x002e U002e . # period
|
||||
0x002f U002f . # slash
|
||||
0x0030 U0030 . # 0
|
||||
0x0031 U0031 . # 1
|
||||
0x0032 U0032 . # 2
|
||||
0x0033 U0033 . # 3
|
||||
0x0034 U0034 . # 4
|
||||
0x0035 U0035 . # 5
|
||||
0x0036 U0036 . # 6
|
||||
0x0037 U0037 . # 7
|
||||
0x0038 U0038 . # 8
|
||||
0x0039 U0039 . # 9
|
||||
0x003a U003a . # colon
|
||||
0x003b U003b . # semicolon
|
||||
0x003c U003c . # less
|
||||
0x003d U003d . # equal
|
||||
0x003e U003e . # greater
|
||||
0x003f U003f . # question
|
||||
0x0040 U0040 . # at }
|
||||
$41: Result := VK_A;
|
||||
{ 0x0042 U0042 . # B
|
||||
0x0043 U0043 . # C
|
||||
0x0044 U0044 . # D
|
||||
0x0045 U0045 . # E
|
||||
0x0046 U0046 . # F
|
||||
0x0047 U0047 . # G
|
||||
0x0048 U0048 . # H
|
||||
0x0049 U0049 . # I
|
||||
0x004a U004a . # J
|
||||
0x004b U004b . # K
|
||||
0x004c U004c . # L
|
||||
0x004d U004d . # M
|
||||
0x004e U004e . # N
|
||||
0x004f U004f . # O
|
||||
0x0050 U0050 . # P
|
||||
0x0051 U0051 . # Q
|
||||
0x0052 U0052 . # R
|
||||
0x0053 U0053 . # S
|
||||
0x0054 U0054 . # T
|
||||
0x0055 U0055 . # U
|
||||
0x0056 U0056 . # V
|
||||
0x0057 U0057 . # W
|
||||
0x0058 U0058 . # X
|
||||
0x0059 U0059 . # Y
|
||||
0x005a U005a . # Z }
|
||||
{ 0x005b U005b . # bracketleft
|
||||
0x005c U005c . # backslash
|
||||
0x005d U005d . # bracketright
|
||||
0x005e U005e . # asciicircum
|
||||
0x005f U005f . # underscore
|
||||
0x0060 U0060 . # grave
|
||||
0x0060 U0060 . # quoteleft /* deprecated */ }
|
||||
$61: Result := VK_A;
|
||||
{ 0x0062 U0062 . # b
|
||||
0x0063 U0063 . # c
|
||||
0x0064 U0064 . # d
|
||||
0x0065 U0065 . # e
|
||||
0x0066 U0066 . # f
|
||||
0x0067 U0067 . # g
|
||||
0x0068 U0068 . # h
|
||||
0x0069 U0069 . # i
|
||||
0x006a U006a . # j
|
||||
0x006b U006b . # k
|
||||
0x006c U006c . # l
|
||||
0x006d U006d . # m
|
||||
0x006e U006e . # n
|
||||
0x006f U006f . # o
|
||||
0x0070 U0070 . # p
|
||||
0x0071 U0071 . # q
|
||||
0x0072 U0072 . # r
|
||||
0x0073 U0073 . # s
|
||||
0x0074 U0074 . # t
|
||||
0x0075 U0075 . # u
|
||||
0x0076 U0076 . # v
|
||||
0x0077 U0077 . # w
|
||||
0x0078 U0078 . # x
|
||||
0x0079 U0079 . # y
|
||||
0x007a U007a . # z }
|
||||
{ 0..Ord('a')-1, Ord('z')+1..$bf, $f7:
|
||||
826 Result := KeySym;
|
||||
827 Ord('a')..Ord('z'), $c0..$f6, $f8..$ff:
|
||||
828 Result := KeySym - 32; // ignore case: convert lowercase a-z to A-Z keysyms;
|
||||
829 $20a0..$20ac: Result := Table_20aX[KeySym];
|
||||
830 $fe20: Result := keyTab;
|
||||
831 $fe50..$fe60: Result := Table_feXX[KeySym];
|
||||
832 XK_BackSpace: Result := keyBackspace;
|
||||
833 XK_Tab: Result := keyTab;
|
||||
834 XK_Linefeed: Result := keyLinefeed;
|
||||
835 $ff0b: Result := keyClear;
|
||||
836 $ff0d: Result := keyReturn;
|
||||
837 $ff13: Result := keyPause;
|
||||
838 $ff14: Result := keyScrollLock;
|
||||
839 $ff15: Result := keySysRq;
|
||||
840 $ff1b: Result := keyEscape;
|
||||
841 $ff50..$ff58: Result := Table_ff5X[KeySym];
|
||||
842 $ff60..$ff6b: Result := Table_ff6X[KeySym];
|
||||
843 $ff7e: Result := keyModeSwitch;
|
||||
844 $ff7f: Result := keyNumLock;
|
||||
845 $ff80: Result := keyPSpace;
|
||||
846 $ff89: Result := keyPTab;
|
||||
847 $ff8d: Result := keyPEnter;
|
||||
848 $ff91..$ff9f: Result := Table_ff9X[KeySym];
|
||||
849 $ffaa: Result := keyPAsterisk;
|
||||
850 $ffab: Result := keyPPlus;
|
||||
851 $ffac: Result := keyPSeparator;
|
||||
852 $ffad: Result := keyPMinus;
|
||||
853 $ffae: Result := keyPDecimal;
|
||||
854 $ffaf: Result := keyPSlash;
|
||||
855 $ffb0..$ffb9: Result := keyP0 + KeySym - $ffb0;
|
||||
856 $ffbd: Result := keyPEqual;
|
||||
857 $ffbe..$ffe0: Result := keyF1 + KeySym - $ffbe;
|
||||
858 $ffe1..$ffee: Result := Table_ffeX[KeySym];
|
||||
859 $ffff: Result := keyDelete; }
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
(*864 {$IFDEF Debug}
|
||||
865 if Result = keyNIL then
|
||||
866 WriteLn('fpGFX/X11: Unknown KeySym: $', IntToHex(KeySym, 4));
|
||||
867 {$ENDIF}*)
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TCDWSCustomForm.CreateHandle
|
||||
Params: None
|
||||
|
Loading…
Reference in New Issue
Block a user