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

Side by Side Diff: ui/aura/desktop_host_linux.cc

Issue 8576005: IME (input method editor) support for Aura, part 3 of 3: Use ui::InputMethod in ash. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: git mv desktop_host_unittest.cc desktop_host_ime_unittest.cc Created 9 years 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
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 "ui/aura/desktop_host.h" 5 #include "ui/aura/desktop_host.h"
6 6
7 #include <X11/cursorfont.h> 7 #include <X11/cursorfont.h>
8 #include <X11/Xlib.h> 8 #include <X11/Xlib.h>
9 9
10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. 10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
11 #undef RootWindow 11 #undef RootWindow
12 12
13 #include <algorithm> 13 #include <algorithm>
14 14
15 #include "base/event_types.h"
16 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop.h" 17 #include "base/message_loop.h"
16 #include "base/message_pump_x.h" 18 #include "base/message_pump_x.h"
17 #include "ui/aura/cursor.h" 19 #include "ui/aura/cursor.h"
18 #include "ui/aura/desktop.h" 20 #include "ui/aura/desktop.h"
19 #include "ui/aura/event.h" 21 #include "ui/aura/event.h"
20 #include "ui/base/keycodes/keyboard_codes.h" 22 #include "ui/base/keycodes/keyboard_codes.h"
21 #include "ui/base/touch/touch_factory.h" 23 #include "ui/base/touch/touch_factory.h"
22 #include "ui/base/x/x11_util.h" 24 #include "ui/base/x/x11_util.h"
23 #include "ui/gfx/compositor/layer.h" 25 #include "ui/gfx/compositor/layer.h"
24 26
25 #include <X11/cursorfont.h> 27 #include <X11/cursorfont.h>
26 #include <X11/extensions/XInput2.h> 28 #include <X11/extensions/XInput2.h>
27 #include <X11/Xlib.h> 29 #include <X11/Xlib.h>
28 30
31 #if defined(HAVE_IBUS)
32 #include "ui/base/ime/input_method_ibus.h"
33 #else
34 #include "ui/base/ime/mock_input_method.h"
35 #endif
36
29 using std::max; 37 using std::max;
30 using std::min; 38 using std::min;
31 39
32 namespace aura { 40 namespace aura {
33 41
34 namespace { 42 namespace {
35 43
36 // Returns X font cursor shape from an Aura cursor. 44 // Returns X font cursor shape from an Aura cursor.
37 int CursorShapeFromNative(gfx::NativeCursor native_cursor) { 45 int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
38 switch (native_cursor) { 46 switch (native_cursor) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } else { 182 } else {
175 // This isn't an event we want so free its cookie data. 183 // This isn't an event we want so free its cookie data.
176 XFreeEventData(display, &next_event.xcookie); 184 XFreeEventData(display, &next_event.xcookie);
177 } 185 }
178 } 186 }
179 break; 187 break;
180 } 188 }
181 return num_coalesed; 189 return num_coalesed;
182 } 190 }
183 191
184 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only
185 // generated for certain keys; see
186 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx.
187 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
188 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) ||
189 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) ||
190 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) {
191 return true;
192 }
193
194 switch (keycode) {
195 case ui::VKEY_BACK:
196 case ui::VKEY_RETURN:
197 case ui::VKEY_ESCAPE:
198 case ui::VKEY_SPACE:
199 case ui::VKEY_TAB:
200 // In addition to the keys listed at MSDN, we include other
201 // graphic-character and numpad keys.
202 case ui::VKEY_MULTIPLY:
203 case ui::VKEY_ADD:
204 case ui::VKEY_SUBTRACT:
205 case ui::VKEY_DECIMAL:
206 case ui::VKEY_DIVIDE:
207 case ui::VKEY_OEM_1:
208 case ui::VKEY_OEM_2:
209 case ui::VKEY_OEM_3:
210 case ui::VKEY_OEM_4:
211 case ui::VKEY_OEM_5:
212 case ui::VKEY_OEM_6:
213 case ui::VKEY_OEM_7:
214 case ui::VKEY_OEM_102:
215 case ui::VKEY_OEM_PLUS:
216 case ui::VKEY_OEM_COMMA:
217 case ui::VKEY_OEM_MINUS:
218 case ui::VKEY_OEM_PERIOD:
219 return true;
220 default:
221 return false;
222 }
223 }
224
225 class DesktopHostLinux : public DesktopHost { 192 class DesktopHostLinux : public DesktopHost {
226 public: 193 public:
227 explicit DesktopHostLinux(const gfx::Rect& bounds); 194 explicit DesktopHostLinux(const gfx::Rect& bounds);
228 virtual ~DesktopHostLinux(); 195 virtual ~DesktopHostLinux();
229 196
230 private: 197 private:
231 // base::MessageLoop::Dispatcher Override. 198 // base::MessageLoop::Dispatcher Override.
232 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; 199 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE;
233 200
234 // DesktopHost Overrides. 201 // DesktopHost Overrides.
235 virtual void SetDesktop(Desktop* desktop) OVERRIDE; 202 virtual void SetDesktop(Desktop* desktop) OVERRIDE;
236 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; 203 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
237 virtual void Show() OVERRIDE; 204 virtual void Show() OVERRIDE;
238 virtual void ToggleFullScreen() OVERRIDE; 205 virtual void ToggleFullScreen() OVERRIDE;
239 virtual gfx::Size GetSize() const OVERRIDE; 206 virtual gfx::Size GetSize() const OVERRIDE;
240 virtual void SetSize(const gfx::Size& size) OVERRIDE; 207 virtual void SetSize(const gfx::Size& size) OVERRIDE;
241 virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; 208 virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
242 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; 209 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
243 virtual gfx::Point QueryMouseLocation() OVERRIDE; 210 virtual gfx::Point QueryMouseLocation() OVERRIDE;
244 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; 211 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
212 virtual void SetInputMethod(ui::InputMethod*) OVERRIDE;
213 virtual ui::InputMethod* GetInputMethod() const OVERRIDE;
214
215 // ui::internal::InputMethodDelegate Override.
216 virtual void DispatchKeyEventPostIME(const base::NativeEvent& event) OVERRIDE;
217 virtual void DispatchFabricatedKeyEventPostIME(
218 ui::EventType type, ui::KeyboardCode key_code, int flags) OVERRIDE;
sky 2011/12/01 17:01:09 each param on its own line.
Yusuke Sato 2011/12/02 02:18:31 Done.
245 219
246 // Returns true if there's an X window manager present... in most cases. Some 220 // Returns true if there's an X window manager present... in most cases. Some
247 // window managers (notably, ion3) don't implement enough of ICCCM for us to 221 // window managers (notably, ion3) don't implement enough of ICCCM for us to
248 // detect that they're there. 222 // detect that they're there.
249 bool IsWindowManagerPresent(); 223 bool IsWindowManagerPresent();
250 224
251 Desktop* desktop_; 225 Desktop* desktop_;
252 226
253 // The display and the native X window hosting the desktop. 227 // The display and the native X window hosting the desktop.
254 Display* xdisplay_; 228 Display* xdisplay_;
255 ::Window xwindow_; 229 ::Window xwindow_;
256 230
257 // The native root window. 231 // The native root window.
258 ::Window root_window_; 232 ::Window root_window_;
259 233
234 // The input method for the desktop.
235 scoped_ptr<ui::InputMethod> input_method_;
236
260 // Current Aura cursor. 237 // Current Aura cursor.
261 gfx::NativeCursor current_cursor_; 238 gfx::NativeCursor current_cursor_;
262 239
263 // The bounds of |xwindow_|. 240 // The bounds of |xwindow_|.
264 gfx::Rect bounds_; 241 gfx::Rect bounds_;
265 242
266 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); 243 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux);
267 }; 244 };
268 245
269 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) 246 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds)
270 : desktop_(NULL), 247 : desktop_(NULL),
271 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), 248 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
272 xwindow_(0), 249 xwindow_(0),
273 root_window_(DefaultRootWindow(xdisplay_)), 250 root_window_(DefaultRootWindow(xdisplay_)),
251 #if defined(HAVE_IBUS)
252 ALLOW_THIS_IN_INITIALIZER_LIST(
253 input_method_(new ui::InputMethodIBus(this))),
254 #else
255 ALLOW_THIS_IN_INITIALIZER_LIST(
256 input_method_(new ui::MockInputMethod(this))),
257 #endif
258
274 current_cursor_(aura::kCursorNull), 259 current_cursor_(aura::kCursorNull),
275 bounds_(bounds) { 260 bounds_(bounds) {
276 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_, 261 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_,
277 bounds.x(), bounds.y(), 262 bounds.x(), bounds.y(),
278 bounds.width(), bounds.height(), 263 bounds.width(), bounds.height(),
279 0, 0, 0); 264 0, 0, 0);
280 265
281 long event_mask = ButtonPressMask | ButtonReleaseMask | 266 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
282 KeyPressMask | KeyReleaseMask | 267 KeyPressMask | KeyReleaseMask |
283 ExposureMask | VisibilityChangeMask | 268 ExposureMask | VisibilityChangeMask |
284 StructureNotifyMask | PropertyChangeMask | 269 StructureNotifyMask | PropertyChangeMask |
285 PointerMotionMask; 270 PointerMotionMask;
286 XSelectInput(xdisplay_, xwindow_, event_mask); 271 XSelectInput(xdisplay_, xwindow_, event_mask);
287 XSelectInput(xdisplay_, root_window_, StructureNotifyMask); 272 XSelectInput(xdisplay_, root_window_, StructureNotifyMask);
288 XFlush(xdisplay_); 273 XFlush(xdisplay_);
289 274
290 // TODO(sadrul): reenable once 103981 is fixed. 275 // TODO(sadrul): reenable once 103981 is fixed.
291 #if defined(TOUCH_UI) 276 #if defined(TOUCH_UI)
292 if (base::MessagePumpForUI::HasXInput2()) 277 if (base::MessagePumpForUI::HasXInput2())
293 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); 278 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
294 #endif 279 #endif
280
281 input_method_->Init(xwindow_);
295 } 282 }
296 283
297 DesktopHostLinux::~DesktopHostLinux() { 284 DesktopHostLinux::~DesktopHostLinux() {
298 XDestroyWindow(xdisplay_, xwindow_); 285 XDestroyWindow(xdisplay_, xwindow_);
299 286
300 // Clears XCursorCache. 287 // Clears XCursorCache.
301 ui::GetXCursor(ui::kCursorClearXCursorCache); 288 ui::GetXCursor(ui::kCursorClearXCursorCache);
302 } 289 }
303 290
304 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( 291 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
305 XEvent* xev) { 292 XEvent* xev) {
306 DLOG(WARNING) << "DispatchEvent:" << xev->type; 293 DLOG(WARNING) << "DispatchEvent:" << xev->type;
307 294
308 bool handled = false; 295 bool handled = false;
309 switch (xev->type) { 296 switch (xev->type) {
310 case Expose: 297 case Expose:
311 desktop_->Draw(); 298 desktop_->Draw();
312 handled = true; 299 handled = true;
313 break; 300 break;
314 case KeyPress: { 301 case KeyPress:
315 KeyEvent keydown_event(xev, false);
316 handled = desktop_->DispatchKeyEvent(&keydown_event);
317 if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) {
318 KeyEvent char_event(xev, true);
319 handled |= desktop_->DispatchKeyEvent(&char_event);
320 }
321 break;
322 }
323 case KeyRelease: { 302 case KeyRelease: {
324 KeyEvent keyup_event(xev, false); 303 input_method_->DispatchKeyEvent(xev);
325 handled = desktop_->DispatchKeyEvent(&keyup_event); 304 handled = true;
326 break;
327 } 305 }
328 case ButtonPress: 306 case ButtonPress:
329 case ButtonRelease: { 307 case ButtonRelease: {
330 MouseEvent mouseev(xev); 308 MouseEvent mouseev(xev);
331 handled = desktop_->DispatchMouseEvent(&mouseev); 309 handled = desktop_->DispatchMouseEvent(&mouseev);
332 break; 310 break;
333 } 311 }
334 case ConfigureNotify: { 312 case ConfigureNotify: {
335 if (xev->xconfigure.window == root_window_) { 313 if (xev->xconfigure.window == root_window_) {
336 desktop_->OnNativeScreenResized( 314 desktop_->OnNativeScreenResized(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 break; 372 break;
395 default: 373 default:
396 NOTREACHED(); 374 NOTREACHED();
397 } 375 }
398 376
399 // If we coalesced an event we need to free its cookie. 377 // If we coalesced an event we need to free its cookie.
400 if (num_coalesced > 0) 378 if (num_coalesced > 0)
401 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); 379 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
402 break; 380 break;
403 } 381 }
382 case FocusIn: {
383 input_method_->OnFocus();
384 break;
385 }
386 case FocusOut: {
387 input_method_->OnBlur();
388 break;
389 }
404 case MapNotify: { 390 case MapNotify: {
405 // If there's no window manager running, we need to assign the X input 391 // If there's no window manager running, we need to assign the X input
406 // focus to our host window. 392 // focus to our host window.
407 if (!IsWindowManagerPresent()) 393 if (!IsWindowManagerPresent())
408 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); 394 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
409 handled = true; 395 handled = true;
410 break; 396 break;
411 } 397 }
412 case MotionNotify: { 398 case MotionNotify: {
413 // Discard all but the most recent motion event that targets the same 399 // Discard all but the most recent motion event that targets the same
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 DLOG(WARNING) << "PostEvent:" << xevent.type << ", status=" << status; 520 DLOG(WARNING) << "PostEvent:" << xevent.type << ", status=" << status;
535 } 521 }
536 522
537 bool DesktopHostLinux::IsWindowManagerPresent() { 523 bool DesktopHostLinux::IsWindowManagerPresent() {
538 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 524 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
539 // of WM_Sn selections (where n is a screen number). 525 // of WM_Sn selections (where n is a screen number).
540 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); 526 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False);
541 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; 527 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None;
542 } 528 }
543 529
530 void DesktopHostLinux::SetInputMethod(ui::InputMethod* input_method) {
531 input_method_.reset(input_method);
532 }
533
534 ui::InputMethod* DesktopHostLinux::GetInputMethod() const {
535 return input_method_.get();
536 }
537
538 void DesktopHostLinux::DispatchKeyEventPostIME(const base::NativeEvent& event) {
539 KeyEvent aura_event(event, false /* is_char */);
540 desktop_->DispatchKeyEvent(&aura_event);
541 // We don't send a Char event here since the input method takes care of it.
542 }
543
544 void DesktopHostLinux::DispatchFabricatedKeyEventPostIME(
545 ui::EventType type, ui::KeyboardCode key_code, int flags) {
546 // Dispatch a ui::VKEY_PROCESSKEY event etc. generated by |input_method_|.
547 KeyEvent aura_event(type, key_code, flags);
548 desktop_->DispatchKeyEvent(&aura_event);
549 }
550
544 } // namespace 551 } // namespace
545 552
546 // static 553 // static
547 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { 554 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
548 return new DesktopHostLinux(bounds); 555 return new DesktopHostLinux(bounds);
549 } 556 }
550 557
551 // static 558 // static
552 gfx::Size DesktopHost::GetNativeScreenSize() { 559 gfx::Size DesktopHost::GetNativeScreenSize() {
553 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); 560 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
554 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 561 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
555 } 562 }
556 563
557 } // namespace aura 564 } // namespace aura
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698