1{%MainUnit customdrawnint.pas} 2 3{****************************************************************************** 4 customdrawnobject_win.inc 5 ****************************************************************************** 6 7 ***************************************************************************** 8 This file is part of the Lazarus Component Library (LCL) 9 10 See the file COPYING.modifiedLGPL.txt, included in this distribution, 11 for details about the license. 12 ***************************************************************************** 13} 14 15const 16 // Shared Mouse / Key constants 17 ACTION_DOWN = 0; 18 ACTION_UP = 1; 19 20 // Touch constants 21 ACTION_MOVE = 2; 22 23 // Constants from android/view/KeyEvent up to level 8 24 ACTION_MULTIPLE = 2; 25 // Keys are in KeyCodes.pas 26 27 // from android.view.KeyCharacterMap 28 COMBINING_ACCENT = $80000000; 29 30const 31 javaConstant_CLIPBOARD_SERVICE = 'clipboard'; 32 javaConstant_Intent_ACTION_VIEW = 'android.intent.action.VIEW'; 33 34 javaConstant_PackageManager_MATCH_DEFAULT_ONLY = $00010000; 35 36function Java_com_pascal_lclproject_LCLActivity_LCLOnTouch(env:PJNIEnv;this:jobject; x, y: single; action: jint): jint; cdecl; 37var 38 lCurForm: TCDNonNativeForm; 39 lTarget: TWinControl; 40 lEventPos: TPoint; 41begin 42 {$ifdef VerboseCDEvents} 43 __android_log_write(ANDROID_LOG_INFO,'lclapp',PChar(Format('LCLOnTouch called x=%f y=%f action=%d', [x, y, action]))); 44 {$endif} 45 eventResult := 0; 46 47 lCurForm := GetCurrentForm(); 48 49 case action of 50 ACTION_DOWN: 51 begin 52 CallbackMouseDown(lCurForm, Round(X), Round(Y), mbLeft, []); 53 end; 54 ACTION_UP: 55 begin 56 CallbackMouseUp(lCurForm, Round(X), Round(Y), mbLeft, []); 57 end; 58 ACTION_MOVE: CallbackMouseMove(lCurForm, Round(X), Round(Y), []); 59 end; 60 61 // This sends messages like Invalidate requests 62 Result := eventResult; 63end; 64 65function Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap( 66 env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl; 67var 68 pixels: PCardinal; 69 lCurForm: TCDNonNativeForm; 70 71 {$IFDEF VerboseCDPaintProfiler} 72 lTimeStart: TDateTime; 73 {$ENDIF} 74begin 75 Result := 0; 76 AndroidBitmap_lockPixels(env, abitmap, @pixels); 77 78 lCurForm := GetCurrentForm(); 79 if lCurForm <> nil then 80 begin 81 {$IFDEF VerboseCDPaintProfiler} 82 //lTimeStart := NowUTC(); 83 {$ENDIF} 84 {$IFDEF VerboseCDPaintEvent} 85 DebugLn(Format('[Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap] lCurForm:TCDNonNativeForm=%x', [PtrInt(lCurForm)])); 86 {$ENDIF} 87 88 // Prepare the non-native image and canvas 89 UpdateControlLazImageAndCanvas(lCurForm.Image, lCurForm.Canvas, Width, Height, clfRGBA32, pixels, True, False); 90 91 RenderForm(lCurForm.Image, lCurForm.Canvas, lCurForm.LCLForm); 92 end; 93 94 // Now returns the bitmap buffer to LCLActivity so that it can render it 95 AndroidBitmap_unlockPixels(env, abitmap); 96end; 97 98function Java_com_pascal_lclproject_LCLActivity_LCLOnCreate( 99 env:PJNIEnv; this:jobject; alclactivity: jobject): jint; cdecl; 100begin 101 __android_log_write(ANDROID_LOG_INFO, 'lclapp', 'LCLOnCreate called by LCLActivity.onCreate'); 102 Result := 0; 103 javaActivityObject := alclactivity; 104 Screen.UpdateScreen(); // Any values read before LCLOnCreate are wrong 105 // Update the font size 106 CDWidgetset.DefaultFontAndroidSize := Round(16 * (Screen.PixelsPerInch / 125)); 107 // Now inform the application 108 if Assigned(CDWidgetset.ActivityOnCreate) then CDWidgetset.ActivityOnCreate() 109 else Application.Run; // <- Support for older code up to 21 dezember 2011 110end; 111 112// This one is for all simple dialogs: MessageBox, PromptUser (MessageDlg) and AskUser 113function Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished( 114 env:PJNIEnv; this:jobject; AResult, ADialogType: jint): jint; cdecl; 115begin 116 __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('LCLOnMessageBoxFinished called AResult=%d ADialogType=%d', 117 [AResult, ADialogType]))); 118 Result := 0; 119 case ADialogType of 120 0: if Assigned(Application.OnMessageDialogFinished) then 121 Application.OnMessageDialogFinished(Application, AResult); 122 1: if Assigned(OnShowSelectItemDialogResult) then OnShowSelectItemDialogResult(AResult); 123 2: if Assigned(OnListViewDialogResult) then OnListViewDialogResult(AResult); 124 end; 125end; 126 127function Java_com_pascal_lclproject_LCLActivity_LCLOnKey( 128 env:PJNIEnv; this:jobject; AKind: jint; AKeyCode: jint; 129 AEvent: jobject; AChar: jint): jint; cdecl; 130var 131 lCurForm: TCDNonNativeForm; 132 lTarget, lFocusedControl: TWinControl; 133 lKey: Word; 134 lCombinedAChar: jint; 135 lChar: Cardinal; 136 AUTF8Text: string; 137 AUTF8Char: TUTF8Char; 138 lForm: TCDNonNativeForm; 139begin 140 lChar := Cardinal(AChar); 141 {$ifdef VerboseCDKeyInput} 142 __android_log_write(ANDROID_LOG_INFO,'lclapp',PChar( 143 Format('[LCLOnKey] called AKind=%d AKeyCode=%x AChar=%s', [AKind, AKeyCode, UnicodeToUTF8(lChar)]))); 144 {$endif} 145 eventResult := 0; 146 147 lCurForm := GetCurrentForm(); 148 lKey := CDWidgetset.AndroidKeyCodeToLCLKeyCode(AKeyCode); 149 150 case AKind of 151 ACTION_DOWN: 152 begin 153 CallbackKeyDown(lCurForm, lKey); 154 155 // Galaxy Nexus S with Android 4.0 sends numbers only as key down/up events, 156 // it doesn't send them to commit text 157 // 158 // Wildfire with Android 2.2 sends the numbers only to commit text 159 // 160 // So if we get any numbers here, generate KeyPress too 161 case lKey of 162 VK_0..VK_9: 163 begin 164 AUTF8Char := VK2Char(lKey); 165 CallbackKeyChar(lCurForm, lKey, AUTF8Char); 166 end; 167 end; 168 end; 169 // This indicates a key char event, created with commitText 170 // We don't get KeyDown/KeyUp when we get this, so generate them 171 -1: 172 begin 173 AUTF8Text := UnicodeToUTF8(lChar); 174 AUTF8Char := AUTF8Text; 175 176 if Length(AUTF8Text) = 1 then 177 begin 178 lKey := Char2VK(AUTF8Text[1]); 179 CallbackKeyDown(lCurForm, lKey); 180 end; 181 182 CallbackKeyChar(lCurForm, lKey, AUTF8Char); 183 184 if Length(AUTF8Text) = 1 then 185 CallbackKeyUp(lCurForm, lKey); 186 end; 187 ACTION_UP: 188 begin 189 CallbackKeyUp(lCurForm, lKey); 190(* if (lChar <> 0) and ((COMBINING_ACCENT and lChar) = 0) then 191 begin 192 if CDWidgetset.CombiningAccent <> 0 then 193 begin 194 // Prepare the input 195 lJavaString :=javaEnvRef^^.NewStringUTF(javaEnvRef, Str); 196 javaEnvRef^^.SetObjectField(javaEnvRef, javaActivityObject, JavaField_lcltext, lJavaString); 197 javaEnvRef^^.SetIntField(javaEnvRef, javaActivityObject, javaField_lcltextsize, lFontSize); 198 199 // Call the method 200 javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_LCLDoGetTextBounds); 201 202 // Read the output 203 Size.cx := javaEnvRef^^.GetIntField(javaEnvRef, javaActivityObject, javaField_lclwidth); 204 Size.cy := javaEnvRef^^.GetIntField(javaEnvRef, javaActivityObject, javaField_lclheight); 205 // 206 lCombinedAChar := getDeadChar(); 207 end; 208 AUTF8Text := UnicodeToUTF8(lChar); 209 AUTF8Char := AUTF8Text; 210 CallbackKeyChar(lCurForm, lKey, AUTF8Char); 211 CDWidgetset.CombiningAccent := 0; 212 end 213 else if (lChar <> 0) and ((COMBINING_ACCENT and lChar) <> 0) then 214 begin 215 CDWidgetset.CombiningAccent := lChar; 216 end;*) 217 218 // Handle the Back hardware key 219 if AKeyCode = AKEYCODE_BACK then 220 begin 221 //DebugLn(Format('CallbackKeyUp D lForm=%x', [PtrInt(lForm)])); 222 // The back hardware key hides the current form and shows the one bellow it 223 // except if the currently focused control is a text editor, in which case 224 // it will take focus out of the text editor 225 lForm := lCurForm; 226 lFocusedControl := lForm.GetFocusedControl(); 227 if (lFocusedControl <> nil) and (csRequiresKeyboardInput in lFocusedControl.ControlStyle) then 228 begin 229 //DebugLn('[LCLOnKey] Sending focus to the form'); 230 CDWidgetset.CDSetFocusToControl(lForm.LCLForm, nil); 231 end 232 // If this is the main form, then go back to desktop 233 else if (Application.MainForm <> nil) and (lForm = TCDForm(Application.MainForm.Handle)) then 234 begin 235 //DebugLn('[LCLOnKey] Back key is going to hide the application'); 236 eventResult := eventResult or 2; 237 end 238 // for other forms, hide them 239 else 240 begin 241 //DebugLn('[LCLOnKey] Hiding the form'); 242 HideForm(lForm); 243 end; 244 end; 245 end; 246 //ACTION_MULTIPLE: 247 end; 248 249 // This sends messages like Invalidate requests 250 Result := eventResult; 251end; 252 253function Java_com_pascal_lclproject_LCLActivity_LCLOnTimer( 254 env:PJNIEnv; this:jobject; ATimer: jobject; ATimerIDIndex: jint): jint; cdecl; 255var 256 lTimer: TCDTimer; 257begin 258 {$ifdef VerboseCDEvents} 259 __android_log_write(ANDROID_LOG_INFO,'lclapp',PChar( 260 Format('LCLOnTimer called ATimer=%x', [PtrInt(ATimer)]))); 261 {$endif} 262 eventResult := 0; 263 264 lTimer := FindTimerWithNativeHandle(PtrInt(ATimer)); 265 266 if lTimer <> nil then lTimer.TimerFunc() 267 else DebugLn('[LCLOnTimer] OnTimer message sent to unknown timer!'); 268 269 // This sends messages like Invalidate requests 270 Result := eventResult; 271end; 272 273function Java_com_pascal_lclproject_LCLActivity_LCLOnConfigurationChanged( 274 env:PJNIEnv; this:jobject; ANewDPI, ANewWidth: jint): jint; cdecl; 275var 276 lForm: TCDNonNativeForm; 277 lOldDPI, lNewDPI, lOldFormWidth, lNewFormWidth: Integer; 278 i: Integer; 279begin 280 for i := 0 to GetFormCount()-1 do 281 begin 282 lForm := GetForm(i); 283 284 if lForm.LayoutAutoAdjusted then lOldDPI := Screen.PixelsPerInch 285 else lOldDPI := lForm.LCLForm.DesignTimePPI; 286 lNewDPI := ANewDPI; 287 lOldFormWidth := lForm.LCLForm.Width; 288 lNewFormWidth := ANewWidth; 289 DebugLn(Format('[LCLOnConfigurationChanged] i=%d lOldDPI=%d lNewDPI=%d lOldFormWidth=%d lNewFormWidth=%d', 290 [i, lOldDPI, lNewDPI, lOldFormWidth, lNewFormWidth])); 291 lForm.LCLForm.AutoAdjustLayout(lapAutoAdjustWithoutHorizontalScrolling, 292 lOldDPI, lNewDPI, lOldFormWidth, lNewFormWidth); 293 end; 294 295 // Update the font size 296 CDWidgetset.DefaultFontAndroidSize := Round(16 * (ANewDPI / 125)); 297end; 298 299function Java_com_pascal_lclproject_LCLActivity_LCLOnSensorChanged( 300 env:PJNIEnv; this:jobject; ASensorKind: jint; AValues: JDoubleArray): jint; cdecl; 301var 302 arraydata: PDouble; 303 arraylen: jsize; 304 lIsCopy: jboolean; 305 lSensorDataInt: Integer; 306 lMessagingStatus: TLazMessagingStatus; 307 lUnixTimeStamp: Int64; 308begin 309 Result := 0; 310 311 if (javaEnvRef = nil) then Exit; 312 313 // Get the elements and length 314 lIsCopy := 0; 315 arraylen := javaEnvRef^^.GetArrayLength(javaEnvRef, AValues); 316 arraydata := javaEnvRef^^.GetDoubleArrayElements(javaEnvRef, AValues, lIsCopy); 317 318 // Send the data to the LCL 319 case ASensorKind of 320 -11: // Defined by ourselves for Messaging Status 321 begin 322 lSensorDataInt := Round(arraydata[0]); 323 case lSensorDataInt of 324 1: lMessagingStatus := mssSentSuccessfully; 325 2: lMessagingStatus := mssSendingGeneralError; 326 3: lMessagingStatus := mssNoService; 327 5: lMessagingStatus := mssRadioOff; 328 10:lMessagingStatus := mssReceivedSuccessfully; 329 11:lMessagingStatus := mssReceivingGeneralError; 330 else 331 lMessagingStatus := mssSendingGeneralError; 332 end; 333 334 if Assigned(Messaging.OnMessagingStatus) then 335 Messaging.OnMessagingStatus(nil, lMessagingStatus); 336 end; 337 -10: // Defined by ourselves for PositionInfo 338 begin 339 PositionInfo.latitude := arraydata[0]; 340 PositionInfo.longitude := arraydata[1]; 341 PositionInfo.altitude := arraydata[2]; 342 PositionInfo.accuracy := arraydata[3]; 343 PositionInfo.altitudeAccuracy := PositionInfo.accuracy; 344 PositionInfo.speed := arraydata[4]; 345 lUnixTimeStamp := Round(arraydata[5]); 346 PositionInfo.timeStamp := UnixToDateTime(lUnixTimeStamp); 347 348 if Assigned(PositionInfo.OnPositionRetrieved) then 349 PositionInfo.OnPositionRetrieved(PositionInfo); 350 end; 351 1: // ACCELEROMETER 352 begin 353 Accelerometer.xaxis := -1*arraydata[0]; 354 Accelerometer.yaxis := -1*arraydata[1]; 355 Accelerometer.zaxis := -1*arraydata[2]; 356 if Assigned(Accelerometer.OnSensorChanged) then 357 Accelerometer.OnSensorChanged(Accelerometer); 358 end; 359 end; 360 361 // Don't forget to release it 362 javaEnvRef^^.ReleaseDoubleArrayElements(javaEnvRef, AValues, arraydata, 0); 363 364 // This sends messages like Invalidate requests 365 Result := eventResult; 366end; 367 368function Java_com_pascal_lclproject_LCLActivity_LCLOnMenuAction( 369 env:PJNIEnv; this:jobject; kind, itemIndex: jint): jint; cdecl; 370var 371 javaField_lclmenu_captions: jfieldid; 372 javaObject_lclmenu_captions: jobjectarray; 373 lJavaString: jstring; 374 lCurrentForm: TCDNonNativeForm; 375 lMenu: TMainMenu; 376 StrPas: string; 377 Str: PChar; 378 lMenuItem: TMenuItem; 379 i, CurIndex, NumMenuItems: Integer; 380begin 381 Result := 0; 382 383 // Very strangely in the emulator it crashes if we don't refresh the Activity class here 384 javaActivityClass := javaEnvRef^^.FindClass(javaEnvRef, PChar(CDWidgetset.ActivityClassName)); 385 386 //{$ifdef VerboseCDEvents} 387 DebugLn(Format('LCLOnMenuAction called kind=%d itemIndex=%d', [kind, itemIndex])); 388 //{$endif} 389 390 if (javaEnvRef = nil) then Exit; 391 392 lCurrentForm := GetCurrentForm(); 393 if lCurrentForm = nil then Exit; 394 lMenu := lCurrentForm.LCLForm.Menu; 395 if lMenu = nil then Exit; 396 397 // kind=0 means that we should create the menu items list 398 if kind = 0 then 399 begin 400 // First calculate the number of menu items 401 NumMenuItems := 0; 402 for i := 0 to lMenu.Items.Count-1 do 403 begin 404 lMenuItem := lMenu.Items[i]; 405 // Various things might make a menu item invalid and therefore not part of the list 406 if not lMenuItem.Visible then Continue; 407 if lMenuItem.Caption = '-' then Continue; 408 Inc(NumMenuItems); 409 end; 410 411 // Now fill the items 412 javaField_lclmenu_captions := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclmenu_captions', '[Ljava/lang/String;'); 413// javaObject_lclmenu_captions := javaEnvRef^^.GetObjectField(javaEnvRef, javaActivityClass, javaField_lclmenu_captions); 414 javaObject_lclmenu_captions := javaEnvRef^^.NewObjectArray(javaEnvRef, NumMenuItems, 415 javaJavaLangStringClass, javaEnvRef^^.NewStringUTF(javaEnvRef, '')); 416// DebugLn(Format('LCLOnMenuAction lclmenu_captions field=%x object=%x', [PtrUInt(javaField_lclmenu_captions), PtrUInt(javaObject_lclmenu_captions)])); 417 418 CurIndex := 0; 419 StrPas := ''; 420 for i := 0 to lMenu.Items.Count-1 do 421 begin 422 DebugLn(Format('LCLOnMenuAction item=%d', [i])); 423 lMenuItem := lMenu.Items[i]; 424 // Various things might make a menu item invalid and therefore not part of the list 425 if not lMenuItem.Visible then Continue; 426 if lMenuItem.Caption = '-' then Continue; 427 428 StrPas := lMenuItem.Caption; 429 Str := PChar(StrPas); 430 lJavaString := javaEnvRef^^.NewStringUTF(javaEnvRef, Str); 431 DebugLn(Format('LCLOnMenuAction lJavaString=%x Str=%s javaObject_lclmenu_captions=%x', [PtrUInt(lJavaString), StrPas, PtrUInt(javaObject_lclmenu_captions)])); 432 javaEnvRef^^.SetObjectArrayElement(javaEnvRef, javaObject_lclmenu_captions, CurIndex, lJavaString); 433 javaEnvRef^^.DeleteLocalRef(javaEnvRef, lJavaString); 434 435 Inc(CurIndex); 436 437 if CurIndex >= NumMenuItems then Break; 438 end; 439 440 javaEnvRef^^.SetObjectField(javaEnvRef, javaActivityObject, javaField_lclmenu_captions, javaObject_lclmenu_captions); 441 javaEnvRef^^.DeleteLocalRef(javaEnvRef, javaObject_lclmenu_captions); 442 end 443 // kind=1 means a button click event 444 else 445 begin 446 // Searched for the clicked item 447 CurIndex := 0; 448 for i := 0 to lMenu.Items.Count-1 do 449 begin 450 lMenuItem := lMenu.Items[i]; 451 // Various things might make a menu item invalid and therefore not part of the list 452 if not lMenuItem.Visible then Continue; 453 if lMenuItem.Caption = '-' then Continue; 454 455 if itemIndex = CurIndex then Break; 456 457 Inc(CurIndex); 458 end; 459 460 lMenuItem.Click(); 461 end; 462 463 // This sends messages like Invalidate requests 464 Result := eventResult; 465 DebugLn('Fim'); 466end; 467 468const NativeMethods: array[0..8] of JNINativeMethod= 469 ((name:'LCLDrawToBitmap'; 470 signature:'(IILandroid/graphics/Bitmap;)I'; 471 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap;), 472 (name:'LCLOnTouch'; 473 signature:'(FFI)I'; 474 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnTouch;), 475 (name:'LCLOnCreate'; 476 signature:'(Landroid/app/Activity;)I'; // Don't use a name which includes the package name like com/pascal/lcltest/LCLActivity; 477 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnCreate;), 478 (name:'LCLOnMessageBoxFinished'; 479 signature:'(II)I'; 480 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnMessageBoxFinished;), 481 (name:'LCLOnKey'; 482 signature:'(IILandroid/view/KeyEvent;I)I'; 483 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnKey;), 484 (name:'LCLOnTimer'; 485 signature:'(Ljava/lang/Runnable;I)I'; 486 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnTimer;), 487 (name:'LCLOnConfigurationChanged'; 488 signature:'(II)I'; 489 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnConfigurationChanged;), 490 (name:'LCLOnSensorChanged'; 491 signature:'(I[D)I'; 492 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnSensorChanged;), 493 (name:'LCLOnMenuAction'; 494 signature:'(II)I'; 495 fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLOnMenuAction;) 496 ); 497 498function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl; 499begin 500 javaVMRef := vm; 501 502 __android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad called'); 503{ __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm=%x', [PtrInt(vm)]))); 504 __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm^=%x', [PtrInt(vm^)]))); 505 __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm^^.reserved0=%x', [PtrInt(vm^^.reserved0)]))); 506 __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(Format('vm^^.GetEnv=%x', [PtrInt(Pointer(@vm^^.GetEnv))]))); } 507 { 508 vm^^.GetEnv crashes HTC Wildfire, Alcatel and the Emulator if you don't build your project with -CpARMV6 509 see: http://groups.google.com/group/android-ndk/browse_thread/thread/ba542483f062a828/ef9077617794e0f5 510 } 511 if vm^^.GetEnv(vm,@javaEnvRef,JNI_VERSION_1_4)<>JNI_OK then 512 begin 513 __android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'curVM^.GetEnv failed'); 514 Exit(JNI_ERR); 515 end; 516 517 // Find our activity class 518 __android_log_write(ANDROID_LOG_INFO,'lclapp','Reading our Activity Class'); 519 javaActivityClass := javaEnvRef^^.FindClass(javaEnvRef, PChar(CDWidgetset.ActivityClassName)); 520 if not assigned(javaActivityClass) then 521 begin 522 __android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'javaEnvRef^.FindClass failed'); 523 Exit(JNI_ERR); 524 end; 525 // Now other classes 526 javaAndroidAppActivityClass := javaEnvRef^^.FindClass(javaEnvRef,'android/app/Activity'); 527 javaJavaLangSystemClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/System'); 528 javaAndroidOSBuildClass := javaEnvRef^^.FindClass(javaEnvRef,'android/os/Build'); 529 javaAndroidOSVibratorClass := javaEnvRef^^.FindClass(javaEnvRef,'android/os/Vibrator'); 530 javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context'); 531 javaJavaLangStringClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/String'); 532 javaAndroidOSBuildVERSIONClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/os/Build$VERSION'); 533 534 // Register Pascal exported calls 535 if javaEnvRef^^.RegisterNatives(javaEnvRef, javaActivityClass, @NativeMethods[0],length(NativeMethods))<0 then 536 begin 537 __android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'javaEnvRef^.RegisterNatives failed'); 538 // Exit(JNI_ERR); Don't exit if exporting the native method fails because it works without this too 539 end; 540 541 // Read all field IDs 542 JavaField_lcltext := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltext', 'Ljava/lang/String;'); 543 JavaField_lcltitle := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltitle', 'Ljava/lang/String;'); 544 JavaField_lclbutton1str := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton1str', 'Ljava/lang/String;'); 545 JavaField_lclbutton2str := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton2str', 'Ljava/lang/String;'); 546 JavaField_lclbutton3str := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton3str', 'Ljava/lang/String;'); 547 // 548 JavaField_lclwidth := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclwidth', 'I'); 549 JavaField_lclheight := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclheight', 'I'); 550 JavaField_lclbutton1 := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton1', 'I'); 551 JavaField_lclbutton2 := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton2', 'I'); 552 JavaField_lclbutton3 := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbutton3', 'I'); 553 JavaField_lclbitmap := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclbitmap', 'Landroid/graphics/Bitmap;'); 554 JavaField_lcltextsize := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextsize', 'I'); 555 // Text metrics 556 javaField_lcltextascent := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextascent', 'I'); 557 javaField_lcltextbottom := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextbottom', 'I'); 558 javaField_lcltextdescent := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextdescent', 'I'); 559 javaField_lcltextleading := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltextleading', 'I'); 560 javaField_lcltexttop := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltexttop', 'I'); 561 javaField_lclmaxwidth := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclmaxwidth', 'I'); 562 javaField_lclmaxcount := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclmaxcount', 'I'); 563 javaField_lclpartialwidths := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclpartialwidths', '[F'); 564 // Timer 565 javaField_lcltimerinterval := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltimerinterval', 'I'); 566 javaField_lcltimerid := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcltimerid', 'Ljava/lang/Runnable;'); 567 // Screen Metrics 568 javaField_lclxdpi := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclxdpi', 'I'); 569 javaField_lclydpi := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclydpi', 'I'); 570 javaField_lclformwidth := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclformwidth', 'I'); 571 javaField_lclformheight := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclformheight', 'I'); 572 javaField_lclscreenwidth := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclscreenwidth', 'I'); 573 javaField_lclscreenheight := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclscreenheight', 'I'); 574 // For LazDeviceAPIs 575 javaField_lcldestination := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lcldestination', 'Ljava/lang/String;'); 576 javaField_lclkind := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclkind', 'I'); 577 // 578 if not assigned(JavaField_lcltext) then 579 begin 580 __android_log_write(ANDROID_LOG_FATAL, 'lclapp', 'javaEnvRef^.GetFieldID failed for lcltext'); 581 Exit(JNI_ERR); 582 end; 583 584 // Read all method IDs 585 javaMethod_LCLDoGetTextBounds := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoGetTextBounds', '()V'); 586 javaMethod_LCLDoGetTextPartialWidths := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoGetTextPartialWidths', '()V'); 587 javaMethod_LCLDoDrawText := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoDrawText', '(I)V'); 588 javaMethod_LCLDoShowMessageBox := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoShowMessageBox', '()V'); 589 javaMethod_LCLDoCreateTimer := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoCreateTimer', '()V'); 590 javaMethod_LCLDoDestroyTimer := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoDestroyTimer', '()V'); 591 javaMethod_LCLDoHideVirtualKeyboard := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoHideVirtualKeyboard', '()V'); 592 javaMethod_LCLDoShowVirtualKeyboard := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoShowVirtualKeyboard', '()V'); 593 javaMethod_LCLDoStartReadingAccelerometer := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoStartReadingAccelerometer', '()V'); 594 javaMethod_LCLDoStopReadingAccelerometer := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoStopReadingAccelerometer', '()V'); 595 javaMethod_LCLDoSendMessage := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoSendMessage', '()V'); 596 javaMethod_LCLDoRequestPositionInfo := javaEnvRef^^.GetMethodID(javaEnvRef, javaActivityClass, 'LCLDoRequestPositionInfo', '()V'); 597 // Methods from android.app.Activity 598 javaMethod_Activity_finish := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidAppActivityClass, 'finish', '()V'); 599 // Methods from java.lang.System 600 javaMethod_System_exit := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaJavaLangSystemClass, 'exit', '(I)V'); 601 // Generic methods from Context 602 javaMethod_getSystemService := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentContextClass, 'getSystemService', '(Ljava/lang/String;)Ljava/lang/Object;'); 603 604 // Read the SDK Version and store it 605 javaField_VERSION_SDK_INT := javaEnvRef^^.GetStaticFieldID(javaEnvRef, javaAndroidOSBuildVERSIONClass, 'SDK_INT', 'I'); 606 android_os_Build_VERSION_SDK_INT := javaEnvRef^^.GetStaticIntField(javaEnvRef, javaAndroidOSBuildVERSIONClass, javaField_VERSION_SDK_INT); 607 608 __android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad finished'); 609 result:=JNI_VERSION_1_4;// 1_6 is another option 610end; 611 612procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl; 613begin 614end; 615 616{$IFnDEF WithOldDebugln} 617procedure TCDWidgetSet.AndroidDebugLn(ASender: TObject; AStr: string; var AHandled: Boolean; 618 Target: TLazLoggerWriteTarget; Data: Pointer); 619begin 620 AHandled := Target in [lwtStdOut, lwtStdErr]; 621 if not AHandled then exit; 622 __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(AccumulatedStr+AStr)); 623 AccumulatedStr := ''; 624end; 625{$ELSE} 626procedure TCDWidgetSet.AndroidDebugLn(AStr: string); 627begin 628 __android_log_write(ANDROID_LOG_INFO, 'lclapp', PChar(AccumulatedStr+AStr)); 629 AccumulatedStr := ''; 630end; 631{$ENDIF} 632 633function TCDWidgetSet.AndroidKeyCodeToLCLKeyCode(AAndroidKeyCode: Integer): Word; 634var 635 lExtendedKeysSupport: Boolean; 636begin 637 lExtendedKeysSupport := Application.ExtendedKeysSupport; 638 639 case AAndroidKeyCode of 640 // First keys which are defined in NDK too 641{ KEYCODE_SOFT_LEFT = 1; 642 KEYCODE_SOFT_RIGHT = 2; 643 KEYCODE_HOME = 3;} 644 KEYCODE_BACK: Result := VK_ESCAPE; 645 KEYCODE_CALL: Result := VK_LCL_CALL; 646 KEYCODE_ENDCALL: Result := VK_LCL_ENDCALL; 647 KEYCODE_0: Result := VK_0; 648 KEYCODE_1: Result := VK_1; 649 KEYCODE_2: Result := VK_2; 650 KEYCODE_3: Result := VK_3; 651 KEYCODE_4: Result := VK_4; 652 KEYCODE_5: Result := VK_5; 653 KEYCODE_6: Result := VK_6; 654 KEYCODE_7: Result := VK_7; 655 KEYCODE_8: Result := VK_8; 656 KEYCODE_9: Result := VK_9; 657{ KEYCODE_STAR = 17; 658 KEYCODE_POUND = 18;} 659 KEYCODE_DPAD_UP: Result := VK_UP; 660 KEYCODE_DPAD_DOWN: Result := VK_DOWN; 661 KEYCODE_DPAD_LEFT: Result := VK_LEFT; 662 KEYCODE_DPAD_RIGHT: Result := VK_RIGHT; 663 KEYCODE_DPAD_CENTER: Result := VK_RETURN; 664 KEYCODE_VOLUME_UP: Result := VK_VOLUME_UP; 665 KEYCODE_VOLUME_DOWN: Result := VK_VOLUME_DOWN; 666 KEYCODE_POWER: Result := VK_LCL_POWER; 667// KEYCODE_CAMERA = 27;} 668 KEYCODE_CLEAR: Result := VK_CLEAR; 669 KEYCODE_A: Result := VK_A; 670 KEYCODE_B: Result := VK_B; 671 KEYCODE_C: Result := VK_C; 672 KEYCODE_D: Result := VK_D; 673 KEYCODE_E: Result := VK_E; 674 KEYCODE_F: Result := VK_F; 675 KEYCODE_G: Result := VK_G; 676 KEYCODE_H: Result := VK_H; 677 KEYCODE_I: Result := VK_I; 678 KEYCODE_J: Result := VK_J; 679 KEYCODE_K: Result := VK_K; 680 KEYCODE_L: Result := VK_L; 681 KEYCODE_M: Result := VK_M; 682 KEYCODE_N: Result := VK_N; 683 KEYCODE_O: Result := VK_O; 684 KEYCODE_P: Result := VK_P; 685 KEYCODE_Q: Result := VK_Q; 686 KEYCODE_R: Result := VK_R; 687 KEYCODE_S: Result := VK_S; 688 KEYCODE_T: Result := VK_T; 689 KEYCODE_U: Result := VK_U; 690 KEYCODE_V: Result := VK_V; 691 KEYCODE_W: Result := VK_W; 692 KEYCODE_X: Result := VK_X; 693 KEYCODE_Y: Result := VK_Y; 694 KEYCODE_Z: Result := VK_Z; 695 KEYCODE_COMMA: Result := VK_LCL_COMMA; 696 KEYCODE_PERIOD: Result := VK_LCL_POINT; 697 KEYCODE_ALT_LEFT: if lExtendedKeysSupport then Result := VK_LMENU else Result := VK_MENU; 698 KEYCODE_ALT_RIGHT: if lExtendedKeysSupport then Result := VK_RMENU else Result := VK_MENU; 699 KEYCODE_SHIFT_LEFT: if lExtendedKeysSupport then Result := VK_LSHIFT else Result := VK_SHIFT; 700 KEYCODE_SHIFT_RIGHT:if lExtendedKeysSupport then Result := VK_RSHIFT else Result := VK_SHIFT; 701 KEYCODE_TAB: Result := VK_TAB; 702 KEYCODE_SPACE: Result := VK_SPACE; 703{ KEYCODE_SYM = 63; 704 KEYCODE_EXPLORER = 64; 705 KEYCODE_ENVELOPE = 65;} 706 KEYCODE_ENTER: Result := VK_RETURN; 707 KEYCODE_DEL: Result := VK_BACK; // The "Backspace" key 708 KEYCODE_GRAVE: Result := VK_LCL_TILDE; 709 KEYCODE_MINUS: Result := VK_LCL_MINUS; 710 KEYCODE_EQUALS:Result := VK_LCL_EQUAL; 711 KEYCODE_LEFT_BRACKET: Result := VK_LCL_OPEN_BRAKET; 712 KEYCODE_RIGHT_BRACKET: Result := VK_LCL_CLOSE_BRAKET; 713 KEYCODE_BACKSLASH: Result := VK_LCL_BACKSLASH; 714 KEYCODE_SEMICOLON: Result := VK_LCL_SEMI_COMMA; 715 KEYCODE_APOSTROPHE: Result := VK_LCL_QUOTE; 716 KEYCODE_SLASH: Result := VK_LCL_SLASH; 717 KEYCODE_AT: Result := VK_LCL_AT; 718{ KEYCODE_NUM = 78; 719 KEYCODE_HEADSETHOOK = 79; // Headset Hook key. Used to hang up calls and stop media. 720 KEYCODE_FOCUS = 80; // *Camera* focus 721 KEYCODE_PLUS = 81;} 722 KEYCODE_MENU: Result := VK_MENU; 723{ KEYCODE_NOTIFICATION = 83; 724 KEYCODE_SEARCH = 84; 725 KEYCODE_MEDIA_PLAY_PAUSE = 85; 726 KEYCODE_MEDIA_STOP = 86; 727 KEYCODE_MEDIA_NEXT = 87; 728 KEYCODE_MEDIA_PREVIOUS = 88; 729 KEYCODE_MEDIA_REWIND = 89; 730 KEYCODE_MEDIA_FAST_FORWARD = 90; 731 KEYCODE_MUTE = 91;} 732 KEYCODE_PAGE_UP: Result := VK_NEXT; 733 KEYCODE_PAGE_DOWN: Result := VK_PRIOR; 734{ KEYCODE_PICTSYMBOLS = 94; 735 KEYCODE_SWITCH_CHARSET = 95; 736 KEYCODE_BUTTON_A = 96; 737 KEYCODE_BUTTON_B = 97; 738 KEYCODE_BUTTON_C = 98; 739 KEYCODE_BUTTON_X = 99; 740 KEYCODE_BUTTON_Y = 100; 741 KEYCODE_BUTTON_Z = 101; 742 KEYCODE_BUTTON_L1 = 102; 743 KEYCODE_BUTTON_R1 = 103; 744 KEYCODE_BUTTON_L2 = 104; 745 KEYCODE_BUTTON_R2 = 105; 746 KEYCODE_BUTTON_THUMBL = 106; 747 KEYCODE_BUTTON_THUMBR = 107; 748 KEYCODE_BUTTON_START = 108; 749 KEYCODE_BUTTON_SELECT = 109; 750 KEYCODE_BUTTON_MODE = 110;} 751 752 // Now keys from the SDK 753 754 {KEYCODE_3D_MODE = $000000ce; // 3D Mode key. Toggles the display between 2D and 3D mode. 755 KEYCODE_APP_SWITCH = $000000bb; 756 KEYCODE_AVR_INPUT = $000000b6; 757 KEYCODE_AVR_POWER = $000000b5; 758 KEYCODE_BOOKMARK = $000000ae;} 759 KEYCODE_BREAK: Result := VK_PAUSE; 760{ KEYCODE_BUTTON_1 = $000000bc; 761 KEYCODE_BUTTON_10 = $000000c5; 762 KEYCODE_BUTTON_11 = $000000c6; 763 KEYCODE_BUTTON_12 = $000000c7; 764 KEYCODE_BUTTON_13 = $000000c8; 765 KEYCODE_BUTTON_14 = $000000c9; 766 KEYCODE_BUTTON_15 = $000000ca; 767 KEYCODE_BUTTON_16 = $000000cb; // Generic Game Pad Button #16. 768 KEYCODE_BUTTON_2 = $000000bd; // Generic Game Pad Button #2. 769 KEYCODE_BUTTON_3 = $000000be; 770 KEYCODE_BUTTON_4 = $000000bf; 771 KEYCODE_BUTTON_5 = $000000c0; 772 KEYCODE_BUTTON_6 = $000000c1; 773 KEYCODE_BUTTON_7 = $000000c2; 774 KEYCODE_BUTTON_8 = $000000c3; 775 KEYCODE_BUTTON_9 = $000000c4; // Generic Game Pad Button #9. 776 KEYCODE_CALCULATOR = $000000d2; // Calculator special function key. Used to launch a calculator application. 777 KEYCODE_CALENDAR = $000000d0; // Calendar special function key. Used to launch a calendar application.} 778 KEYCODE_CAPS_LOCK: Result := VK_CAPITAL; 779{ KEYCODE_CAPTIONS = $000000af; // Toggle captions key. Switches the mode for closed-captioning text, for example during television shows. 780 KEYCODE_CHANNEL_DOWN = $000000a7; // Channel down key. On TV remotes, decrements the television channel. 781 KEYCODE_CHANNEL_UP = $000000a6; // Channel up key. On TV remotes, increments the television channel. 782 KEYCODE_CONTACTS = $000000cf; // Contacts special function key. Used to launch an address book application. 783 KEYCODE_CTRL_LEFT = $00000071; // Left Control modifier key. 784 KEYCODE_CTRL_RIGHT = $00000072; // Right Control modifier key. 785 KEYCODE_DVR = $000000ad; // DVR key. On some TV remotes, switches to a DVR mode for recorded shows. 786 KEYCODE_ENTER = $00000042; // Enter key. 787 KEYCODE_ENVELOPE = $00000041; // Envelope special function key. Used to launch a mail application. 788 KEYCODE_EQUALS = $00000046; // '=' key. 789 KEYCODE_ESCAPE = $0000006f; // Escape key. 790 KEYCODE_EXPLORER = $00000040; // Explorer special function key. Used to launch a browser application. 791 KEYCODE_F1 = $00000083; 792 KEYCODE_F10 = $0000008c; 793 KEYCODE_F11 = $0000008d; 794 KEYCODE_F12 = $0000008e; 795 KEYCODE_F2 = $00000084; 796 KEYCODE_F3 = $00000085; 797 KEYCODE_F4 = $00000086; 798 KEYCODE_F5 = $00000087; 799 KEYCODE_F6 = $00000088; 800 KEYCODE_F7 = $00000089; 801 KEYCODE_F8 = $0000008a; 802 KEYCODE_F9 = $0000008b; 803 KEYCODE_FORWARD = $0000007d; // Forward key. Navigates forward in the history stack. Complement of KEYCODE_BACK.} 804 KEYCODE_FORWARD_DEL: Result := VK_DELETE; 805{ KEYCODE_FUNCTION = $00000077; // Function modifier key. 806 KEYCODE_GUIDE = $000000ac; // Guide key. On TV remotes, shows a programming guide. 807 KEYCODE_INFO = $000000a5; // Info key. Common on TV remotes to show additional information related to what is currently being viewed.} 808 KEYCODE_INSERT: Result := VK_INSERT; 809{ KEYCODE_LANGUAGE_SWITCH = $000000cc; // Language Switch key. Toggles the current input language such as switching between English and Japanese on a QWERTY keyboard. On some devices, the same function may be performed by pressing Shift+Spacebar. 810 KEYCODE_MANNER_MODE = $000000cd; // Manner Mode key. Toggles silent or vibrate mode on and off to make the device behave more politely in certain settings such as on a crowded train. On some devices, the key may only operate when long-pressed. 811 KEYCODE_MEDIA_CLOSE = $00000080; // Close media key. May be used to close a CD tray, for example. 812 KEYCODE_MEDIA_EJECT = $00000081; // Eject media key. May be used to eject a CD tray, for example. 813 KEYCODE_MEDIA_PAUSE = $0000007f; // Pause media key. 814 KEYCODE_MEDIA_PLAY = $0000007e; // Play media key. 815 KEYCODE_MEDIA_RECORD = $00000082; // Record media key.} 816 KEYCODE_META_LEFT: Result := VK_LWIN; 817 KEYCODE_META_RIGHT: Result := VK_RWIN; 818{ KEYCODE_MOVE_END = $0000007b; // End Movement key. Used for scrolling or moving the cursor around to the end of a line or to the bottom of a list. 819 KEYCODE_MOVE_HOME = $0000007a; // Home Movement key. Used for scrolling or moving the cursor around to the start of a line or to the top of a list. 820 KEYCODE_MUSIC = $000000d1; // Music special function key. Used to launch a music player application.} 821 KEYCODE_NUMPAD_0: Result := VK_NUMPAD0; 822 KEYCODE_NUMPAD_1: Result := VK_NUMPAD1; 823 KEYCODE_NUMPAD_2: Result := VK_NUMPAD2; 824 KEYCODE_NUMPAD_3: Result := VK_NUMPAD3; 825 KEYCODE_NUMPAD_4: Result := VK_NUMPAD4; 826 KEYCODE_NUMPAD_5: Result := VK_NUMPAD5; 827 KEYCODE_NUMPAD_6: Result := VK_NUMPAD6; 828 KEYCODE_NUMPAD_7: Result := VK_NUMPAD7; 829 KEYCODE_NUMPAD_8: Result := VK_NUMPAD8; 830 KEYCODE_NUMPAD_9: Result := VK_NUMPAD9; 831 KEYCODE_NUMPAD_ADD: Result := VK_ADD; 832 //KEYCODE_NUMPAD_COMMA: Result := $0000009f; 833 KEYCODE_NUMPAD_DIVIDE: Result := VK_DIVIDE; 834 KEYCODE_NUMPAD_DOT: Result := VK_DECIMAL; 835 KEYCODE_NUMPAD_ENTER: Result := VK_RETURN; 836 //KEYCODE_NUMPAD_EQUALS: Result := VK_LCL_EQUAL; 837 //KEYCODE_NUMPAD_LEFT_PAREN: Result := $000000a2; 838 KEYCODE_NUMPAD_MULTIPLY: Result := VK_MULTIPLY; 839 //KEYCODE_NUMPAD_RIGHT_PAREN:Result := $000000a3; 840 KEYCODE_NUMPAD_SUBTRACT: Result := VK_LCL_MINUS; 841 KEYCODE_NUM_LOCK: Result := VK_NUMLOCK; 842 {KEYCODE_PROG_BLUE = $000000ba; 843 KEYCODE_PROG_GREEN = $000000b8; 844 KEYCODE_PROG_RED = $000000b7; 845 KEYCODE_PROG_YELLOW = $000000b9;} 846 KEYCODE_SCROLL_LOCK: Result := VK_SCROLL; 847{ KEYCODE_SETTINGS = $000000b0; 848 KEYCODE_STB_INPUT = $000000b4; 849 KEYCODE_STB_POWER = $000000b3;} 850 KEYCODE_SYSRQ: Result := VK_PRINT; 851{ KEYCODE_TV = $000000aa; 852 KEYCODE_TV_INPUT = $000000b2; 853 KEYCODE_TV_POWER = $000000b1;} 854 KEYCODE_VOLUME_MUTE: Result := VK_VOLUME_MUTE; 855 {KEYCODE_WINDOW = $000000ab; 856 KEYCODE_ZOOM_IN = $000000a8; 857 KEYCODE_ZOOM_OUT = $000000a9; } 858 else 859 Result := 0; 860 end; 861end; 862 863function TCDWidgetSet.DoOpenURLWidgetsetImplementation(AURL: string): Boolean; 864var 865 // Java IDs 866 javaAndroidContentContextClass: JClass; 867 javaAndroidNetUriClass: JClass; 868 javaMethod_Uri_fromParts: jmethodid = nil; 869 // Java Object instances 870 lJavaString, lJavaString2: jstring; 871 lJavaFileObject: JObject; 872 lJavaURIObject: JObject; 873 // array for the parameters 874 lParams: array[0..2] of JValue; 875 // 876 lURLProtocol, lURLAfterDoublePoint: string; 877 lDoublePointPos: SizeInt; 878begin 879 Result := True; 880 881 lDoublePointPos := Pos(':', AURL); 882 lURLProtocol := Copy(AURL, 1, lDoublePointPos-1); 883 lURLAfterDoublePoint := Copy(AURL, lDoublePointPos+1, Length(AURL)); 884 DebugLn(Format('[DoOpenURLWidgetsetImplementation] AURL=%s lURLProtocol=%s lURLAfterDoublePoint=%s', 885 [AURL, lURLProtocol, lURLAfterDoublePoint])); 886 887 // First IDs 888 javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context'); 889 javaAndroidNetUriClass := javaEnvRef^^.FindClass(javaEnvRef,'android/net/Uri'); 890 891 javaMethod_Uri_fromParts := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaAndroidNetUriClass, 'fromParts', '(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri;'); 892 893 // Uri uri = Uri.fromParts("file", "dest", null); 894 lJavaString := javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(lURLProtocol)); 895 lParams[0].l := lJavaString; 896 lJavaString2 := javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(lURLAfterDoublePoint)); 897 lParams[1].l := lJavaString2; 898 lParams[2].l := nil; 899 lJavaURIObject := javaEnvRef^^.CallStaticObjectMethodA(javaEnvRef, javaAndroidNetUriClass, javaMethod_Uri_fromParts, @lParams[0]); 900 901 Result := DoOpenAndroidURI(lJavaURIObject, 'text/html'); 902end; 903 904function TCDWidgetSet.DoOpenDocumentWidgetsetImplementation(APath: string): Boolean; 905var 906 // Java IDs 907 javaAndroidContentContextClass: JClass; 908 javaAndroidNetUriClass: JClass; 909 javaJavaIoFileClass: JClass; 910 javaMethod_Uri_fromFile: jmethodid = nil; 911 javaMethod_File_new: jmethodid = nil; 912 // Java Object instances 913 lJavaString: jstring; 914 lJavaFileObject: JObject; 915 lJavaURIObject: JObject; 916 // array for the parameters 917 lParams: array[0..2] of JValue; 918 // 919begin 920 Result := False; 921 922 if (javaEnvRef = nil) then Exit; 923 924 // First IDs 925 javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context'); 926 javaAndroidNetUriClass := javaEnvRef^^.FindClass(javaEnvRef,'android/net/Uri'); 927 javaJavaIoFileClass := javaEnvRef^^.FindClass(javaEnvRef,'java/io/File'); 928 929 javaMethod_Uri_fromFile := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaAndroidNetUriClass, 'fromFile', '(Ljava/io/File;)Landroid/net/Uri;'); 930 javaMethod_File_new := javaEnvRef^^.GetMethodID(javaEnvRef, javaJavaIoFileClass, '<init>', '(Ljava/lang/String;)V'); 931 932 // File file = new File("/sdcard/test.mp4"); 933 lJavaString := javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(APath)); 934 lParams[0].l := lJavaString; 935 lJavaFileObject := javaEnvRef^^.NewObjectA(javaEnvRef, javaJavaIoFileClass, javaMethod_File_new, @lParams[0]); 936 937 // Uri uri = Uri.fromFile(file); 938 DebugLn(Format('[DoOpenDocumentWidgetsetImplementation] APath=%s lJavaFileObject=%x', [APath, PtrInt(lJavaFileObject)])); 939 lParams[0].l := lJavaFileObject; 940 lJavaURIObject := javaEnvRef^^.CallStaticObjectMethodA(javaEnvRef, javaAndroidNetUriClass, javaMethod_Uri_fromFile, @lParams[0]); 941 942 Result := DoOpenAndroidURI(lJavaURIObject, GetMimeTypeFromFileName(APath)); 943end; 944 945function TCDWidgetSet.DoOpenAndroidURI(AURI: JObject; AMimeType: string): Boolean; 946var 947 // Java IDs 948 javaAndroidContentContextClass: JClass; 949 javaAndroidContentIntentClass: JClass; 950 javaAndroidContentPmPackageManagerClass: JClass; 951 javaAndroidAppActivityClass: JClass; 952 javaJavaUtilListClass: JClass; 953 javaMethod_Intent_new: jmethodid = nil; 954 javaMethod_Intent_setDataAndType: jmethodid = nil; 955 javaMethod_Context_getPackageManager: jmethodid = nil; 956 javaMethod_PmPackageManager_queryIntentActivities: jmethodid = nil; 957 javaMethod_Activity_startActivity: jmethodid = nil; 958 javaMethod_List_size: JMethodID = nil; 959 // Java Object instances 960 lJavaString: jstring; 961 javaViewDocObject: JObject; 962 lJavaPackageManagerObject: JObject; 963 lJavaListObject: JObject; 964 lJavaArray: JArray; 965 lJavaInt: JInt; 966 // array for the parameters 967 lParams: array[0..1] of JValue; 968 // 969begin 970 Result := False; 971 972 if (javaEnvRef = nil) then Exit; 973 974 // First IDs 975 DebugLn(Format(':>[DoOpenAndroidURI] AURI=%x', [PtrInt(AURI)])); 976 javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context'); 977 javaAndroidContentIntentClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Intent'); 978 javaAndroidContentPmPackageManagerClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/pm/PackageManager'); 979 javaAndroidAppActivityClass := javaEnvRef^^.FindClass(javaEnvRef,'android/app/Activity'); 980 javaJavaUtilListClass := javaEnvRef^^.FindClass(javaEnvRef,'java/util/List'); 981 982 javaMethod_Intent_new := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentIntentClass, '<init>', '(Ljava/lang/String;)V'); 983 javaMethod_Intent_setDataAndType := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentIntentClass, 'setDataAndType', '(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;'); 984 javaMethod_Context_getPackageManager := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentContextClass, 'getPackageManager', '()Landroid/content/pm/PackageManager;'); 985 javaMethod_PmPackageManager_queryIntentActivities := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentPmPackageManagerClass, 'queryIntentActivities', '(Landroid/content/Intent;I)Ljava/util/List;'); 986 javaMethod_Activity_startActivity := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidAppActivityClass, 'startActivity', '(Landroid/content/Intent;)V'); 987 javaMethod_List_size := javaEnvRef^^.GetMethodID(javaEnvRef, javaJavaUtilListClass, 'size', '()I'); 988 989 // Intent viewDoc = new Intent(Intent.ACTION_VIEW); 990 lJavaString := javaEnvRef^^.NewStringUTF(javaEnvRef, javaConstant_Intent_ACTION_VIEW); 991 lParams[0].l := lJavaString; 992 javaViewDocObject := javaEnvRef^^.NewObjectA(javaEnvRef, javaAndroidContentIntentClass, javaMethod_Intent_new, @lParams[0]); 993 994 // viewDoc.setDataAndType(uri, "application/pdf"); 995 lParams[0].l := AURI; 996 lJavaString := javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(AMimeType)); 997 lParams[1].l := lJavaString; 998 javaEnvRef^^.CallObjectMethodA(javaEnvRef, javaViewDocObject, javaMethod_Intent_setDataAndType, @lParams[0]); 999 1000 // PackageManager pm = this.getPackageManager(); 1001 lJavaPackageManagerObject := javaEnvRef^^.CallObjectMethod(javaEnvRef, javaActivityObject, javaMethod_Context_getPackageManager); 1002 1003 // List<ResolveInfo> apps = pm.queryIntentActivities(viewDoc, PackageManager.MATCH_DEFAULT_ONLY); 1004 lParams[0].l := javaViewDocObject; 1005 lParams[1].i := javaConstant_PackageManager_MATCH_DEFAULT_ONLY; 1006 lJavaListObject := javaEnvRef^^.CallObjectMethodA(javaEnvRef, lJavaPackageManagerObject, javaMethod_PmPackageManager_queryIntentActivities, @lParams[0]); 1007 1008 // int lSize = apps.size() 1009 lJavaInt := javaEnvRef^^.CallIntMethod(javaEnvRef, lJavaListObject, javaMethod_List_size); 1010 1011 // if (lSize > 0) this.startActivity(viewDoc); 1012 if lJavaInt > 0 then 1013 begin 1014 lParams[0].l := javaViewDocObject; 1015 javaEnvRef^^.CallVoidMethodA(javaEnvRef, javaActivityObject, javaMethod_Activity_startActivity, @lParams[0]); 1016 Result := True; 1017 DebugLn(':<[DoOpenAndroidURI] Success'); 1018 end 1019 else 1020 DebugLn(':<[DoOpenAndroidURI] There are no activities registered for the mimetype ' + AMimeType); 1021end; 1022 1023function TCDWidgetSet.GetMimeTypeFromFileName(AFileName: string): string; 1024var 1025 lExt: String; 1026begin 1027 lExt := SysUtils.ExtractFileExt(AFileName); 1028 // First the most common formats 1029 if AnsiCompareText(lExt, '.png') = 0 then Result := 'image/png' 1030 else if AnsiCompareText(lExt, '.txt') = 0 then Result := 'text/plain' 1031 else if AnsiCompareText(lExt, '.jpg') = 0 then Result := 'image/jpeg' 1032 else if AnsiCompareText(lExt, '.jpeg') = 0 then Result := 'image/jpeg' 1033 else if AnsiCompareText(lExt, '.pdf') = 0 then Result := 'application/pdf' 1034 else if AnsiCompareText(lExt, '.xml') = 0 then Result := 'application/xml' 1035 else if AnsiCompareText(lExt, '.svg') = 0 then Result := 'image/svg+xml' 1036 else if AnsiCompareText(lExt, '.swf') = 0 then Result := 'application/x-shockwave-flash' 1037 else if AnsiCompareText(lExt, '.htm') = 0 then Result := 'text/html' 1038 else if AnsiCompareText(lExt, '.html') = 0 then Result := 'text/html' 1039 // Now all images 1040 else if AnsiCompareText(lExt, '.xpm') = 0 then Result := 'image/x-xpixmap' 1041 else if AnsiCompareText(lExt, '.gif') = 0 then Result := 'image/gif' 1042 else if AnsiCompareText(lExt, '.tiff') = 0 then Result := 'image/tiff' 1043 else if AnsiCompareText(lExt, '.tif') = 0 then Result := 'image/tiff' 1044 else if AnsiCompareText(lExt, '.ico') = 0 then Result := 'image/x-icon' 1045 else if AnsiCompareText(lExt, '.icns') = 0 then Result := 'image/icns' 1046 else if AnsiCompareText(lExt, '.ppm') = 0 then Result := 'image/x-portable-pixmap' 1047 else if AnsiCompareText(lExt, '.bmp') = 0 then Result := 'image/bmp' 1048 // Now all textual formats 1049 else if AnsiCompareText(lExt, '.pas') = 0 then Result := 'text/plain' 1050 else if AnsiCompareText(lExt, '.pp') = 0 then Result := 'text/plain' 1051 else if AnsiCompareText(lExt, '.inc') = 0 then Result := 'text/plain' 1052 else if AnsiCompareText(lExt, '.c') = 0 then Result := 'text/plain' 1053 else if AnsiCompareText(lExt, '.cpp') = 0 then Result := 'text/plain' 1054 else if AnsiCompareText(lExt, '.java') = 0 then Result := 'text/plain' 1055 else if AnsiCompareText(lExt, '.log') = 0 then Result := 'text/plain' 1056 // Now all videos 1057 else if AnsiCompareText(lExt, '.mp4') = 0 then Result := 'video/*' 1058 else if AnsiCompareText(lExt, '.avi') = 0 then Result := 'video/vnd.avi' // also possible video/x-msvideo 1059 else if AnsiCompareText(lExt, '.mpeg') = 0 then Result := 'video/MPEG' 1060 else if AnsiCompareText(lExt, '.mpg') = 0 then Result := 'video/MPEG' 1061 else if AnsiCompareText(lExt, '.mov') = 0 then Result := 'video/quicktime' 1062 // Now all sounds 1063 else if AnsiCompareText(lExt, '.mp3') = 0 then Result := 'audio/mpeg' 1064 else if AnsiCompareText(lExt, '.ogg') = 0 then Result := 'audio/ogg' 1065 else if AnsiCompareText(lExt, '.wav') = 0 then Result := 'audio/x-wav' 1066 else if AnsiCompareText(lExt, '.mid') = 0 then Result := 'audio/midi' 1067 else if AnsiCompareText(lExt, '.midi') = 0 then Result := 'audio/midi' 1068 else if AnsiCompareText(lExt, '.au') = 0 then Result := 'audio/basic' 1069 else if AnsiCompareText(lExt, '.snd') = 0 then Result := 'audio/basic' 1070 // Now all documents 1071 else if AnsiCompareText(lExt, '.rtf') = 0 then Result := 'text/rtf' 1072 else if AnsiCompareText(lExt, '.eps') = 0 then Result := 'application/Postscript' 1073 else if AnsiCompareText(lExt, '.ps') = 0 then Result := 'application/Postscript' 1074 // 1075 else if AnsiCompareText(lExt, '.xls') = 0 then Result := 'application/vnd.ms-excel' 1076 else if AnsiCompareText(lExt, '.doc') = 0 then Result := 'application/msword' 1077 else if AnsiCompareText(lExt, '.ppt') = 0 then Result := 'application/vnd.ms-powerpoint' 1078 // 1079 else if AnsiCompareText(lExt, '.odt') = 0 then Result := 'application/vnd.oasis.opendocument.text' 1080 else if AnsiCompareText(lExt, '.ods') = 0 then Result := 'application/vnd.oasis.opendocument.spreadsheet' 1081 else if AnsiCompareText(lExt, '.odp') = 0 then Result := 'application/vnd.oasis.opendocument.presentation' 1082 else if AnsiCompareText(lExt, '.odg') = 0 then Result := 'application/vnd.oasis.opendocument.graphics' 1083 else if AnsiCompareText(lExt, '.odc') = 0 then Result := 'application/vnd.oasis.opendocument.chart' 1084 else if AnsiCompareText(lExt, '.odf') = 0 then Result := 'application/vnd.oasis.opendocument.formula' 1085 else if AnsiCompareText(lExt, '.odi') = 0 then Result := 'application/vnd.oasis.opendocument.image' 1086 // 1087 else if AnsiCompareText(lExt, '.xlsx') = 0 then Result := 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 1088 else if AnsiCompareText(lExt, '.pptx') = 0 then Result := 'application/vnd.openxmlformats-officedocument.presentationml.presentation' 1089 else if AnsiCompareText(lExt, '.docx') = 0 then Result := 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' 1090 // Now compressed archives 1091 else if AnsiCompareText(lExt, '.zip') = 0 then Result := 'application/zip' 1092 else if AnsiCompareText(lExt, '.tar') = 0 then Result := 'application/x-tar' 1093 // If we can't auto-detect just suppose it is text! 1094 else Result := 'text/plain'; 1095end; 1096 1097procedure TCDWidgetSet.ShowListViewDialog(ATitle: string; ATitles, 1098 ADescriptions: array of string; 1099 AColorOddRow: jint = $ff292C29; AColorEvenRow: jint = $ff424542); 1100var 1101 javaClass_LCLActivity, javaClass_String: jclass; 1102 javaMethod_LCLActivity_LCLDoShowListViewDialog: jmethodid; 1103 javaString: jstring; 1104 lParams: array[0..4] of JValue; 1105 lNativeString: PChar; 1106 i: Integer; 1107begin 1108 // Here we call this routine: 1109 // public void LCLDoShowListViewDialog(String ATitle, String[] AItems, String[] ASubItems) 1110 DebugLn(':>ShowListViewDialog'); 1111 // First call FindClass for all required classes 1112 javaClass_LCLActivity := javaEnvRef^^.FindClass(javaEnvRef, PChar(CDWidgetset.ActivityClassName)); 1113 javaClass_String := javaEnvRef^^.FindClass(javaEnvRef, 'java/lang/String'); 1114 1115 // Now all Method IDs 1116 //DebugLn(':ShowListViewDialog 1'); 1117 javaMethod_LCLActivity_LCLDoShowListViewDialog := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_LCLACtivity, 1118 'LCLDoShowListViewDialog', 1119 '(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;II)V'); 1120 1121 //DebugLn(':ShowListViewDialog 2'); 1122 // Create a new instance for the HTTP request object 1123 // HttpGet javaRequest = new HttpGet(); 1124 lParams[0].l := javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(ATitle)); 1125 lParams[1].l := javaEnvRef^^.NewObjectArray(javaEnvRef, Length(ATitles), javaClass_String, javaEnvRef^^.NewStringUTF(javaEnvRef, '')); 1126 for i := 0 to Length(ATitles)-1 do 1127 javaEnvRef^^.SetObjectArrayElement(javaEnvRef, lParams[1].l, i, javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(ATitles[i]))); 1128 lParams[2].l := javaEnvRef^^.NewObjectArray(javaEnvRef, Length(ADescriptions), javaClass_String, javaEnvRef^^.NewStringUTF(javaEnvRef, '')); 1129 for i := 0 to Length(ADescriptions)-1 do 1130 javaEnvRef^^.SetObjectArrayElement(javaEnvRef, lParams[2].l, i, javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(ADescriptions[i]))); 1131 lParams[3].i := AColorOddRow; 1132 lParams[4].i := AColorEvenRow; 1133 // 1134 javaEnvRef^^.CallVoidMethodA(javaEnvRef, javaActivityObject, 1135 javaMethod_LCLActivity_LCLDoShowListViewDialog, @lParams[0]); 1136 javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[0].l); 1137 javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[1].l); 1138 javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[2].l); 1139 DebugLn(':<ShowListViewDialog END'); 1140end; 1141 1142function TCDWidgetSet.GetAppHandle: THandle; 1143begin 1144 Result := 0; 1145end; 1146 1147{------------------------------------------------------------------------------ 1148 Method: TCDWidgetSet.Create 1149 Params: None 1150 Returns: Nothing 1151 1152 Constructor for the class. 1153 ------------------------------------------------------------------------------} 1154procedure TCDWidgetSet.BackendCreate; 1155begin 1156 // Setup DebugLn 1157 {$IFnDEF WithOldDebugln} 1158 OnWidgetSetDebugLn := @AndroidDebugLn; 1159 OnWidgetSetDbgOut := @AccumulatingDebugOut; 1160 {$ELSE} 1161 DebugLnProc := @AndroidDebugLn; 1162 DebugOutProc := @AccumulatingDebugOut; 1163 {$ENDIF} 1164 1165 {$ifdef CD_UseNativeText} 1166 // Create the dummy screen DC 1167 ScreenBitmapRawImage.Init; 1168 ScreenBitmapHeight := 100; 1169 ScreenBitmapWidth := 100; 1170 ScreenBitmapRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(ScreenBitmapWidth, ScreenBitmapHeight); 1171 ScreenBitmapRawImage.CreateData(True); 1172 ScreenImage := TLazIntfImage.Create(0, 0); 1173 ScreenImage.SetRawImage(ScreenBitmapRawImage); 1174 ScreenDC := TLazCanvas.Create(ScreenImage); 1175 1176 DefaultFontAndroidSize := 16; 1177 {$endif} 1178 1179 // Android support for OpenURL and OpenDocument 1180 LCLIntf.OpenURLWidgetsetImplementation := @DoOpenURLWidgetsetImplementation; 1181 LCLIntf.OpenDocumentWidgetsetImplementation := @DoOpenDocumentWidgetsetImplementation; 1182end; 1183 1184{------------------------------------------------------------------------------ 1185 Method: TWinCEWidgetSet.Destroy 1186 Params: None 1187 Returns: Nothing 1188 1189 destructor for the class. 1190 ------------------------------------------------------------------------------} 1191procedure TCDWidgetSet.BackendDestroy; 1192begin 1193 {$ifdef CD_UseNativeText} 1194 // Free the dummy screen DC 1195 ScreenImage.Free; 1196 ScreenDC.Free; 1197 {$endif} 1198end; 1199 1200{------------------------------------------------------------------------------ 1201 Method: TWinCEWidgetSet.AppInit 1202 Params: None 1203 Returns: Nothing 1204 1205 initialize Windows 1206 ------------------------------------------------------------------------------} 1207procedure TCDWidgetSet.AppInit(var ScreenInfo: TScreenInfo); 1208begin 1209 {$ifdef VerboseCDApplication} 1210 DebugLn('TCDWidgetSet.AppInit'); 1211 {$endif} 1212 1213 Forms.MessageBoxFunction := @CDMessageBoxFunction; 1214 1215 if Application.LayoutAdjustmentPolicy = lapDefault then 1216 Application.LayoutAdjustmentPolicy := lapAutoAdjustWithoutHorizontalScrolling; 1217 1218 // Generic 1219 GenericAppInit(); 1220end; 1221 1222procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop); 1223begin 1224 {$ifdef VerboseCDApplication} 1225 DebugLn('TCDWidgetSet.AppRun'); 1226 {$endif} 1227end; 1228 1229(* 1230function TWinCEWidgetSet.GetAppHandle: THandle; 1231begin 1232 Result:= FAppHandle; 1233end; 1234 1235procedure TWinCEWidgetSet.SetAppHandle(const AValue: THandle); 1236begin 1237 // Do it only if handle is not yet created (for example for DLL initialization) 1238 // if handle is already created we can't reassign it 1239 if AppHandle = 0 then 1240 FAppHandle := AValue; 1241end;*) 1242 1243{------------------------------------------------------------------------------ 1244 Method: TWinCEWidgetSet.AppMinimize 1245 Params: None 1246 Returns: Nothing 1247 1248 Minimizes the whole application to the taskbar 1249 ------------------------------------------------------------------------------} 1250procedure TCDWidgetSet.AppMinimize; 1251begin 1252 // calling Activity.Free doesnt close the app, only hides it, so it is good for AppMinimize 1253 javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_Activity_finish); 1254end; 1255 1256{------------------------------------------------------------------------------ 1257 Method: TWinCEWidgetSet.AppRestore 1258 Params: None 1259 Returns: Nothing 1260 1261 Restore minimized whole application from taskbar 1262 ------------------------------------------------------------------------------} 1263 1264procedure TCDWidgetSet.AppRestore; 1265begin 1266// Windows.SendMessage(FAppHandle, WM_SYSCOMMAND, SC_RESTORE, 0); 1267end; 1268 1269 1270{------------------------------------------------------------------------------ 1271 Method: TWinCEWidgetSet.AppBringToFront 1272 Params: None 1273 Returns: Nothing 1274 1275 Brings the entire application on top of all other non-topmost programs 1276 ------------------------------------------------------------------------------} 1277procedure TCDWidgetSet.AppBringToFront; 1278begin 1279end; 1280 1281(* 1282procedure TWinCEWidgetSet.SetDesigning(AComponent: TComponent); 1283begin 1284 //if Data<>nil then EnableWindow((AComponent As TWinControl).Handle, boolean(Data^)); 1285end; 1286 1287{------------------------------------------------------------------------------ 1288 Method: TWinCEWidgetSet.SetCallback 1289 Params: Msg - message for which to set a callback 1290 Sender - object to which callback will be sent 1291 Returns: nothing 1292 1293 Applies a Message to the sender 1294 ------------------------------------------------------------------------------} 1295procedure TWinCEWidgetSet.SetCallback(Msg: LongInt; Sender: TObject); 1296var 1297 Window: HWnd; 1298begin 1299 //DebugLn('Trace:TWinCEWidgetSet.SetCallback - Start'); 1300 //DebugLn(Format('Trace:TWinCEWidgetSet.SetCallback - Class Name --> %S', [Sender.ClassName])); 1301 //DebugLn(Format('Trace:TWinCEWidgetSet.SetCallback - Message Name --> %S', [GetMessageName(Msg)])); 1302 if Sender Is TControlCanvas then 1303 Window := TControlCanvas(Sender).Handle 1304 else if Sender Is TCustomForm then 1305 Window := TCustomForm(Sender).Handle 1306 else 1307 Window := TWinControl(Sender).Handle; 1308 if Window=0 then exit; 1309 1310 //DebugLn('Trace:TWinCEWidgetSet.SetCallback - Exit'); 1311end; 1312 1313{------------------------------------------------------------------------------ 1314 Method: TWinCEWidgetSet.RemoveCallbacks 1315 Params: Sender - object from which to remove callbacks 1316 Returns: nothing 1317 1318 Removes Call Back Signals from the sender 1319 ------------------------------------------------------------------------------} 1320procedure TWinCEWidgetSet.RemoveCallbacks(Sender: TObject); 1321var 1322 Window: HWnd; 1323begin 1324 if Sender Is TControlCanvas then 1325 Window := TControlCanvas(Sender).Handle 1326 else if Sender Is TCustomForm then 1327 Window := TCustomForm(Sender).Handle 1328 else 1329 Window := (Sender as TWinControl).Handle; 1330 if Window=0 then exit; 1331end;*) 1332 1333{------------------------------------------------------------------------------ 1334 Method: TWinCEWidgetSet.AppProcessMessages 1335 Params: None 1336 Returns: Nothing 1337 1338 Handle all pending messages 1339 ------------------------------------------------------------------------------} 1340procedure TCDWidgetSet.AppProcessMessages; 1341begin 1342end; 1343(* 1344procedure TWinCEWidgetSet.CheckPipeEvents; 1345var 1346 lHandler: PPipeEventInfo; 1347// lBytesAvail: dword; 1348// SomethingChanged: Boolean; 1349 ChangedCount:integer; 1350begin 1351 lHandler := FWaitPipeHandlers; 1352 ChangedCount := 0; 1353 while (lHandler <> nil) and (ChangedCount < 10) do 1354 begin 1355 { 1356 roozbeh : ooops not supported 1357 SomethingChanged:=true; 1358 if Windows.PeekNamedPipe(lHandler^.Handle, nil, 0, nil, @lBytesAvail, nil) then 1359 begin 1360 if lBytesAvail <> 0 then 1361 lHandler^.OnEvent(lHandler^.UserData, [prDataAvailable]) 1362 else 1363 SomethingChanged := false; 1364 end else 1365 lHandler^.OnEvent(lHandler^.UserData, [prBroken]); 1366 if SomethingChanged then 1367 lHandler := FWaitPipeHandlers 1368 else begin 1369 lHandler := lHandler^.Next; 1370 ChangedCount := 0; 1371 end; 1372 inc(ChangedCount);} 1373 end; 1374end;*) 1375 1376{------------------------------------------------------------------------------ 1377 Method: TWinCEWidgetSet.AppWaitMessage 1378 Params: None 1379 Returns: Nothing 1380 1381 Passes execution control to Windows 1382 ------------------------------------------------------------------------------} 1383//roozbeh:new update...whole procedure body is added.what is it? 1384procedure TCDWidgetSet.AppWaitMessage; 1385begin 1386end; 1387 1388{------------------------------------------------------------------------------ 1389 Method: TCDWidgetSet.AppTerminate 1390 Params: None 1391 Returns: Nothing 1392 1393 Terminates the application 1394 ------------------------------------------------------------------------------} 1395procedure TCDWidgetSet.AppTerminate; 1396var 1397 lParams: array[0..0] of JValue; 1398begin 1399 DebugLn('[TCDWidgetSet.AppTerminate] Start'); 1400 1401 // Call the method 1402 lParams[0].i := 0; 1403 javaEnvRef^^.CallStaticVoidMethodA(javaEnvRef, javaJavaLangSystemClass, javaMethod_System_exit, @lParams[0]); 1404 1405 DebugLn('[TCDWidgetSet.AppTerminate] End'); 1406end; 1407 1408procedure TCDWidgetSet.AppSetIcon(const Small, Big: HICON); 1409begin 1410end; 1411 1412procedure TCDWidgetSet.AppSetTitle(const ATitle: string); 1413begin 1414end; 1415 1416procedure TCDWidgetSet.AppSetVisible(const AVisible: Boolean); 1417begin 1418end; 1419 1420function TCDWidgetSet.AppRemoveStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; 1421begin 1422end; 1423 1424function TCDWidgetSet.AppRestoreStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; 1425begin 1426end; 1427 1428procedure TCDWidgetSet.AppSetMainFormOnTaskBar(const DoSet: Boolean); 1429begin 1430end; 1431 1432{------------------------------------------------------------------------------ 1433 function: CreateTimer 1434 Params: Interval: 1435 TimerFunc: Callback 1436 Returns: a Timer id (use this ID to destroy timer) 1437 1438 Design: A timer which calls TimerCallBackProc, is created. 1439 The TimerCallBackProc calls the TimerFunc. 1440 ------------------------------------------------------------------------------} 1441function TCDWidgetSet.CreateTimer(Interval: integer; TimerFunc: TWSTimerProc) : THandle; 1442var 1443 lTimer: TCDTimer; 1444 lTimerObject, lGlobalTimerObject: JObject; 1445begin 1446 lTimer := TCDTimer.Create; 1447 1448 Result := THandle(lTimer); 1449 1450 lTimer.Interval := Interval; 1451 lTimer.TimerFunc := TimerFunc; 1452 1453 // Prepare the input 1454 javaEnvRef^^.SetIntField(javaEnvRef, javaActivityObject, javaField_lcltimerinterval, Interval); 1455 1456 // Call the method 1457 javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_LCLDoCreateTimer); 1458 1459 // Read the output 1460 lTimerObject := javaEnvRef^^.GetObjectField(javaEnvRef, javaActivityObject, javaField_lcltimerid); 1461 lGlobalTimerObject := javaEnvRef^^.NewGlobalRef(javaEnvRef, lTimerObject); 1462 lTimer.NativeHandle := PtrInt(lTimerObject); 1463 lTimer.NativeGlobalReference := PtrInt(lGlobalTimerObject); 1464 1465 // Add it to our list 1466 AddTimer(lTimer); 1467 DebugLn(Format('[TCDWidgetSet.CreateTimer] Result=%x', [PtrInt(Result)])); 1468end; 1469 1470{------------------------------------------------------------------------------ 1471 function: DestroyTimer 1472 Params: TimerHandle 1473 Returns: 1474 ------------------------------------------------------------------------------} 1475function TCDWidgetSet.DestroyTimer(TimerHandle: THandle) : boolean; 1476var 1477 lTimer: TCDTimer; 1478begin 1479 lTimer := TCDTimer(TimerHandle); 1480 1481 DebugLn(Format('[TCDWidgetSet.DestroyTimer] TimerHandle=%x lTimer.NativeHandle=%x lTimer.NativeGlobalReference=%x', 1482 [PtrInt(TimerHandle), PtrInt(lTimer.NativeHandle), PtrInt(lTimer.NativeGlobalReference)])); 1483 Result := False; 1484 1485 if lTimer = nil then Exit; 1486 1487 // Prepare the input 1488 javaEnvRef^^.SetObjectField(javaEnvRef, javaActivityObject, javaField_lcltimerid, jobject(lTimer.NativeGlobalReference)); 1489 1490 // Call the method 1491 javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_LCLDoDestroyTimer); 1492 javaEnvRef^^.DeleteGlobalRef(javaEnvRef, JObject(lTimer.NativeGlobalReference)); 1493 1494 // Remove from the list 1495 RemoveTimer(lTimer); 1496 lTimer.Free; 1497 1498 Result := True; 1499end; 1500(* 1501procedure TWinCEWidgetSet.HandleWakeMainThread(Sender: TObject); 1502begin 1503 // wake up GUI thread by sending a message to it 1504 Windows.PostMessage(AppHandle, WM_NULL, 0, 0); 1505end; 1506*) 1507 1508