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 |