| OLD | NEW |
| 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/aura/root_window_host_linux.h" | 5 #include "ui/aura/root_window_host_linux.h" |
| 6 | 6 |
| 7 #include <X11/cursorfont.h> | 7 #include <X11/cursorfont.h> |
| 8 #include <X11/extensions/Xfixes.h> | 8 #include <X11/extensions/Xfixes.h> |
| 9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
| 10 #include <X11/extensions/Xrandr.h> | 10 #include <X11/extensions/Xrandr.h> |
| 11 #include <X11/Xatom.h> | 11 #include <X11/Xatom.h> |
| 12 #include <X11/Xcursor/Xcursor.h> | 12 #include <X11/Xcursor/Xcursor.h> |
| 13 #include <X11/Xlib.h> | 13 #include <X11/Xlib.h> |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 | 15 |
| 16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 17 #include "base/message_pump_aurax11.h" | 17 #include "base/message_pump_aurax11.h" |
| 18 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 19 #include "base/stringprintf.h" | 19 #include "base/stringprintf.h" |
| 20 #include "grit/ui_resources.h" | |
| 21 #include "ui/aura/client/capture_client.h" | 20 #include "ui/aura/client/capture_client.h" |
| 21 #include "ui/aura/client/cursor_client.h" |
| 22 #include "ui/aura/client/screen_position_client.h" | 22 #include "ui/aura/client/screen_position_client.h" |
| 23 #include "ui/aura/client/user_action_client.h" | 23 #include "ui/aura/client/user_action_client.h" |
| 24 #include "ui/aura/env.h" | 24 #include "ui/aura/env.h" |
| 25 #include "ui/aura/root_window.h" | 25 #include "ui/aura/root_window.h" |
| 26 #include "ui/base/cursor/cursor.h" | 26 #include "ui/base/cursor/cursor.h" |
| 27 #include "ui/base/events/event.h" | 27 #include "ui/base/events/event.h" |
| 28 #include "ui/base/keycodes/keyboard_codes.h" | 28 #include "ui/base/keycodes/keyboard_codes.h" |
| 29 #include "ui/base/resource/resource_bundle.h" | |
| 30 #include "ui/base/touch/touch_factory.h" | 29 #include "ui/base/touch/touch_factory.h" |
| 31 #include "ui/base/ui_base_switches.h" | 30 #include "ui/base/ui_base_switches.h" |
| 32 #include "ui/base/view_prop.h" | 31 #include "ui/base/view_prop.h" |
| 33 #include "ui/base/x/valuators.h" | 32 #include "ui/base/x/valuators.h" |
| 34 #include "ui/base/x/x11_util.h" | 33 #include "ui/base/x/x11_util.h" |
| 35 #include "ui/compositor/layer.h" | 34 #include "ui/compositor/layer.h" |
| 36 #include "ui/gfx/codec/png_codec.h" | 35 #include "ui/gfx/codec/png_codec.h" |
| 37 #include "ui/gfx/image/image.h" | |
| 38 #include "ui/gfx/image/image_skia.h" | |
| 39 #include "ui/gfx/screen.h" | 36 #include "ui/gfx/screen.h" |
| 40 | 37 |
| 41 using std::max; | 38 using std::max; |
| 42 using std::min; | 39 using std::min; |
| 43 | 40 |
| 44 namespace aura { | 41 namespace aura { |
| 45 | 42 |
| 46 namespace { | 43 namespace { |
| 47 | 44 |
| 48 // Standard Linux mouse buttons for going back and forward. | 45 // Standard Linux mouse buttons for going back and forward. |
| 49 const int kBackMouseButton = 8; | 46 const int kBackMouseButton = 8; |
| 50 const int kForwardMouseButton = 9; | 47 const int kForwardMouseButton = 9; |
| 51 | 48 |
| 52 const int kAnimatedCursorFrameDelayMs = 25; | |
| 53 | |
| 54 // These are the same values that are used to calibrate touch events in | 49 // These are the same values that are used to calibrate touch events in |
| 55 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). | 50 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). |
| 56 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) | 51 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) |
| 57 const int kXRootWindowPaddingLeft = 40; | 52 const int kXRootWindowPaddingLeft = 40; |
| 58 const int kXRootWindowPaddingRight = 40; | 53 const int kXRootWindowPaddingRight = 40; |
| 59 const int kXRootWindowPaddingBottom = 30; | 54 const int kXRootWindowPaddingBottom = 30; |
| 60 const int kXRootWindowPaddingTop = 0; | 55 const int kXRootWindowPaddingTop = 0; |
| 61 | 56 |
| 62 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; | 57 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; |
| 63 | 58 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); | 108 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); |
| 114 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); | 109 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); |
| 115 CHECK_EQ(slave_event.mods.base, xievent->mods.base); | 110 CHECK_EQ(slave_event.mods.base, xievent->mods.base); |
| 116 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); | 111 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); |
| 117 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); | 112 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); |
| 118 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); | 113 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); |
| 119 } | 114 } |
| 120 #endif // defined(USE_XI2_MT) && !defined(NDEBUG) | 115 #endif // defined(USE_XI2_MT) && !defined(NDEBUG) |
| 121 } | 116 } |
| 122 | 117 |
| 123 // Returns X font cursor shape from an Aura cursor. | |
| 124 int CursorShapeFromNative(gfx::NativeCursor native_cursor) { | |
| 125 switch (native_cursor.native_type()) { | |
| 126 case ui::kCursorMiddlePanning: | |
| 127 return XC_fleur; | |
| 128 case ui::kCursorEastPanning: | |
| 129 return XC_sb_right_arrow; | |
| 130 case ui::kCursorNorthPanning: | |
| 131 return XC_sb_up_arrow; | |
| 132 case ui::kCursorNorthEastPanning: | |
| 133 return XC_top_right_corner; | |
| 134 case ui::kCursorNorthWestPanning: | |
| 135 return XC_top_left_corner; | |
| 136 case ui::kCursorSouthPanning: | |
| 137 return XC_sb_down_arrow; | |
| 138 case ui::kCursorSouthEastPanning: | |
| 139 return XC_bottom_right_corner; | |
| 140 case ui::kCursorSouthWestPanning: | |
| 141 return XC_bottom_left_corner; | |
| 142 case ui::kCursorWestPanning: | |
| 143 return XC_sb_left_arrow; | |
| 144 case ui::kCursorNone: | |
| 145 // TODO(jamescook): Need cursors for these. crbug.com/111650 | |
| 146 return XC_left_ptr; | |
| 147 | |
| 148 case ui::kCursorNull: | |
| 149 case ui::kCursorPointer: | |
| 150 case ui::kCursorNoDrop: | |
| 151 case ui::kCursorNotAllowed: | |
| 152 case ui::kCursorCopy: | |
| 153 case ui::kCursorMove: | |
| 154 case ui::kCursorEastResize: | |
| 155 case ui::kCursorNorthResize: | |
| 156 case ui::kCursorSouthResize: | |
| 157 case ui::kCursorWestResize: | |
| 158 case ui::kCursorNorthEastResize: | |
| 159 case ui::kCursorNorthWestResize: | |
| 160 case ui::kCursorSouthWestResize: | |
| 161 case ui::kCursorSouthEastResize: | |
| 162 case ui::kCursorIBeam: | |
| 163 case ui::kCursorAlias: | |
| 164 case ui::kCursorCell: | |
| 165 case ui::kCursorContextMenu: | |
| 166 case ui::kCursorCross: | |
| 167 case ui::kCursorHelp: | |
| 168 case ui::kCursorWait: | |
| 169 case ui::kCursorNorthSouthResize: | |
| 170 case ui::kCursorEastWestResize: | |
| 171 case ui::kCursorNorthEastSouthWestResize: | |
| 172 case ui::kCursorNorthWestSouthEastResize: | |
| 173 case ui::kCursorProgress: | |
| 174 case ui::kCursorColumnResize: | |
| 175 case ui::kCursorRowResize: | |
| 176 case ui::kCursorVerticalText: | |
| 177 case ui::kCursorZoomIn: | |
| 178 case ui::kCursorZoomOut: | |
| 179 case ui::kCursorGrab: | |
| 180 case ui::kCursorGrabbing: | |
| 181 NOTREACHED() << "Cursor (" << native_cursor.native_type() << ") should " | |
| 182 << "have an image asset."; | |
| 183 return XC_left_ptr; | |
| 184 case ui::kCursorCustom: | |
| 185 NOTREACHED(); | |
| 186 return XC_left_ptr; | |
| 187 } | |
| 188 NOTREACHED(); | |
| 189 return XC_left_ptr; | |
| 190 } | |
| 191 | |
| 192 // Coalesce all pending motion events (touch or mouse) that are at the top of | 118 // Coalesce all pending motion events (touch or mouse) that are at the top of |
| 193 // the queue, and return the number eliminated, storing the last one in | 119 // the queue, and return the number eliminated, storing the last one in |
| 194 // |last_event|. | 120 // |last_event|. |
| 195 int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { | 121 int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { |
| 196 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 122 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
| 197 int num_coalesed = 0; | 123 int num_coalesed = 0; |
| 198 Display* display = xev->xany.display; | 124 Display* display = xev->xany.display; |
| 199 int event_type = xev->xgeneric.evtype; | 125 int event_type = xev->xgeneric.evtype; |
| 200 | 126 |
| 201 #if defined(USE_XI2_MT) | 127 #if defined(USE_XI2_MT) |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 case ui::VKEY_OEM_MINUS: | 269 case ui::VKEY_OEM_MINUS: |
| 344 case ui::VKEY_OEM_PERIOD: | 270 case ui::VKEY_OEM_PERIOD: |
| 345 return true; | 271 return true; |
| 346 default: | 272 default: |
| 347 return false; | 273 return false; |
| 348 } | 274 } |
| 349 } | 275 } |
| 350 | 276 |
| 351 } // namespace | 277 } // namespace |
| 352 | 278 |
| 353 // A utility class that provides X Cursor for NativeCursors for which we have | |
| 354 // image resources. | |
| 355 class RootWindowHostLinux::ImageCursors { | |
| 356 public: | |
| 357 ImageCursors() : scale_factor_(0.0) { | |
| 358 } | |
| 359 | |
| 360 void Reload(float scale_factor) { | |
| 361 if (scale_factor_ == scale_factor) | |
| 362 return; | |
| 363 scale_factor_ = scale_factor; | |
| 364 UnloadAll(); | |
| 365 // The cursor's hot points are defined in chromeos cursor images at: | |
| 366 // http://folder/kuscher/projects/Chrome_OS/Pointers/focuspoint | |
| 367 LoadImageCursor(ui::kCursorNull, IDR_AURA_CURSOR_PTR, | |
| 368 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 369 LoadImageCursor(ui::kCursorPointer, IDR_AURA_CURSOR_PTR, | |
| 370 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 371 LoadImageCursor(ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP, | |
| 372 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 373 LoadImageCursor(ui::kCursorNotAllowed, IDR_AURA_CURSOR_NO_DROP, | |
| 374 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 375 LoadImageCursor(ui::kCursorCopy, IDR_AURA_CURSOR_COPY, | |
| 376 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 377 LoadImageCursor(ui::kCursorHand, IDR_AURA_CURSOR_HAND, | |
| 378 gfx::Point(9, 4), gfx::Point(19, 8)); | |
| 379 LoadImageCursor(ui::kCursorMove, IDR_AURA_CURSOR_MOVE, | |
| 380 gfx::Point(11, 11), gfx::Point(23, 23)); | |
| 381 LoadImageCursor(ui::kCursorNorthEastResize, | |
| 382 IDR_AURA_CURSOR_NORTH_EAST_RESIZE, | |
| 383 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 384 LoadImageCursor(ui::kCursorSouthWestResize, | |
| 385 IDR_AURA_CURSOR_SOUTH_WEST_RESIZE, | |
| 386 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 387 LoadImageCursor(ui::kCursorSouthEastResize, | |
| 388 IDR_AURA_CURSOR_SOUTH_EAST_RESIZE, | |
| 389 gfx::Point(11, 11), gfx::Point(24, 23)); | |
| 390 LoadImageCursor(ui::kCursorNorthWestResize, | |
| 391 IDR_AURA_CURSOR_NORTH_WEST_RESIZE, | |
| 392 gfx::Point(11, 11), gfx::Point(24, 23)); | |
| 393 LoadImageCursor(ui::kCursorNorthResize, IDR_AURA_CURSOR_NORTH_RESIZE, | |
| 394 gfx::Point(11, 12), gfx::Point(23, 23)); | |
| 395 LoadImageCursor(ui::kCursorSouthResize, IDR_AURA_CURSOR_SOUTH_RESIZE, | |
| 396 gfx::Point(11, 12), gfx::Point(23, 23)); | |
| 397 LoadImageCursor(ui::kCursorEastResize, IDR_AURA_CURSOR_EAST_RESIZE, | |
| 398 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 399 LoadImageCursor(ui::kCursorWestResize, IDR_AURA_CURSOR_WEST_RESIZE, | |
| 400 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 401 LoadImageCursor(ui::kCursorIBeam, IDR_AURA_CURSOR_IBEAM, | |
| 402 gfx::Point(12, 12), gfx::Point(24, 25)); | |
| 403 LoadImageCursor(ui::kCursorAlias, IDR_AURA_CURSOR_ALIAS, | |
| 404 gfx::Point(8, 6), gfx::Point(15, 11)); | |
| 405 LoadImageCursor(ui::kCursorCell, IDR_AURA_CURSOR_CELL, | |
| 406 gfx::Point(11, 11), gfx::Point(24, 23)); | |
| 407 LoadImageCursor(ui::kCursorContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, | |
| 408 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 409 LoadImageCursor(ui::kCursorCross, IDR_AURA_CURSOR_CROSSHAIR, | |
| 410 gfx::Point(12, 12), gfx::Point(25, 23)); | |
| 411 LoadImageCursor(ui::kCursorHelp, IDR_AURA_CURSOR_HELP, | |
| 412 gfx::Point(4, 4), gfx::Point(8, 9)); | |
| 413 LoadImageCursor(ui::kCursorVerticalText, IDR_AURA_CURSOR_XTERM_HORIZ, | |
| 414 gfx::Point(12, 11), gfx::Point(26, 23)); | |
| 415 LoadImageCursor(ui::kCursorZoomIn, IDR_AURA_CURSOR_ZOOM_IN, | |
| 416 gfx::Point(10, 10), gfx::Point(20, 20)); | |
| 417 LoadImageCursor(ui::kCursorZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, | |
| 418 gfx::Point(10, 10), gfx::Point(20, 20)); | |
| 419 LoadImageCursor(ui::kCursorRowResize, IDR_AURA_CURSOR_ROW_RESIZE, | |
| 420 gfx::Point(11, 12), gfx::Point(23, 23)); | |
| 421 LoadImageCursor(ui::kCursorColumnResize, IDR_AURA_CURSOR_COL_RESIZE, | |
| 422 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 423 LoadImageCursor(ui::kCursorEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE, | |
| 424 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 425 LoadImageCursor(ui::kCursorNorthSouthResize, | |
| 426 IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, | |
| 427 gfx::Point(11, 12), gfx::Point(23, 23)); | |
| 428 LoadImageCursor(ui::kCursorNorthEastSouthWestResize, | |
| 429 IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, | |
| 430 gfx::Point(12, 11), gfx::Point(25, 23)); | |
| 431 LoadImageCursor(ui::kCursorNorthWestSouthEastResize, | |
| 432 IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, | |
| 433 gfx::Point(11, 11), gfx::Point(24, 23)); | |
| 434 LoadImageCursor(ui::kCursorGrab, IDR_AURA_CURSOR_GRAB, | |
| 435 gfx::Point(8, 5), gfx::Point(16, 10)); | |
| 436 LoadImageCursor(ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING, | |
| 437 gfx::Point(9, 9), gfx::Point(18, 18)); | |
| 438 LoadAnimatedCursor(ui::kCursorWait, IDR_THROBBER, 7, 7); | |
| 439 LoadAnimatedCursor(ui::kCursorProgress, IDR_THROBBER, 7, 7); | |
| 440 } | |
| 441 | |
| 442 ~ImageCursors() { | |
| 443 UnloadAll(); | |
| 444 } | |
| 445 | |
| 446 void UnloadAll() { | |
| 447 for (std::map<int, Cursor>::const_iterator it = cursors_.begin(); | |
| 448 it != cursors_.end(); ++it) | |
| 449 ui::UnrefCustomXCursor(it->second); | |
| 450 | |
| 451 // Free animated cursors and images. | |
| 452 for (AnimatedCursorMap::iterator it = animated_cursors_.begin(); | |
| 453 it != animated_cursors_.end(); ++it) { | |
| 454 XcursorImagesDestroy(it->second.second); // also frees individual frames. | |
| 455 XFreeCursor(ui::GetXDisplay(), it->second.first); | |
| 456 } | |
| 457 } | |
| 458 | |
| 459 // Returns true if we have an image resource loaded for the |native_cursor|. | |
| 460 bool IsImageCursor(gfx::NativeCursor native_cursor) { | |
| 461 int type = native_cursor.native_type(); | |
| 462 return cursors_.find(type) != cursors_.end() || | |
| 463 animated_cursors_.find(type) != animated_cursors_.end(); | |
| 464 } | |
| 465 | |
| 466 // Gets the X Cursor corresponding to the |native_cursor|. | |
| 467 ::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor) { | |
| 468 int type = native_cursor.native_type(); | |
| 469 if (animated_cursors_.find(type) != animated_cursors_.end()) | |
| 470 return animated_cursors_[type].first; | |
| 471 DCHECK(cursors_.find(type) != cursors_.end()); | |
| 472 return cursors_[type]; | |
| 473 } | |
| 474 | |
| 475 private: | |
| 476 // Creates an X Cursor from an image resource and puts it in the cursor map. | |
| 477 void LoadImageCursor(int id, | |
| 478 int resource_id, | |
| 479 const gfx::Point& hot_1x, | |
| 480 const gfx::Point& hot_2x) { | |
| 481 const gfx::ImageSkia* image = | |
| 482 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); | |
| 483 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( | |
| 484 ui::GetScaleFactorFromScale(scale_factor_)); | |
| 485 const gfx::Point& hot = (scale_factor_ == 1) ? hot_1x : hot_2x; | |
| 486 XcursorImage* x_image = | |
| 487 ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot); | |
| 488 cursors_[id] = ui::CreateReffedCustomXCursor(x_image); | |
| 489 // |bitmap| is owned by the resource bundle. So we do not need to free it. | |
| 490 } | |
| 491 | |
| 492 // Creates an animated X Cursor from an image resource and puts it in the | |
| 493 // cursor map. The image is assumed to be a concatenation of animation frames. | |
| 494 // Also, each frame is assumed to be square (width == height) | |
| 495 void LoadAnimatedCursor(int id, int resource_id, int hot_x, int hot_y) { | |
| 496 const gfx::ImageSkia* image = | |
| 497 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); | |
| 498 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( | |
| 499 ui::GetScaleFactorFromScale(scale_factor_)); | |
| 500 const SkBitmap bitmap = image_rep.sk_bitmap(); | |
| 501 DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config); | |
| 502 int frame_width = bitmap.height(); | |
| 503 int frame_height = frame_width; | |
| 504 int total_width = bitmap.width(); | |
| 505 DCHECK_EQ(total_width % frame_width, 0); | |
| 506 int frame_count = total_width / frame_width; | |
| 507 DCHECK_GT(frame_count, 0); | |
| 508 XcursorImages* x_images = XcursorImagesCreate(frame_count); | |
| 509 x_images->nimage = frame_count; | |
| 510 bitmap.lockPixels(); | |
| 511 unsigned int* pixels = bitmap.getAddr32(0, 0); | |
| 512 // Create each frame. | |
| 513 for (int i = 0; i < frame_count; ++i) { | |
| 514 XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height); | |
| 515 for (int j = 0; j < frame_height; ++j) { | |
| 516 // Copy j'th row of i'th frame. | |
| 517 memcpy(x_image->pixels + j * frame_width, | |
| 518 pixels + i * frame_width + j * total_width, | |
| 519 frame_width * 4); | |
| 520 } | |
| 521 x_image->xhot = hot_x * scale_factor_; | |
| 522 x_image->yhot = hot_y * scale_factor_; | |
| 523 x_image->delay = kAnimatedCursorFrameDelayMs; | |
| 524 x_images->images[i] = x_image; | |
| 525 } | |
| 526 bitmap.unlockPixels(); | |
| 527 | |
| 528 animated_cursors_[id] = std::make_pair( | |
| 529 XcursorImagesLoadCursor(ui::GetXDisplay(), x_images), x_images); | |
| 530 // |bitmap| is owned by the resource bundle. So we do not need to free it. | |
| 531 } | |
| 532 | |
| 533 // A map to hold all image cursors. It maps the cursor ID to the X Cursor. | |
| 534 std::map<int, Cursor> cursors_; | |
| 535 | |
| 536 // A map to hold all animated cursors. It maps the cursor ID to the pair of | |
| 537 // the X Cursor and the corresponding XcursorImages. We need a pointer to the | |
| 538 // images so that we can free them on destruction. | |
| 539 typedef std::map<int, std::pair<Cursor, XcursorImages*> > AnimatedCursorMap; | |
| 540 AnimatedCursorMap animated_cursors_; | |
| 541 | |
| 542 float scale_factor_; | |
| 543 | |
| 544 DISALLOW_COPY_AND_ASSIGN(ImageCursors); | |
| 545 }; | |
| 546 | |
| 547 RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, | 279 RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, |
| 548 const gfx::Rect& bounds) | 280 const gfx::Rect& bounds) |
| 549 : delegate_(delegate), | 281 : delegate_(delegate), |
| 550 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), | 282 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), |
| 551 xwindow_(0), | 283 xwindow_(0), |
| 552 x_root_window_(DefaultRootWindow(xdisplay_)), | 284 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 553 current_cursor_(ui::kCursorNull), | 285 current_cursor_(ui::kCursorNull), |
| 554 window_mapped_(false), | 286 window_mapped_(false), |
| 555 cursor_shown_(true), | 287 cursor_shown_(true), |
| 556 bounds_(bounds), | 288 bounds_(bounds), |
| 557 focus_when_shown_(false), | 289 focus_when_shown_(false), |
| 558 pointer_barriers_(NULL), | 290 pointer_barriers_(NULL), |
| 559 image_cursors_(new ImageCursors), | |
| 560 atom_cache_(xdisplay_, kAtomsToCache) { | 291 atom_cache_(xdisplay_, kAtomsToCache) { |
| 561 XSetWindowAttributes swa; | 292 XSetWindowAttributes swa; |
| 562 memset(&swa, 0, sizeof(swa)); | 293 memset(&swa, 0, sizeof(swa)); |
| 563 swa.background_pixmap = None; | 294 swa.background_pixmap = None; |
| 564 xwindow_ = XCreateWindow( | 295 xwindow_ = XCreateWindow( |
| 565 xdisplay_, x_root_window_, | 296 xdisplay_, x_root_window_, |
| 566 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 297 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 567 0, // border width | 298 0, // border width |
| 568 CopyFromParent, // depth | 299 CopyFromParent, // depth |
| 569 InputOutput, | 300 InputOutput, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 587 if (base::MessagePumpForUI::HasXInput2()) | 318 if (base::MessagePumpForUI::HasXInput2()) |
| 588 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 319 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
| 589 | 320 |
| 590 SelectEventsForRootWindow(); | 321 SelectEventsForRootWindow(); |
| 591 | 322 |
| 592 // Get the initial size of the X root window. | 323 // Get the initial size of the X root window. |
| 593 XWindowAttributes attrs; | 324 XWindowAttributes attrs; |
| 594 XGetWindowAttributes(xdisplay_, x_root_window_, &attrs); | 325 XGetWindowAttributes(xdisplay_, x_root_window_, &attrs); |
| 595 x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height); | 326 x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height); |
| 596 | 327 |
| 597 // Initialize invisible cursor. | 328 invisible_cursor_ = ui::CreateInvisibleCursor(); |
| 598 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
| 599 XColor black; | |
| 600 black.red = black.green = black.blue = 0; | |
| 601 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, | |
| 602 nodata, 8, 8); | |
| 603 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, | |
| 604 &black, &black, 0, 0); | |
| 605 XFreePixmap(xdisplay_, blank); | |
| 606 | |
| 607 if (RootWindow::hide_host_cursor()) | |
| 608 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_); | |
| 609 | 329 |
| 610 // TODO(erg): We currently only request window deletion events. We also | 330 // TODO(erg): We currently only request window deletion events. We also |
| 611 // should listen for activation events and anything else that GTK+ listens | 331 // should listen for activation events and anything else that GTK+ listens |
| 612 // for, and do something useful. | 332 // for, and do something useful. |
| 613 ::Atom protocols[2]; | 333 ::Atom protocols[2]; |
| 614 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); | 334 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); |
| 615 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); | 335 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); |
| 616 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); | 336 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); |
| 617 | 337 |
| 618 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with | 338 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with |
| (...skipping 22 matching lines...) Expand all Loading... |
| 641 } | 361 } |
| 642 | 362 |
| 643 RootWindowHostLinux::~RootWindowHostLinux() { | 363 RootWindowHostLinux::~RootWindowHostLinux() { |
| 644 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); | 364 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); |
| 645 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); | 365 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); |
| 646 | 366 |
| 647 UnConfineCursor(); | 367 UnConfineCursor(); |
| 648 | 368 |
| 649 XDestroyWindow(xdisplay_, xwindow_); | 369 XDestroyWindow(xdisplay_, xwindow_); |
| 650 | 370 |
| 651 // Clears XCursorCache. | |
| 652 ui::GetXCursor(ui::kCursorClearXCursorCache); | |
| 653 | |
| 654 XFreeCursor(xdisplay_, invisible_cursor_); | 371 XFreeCursor(xdisplay_, invisible_cursor_); |
| 655 } | 372 } |
| 656 | 373 |
| 657 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { | 374 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { |
| 658 XEvent* xev = event; | 375 XEvent* xev = event; |
| 659 | 376 |
| 660 CheckXEventForConsistency(xev); | 377 CheckXEventForConsistency(xev); |
| 661 | 378 |
| 662 switch (xev->type) { | 379 switch (xev->type) { |
| 380 case EnterNotify: { |
| 381 ui::MouseEvent mouseenter_event(xev); |
| 382 delegate_->OnHostMouseEvent(&mouseenter_event); |
| 383 break; |
| 384 } |
| 663 case Expose: | 385 case Expose: |
| 664 delegate_->AsRootWindow()->ScheduleFullDraw(); | 386 delegate_->AsRootWindow()->ScheduleFullDraw(); |
| 665 break; | 387 break; |
| 666 case KeyPress: { | 388 case KeyPress: { |
| 667 ui::KeyEvent keydown_event(xev, false); | 389 ui::KeyEvent keydown_event(xev, false); |
| 668 delegate_->OnHostKeyEvent(&keydown_event); | 390 delegate_->OnHostKeyEvent(&keydown_event); |
| 669 break; | 391 break; |
| 670 } | 392 } |
| 671 case KeyRelease: { | 393 case KeyRelease: { |
| 672 ui::KeyEvent keyup_event(xev, false); | 394 ui::KeyEvent keyup_event(xev, false); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 | 622 |
| 901 RootWindow* RootWindowHostLinux::GetRootWindow() { | 623 RootWindow* RootWindowHostLinux::GetRootWindow() { |
| 902 return delegate_->AsRootWindow(); | 624 return delegate_->AsRootWindow(); |
| 903 } | 625 } |
| 904 | 626 |
| 905 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { | 627 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { |
| 906 return xwindow_; | 628 return xwindow_; |
| 907 } | 629 } |
| 908 | 630 |
| 909 void RootWindowHostLinux::Show() { | 631 void RootWindowHostLinux::Show() { |
| 910 // The device scale factor is now accessible, so load cursors now. | |
| 911 image_cursors_->Reload(delegate_->GetDeviceScaleFactor()); | |
| 912 | |
| 913 if (!window_mapped_) { | 632 if (!window_mapped_) { |
| 914 // Before we map the window, set size hints. Otherwise, some window managers | 633 // Before we map the window, set size hints. Otherwise, some window managers |
| 915 // will ignore toplevel XMoveWindow commands. | 634 // will ignore toplevel XMoveWindow commands. |
| 916 XSizeHints size_hints; | 635 XSizeHints size_hints; |
| 917 size_hints.flags = PPosition; | 636 size_hints.flags = PPosition; |
| 918 size_hints.x = bounds_.x(); | 637 size_hints.x = bounds_.x(); |
| 919 size_hints.y = bounds_.y(); | 638 size_hints.y = bounds_.y(); |
| 920 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); | 639 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); |
| 921 | 640 |
| 922 XMapWindow(xdisplay_, xwindow_); | 641 XMapWindow(xdisplay_, xwindow_); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 current_cursor_ = cursor; | 710 current_cursor_ = cursor; |
| 992 | 711 |
| 993 if (cursor_shown_) | 712 if (cursor_shown_) |
| 994 SetCursorInternal(cursor); | 713 SetCursorInternal(cursor); |
| 995 } | 714 } |
| 996 | 715 |
| 997 void RootWindowHostLinux::ShowCursor(bool show) { | 716 void RootWindowHostLinux::ShowCursor(bool show) { |
| 998 if (show == cursor_shown_) | 717 if (show == cursor_shown_) |
| 999 return; | 718 return; |
| 1000 cursor_shown_ = show; | 719 cursor_shown_ = show; |
| 1001 SetCursorInternal(show ? current_cursor_ : ui::kCursorNone); | 720 SetCursorInternal(show ? current_cursor_ : invisible_cursor_); |
| 1002 } | 721 } |
| 1003 | 722 |
| 1004 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { | 723 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { |
| 1005 ::Window root_return, child_return; | 724 ::Window root_return, child_return; |
| 1006 int root_x_return, root_y_return, win_x_return, win_y_return; | 725 int root_x_return, root_y_return, win_x_return, win_y_return; |
| 1007 unsigned int mask_return; | 726 unsigned int mask_return; |
| 1008 XQueryPointer(xdisplay_, | 727 XQueryPointer(xdisplay_, |
| 1009 xwindow_, | 728 xwindow_, |
| 1010 &root_return, | 729 &root_return, |
| 1011 &child_return, | 730 &child_return, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 xevent.xmotion.y_root = point.y(); | 877 xevent.xmotion.y_root = point.y(); |
| 1159 } | 878 } |
| 1160 default: | 879 default: |
| 1161 break; | 880 break; |
| 1162 } | 881 } |
| 1163 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); | 882 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); |
| 1164 } | 883 } |
| 1165 | 884 |
| 1166 void RootWindowHostLinux::OnDeviceScaleFactorChanged( | 885 void RootWindowHostLinux::OnDeviceScaleFactorChanged( |
| 1167 float device_scale_factor) { | 886 float device_scale_factor) { |
| 1168 image_cursors_->Reload(device_scale_factor); | |
| 1169 } | 887 } |
| 1170 | 888 |
| 1171 void RootWindowHostLinux::PrepareForShutdown() { | 889 void RootWindowHostLinux::PrepareForShutdown() { |
| 1172 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); | 890 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); |
| 1173 } | 891 } |
| 1174 | 892 |
| 1175 bool RootWindowHostLinux::IsWindowManagerPresent() { | 893 bool RootWindowHostLinux::IsWindowManagerPresent() { |
| 1176 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 894 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
| 1177 // of WM_Sn selections (where n is a screen number). | 895 // of WM_Sn selections (where n is a screen number). |
| 1178 return XGetSelectionOwner( | 896 return XGetSelectionOwner( |
| 1179 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; | 897 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
| 1180 } | 898 } |
| 1181 | 899 |
| 1182 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { | 900 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { |
| 1183 // At times the cursor on the RootWindow is set before it is displayed. So | 901 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); |
| 1184 // make sure the image-cursors are initialized properly before setting it. | |
| 1185 image_cursors_->Reload(delegate_->GetDeviceScaleFactor()); | |
| 1186 | |
| 1187 ::Cursor xcursor; | |
| 1188 if (image_cursors_->IsImageCursor(cursor)) | |
| 1189 xcursor = image_cursors_->ImageCursorFromNative(cursor); | |
| 1190 else if (cursor == ui::kCursorNone) | |
| 1191 xcursor = invisible_cursor_; | |
| 1192 else if (cursor == ui::kCursorCustom) | |
| 1193 xcursor = cursor.platform(); | |
| 1194 else if (delegate_->GetDeviceScaleFactor() == 1.0) | |
| 1195 xcursor = ui::GetXCursor(CursorShapeFromNative(cursor)); | |
| 1196 else | |
| 1197 xcursor = image_cursors_->ImageCursorFromNative(ui::kCursorPointer); | |
| 1198 XDefineCursor(xdisplay_, xwindow_, xcursor); | |
| 1199 } | 902 } |
| 1200 | 903 |
| 1201 // static | 904 // static |
| 1202 RootWindowHost* RootWindowHost::Create(RootWindowHostDelegate* delegate, | 905 RootWindowHost* RootWindowHost::Create(RootWindowHostDelegate* delegate, |
| 1203 const gfx::Rect& bounds) { | 906 const gfx::Rect& bounds) { |
| 1204 return new RootWindowHostLinux(delegate, bounds); | 907 return new RootWindowHostLinux(delegate, bounds); |
| 1205 } | 908 } |
| 1206 | 909 |
| 1207 // static | 910 // static |
| 1208 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( | 911 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( |
| 1209 gfx::AcceleratedWidget accelerated_widget) { | 912 gfx::AcceleratedWidget accelerated_widget) { |
| 1210 return reinterpret_cast<RootWindowHost*>( | 913 return reinterpret_cast<RootWindowHost*>( |
| 1211 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); | 914 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); |
| 1212 } | 915 } |
| 1213 | 916 |
| 1214 // static | 917 // static |
| 1215 gfx::Size RootWindowHost::GetNativeScreenSize() { | 918 gfx::Size RootWindowHost::GetNativeScreenSize() { |
| 1216 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 919 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
| 1217 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 920 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 1218 } | 921 } |
| 1219 | 922 |
| 1220 } // namespace aura | 923 } // namespace aura |
| OLD | NEW |