mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-04 16:38:16 +02:00
812 lines
28 KiB
PHP
812 lines
28 KiB
PHP
{%MainUnit customdrawnint.pas}
|
|
|
|
{******************************************************************************
|
|
customdrawnobject_win.inc
|
|
******************************************************************************
|
|
|
|
*****************************************************************************
|
|
* *
|
|
* This file is part of the Lazarus Component Library (LCL) *
|
|
* *
|
|
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
|
|
* for details about the copyright. *
|
|
* *
|
|
* This program 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. *
|
|
* *
|
|
*****************************************************************************
|
|
}
|
|
|
|
const
|
|
// Shared Mouse / Key constants
|
|
ACTION_DOWN = 0;
|
|
ACTION_UP = 1;
|
|
|
|
// Touch constants
|
|
ACTION_MOVE = 2;
|
|
|
|
// Constants from android/view/KeyEvent up to level 8
|
|
ACTION_MULTIPLE = 2;
|
|
// Keys are in KeyCodes.pas
|
|
|
|
function Java_com_pascal_lclproject_LCLActivity_LCLOnTouch(env:PJNIEnv;this:jobject; x, y: single; action: jint): jint; cdecl;
|
|
var
|
|
lCurForm: TCDNonNativeForm;
|
|
lTarget: TWinControl;
|
|
lEventPos: TPoint;
|
|
begin
|
|
{$ifdef VerboseCDEvents}
|
|
__android_log_write(ANDROID_LOG_INFO,'lclapp',PChar(Format('LCLOnTouch called x=%f y=%f action=%d', [x, y, action])));
|
|
{$endif}
|
|
eventResult := 0;
|
|
|
|
lCurForm := GetCurrentForm();
|
|
|
|
case action of
|
|
ACTION_DOWN:
|
|
begin
|
|
CallbackMouseDown(lCurForm, Round(X), Round(Y), mbLeft, []);
|
|
end;
|
|
ACTION_UP:
|
|
begin
|
|
CallbackMouseUp(lCurForm, Round(X), Round(Y), mbLeft, []);
|
|
end;
|
|
ACTION_MOVE: CallbackMouseMove(lCurForm, Round(X), Round(Y), []);
|
|
end;
|
|
|
|
// This sends messages like Invalidate requests
|
|
Result := eventResult;
|
|
end;
|
|
|
|
function Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap(
|
|
env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl;
|
|
var
|
|
pixels: PCardinal;
|
|
lCurForm: TCDNonNativeForm;
|
|
|
|
struct : TPaintStruct;
|
|
lBitmap, lMask: HBITMAP;
|
|
lRawImage: TRawImage;
|
|
{$IFDEF VerboseCDPaintProfiler}
|
|
lTimeStart: TDateTime;
|
|
{$ENDIF}
|
|
begin
|
|
Result := 0;
|
|
AndroidBitmap_lockPixels(env, abitmap, @pixels);
|
|
|
|
lCurForm := GetCurrentForm();
|
|
if lCurForm <> nil then
|
|
begin
|
|
{$IFDEF VerboseCDPaintProfiler}
|
|
//lTimeStart := NowUTC();
|
|
{$ENDIF}
|
|
{$IFDEF VerboseCDPaintEvent}
|
|
DebugLn(Format('[Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap] lCurForm:TCDNonNativeForm=%x', [PtrInt(lCurForm)]));
|
|
{$ENDIF}
|
|
|
|
FillChar(struct, SizeOf(TPaintStruct), 0);
|
|
|
|
// Prepare the non-native image and canvas
|
|
UpdateControlLazImageAndCanvas(lCurForm.Image, lCurForm.Canvas, Width, Height, clfRGBA32, pixels, True, False);
|
|
DrawFormBackground(lCurForm.Image, lCurForm.Canvas);
|
|
|
|
struct.hdc := HDC(lCurForm.Canvas);
|
|
|
|
// Send the paint message to the LCL
|
|
{$IFDEF VerboseCDPaintEvent}
|
|
//DebugLn(Format('[TCDWSCustomForm.EvPaint] OnPaint event started context: %x', [struct.hdc]));
|
|
{$ENDIF}
|
|
LCLSendPaintMsg(lCurForm.LCLForm, struct.hdc, @struct);
|
|
{$IFDEF VerboseCDPaintEvent}
|
|
//DebugLn('[TCDWSCustomForm.EvPaint] OnPaint event ended');
|
|
{$ENDIF}
|
|
|
|
// Now paint all child win controls
|
|
RenderChildWinControls(lCurForm.Image, lCurForm.Canvas, lCurForm.Children);
|
|
end;
|
|
|
|
// Now returns the bitmap buffer to LCLActivity so that it can render it
|
|
AndroidBitmap_unlockPixels(env, abitmap);
|
|
end;
|
|
|
|
function Java_com_pascal_lclproject_LCLActivity_LCLOnCreate(
|
|
env:PJNIEnv; this:jobject; alclactivity: jobject): jint; cdecl;
|
|
begin
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'LCLOnCreate called by LCLActivity.onCreate');
|
|
Result := 0;
|
|
javaActivityObject := alclactivity;
|
|
Application.Run;
|
|
end;
|
|
|
|
// This one is for all simple dialogs: MessageBox, PromptUser (MessageDlg) and AskUser
|
|
function Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished(
|
|
env:PJNIEnv; this:jobject; AResult: jint): jint; cdecl;
|
|
begin
|
|
//__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'LCLOnCreate called by LCLActivity.onCreate');
|
|
Result := 0;
|
|
if Assigned(Application.OnMessageDialogFinished) then
|
|
Application.OnMessageDialogFinished(Application, AResult);
|
|
end;
|
|
|
|
function Java_com_pascal_lclproject_LCLActivity_LCLOnKey(
|
|
env:PJNIEnv; this:jobject; AKind: jint; AKeyCode: jint;
|
|
AEvent: jobject; AChar: jchar): jint; cdecl;
|
|
var
|
|
lCurForm: TCDNonNativeForm;
|
|
lTarget, lFocusedControl: TWinControl;
|
|
lKey: Word;
|
|
AWideText: widestring;
|
|
AUTF8Text: string;
|
|
AUTF8Char: TUTF8Char;
|
|
lForm: TCDNonNativeForm;
|
|
begin
|
|
{$ifdef VerboseCDEvents}
|
|
__android_log_write(ANDROID_LOG_INFO,'lclapp',PChar(
|
|
Format('[LCLOnKey] called AKind=%d AKeyCode=%x AChar=%s', [AKind, AKeyCode, UTF8Encode(WideChar(AChar))])));
|
|
{$endif}
|
|
eventResult := 0;
|
|
|
|
lCurForm := GetCurrentForm();
|
|
lKey := CDWidgetset.AndroidKeyCodeToLCLKeyCode(AKeyCode);
|
|
|
|
case AKind of
|
|
ACTION_DOWN: CallbackKeyDown(lCurForm, lKey);
|
|
ACTION_UP:
|
|
begin
|
|
CallbackKeyUp(lCurForm, lKey);
|
|
if AChar <> 0 then
|
|
begin
|
|
SetLength(AWideText, 1);
|
|
AWideText[1] := WideChar(AChar);
|
|
AUTF8Text := UTF16ToUTF8(AWideText);
|
|
AUTF8Char := AUTF8Text;
|
|
CallbackKeyChar(lCurForm, lKey, AUTF8Char);
|
|
end;
|
|
|
|
// Handle the Back hardware key
|
|
if AKeyCode = AKEYCODE_BACK then
|
|
begin
|
|
//DebugLn(Format('CallbackKeyUp D lForm=%x', [PtrInt(lForm)]));
|
|
// The back hardware key hides the current form and shows the one bellow it
|
|
// except if the currently focused control is a text editor, in which case
|
|
// it will take focus out of the text editor
|
|
lForm := lCurForm;
|
|
lFocusedControl := lForm.GetFocusedControl();
|
|
if (lFocusedControl <> nil) and (csRequiresKeyboardInput in lFocusedControl.ControlStyle) then
|
|
begin
|
|
//DebugLn('[LCLOnKey] Sending focus to the form');
|
|
CDWidgetset.CDSetFocusToControl(lForm.LCLForm, nil);
|
|
end
|
|
// If this is the main form, then go back to desktop
|
|
else if (Application.MainForm <> nil) and (lForm = TCDForm(Application.MainForm.Handle)) then
|
|
begin
|
|
//DebugLn('[LCLOnKey] Back key is going to hide the application');
|
|
eventResult := eventResult or 2;
|
|
end
|
|
// for other forms, hide them
|
|
else
|
|
begin
|
|
//DebugLn('[LCLOnKey] Hiding the form');
|
|
HideForm(lForm);
|
|
end;
|
|
end;
|
|
end;
|
|
//ACTION_MULTIPLE:
|
|
end;
|
|
|
|
// This sends messages like Invalidate requests
|
|
Result := eventResult;
|
|
end;
|
|
|
|
function Java_com_pascal_lclproject_LCLActivity_LCLOnTimer(
|
|
env:PJNIEnv; this:jobject; ATimer: jobject): jint; cdecl;
|
|
var
|
|
lTimer: TCDTimer;
|
|
begin
|
|
{$ifdef VerboseCDEvents}
|
|
__android_log_write(ANDROID_LOG_INFO,'lclapp',PChar(
|
|
Format('LCLOnTimer called ATimer=%x', [PtrInt(ATimer)])));
|
|
{$endif}
|
|
eventResult := 0;
|
|
|
|
lTimer := FindTimerWithNativeHandle(PtrInt(ATimer));
|
|
|
|
if lTimer <> nil then lTimer.TimerFunc()
|
|
else DebugLn('[LCLOnTimer] OnTimer message sent to unknown timer!');
|
|
|
|
// This sends messages like Invalidate requests
|
|
Result := eventResult;
|
|
end;
|
|
|
|
const NativeMethods: array[0..5] of JNINativeMethod=
|
|
((name:'LCLDrawToBitmap';
|
|
signature:'(IILandroid/graphics/Bitmap;)I';
|
|
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap;),
|
|
(name:'LCLOnTouch';
|
|
signature:'(FFI)I';
|
|
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnTouch;),
|
|
(name:'LCLOnCreate';
|
|
signature:'(Lcom/pascal/lcltest/LCLActivity;)I'; //android/app/Activity;
|
|
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnCreate;),
|
|
(name:'LCLOnMessageBoxFinished';
|
|
signature:'(I)I';
|
|
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished;),
|
|
(name:'LCLOnKey';
|
|
signature:'(IILandroid/view/KeyEvent;C)I';
|
|
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnKey;),
|
|
(name:'LCLOnTimer';
|
|
signature:'(Ljava/lang/Runnable;)I';
|
|
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnTimer;)
|
|
);
|
|
|
|
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
|
|
begin
|
|
javaVMRef := vm;
|
|
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad called');
|
|
{ __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm=%x', [PtrInt(vm)])));
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm^=%x', [PtrInt(vm^)])));
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm^^.reserved0=%x', [PtrInt(vm^^.reserved0)])));
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm^^.GetEnv=%x', [PtrInt(Pointer(@vm^^.GetEnv))]))); }
|
|
{
|
|
vm^^.GetEnv crashes HTC Wildfire, Alcatel and the Emulator if you don't build your project with -CpARMV6
|
|
see: http://groups.google.com/group/android-ndk/browse_thread/thread/ba542483f062a828/ef9077617794e0f5
|
|
}
|
|
if vm^^.GetEnv(vm,@javaEnvRef,JNI_VERSION_1_4)<>JNI_OK then
|
|
begin
|
|
__android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'curVM^.GetEnv failed');
|
|
Exit(JNI_ERR);
|
|
end;
|
|
|
|
// Find our activity class
|
|
__android_log_write(ANDROID_LOG_INFO,'lclapp','Reading our Activity Class');
|
|
javaActivityClass := javaEnvRef^^.FindClass(javaEnvRef,'com/pascal/lcltest/LCLActivity');
|
|
if not assigned(javaActivityClass) then
|
|
begin
|
|
__android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'javaEnvRef^.FindClass failed');
|
|
Exit(JNI_ERR);
|
|
end;
|
|
|
|
// Register Pascal exported calls
|
|
if javaEnvRef^^.RegisterNatives(javaEnvRef, javaActivityClass, @NativeMethods[0],length(NativeMethods))<0 then
|
|
begin
|
|
__android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'javaEnvRef^.RegisterNatives failed');
|
|
// Exit(JNI_ERR); Don't exit if exporting the native method fails because it works without this too
|
|
end;
|
|
|
|
// Read all field IDs
|
|
JavaField_lcltext := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltext', 'Ljava/lang/String;');
|
|
JavaField_lcltitle := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltitle', 'Ljava/lang/String;');
|
|
JavaField_lclbutton1str := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton1str', 'Ljava/lang/String;');
|
|
JavaField_lclbutton2str := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton2str', 'Ljava/lang/String;');
|
|
JavaField_lclbutton3str := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton3str', 'Ljava/lang/String;');
|
|
//
|
|
JavaField_lclwidth := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclwidth', 'I');
|
|
JavaField_lclheight := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclheight', 'I');
|
|
JavaField_lclbutton1 := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton1', 'I');
|
|
JavaField_lclbutton2 := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton2', 'I');
|
|
JavaField_lclbutton3 := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton3', 'I');
|
|
JavaField_lclbitmap := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbitmap', 'Landroid/graphics/Bitmap;');
|
|
JavaField_lcltextsize := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextsize', 'I');
|
|
// Text metrics
|
|
javaField_lcltextascent := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextascent', 'I');
|
|
javaField_lcltextbottom := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextbottom', 'I');
|
|
javaField_lcltextdescent := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextdescent', 'I');
|
|
javaField_lcltextleading := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextleading', 'I');
|
|
javaField_lcltexttop := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltexttop', 'I');
|
|
// Timer
|
|
javaField_lcltimerinterval := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltimerinterval', 'I');
|
|
javaField_lcltimerid := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltimerid', 'Ljava/lang/Runnable;');
|
|
//
|
|
if not assigned(JavaField_lcltext) then
|
|
begin
|
|
__android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'javaEnvRef^.GetFieldID failed for lcltext');
|
|
Exit(JNI_ERR);
|
|
end;
|
|
|
|
// Read all method IDs
|
|
javaMethod_LCLDoGetTextBounds := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoGetTextBounds', '()V');
|
|
javaMethod_LCLDoDrawText := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoDrawText', '()V');
|
|
javaMethod_LCLDoShowMessageBox := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoShowMessageBox', '()V');
|
|
javaMethod_LCLDoCreateTimer := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoCreateTimer', '()V');
|
|
javaMethod_LCLDoDestroyTimer := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoDestroyTimer', '()V');
|
|
javaMethod_LCLDoHideVirtualKeyboard := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoHideVirtualKeyboard', '()V');
|
|
javaMethod_LCLDoShowVirtualKeyboard := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoShowVirtualKeyboard', '()V');
|
|
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad finished');
|
|
result:=JNI_VERSION_1_4;// 1_6 is another option
|
|
end;
|
|
|
|
procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl;
|
|
begin
|
|
end;
|
|
|
|
procedure TCDWidgetSet.AndroidDebugLn(AStr: string);
|
|
begin
|
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(AccumulatedStr+AStr));
|
|
AccumulatedStr := '';
|
|
end;
|
|
|
|
function TCDWidgetSet.AndroidKeyCodeToLCLKeyCode(AAndroidKeyCode: Integer): Word;
|
|
begin
|
|
case AAndroidKeyCode of
|
|
{ AKEYCODE_SOFT_LEFT = 1;
|
|
AKEYCODE_SOFT_RIGHT = 2;
|
|
AKEYCODE_HOME = 3;}
|
|
AKEYCODE_BACK: Result := VK_ESCAPE;
|
|
{ AKEYCODE_CALL = 5;
|
|
AKEYCODE_ENDCALL = 6;}
|
|
AKEYCODE_0: Result := VK_0;
|
|
AKEYCODE_1: Result := VK_1;
|
|
AKEYCODE_2: Result := VK_2;
|
|
AKEYCODE_3: Result := VK_3;
|
|
AKEYCODE_4: Result := VK_4;
|
|
AKEYCODE_5: Result := VK_5;
|
|
AKEYCODE_6: Result := VK_6;
|
|
AKEYCODE_7: Result := VK_7;
|
|
AKEYCODE_8: Result := VK_8;
|
|
AKEYCODE_9: Result := VK_9;
|
|
{ AKEYCODE_STAR = 17;
|
|
AKEYCODE_POUND = 18;}
|
|
AKEYCODE_DPAD_UP: Result := VK_UP;
|
|
AKEYCODE_DPAD_DOWN: Result := VK_DOWN;
|
|
AKEYCODE_DPAD_LEFT: Result := VK_LEFT;
|
|
AKEYCODE_DPAD_RIGHT: Result := VK_RIGHT;
|
|
AKEYCODE_DPAD_CENTER: Result := VK_RETURN;
|
|
{ AKEYCODE_VOLUME_UP = 24;
|
|
AKEYCODE_VOLUME_DOWN = 25;
|
|
AKEYCODE_POWER = 26;
|
|
AKEYCODE_CAMERA = 27;}
|
|
AKEYCODE_CLEAR: Result := VK_CLEAR;
|
|
AKEYCODE_A: Result := VK_A;
|
|
AKEYCODE_B: Result := VK_B;
|
|
AKEYCODE_C: Result := VK_C;
|
|
AKEYCODE_D: Result := VK_D;
|
|
AKEYCODE_E: Result := VK_E;
|
|
AKEYCODE_F: Result := VK_F;
|
|
AKEYCODE_G: Result := VK_G;
|
|
AKEYCODE_H: Result := VK_H;
|
|
AKEYCODE_I: Result := VK_I;
|
|
AKEYCODE_J: Result := VK_J;
|
|
AKEYCODE_K: Result := VK_K;
|
|
AKEYCODE_L: Result := VK_L;
|
|
AKEYCODE_M: Result := VK_M;
|
|
AKEYCODE_N: Result := VK_N;
|
|
AKEYCODE_O: Result := VK_O;
|
|
AKEYCODE_P: Result := VK_P;
|
|
AKEYCODE_Q: Result := VK_Q;
|
|
AKEYCODE_R: Result := VK_R;
|
|
AKEYCODE_S: Result := VK_S;
|
|
AKEYCODE_T: Result := VK_T;
|
|
AKEYCODE_U: Result := VK_U;
|
|
AKEYCODE_V: Result := VK_V;
|
|
AKEYCODE_W: Result := VK_W;
|
|
AKEYCODE_X: Result := VK_X;
|
|
AKEYCODE_Y: Result := VK_Y;
|
|
AKEYCODE_Z: Result := VK_Z;
|
|
//AKEYCODE_COMMA: Result := VK_?
|
|
//AKEYCODE_PERIOD = 56;
|
|
AKEYCODE_ALT_LEFT: Result := VK_LMENU;
|
|
AKEYCODE_ALT_RIGHT: Result := VK_RMENU;
|
|
AKEYCODE_SHIFT_LEFT: Result := VK_LSHIFT;
|
|
AKEYCODE_SHIFT_RIGHT: Result := VK_RSHIFT;
|
|
AKEYCODE_TAB: Result := VK_TAB;
|
|
AKEYCODE_SPACE: Result := VK_SPACE;
|
|
{ AKEYCODE_SYM = 63;
|
|
AKEYCODE_EXPLORER = 64;
|
|
AKEYCODE_ENVELOPE = 65;}
|
|
AKEYCODE_ENTER: Result := VK_RETURN;
|
|
AKEYCODE_DEL: Result := VK_BACK; // The "Backspace" key
|
|
{ AKEYCODE_GRAVE = 68;
|
|
AKEYCODE_MINUS = 69;
|
|
AKEYCODE_EQUALS = 70;
|
|
AKEYCODE_LEFT_BRACKET = 71;
|
|
AKEYCODE_RIGHT_BRACKET = 72;
|
|
AKEYCODE_BACKSLASH = 73;
|
|
AKEYCODE_SEMICOLON = 74;
|
|
AKEYCODE_APOSTROPHE = 75;
|
|
AKEYCODE_SLASH = 76;
|
|
AKEYCODE_AT = 77;
|
|
AKEYCODE_NUM = 78;
|
|
AKEYCODE_HEADSETHOOK = 79;
|
|
AKEYCODE_FOCUS = 80; // *Camera* focus
|
|
AKEYCODE_PLUS = 81;}
|
|
AKEYCODE_MENU: Result := VK_MENU;
|
|
{ AKEYCODE_NOTIFICATION = 83;
|
|
AKEYCODE_SEARCH = 84;
|
|
AKEYCODE_MEDIA_PLAY_PAUSE = 85;
|
|
AKEYCODE_MEDIA_STOP = 86;
|
|
AKEYCODE_MEDIA_NEXT = 87;
|
|
AKEYCODE_MEDIA_PREVIOUS = 88;
|
|
AKEYCODE_MEDIA_REWIND = 89;
|
|
AKEYCODE_MEDIA_FAST_FORWARD = 90;
|
|
AKEYCODE_MUTE = 91;}
|
|
AKEYCODE_PAGE_UP: Result := VK_NEXT;
|
|
AKEYCODE_PAGE_DOWN: Result := VK_PRIOR;
|
|
{ AKEYCODE_PICTSYMBOLS = 94;
|
|
AKEYCODE_SWITCH_CHARSET = 95;
|
|
AKEYCODE_BUTTON_A = 96;
|
|
AKEYCODE_BUTTON_B = 97;
|
|
AKEYCODE_BUTTON_C = 98;
|
|
AKEYCODE_BUTTON_X = 99;
|
|
AKEYCODE_BUTTON_Y = 100;
|
|
AKEYCODE_BUTTON_Z = 101;
|
|
AKEYCODE_BUTTON_L1 = 102;
|
|
AKEYCODE_BUTTON_R1 = 103;
|
|
AKEYCODE_BUTTON_L2 = 104;
|
|
AKEYCODE_BUTTON_R2 = 105;
|
|
AKEYCODE_BUTTON_THUMBL = 106;
|
|
AKEYCODE_BUTTON_THUMBR = 107;
|
|
AKEYCODE_BUTTON_START = 108;
|
|
AKEYCODE_BUTTON_SELECT = 109;
|
|
AKEYCODE_BUTTON_MODE = 110;}
|
|
// New since API level 11 from android.view.KeyEvent
|
|
AKEYCODE_NUMPAD_0: Result := VK_NUMPAD0;
|
|
AKEYCODE_NUMPAD_1: Result := VK_NUMPAD1;
|
|
AKEYCODE_NUMPAD_2: Result := VK_NUMPAD2;
|
|
AKEYCODE_NUMPAD_3: Result := VK_NUMPAD3;
|
|
AKEYCODE_NUMPAD_4: Result := VK_NUMPAD4;
|
|
AKEYCODE_NUMPAD_5: Result := VK_NUMPAD5;
|
|
AKEYCODE_NUMPAD_6: Result := VK_NUMPAD6;
|
|
AKEYCODE_NUMPAD_7: Result := VK_NUMPAD7;
|
|
AKEYCODE_NUMPAD_8: Result := VK_NUMPAD8;
|
|
AKEYCODE_NUMPAD_9: Result := VK_NUMPAD9;
|
|
AKEYCODE_NUMPAD_ADD: Result := VK_ADD;
|
|
{AKEYCODE_NUMPAD_COMMA = $0000009f;
|
|
AKEYCODE_NUMPAD_DIVIDE = $0000009a;
|
|
AKEYCODE_NUMPAD_DOT = $0000009e;
|
|
AKEYCODE_NUMPAD_ENTER = $000000a0;
|
|
AKEYCODE_NUMPAD_EQUALS = $000000a1;
|
|
AKEYCODE_NUMPAD_LEFT_PAREN = $000000a2;
|
|
AKEYCODE_NUMPAD_MULTIPLY = $0000009b;
|
|
AKEYCODE_NUMPAD_RIGHT_PAREN = $000000a3;
|
|
AKEYCODE_NUMPAD_SUBTRACT = $0000009c;}
|
|
AKEYCODE_NUM_LOCK: Result := VK_NUMLOCK;
|
|
else
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TCDWidgetSet.Create
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Constructor for the class.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCDWidgetSet.BackendCreate;
|
|
begin
|
|
// Setup DebugLn
|
|
DebugLnProc := @AndroidDebugLn;
|
|
DebugOutProc := @AccumulatingDebugOut;
|
|
|
|
{$ifdef CD_UseNativeText}
|
|
// Create the dummy screen DC
|
|
ScreenBitmapRawImage.Init;
|
|
ScreenBitmapHeight := 100;
|
|
ScreenBitmapWidth := 100;
|
|
ScreenBitmapRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(ScreenBitmapWidth, ScreenBitmapHeight);
|
|
ScreenBitmapRawImage.CreateData(True);
|
|
ScreenImage := TLazIntfImage.Create(0, 0);
|
|
ScreenImage.SetRawImage(ScreenBitmapRawImage);
|
|
ScreenDC := TLazCanvas.Create(ScreenImage);
|
|
|
|
DefaultFontAndroidSize := 16;
|
|
{$endif}
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.Destroy
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
destructor for the class.
|
|
------------------------------------------------------------------------------}
|
|
procedure TCDWidgetSet.BackendDestroy;
|
|
begin
|
|
{$ifdef CD_UseNativeText}
|
|
// Free the dummy screen DC
|
|
ScreenImage.Free;
|
|
ScreenDC.Free;
|
|
{$endif}
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppInit
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
initialize Windows
|
|
------------------------------------------------------------------------------}
|
|
procedure TCDWidgetSet.AppInit(var ScreenInfo: TScreenInfo);
|
|
begin
|
|
{$ifdef VerboseCDApplication}
|
|
DebugLn('TCDWidgetSet.AppInit');
|
|
{$endif}
|
|
|
|
Forms.MessageBoxFunction := @CDMessageBoxFunction;
|
|
end;
|
|
|
|
procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop);
|
|
begin
|
|
{$ifdef VerboseCDApplication}
|
|
DebugLn('TCDWidgetSet.AppRun');
|
|
{$endif}
|
|
end;
|
|
|
|
(*
|
|
function TWinCEWidgetSet.GetAppHandle: THandle;
|
|
begin
|
|
Result:= FAppHandle;
|
|
end;
|
|
|
|
procedure TWinCEWidgetSet.SetAppHandle(const AValue: THandle);
|
|
begin
|
|
// Do it only if handle is not yet created (for example for DLL initialization)
|
|
// if handle is already created we can't reassign it
|
|
if AppHandle = 0 then
|
|
FAppHandle := AValue;
|
|
end;*)
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppMinimize
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Minimizes the whole application to the taskbar
|
|
------------------------------------------------------------------------------}
|
|
procedure TCDWidgetSet.AppMinimize;
|
|
begin
|
|
// Windows.SendMessage(FAppHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppRestore
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Restore minimized whole application from taskbar
|
|
------------------------------------------------------------------------------}
|
|
|
|
procedure TCDWidgetSet.AppRestore;
|
|
begin
|
|
// Windows.SendMessage(FAppHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
|
|
end;
|
|
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppBringToFront
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Brings the entire application on top of all other non-topmost programs
|
|
------------------------------------------------------------------------------}
|
|
procedure TCDWidgetSet.AppBringToFront;
|
|
begin
|
|
end;
|
|
|
|
(*
|
|
procedure TWinCEWidgetSet.SetDesigning(AComponent: TComponent);
|
|
begin
|
|
//if Data<>nil then EnableWindow((AComponent As TWinControl).Handle, boolean(Data^));
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.SetCallback
|
|
Params: Msg - message for which to set a callback
|
|
Sender - object to which callback will be sent
|
|
Returns: nothing
|
|
|
|
Applies a Message to the sender
|
|
------------------------------------------------------------------------------}
|
|
procedure TWinCEWidgetSet.SetCallback(Msg: LongInt; Sender: TObject);
|
|
var
|
|
Window: HWnd;
|
|
begin
|
|
//DebugLn('Trace:TWinCEWidgetSet.SetCallback - Start');
|
|
//DebugLn(Format('Trace:TWinCEWidgetSet.SetCallback - Class Name --> %S', [Sender.ClassName]));
|
|
//DebugLn(Format('Trace:TWinCEWidgetSet.SetCallback - Message Name --> %S', [GetMessageName(Msg)]));
|
|
if Sender Is TControlCanvas then
|
|
Window := TControlCanvas(Sender).Handle
|
|
else if Sender Is TCustomForm then
|
|
Window := TCustomForm(Sender).Handle
|
|
else
|
|
Window := TWinControl(Sender).Handle;
|
|
if Window=0 then exit;
|
|
|
|
//DebugLn('Trace:TWinCEWidgetSet.SetCallback - Exit');
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.RemoveCallbacks
|
|
Params: Sender - object from which to remove callbacks
|
|
Returns: nothing
|
|
|
|
Removes Call Back Signals from the sender
|
|
------------------------------------------------------------------------------}
|
|
procedure TWinCEWidgetSet.RemoveCallbacks(Sender: TObject);
|
|
var
|
|
Window: HWnd;
|
|
begin
|
|
if Sender Is TControlCanvas then
|
|
Window := TControlCanvas(Sender).Handle
|
|
else if Sender Is TCustomForm then
|
|
Window := TCustomForm(Sender).Handle
|
|
else
|
|
Window := (Sender as TWinControl).Handle;
|
|
if Window=0 then exit;
|
|
end;*)
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppProcessMessages
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Handle all pending messages
|
|
------------------------------------------------------------------------------}
|
|
procedure TCDWidgetSet.AppProcessMessages;
|
|
begin
|
|
end;
|
|
(*
|
|
procedure TWinCEWidgetSet.CheckPipeEvents;
|
|
var
|
|
lHandler: PPipeEventInfo;
|
|
// lBytesAvail: dword;
|
|
// SomethingChanged: Boolean;
|
|
ChangedCount:integer;
|
|
begin
|
|
lHandler := FWaitPipeHandlers;
|
|
ChangedCount := 0;
|
|
while (lHandler <> nil) and (ChangedCount < 10) do
|
|
begin
|
|
{
|
|
roozbeh : ooops not supported
|
|
SomethingChanged:=true;
|
|
if Windows.PeekNamedPipe(lHandler^.Handle, nil, 0, nil, @lBytesAvail, nil) then
|
|
begin
|
|
if lBytesAvail <> 0 then
|
|
lHandler^.OnEvent(lHandler^.UserData, [prDataAvailable])
|
|
else
|
|
SomethingChanged := false;
|
|
end else
|
|
lHandler^.OnEvent(lHandler^.UserData, [prBroken]);
|
|
if SomethingChanged then
|
|
lHandler := FWaitPipeHandlers
|
|
else begin
|
|
lHandler := lHandler^.Next;
|
|
ChangedCount := 0;
|
|
end;
|
|
inc(ChangedCount);}
|
|
end;
|
|
end;*)
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppWaitMessage
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Passes execution control to Windows
|
|
------------------------------------------------------------------------------}
|
|
//roozbeh:new update...whole procedure body is added.what is it?
|
|
procedure TCDWidgetSet.AppWaitMessage;
|
|
begin
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
Method: TWinCEWidgetSet.AppTerminate
|
|
Params: None
|
|
Returns: Nothing
|
|
|
|
Tells Windows to halt and destroy
|
|
------------------------------------------------------------------------------}
|
|
|
|
procedure TCDWidgetSet.AppTerminate;
|
|
begin
|
|
//DebugLn('Trace:TWinCEWidgetSet.AppTerminate - Start');
|
|
end;
|
|
|
|
|
|
procedure TCDWidgetSet.AppSetIcon(const Small, Big: HICON);
|
|
begin
|
|
end;
|
|
|
|
procedure TCDWidgetSet.AppSetTitle(const ATitle: string);
|
|
begin
|
|
end;
|
|
|
|
procedure TCDWidgetSet.AppSetVisible(const AVisible: Boolean);
|
|
begin
|
|
end;
|
|
|
|
function TCDWidgetSet.AppRemoveStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean;
|
|
begin
|
|
end;
|
|
|
|
function TCDWidgetSet.AppRestoreStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean;
|
|
begin
|
|
end;
|
|
|
|
procedure TCDWidgetSet.AppSetMainFormOnTaskBar(const DoSet: Boolean);
|
|
begin
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function: CreateTimer
|
|
Params: Interval:
|
|
TimerFunc: Callback
|
|
Returns: a Timer id (use this ID to destroy timer)
|
|
|
|
Design: A timer which calls TimerCallBackProc, is created.
|
|
The TimerCallBackProc calls the TimerFunc.
|
|
------------------------------------------------------------------------------}
|
|
function TCDWidgetSet.CreateTimer(Interval: integer; TimerFunc: TWSTimerProc) : THandle;
|
|
var
|
|
lTimer: TCDTimer;
|
|
begin
|
|
lTimer := TCDTimer.Create;
|
|
|
|
Result := THandle(lTimer);
|
|
|
|
lTimer.Interval := Interval;
|
|
lTimer.TimerFunc := TimerFunc;
|
|
|
|
// Prepare the input
|
|
javaEnvRef^^.SetIntField(javaEnvRef, javaActivityObject, javaField_lcltimerinterval, Interval);
|
|
|
|
// Call the method
|
|
javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_LCLDoCreateTimer);
|
|
|
|
// Read the output
|
|
lTimer.NativeHandle := PtrInt(javaEnvRef^^.GetObjectField(javaEnvRef, javaActivityObject, javaField_lcltimerid));
|
|
|
|
// Add it to our list
|
|
AddTimer(lTimer);
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------
|
|
function: DestroyTimer
|
|
Params: TimerHandle
|
|
Returns:
|
|
------------------------------------------------------------------------------}
|
|
function TCDWidgetSet.DestroyTimer(TimerHandle: THandle) : boolean;
|
|
var
|
|
lTimer: TCDTimer;
|
|
begin
|
|
Result := False;
|
|
|
|
lTimer := TCDTimer(TimerHandle);
|
|
|
|
if lTimer = nil then Exit;
|
|
|
|
// Prepare the input
|
|
javaEnvRef^^.SetObjectField(javaEnvRef, javaActivityObject, javaField_lcltimerid, jobject(lTimer.NativeHandle));
|
|
|
|
// Call the method
|
|
javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_LCLDoDestroyTimer);
|
|
|
|
// Remove from the list
|
|
RemoveTimer(lTimer);
|
|
|
|
Result := True;
|
|
end;
|
|
(*
|
|
procedure TWinCEWidgetSet.HandleWakeMainThread(Sender: TObject);
|
|
begin
|
|
// wake up GUI thread by sending a message to it
|
|
Windows.PostMessage(AppHandle, WM_NULL, 0, 0);
|
|
end;
|
|
*)
|
|
|
|
// This code is unnecessary in FPC 2.6+,
|
|
// it was required when the 2.5.1 snapshot was created
|
|
{$ifdef ver2_5}
|
|
procedure PASCALMAIN; external name 'PASCALMAIN';
|
|
|
|
procedure FPC_SHARED_LIB_START; [public, alias: 'FPC_SHARED_LIB_START'];
|
|
begin
|
|
PASCALMAIN;
|
|
end;
|
|
{$endif}
|
|
|