Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: ui/base/ime/character_composer.cc

Issue 15816003: Supports unicode composition(Ctrl+Shift+U) with C-S pressed. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added a comment. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/base/ime/character_composer.h ('k') | ui/base/ime/character_composer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/character_composer.h" 5 #include "ui/base/ime/character_composer.h"
6 6
7 #include <X11/Xlib.h>
8
7 #include <algorithm> 9 #include <algorithm>
8 #include <iterator> 10 #include <iterator>
9 11
10 #include "base/third_party/icu/icu_utf.h" 12 #include "base/third_party/icu/icu_utf.h"
11 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
12 // Note for Gtk removal: gdkkeysyms.h only contains a set of 14 // Note for Gtk removal: gdkkeysyms.h only contains a set of
13 // '#define GDK_KeyName 0xNNNN' macros and does not #include any Gtk headers. 15 // '#define GDK_KeyName 0xNNNN' macros and does not #include any Gtk headers.
14 #include "third_party/gtk+/gdk/gdkkeysyms.h" 16 #include "third_party/gtk+/gdk/gdkkeysyms.h"
15 #include "ui/base/events/event_constants.h" 17 #include "ui/base/events/event_constants.h"
16 #include "ui/base/glib/glib_integers.h" 18 #include "ui/base/glib/glib_integers.h"
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 if (!CBU_IS_UNICODE_CHAR(character)) 344 if (!CBU_IS_UNICODE_CHAR(character))
343 return false; 345 return false;
344 if (character) { 346 if (character) {
345 output->resize(CBU16_LENGTH(character)); 347 output->resize(CBU16_LENGTH(character));
346 size_t i = 0; 348 size_t i = 0;
347 CBU16_APPEND_UNSAFE(&(*output)[0], i, character); 349 CBU16_APPEND_UNSAFE(&(*output)[0], i, character);
348 } 350 }
349 return true; 351 return true;
350 } 352 }
351 353
354 // Converts a X keycode to a X keysym with no modifiers.
355 KeySym XKeyCodeToXKeySym(unsigned int keycode) {
356 Display* display = ::XOpenDisplay(NULL);
Seigo Nonaka 2013/05/23 08:19:21 How about using MessagePumpAuraForUI::GetDefaultXD
Yuki 2013/05/23 08:48:40 Done.
357 if (!display)
358 return NoSymbol;
359
360 XKeyEvent x_key_event = {0};
361 x_key_event.type = KeyPress;
362 x_key_event.display = display;
363 x_key_event.keycode = keycode;
364 KeySym keysym = ::XLookupKeysym(&x_key_event, 0);
365 ::XCloseDisplay(display);
366 return keysym;
367 }
368
352 // Returns an hexadecimal digit integer (0 to 15) corresponding to |keyval|. 369 // Returns an hexadecimal digit integer (0 to 15) corresponding to |keyval|.
353 // -1 is returned when |keyval| cannot be a hexadecimal digit. 370 // -1 is returned when |keyval| cannot be a hexadecimal digit.
354 int KeyvalToHexDigit(unsigned int keyval) { 371 int KeyvalToHexDigit(unsigned int keyval) {
355 if (GDK_KEY_0 <= keyval && keyval <= GDK_KEY_9) 372 if (GDK_KEY_0 <= keyval && keyval <= GDK_KEY_9)
356 return keyval - GDK_KEY_0; 373 return keyval - GDK_KEY_0;
357 if (GDK_KEY_a <= keyval && keyval <= GDK_KEY_f) 374 if (GDK_KEY_a <= keyval && keyval <= GDK_KEY_f)
358 return keyval - GDK_KEY_a + 10; 375 return keyval - GDK_KEY_a + 10;
359 if (GDK_KEY_A <= keyval && keyval <= GDK_KEY_F) 376 if (GDK_KEY_A <= keyval && keyval <= GDK_KEY_F)
360 return keyval - GDK_KEY_A + 10; 377 return keyval - GDK_KEY_A + 10;
361 return -1; // |keyval| cannot be a hexadecimal digit. 378 return -1; // |keyval| cannot be a hexadecimal digit.
362 } 379 }
363 380
364 } // namespace 381 } // namespace
365 382
366 namespace ui { 383 namespace ui {
367 384
368 CharacterComposer::CharacterComposer() : composition_mode_(KEY_SEQUENCE_MODE) {} 385 CharacterComposer::CharacterComposer() : composition_mode_(KEY_SEQUENCE_MODE) {}
369 386
370 CharacterComposer::~CharacterComposer() {} 387 CharacterComposer::~CharacterComposer() {}
371 388
372 void CharacterComposer::Reset() { 389 void CharacterComposer::Reset() {
373 compose_buffer_.clear(); 390 compose_buffer_.clear();
374 composed_character_.clear(); 391 composed_character_.clear();
375 preedit_string_.clear(); 392 preedit_string_.clear();
376 composition_mode_ = KEY_SEQUENCE_MODE; 393 composition_mode_ = KEY_SEQUENCE_MODE;
377 } 394 }
378 395
379 bool CharacterComposer::FilterKeyPress(unsigned int keyval, 396 bool CharacterComposer::FilterKeyPress(unsigned int keyval,
380 unsigned int flags) { 397 unsigned int keycode,
398 int flags) {
381 composed_character_.clear(); 399 composed_character_.clear();
382 preedit_string_.clear(); 400 preedit_string_.clear();
383 401
384 // We don't care about modifier key presses. 402 // We don't care about modifier key presses.
385 if(KeypressShouldBeIgnored(keyval)) 403 if(KeypressShouldBeIgnored(keyval))
386 return false; 404 return false;
387 405
388 // When the user presses Ctrl+Shift+U, maybe switch to HEX_MODE. 406 // When the user presses Ctrl+Shift+U, maybe switch to HEX_MODE.
389 // We don't care about other modifiers like Alt. When CapsLock is down, we 407 // We don't care about other modifiers like Alt. When CapsLock is down, we
390 // do nothing because what we receive is Ctrl+Shift+u (not U). 408 // do nothing because what we receive is Ctrl+Shift+u (not U).
391 if (keyval == GDK_KEY_U && (flags & EF_SHIFT_DOWN) && 409 if (keyval == GDK_KEY_U && (flags & EF_SHIFT_DOWN) &&
392 (flags & EF_CONTROL_DOWN)) { 410 (flags & EF_CONTROL_DOWN)) {
393 if (composition_mode_ == KEY_SEQUENCE_MODE && compose_buffer_.empty()) { 411 if (composition_mode_ == KEY_SEQUENCE_MODE && compose_buffer_.empty()) {
394 // There is no ongoing composition. Let's switch to HEX_MODE. 412 // There is no ongoing composition. Let's switch to HEX_MODE.
395 composition_mode_ = HEX_MODE; 413 composition_mode_ = HEX_MODE;
396 UpdatePreeditStringHexMode(); 414 UpdatePreeditStringHexMode();
397 return true; 415 return true;
398 } 416 }
399 } 417 }
400 418
401 // Filter key press in an appropriate manner. 419 // Filter key press in an appropriate manner.
402 switch (composition_mode_) { 420 switch (composition_mode_) {
403 case KEY_SEQUENCE_MODE: 421 case KEY_SEQUENCE_MODE:
404 return FilterKeyPressSequenceMode(keyval, flags); 422 return FilterKeyPressSequenceMode(keyval, keycode, flags);
405 case HEX_MODE: 423 case HEX_MODE:
406 return FilterKeyPressHexMode(keyval, flags); 424 return FilterKeyPressHexMode(keyval, keycode, flags);
407 default: 425 default:
408 NOTREACHED(); 426 NOTREACHED();
409 return false; 427 return false;
410 } 428 }
411 } 429 }
412 430
413 bool CharacterComposer::FilterKeyPressSequenceMode(unsigned int keyval, 431 bool CharacterComposer::FilterKeyPressSequenceMode(unsigned int keyval,
414 unsigned int flags) { 432 unsigned int keycode,
433 int flags) {
415 DCHECK(composition_mode_ == KEY_SEQUENCE_MODE); 434 DCHECK(composition_mode_ == KEY_SEQUENCE_MODE);
416 compose_buffer_.push_back(keyval); 435 compose_buffer_.push_back(keyval);
417 436
418 // Check compose table. 437 // Check compose table.
419 uint32 composed_character_utf32 = 0; 438 uint32 composed_character_utf32 = 0;
420 if (CheckCharacterComposeTable(compose_buffer_, &composed_character_utf32)) { 439 if (CheckCharacterComposeTable(compose_buffer_, &composed_character_utf32)) {
421 // Key press is recognized as a part of composition. 440 // Key press is recognized as a part of composition.
422 if (composed_character_utf32 != 0) { 441 if (composed_character_utf32 != 0) {
423 // We get a composed character. 442 // We get a composed character.
424 compose_buffer_.clear(); 443 compose_buffer_.clear();
425 UTF32CharacterToUTF16(composed_character_utf32, &composed_character_); 444 UTF32CharacterToUTF16(composed_character_utf32, &composed_character_);
426 } 445 }
427 return true; 446 return true;
428 } 447 }
429 // Key press is not a part of composition. 448 // Key press is not a part of composition.
430 compose_buffer_.pop_back(); // Remove the keypress added this time. 449 compose_buffer_.pop_back(); // Remove the keypress added this time.
431 if (!compose_buffer_.empty()) { 450 if (!compose_buffer_.empty()) {
432 compose_buffer_.clear(); 451 compose_buffer_.clear();
433 return true; 452 return true;
434 } 453 }
435 return false; 454 return false;
436 } 455 }
437 456
438 bool CharacterComposer::FilterKeyPressHexMode(unsigned int keyval, 457 bool CharacterComposer::FilterKeyPressHexMode(unsigned int keyval,
439 unsigned int flags) { 458 unsigned int keycode,
459 int flags) {
440 DCHECK(composition_mode_ == HEX_MODE); 460 DCHECK(composition_mode_ == HEX_MODE);
441 const size_t kMaxHexSequenceLength = 8; 461 const size_t kMaxHexSequenceLength = 8;
442 const int hex_digit = KeyvalToHexDigit(keyval); 462 int hex_digit = KeyvalToHexDigit(keyval);
463 if (hex_digit < 0) {
464 // With 101 keyboard, control + shift + 3 produces '#', but a user may
465 // have intended to type '3'. So, if a hexadecimal character was not found,
466 // suppose a user is holding shift key (and possibly control key, too) and
467 // try a character with modifier keys removed.
468 hex_digit = KeyvalToHexDigit(XKeyCodeToXKeySym(keycode));
469 }
443 470
444 if (keyval == GDK_KEY_Escape) { 471 if (keyval == GDK_KEY_Escape) {
445 // Cancel composition when ESC is pressed. 472 // Cancel composition when ESC is pressed.
446 Reset(); 473 Reset();
447 } else if (keyval == GDK_KEY_Return || keyval == GDK_KEY_KP_Enter || 474 } else if (keyval == GDK_KEY_Return || keyval == GDK_KEY_KP_Enter ||
448 keyval == GDK_KEY_ISO_Enter || 475 keyval == GDK_KEY_ISO_Enter ||
449 keyval == GDK_KEY_space || keyval == GDK_KEY_KP_Space) { 476 keyval == GDK_KEY_space || keyval == GDK_KEY_KP_Space) {
450 // Commit the composed character when Enter or space is pressed. 477 // Commit the composed character when Enter or space is pressed.
451 CommitHex(); 478 CommitHex();
452 } else if (keyval == GDK_KEY_BackSpace) { 479 } else if (keyval == GDK_KEY_BackSpace) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 std::string preedit_string_ascii("u"); 516 std::string preedit_string_ascii("u");
490 for (size_t i = 0; i != compose_buffer_.size(); ++i) { 517 for (size_t i = 0; i != compose_buffer_.size(); ++i) {
491 const int digit = compose_buffer_[i]; 518 const int digit = compose_buffer_[i];
492 DCHECK(0 <= digit && digit < 16); 519 DCHECK(0 <= digit && digit < 16);
493 preedit_string_ascii += digit <= 9 ? ('0' + digit) : ('a' + (digit - 10)); 520 preedit_string_ascii += digit <= 9 ? ('0' + digit) : ('a' + (digit - 10));
494 } 521 }
495 preedit_string_ = ASCIIToUTF16(preedit_string_ascii); 522 preedit_string_ = ASCIIToUTF16(preedit_string_ascii);
496 } 523 }
497 524
498 } // namespace ui 525 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/character_composer.h ('k') | ui/base/ime/character_composer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698