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

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

Issue 10919135: Move ash specific cursor code to CursorManager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comment Created 8 years, 3 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
OLDNEW
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 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; 49 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__";
55 50
56 const char* kAtomsToCache[] = { 51 const char* kAtomsToCache[] = {
57 "WM_DELETE_WINDOW", 52 "WM_DELETE_WINDOW",
58 "_NET_WM_PING", 53 "_NET_WM_PING",
59 "_NET_WM_PID", 54 "_NET_WM_PID",
60 "WM_S0", 55 "WM_S0",
61 NULL 56 NULL
62 }; 57 };
63 58
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); 100 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len);
106 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); 101 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len);
107 CHECK_EQ(slave_event.mods.base, xievent->mods.base); 102 CHECK_EQ(slave_event.mods.base, xievent->mods.base);
108 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); 103 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched);
109 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); 104 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked);
110 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); 105 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective);
111 } 106 }
112 #endif // defined(USE_XI2_MT) && !defined(NDEBUG) 107 #endif // defined(USE_XI2_MT) && !defined(NDEBUG)
113 } 108 }
114 109
115 // Returns X font cursor shape from an Aura cursor.
116 int CursorShapeFromNative(gfx::NativeCursor native_cursor) {
117 switch (native_cursor.native_type()) {
118 case ui::kCursorMiddlePanning:
119 return XC_fleur;
120 case ui::kCursorEastPanning:
121 return XC_sb_right_arrow;
122 case ui::kCursorNorthPanning:
123 return XC_sb_up_arrow;
124 case ui::kCursorNorthEastPanning:
125 return XC_top_right_corner;
126 case ui::kCursorNorthWestPanning:
127 return XC_top_left_corner;
128 case ui::kCursorSouthPanning:
129 return XC_sb_down_arrow;
130 case ui::kCursorSouthEastPanning:
131 return XC_bottom_right_corner;
132 case ui::kCursorSouthWestPanning:
133 return XC_bottom_left_corner;
134 case ui::kCursorWestPanning:
135 return XC_sb_left_arrow;
136 case ui::kCursorNone:
137 // TODO(jamescook): Need cursors for these. crbug.com/111650
138 return XC_left_ptr;
139
140 case ui::kCursorNull:
141 case ui::kCursorPointer:
142 case ui::kCursorNoDrop:
143 case ui::kCursorNotAllowed:
144 case ui::kCursorCopy:
145 case ui::kCursorMove:
146 case ui::kCursorEastResize:
147 case ui::kCursorNorthResize:
148 case ui::kCursorSouthResize:
149 case ui::kCursorWestResize:
150 case ui::kCursorNorthEastResize:
151 case ui::kCursorNorthWestResize:
152 case ui::kCursorSouthWestResize:
153 case ui::kCursorSouthEastResize:
154 case ui::kCursorIBeam:
155 case ui::kCursorAlias:
156 case ui::kCursorCell:
157 case ui::kCursorContextMenu:
158 case ui::kCursorCross:
159 case ui::kCursorHelp:
160 case ui::kCursorWait:
161 case ui::kCursorNorthSouthResize:
162 case ui::kCursorEastWestResize:
163 case ui::kCursorNorthEastSouthWestResize:
164 case ui::kCursorNorthWestSouthEastResize:
165 case ui::kCursorProgress:
166 case ui::kCursorColumnResize:
167 case ui::kCursorRowResize:
168 case ui::kCursorVerticalText:
169 case ui::kCursorZoomIn:
170 case ui::kCursorZoomOut:
171 case ui::kCursorGrab:
172 case ui::kCursorGrabbing:
173 NOTREACHED() << "Cursor (" << native_cursor.native_type() << ") should "
174 << "have an image asset.";
175 return XC_left_ptr;
176 case ui::kCursorCustom:
177 NOTREACHED();
178 return XC_left_ptr;
179 }
180 NOTREACHED();
181 return XC_left_ptr;
182 }
183
184 // Coalesce all pending motion events (touch or mouse) that are at the top of 110 // Coalesce all pending motion events (touch or mouse) that are at the top of
185 // the queue, and return the number eliminated, storing the last one in 111 // the queue, and return the number eliminated, storing the last one in
186 // |last_event|. 112 // |last_event|.
187 int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { 113 int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) {
188 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); 114 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
189 int num_coalesed = 0; 115 int num_coalesed = 0;
190 Display* display = xev->xany.display; 116 Display* display = xev->xany.display;
191 int event_type = xev->xgeneric.evtype; 117 int event_type = xev->xgeneric.evtype;
192 118
193 #if defined(USE_XI2_MT) 119 #if defined(USE_XI2_MT)
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 case ui::VKEY_OEM_MINUS: 229 case ui::VKEY_OEM_MINUS:
304 case ui::VKEY_OEM_PERIOD: 230 case ui::VKEY_OEM_PERIOD:
305 return true; 231 return true;
306 default: 232 default:
307 return false; 233 return false;
308 } 234 }
309 } 235 }
310 236
311 } // namespace 237 } // namespace
312 238
313 // A utility class that provides X Cursor for NativeCursors for which we have
314 // image resources.
315 class RootWindowHostLinux::ImageCursors {
316 public:
317 ImageCursors() : scale_factor_(0.0) {
318 }
319
320 void Reload(float scale_factor) {
321 if (scale_factor_ == scale_factor)
322 return;
323 scale_factor_ = scale_factor;
324 UnloadAll();
325 // The cursor's hot points are defined in chromeos cursor images at:
326 // http://folder/kuscher/projects/Chrome_OS/Pointers/focuspoint
327 LoadImageCursor(ui::kCursorNull, IDR_AURA_CURSOR_PTR,
328 gfx::Point(4, 4), gfx::Point(8, 9));
329 LoadImageCursor(ui::kCursorPointer, IDR_AURA_CURSOR_PTR,
330 gfx::Point(4, 4), gfx::Point(8, 9));
331 LoadImageCursor(ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP,
332 gfx::Point(4, 4), gfx::Point(8, 9));
333 LoadImageCursor(ui::kCursorNotAllowed, IDR_AURA_CURSOR_NO_DROP,
334 gfx::Point(4, 4), gfx::Point(8, 9));
335 LoadImageCursor(ui::kCursorCopy, IDR_AURA_CURSOR_COPY,
336 gfx::Point(4, 4), gfx::Point(8, 9));
337 LoadImageCursor(ui::kCursorHand, IDR_AURA_CURSOR_HAND,
338 gfx::Point(9, 4), gfx::Point(19, 8));
339 LoadImageCursor(ui::kCursorMove, IDR_AURA_CURSOR_MOVE,
340 gfx::Point(11, 11), gfx::Point(23, 23));
341 LoadImageCursor(ui::kCursorNorthEastResize,
342 IDR_AURA_CURSOR_NORTH_EAST_RESIZE,
343 gfx::Point(12, 11), gfx::Point(25, 23));
344 LoadImageCursor(ui::kCursorSouthWestResize,
345 IDR_AURA_CURSOR_SOUTH_WEST_RESIZE,
346 gfx::Point(12, 11), gfx::Point(25, 23));
347 LoadImageCursor(ui::kCursorSouthEastResize,
348 IDR_AURA_CURSOR_SOUTH_EAST_RESIZE,
349 gfx::Point(11, 11), gfx::Point(24, 23));
350 LoadImageCursor(ui::kCursorNorthWestResize,
351 IDR_AURA_CURSOR_NORTH_WEST_RESIZE,
352 gfx::Point(11, 11), gfx::Point(24, 23));
353 LoadImageCursor(ui::kCursorNorthResize, IDR_AURA_CURSOR_NORTH_RESIZE,
354 gfx::Point(11, 12), gfx::Point(23, 23));
355 LoadImageCursor(ui::kCursorSouthResize, IDR_AURA_CURSOR_SOUTH_RESIZE,
356 gfx::Point(11, 12), gfx::Point(23, 23));
357 LoadImageCursor(ui::kCursorEastResize, IDR_AURA_CURSOR_EAST_RESIZE,
358 gfx::Point(12, 11), gfx::Point(25, 23));
359 LoadImageCursor(ui::kCursorWestResize, IDR_AURA_CURSOR_WEST_RESIZE,
360 gfx::Point(12, 11), gfx::Point(25, 23));
361 LoadImageCursor(ui::kCursorIBeam, IDR_AURA_CURSOR_IBEAM,
362 gfx::Point(12, 12), gfx::Point(24, 25));
363 LoadImageCursor(ui::kCursorAlias, IDR_AURA_CURSOR_ALIAS,
364 gfx::Point(8, 6), gfx::Point(15, 11));
365 LoadImageCursor(ui::kCursorCell, IDR_AURA_CURSOR_CELL,
366 gfx::Point(11, 11), gfx::Point(24, 23));
367 LoadImageCursor(ui::kCursorContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU,
368 gfx::Point(4, 4), gfx::Point(8, 9));
369 LoadImageCursor(ui::kCursorCross, IDR_AURA_CURSOR_CROSSHAIR,
370 gfx::Point(12, 12), gfx::Point(25, 23));
371 LoadImageCursor(ui::kCursorHelp, IDR_AURA_CURSOR_HELP,
372 gfx::Point(4, 4), gfx::Point(8, 9));
373 LoadImageCursor(ui::kCursorVerticalText, IDR_AURA_CURSOR_XTERM_HORIZ,
374 gfx::Point(12, 11), gfx::Point(26, 23));
375 LoadImageCursor(ui::kCursorZoomIn, IDR_AURA_CURSOR_ZOOM_IN,
376 gfx::Point(10, 10), gfx::Point(20, 20));
377 LoadImageCursor(ui::kCursorZoomOut, IDR_AURA_CURSOR_ZOOM_OUT,
378 gfx::Point(10, 10), gfx::Point(20, 20));
379 LoadImageCursor(ui::kCursorRowResize, IDR_AURA_CURSOR_ROW_RESIZE,
380 gfx::Point(11, 12), gfx::Point(23, 23));
381 LoadImageCursor(ui::kCursorColumnResize, IDR_AURA_CURSOR_COL_RESIZE,
382 gfx::Point(12, 11), gfx::Point(25, 23));
383 LoadImageCursor(ui::kCursorEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE,
384 gfx::Point(12, 11), gfx::Point(25, 23));
385 LoadImageCursor(ui::kCursorNorthSouthResize,
386 IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE,
387 gfx::Point(11, 12), gfx::Point(23, 23));
388 LoadImageCursor(ui::kCursorNorthEastSouthWestResize,
389 IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE,
390 gfx::Point(12, 11), gfx::Point(25, 23));
391 LoadImageCursor(ui::kCursorNorthWestSouthEastResize,
392 IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE,
393 gfx::Point(11, 11), gfx::Point(24, 23));
394 LoadImageCursor(ui::kCursorGrab, IDR_AURA_CURSOR_GRAB,
395 gfx::Point(8, 5), gfx::Point(16, 10));
396 LoadImageCursor(ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING,
397 gfx::Point(9, 9), gfx::Point(18, 18));
398 LoadAnimatedCursor(ui::kCursorWait, IDR_THROBBER, 7, 7);
399 LoadAnimatedCursor(ui::kCursorProgress, IDR_THROBBER, 7, 7);
400 }
401
402 ~ImageCursors() {
403 UnloadAll();
404 }
405
406 void UnloadAll() {
407 for (std::map<int, Cursor>::const_iterator it = cursors_.begin();
408 it != cursors_.end(); ++it)
409 ui::UnrefCustomXCursor(it->second);
410
411 // Free animated cursors and images.
412 for (AnimatedCursorMap::iterator it = animated_cursors_.begin();
413 it != animated_cursors_.end(); ++it) {
414 XcursorImagesDestroy(it->second.second); // also frees individual frames.
415 XFreeCursor(ui::GetXDisplay(), it->second.first);
416 }
417 }
418
419 // Returns true if we have an image resource loaded for the |native_cursor|.
420 bool IsImageCursor(gfx::NativeCursor native_cursor) {
421 int type = native_cursor.native_type();
422 return cursors_.find(type) != cursors_.end() ||
423 animated_cursors_.find(type) != animated_cursors_.end();
424 }
425
426 // Gets the X Cursor corresponding to the |native_cursor|.
427 ::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor) {
428 int type = native_cursor.native_type();
429 if (animated_cursors_.find(type) != animated_cursors_.end())
430 return animated_cursors_[type].first;
431 DCHECK(cursors_.find(type) != cursors_.end());
432 return cursors_[type];
433 }
434
435 private:
436 // Creates an X Cursor from an image resource and puts it in the cursor map.
437 void LoadImageCursor(int id,
438 int resource_id,
439 const gfx::Point& hot_1x,
440 const gfx::Point& hot_2x) {
441 const gfx::ImageSkia* image =
442 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
443 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
444 ui::GetScaleFactorFromScale(scale_factor_));
445 const gfx::Point& hot = (scale_factor_ == 1) ? hot_1x : hot_2x;
446 XcursorImage* x_image =
447 ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot);
448 cursors_[id] = ui::CreateReffedCustomXCursor(x_image);
449 // |bitmap| is owned by the resource bundle. So we do not need to free it.
450 }
451
452 // Creates an animated X Cursor from an image resource and puts it in the
453 // cursor map. The image is assumed to be a concatenation of animation frames.
454 // Also, each frame is assumed to be square (width == height)
455 void LoadAnimatedCursor(int id, int resource_id, int hot_x, int hot_y) {
456 const gfx::ImageSkia* image =
457 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
458 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(
459 ui::GetScaleFactorFromScale(scale_factor_));
460 const SkBitmap bitmap = image_rep.sk_bitmap();
461 DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config);
462 int frame_width = bitmap.height();
463 int frame_height = frame_width;
464 int total_width = bitmap.width();
465 DCHECK_EQ(total_width % frame_width, 0);
466 int frame_count = total_width / frame_width;
467 DCHECK_GT(frame_count, 0);
468 XcursorImages* x_images = XcursorImagesCreate(frame_count);
469 x_images->nimage = frame_count;
470 bitmap.lockPixels();
471 unsigned int* pixels = bitmap.getAddr32(0, 0);
472 // Create each frame.
473 for (int i = 0; i < frame_count; ++i) {
474 XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height);
475 for (int j = 0; j < frame_height; ++j) {
476 // Copy j'th row of i'th frame.
477 memcpy(x_image->pixels + j * frame_width,
478 pixels + i * frame_width + j * total_width,
479 frame_width * 4);
480 }
481 x_image->xhot = hot_x * scale_factor_;
482 x_image->yhot = hot_y * scale_factor_;
483 x_image->delay = kAnimatedCursorFrameDelayMs;
484 x_images->images[i] = x_image;
485 }
486 bitmap.unlockPixels();
487
488 animated_cursors_[id] = std::make_pair(
489 XcursorImagesLoadCursor(ui::GetXDisplay(), x_images), x_images);
490 // |bitmap| is owned by the resource bundle. So we do not need to free it.
491 }
492
493 // A map to hold all image cursors. It maps the cursor ID to the X Cursor.
494 std::map<int, Cursor> cursors_;
495
496 // A map to hold all animated cursors. It maps the cursor ID to the pair of
497 // the X Cursor and the corresponding XcursorImages. We need a pointer to the
498 // images so that we can free them on destruction.
499 typedef std::map<int, std::pair<Cursor, XcursorImages*> > AnimatedCursorMap;
500 AnimatedCursorMap animated_cursors_;
501
502 float scale_factor_;
503
504 DISALLOW_COPY_AND_ASSIGN(ImageCursors);
505 };
506
507 RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, 239 RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate,
508 const gfx::Rect& bounds) 240 const gfx::Rect& bounds)
509 : delegate_(delegate), 241 : delegate_(delegate),
510 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), 242 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
511 xwindow_(0), 243 xwindow_(0),
512 x_root_window_(DefaultRootWindow(xdisplay_)), 244 x_root_window_(DefaultRootWindow(xdisplay_)),
513 current_cursor_(ui::kCursorNull), 245 current_cursor_(ui::kCursorNull),
514 window_mapped_(false), 246 window_mapped_(false),
515 cursor_shown_(true), 247 cursor_shown_(true),
516 bounds_(bounds), 248 bounds_(bounds),
517 focus_when_shown_(false), 249 focus_when_shown_(false),
518 pointer_barriers_(NULL), 250 pointer_barriers_(NULL),
519 image_cursors_(new ImageCursors),
520 atom_cache_(xdisplay_, kAtomsToCache) { 251 atom_cache_(xdisplay_, kAtomsToCache) {
521 XSetWindowAttributes swa; 252 XSetWindowAttributes swa;
522 memset(&swa, 0, sizeof(swa)); 253 memset(&swa, 0, sizeof(swa));
523 swa.background_pixmap = None; 254 swa.background_pixmap = None;
524 xwindow_ = XCreateWindow( 255 xwindow_ = XCreateWindow(
525 xdisplay_, x_root_window_, 256 xdisplay_, x_root_window_,
526 bounds.x(), bounds.y(), bounds.width(), bounds.height(), 257 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
527 0, // border width 258 0, // border width
528 CopyFromParent, // depth 259 CopyFromParent, // depth
529 InputOutput, 260 InputOutput,
530 CopyFromParent, // visual 261 CopyFromParent, // visual
531 CWBackPixmap, 262 CWBackPixmap,
532 &swa); 263 &swa);
533 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); 264 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_);
534 265
535 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); 266 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this));
536 267
537 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | 268 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
538 KeyPressMask | KeyReleaseMask | 269 KeyPressMask | KeyReleaseMask |
539 EnterWindowMask | LeaveWindowMask | 270 EnterWindowMask | LeaveWindowMask |
540 ExposureMask | VisibilityChangeMask | 271 ExposureMask | VisibilityChangeMask |
541 StructureNotifyMask | PropertyChangeMask | 272 StructureNotifyMask | PropertyChangeMask |
542 PointerMotionMask; 273 PointerMotionMask;
543 XSelectInput(xdisplay_, xwindow_, event_mask); 274 XSelectInput(xdisplay_, xwindow_, event_mask);
544 XFlush(xdisplay_); 275 XFlush(xdisplay_);
545 276
546 if (base::MessagePumpForUI::HasXInput2()) 277 if (base::MessagePumpForUI::HasXInput2())
547 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); 278 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
548 279
549 // Initialize invisible cursor.
550 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
551 XColor black;
552 black.red = black.green = black.blue = 0;
553 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_,
554 nodata, 8, 8);
555 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank,
556 &black, &black, 0, 0);
557 XFreePixmap(xdisplay_, blank);
558
559 if (RootWindow::hide_host_cursor())
560 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_);
561
562 // TODO(erg): We currently only request window deletion events. We also 280 // TODO(erg): We currently only request window deletion events. We also
563 // should listen for activation events and anything else that GTK+ listens 281 // should listen for activation events and anything else that GTK+ listens
564 // for, and do something useful. 282 // for, and do something useful.
565 ::Atom protocols[2]; 283 ::Atom protocols[2];
566 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); 284 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
567 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); 285 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
568 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); 286 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
569 287
570 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with 288 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
571 // the desktop environment. 289 // the desktop environment.
(...skipping 19 matching lines...) Expand all
591 XRRSelectInput(xdisplay_, x_root_window_, 309 XRRSelectInput(xdisplay_, x_root_window_,
592 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); 310 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
593 } 311 }
594 312
595 RootWindowHostLinux::~RootWindowHostLinux() { 313 RootWindowHostLinux::~RootWindowHostLinux() {
596 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); 314 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
597 315
598 UnConfineCursor(); 316 UnConfineCursor();
599 317
600 XDestroyWindow(xdisplay_, xwindow_); 318 XDestroyWindow(xdisplay_, xwindow_);
601
602 // Clears XCursorCache.
603 ui::GetXCursor(ui::kCursorClearXCursorCache);
604
605 XFreeCursor(xdisplay_, invisible_cursor_);
606 } 319 }
607 320
608 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { 321 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
609 XEvent* xev = event; 322 XEvent* xev = event;
610 323
611 CheckXEventForConsistency(xev); 324 CheckXEventForConsistency(xev);
612 325
613 switch (xev->type) { 326 switch (xev->type) {
oshima 2012/09/07 19:52:01 there may be a case where a mouse is sent to outsi
mazda 2012/09/07 22:38:14 Instead of setting the cursor here, I added code t
oshima 2012/09/07 23:08:20 If we always update scale factor in CompoundEventF
mazda 2012/09/08 00:27:02 As far as I tested it on desktop, it looks a wrong
oshima 2012/09/08 01:26:53 sure. My guess is that the gap between EnterNotify
614 case Expose: 327 case Expose:
615 delegate_->AsRootWindow()->ScheduleFullDraw(); 328 delegate_->AsRootWindow()->ScheduleFullDraw();
616 break; 329 break;
617 case KeyPress: { 330 case KeyPress: {
618 ui::KeyEvent keydown_event(xev, false); 331 ui::KeyEvent keydown_event(xev, false);
619 delegate_->OnHostKeyEvent(&keydown_event); 332 delegate_->OnHostKeyEvent(&keydown_event);
620 break; 333 break;
621 } 334 }
622 case KeyRelease: { 335 case KeyRelease: {
623 ui::KeyEvent keyup_event(xev, false); 336 ui::KeyEvent keyup_event(xev, false);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 client::ScreenPositionClient* client = 379 client::ScreenPositionClient* client =
667 client::GetScreenPositionClient(root); 380 client::GetScreenPositionClient(root);
668 if (client) { 381 if (client) {
669 gfx::Point p = gfx::Screen::GetCursorScreenPoint(); 382 gfx::Point p = gfx::Screen::GetCursorScreenPoint();
670 client->ConvertPointFromScreen(root, &p); 383 client->ConvertPointFromScreen(root, &p);
671 if (root->ContainsPoint(p)) { 384 if (root->ContainsPoint(p)) {
672 root->ConvertPointToNativeScreen(&p); 385 root->ConvertPointToNativeScreen(&p);
673 XWarpPointer( 386 XWarpPointer(
674 xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y()); 387 xdisplay_, None, x_root_window_, 0, 0, 0, 0, p.x(), p.y());
675 } 388 }
676 } 389 }
oshima 2012/09/07 19:52:01 if you update cursor upon EnterNotify, you probabl
mazda 2012/09/07 22:38:14 As I wrote in another comment, XWarpPointer causes
677 ConfineCursorToRootWindow(); 390 ConfineCursorToRootWindow();
678 } 391 }
679 if (size_changed) 392 if (size_changed)
680 delegate_->OnHostResized(bounds.size()); 393 delegate_->OnHostResized(bounds.size());
681 if (origin_changed) 394 if (origin_changed)
682 delegate_->OnHostMoved(bounds_.origin()); 395 delegate_->OnHostMoved(bounds_.origin());
683 break; 396 break;
684 } 397 }
685 case GenericEvent: { 398 case GenericEvent: {
686 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 399 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 542
830 RootWindow* RootWindowHostLinux::GetRootWindow() { 543 RootWindow* RootWindowHostLinux::GetRootWindow() {
831 return delegate_->AsRootWindow(); 544 return delegate_->AsRootWindow();
832 } 545 }
833 546
834 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { 547 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() {
835 return xwindow_; 548 return xwindow_;
836 } 549 }
837 550
838 void RootWindowHostLinux::Show() { 551 void RootWindowHostLinux::Show() {
839 // The device scale factor is now accessible, so load cursors now.
840 image_cursors_->Reload(delegate_->GetDeviceScaleFactor());
841
842 if (!window_mapped_) { 552 if (!window_mapped_) {
843 // Before we map the window, set size hints. Otherwise, some window managers 553 // Before we map the window, set size hints. Otherwise, some window managers
844 // will ignore toplevel XMoveWindow commands. 554 // will ignore toplevel XMoveWindow commands.
845 XSizeHints size_hints; 555 XSizeHints size_hints;
846 size_hints.flags = PPosition; 556 size_hints.flags = PPosition;
847 size_hints.x = bounds_.x(); 557 size_hints.x = bounds_.x();
848 size_hints.y = bounds_.y(); 558 size_hints.y = bounds_.y();
849 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); 559 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
850 560
851 XMapWindow(xdisplay_, xwindow_); 561 XMapWindow(xdisplay_, xwindow_);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 current_cursor_ = cursor; 630 current_cursor_ = cursor;
921 631
922 if (cursor_shown_) 632 if (cursor_shown_)
923 SetCursorInternal(cursor); 633 SetCursorInternal(cursor);
924 } 634 }
925 635
926 void RootWindowHostLinux::ShowCursor(bool show) { 636 void RootWindowHostLinux::ShowCursor(bool show) {
927 if (show == cursor_shown_) 637 if (show == cursor_shown_)
928 return; 638 return;
929 cursor_shown_ = show; 639 cursor_shown_ = show;
930 SetCursorInternal(show ? current_cursor_ : ui::kCursorNone); 640 client::CursorClient* cursor_client =
641 client::GetCursorClient(GetRootWindow());
642 if (cursor_client)
643 cursor_client->SetCursor(show ? current_cursor_ : ui::kCursorNone);
931 } 644 }
932 645
933 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { 646 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) {
934 ::Window root_return, child_return; 647 ::Window root_return, child_return;
935 int root_x_return, root_y_return, win_x_return, win_y_return; 648 int root_x_return, root_y_return, win_x_return, win_y_return;
936 unsigned int mask_return; 649 unsigned int mask_return;
937 XQueryPointer(xdisplay_, 650 XQueryPointer(xdisplay_,
938 xwindow_, 651 xwindow_,
939 &root_return, 652 &root_return,
940 &child_return, 653 &child_return,
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 xevent.xmotion.y_root = point.y(); 800 xevent.xmotion.y_root = point.y();
1088 } 801 }
1089 default: 802 default:
1090 break; 803 break;
1091 } 804 }
1092 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); 805 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
1093 } 806 }
1094 807
1095 void RootWindowHostLinux::OnDeviceScaleFactorChanged( 808 void RootWindowHostLinux::OnDeviceScaleFactorChanged(
1096 float device_scale_factor) { 809 float device_scale_factor) {
1097 image_cursors_->Reload(device_scale_factor);
1098 } 810 }
1099 811
1100 bool RootWindowHostLinux::IsWindowManagerPresent() { 812 bool RootWindowHostLinux::IsWindowManagerPresent() {
1101 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 813 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
1102 // of WM_Sn selections (where n is a screen number). 814 // of WM_Sn selections (where n is a screen number).
1103 return XGetSelectionOwner( 815 return XGetSelectionOwner(
1104 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; 816 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
1105 } 817 }
1106 818
1107 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { 819 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
1108 // At times the cursor on the RootWindow is set before it is displayed. So 820 XDefineCursor(xdisplay_, xwindow_, cursor.platform());
1109 // make sure the image-cursors are initialized properly before setting it.
1110 image_cursors_->Reload(delegate_->GetDeviceScaleFactor());
1111
1112 ::Cursor xcursor;
1113 if (image_cursors_->IsImageCursor(cursor))
1114 xcursor = image_cursors_->ImageCursorFromNative(cursor);
1115 else if (cursor == ui::kCursorNone)
1116 xcursor = invisible_cursor_;
1117 else if (cursor == ui::kCursorCustom)
1118 xcursor = cursor.platform();
1119 else if (delegate_->GetDeviceScaleFactor() == 1.0)
1120 xcursor = ui::GetXCursor(CursorShapeFromNative(cursor));
1121 else
1122 xcursor = image_cursors_->ImageCursorFromNative(ui::kCursorPointer);
1123 XDefineCursor(xdisplay_, xwindow_, xcursor);
1124 } 821 }
1125 822
1126 // static 823 // static
1127 RootWindowHost* RootWindowHost::Create(RootWindowHostDelegate* delegate, 824 RootWindowHost* RootWindowHost::Create(RootWindowHostDelegate* delegate,
1128 const gfx::Rect& bounds) { 825 const gfx::Rect& bounds) {
1129 return new RootWindowHostLinux(delegate, bounds); 826 return new RootWindowHostLinux(delegate, bounds);
1130 } 827 }
1131 828
1132 // static 829 // static
1133 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( 830 RootWindowHost* RootWindowHost::GetForAcceleratedWidget(
1134 gfx::AcceleratedWidget accelerated_widget) { 831 gfx::AcceleratedWidget accelerated_widget) {
1135 return reinterpret_cast<RootWindowHost*>( 832 return reinterpret_cast<RootWindowHost*>(
1136 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); 833 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey));
1137 } 834 }
1138 835
1139 // static 836 // static
1140 gfx::Size RootWindowHost::GetNativeScreenSize() { 837 gfx::Size RootWindowHost::GetNativeScreenSize() {
1141 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); 838 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay();
1142 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 839 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
1143 } 840 }
1144 841
1145 } // namespace aura 842 } // namespace aura
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698