customdrawn-android: Implements TTimer and improves the key handling

git-svn-id: trunk@34179 -
This commit is contained in:
sekelsenmat 2011-12-14 12:36:48 +00:00
parent 4df5e7288b
commit 872dd6830b
7 changed files with 236 additions and 23 deletions

View File

@ -62,7 +62,10 @@ public class LCLActivity extends Activity
if ((eventResult | 1) != 0) postInvalidate();
return true;
}
}
}
// Global objects
LCLSurface lclsurface;
// -------------------------------------------
// Activity Events
@ -74,7 +77,7 @@ public class LCLActivity extends Activity
{
super.onCreate(savedInstanceState);
LCLSurface lclsurface = new LCLSurface(this);
lclsurface = new LCLSurface(this);
setContentView(lclsurface);
lclsurface.postInvalidate();
// Tell the LCL that an OnCreate has happened and what is our instance
@ -89,6 +92,7 @@ public class LCLActivity extends Activity
public native int LCLOnCreate(LCLActivity lclactivity);
public native int LCLOnMessageBoxFinished(int Result);
public native int LCLOnKey(int kind, int keyCode, KeyEvent event, char AChar);
public native int LCLOnTimer(Runnable timerid);
// -------------------------------------------
// Functions exported to the Pascal side
@ -192,7 +196,33 @@ public class LCLActivity extends Activity
if (lclbutton2 >= 0) builder.setNeutralButton(lclbutton2str, dialogClickListener);
if (lclbutton3 >= 0) builder.setNegativeButton(lclbutton3str, dialogClickListener);
builder.show().setOnCancelListener(dialogCancelListener);
}
};
private Handler LocalHandler = new Handler();
// input: int lcltimerinterval in milliseconds
// output: Runnable lcltimerid
public void LCLDoCreateTimer()
{
lcltimerid = new Runnable()
{
public void run()
{
int eventResult = LCLOnTimer(this);
if (((eventResult | 1) != 0) && (lclsurface != null)) lclsurface.postInvalidate();
LocalHandler.postDelayed(this, lcltimerinterval);
}
};
LocalHandler.removeCallbacks(lcltimerid);
LocalHandler.postDelayed(lcltimerid, lcltimerinterval);
};
// input: Runnable lcltimerid
public void LCLDoDestroyTimer()
{
LocalHandler.removeCallbacks(lcltimerid);
};
// -------------------------------------------
// Fields exported to the Pascal side for easier data communication
@ -202,18 +232,23 @@ public class LCLActivity extends Activity
public String lclbutton1str;
public String lclbutton2str;
public String lclbutton3str;
//
public int lclwidth;
public int lclheight;
public int lclbutton1;
public int lclbutton2;
public int lclbutton3;
public Bitmap lclbitmap;
//
public int lcltextsize;
public int lcltextascent;
public int lcltextbottom;
public int lcltextdescent;
public int lcltextleading;
public int lcltexttop;
//
public int lcltimerinterval;
public Runnable lcltimerid;
static
{

View File

@ -18,6 +18,7 @@ exports
Java_com_pascal_lclproject_LCLActivity_LCLOnCreate name 'Java_com_pascal_lcltest_LCLActivity_LCLOnCreate',
Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished name 'Java_com_pascal_lcltest_LCLActivity_LCLOnMessageBoxFinished',
Java_com_pascal_lclproject_LCLActivity_LCLOnKey name 'Java_com_pascal_lcltest_LCLActivity_LCLOnKey',
Java_com_pascal_lclproject_LCLActivity_LCLOnTimer name 'Java_com_pascal_lcltest_LCLActivity_LCLOnTimer',
JNI_OnLoad name 'JNI_OnLoad',
JNI_OnUnload name 'JNI_OnUnload';
{$endif}

View File

@ -14,6 +14,8 @@
* limitations under the License.
*)
// Note: This translation does not limit itself to the NDK defined constants
// but instead all constants from android.view.KeyEvent can be added here
unit keycodes;
interface
@ -153,6 +155,29 @@ const
AKEYCODE_BUTTON_SELECT = 109;
AKEYCODE_BUTTON_MODE = 110;
// New since API level 11 from android.view.KeyEvent
AKEYCODE_NUMPAD_0 = $00000090;
AKEYCODE_NUMPAD_1 = $00000091;
AKEYCODE_NUMPAD_2 = $00000092;
AKEYCODE_NUMPAD_3 = $00000093;
AKEYCODE_NUMPAD_4 = $00000094;
AKEYCODE_NUMPAD_5 = $00000095;
AKEYCODE_NUMPAD_6 = $00000096;
AKEYCODE_NUMPAD_7 = $00000097;
AKEYCODE_NUMPAD_8 = $00000098;
AKEYCODE_NUMPAD_9 = $00000099;
AKEYCODE_NUMPAD_ADD = $0000009d;
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 = $0000008f;
implementation
end.

