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

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_win.cc

Issue 6709023: Move some common ime code to ui/base/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Always put the composition cursor to the selection end. Created 9 years, 9 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 | « chrome/browser/renderer_host/render_widget_host_view_win.h ('k') | chrome/chrome_browser.gypi » ('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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/renderer_host/render_widget_host_view_win.h" 5 #include "chrome/browser/renderer_host/render_widget_host_view_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
(...skipping 14 matching lines...) Expand all
25 #include "content/browser/plugin_process_host.h" 25 #include "content/browser/plugin_process_host.h"
26 #include "content/browser/renderer_host/backing_store.h" 26 #include "content/browser/renderer_host/backing_store.h"
27 #include "content/browser/renderer_host/backing_store_win.h" 27 #include "content/browser/renderer_host/backing_store_win.h"
28 #include "content/browser/renderer_host/render_process_host.h" 28 #include "content/browser/renderer_host/render_process_host.h"
29 #include "content/browser/renderer_host/render_widget_host.h" 29 #include "content/browser/renderer_host/render_widget_host.h"
30 #include "content/common/native_web_keyboard_event.h" 30 #include "content/common/native_web_keyboard_event.h"
31 #include "content/common/notification_service.h" 31 #include "content/common/notification_service.h"
32 #include "content/common/plugin_messages.h" 32 #include "content/common/plugin_messages.h"
33 #include "grit/webkit_resources.h" 33 #include "grit/webkit_resources.h"
34 #include "skia/ext/skia_utils_win.h" 34 #include "skia/ext/skia_utils_win.h"
35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderli ne.h"
35 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" 36 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
36 #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFact ory.h" 37 #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFact ory.h"
38 #include "ui/base/ime/composition_text.h"
37 #include "ui/base/l10n/l10n_util.h" 39 #include "ui/base/l10n/l10n_util.h"
38 #include "ui/base/l10n/l10n_util_win.h" 40 #include "ui/base/l10n/l10n_util_win.h"
39 #include "ui/base/resource/resource_bundle.h" 41 #include "ui/base/resource/resource_bundle.h"
40 #include "ui/base/view_prop.h" 42 #include "ui/base/view_prop.h"
41 #include "ui/base/win/hwnd_util.h" 43 #include "ui/base/win/hwnd_util.h"
42 #include "ui/gfx/canvas.h" 44 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/canvas_skia.h" 45 #include "ui/gfx/canvas_skia.h"
44 #include "ui/gfx/gdi_util.h" 46 #include "ui/gfx/gdi_util.h"
45 #include "ui/gfx/rect.h" 47 #include "ui/gfx/rect.h"
46 #include "views/accessibility/native_view_accessibility_win.h" 48 #include "views/accessibility/native_view_accessibility_win.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 if (::IsWindowVisible(window)) { 89 if (::IsWindowVisible(window)) {
88 const HWND owner = ::GetWindow(window, GW_OWNER); 90 const HWND owner = ::GetWindow(window, GW_OWNER);
89 if (toplevel_hwnd == owner) { 91 if (toplevel_hwnd == owner) {
90 ::PostMessage(window, WM_CANCELMODE, 0, 0); 92 ::PostMessage(window, WM_CANCELMODE, 0, 0);
91 } 93 }
92 } 94 }
93 95
94 return TRUE; 96 return TRUE;
95 } 97 }
96 98
97 // Enumerates the installed keyboard layouts in this system and returns true
98 // if an RTL keyboard layout is installed.
99 // TODO(hbono): to be moved to "src/chrome/common/l10n_util.cc"?
100 static bool IsRTLKeyboardLayoutInstalled() {
101 static enum {
102 RTL_KEYBOARD_LAYOUT_NOT_INITIALIZED,
103 RTL_KEYBOARD_LAYOUT_INSTALLED,
104 RTL_KEYBOARD_LAYOUT_NOT_INSTALLED,
105 RTL_KEYBOARD_LAYOUT_ERROR,
106 } layout = RTL_KEYBOARD_LAYOUT_NOT_INITIALIZED;
107
108 // Cache the result value.
109 if (layout != RTL_KEYBOARD_LAYOUT_NOT_INITIALIZED)
110 return layout == RTL_KEYBOARD_LAYOUT_INSTALLED;
111
112 // Retrieve the number of layouts installed in this system.
113 int size = GetKeyboardLayoutList(0, NULL);
114 if (size <= 0) {
115 layout = RTL_KEYBOARD_LAYOUT_ERROR;
116 return false;
117 }
118
119 // Retrieve the keyboard layouts in an array and check if there is an RTL
120 // layout in it.
121 scoped_array<HKL> layouts(new HKL[size]);
122 GetKeyboardLayoutList(size, layouts.get());
123 for (int i = 0; i < size; ++i) {
124 if (PRIMARYLANGID(layouts[i]) == LANG_ARABIC ||
125 PRIMARYLANGID(layouts[i]) == LANG_HEBREW ||
126 PRIMARYLANGID(layouts[i]) == LANG_PERSIAN) {
127 layout = RTL_KEYBOARD_LAYOUT_INSTALLED;
128 return true;
129 }
130 }
131
132 layout = RTL_KEYBOARD_LAYOUT_NOT_INSTALLED;
133 return false;
134 }
135
136 // Returns the text direction according to the keyboard status.
137 // This function retrieves the status of all keys and returns the following
138 // values:
139 // * WEB_TEXT_DIRECTION_RTL
140 // If only a control key and a right-shift key are down.
141 // * WEB_TEXT_DIRECTION_LTR
142 // If only a control key and a left-shift key are down.
143
144 static bool GetNewTextDirection(WebTextDirection* direction) {
145 uint8_t keystate[256];
146 if (!GetKeyboardState(&keystate[0]))
147 return false;
148
149 // To check if a user is pressing only a control key and a right-shift key
150 // (or a left-shift key), we use the steps below:
151 // 1. Check if a user is pressing a control key and a right-shift key (or
152 // a left-shift key).
153 // 2. If the condition 1 is true, we should check if there are any other
154 // keys pressed at the same time.
155 // To ignore the keys checked in 1, we set their status to 0 before
156 // checking the key status.
157 const int kKeyDownMask = 0x80;
158 if ((keystate[VK_CONTROL] & kKeyDownMask) == 0)
159 return false;
160
161 if (keystate[VK_RSHIFT] & kKeyDownMask) {
162 keystate[VK_RSHIFT] = 0;
163 *direction = WebKit::WebTextDirectionRightToLeft;
164 } else if (keystate[VK_LSHIFT] & kKeyDownMask) {
165 keystate[VK_LSHIFT] = 0;
166 *direction = WebKit::WebTextDirectionLeftToRight;
167 } else {
168 return false;
169 }
170
171 // Scan the key status to find pressed keys. We should adandon changing the
172 // text direction when there are other pressed keys.
173 // This code is executed only when a user is pressing a control key and a
174 // right-shift key (or a left-shift key), i.e. we should ignore the status of
175 // the keys: VK_SHIFT, VK_CONTROL, VK_RCONTROL, and VK_LCONTROL.
176 // So, we reset their status to 0 and ignore them.
177 keystate[VK_SHIFT] = 0;
178 keystate[VK_CONTROL] = 0;
179 keystate[VK_RCONTROL] = 0;
180 keystate[VK_LCONTROL] = 0;
181 for (int i = 0; i <= VK_PACKET; ++i) {
182 if (keystate[i] & kKeyDownMask)
183 return false;
184 }
185 return true;
186 }
187
188 class NotifyPluginProcessHostTask : public Task { 99 class NotifyPluginProcessHostTask : public Task {
189 public: 100 public:
190 NotifyPluginProcessHostTask(HWND window, HWND parent) 101 NotifyPluginProcessHostTask(HWND window, HWND parent)
191 : window_(window), parent_(parent), tries_(kMaxTries) { } 102 : window_(window), parent_(parent), tries_(kMaxTries) { }
192 103
193 private: 104 private:
194 void Run() { 105 void Run() {
195 DWORD plugin_process_id; 106 DWORD plugin_process_id;
196 bool found_starting_plugin_process = false; 107 bool found_starting_plugin_process = false;
197 GetWindowThreadProcessId(window_, &plugin_process_id); 108 GetWindowThreadProcessId(window_, &plugin_process_id);
(...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 bool activated = (wparam == TRUE); 1100 bool activated = (wparam == TRUE);
1190 if (render_widget_host_) { 1101 if (render_widget_host_) {
1191 render_widget_host_->SetInputMethodActive(activated); 1102 render_widget_host_->SetInputMethodActive(activated);
1192 ime_notification_ = activated; 1103 ime_notification_ = activated;
1193 } 1104 }
1194 1105
1195 if (ime_notification_) 1106 if (ime_notification_)
1196 ime_input_.CreateImeWindow(m_hWnd); 1107 ime_input_.CreateImeWindow(m_hWnd);
1197 1108
1198 ime_input_.CleanupComposition(m_hWnd); 1109 ime_input_.CleanupComposition(m_hWnd);
1199 ime_input_.SetImeWindowStyle(m_hWnd, message, wparam, lparam, &handled); 1110 return ime_input_.SetImeWindowStyle(
1200 return 0; 1111 m_hWnd, message, wparam, lparam, &handled);
1201 } 1112 }
1202 1113
1203 LRESULT RenderWidgetHostViewWin::OnImeStartComposition( 1114 LRESULT RenderWidgetHostViewWin::OnImeStartComposition(
1204 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { 1115 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1205 if (!render_widget_host_) 1116 if (!render_widget_host_)
1206 return 0; 1117 return 0;
1207 1118
1208 // Reset the composition status and create IME windows. 1119 // Reset the composition status and create IME windows.
1209 ime_input_.CreateImeWindow(m_hWnd); 1120 ime_input_.CreateImeWindow(m_hWnd);
1210 ime_input_.ResetComposition(m_hWnd); 1121 ime_input_.ResetComposition(m_hWnd);
1211 // We have to prevent WTL from calling ::DefWindowProc() because the function 1122 // We have to prevent WTL from calling ::DefWindowProc() because the function
1212 // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to 1123 // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
1213 // over-write the position of IME windows. 1124 // over-write the position of IME windows.
1214 handled = TRUE; 1125 handled = TRUE;
1215 return 0; 1126 return 0;
1216 } 1127 }
1217 1128
1218 LRESULT RenderWidgetHostViewWin::OnImeComposition( 1129 LRESULT RenderWidgetHostViewWin::OnImeComposition(
1219 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { 1130 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1220 if (!render_widget_host_) 1131 if (!render_widget_host_)
1221 return 0; 1132 return 0;
1222 1133
1223 // At first, update the position of the IME window. 1134 // At first, update the position of the IME window.
1224 ime_input_.UpdateImeWindow(m_hWnd); 1135 ime_input_.UpdateImeWindow(m_hWnd);
1225 1136
1137 // ui::CompositionUnderline should be identical to
1138 // WebKit::WebCompositionUnderline, so that we can do reinterpret_cast safely.
1139 COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
1140 sizeof(WebKit::WebCompositionUnderline),
1141 ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
1142
1226 // Retrieve the result string and its attributes of the ongoing composition 1143 // Retrieve the result string and its attributes of the ongoing composition
1227 // and send it to a renderer process. 1144 // and send it to a renderer process.
1228 ImeComposition composition; 1145 ui::CompositionText composition;
1229 if (ime_input_.GetResult(m_hWnd, lparam, &composition)) { 1146 if (ime_input_.GetResult(m_hWnd, lparam, &composition.text)) {
1230 render_widget_host_->ImeConfirmComposition(composition.ime_string); 1147 render_widget_host_->ImeConfirmComposition(composition.text);
1231 ime_input_.ResetComposition(m_hWnd); 1148 ime_input_.ResetComposition(m_hWnd);
1232 // Fall though and try reading the composition string. 1149 // Fall though and try reading the composition string.
1233 // Japanese IMEs send a message containing both GCS_RESULTSTR and 1150 // Japanese IMEs send a message containing both GCS_RESULTSTR and
1234 // GCS_COMPSTR, which means an ongoing composition has been finished 1151 // GCS_COMPSTR, which means an ongoing composition has been finished
1235 // by the start of another composition. 1152 // by the start of another composition.
1236 } 1153 }
1237 // Retrieve the composition string and its attributes of the ongoing 1154 // Retrieve the composition string and its attributes of the ongoing
1238 // composition and send it to a renderer process. 1155 // composition and send it to a renderer process.
1239 if (ime_input_.GetComposition(m_hWnd, lparam, &composition)) { 1156 if (ime_input_.GetComposition(m_hWnd, lparam, &composition)) {
1157 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1158 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1159 composition.selection = ui::Range(composition.selection.end());
1160
1161 // TODO(suzhe): convert both renderer_host and renderer to use
1162 // ui::CompositionText.
1163 const std::vector<WebKit::WebCompositionUnderline>& underlines =
1164 reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
1165 composition.underlines);
1240 render_widget_host_->ImeSetComposition( 1166 render_widget_host_->ImeSetComposition(
1241 composition.ime_string, composition.underlines, 1167 composition.text, underlines,
1242 composition.selection_start, composition.selection_end); 1168 composition.selection.start(), composition.selection.end());
1243 } 1169 }
1244 // We have to prevent WTL from calling ::DefWindowProc() because we do not 1170 // We have to prevent WTL from calling ::DefWindowProc() because we do not
1245 // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages. 1171 // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
1246 handled = TRUE; 1172 handled = TRUE;
1247 return 0; 1173 return 0;
1248 } 1174 }
1249 1175
1250 LRESULT RenderWidgetHostViewWin::OnImeEndComposition( 1176 LRESULT RenderWidgetHostViewWin::OnImeEndComposition(
1251 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { 1177 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1252 if (!render_widget_host_) 1178 if (!render_widget_host_)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 if (!render_widget_host_) 1274 if (!render_widget_host_)
1349 return 0; 1275 return 0;
1350 1276
1351 // Bug 1845: we need to update the text direction when a user releases 1277 // Bug 1845: we need to update the text direction when a user releases
1352 // either a right-shift key or a right-control key after pressing both of 1278 // either a right-shift key or a right-control key after pressing both of
1353 // them. So, we just update the text direction while a user is pressing the 1279 // them. So, we just update the text direction while a user is pressing the
1354 // keys, and we notify the text direction when a user releases either of them. 1280 // keys, and we notify the text direction when a user releases either of them.
1355 // Bug 9718: http://crbug.com/9718 To investigate IE and notepad, this 1281 // Bug 9718: http://crbug.com/9718 To investigate IE and notepad, this
1356 // shortcut is enabled only on a PC having RTL keyboard layouts installed. 1282 // shortcut is enabled only on a PC having RTL keyboard layouts installed.
1357 // We should emulate them. 1283 // We should emulate them.
1358 if (IsRTLKeyboardLayoutInstalled()) { 1284 if (ui::ImeInput::IsRTLKeyboardLayoutInstalled()) {
1359 if (message == WM_KEYDOWN) { 1285 if (message == WM_KEYDOWN) {
1360 if (wparam == VK_SHIFT) { 1286 if (wparam == VK_SHIFT) {
1361 WebTextDirection direction; 1287 base::i18n::TextDirection dir;
1362 if (GetNewTextDirection(&direction)) 1288 if (ui::ImeInput::IsCtrlShiftPressed(&dir)) {
1363 render_widget_host_->UpdateTextDirection(direction); 1289 render_widget_host_->UpdateTextDirection(
1290 dir == base::i18n::RIGHT_TO_LEFT ?
1291 WebKit::WebTextDirectionRightToLeft :
1292 WebKit::WebTextDirectionLeftToRight);
1293 }
1364 } else if (wparam != VK_CONTROL) { 1294 } else if (wparam != VK_CONTROL) {
1365 // Bug 9762: http://crbug.com/9762 A user pressed a key except shift 1295 // Bug 9762: http://crbug.com/9762 A user pressed a key except shift
1366 // and control keys. 1296 // and control keys.
1367 // When a user presses a key while he/she holds control and shift keys, 1297 // When a user presses a key while he/she holds control and shift keys,
1368 // we cancel sending an IPC message in NotifyTextDirection() below and 1298 // we cancel sending an IPC message in NotifyTextDirection() below and
1369 // ignore succeeding UpdateTextDirection() calls while we call 1299 // ignore succeeding UpdateTextDirection() calls while we call
1370 // NotifyTextDirection(). 1300 // NotifyTextDirection().
1371 // To cancel it, this call set a flag that prevents sending an IPC 1301 // To cancel it, this call set a flag that prevents sending an IPC
1372 // message in NotifyTextDirection() only if we are going to send it. 1302 // message in NotifyTextDirection() only if we are going to send it.
1373 // It is harmless to call this function if we aren't going to send it. 1303 // It is harmless to call this function if we aren't going to send it.
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 } 1796 }
1867 1797
1868 // static 1798 // static
1869 RenderWidgetHostView* 1799 RenderWidgetHostView*
1870 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( 1800 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView(
1871 gfx::NativeView native_view) { 1801 gfx::NativeView native_view) {
1872 return ::IsWindow(native_view) ? 1802 return ::IsWindow(native_view) ?
1873 reinterpret_cast<RenderWidgetHostView*>( 1803 reinterpret_cast<RenderWidgetHostView*>(
1874 ViewProp::GetValue(native_view, kRenderWidgetHostViewKey)) : NULL; 1804 ViewProp::GetValue(native_view, kRenderWidgetHostViewKey)) : NULL;
1875 } 1805 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_win.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698