| 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 |