View File

@ -229,6 +229,8 @@ function Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished(
function Java_com_pascal_lclproject_LCLActivity_LCLOnKey(
env:PJNIEnv; this:jobject; AKind: jint; AKeyCode: jint;
AEvent: jobject; AChar: jchar): jint; cdecl;
function Java_com_pascal_lclproject_LCLActivity_LCLOnTimer(
env:PJNIEnv; this:jobject; ATimer: jobject): jint; cdecl;
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl;
@ -259,11 +261,16 @@ var
javaField_lcltextdescent: JfieldID=nil;
javaField_lcltextleading: JfieldID=nil;
javaField_lcltexttop: JfieldID=nil;
// Timer
javaField_lcltimerinterval: JfieldID=nil;
javaField_lcltimerid: JfieldID=nil;
// Methods of our Activity
javaMethod_LCLDoGetTextBounds: jmethodid = nil;
javaMethod_LCLDoDrawText: jmethodid = nil;
javaMethod_LCLDoShowMessageBox: jmethodid = nil;
javaMethod_LCLDoCreateTimer: jmethodid = nil;
javaMethod_LCLDoDestroyTimer: jmethodid = nil;
// This is utilized to store the information such as invalidate requests in events
eventResult: jint;

View File

@ -182,7 +182,27 @@ begin
Result := eventResult;
end;
const NativeMethods: array[0..4] of JNINativeMethod=
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;),
@ -197,7 +217,10 @@ const NativeMethods: array[0..4] of JNINativeMethod=
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished;),
(name:'LCLOnKey';
signature:'(IILandroid/view/KeyEvent;C)I';
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnKey;)
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;
@ -255,6 +278,10 @@ begin
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');
@ -265,6 +292,8 @@ begin
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');
__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad finished');
result:=JNI_VERSION_1_4;// 1_6 is another option
@ -300,13 +329,13 @@ begin
AKEYCODE_8: Result := VK_8;
AKEYCODE_9: Result := VK_9;
{ AKEYCODE_STAR = 17;
AKEYCODE_POUND = 18;
AKEYCODE_DPAD_UP = 19;
AKEYCODE_DPAD_DOWN = 20;
AKEYCODE_DPAD_LEFT = 21;
AKEYCODE_DPAD_RIGHT = 22;
AKEYCODE_DPAD_CENTER = 23;
AKEYCODE_VOLUME_UP = 24;
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_CENTER;
{ AKEYCODE_VOLUME_UP = 24;
AKEYCODE_VOLUME_DOWN = 25;
AKEYCODE_POWER = 26;
AKEYCODE_CAMERA = 27;
@ -337,15 +366,15 @@ begin
AKEYCODE_X: Result := VK_X;
AKEYCODE_Y: Result := VK_Y;
AKEYCODE_Z: Result := VK_Z;
{ AKEYCODE_COMMA = 55;
AKEYCODE_PERIOD = 56;
AKEYCODE_ALT_LEFT = 57;
//AKEYCODE_COMMA: Result := VK_?
//AKEYCODE_PERIOD = 56;
{ AKEYCODE_ALT_LEFT = 57;
AKEYCODE_ALT_RIGHT = 58;
AKEYCODE_SHIFT_LEFT = 59;
AKEYCODE_SHIFT_RIGHT = 60;
AKEYCODE_TAB = 61;
AKEYCODE_SPACE = 62;
AKEYCODE_SYM = 63;
AKEYCODE_SHIFT_RIGHT = 60;}
//AKEYCODE_TAB: Result := VK_Z;
AKEYCODE_SPACE: Result := VK_SPACE;
{ AKEYCODE_SYM = 63;
AKEYCODE_EXPLORER = 64;
AKEYCODE_ENVELOPE = 65;
AKEYCODE_ENTER = 66;
@ -393,6 +422,28 @@ begin
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 = $0000008f;}
else
Result := 0;
end;
@ -671,7 +722,27 @@ end;
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;
{------------------------------------------------------------------------------
@ -680,7 +751,25 @@ end;
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);

View File

@ -12,7 +12,8 @@ uses
IntfGraphics, lazcanvas, lazregions,
// LCL
GraphType, Controls, LCLMessageGlue, WSControls, LCLType, LCLProc,
StdCtrls, ExtCtrls, Forms, Graphics, customdrawncontrols;
StdCtrls, ExtCtrls, Forms, Graphics, customdrawncontrols,
InterfaceBase;
type
TUpdateLazImageFormat = (
@ -70,6 +71,13 @@ type
Image: TLazIntfImage;
end;
TCDTimer = class
public
NativeHandle: PtrInt;
Interval: integer;
TimerFunc: TWSTimerProc;
end;
// Routines for form managing (both native and non-native)
procedure AddCDWinControlToForm(const AForm: TCustomForm; ACDWinControl: TCDWinControl);
@ -111,12 +119,22 @@ function IsValidGDIObject(AGDIObj: HGDIOBJ): Boolean;
function IsValidBitmap(ABitmap: HBITMAP): Boolean;
function RemoveAccelChars(AStr: string): string;
// Timers list management (for platforms that need it)
procedure InitTimersList();
procedure AddTimer(ATimer: TCDTimer);
procedure RemoveTimer(ATimer: TCDTimer);
function FindTimerWithNativeHandle(ANativeHandle: PtrInt): TCDTimer;
implementation
// List with the Z-order of non-native forms, index=0 is the bottom-most form
var
// List with the Z-order of non-native forms, index=0 is the bottom-most form
NonNativeForms: TFPList = nil;
// List of timers
TimersList: TFPList = nil;
procedure AddCDWinControlToForm(const AForm: TCustomForm; ACDWinControl: TCDWinControl);
var
lWindowInfo: TCDForm;
@ -504,6 +522,38 @@ begin
Result := StringReplace(AStr, '&', '', [rfReplaceAll]);
end;
procedure InitTimersList;
begin
if TimersList = nil then TimersList := TFPList.Create;
end;
procedure AddTimer(ATimer: TCDTimer);
begin
InitTimersList();
TimersList.Add(ATimer);
end;
procedure RemoveTimer(ATimer: TCDTimer);
begin
InitTimersList();
TimersList.Remove(ATimer);
end;
function FindTimerWithNativeHandle(ANativeHandle: PtrInt): TCDTimer;
var
lTimer: TCDTimer;
i: Integer;
begin
Result := nil;
InitTimersList();
for i := 0 to TimersList.Count - 1 do
begin
lTimer := TCDTimer(TimersList.Items[i]);
if lTimer.NativeHandle = ANativeHandle then
Exit(lTimer);
end;
end;
{ TCDBaseControl }
function TCDBaseControl.GetProps(AnIndex: String): pointer;

View File

@ -1,8 +1,14 @@
{%MainUnit customdrawnint.pas}
{******************************************************************************
All QT Winapi related stuff goes here.
This are the overrides of the QT Interface for the methods defined in the
All CustomDrawn Winapi related stuff goes here.
Note the structure which allows multiple implementations of the same method:
customdrawnwinapi.inc -> Generic implementation
customdrawnwinapi_*.inc -> Backend specific implementations
This are the overrides of the CustomDrawn Interface for the methods defined in the
lcl/include/winapih.inc
!! Keep this alphabetical !!