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

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

Issue 8824007: Revert 113224 - IME (input method editor) support for Aura, part 3 of 3: Use ui::InputMethod in u... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: 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
« no previous file with comments | « ui/aura/desktop_host_ime_unittest.cc ('k') | ui/aura/desktop_host_win.h » ('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 "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"
17 #include "base/message_loop.h" 15 #include "base/message_loop.h"
18 #include "base/message_pump_x.h" 16 #include "base/message_pump_x.h"
19 #include "ui/aura/cursor.h" 17 #include "ui/aura/cursor.h"
20 #include "ui/aura/desktop.h" 18 #include "ui/aura/desktop.h"
21 #include "ui/aura/event.h" 19 #include "ui/aura/event.h"
22 #include "ui/base/keycodes/keyboard_codes.h" 20 #include "ui/base/keycodes/keyboard_codes.h"
23 #include "ui/base/touch/touch_factory.h" 21 #include "ui/base/touch/touch_factory.h"
24 #include "ui/base/x/x11_util.h" 22 #include "ui/base/x/x11_util.h"
25 #include "ui/gfx/compositor/layer.h" 23 #include "ui/gfx/compositor/layer.h"
26 24
27 #include <X11/cursorfont.h> 25 #include <X11/cursorfont.h>
28 #include <X11/extensions/XInput2.h> 26 #include <X11/extensions/XInput2.h>
29 #include <X11/Xlib.h> 27 #include <X11/Xlib.h>
30 28
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
37 using std::max; 29 using std::max;
38 using std::min; 30 using std::min;
39 31
40 namespace aura { 32 namespace aura {
41 33
42 namespace { 34 namespace {
43 35
44 // The events reported for slave devices can have incorrect information for some 36 // The events reported for slave devices can have incorrect information for some
45 // fields. This utility function is used to check for such inconsistencies. 37 // fields. This utility function is used to check for such inconsistencies.
46 void CheckXEventForConsistency(XEvent* xevent) { 38 void CheckXEventForConsistency(XEvent* xevent) {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 } else { 223 } else {
232 // This isn't an event we want so free its cookie data. 224 // This isn't an event we want so free its cookie data.
233 XFreeEventData(display, &next_event.xcookie); 225 XFreeEventData(display, &next_event.xcookie);
234 } 226 }
235 } 227 }
236 break; 228 break;
237 } 229 }
238 return num_coalesed; 230 return num_coalesed;
239 } 231 }
240 232
233 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages. WM_CHAR events are only
234 // generated for certain keys; see
235 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx.
236 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
237 if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) ||
238 (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) ||
239 (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) {
240 return true;
241 }
242
243 switch (keycode) {
244 case ui::VKEY_BACK:
245 case ui::VKEY_RETURN:
246 case ui::VKEY_ESCAPE:
247 case ui::VKEY_SPACE:
248 case ui::VKEY_TAB:
249 // In addition to the keys listed at MSDN, we include other
250 // graphic-character and numpad keys.
251 case ui::VKEY_MULTIPLY:
252 case ui::VKEY_ADD:
253 case ui::VKEY_SUBTRACT:
254 case ui::VKEY_DECIMAL:
255 case ui::VKEY_DIVIDE:
256 case ui::VKEY_OEM_1:
257 case ui::VKEY_OEM_2:
258 case ui::VKEY_OEM_3:
259 case ui::VKEY_OEM_4:
260 case ui::VKEY_OEM_5:
261 case ui::VKEY_OEM_6:
262 case ui::VKEY_OEM_7:
263 case ui::VKEY_OEM_102:
264 case ui::VKEY_OEM_PLUS:
265 case ui::VKEY_OEM_COMMA:
266 case ui::VKEY_OEM_MINUS:
267 case ui::VKEY_OEM_PERIOD:
268 return true;
269 default:
270 return false;
271 }
272 }
273
241 class DesktopHostLinux : public DesktopHost, 274 class DesktopHostLinux : public DesktopHost,
242 public MessageLoop::DestructionObserver { 275 public MessageLoop::DestructionObserver {
243 public: 276 public:
244 explicit DesktopHostLinux(const gfx::Rect& bounds); 277 explicit DesktopHostLinux(const gfx::Rect& bounds);
245 virtual ~DesktopHostLinux(); 278 virtual ~DesktopHostLinux();
246 279
247 private: 280 private:
248 // MessageLoop::Dispatcher Override. 281 // MessageLoop::Dispatcher Override.
249 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; 282 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE;
250 283
251 // DesktopHost Overrides. 284 // DesktopHost Overrides.
252 virtual void SetDesktop(Desktop* desktop) OVERRIDE; 285 virtual void SetDesktop(Desktop* desktop) OVERRIDE;
253 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; 286 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
254 virtual void Show() OVERRIDE; 287 virtual void Show() OVERRIDE;
255 virtual void ToggleFullScreen() OVERRIDE; 288 virtual void ToggleFullScreen() OVERRIDE;
256 virtual gfx::Size GetSize() const OVERRIDE; 289 virtual gfx::Size GetSize() const OVERRIDE;
257 virtual void SetSize(const gfx::Size& size) OVERRIDE; 290 virtual void SetSize(const gfx::Size& size) OVERRIDE;
258 virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; 291 virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
259 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; 292 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
260 virtual gfx::Point QueryMouseLocation() OVERRIDE; 293 virtual gfx::Point QueryMouseLocation() OVERRIDE;
261 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; 294 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
262 virtual void SetInputMethod(ui::InputMethod*) OVERRIDE;
263 virtual ui::InputMethod* GetInputMethod() const OVERRIDE;
264
265 // ui::internal::InputMethodDelegate Override.
266 virtual void DispatchKeyEventPostIME(const base::NativeEvent& event) OVERRIDE;
267 virtual void DispatchFabricatedKeyEventPostIME(ui::EventType type,
268 ui::KeyboardCode key_code,
269 int flags) OVERRIDE;
270 295
271 // MessageLoop::DestructionObserver Overrides. 296 // MessageLoop::DestructionObserver Overrides.
272 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 297 virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
273 298
274 // Returns true if there's an X window manager present... in most cases. Some 299 // Returns true if there's an X window manager present... in most cases. Some
275 // window managers (notably, ion3) don't implement enough of ICCCM for us to 300 // window managers (notably, ion3) don't implement enough of ICCCM for us to
276 // detect that they're there. 301 // detect that they're there.
277 bool IsWindowManagerPresent(); 302 bool IsWindowManagerPresent();
278 303
279 Desktop* desktop_; 304 Desktop* desktop_;
280 305
281 // The display and the native X window hosting the desktop. 306 // The display and the native X window hosting the desktop.
282 Display* xdisplay_; 307 Display* xdisplay_;
283 ::Window xwindow_; 308 ::Window xwindow_;
284 309
285 // The native root window. 310 // The native root window.
286 ::Window root_window_; 311 ::Window root_window_;
287 312
288 // The input method for the desktop.
289 scoped_ptr<ui::InputMethod> input_method_;
290
291 // Current Aura cursor. 313 // Current Aura cursor.
292 gfx::NativeCursor current_cursor_; 314 gfx::NativeCursor current_cursor_;
293 315
294 // The bounds of |xwindow_|. 316 // The bounds of |xwindow_|.
295 gfx::Rect bounds_; 317 gfx::Rect bounds_;
296 318
297 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); 319 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux);
298 }; 320 };
299 321
300 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) 322 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds)
301 : desktop_(NULL), 323 : desktop_(NULL),
302 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), 324 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
303 xwindow_(0), 325 xwindow_(0),
304 root_window_(DefaultRootWindow(xdisplay_)), 326 root_window_(DefaultRootWindow(xdisplay_)),
305 #if defined(HAVE_IBUS)
306 ALLOW_THIS_IN_INITIALIZER_LIST(
307 input_method_(new ui::InputMethodIBus(this))),
308 #else
309 ALLOW_THIS_IN_INITIALIZER_LIST(
310 input_method_(new ui::MockInputMethod(this))),
311 #endif
312
313 current_cursor_(aura::kCursorNull), 327 current_cursor_(aura::kCursorNull),
314 bounds_(bounds) { 328 bounds_(bounds) {
315 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_, 329 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_,
316 bounds.x(), bounds.y(), 330 bounds.x(), bounds.y(),
317 bounds.width(), bounds.height(), 331 bounds.width(), bounds.height(),
318 0, 0, 0); 332 0, 0, 0);
319 333
320 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | 334 long event_mask = ButtonPressMask | ButtonReleaseMask |
321 KeyPressMask | KeyReleaseMask | 335 KeyPressMask | KeyReleaseMask |
322 EnterWindowMask | LeaveWindowMask | 336 EnterWindowMask | LeaveWindowMask |
323 ExposureMask | VisibilityChangeMask | 337 ExposureMask | VisibilityChangeMask |
324 StructureNotifyMask | PropertyChangeMask | 338 StructureNotifyMask | PropertyChangeMask |
325 PointerMotionMask; 339 PointerMotionMask;
326 XSelectInput(xdisplay_, xwindow_, event_mask); 340 XSelectInput(xdisplay_, xwindow_, event_mask);
327 XSelectInput(xdisplay_, root_window_, StructureNotifyMask); 341 XSelectInput(xdisplay_, root_window_, StructureNotifyMask);
328 XFlush(xdisplay_); 342 XFlush(xdisplay_);
329 343
330 // TODO(sad): Re-enable once crbug.com/106516 is fixed. 344 // TODO(sad): Re-enable once crbug.com/106516 is fixed.
331 #if 0 345 #if 0
332 if (base::MessagePumpForUI::HasXInput2()) 346 if (base::MessagePumpForUI::HasXInput2())
333 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); 347 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
334 #endif 348 #endif
335 349
336 base::MessagePumpX::SetDefaultDispatcher(this); 350 base::MessagePumpX::SetDefaultDispatcher(this);
337 MessageLoopForUI::current()->AddDestructionObserver(this); 351 MessageLoopForUI::current()->AddDestructionObserver(this);
338
339 ::Window focused_window = None;
340 int revert_to = 0;
341 XGetInputFocus(xdisplay_, &focused_window, &revert_to);
342 input_method_->Init(focused_window == xwindow_);
343 } 352 }
344 353
345 DesktopHostLinux::~DesktopHostLinux() { 354 DesktopHostLinux::~DesktopHostLinux() {
346 XDestroyWindow(xdisplay_, xwindow_); 355 XDestroyWindow(xdisplay_, xwindow_);
347 356
348 // Clears XCursorCache. 357 // Clears XCursorCache.
349 ui::GetXCursor(ui::kCursorClearXCursorCache); 358 ui::GetXCursor(ui::kCursorClearXCursorCache);
350 359
351 MessageLoopForUI::current()->RemoveDestructionObserver(this); 360 MessageLoopForUI::current()->RemoveDestructionObserver(this);
352 base::MessagePumpX::SetDefaultDispatcher(NULL); 361 base::MessagePumpX::SetDefaultDispatcher(NULL);
353 } 362 }
354 363
355 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( 364 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
356 XEvent* xev) { 365 XEvent* xev) {
357 bool handled = false; 366 bool handled = false;
358 367
359 CheckXEventForConsistency(xev); 368 CheckXEventForConsistency(xev);
360 369
361 switch (xev->type) { 370 switch (xev->type) {
362 case Expose: 371 case Expose:
363 desktop_->ScheduleDraw(); 372 desktop_->ScheduleDraw();
364 handled = true; 373 handled = true;
365 break; 374 break;
366 case KeyPress: 375 case KeyPress: {
376 KeyEvent keydown_event(xev, false);
377 handled = desktop_->DispatchKeyEvent(&keydown_event);
378 if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) {
379 KeyEvent char_event(xev, true);
380 handled |= desktop_->DispatchKeyEvent(&char_event);
381 }
382 break;
383 }
367 case KeyRelease: { 384 case KeyRelease: {
368 input_method_->DispatchKeyEvent(xev); 385 KeyEvent keyup_event(xev, false);
369 handled = true; 386 handled = desktop_->DispatchKeyEvent(&keyup_event);
387 break;
370 } 388 }
371 case ButtonPress: 389 case ButtonPress:
372 case ButtonRelease: { 390 case ButtonRelease: {
373 MouseEvent mouseev(xev); 391 MouseEvent mouseev(xev);
374 handled = desktop_->DispatchMouseEvent(&mouseev); 392 handled = desktop_->DispatchMouseEvent(&mouseev);
375 break; 393 break;
376 } 394 }
377 case ConfigureNotify: { 395 case ConfigureNotify: {
378 if (xev->xconfigure.window == root_window_) { 396 if (xev->xconfigure.window == root_window_) {
379 desktop_->OnNativeScreenResized( 397 desktop_->OnNativeScreenResized(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 break; 455 break;
438 default: 456 default:
439 NOTREACHED(); 457 NOTREACHED();
440 } 458 }
441 459
442 // If we coalesced an event we need to free its cookie. 460 // If we coalesced an event we need to free its cookie.
443 if (num_coalesced > 0) 461 if (num_coalesced > 0)
444 XFreeEventData(xev->xgeneric.display, &last_event.xcookie); 462 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
445 break; 463 break;
446 } 464 }
447 case FocusIn: {
448 input_method_->OnFocus();
449 break;
450 }
451 case FocusOut: {
452 input_method_->OnBlur();
453 break;
454 }
455 case MapNotify: { 465 case MapNotify: {
456 // If there's no window manager running, we need to assign the X input 466 // If there's no window manager running, we need to assign the X input
457 // focus to our host window. 467 // focus to our host window.
458 if (!IsWindowManagerPresent()) 468 if (!IsWindowManagerPresent())
459 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); 469 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
460 handled = true; 470 handled = true;
461 break; 471 break;
462 } 472 }
463 case MappingNotify: { 473 case MappingNotify: {
464 if (xev->xmapping.request == MappingModifier || 474 if (xev->xmapping.request == MappingModifier ||
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 aura::Desktop::DeleteInstance(); 604 aura::Desktop::DeleteInstance();
595 } 605 }
596 606
597 bool DesktopHostLinux::IsWindowManagerPresent() { 607 bool DesktopHostLinux::IsWindowManagerPresent() {
598 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 608 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
599 // of WM_Sn selections (where n is a screen number). 609 // of WM_Sn selections (where n is a screen number).
600 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); 610 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False);
601 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; 611 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None;
602 } 612 }
603 613
604 void DesktopHostLinux::SetInputMethod(ui::InputMethod* input_method) {
605 input_method_.reset(input_method);
606 }
607
608 ui::InputMethod* DesktopHostLinux::GetInputMethod() const {
609 return input_method_.get();
610 }
611
612 void DesktopHostLinux::DispatchKeyEventPostIME(const base::NativeEvent& event) {
613 KeyEvent aura_event(event, false /* is_char */);
614 desktop_->DispatchKeyEvent(&aura_event);
615 // We don't send a Char event here since the input method takes care of it.
616 }
617
618 void DesktopHostLinux::DispatchFabricatedKeyEventPostIME(
619 ui::EventType type, ui::KeyboardCode key_code, int flags) {
620 // Dispatch a ui::VKEY_PROCESSKEY event etc. generated by |input_method_|.
621 KeyEvent aura_event(type, key_code, flags);
622 desktop_->DispatchKeyEvent(&aura_event);
623 }
624
625 } // namespace 614 } // namespace
626 615
627 // static 616 // static
628 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { 617 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) {
629 return new DesktopHostLinux(bounds); 618 return new DesktopHostLinux(bounds);
630 } 619 }
631 620
632 // static 621 // static
633 gfx::Size DesktopHost::GetNativeScreenSize() { 622 gfx::Size DesktopHost::GetNativeScreenSize() {
634 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); 623 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay();
635 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 624 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
636 } 625 }
637 626
638 } // namespace aura 627 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/desktop_host_ime_unittest.cc ('k') | ui/aura/desktop_host_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698