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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |