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/x11_util.h" | 32 #include "ui/base/x/x11_util.h" |
34 #include "ui/compositor/layer.h" | 33 #include "ui/compositor/layer.h" |
35 #include "ui/gfx/codec/png_codec.h" | 34 #include "ui/gfx/codec/png_codec.h" |
36 #include "ui/gfx/image/image.h" | |
37 #include "ui/gfx/image/image_skia.h" | |
38 #include "ui/gfx/screen.h" | 35 #include "ui/gfx/screen.h" |
39 | 36 |
40 using std::max; | 37 using std::max; |
41 using std::min; | 38 using std::min; |
42 | 39 |
43 namespace aura { | 40 namespace aura { |
44 | 41 |
45 namespace { | 42 namespace { |
46 | 43 |
47 // Standard Linux mouse buttons for going back and forward. | 44 // Standard Linux mouse buttons for going back and forward. |
48 const int kBackMouseButton = 8; | 45 const int kBackMouseButton = 8; |
49 const int kForwardMouseButton = 9; | 46 const int kForwardMouseButton = 9; |
50 | 47 |
51 const int kAnimatedCursorFrameDelayMs = 25; | |
52 | |
53 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; | 48 const char kRootWindowHostLinuxKey[] = "__AURA_ROOT_WINDOW_HOST_LINUX__"; |
54 | 49 |
55 const char* kAtomsToCache[] = { | 50 const char* kAtomsToCache[] = { |
56 "WM_DELETE_WINDOW", | 51 "WM_DELETE_WINDOW", |
57 "_NET_WM_PING", | 52 "_NET_WM_PING", |
58 "_NET_WM_PID", | 53 "_NET_WM_PID", |
59 "WM_S0", | 54 "WM_S0", |
60 NULL | 55 NULL |
61 }; | 56 }; |
62 | 57 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); | 99 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); |
105 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); | 100 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); |
106 CHECK_EQ(slave_event.mods.base, xievent->mods.base); | 101 CHECK_EQ(slave_event.mods.base, xievent->mods.base); |
107 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); | 102 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); |
108 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); | 103 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); |
109 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); | 104 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); |
110 } | 105 } |
111 #endif // defined(USE_XI2_MT) && !defined(NDEBUG) | 106 #endif // defined(USE_XI2_MT) && !defined(NDEBUG) |
112 } | 107 } |
113 | 108 |
114 // Returns X font cursor shape from an Aura cursor. | |
115 int CursorShapeFromNative(gfx::NativeCursor native_cursor) { | |
116 switch (native_cursor.native_type()) { | |
117 case ui::kCursorMiddlePanning: | |
118 return XC_fleur; | |
119 case ui::kCursorEastPanning: | |
120 return XC_sb_right_arrow; | |
121 case ui::kCursorNorthPanning: | |
122 return XC_sb_up_arrow; | |
123 case ui::kCursorNorthEastPanning: | |
124 return XC_top_right_corner; | |
125 case ui::kCursorNorthWestPanning: | |
126 return XC_top_left_corner; | |
127 case ui::kCursorSouthPanning: | |
128 return XC_sb_down_arrow; | |
129 case ui::kCursorSouthEastPanning: | |
130 return XC_bottom_right_corner; | |
131 case ui::kCursorSouthWestPanning: | |
132 return XC_bottom_left_corner; | |
133 case ui::kCursorWestPanning: | |
134 return XC_sb_left_arrow; | |
135 case ui::kCursorNone: | |
136 // TODO(jamescook): Need cursors for these. crbug.com/111650 | |
137 return XC_left_ptr; | |
138 | |
139 case ui::kCursorNull: | |
140 case ui::kCursorPointer: | |
141 case ui::kCursorNoDrop: | |
142 case ui::kCursorNotAllowed: | |
143 case ui::kCursorCopy: | |
144 case ui::kCursorMove: | |
145 case ui::kCursorEastResize: | |
146 case ui::kCursorNorthResize: | |
147 case ui::kCursorSouthResize: | |
148 case ui::kCursorWestResize: | |
149 case ui::kCursorNorthEastResize: | |
150 case ui::kCursorNorthWestResize: | |
151 case ui::kCursorSouthWestResize: | |
152 case ui::kCursorSouthEastResize: | |
153 case ui::kCursorIBeam: | |
154 case ui::kCursorAlias: | |
155 case ui::kCursorCell: | |
156 case ui::kCursorContextMenu: | |
157 case ui::kCursorCross: | |
158 case ui::kCursorHelp: | |
159 case ui::kCursorWait: | |
160 case ui::kCursorNorthSouthResize: | |
161 case ui::kCursorEastWestResize: | |
162 case ui::kCursorNorthEastSouthWestResize: | |
163 case ui::kCursorNorthWestSouthEastResize: | |
164 case ui::kCursorProgress: | |
165 case ui::kCursorColumnResize: | |
166 case ui::kCursorRowResize: | |
167 case ui::kCursorVerticalText: | |
168 case ui::kCursorZoomIn: | |
169 case ui::kCursorZoomOut: | |
170 case ui::kCursorGrab: | |
171 case ui::kCursorGrabbing: | |
172 NOTREACHED() << "Cursor (" << native_cursor.native_type() << ") should " | |
173 << "have an image asset."; | |
174 return XC_left_ptr; | |
175 case ui::kCursorCustom: | |
176 NOTREACHED(); | |
177 return XC_left_ptr; | |
178 } | |
179 NOTREACHED(); | |
180 return XC_left_ptr; | |
181 } | |
182 | |
183 // Coalesce all pending motion events that are at the top of the queue, and | 109 // Coalesce all pending motion events that are at the top of the queue, and |
184 // return the number eliminated, storing the last one in |last_event|. | 110 // return the number eliminated, storing the last one in |last_event|. |
185 int CoalescePendingXIMotionEvents(const XEvent* xev, XEvent* last_event) { | 111 int CoalescePendingXIMotionEvents(const XEvent* xev, XEvent* last_event) { |
186 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 112 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
187 int num_coalesed = 0; | 113 int num_coalesed = 0; |
188 Display* display = xev->xany.display; | 114 Display* display = xev->xany.display; |
189 | 115 |
190 while (XPending(display)) { | 116 while (XPending(display)) { |
191 XEvent next_event; | 117 XEvent next_event; |
192 XPeekEvent(display, &next_event); | 118 XPeekEvent(display, &next_event); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 case ui::VKEY_OEM_MINUS: | 204 case ui::VKEY_OEM_MINUS: |
279 case ui::VKEY_OEM_PERIOD: | 205 case ui::VKEY_OEM_PERIOD: |
280 return true; | 206 return true; |
281 default: | 207 default: |
282 return false; | 208 return false; |
283 } | 209 } |
284 } | 210 } |
285 | 211 |
286 } // namespace | 212 } // namespace |
287 | 213 |
288 // A utility class that provides X Cursor for NativeCursors for which we have | |
289 // image resources. | |
290 class RootWindowHostLinux::ImageCursors { | |
291 public: | |
292 ImageCursors() : scale_factor_(0.0) { | |
293 } | |
294 | |
295 void Reload(float scale_factor) { | |
296 if (scale_factor_ == scale_factor) | |
297 return; | |
298 scale_factor_ = scale_factor; | |
299 UnloadAll(); | |
300 // The cursor's hot points are defined in chromeos cursor images at: | |
301 // http://folder/kuscher/projects/Chrome_OS/Pointers/focuspoint | |
302 LoadImageCursor(ui::kCursorNull, IDR_AURA_CURSOR_PTR, | |
303 gfx::Point(4, 4), gfx::Point(8, 9)); | |
304 LoadImageCursor(ui::kCursorPointer, IDR_AURA_CURSOR_PTR, | |
305 gfx::Point(4, 4), gfx::Point(8, 9)); | |
306 LoadImageCursor(ui::kCursorNoDrop, IDR_AURA_CURSOR_NO_DROP, | |
307 gfx::Point(4, 4), gfx::Point(8, 9)); | |
308 LoadImageCursor(ui::kCursorNotAllowed, IDR_AURA_CURSOR_NO_DROP, | |
309 gfx::Point(4, 4), gfx::Point(8, 9)); | |
310 LoadImageCursor(ui::kCursorCopy, IDR_AURA_CURSOR_COPY, | |
311 gfx::Point(4, 4), gfx::Point(8, 9)); | |
312 LoadImageCursor(ui::kCursorHand, IDR_AURA_CURSOR_HAND, | |
313 gfx::Point(9, 4), gfx::Point(19, 8)); | |
314 LoadImageCursor(ui::kCursorMove, IDR_AURA_CURSOR_MOVE, | |
315 gfx::Point(11, 11), gfx::Point(23, 23)); | |
316 LoadImageCursor(ui::kCursorNorthEastResize, | |
317 IDR_AURA_CURSOR_NORTH_EAST_RESIZE, | |
318 gfx::Point(12, 11), gfx::Point(25, 23)); | |
319 LoadImageCursor(ui::kCursorSouthWestResize, | |
320 IDR_AURA_CURSOR_SOUTH_WEST_RESIZE, | |
321 gfx::Point(12, 11), gfx::Point(25, 23)); | |
322 LoadImageCursor(ui::kCursorSouthEastResize, | |
323 IDR_AURA_CURSOR_SOUTH_EAST_RESIZE, | |
324 gfx::Point(11, 11), gfx::Point(24, 23)); | |
325 LoadImageCursor(ui::kCursorNorthWestResize, | |
326 IDR_AURA_CURSOR_NORTH_WEST_RESIZE, | |
327 gfx::Point(11, 11), gfx::Point(24, 23)); | |
328 LoadImageCursor(ui::kCursorNorthResize, IDR_AURA_CURSOR_NORTH_RESIZE, | |
329 gfx::Point(11, 12), gfx::Point(23, 23)); | |
330 LoadImageCursor(ui::kCursorSouthResize, IDR_AURA_CURSOR_SOUTH_RESIZE, | |
331 gfx::Point(11, 12), gfx::Point(23, 23)); | |
332 LoadImageCursor(ui::kCursorEastResize, IDR_AURA_CURSOR_EAST_RESIZE, | |
333 gfx::Point(12, 11), gfx::Point(25, 23)); | |
334 LoadImageCursor(ui::kCursorWestResize, IDR_AURA_CURSOR_WEST_RESIZE, | |
335 gfx::Point(12, 11), gfx::Point(25, 23)); | |
336 LoadImageCursor(ui::kCursorIBeam, IDR_AURA_CURSOR_IBEAM, | |
337 gfx::Point(12, 12), gfx::Point(24, 25)); | |
338 LoadImageCursor(ui::kCursorAlias, IDR_AURA_CURSOR_ALIAS, | |
339 gfx::Point(8, 6), gfx::Point(15, 11)); | |
340 LoadImageCursor(ui::kCursorCell, IDR_AURA_CURSOR_CELL, | |
341 gfx::Point(11, 11), gfx::Point(24, 23)); | |
342 LoadImageCursor(ui::kCursorContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, | |
343 gfx::Point(4, 4), gfx::Point(8, 9)); | |
344 LoadImageCursor(ui::kCursorCross, IDR_AURA_CURSOR_CROSSHAIR, | |
345 gfx::Point(12, 12), gfx::Point(25, 23)); | |
346 LoadImageCursor(ui::kCursorHelp, IDR_AURA_CURSOR_HELP, | |
347 gfx::Point(4, 4), gfx::Point(8, 9)); | |
348 LoadImageCursor(ui::kCursorVerticalText, IDR_AURA_CURSOR_XTERM_HORIZ, | |
349 gfx::Point(12, 11), gfx::Point(26, 23)); | |
350 LoadImageCursor(ui::kCursorZoomIn, IDR_AURA_CURSOR_ZOOM_IN, | |
351 gfx::Point(10, 10), gfx::Point(20, 20)); | |
352 LoadImageCursor(ui::kCursorZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, | |
353 gfx::Point(10, 10), gfx::Point(20, 20)); | |
354 LoadImageCursor(ui::kCursorRowResize, IDR_AURA_CURSOR_ROW_RESIZE, | |
355 gfx::Point(11, 12), gfx::Point(23, 23)); | |
356 LoadImageCursor(ui::kCursorColumnResize, IDR_AURA_CURSOR_COL_RESIZE, | |
357 gfx::Point(12, 11), gfx::Point(25, 23)); | |
358 LoadImageCursor(ui::kCursorEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE, | |
359 gfx::Point(12, 11), gfx::Point(25, 23)); | |
360 LoadImageCursor(ui::kCursorNorthSouthResize, | |
361 IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, | |
362 gfx::Point(11, 12), gfx::Point(23, 23)); | |
363 LoadImageCursor(ui::kCursorNorthEastSouthWestResize, | |
364 IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, | |
365 gfx::Point(12, 11), gfx::Point(25, 23)); | |
366 LoadImageCursor(ui::kCursorNorthWestSouthEastResize, | |
367 IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, | |
368 gfx::Point(11, 11), gfx::Point(24, 23)); | |
369 LoadImageCursor(ui::kCursorGrab, IDR_AURA_CURSOR_GRAB, | |
370 gfx::Point(8, 5), gfx::Point(16, 10)); | |
371 LoadImageCursor(ui::kCursorGrabbing, IDR_AURA_CURSOR_GRABBING, | |
372 gfx::Point(9, 9), gfx::Point(18, 18)); | |
373 LoadAnimatedCursor(ui::kCursorWait, IDR_THROBBER, 7, 7); | |
374 LoadAnimatedCursor(ui::kCursorProgress, IDR_THROBBER, 7, 7); | |
375 } | |
376 | |
377 ~ImageCursors() { | |
378 UnloadAll(); | |
379 } | |
380 | |
381 void UnloadAll() { | |
382 for (std::map<int, Cursor>::const_iterator it = cursors_.begin(); | |
383 it != cursors_.end(); ++it) | |
384 ui::UnrefCustomXCursor(it->second); | |
385 | |
386 // Free animated cursors and images. | |
387 for (AnimatedCursorMap::iterator it = animated_cursors_.begin(); | |
388 it != animated_cursors_.end(); ++it) { | |
389 XcursorImagesDestroy(it->second.second); // also frees individual frames. | |
390 XFreeCursor(ui::GetXDisplay(), it->second.first); | |
391 } | |
392 } | |
393 | |
394 // Returns true if we have an image resource loaded for the |native_cursor|. | |
395 bool IsImageCursor(gfx::NativeCursor native_cursor) { | |
396 int type = native_cursor.native_type(); | |
397 return cursors_.find(type) != cursors_.end() || | |
398 animated_cursors_.find(type) != animated_cursors_.end(); | |
399 } | |
400 | |
401 // Gets the X Cursor corresponding to the |native_cursor|. | |
402 ::Cursor ImageCursorFromNative(gfx::NativeCursor native_cursor) { | |
403 int type = native_cursor.native_type(); | |
404 if (animated_cursors_.find(type) != animated_cursors_.end()) | |
405 return animated_cursors_[type].first; | |
406 DCHECK(cursors_.find(type) != cursors_.end()); | |
407 return cursors_[type]; | |
408 } | |
409 | |
410 private: | |
411 // Creates an X Cursor from an image resource and puts it in the cursor map. | |
412 void LoadImageCursor(int id, | |
413 int resource_id, | |
414 const gfx::Point& hot_1x, | |
415 const gfx::Point& hot_2x) { | |
416 const gfx::ImageSkia* image = | |
417 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); | |
418 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( | |
419 ui::GetScaleFactorFromScale(scale_factor_)); | |
420 const gfx::Point& hot = (scale_factor_ == 1) ? hot_1x : hot_2x; | |
421 XcursorImage* x_image = | |
422 ui::SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot); | |
423 cursors_[id] = ui::CreateReffedCustomXCursor(x_image); | |
424 // |bitmap| is owned by the resource bundle. So we do not need to free it. | |
425 } | |
426 | |
427 // Creates an animated X Cursor from an image resource and puts it in the | |
428 // cursor map. The image is assumed to be a concatenation of animation frames. | |
429 // Also, each frame is assumed to be square (width == height) | |
430 void LoadAnimatedCursor(int id, int resource_id, int hot_x, int hot_y) { | |
431 const gfx::ImageSkia* image = | |
432 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); | |
433 const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( | |
434 ui::GetScaleFactorFromScale(scale_factor_)); | |
435 const SkBitmap bitmap = image_rep.sk_bitmap(); | |
436 DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config); | |
437 int frame_width = bitmap.height(); | |
438 int frame_height = frame_width; | |
439 int total_width = bitmap.width(); | |
440 DCHECK_EQ(total_width % frame_width, 0); | |
441 int frame_count = total_width / frame_width; | |
442 DCHECK_GT(frame_count, 0); | |
443 XcursorImages* x_images = XcursorImagesCreate(frame_count); | |
444 x_images->nimage = frame_count; | |
445 bitmap.lockPixels(); | |
446 unsigned int* pixels = bitmap.getAddr32(0, 0); | |
447 // Create each frame. | |
448 for (int i = 0; i < frame_count; ++i) { | |
449 XcursorImage* x_image = XcursorImageCreate(frame_width, frame_height); | |
450 for (int j = 0; j < frame_height; ++j) { | |
451 // Copy j'th row of i'th frame. | |
452 memcpy(x_image->pixels + j * frame_width, | |
453 pixels + i * frame_width + j * total_width, | |
454 frame_width * 4); | |
455 } | |
456 x_image->xhot = hot_x * scale_factor_; | |
457 x_image->yhot = hot_y * scale_factor_; | |
458 x_image->delay = kAnimatedCursorFrameDelayMs; | |
459 x_images->images[i] = x_image; | |
460 } | |
461 bitmap.unlockPixels(); | |
462 | |
463 animated_cursors_[id] = std::make_pair( | |
464 XcursorImagesLoadCursor(ui::GetXDisplay(), x_images), x_images); | |
465 // |bitmap| is owned by the resource bundle. So we do not need to free it. | |
466 } | |
467 | |
468 // A map to hold all image cursors. It maps the cursor ID to the X Cursor. | |
469 std::map<int, Cursor> cursors_; | |
470 | |
471 // A map to hold all animated cursors. It maps the cursor ID to the pair of | |
472 // the X Cursor and the corresponding XcursorImages. We need a pointer to the | |
473 // images so that we can free them on destruction. | |
474 typedef std::map<int, std::pair<Cursor, XcursorImages*> > AnimatedCursorMap; | |
475 AnimatedCursorMap animated_cursors_; | |
476 | |
477 float scale_factor_; | |
478 | |
479 DISALLOW_COPY_AND_ASSIGN(ImageCursors); | |
480 }; | |
481 | |
482 RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, | 214 RootWindowHostLinux::RootWindowHostLinux(RootWindowHostDelegate* delegate, |
483 const gfx::Rect& bounds) | 215 const gfx::Rect& bounds) |
484 : delegate_(delegate), | 216 : delegate_(delegate), |
485 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), | 217 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), |
486 xwindow_(0), | 218 xwindow_(0), |
487 x_root_window_(DefaultRootWindow(xdisplay_)), | 219 x_root_window_(DefaultRootWindow(xdisplay_)), |
488 current_cursor_(ui::kCursorNull), | 220 current_cursor_(ui::kCursorNull), |
489 window_mapped_(false), | 221 window_mapped_(false), |
490 cursor_shown_(true), | 222 cursor_shown_(true), |
491 bounds_(bounds), | 223 bounds_(bounds), |
492 focus_when_shown_(false), | 224 focus_when_shown_(false), |
493 pointer_barriers_(NULL), | 225 pointer_barriers_(NULL), |
494 image_cursors_(new ImageCursors), | |
495 atom_cache_(xdisplay_, kAtomsToCache) { | 226 atom_cache_(xdisplay_, kAtomsToCache) { |
496 XSetWindowAttributes swa; | 227 XSetWindowAttributes swa; |
497 memset(&swa, 0, sizeof(swa)); | 228 memset(&swa, 0, sizeof(swa)); |
498 swa.background_pixmap = None; | 229 swa.background_pixmap = None; |
499 xwindow_ = XCreateWindow( | 230 xwindow_ = XCreateWindow( |
500 xdisplay_, x_root_window_, | 231 xdisplay_, x_root_window_, |
501 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 232 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
502 0, // border width | 233 0, // border width |
503 CopyFromParent, // depth | 234 CopyFromParent, // depth |
504 InputOutput, | 235 InputOutput, |
505 CopyFromParent, // visual | 236 CopyFromParent, // visual |
506 CWBackPixmap, | 237 CWBackPixmap, |
507 &swa); | 238 &swa); |
508 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); | 239 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); |
509 | 240 |
510 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); | 241 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); |
511 | 242 |
512 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 243 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
513 KeyPressMask | KeyReleaseMask | | 244 KeyPressMask | KeyReleaseMask | |
514 EnterWindowMask | LeaveWindowMask | | 245 EnterWindowMask | LeaveWindowMask | |
515 ExposureMask | VisibilityChangeMask | | 246 ExposureMask | VisibilityChangeMask | |
516 StructureNotifyMask | PropertyChangeMask | | 247 StructureNotifyMask | PropertyChangeMask | |
517 PointerMotionMask; | 248 PointerMotionMask; |
518 XSelectInput(xdisplay_, xwindow_, event_mask); | 249 XSelectInput(xdisplay_, xwindow_, event_mask); |
519 XFlush(xdisplay_); | 250 XFlush(xdisplay_); |
520 | 251 |
521 if (base::MessagePumpForUI::HasXInput2()) | 252 if (base::MessagePumpForUI::HasXInput2()) |
522 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 253 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
523 | 254 |
524 // Initialize invisible cursor. | |
525 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
526 XColor black; | |
527 black.red = black.green = black.blue = 0; | |
528 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, | |
529 nodata, 8, 8); | |
530 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, | |
531 &black, &black, 0, 0); | |
532 XFreePixmap(xdisplay_, blank); | |
533 | |
534 if (RootWindow::hide_host_cursor()) | |
535 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_); | |
536 | |
537 // TODO(erg): We currently only request window deletion events. We also | 255 // TODO(erg): We currently only request window deletion events. We also |
538 // should listen for activation events and anything else that GTK+ listens | 256 // should listen for activation events and anything else that GTK+ listens |
539 // for, and do something useful. | 257 // for, and do something useful. |
540 ::Atom protocols[2]; | 258 ::Atom protocols[2]; |
541 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); | 259 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); |
542 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); | 260 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); |
543 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); | 261 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); |
544 | 262 |
545 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with | 263 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with |
546 // the desktop environment. | 264 // the desktop environment. |
(...skipping 19 matching lines...) Expand all Loading... |
566 XRRSelectInput(xdisplay_, x_root_window_, | 284 XRRSelectInput(xdisplay_, x_root_window_, |
567 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); | 285 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); |
568 } | 286 } |
569 | 287 |
570 RootWindowHostLinux::~RootWindowHostLinux() { | 288 RootWindowHostLinux::~RootWindowHostLinux() { |
571 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); | 289 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); |
572 | 290 |
573 UnConfineCursor(); | 291 UnConfineCursor(); |
574 | 292 |
575 XDestroyWindow(xdisplay_, xwindow_); | 293 XDestroyWindow(xdisplay_, xwindow_); |
576 | |
577 // Clears XCursorCache. | |
578 ui::GetXCursor(ui::kCursorClearXCursorCache); | |
579 | |
580 XFreeCursor(xdisplay_, invisible_cursor_); | |
581 } | 294 } |
582 | 295 |
583 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { | 296 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { |
584 XEvent* xev = event; | 297 XEvent* xev = event; |
585 | 298 |
586 CheckXEventForConsistency(xev); | 299 CheckXEventForConsistency(xev); |
587 | 300 |
588 switch (xev->type) { | 301 switch (xev->type) { |
589 case Expose: | 302 case Expose: |
590 delegate_->AsRootWindow()->ScheduleFullDraw(); | 303 delegate_->AsRootWindow()->ScheduleFullDraw(); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 | 513 |
801 RootWindow* RootWindowHostLinux::GetRootWindow() { | 514 RootWindow* RootWindowHostLinux::GetRootWindow() { |
802 return delegate_->AsRootWindow(); | 515 return delegate_->AsRootWindow(); |
803 } | 516 } |
804 | 517 |
805 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { | 518 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { |
806 return xwindow_; | 519 return xwindow_; |
807 } | 520 } |
808 | 521 |
809 void RootWindowHostLinux::Show() { | 522 void RootWindowHostLinux::Show() { |
810 // The device scale factor is now accessible, so load cursors now. | |
811 image_cursors_->Reload(delegate_->GetDeviceScaleFactor()); | |
812 | |
813 if (!window_mapped_) { | 523 if (!window_mapped_) { |
814 // Before we map the window, set size hints. Otherwise, some window managers | 524 // Before we map the window, set size hints. Otherwise, some window managers |
815 // will ignore toplevel XMoveWindow commands. | 525 // will ignore toplevel XMoveWindow commands. |
816 XSizeHints size_hints; | 526 XSizeHints size_hints; |
817 size_hints.flags = PPosition; | 527 size_hints.flags = PPosition; |
818 size_hints.x = bounds_.x(); | 528 size_hints.x = bounds_.x(); |
819 size_hints.y = bounds_.y(); | 529 size_hints.y = bounds_.y(); |
820 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); | 530 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); |
821 | 531 |
822 XMapWindow(xdisplay_, xwindow_); | 532 XMapWindow(xdisplay_, xwindow_); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 current_cursor_ = cursor; | 601 current_cursor_ = cursor; |
892 | 602 |
893 if (cursor_shown_) | 603 if (cursor_shown_) |
894 SetCursorInternal(cursor); | 604 SetCursorInternal(cursor); |
895 } | 605 } |
896 | 606 |
897 void RootWindowHostLinux::ShowCursor(bool show) { | 607 void RootWindowHostLinux::ShowCursor(bool show) { |
898 if (show == cursor_shown_) | 608 if (show == cursor_shown_) |
899 return; | 609 return; |
900 cursor_shown_ = show; | 610 cursor_shown_ = show; |
901 SetCursorInternal(show ? current_cursor_ : ui::kCursorNone); | 611 client::CursorClient* cursor_client = |
| 612 client::GetCursorClient(GetRootWindow()); |
| 613 if (cursor_client) |
| 614 cursor_client->SetCursor(show ? current_cursor_ : ui::kCursorNone); |
902 } | 615 } |
903 | 616 |
904 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { | 617 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { |
905 ::Window root_return, child_return; | 618 ::Window root_return, child_return; |
906 int root_x_return, root_y_return, win_x_return, win_y_return; | 619 int root_x_return, root_y_return, win_x_return, win_y_return; |
907 unsigned int mask_return; | 620 unsigned int mask_return; |
908 XQueryPointer(xdisplay_, | 621 XQueryPointer(xdisplay_, |
909 xwindow_, | 622 xwindow_, |
910 &root_return, | 623 &root_return, |
911 &child_return, | 624 &child_return, |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 xevent.xmotion.y_root = point.y(); | 771 xevent.xmotion.y_root = point.y(); |
1059 } | 772 } |
1060 default: | 773 default: |
1061 break; | 774 break; |
1062 } | 775 } |
1063 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); | 776 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); |
1064 } | 777 } |
1065 | 778 |
1066 void RootWindowHostLinux::OnDeviceScaleFactorChanged( | 779 void RootWindowHostLinux::OnDeviceScaleFactorChanged( |
1067 float device_scale_factor) { | 780 float device_scale_factor) { |
1068 image_cursors_->Reload(device_scale_factor); | |
1069 } | 781 } |
1070 | 782 |
1071 bool RootWindowHostLinux::IsWindowManagerPresent() { | 783 bool RootWindowHostLinux::IsWindowManagerPresent() { |
1072 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 784 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
1073 // of WM_Sn selections (where n is a screen number). | 785 // of WM_Sn selections (where n is a screen number). |
1074 return XGetSelectionOwner( | 786 return XGetSelectionOwner( |
1075 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; | 787 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
1076 } | 788 } |
1077 | 789 |
1078 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { | 790 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { |
1079 // At times the cursor on the RootWindow is set before it is displayed. So | 791 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); |
1080 // make sure the image-cursors are initialized properly before setting it. | |
1081 image_cursors_->Reload(delegate_->GetDeviceScaleFactor()); | |
1082 | |
1083 ::Cursor xcursor; | |
1084 if (image_cursors_->IsImageCursor(cursor)) | |
1085 xcursor = image_cursors_->ImageCursorFromNative(cursor); | |
1086 else if (cursor == ui::kCursorNone) | |
1087 xcursor = invisible_cursor_; | |
1088 else if (cursor == ui::kCursorCustom) | |
1089 xcursor = cursor.platform(); | |
1090 else if (delegate_->GetDeviceScaleFactor() == 1.0) | |
1091 xcursor = ui::GetXCursor(CursorShapeFromNative(cursor)); | |
1092 else | |
1093 xcursor = image_cursors_->ImageCursorFromNative(ui::kCursorPointer); | |
1094 XDefineCursor(xdisplay_, xwindow_, xcursor); | |
1095 } | 792 } |
1096 | 793 |
1097 // static | 794 // static |
1098 RootWindowHost* RootWindowHost::Create(RootWindowHostDelegate* delegate, | 795 RootWindowHost* RootWindowHost::Create(RootWindowHostDelegate* delegate, |
1099 const gfx::Rect& bounds) { | 796 const gfx::Rect& bounds) { |
1100 return new RootWindowHostLinux(delegate, bounds); | 797 return new RootWindowHostLinux(delegate, bounds); |
1101 } | 798 } |
1102 | 799 |
1103 // static | 800 // static |
1104 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( | 801 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( |
1105 gfx::AcceleratedWidget accelerated_widget) { | 802 gfx::AcceleratedWidget accelerated_widget) { |
1106 return reinterpret_cast<RootWindowHost*>( | 803 return reinterpret_cast<RootWindowHost*>( |
1107 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); | 804 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); |
1108 } | 805 } |
1109 | 806 |
1110 // static | 807 // static |
1111 gfx::Size RootWindowHost::GetNativeScreenSize() { | 808 gfx::Size RootWindowHost::GetNativeScreenSize() { |
1112 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 809 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
1113 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 810 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
1114 } | 811 } |
1115 | 812 |
1116 } // namespace aura | 813 } // namespace aura |
OLD | NEW |