443 (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, 444 (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, 445 (modifiers & KeyEvent.MODIFIER_ALT) != 0, 446 (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0, 447 false, // this is always indirect 448 false); // this has no inertia 449 } 450 return null; 451 }, scene.getAccessControlContext()); 452 }); 453 } finally { 454 if (stage != null) { 455 stage.setInEventHandler(false); 456 } 457 if (PULSE_LOGGING_ENABLED) { 458 PulseLogger.newInput(null); 459 } 460 } 461 } 462 463 // TODO: Define these somewhere else. It is Windows specific for now. 464 private final static byte ATTR_INPUT = 0x00; 465 private final static byte ATTR_TARGET_CONVERTED = 0x01; 466 private final static byte ATTR_CONVERTED = 0x02; 467 private final static byte ATTR_TARGET_NOTCONVERTED = 0x03; 468 private final static byte ATTR_INPUT_ERROR = 0x04; 469 470 private static byte inputMethodEventAttrValue(int pos, int[] attrBoundary, byte[] attrValue) { 471 if (attrBoundary != null) { 472 for (int current = 0; current < attrBoundary.length-1; current++) { 473 if (pos >= attrBoundary[current] && 474 pos < attrBoundary[current+1]) { 475 return attrValue[current]; 476 } 477 } 478 } 479 return ATTR_INPUT_ERROR; 480 } 481 482 private static ObservableList<InputMethodTextRun> inputMethodEventComposed( 483 String text, int commitCount, int[] clauseBoundary, int[] attrBoundary, byte[] attrValue) 484 { 485 ObservableList<InputMethodTextRun> composed = new TrackableObservableList<InputMethodTextRun>() { 486 @Override 487 protected void onChanged(ListChangeListener.Change<InputMethodTextRun> c) { 488 } 489 }; 490 491 if (commitCount < text.length()) { 492 if (clauseBoundary == null) { 493 // Create one single segment as UNSELECTED_RAW 494 composed.add(new InputMethodTextRun( 495 text.substring(commitCount), 496 InputMethodHighlight.UNSELECTED_RAW)); 497 } else { 498 for (int current = 0; current < clauseBoundary.length-1; current++) { 499 if (clauseBoundary[current] < commitCount) { 500 continue; 501 } 502 503 InputMethodHighlight highlight; 504 switch (inputMethodEventAttrValue(clauseBoundary[current], attrBoundary, attrValue)) { 505 case ATTR_TARGET_CONVERTED: 506 highlight = InputMethodHighlight.SELECTED_CONVERTED; 507 break; 508 case ATTR_CONVERTED: 509 highlight = InputMethodHighlight.UNSELECTED_CONVERTED; 510 break; 511 case ATTR_TARGET_NOTCONVERTED: 512 highlight = InputMethodHighlight.SELECTED_RAW; 513 break; 514 case ATTR_INPUT: 515 case ATTR_INPUT_ERROR: 516 default: 517 highlight = InputMethodHighlight.UNSELECTED_RAW; 518 break; 519 } 520 composed.add(new InputMethodTextRun( 521 text.substring(clauseBoundary[current], 522 clauseBoundary[current+1]), 523 highlight)); 524 } 525 } 526 } 527 return composed; 528 } 529 530 @Override public void handleInputMethodEvent(final long time, final String text, 531 final int[] clauseBoundary, 532 final int[] attrBoundary, final byte[] attrValue, 533 final int commitCount, final int cursorPos) 534 { 535 if (PULSE_LOGGING_ENABLED) { | 443 (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, 444 (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, 445 (modifiers & KeyEvent.MODIFIER_ALT) != 0, 446 (modifiers & KeyEvent.MODIFIER_WINDOWS) != 0, 447 false, // this is always indirect 448 false); // this has no inertia 449 } 450 return null; 451 }, scene.getAccessControlContext()); 452 }); 453 } finally { 454 if (stage != null) { 455 stage.setInEventHandler(false); 456 } 457 if (PULSE_LOGGING_ENABLED) { 458 PulseLogger.newInput(null); 459 } 460 } 461 } 462 463 private static byte inputMethodEventAttrValue(int pos, int[] attrBoundary, byte[] attrValue) { 464 if (attrBoundary != null) { 465 for (int current = 0; current < attrBoundary.length-1; current++) { 466 if (pos >= attrBoundary[current] && 467 pos < attrBoundary[current+1]) { 468 return attrValue[current]; 469 } 470 } 471 } 472 return View.IME_ATTR_INPUT_ERROR; 473 } 474 475 private static ObservableList<InputMethodTextRun> inputMethodEventComposed( 476 String text, int commitCount, int[] clauseBoundary, int[] attrBoundary, byte[] attrValue) 477 { 478 ObservableList<InputMethodTextRun> composed = new TrackableObservableList<InputMethodTextRun>() { 479 @Override 480 protected void onChanged(ListChangeListener.Change<InputMethodTextRun> c) { 481 } 482 }; 483 484 if (commitCount < text.length()) { 485 if (clauseBoundary == null) { 486 // Create one single segment as UNSELECTED_RAW 487 composed.add(new InputMethodTextRun( 488 text.substring(commitCount), 489 InputMethodHighlight.UNSELECTED_RAW)); 490 } else { 491 for (int current = 0; current < clauseBoundary.length-1; current++) { 492 if (clauseBoundary[current] < commitCount) { 493 continue; 494 } 495 496 InputMethodHighlight highlight; 497 switch (inputMethodEventAttrValue(clauseBoundary[current], attrBoundary, attrValue)) { 498 case View.IME_ATTR_TARGET_CONVERTED: 499 highlight = InputMethodHighlight.SELECTED_CONVERTED; 500 break; 501 case View.IME_ATTR_CONVERTED: 502 highlight = InputMethodHighlight.UNSELECTED_CONVERTED; 503 break; 504 case View.IME_ATTR_TARGET_NOTCONVERTED: 505 highlight = InputMethodHighlight.SELECTED_RAW; 506 break; 507 case View.IME_ATTR_INPUT: 508 case View.IME_ATTR_INPUT_ERROR: 509 default: 510 highlight = InputMethodHighlight.UNSELECTED_RAW; 511 break; 512 } 513 composed.add(new InputMethodTextRun( 514 text.substring(clauseBoundary[current], 515 clauseBoundary[current+1]), 516 highlight)); 517 } 518 } 519 } 520 return composed; 521 } 522 523 @Override public void handleInputMethodEvent(final long time, final String text, 524 final int[] clauseBoundary, 525 final int[] attrBoundary, final byte[] attrValue, 526 final int commitCount, final int cursorPos) 527 { 528 if (PULSE_LOGGING_ENABLED) { |