1 /* 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * A sample Assistive Technology which queries the JavaVM (if any) underneath 28 * the mouse pointer to get the Java Accessibility information available 29 * for the Java UI object underneath the mouse, using the Java 30 * Accessibility Bridge, AccessBridge.DLL 31 */ 32 33 /* 34 TO DO 35 36 - update copyright 37 - add logging to JavaFerret docs 38 - add /NO_LOGGING flag to JavaFerret docs 39 40 */ 41 42 #include <windows.h> // includes basic windows functionality 43 #include <jni.h> 44 45 #include "ferretResource.h" 46 #include "AccessBridgeCalls.h" 47 #include "AccessBridgeCallbacks.h" 48 49 #include <stdio.h> 50 #include <time.h> 51 #include <string.h> 52 53 #include "JavaFerret.h" 54 #include "AccessInfo.h" 55 56 #define TIMER_ID 1 57 #define DISPLAY_INFO_MESSAGE WM_USER+1 58 #define DISPLAY_HWND_INFO_MESSAGE WM_USER+2 59 60 HWND theDialogWindow; 61 HINSTANCE theInstance; 62 BOOL theAccessBridgeLoadedFlag; 63 64 HHOOK prevKbdHook; 65 HHOOK prevMouseHook; 66 67 BOOL updateMouse; 68 BOOL updateF1; 69 BOOL updateF2; 70 71 BOOL trackMouse; 72 BOOL trackFocus; 73 BOOL trackCaret; 74 BOOL trackShutdown; 75 76 BOOL trackMenuSelected; 77 BOOL trackMenuDeselected; 78 BOOL trackMenuCanceled; 79 80 BOOL trackPopupVisible; 81 BOOL trackPopupInvisible; 82 BOOL trackPopupCanceled; 83 84 //BOOL trackPropertyChange; 85 86 BOOL trackPropertyNameChange; 87 BOOL trackPropertyDescriptionChange; 88 BOOL trackPropertyStateChange; 89 BOOL trackPropertyValueChange; 90 BOOL trackPropertySelectionChange; 91 BOOL trackPropertyTextChange; 92 BOOL trackPropertyCaretChange; 93 BOOL trackPropertyVisibleDataChange; 94 BOOL trackPropertyChildChange; 95 BOOL trackPropertyActiveDescendentChange; 96 BOOL trackPropertyTableModelChange; 97 98 99 FILE *logfile = NULL; 100 101 /** 102 * WinMain 103 * 104 */ 105 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd) { 106 MSG msg; 107 108 theInstance = hInst; 109 110 updateF1 = FALSE; 111 updateF2 = FALSE; 112 updateMouse = FALSE; 113 114 trackMouse = FALSE; 115 trackShutdown = FALSE; 116 trackFocus = FALSE; 117 trackCaret = FALSE; 118 trackMenuSelected = FALSE; 119 trackMenuDeselected = FALSE; 120 trackMenuCanceled = FALSE; 121 trackPopupVisible = FALSE; 122 trackPopupInvisible = FALSE; 123 trackPopupCanceled = FALSE; 124 125 trackPropertyNameChange = FALSE; 126 trackPropertyDescriptionChange = FALSE; 127 trackPropertyStateChange = FALSE; 128 trackPropertyValueChange = FALSE; 129 trackPropertySelectionChange = FALSE; 130 trackPropertyTextChange = FALSE; 131 trackPropertyCaretChange = FALSE; 132 trackPropertyVisibleDataChange = FALSE; 133 trackPropertyChildChange = FALSE; 134 trackPropertyActiveDescendentChange = FALSE; 135 trackPropertyTableModelChange = FALSE; 136 137 138 theAccessBridgeLoadedFlag = FALSE; 139 140 141 if (InitWindow(hInst)) { 142 if (initializeAccessBridge() == TRUE) { 143 theAccessBridgeLoadedFlag = TRUE; 144 while (GetMessage(&msg, NULL, 0, 0)) { 145 TranslateMessage(&msg); 146 DispatchMessage(&msg); 147 } 148 if (theAccessBridgeLoadedFlag == TRUE) { 149 shutdownAccessBridge(); 150 } 151 } 152 } 153 return(0); 154 } 155 156 char szAppName [] = "FERRETWINDOW"; 157 158 /** 159 * Real(tm) MS-Windows window initialization 160 * 161 */ 162 BOOL InitWindow (HANDLE hInstance) { 163 theDialogWindow = CreateDialog ((struct HINSTANCE__ *)hInstance, 164 szAppName, 165 NULL, 166 (DLGPROC)FerretDialogProc); 167 168 // If window could not be created, return "failure". 169 if (!theDialogWindow) 170 return (FALSE); 171 172 if (logfile == null) { 173 logfile = fopen(JAVA_FERRET_LOG, "w"); // overwrite existing log file 174 logString(logfile, "Starting JavaFerret.exe %s\n", getTimeAndDate()); 175 } 176 177 // Make the window visible, update its client area, & return "success". 178 SetWindowText (theDialogWindow, "Java Ferret"); 179 ShowWindow (theDialogWindow, SW_SHOWNORMAL); 180 UpdateWindow (theDialogWindow); 181 182 return (TRUE); 183 } 184 185 /** 186 * Display Accessible information about the object under the mouse 187 */ 188 void displayAccessibleInfo(long vmID, AccessibleContext ac, int x, int y) { 189 char buffer[HUGE_BUFSIZE]; 190 191 getAccessibleInfo(vmID, ac, x, y, buffer, (int)(sizeof(buffer))); 192 displayAndLog(theDialogWindow, cFerretText, logfile, (char *)buffer); 193 } 194 195 /** 196 * Display Java event info 197 */ 198 void displayJavaEvent(long vmID, AccessibleContext ac, char *announcement) { 199 char buffer[HUGE_BUFSIZE]; 200 char *bufOffset; 201 202 strncpy(buffer, announcement, sizeof(buffer)); 203 204 bufOffset = (char *) (buffer + strlen(buffer)); 205 getAccessibleInfo(vmID, ac, -1, -1, bufOffset, (int)(sizeof(buffer) - strlen(buffer))); 206 displayAndLog(theDialogWindow, cFerretText, logfile, (char *)buffer); 207 } 208 209 210 /** 211 * Display Accessible propertyChange event info 212 */ 213 void displayAccessiblePropertyChange(long vmID, AccessibleContext ac, 214 char *announcement) { 215 char buffer[HUGE_BUFSIZE]; 216 char *bufOffset; 217 218 strncpy(buffer, announcement, sizeof(buffer)); 219 220 bufOffset = (char *) (buffer + strlen(buffer)); 221 getAccessibleInfo(vmID, ac, -1, -1, bufOffset, (int)(sizeof(buffer) - strlen(buffer))); 222 displayAndLog(theDialogWindow, cFerretText, logfile, (char *)buffer); 223 } 224 225 226 /** 227 * Update display under mouse when it moves 228 */ 229 void echoMouseObject() { 230 long vmID; 231 AccessibleContext acParent; 232 AccessibleContext ac; 233 POINT p; 234 HWND hwnd; 235 RECT windowRect; 236 237 GetCursorPos(&p); 238 hwnd = WindowFromPoint(p); 239 if (GetAccessibleContextFromHWND(hwnd, &vmID, &acParent)) { 240 GetWindowRect(hwnd, &windowRect); 241 // send the point in global coordinates; Java will handle it! 242 if (GetAccessibleContextAt(vmID, acParent, (jint) p.x, (jint) p.y, &ac)) { 243 displayAccessibleInfo(vmID, ac, p.x, p.y); // can handle null 244 ReleaseJavaObject(vmID, ac); 245 } 246 } 247 } 248 249 250 /** 251 * Update display under HWND the mouse is in 252 */ 253 void echoMouseHWNDObject() { 254 long vmID; 255 AccessibleContext ac; 256 POINT p; 257 HWND hwnd; 258 259 GetCursorPos(&p); 260 hwnd = WindowFromPoint(p); 261 262 if (GetAccessibleContextFromHWND(hwnd, &vmID, &ac)) { 263 displayAccessibleInfo(vmID, ac, 0, 0); // can handle null 264 ReleaseJavaObject(vmID, ac); 265 } 266 } 267 268 /** 269 * Display Accessible information about the object that has focus in 270 * the topmost Java HWND 271 * 272 */ 273 void displayFocusedObject() { 274 HWND hWnd; 275 long vmID; 276 AccessibleContext ac; 277 278 hWnd = GetTopWindow(NULL); 279 while (hWnd != NULL) { 280 if (IsJavaWindow(hWnd)) { 281 if (GetAccessibleContextWithFocus(hWnd, &vmID, &ac) == TRUE) { 282 displayAccessibleInfo(vmID, ac, 0, 0); 283 ReleaseJavaObject(vmID, ac); 284 } 285 return; 286 } else { 287 hWnd = GetNextWindow(hWnd, GW_HWNDNEXT); 288 } 289 } 290 } 291 292 /* 293 * Handle notification of the Java application shutting down 294 */ 295 void HandleJavaShutdown(long vmID) { 296 char s[1024]; 297 wsprintf(s, "Java VM 0x%X terminated\r\n\r\n", vmID); 298 299 displayJavaEvent(vmID, null, s); // intentially passing null AccessibleContext 300 displayAndLog(theDialogWindow, cFerretText, logfile, (char *)s); 301 } 302 303 /** 304 * Handle a FocusGained event 305 */ 306 void HandleJavaFocusGained(long vmID, FocusEvent event, AccessibleContext ac) { 307 308 char s[1024]; 309 wsprintf(s, "FocusGained\r\n\r\n"); 310 311 if (ac != (AccessibleContext) 0) { 312 displayJavaEvent(vmID, ac, s); 313 } 314 315 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 316 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 317 } 318 319 /** 320 * Handle a FocusLost event 321 */ 322 void HandleJavaFocusLost(long vmID, FocusEvent event, AccessibleContext ac) { 323 324 // NOTE: calling GetAccessibleContextWithFocus() after a FocusLost event 325 // would result in a null AccessibleContext being returned, since 326 // at that point, no object has the focus. If the topmost window 327 // does not belong to a JavaVM, then no component within a JavaVM 328 // will have the focus (and again, GetAccessibleContextWithFocus() 329 // will return a null AccessibleContext). You should always get 330 // a FocusLost event when a window not belonging to a JavaVM becomes 331 // topmost. 332 333 char s[1024]; 334 wsprintf(s, "FocusLost\r\n\r\n"); 335 336 if (ac != (AccessibleContext) 0) { 337 displayJavaEvent(vmID, ac, s); 338 } 339 /* 340 if (ac != (AccessibleContext) 0) { 341 displayAccessibleInfo(vmID, ac, 0, 0); 342 } 343 */ 344 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 345 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 346 } 347 348 /** 349 * Handle a CaretUpdate event 350 */ 351 void HandleJavaCaretUpdate(long vmID, CaretEvent event, AccessibleContext ac) { 352 if (ac != (AccessibleContext) 0) { 353 displayAccessibleInfo(vmID, ac, 0, 0); 354 } 355 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 356 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 357 } 358 359 /** 360 * Handle a MouseClicked event 361 */ 362 void HandleMouseClicked(long vmID, MouseEvent event, AccessibleContext ac) { 363 if (ac != (AccessibleContext) 0) { 364 displayAccessibleInfo(vmID, ac, 0, 0); 365 } 366 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 367 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 368 } 369 370 /** 371 * Handle a MouseEntered event 372 */ 373 void HandleMouseEntered(long vmID, MouseEvent event, AccessibleContext ac) { 374 if (ac != (AccessibleContext) 0) { 375 displayAccessibleInfo(vmID, ac, 0, 0); 376 } 377 378 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 379 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 380 } 381 382 /** 383 * Handle a MouseExited event 384 */ 385 void HandleMouseExited(long vmID, MouseEvent event, AccessibleContext ac) { 386 if (ac != (AccessibleContext) 0) { 387 displayAccessibleInfo(vmID, ac, 0, 0); 388 } 389 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 390 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 391 } 392 393 /** 394 * Handle a MousePressed event 395 */ 396 void HandleMousePressed(long vmID, MouseEvent event, AccessibleContext ac) { 397 if (ac != (AccessibleContext) 0) { 398 displayAccessibleInfo(vmID, ac, 0, 0); 399 } 400 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 401 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 402 } 403 404 /** 405 * Handle a MouseReleased event 406 */ 407 void HandleMouseReleased(long vmID, MouseEvent event, AccessibleContext ac) { 408 if (ac != (AccessibleContext) 0) { 409 displayAccessibleInfo(vmID, ac, 0, 0); 410 } 411 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 412 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 413 } 414 415 /** 416 * Handle a MenuCanceled event 417 */ 418 void HandleMenuCanceled(long vmID, MenuEvent event, AccessibleContext ac) { 419 if (ac != (AccessibleContext) 0) { 420 displayAccessibleInfo(vmID, ac, 0, 0); 421 } 422 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 423 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 424 } 425 426 /** 427 * Handle a MenuDeselected event 428 */ 429 void HandleMenuDeselected(long vmID, MenuEvent event, AccessibleContext ac) { 430 if (ac != (AccessibleContext) 0) { 431 displayAccessibleInfo(vmID, ac, 0, 0); 432 } 433 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 434 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 435 } 436 437 /** 438 * Handle a MenuSelected event 439 */ 440 void HandleMenuSelected(long vmID, MenuEvent event, AccessibleContext ac) { 441 if (ac != (AccessibleContext) 0) { 442 displayAccessibleInfo(vmID, ac, 0, 0); 443 } 444 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 445 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 446 } 447 448 /** 449 * Handle a PopupMenuCanceled event 450 */ 451 void HandlePopupMenuCanceled(long vmID, MenuEvent event, AccessibleContext ac) { 452 if (ac != (AccessibleContext) 0) { 453 displayAccessibleInfo(vmID, ac, 0, 0); 454 } 455 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 456 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 457 } 458 459 /** 460 * Handle a PopupMenuWillBecomeInvisible event 461 */ 462 void HandlePopupMenuWillBecomeInvisible(long vmID, MenuEvent event, AccessibleContext ac) { 463 if (ac != (AccessibleContext) 0) { 464 displayAccessibleInfo(vmID, ac, 0, 0); 465 } 466 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 467 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 468 } 469 470 /** 471 * Handle a PopupMenuWillBecomeVisible event 472 */ 473 void HandlePopupMenuWillBecomeVisible(long vmID, MenuEvent event, AccessibleContext ac) { 474 if (ac != (AccessibleContext) 0) { 475 displayAccessibleInfo(vmID, ac, 0, 0); 476 } 477 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 478 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 479 } 480 481 482 483 484 /** 485 * Handle a HandlePropertyNameChange event 486 */ 487 void HandlePropertyNameChange(long vmID, PropertyChangeEvent event, AccessibleContext ac, 488 wchar_t *oldName, wchar_t *newName) { 489 char s[1024]; 490 wsprintf(s, "Name changed event: old = %ls; new = %ls\r\n\r\n", oldName, newName); 491 492 if (ac != (AccessibleContext) 0) { 493 displayAccessiblePropertyChange(vmID, ac, s); 494 } 495 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 496 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 497 } 498 499 /** 500 * Handle a HandlePropertyDescriptionChange event 501 */ 502 void HandlePropertyDescriptionChange(long vmID, PropertyChangeEvent event, AccessibleContext ac, 503 wchar_t *oldDescription, wchar_t *newDescription) { 504 char s[1024]; 505 wsprintf(s, "Description changed event: old = %ls; new = %ls\r\n\r\n", oldDescription, newDescription); 506 507 if (ac != (AccessibleContext) 0) { 508 displayAccessiblePropertyChange(vmID, ac, s); 509 } 510 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 511 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 512 } 513 514 /** 515 * Handle a HandlePropertyStateChange event 516 */ 517 void HandlePropertyStateChange(long vmID, PropertyChangeEvent event, AccessibleContext ac, 518 wchar_t *oldState, wchar_t *newState) { 519 char s[1024]; 520 wsprintf(s, "State changed event: old = %ls; new = %ls\r\n\r\n", oldState, newState); 521 522 if (ac != (AccessibleContext) 0) { 523 displayAccessiblePropertyChange(vmID, ac, s); 524 } 525 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 526 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 527 } 528 529 /** 530 * Handle a HandlePropertyValueChange event 531 */ 532 void HandlePropertyValueChange(long vmID, PropertyChangeEvent event, AccessibleContext ac, 533 wchar_t *oldValue, wchar_t *newValue) { 534 char s[1024]; 535 wsprintf(s, "Value changed event: old = %ls; new = %ls\r\n\r\n", oldValue, newValue); 536 537 if (ac != (AccessibleContext) 0) { 538 displayAccessiblePropertyChange(vmID, ac, s); 539 } 540 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 541 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 542 } 543 544 /** 545 * Handle a HandlePropertySelectionChange event 546 */ 547 void HandlePropertySelectionChange(long vmID, PropertyChangeEvent event, AccessibleContext ac) { 548 if (ac != (AccessibleContext) 0) { 549 displayAccessiblePropertyChange(vmID, ac, "Selection changed event\r\n\r\n"); 550 } 551 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 552 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 553 } 554 555 /** 556 * Handle a HandlePropertyTextChange event 557 */ 558 void HandlePropertyTextChange(long vmID, PropertyChangeEvent event, AccessibleContext ac) { 559 if (ac != (AccessibleContext) 0) { 560 displayAccessiblePropertyChange(vmID, ac, "Text changed event\r\n\r\n"); 561 } 562 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 563 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 564 } 565 566 /** 567 * Handle a HandlePropertyCaretChange event 568 */ 569 void HandlePropertyCaretChange(long vmID, PropertyChangeEvent event, AccessibleContext ac, 570 int oldPosition, int newPosition) { 571 char s[1024]; 572 573 wsprintf(s, "Caret changed event: oldPosition = %d; newPosition = %d\r\n\r\n", oldPosition, newPosition); 574 575 if (ac != (AccessibleContext) 0) { 576 displayAccessiblePropertyChange(vmID, ac, s); 577 } 578 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 579 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 580 } 581 582 /** 583 * Handle a HandlePropertyVisibleDataChange event 584 */ 585 void HandlePropertyVisibleDataChange(long vmID, PropertyChangeEvent event, AccessibleContext ac) { 586 if (ac != (AccessibleContext) 0) { 587 displayAccessiblePropertyChange(vmID, ac, "VisibleData changed event\r\n\r\n"); 588 } 589 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 590 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 591 } 592 593 /** 594 * Handle a HandlePropertyChildChange event 595 */ 596 void HandlePropertyChildChange(long vmID, PropertyChangeEvent event, AccessibleContext ac, 597 JOBJECT64 oldChild, JOBJECT64 newChild) { 598 char buffer[HUGE_BUFSIZE]; 599 char *bufOffset; 600 601 sprintf(buffer, "Child property changed event:\r\n=======================\r\n\r\n"); 602 603 if (oldChild != 0) { 604 strncat(buffer, "Old Accessible Child info:\r\n\r\n", sizeof(buffer)); 605 bufOffset = (char *) (buffer + strlen(buffer)); 606 getAccessibleInfo(vmID, oldChild, 0, 0, bufOffset, (int)(sizeof(buffer) - strlen(buffer))); 607 strncat(buffer, "\r\n\r\n", sizeof(buffer)); 608 } 609 610 if (newChild != 0) { 611 strncat(buffer, "New Accessible Child info:\r\n\r\n", sizeof(buffer)); 612 bufOffset = (char *) (buffer + strlen(buffer)); 613 getAccessibleInfo(vmID, newChild, 0, 0, bufOffset, (int)(sizeof(buffer) - strlen(buffer))); 614 strncat(buffer, "\r\n\r\n", sizeof(buffer)); 615 } 616 617 if (ac != (AccessibleContext) 0) { 618 displayAccessiblePropertyChange(vmID, ac, buffer); 619 } 620 621 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 622 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 623 ReleaseJavaObject(vmID, oldChild); // must always release, to stave off memory leaks 624 ReleaseJavaObject(vmID, newChild); // must always release, to stave off memory leaks 625 } 626 627 /** 628 * Handle a HandlePropertyActiveDescendentChange event 629 */ 630 void HandlePropertyActiveDescendentChange(long vmID, PropertyChangeEvent event, 631 AccessibleContext ac, 632 JOBJECT64 oldActiveDescendent, 633 JOBJECT64 newActiveDescendent) { 634 char buffer[HUGE_BUFSIZE]; 635 636 sprintf(buffer, "ActiveDescendent property changed event:\r\n=======================\r\n\r\n"); 637 638 #ifdef _notdef 639 char *bufOffset; 640 if (oldActiveDescendent != 0) { 641 strncat(buffer, "Old Accessible ActiveDescendent info:\r\n\r\n", sizeof(buffer)); 642 bufOffset = (char *) (buffer + strlen(buffer)); 643 getAccessibleInfo(vmID, oldActiveDescendent, 0, 0, bufOffset, (int)(sizeof(buffer) - strlen(buffer))); 644 strncat(buffer, "\r\n\r\n", sizeof(buffer)); 645 } 646 647 if (newActiveDescendent != 0) { 648 strncat(buffer, "New Accessible ActiveDescendent info:\r\n\r\n", sizeof(buffer)); 649 bufOffset = (char *) (buffer + strlen(buffer)); 650 getAccessibleInfo(vmID, newActiveDescendent, 0, 0, bufOffset, (int)(sizeof(buffer) - strlen(buffer))); 651 strncat(buffer, "\r\n\r\n", sizeof(buffer)); 652 } 653 #endif _notdef 654 655 656 if (newActiveDescendent != (AccessibleContext) 0) { 657 displayAccessiblePropertyChange(vmID, newActiveDescendent, buffer); 658 } 659 660 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 661 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 662 ReleaseJavaObject(vmID, oldActiveDescendent); // must always release, to stave off memory leaks 663 ReleaseJavaObject(vmID, newActiveDescendent); // must always release, to stave off memory leaks 664 } 665 666 667 /** 668 * Handle a HandlePropertyTableModelChange event 669 */ 670 void HandlePropertyTableModelChange(long vmID, PropertyChangeEvent event, 671 AccessibleContext ac, 672 wchar_t *oldValue, wchar_t *newValue) { 673 674 char s[1024]; 675 wsprintf(s, "Table Model Change: old = %ls; new = %ls\r\n\r\n", oldValue, newValue); 676 677 if (ac != (AccessibleContext) 0) { 678 displayAccessiblePropertyChange(vmID, ac, s); 679 } 680 ReleaseJavaObject(vmID, ac); // must always release, to stave off memory leaks 681 ReleaseJavaObject(vmID, event); // must always release, to stave off memory leaks 682 } 683 684 685 686 #define DOWN_UP_FLAG 1<<31 687 688 void CALLBACK TimerProc(HWND hWnd, UINT uTimerMsg, UINT uTimerID, DWORD dwTime) { 689 // when mouse settles from movement 690 KillTimer(hWnd, uTimerID); 691 if (updateMouse == TRUE) { 692 PostMessage(theDialogWindow, DISPLAY_INFO_MESSAGE, 0, 0); 693 } 694 } 695 696 LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) { 697 // on mouse-up of F1 698 if (code < 0) { 699 CallNextHookEx(prevKbdHook, code, wParam, lParam); 700 } else if (wParam == VK_F1 && lParam & DOWN_UP_FLAG) { 701 PostMessage(theDialogWindow, DISPLAY_INFO_MESSAGE, wParam, lParam); 702 } else if (wParam == VK_F2 && lParam & DOWN_UP_FLAG) { 703 PostMessage(theDialogWindow, DISPLAY_HWND_INFO_MESSAGE, wParam, lParam); 704 } 705 return 0; 706 } 707 708 LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) { 709 // when mouse settles from movement 710 if (code < 0) { 711 CallNextHookEx(prevMouseHook, code, wParam, lParam); 712 } else { 713 // reset the timer every time the mouse moves 714 KillTimer(theDialogWindow, TIMER_ID); 715 SetTimer(theDialogWindow, TIMER_ID, 1000, (TIMERPROC)TimerProc); 716 } 717 return 0; 718 } 719 720 void exitJavaFerret(HWND hWnd) { 721 EndDialog(hWnd, TRUE); 722 PostQuitMessage (0); 723 } 724 725 #define INSTALL_EVENT_LISTENER(toggleVal, setFP, handler) \ 726 if (toggleVal) { \ 727 setFP(handler); \ 728 } 729 730 void reinstallEventListeners() { 731 INSTALL_EVENT_LISTENER(trackMouse, SetMouseEntered, HandleMouseEntered); 732 INSTALL_EVENT_LISTENER(trackShutdown, SetJavaShutdown, HandleJavaShutdown); 733 INSTALL_EVENT_LISTENER(trackFocus, SetFocusGained, HandleJavaFocusGained); 734 INSTALL_EVENT_LISTENER(trackFocus, SetFocusGained, HandleJavaFocusGained); 735 INSTALL_EVENT_LISTENER(trackCaret, SetCaretUpdate, HandleJavaCaretUpdate); 736 737 INSTALL_EVENT_LISTENER(trackMenuSelected, SetMenuSelected, HandleMenuSelected); 738 INSTALL_EVENT_LISTENER(trackMenuDeselected, SetMenuDeselected, HandleMenuDeselected); 739 INSTALL_EVENT_LISTENER(trackMenuCanceled, SetMenuCanceled, HandleMenuCanceled); 740 741 INSTALL_EVENT_LISTENER(trackPopupVisible, SetPopupMenuWillBecomeVisible, HandlePopupMenuWillBecomeVisible); 742 INSTALL_EVENT_LISTENER(trackPopupInvisible, SetPopupMenuWillBecomeInvisible, HandlePopupMenuWillBecomeInvisible); 743 INSTALL_EVENT_LISTENER(trackPopupCanceled, SetPopupMenuCanceled, HandlePopupMenuCanceled); 744 745 INSTALL_EVENT_LISTENER(trackPropertyNameChange, SetPropertyNameChange, HandlePropertyNameChange); 746 INSTALL_EVENT_LISTENER(trackPropertyDescriptionChange, SetPropertyDescriptionChange, HandlePropertyDescriptionChange); 747 INSTALL_EVENT_LISTENER(trackPropertyStateChange, SetPropertyStateChange, HandlePropertyStateChange); 748 INSTALL_EVENT_LISTENER(trackPropertyValueChange, SetPropertyValueChange, HandlePropertyValueChange); 749 INSTALL_EVENT_LISTENER(trackPropertySelectionChange, SetPropertySelectionChange, HandlePropertySelectionChange); 750 INSTALL_EVENT_LISTENER(trackPropertyTextChange, SetPropertyTextChange, HandlePropertyTextChange); 751 INSTALL_EVENT_LISTENER(trackPropertyCaretChange, SetPropertyCaretChange, HandlePropertyCaretChange); 752 INSTALL_EVENT_LISTENER(trackPropertyVisibleDataChange, SetPropertyVisibleDataChange, HandlePropertyVisibleDataChange); 753 INSTALL_EVENT_LISTENER(trackPropertyChildChange, SetPropertyChildChange, HandlePropertyChildChange); 754 INSTALL_EVENT_LISTENER(trackPropertyActiveDescendentChange, SetPropertyActiveDescendentChange, HandlePropertyActiveDescendentChange); 755 INSTALL_EVENT_LISTENER(trackPropertyTableModelChange, SetPropertyTableModelChange, HandlePropertyTableModelChange); 756 } 757 758 759 #define TRACK_EVENT_TOGGLE(menuItem, toggleVal, setFP, handler) \ 760 case menuItem: \ 761 menu = GetMenu(hWnd); \ 762 if (toggleVal) { \ 763 toggleVal = FALSE; \ 764 CheckMenuItem(menu, menuItem, \ 765 MF_BYCOMMAND | MF_UNCHECKED); \ 766 setFP(NULL); \ 767 } else { \ 768 toggleVal = TRUE; \ 769 CheckMenuItem(menu, menuItem, \ 770 MF_BYCOMMAND | MF_CHECKED); \ 771 setFP(handler); \ 772 } \ 773 return(TRUE) 774 775 776 BOOL APIENTRY FerretDialogProc (HWND hWnd, UINT message, UINT wParam, LONG lParam) { 777 int command; 778 short width, height; 779 HWND dlgItem; 780 HMENU menu; 781 782 switch (message) { 783 784 case WM_CREATE: 785 return 0; 786 787 case WM_INITDIALOG: 788 CheckMenuItem(GetMenu(hWnd), cAccessBridgeDLLLoaded, MF_BYCOMMAND | MF_CHECKED); 789 return(TRUE); 790 791 case WM_CLOSE: 792 exitJavaFerret(hWnd); 793 return(TRUE); 794 break; 795 796 case WM_SIZE: 797 width = LOWORD(lParam); 798 height = HIWORD(lParam); 799 dlgItem = GetDlgItem(theDialogWindow, cFerretText); 800 SetWindowPos(dlgItem, NULL, 0, 0, width, height, 0); 801 return(FALSE); // let windows finish handling this 802 break; 803 804 case WM_COMMAND: 805 command = LOWORD(wParam); 806 807 switch(command) { 808 case cAccessBridgeDLLLoaded: // toggle; unload or load AccessBridge 809 if (theAccessBridgeLoadedFlag) { 810 shutdownAccessBridge(); 811 theAccessBridgeLoadedFlag = FALSE; 812 CheckMenuItem(GetMenu(hWnd), cAccessBridgeDLLLoaded, MF_BYCOMMAND | MF_UNCHECKED); 813 } else { 814 theAccessBridgeLoadedFlag = initializeAccessBridge(); 815 if (theAccessBridgeLoadedFlag) { 816 CheckMenuItem(GetMenu(hWnd), cAccessBridgeDLLLoaded, MF_BYCOMMAND | MF_CHECKED); 817 reinstallEventListeners(); 818 } 819 } 820 return(TRUE); 821 822 case cExitMenuItem: 823 exitJavaFerret(hWnd); 824 return(TRUE); 825 826 TRACK_EVENT_TOGGLE(cTrackMouseMenuItem, trackMouse, SetMouseEntered, HandleMouseEntered); 827 TRACK_EVENT_TOGGLE(cTrackShutdownMenuItem, trackShutdown, SetJavaShutdown, HandleJavaShutdown); 828 TRACK_EVENT_TOGGLE(cTrackFocusMenuItem, trackFocus, SetFocusGained, HandleJavaFocusGained); 829 TRACK_EVENT_TOGGLE(cTrackCaretMenuItem, trackCaret, SetCaretUpdate, HandleJavaCaretUpdate); 830 831 TRACK_EVENT_TOGGLE(cTrackMenuSelectedMenuItem, trackMenuSelected, SetMenuSelected, HandleMenuSelected); 832 TRACK_EVENT_TOGGLE(cTrackMenuDeselectedMenuItem, trackMenuDeselected, SetMenuDeselected, HandleMenuDeselected); 833 TRACK_EVENT_TOGGLE(cTrackMenuCanceledItem, trackMenuCanceled, SetMenuCanceled, HandleMenuCanceled); 834 835 TRACK_EVENT_TOGGLE(cTrackPopupBecomeVisibleMenuItem, trackPopupVisible, SetPopupMenuWillBecomeVisible, HandlePopupMenuWillBecomeVisible); 836 TRACK_EVENT_TOGGLE(cTrackPopupBecomeInvisibleMenuItem, trackPopupInvisible, SetPopupMenuWillBecomeInvisible, HandlePopupMenuWillBecomeInvisible); 837 TRACK_EVENT_TOGGLE(cTrackPopupCanceledItem, trackPopupCanceled, SetPopupMenuCanceled, HandlePopupMenuCanceled); 838 839 TRACK_EVENT_TOGGLE(cTrackPropertyNameItem, trackPropertyNameChange, SetPropertyNameChange, HandlePropertyNameChange); 840 TRACK_EVENT_TOGGLE(cTrackPropertyDescriptionItem, trackPropertyDescriptionChange, SetPropertyDescriptionChange, HandlePropertyDescriptionChange); 841 TRACK_EVENT_TOGGLE(cTrackPropertyStateItem, trackPropertyStateChange, SetPropertyStateChange, HandlePropertyStateChange); 842 TRACK_EVENT_TOGGLE(cTrackPropertyValueItem, trackPropertyValueChange, SetPropertyValueChange, HandlePropertyValueChange); 843 TRACK_EVENT_TOGGLE(cTrackPropertySelectionItem, trackPropertySelectionChange, SetPropertySelectionChange, HandlePropertySelectionChange); 844 TRACK_EVENT_TOGGLE(cTrackPropertyTextItem, trackPropertyTextChange, SetPropertyTextChange, HandlePropertyTextChange); 845 TRACK_EVENT_TOGGLE(cTrackPropertyCaretItem, trackPropertyCaretChange, SetPropertyCaretChange, HandlePropertyCaretChange); 846 TRACK_EVENT_TOGGLE(cTrackPropertyVisibleDataItem, trackPropertyVisibleDataChange, SetPropertyVisibleDataChange, HandlePropertyVisibleDataChange); 847 TRACK_EVENT_TOGGLE(cTrackPropertyChildItem, trackPropertyChildChange, SetPropertyChildChange, HandlePropertyChildChange); 848 TRACK_EVENT_TOGGLE(cTrackPropertyActiveDescendentItem, trackPropertyActiveDescendentChange, SetPropertyActiveDescendentChange, HandlePropertyActiveDescendentChange); 849 TRACK_EVENT_TOGGLE(cTrackPropertyTableModelChangeItem, trackPropertyTableModelChange, SetPropertyTableModelChange, HandlePropertyTableModelChange); 850 851 case cUpdateFromMouseMenuItem: 852 menu = GetMenu(hWnd); 853 if (updateMouse) { 854 updateMouse = FALSE; 855 CheckMenuItem(menu, cUpdateFromMouseMenuItem, 856 MF_BYCOMMAND | MF_UNCHECKED); 857 UnhookWindowsHookEx((HHOOK)MouseProc); 858 KillTimer(hWnd, TIMER_ID); 859 } else { 860 updateMouse = TRUE; 861 CheckMenuItem(menu, cUpdateFromMouseMenuItem, 862 MF_BYCOMMAND | MF_CHECKED); 863 prevMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, theInstance, 0); 864 } 865 return(TRUE); 866 867 case cUpdateWithF1Item: 868 menu = GetMenu(hWnd); 869 if (updateF1) { 870 updateF1 = FALSE; 871 CheckMenuItem(menu, cUpdateWithF1Item, 872 MF_BYCOMMAND | MFS_UNCHECKED); 873 UnhookWindowsHookEx((HHOOK)KeyboardProc); 874 } else { 875 updateF1 = TRUE; 876 CheckMenuItem(menu, cUpdateWithF1Item, 877 MF_BYCOMMAND | MFS_CHECKED); 878 prevKbdHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, theInstance, 0); 879 } 880 return(TRUE); 881 882 case cUpdateWithF2Item: 883 menu = GetMenu(hWnd); 884 if (updateF2) { 885 updateF2 = FALSE; 886 CheckMenuItem(menu, cUpdateWithF2Item, 887 MF_BYCOMMAND | MFS_UNCHECKED); 888 UnhookWindowsHookEx((HHOOK)KeyboardProc); 889 } else { 890 updateF2 = TRUE; 891 CheckMenuItem(menu, cUpdateWithF2Item, 892 MF_BYCOMMAND | MFS_CHECKED); 893 prevKbdHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, theInstance, 0); 894 } 895 return(TRUE); 896 897 } 898 break; 899 900 case DISPLAY_INFO_MESSAGE: 901 echoMouseObject(); 902 break; 903 904 case DISPLAY_HWND_INFO_MESSAGE: 905 echoMouseHWNDObject(); 906 break; 907 } 908 909 return (FALSE); 910 }