3 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "PlatformInputManager.h"
20 //#include <X11/Xlib.h>
23 #include <Ecore_Evas.h>
24 #include <Ecore_Input.h>
27 #include "BrowserAssert.h"
28 #include "BrowserLogger.h"
30 #define E_PROP_DEVICEMGR_INPUTWIN "DeviceMgr Input Window"
31 #define E_PROP_NOT_CURSOR_HIDE "E_NOT_CURSOR_HIDE"
33 #define MOUSE_POINTER_MOVE_DELAY 0.015f
34 #define MOUSE_POINTER_STEPS 10
36 namespace tizen_browser
41 EXPORT_SERVICE(PlatformInputManager, "org.tizen.browser.platforminputmanager")
43 PlatformInputManager::PlatformInputManager() :
44 m_mouseMoveTimer(NULL),
45 m_moveMousePointer(false),
46 m_lastPressedKey(OTHER_KEY),
47 m_pointerModeEnabled(true)
52 void PlatformInputManager::init(Evas_Object* mainWindow)
55 ecore_event_filter_add(NULL, __filter, NULL, this);
56 m_xWindow = elm_win_xwindow_get(mainWindow);
58 // This snippet is needed to show mouse pointer all the time, because by default it is hidden after few seconds
59 //m_atomDevicemgrInputWindow = ecore_x_atom_get(E_PROP_DEVICEMGR_INPUTWIN);
60 //m_atomAlwaysCursorOn = ecore_x_atom_get(E_PROP_NOT_CURSOR_HIDE);
61 //if(!ecore_x_window_prop_window_get(ecore_x_window_root_first_get(), m_atomDevicemgrInputWindow, &m_devicemgr_win, 1))
62 // BROWSER_LOGD("Failed to get device manager input window!");
63 //ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, __handler_FOCUS_IN, this);
66 Eina_Bool PlatformInputManager::__filter(void *data, void */*loop_data*/, int type, void *event)
68 PlatformInputManager *self = static_cast<PlatformInputManager*>(data);
70 if (type == ECORE_EVENT_KEY_DOWN) {
72 Ecore_Event_Key *ev = static_cast<Ecore_Event_Key *>(event);
77 BROWSER_LOGD("Pressed key: %s", ev->keyname);
78 const std::string keyName = ev->keyname;
80 bool wasArrow = false;
82 * In pointer mode arrow key events cause mouse pointer to move.
83 * For that each arrow key is handled by us.
84 * Pointer movement is realized in timer to achieve smooth animation of pointer's move.
87 if(self->m_pointerModeEnabled) {
89 if (!keyName.compare("KEY_LEFT")) {
90 self->m_currentMouseMovementParams.xMod = -1;
91 self->m_currentMouseMovementParams.yMod = 0;
93 else if (!keyName.compare("KEY_RIGHT")) {
94 self->m_currentMouseMovementParams.xMod = 1;
95 self->m_currentMouseMovementParams.yMod = 0;
97 else if (!keyName.compare("KEY_UP")) {
98 self->m_currentMouseMovementParams.xMod = 0;
99 self->m_currentMouseMovementParams.yMod = -1;
101 else if (!keyName.compare("KEY_DOWN")) {
102 self->m_currentMouseMovementParams.xMod = 0;
103 self->m_currentMouseMovementParams.yMod = 1;
109 * If last pressed key was arrow we would like to convert Return key to mouse click
110 * assuming that user was moving cursor and now want to "click" chosen element.
111 * In other cases Return key is handled normally allowing for example to accecpt typed url.
114 if(!keyName.compare("KEY_ENTER")) {
115 if(self->m_lastPressedKey == ARROW) {
116 self->m_lastPressedKey = RETURN;
117 self->mouseButtonManipulate(Button1, ButtonPress);
123 self->m_lastPressedKey = ARROW;
124 if(!(self->m_mouseMoveTimer)) {
125 self->m_currentMouseMovementParams.moveMousePointer = true;
126 self->m_currentMouseMovementParams.counter = 0;
127 self->m_currentMouseMovementParams.speed = 1;
128 self->m_mouseMoveTimer = ecore_timer_add(MOUSE_POINTER_MOVE_DELAY, &PlatformInputManager::mouseMove, self);
135 self->m_lastPressedKey= OTHER_KEY;
138 * Because MENU button launches org.tizen.menu
139 * we use blue 'D' button on remote control or F4 on keyboard as substitution of MENU button
141 if(!keyName.compare("KEY_MENU") || !keyName.compare("KEY_BLUE")) {
146 // if(!keyName.compare("KEY_CHANNELUP")){
148 * Converting ChannelUp Button on remote control and Page Up key on keyboard to mouse's wheel up move.
149 * This is used to achieve same effect of scrolling web page using mouse, remote control and keyboard.
151 // self->mouseButtonManipulate(Button4, ButtonPress); // Simulate mouse wheel up movement
152 // self->mouseButtonManipulate(Button4, ButtonRelease);
153 // return EINA_FALSE;
156 // if(!keyName.compare("KEY_CHANNELDOWN")){
158 * Same as above ChannelDown and Page Down are replaced by mouse's wheel down movement.
160 // self->mouseButtonManipulate(Button5, ButtonPress); // Simulate mouse wheel down movement
161 // self->mouseButtonManipulate(Button5, ButtonRelease);
162 // return EINA_FALSE;
165 if(!keyName.compare("KEY_RETURN"))
166 self->returnPressed();
167 else if(!keyName.compare("KEY_LEFT"))
169 else if(!keyName.compare("KEY_RIGHT"))
170 self->rightPressed();
171 else if(!keyName.compare("KEY_ENTER"))
172 self->enterPressed();
173 // MERGE_ME dont know if should be commented out
174 else if(!keyName.compare("BackSpace"))
176 } else if(type == ECORE_EVENT_KEY_UP) {
178 Ecore_Event_Key *ev = static_cast<Ecore_Event_Key *>(event);
183 BROWSER_LOGD("Released key: %s", ev->keyname);
184 const std::string keyName = ev->keyname;
187 * When arrow key is released thread realizing pointer movement is stopped.
189 // if(self->m_pointerModeEnabled && (!keyName.compare("KEY_LEFT")||!keyName.compare("KEY_UP")
190 // || !keyName.compare("KEY_RIGHT")||!keyName.compare("KEY_DOWN"))) {
191 // if(self->m_mouseMoveTimer) {
192 // self->m_currentMouseMovementParams.moveMousePointer = false;
193 // ecore_timer_del(self->m_mouseMoveTimer);
194 // self->m_mouseMoveTimer = NULL;
196 // return EINA_FALSE;
199 * If Return key is being released we send event that mouse button was released (in pointer mode).
201 // if(self->m_lastPressedKey == RETURN && self->m_pointerModeEnabled && !keyName.compare("KEY_ENTER")) {
202 // self->m_lastPressedKey = OTHER_KEY;
203 // self->mouseButtonManipulate(Button1, ButtonRelease);
204 // return EINA_FALSE;
210 Eina_Bool PlatformInputManager::mouseMove(void *data)
213 PlatformInputManager *self = static_cast<PlatformInputManager*>(data);
215 if(self->m_currentMouseMovementParams.moveMousePointer) {
216 ecore_x_pointer_xy_get(self->m_xWindow, &x, &y);
217 x += self->m_currentMouseMovementParams.xMod * self->m_currentMouseMovementParams.speed;
218 y += self->m_currentMouseMovementParams.yMod * self->m_currentMouseMovementParams.speed;
219 ecore_x_pointer_warp(self->m_xWindow, x, y);
222 ++(self->m_currentMouseMovementParams.counter);
223 if(self->m_currentMouseMovementParams.counter == MOUSE_POINTER_STEPS) {
224 self->m_currentMouseMovementParams.counter = 0;
225 ++(self->m_currentMouseMovementParams.speed);
232 //Eina_Bool PlatformInputManager::__handler_FOCUS_IN(void *data, int /*type*/, void */*event*/)
234 // PlatformInputManager * self = reinterpret_cast<PlatformInputManager *>(data);
235 // ecore_x_window_prop_window_set(self->m_devicemgr_win, self->m_atomAlwaysCursorOn, &(self->m_xWindow), 1);
239 void PlatformInputManager::mouseButtonManipulate(int button, int event_type)
243 Display *display = static_cast<Display*>(ecore_x_display_get());
245 memset(&event, 0x00, sizeof(event));
247 event.type = event_type;
249 if (event_type == ButtonRelease)
250 event.xbutton.state = 0x100;
252 event.xbutton.button = button;
253 event.xbutton.same_screen = True;
255 XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
257 event.xbutton.subwindow = event.xbutton.window;
259 while (event.xbutton.subwindow) {
260 event.xbutton.window = event.xbutton.subwindow;
262 XQueryPointer(display, event.xbutton.window, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
265 XSendEvent(display, PointerWindow, True, 0xfff, &event);
270 void PlatformInputManager::setPointerModeEnabled(bool enabled)
272 m_pointerModeEnabled = enabled;
275 bool PlatformInputManager::getPointerModeEnabled() const
277 return m_pointerModeEnabled;