OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/ime/chromeos/character_composer.h" | 5 #include "ui/base/ime/chromeos/character_composer.h" |
6 | 6 |
7 #include <X11/Xlib.h> | |
8 #include <X11/Xutil.h> | |
9 | |
10 #include <algorithm> | 7 #include <algorithm> |
11 #include <iterator> | 8 #include <iterator> |
12 | 9 |
13 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
14 #include "base/third_party/icu/icu_utf.h" | 11 #include "base/third_party/icu/icu_utf.h" |
15 // Note for Gtk removal: gdkkeysyms.h only contains a set of | 12 // Note for Gtk removal: gdkkeysyms.h only contains a set of |
16 // '#define GDK_KeyName 0xNNNN' macros and does not #include any Gtk headers. | 13 // '#define GDK_KeyName 0xNNNN' macros and does not #include any Gtk headers. |
17 #include "third_party/gtk+/gdk/gdkkeysyms.h" | 14 #include "third_party/gtk+/gdk/gdkkeysyms.h" |
| 15 |
18 #include "ui/base/glib/glib_integers.h" | 16 #include "ui/base/glib/glib_integers.h" |
19 #include "ui/events/event.h" | 17 #include "ui/events/event.h" |
20 #include "ui/events/event_constants.h" | 18 #include "ui/events/keycodes/keyboard_codes.h" |
21 #include "ui/gfx/x/x11_types.h" | |
22 | 19 |
23 // Note for Gtk removal: gtkimcontextsimpleseqs.h does not #include any Gtk | 20 // Note for Gtk removal: gtkimcontextsimpleseqs.h does not #include any Gtk |
24 // headers and only contains one big guint16 array |gtk_compose_seqs_compact| | 21 // headers and only contains one big guint16 array |gtk_compose_seqs_compact| |
25 // which defines the main compose table. The table has internal linkage. | 22 // which defines the main compose table. The table has internal linkage. |
26 // The order of header inclusion is out of order because | 23 // The order of header inclusion is out of order because |
27 // gtkimcontextsimpleseqs.h depends on guint16, which is defined in | 24 // gtkimcontextsimpleseqs.h depends on guint16, which is defined in |
28 // "ui/base/glib/glib_integers.h". | 25 // "ui/base/glib/glib_integers.h". |
29 #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h" | 26 #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h" |
30 | 27 |
31 namespace { | 28 namespace { |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 if (!CBU_IS_UNICODE_CHAR(character)) | 361 if (!CBU_IS_UNICODE_CHAR(character)) |
365 return false; | 362 return false; |
366 if (character) { | 363 if (character) { |
367 output->resize(CBU16_LENGTH(character)); | 364 output->resize(CBU16_LENGTH(character)); |
368 size_t i = 0; | 365 size_t i = 0; |
369 CBU16_APPEND_UNSAFE(&(*output)[0], i, character); | 366 CBU16_APPEND_UNSAFE(&(*output)[0], i, character); |
370 } | 367 } |
371 return true; | 368 return true; |
372 } | 369 } |
373 | 370 |
374 // Converts a X keycode to a X keysym with no modifiers. | |
375 KeySym XKeyCodeToXKeySym(unsigned int keycode) { | |
376 XDisplay* display = gfx::GetXDisplay(); | |
377 if (!display) | |
378 return NoSymbol; | |
379 | |
380 XKeyEvent x_key_event = {0}; | |
381 x_key_event.type = KeyPress; | |
382 x_key_event.display = display; | |
383 x_key_event.keycode = keycode; | |
384 return ::XLookupKeysym(&x_key_event, 0); | |
385 } | |
386 | |
387 // Returns an hexadecimal digit integer (0 to 15) corresponding to |keyval|. | 371 // Returns an hexadecimal digit integer (0 to 15) corresponding to |keyval|. |
388 // -1 is returned when |keyval| cannot be a hexadecimal digit. | 372 // -1 is returned when |keyval| cannot be a hexadecimal digit. |
389 int KeyvalToHexDigit(unsigned int keyval) { | 373 int KeyvalToHexDigit(unsigned int keyval) { |
390 if (GDK_KEY_0 <= keyval && keyval <= GDK_KEY_9) | 374 if (GDK_KEY_0 <= keyval && keyval <= GDK_KEY_9) |
391 return keyval - GDK_KEY_0; | 375 return keyval - GDK_KEY_0; |
392 if (GDK_KEY_a <= keyval && keyval <= GDK_KEY_f) | 376 if (GDK_KEY_a <= keyval && keyval <= GDK_KEY_f) |
393 return keyval - GDK_KEY_a + 10; | 377 return keyval - GDK_KEY_a + 10; |
394 if (GDK_KEY_A <= keyval && keyval <= GDK_KEY_F) | 378 if (GDK_KEY_A <= keyval && keyval <= GDK_KEY_F) |
395 return keyval - GDK_KEY_A + 10; | 379 return keyval - GDK_KEY_A + 10; |
396 return -1; // |keyval| cannot be a hexadecimal digit. | 380 return -1; // |keyval| cannot be a hexadecimal digit. |
397 } | 381 } |
398 | 382 |
| 383 // Returns an hexadecimal digit integer (0 to 15) corresponding to |keycode|. |
| 384 // -1 is returned when |keycode| cannot be a hexadecimal digit. |
| 385 int KeycodeToHexDigit(unsigned int keycode) { |
| 386 if (ui::VKEY_0 <= keycode && keycode <= ui::VKEY_9) |
| 387 return keycode - ui::VKEY_0; |
| 388 if (ui::VKEY_A <= keycode && keycode <= ui::VKEY_F) |
| 389 return keycode - ui::VKEY_A + 10; |
| 390 return -1; // |keycode| cannot be a hexadecimal digit. |
| 391 } |
| 392 |
399 } // namespace | 393 } // namespace |
400 | 394 |
401 namespace ui { | 395 namespace ui { |
402 | 396 |
403 CharacterComposer::CharacterComposer() : composition_mode_(KEY_SEQUENCE_MODE) {} | 397 CharacterComposer::CharacterComposer() : composition_mode_(KEY_SEQUENCE_MODE) {} |
404 | 398 |
405 CharacterComposer::~CharacterComposer() {} | 399 CharacterComposer::~CharacterComposer() {} |
406 | 400 |
407 void CharacterComposer::Reset() { | 401 void CharacterComposer::Reset() { |
408 compose_buffer_.clear(); | 402 compose_buffer_.clear(); |
409 composed_character_.clear(); | 403 composed_character_.clear(); |
410 preedit_string_.clear(); | 404 preedit_string_.clear(); |
411 composition_mode_ = KEY_SEQUENCE_MODE; | 405 composition_mode_ = KEY_SEQUENCE_MODE; |
412 } | 406 } |
413 | 407 |
414 bool CharacterComposer::FilterKeyPress(const ui::KeyEvent& event) { | 408 bool CharacterComposer::FilterKeyPress(const ui::KeyEvent& event) { |
415 if (!event.HasNativeEvent() || | 409 uint32 keyval = event.platform_keycode(); |
| 410 if (!keyval || |
416 (event.type() != ET_KEY_PRESSED && event.type() != ET_KEY_RELEASED)) | 411 (event.type() != ET_KEY_PRESSED && event.type() != ET_KEY_RELEASED)) |
417 return false; | 412 return false; |
418 | 413 |
419 XEvent* xevent = event.native_event(); | 414 return FilterKeyPressInternal(keyval, event.key_code(), event.flags()); |
420 DCHECK(xevent); | |
421 KeySym keysym = NoSymbol; | |
422 ::XLookupString(&xevent->xkey, NULL, 0, &keysym, NULL); | |
423 | |
424 return FilterKeyPressInternal(keysym, xevent->xkey.keycode, event.flags()); | |
425 } | 415 } |
426 | 416 |
427 | 417 |
428 bool CharacterComposer::FilterKeyPressInternal(unsigned int keyval, | 418 bool CharacterComposer::FilterKeyPressInternal(unsigned int keyval, |
429 unsigned int keycode, | 419 unsigned int keycode, |
430 int flags) { | 420 int flags) { |
431 composed_character_.clear(); | 421 composed_character_.clear(); |
432 preedit_string_.clear(); | 422 preedit_string_.clear(); |
433 | 423 |
434 // We don't care about modifier key presses. | 424 // We don't care about modifier key presses. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 unsigned int keycode, | 490 unsigned int keycode, |
501 int flags) { | 491 int flags) { |
502 DCHECK(composition_mode_ == HEX_MODE); | 492 DCHECK(composition_mode_ == HEX_MODE); |
503 const size_t kMaxHexSequenceLength = 8; | 493 const size_t kMaxHexSequenceLength = 8; |
504 int hex_digit = KeyvalToHexDigit(keyval); | 494 int hex_digit = KeyvalToHexDigit(keyval); |
505 if (hex_digit < 0) { | 495 if (hex_digit < 0) { |
506 // With 101 keyboard, control + shift + 3 produces '#', but a user may | 496 // With 101 keyboard, control + shift + 3 produces '#', but a user may |
507 // have intended to type '3'. So, if a hexadecimal character was not found, | 497 // have intended to type '3'. So, if a hexadecimal character was not found, |
508 // suppose a user is holding shift key (and possibly control key, too) and | 498 // suppose a user is holding shift key (and possibly control key, too) and |
509 // try a character with modifier keys removed. | 499 // try a character with modifier keys removed. |
510 hex_digit = KeyvalToHexDigit(XKeyCodeToXKeySym(keycode)); | 500 hex_digit = KeycodeToHexDigit(keycode); |
511 } | 501 } |
512 | 502 |
513 if (keyval == GDK_KEY_Escape) { | 503 if (keyval == GDK_KEY_Escape) { |
514 // Cancel composition when ESC is pressed. | 504 // Cancel composition when ESC is pressed. |
515 Reset(); | 505 Reset(); |
516 } else if (keyval == GDK_KEY_Return || keyval == GDK_KEY_KP_Enter || | 506 } else if (keyval == GDK_KEY_Return || keyval == GDK_KEY_KP_Enter || |
517 keyval == GDK_KEY_ISO_Enter || | 507 keyval == GDK_KEY_ISO_Enter || |
518 keyval == GDK_KEY_space || keyval == GDK_KEY_KP_Space) { | 508 keyval == GDK_KEY_space || keyval == GDK_KEY_KP_Space) { |
519 // Commit the composed character when Enter or space is pressed. | 509 // Commit the composed character when Enter or space is pressed. |
520 CommitHex(); | 510 CommitHex(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 std::string preedit_string_ascii("u"); | 548 std::string preedit_string_ascii("u"); |
559 for (size_t i = 0; i != compose_buffer_.size(); ++i) { | 549 for (size_t i = 0; i != compose_buffer_.size(); ++i) { |
560 const int digit = compose_buffer_[i]; | 550 const int digit = compose_buffer_[i]; |
561 DCHECK(0 <= digit && digit < 16); | 551 DCHECK(0 <= digit && digit < 16); |
562 preedit_string_ascii += digit <= 9 ? ('0' + digit) : ('a' + (digit - 10)); | 552 preedit_string_ascii += digit <= 9 ? ('0' + digit) : ('a' + (digit - 10)); |
563 } | 553 } |
564 preedit_string_ = base::ASCIIToUTF16(preedit_string_ascii); | 554 preedit_string_ = base::ASCIIToUTF16(preedit_string_ascii); |
565 } | 555 } |
566 | 556 |
567 } // namespace ui | 557 } // namespace ui |
OLD | NEW |