OLD | NEW |
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. |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 // base::MessageLoop::Dispatcher Override. | 231 // base::MessageLoop::Dispatcher Override. |
232 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; | 232 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; |
233 | 233 |
234 // DesktopHost Overrides. | 234 // DesktopHost Overrides. |
235 virtual void SetDesktop(Desktop* desktop) OVERRIDE; | 235 virtual void SetDesktop(Desktop* desktop) OVERRIDE; |
236 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; | 236 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; |
237 virtual void Show() OVERRIDE; | 237 virtual void Show() OVERRIDE; |
238 virtual void ToggleFullScreen() OVERRIDE; | 238 virtual void ToggleFullScreen() OVERRIDE; |
239 virtual gfx::Size GetSize() const OVERRIDE; | 239 virtual gfx::Size GetSize() const OVERRIDE; |
240 virtual void SetSize(const gfx::Size& size) OVERRIDE; | 240 virtual void SetSize(const gfx::Size& size) OVERRIDE; |
| 241 virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; |
241 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; | 242 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
242 virtual gfx::Point QueryMouseLocation() OVERRIDE; | 243 virtual gfx::Point QueryMouseLocation() OVERRIDE; |
243 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; | 244 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; |
244 | 245 |
245 // Returns true if there's an X window manager present... in most cases. Some | 246 // Returns true if there's an X window manager present... in most cases. Some |
246 // window managers (notably, ion3) don't implement enough of ICCCM for us to | 247 // window managers (notably, ion3) don't implement enough of ICCCM for us to |
247 // detect that they're there. | 248 // detect that they're there. |
248 bool IsWindowManagerPresent(); | 249 bool IsWindowManagerPresent(); |
249 | 250 |
250 Desktop* desktop_; | 251 Desktop* desktop_; |
251 | 252 |
252 // The display and the native X window hosting the desktop. | 253 // The display and the native X window hosting the desktop. |
253 Display* xdisplay_; | 254 Display* xdisplay_; |
254 ::Window xwindow_; | 255 ::Window xwindow_; |
255 | 256 |
256 // Current Aura cursor. | 257 // Current Aura cursor. |
257 gfx::NativeCursor current_cursor_; | 258 gfx::NativeCursor current_cursor_; |
258 | 259 |
259 // The size of |xwindow_|. | 260 // The bounds of |xwindow_|. |
260 gfx::Size size_; | 261 gfx::Rect bounds_; |
261 | 262 |
262 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); | 263 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); |
263 }; | 264 }; |
264 | 265 |
265 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) | 266 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
266 : desktop_(NULL), | 267 : desktop_(NULL), |
267 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), | 268 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), |
268 xwindow_(0), | 269 xwindow_(0), |
269 current_cursor_(aura::kCursorNull), | 270 current_cursor_(aura::kCursorNull), |
270 size_(bounds.size()) { | 271 bounds_(bounds) { |
271 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), | 272 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), |
272 bounds.x(), bounds.y(), | 273 bounds.x(), bounds.y(), |
273 bounds.width(), bounds.height(), | 274 bounds.width(), bounds.height(), |
274 0, 0, 0); | 275 0, 0, 0); |
275 | 276 |
276 long event_mask = ButtonPressMask | ButtonReleaseMask | | 277 long event_mask = ButtonPressMask | ButtonReleaseMask | |
277 KeyPressMask | KeyReleaseMask | | 278 KeyPressMask | KeyReleaseMask | |
278 ExposureMask | VisibilityChangeMask | | 279 ExposureMask | VisibilityChangeMask | |
279 StructureNotifyMask | PropertyChangeMask | | 280 StructureNotifyMask | PropertyChangeMask | |
280 PointerMotionMask; | 281 PointerMotionMask; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 break; | 322 break; |
322 } | 323 } |
323 case ConfigureNotify: { | 324 case ConfigureNotify: { |
324 DCHECK_EQ(xdisplay_, xev->xconfigure.display); | 325 DCHECK_EQ(xdisplay_, xev->xconfigure.display); |
325 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 326 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
326 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 327 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
327 | 328 |
328 // It's possible that the X window may be resized by some other means than | 329 // It's possible that the X window may be resized by some other means than |
329 // from within aura (e.g. the X window manager can change the size). Make | 330 // from within aura (e.g. the X window manager can change the size). Make |
330 // sure the desktop size is maintained properly. | 331 // sure the desktop size is maintained properly. |
331 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height); | 332 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
332 if (size_ != size) { | 333 xev->xconfigure.width, xev->xconfigure.height); |
333 size_ = size; | 334 bool size_changed = bounds_.size() != bounds.size(); |
334 desktop_->OnHostResized(size); | 335 bounds_ = bounds; |
335 } | 336 if (size_changed) |
| 337 desktop_->OnHostResized(bounds.size()); |
336 handled = true; | 338 handled = true; |
337 break; | 339 break; |
338 } | 340 } |
339 case GenericEvent: { | 341 case GenericEvent: { |
340 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 342 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
341 if (!factory->ShouldProcessXI2Event(xev)) | 343 if (!factory->ShouldProcessXI2Event(xev)) |
342 break; | 344 break; |
343 | 345 |
344 // If this is a motion event we want to coalesce all pending motion | 346 // If this is a motion event we want to coalesce all pending motion |
345 // events that are at the top of the queue. | 347 // events that are at the top of the queue. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 | 429 |
428 void DesktopHostLinux::Show() { | 430 void DesktopHostLinux::Show() { |
429 XMapWindow(xdisplay_, xwindow_); | 431 XMapWindow(xdisplay_, xwindow_); |
430 } | 432 } |
431 | 433 |
432 void DesktopHostLinux::ToggleFullScreen() { | 434 void DesktopHostLinux::ToggleFullScreen() { |
433 NOTIMPLEMENTED(); | 435 NOTIMPLEMENTED(); |
434 } | 436 } |
435 | 437 |
436 gfx::Size DesktopHostLinux::GetSize() const { | 438 gfx::Size DesktopHostLinux::GetSize() const { |
437 return size_; | 439 return bounds_.size(); |
438 } | 440 } |
439 | 441 |
440 void DesktopHostLinux::SetSize(const gfx::Size& size) { | 442 void DesktopHostLinux::SetSize(const gfx::Size& size) { |
441 if (size == size_) | 443 if (size == bounds_.size()) |
442 return; | 444 return; |
443 | 445 |
444 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); | 446 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
445 | 447 |
446 // Assume that the resize will go through as requested, which should be the | 448 // Assume that the resize will go through as requested, which should be the |
447 // case if we're running without a window manager. If there's a window | 449 // case if we're running without a window manager. If there's a window |
448 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 450 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
449 // (possibly synthetic) ConfigureNotify about the actual size and correct | 451 // (possibly synthetic) ConfigureNotify about the actual size and correct |
450 // |size_| later. | 452 // |bounds_| later. |
451 size_ = size; | 453 bounds_.set_size(size); |
452 desktop_->OnHostResized(size); | 454 desktop_->OnHostResized(size); |
453 } | 455 } |
454 | 456 |
| 457 gfx::Point DesktopHostLinux::GetLocationOnNativeScreen() const { |
| 458 return bounds_.origin(); |
| 459 } |
| 460 |
455 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { | 461 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { |
456 if (current_cursor_ == cursor) | 462 if (current_cursor_ == cursor) |
457 return; | 463 return; |
458 current_cursor_ = cursor; | 464 current_cursor_ = cursor; |
459 // Custom web cursors are handled directly. | 465 // Custom web cursors are handled directly. |
460 if (cursor == kCursorCustom) | 466 if (cursor == kCursorCustom) |
461 return; | 467 return; |
462 int cursor_shape = CursorShapeFromNative(cursor); | 468 int cursor_shape = CursorShapeFromNative(cursor); |
463 ::Cursor xcursor = ui::GetXCursor(cursor_shape); | 469 ::Cursor xcursor = ui::GetXCursor(cursor_shape); |
464 XDefineCursor(xdisplay_, xwindow_, xcursor); | 470 XDefineCursor(xdisplay_, xwindow_, xcursor); |
465 } | 471 } |
466 | 472 |
467 gfx::Point DesktopHostLinux::QueryMouseLocation() { | 473 gfx::Point DesktopHostLinux::QueryMouseLocation() { |
468 ::Window root_return, child_return; | 474 ::Window root_return, child_return; |
469 int root_x_return, root_y_return, win_x_return, win_y_return; | 475 int root_x_return, root_y_return, win_x_return, win_y_return; |
470 unsigned int mask_return; | 476 unsigned int mask_return; |
471 XQueryPointer(xdisplay_, | 477 XQueryPointer(xdisplay_, |
472 xwindow_, | 478 xwindow_, |
473 &root_return, | 479 &root_return, |
474 &child_return, | 480 &child_return, |
475 &root_x_return, &root_y_return, | 481 &root_x_return, &root_y_return, |
476 &win_x_return, &win_y_return, | 482 &win_x_return, &win_y_return, |
477 &mask_return); | 483 &mask_return); |
478 return gfx::Point(max(0, min(size_.width(), win_x_return)), | 484 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), |
479 max(0, min(size_.height(), win_y_return))); | 485 max(0, min(bounds_.height(), win_y_return))); |
480 } | 486 } |
481 | 487 |
482 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { | 488 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { |
483 DCHECK(xwindow_); | 489 DCHECK(xwindow_); |
484 DCHECK(xdisplay_); | 490 DCHECK(xdisplay_); |
485 XEvent xevent = *native_event; | 491 XEvent xevent = *native_event; |
486 xevent.xany.display = xdisplay_; | 492 xevent.xany.display = xdisplay_; |
487 xevent.xany.window = xwindow_; | 493 xevent.xany.window = xwindow_; |
488 ::XPutBackEvent(xdisplay_, &xevent); | 494 |
| 495 switch (xevent.type) { |
| 496 case EnterNotify: |
| 497 case LeaveNotify: |
| 498 case MotionNotify: |
| 499 case KeyPress: |
| 500 case KeyRelease: |
| 501 case ButtonPress: |
| 502 case ButtonRelease: { |
| 503 // The fields used below are in the same place for all of events |
| 504 // above. Using xmotion from XEvent's unions to avoid repeating |
| 505 // the code. |
| 506 xevent.xmotion.root = DefaultRootWindow(xdisplay_); |
| 507 xevent.xmotion.time = CurrentTime; |
| 508 |
| 509 gfx::Point point(xevent.xmotion.x, xevent.xmotion.y); |
| 510 desktop_->ConvertPointToNativeScreen(&point); |
| 511 xevent.xmotion.x_root = point.x(); |
| 512 xevent.xmotion.y_root = point.y(); |
| 513 } |
| 514 default: |
| 515 break; |
| 516 } |
| 517 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); |
489 } | 518 } |
490 | 519 |
491 bool DesktopHostLinux::IsWindowManagerPresent() { | 520 bool DesktopHostLinux::IsWindowManagerPresent() { |
492 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 521 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
493 // of WM_Sn selections (where n is a screen number). | 522 // of WM_Sn selections (where n is a screen number). |
494 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); | 523 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); |
495 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; | 524 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
496 } | 525 } |
497 | 526 |
498 } // namespace | 527 } // namespace |
499 | 528 |
500 // static | 529 // static |
501 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { | 530 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { |
502 return new DesktopHostLinux(bounds); | 531 return new DesktopHostLinux(bounds); |
503 } | 532 } |
504 | 533 |
505 // static | 534 // static |
506 gfx::Size DesktopHost::GetNativeDisplaySize() { | 535 gfx::Size DesktopHost::GetNativeDisplaySize() { |
507 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); | 536 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); |
508 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 537 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
509 } | 538 } |
510 | 539 |
511 } // namespace aura | 540 } // namespace aura |
OLD | NEW |