Upstream version 11.39.252.0
[platform/framework/web/crosswalk.git] / src / ozone / wayland / input / cursor.cc
1 // Copyright 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ozone/wayland/input/cursor.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "ozone/wayland/display.h"
11
12 namespace ozonewayland {
13 // This number should be equal to size of array defined in WaylandCursorData
14 // constructor.
15 const unsigned TotalCursorTypes = 24;
16
17 class WaylandCursorData {
18  public:
19   explicit WaylandCursorData(wl_shm* shm);
20   ~WaylandCursorData();
21
22   static WaylandCursorData* GetInstance() {
23     return impl_;
24   }
25
26   static void InitializeCursorData(wl_shm* shm) {
27     if (!impl_)
28       impl_ = new WaylandCursorData(shm);
29   }
30
31   static void DestroyCursorData() {
32     if (impl_) {
33       delete impl_;
34       impl_ = NULL;
35     }
36   }
37
38   struct wl_cursor_image* GetCursorImage(WaylandCursor::CursorType index);
39
40  private:
41   wl_cursor_theme* cursor_theme_;
42   // All supported Cursor types.
43   std::vector<wl_cursor*> cursors_;
44   static WaylandCursorData* impl_;
45   DISALLOW_COPY_AND_ASSIGN(WaylandCursorData);
46 };
47
48 WaylandCursorData* WaylandCursorData::impl_ = NULL;
49
50 WaylandCursorData::WaylandCursorData(wl_shm* shm)
51     : cursor_theme_(NULL),
52       cursors_(std::vector<wl_cursor*>(TotalCursorTypes)) {
53   // This list should be always in sync with WaylandCursor::CursorType
54   const char* cursor_names[] = {
55     "default",
56     "bottom_left_corner",
57     "bottom_right_corner",
58     "bottom_side",
59     "cross",
60     "fleur",
61     "grabbing",
62     "left_ptr",
63     "left_side",
64     "left_arrow",
65     "right_side",
66     "top_left_corner",
67     "top_left_arrow",
68     "top_right_corner",
69     "top_side",
70     "up_arrow",
71     "wait",
72     "watch",
73     "xterm",
74     "hand1",
75     "text",
76     "question_arrow",
77     "v_double_arrow",
78     "h_double_arrow"
79   };
80
81   // (kalyan) We should be able to configure the size of cursor and theme name.
82   cursor_theme_ = wl_cursor_theme_load(NULL, 24, shm);
83   DCHECK(cursor_theme_);
84
85   for (unsigned i = 0; i < TotalCursorTypes; i++)
86     cursors_[i] = wl_cursor_theme_get_cursor(cursor_theme_, cursor_names[i]);
87 }
88
89 struct wl_cursor_image* WaylandCursorData::GetCursorImage(
90     WaylandCursor::CursorType type) {
91   int index = type - 1;
92   const struct wl_cursor* cursor = cursors_.at(index);
93   if (!cursor)
94     return NULL;
95
96   return cursor->images[0];
97 }
98
99 WaylandCursorData::~WaylandCursorData() {
100   wl_cursor_theme_destroy(cursor_theme_);
101
102   if (!cursors_.empty())
103     cursors_.clear();
104 }
105
106 WaylandCursor::WaylandCursor(wl_shm* shm) : input_pointer_(NULL),
107     pointer_surface_(NULL),
108     current_cursor_(CURSOR_UNSET) {
109   DCHECK(WaylandCursorData::GetInstance());
110   WaylandDisplay* display = WaylandDisplay::GetInstance();
111   pointer_surface_ = wl_compositor_create_surface(display->GetCompositor());
112 }
113
114 WaylandCursor::~WaylandCursor() {
115   DCHECK(pointer_surface_);
116   wl_surface_destroy(pointer_surface_);
117 }
118
119 void WaylandCursor::Clear() {
120   WaylandCursorData::DestroyCursorData();
121 }
122
123 void WaylandCursor::InitializeCursorData(wl_shm* shm) {
124   WaylandCursorData::InitializeCursorData(shm);
125 }
126
127 void WaylandCursor::Update(CursorType type, uint32_t serial) {
128   if (!input_pointer_)
129     return;
130
131   DCHECK(type != CURSOR_UNSET);
132   CursorType cursor_type = type;
133   wl_cursor_image* image = WaylandCursorData::GetInstance()->GetCursorImage(
134       cursor_type);
135
136   if (!image) {
137     LOG(INFO) << "The current cursor theme does not have a cursor for type "
138               << cursor_type << ". Falling back to the default cursor.";
139     // The cursor currently being displayed is already the default one, so we
140     // can just continue showing it.
141     if (current_cursor_ == CURSOR_LEFT_PTR)
142       return;
143
144     cursor_type = CURSOR_LEFT_PTR;
145     image = WaylandCursorData::GetInstance()->GetCursorImage(cursor_type);
146     DCHECK(image);
147   }
148
149   current_cursor_ = cursor_type;
150   struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);
151   int width = image->width;
152   int height = image->height;
153   wl_pointer_set_cursor(input_pointer_,
154                         serial,
155                         pointer_surface_,
156                         image->hotspot_x,
157                         image->hotspot_y);
158
159   struct wl_surface* surface = pointer_surface_;
160   wl_surface_attach(surface, buffer, 0, 0);
161   wl_surface_damage(surface, 0, 0, width, height);
162   wl_surface_commit(surface);
163 }
164
165 void WaylandCursor::SetInputPointer(wl_pointer* pointer) {
166   if (input_pointer_ == pointer)
167     return;
168
169   if (input_pointer_)
170     wl_pointer_destroy(input_pointer_);
171
172   input_pointer_ = pointer;
173 }
174
175 }  // namespace ozonewayland