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 3 // found in the LICENSE file. 4 5 // Portions based heavily on: 6 // third_party/WebKit/public/web/gtk/WebInputEventFactory.cpp 7 // 8 /* 9 * Copyright (C) 2006-2011 Google Inc. All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions are 13 * met: 14 * 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above 18 * copyright notice, this list of conditions and the following disclaimer 19 * in the documentation and/or other materials provided with the 20 * distribution. 21 * * Neither the name of Google Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include "content/browser/renderer_host/web_input_event_aura.h" 39 40 #include <X11/keysym.h> 41 #include <X11/Xlib.h> 42 #include <X11/Xutil.h> 43 #include <cstdlib> 44 45 #include "base/event_types.h" 46 #include "base/logging.h" 47 #include "content/browser/renderer_host/ui_events_helper.h" 48 #include "ui/base/events/event.h" 49 #include "ui/base/events/event_constants.h" 50 #include "ui/base/keycodes/keyboard_code_conversion_x.h" 51 #include "ui/base/keycodes/keyboard_codes.h" 52 53 namespace content { 54 55 // chromium WebKit does not provide a WebInputEventFactory for X11, so we have 56 // to do the work here ourselves. 57 58 namespace { 59 60 int XKeyEventToWindowsKeyCode(XKeyEvent* event) { 61 int windows_key_code = 62 ui::KeyboardCodeFromXKeyEvent(reinterpret_cast<XEvent*>(event)); 63 if (windows_key_code == ui::VKEY_SHIFT || 64 windows_key_code == ui::VKEY_CONTROL || 65 windows_key_code == ui::VKEY_MENU) { 66 // To support DOM3 'location' attribute, we need to lookup an X KeySym and 67 // set ui::VKEY_[LR]XXX instead of ui::VKEY_XXX. 68 KeySym keysym = XK_VoidSymbol; 69 XLookupString(event, NULL, 0, &keysym, NULL); 70 switch (keysym) { 71 case XK_Shift_L: 72 return ui::VKEY_LSHIFT; 73 case XK_Shift_R: 74 return ui::VKEY_RSHIFT; 75 case XK_Control_L: 76 return ui::VKEY_LCONTROL; 77 case XK_Control_R: 78 return ui::VKEY_RCONTROL; 79 case XK_Meta_L: 80 case XK_Alt_L: 81 return ui::VKEY_LMENU; 82 case XK_Meta_R: 83 case XK_Alt_R: 84 return ui::VKEY_RMENU; 85 } 86 } 87 return windows_key_code; 88 } 89 90 // From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp: 91 WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) { 92 if (windows_key_code >= ui::VKEY_A && 93 windows_key_code <= ui::VKEY_Z) { 94 // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A 95 return windows_key_code - ui::VKEY_A + 1; 96 } 97 if (shift) { 98 // following graphics chars require shift key to input. 99 switch (windows_key_code) { 100 // ctrl-@ maps to \x00 (Null byte) 101 case ui::VKEY_2: 102 return 0; 103 // ctrl-^ maps to \x1E (Record separator, Information separator two) 104 case ui::VKEY_6: 105 return 0x1E; 106 // ctrl-_ maps to \x1F (Unit separator, Information separator one) 107 case ui::VKEY_OEM_MINUS: 108 return 0x1F; 109 // Returns 0 for all other keys to avoid inputting unexpected chars. 110 default: 111 break; 112 } 113 } else { 114 switch (windows_key_code) { 115 // ctrl-[ maps to \x1B (Escape) 116 case ui::VKEY_OEM_4: 117 return 0x1B; 118 // ctrl-\ maps to \x1C (File separator, Information separator four) 119 case ui::VKEY_OEM_5: 120 return 0x1C; 121 // ctrl-] maps to \x1D (Group separator, Information separator three) 122 case ui::VKEY_OEM_6: 123 return 0x1D; 124 // ctrl-Enter maps to \x0A (Line feed) 125 case ui::VKEY_RETURN: 126 return 0x0A; 127 // Returns 0 for all other keys to avoid inputting unexpected chars. 128 default: 129 break; 130 } 131 } 132 return 0; 133 } 134 135 } // namespace 136 137 WebKit::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent( 138 ui::ScrollEvent* event) { 139 WebKit::WebMouseWheelEvent webkit_event; 140 141 webkit_event.type = WebKit::WebInputEvent::MouseWheel; 142 webkit_event.button = WebKit::WebMouseEvent::ButtonNone; 143 webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags()); 144 webkit_event.timeStampSeconds = event->time_stamp().InSecondsF(); 145 webkit_event.hasPreciseScrollingDeltas = true; 146 webkit_event.deltaX = event->x_offset(); 147 if (event->x_offset_ordinal() != 0.f && event->x_offset() != 0.f) { 148 webkit_event.accelerationRatioX = 149 event->x_offset_ordinal() / event->x_offset(); 150 } 151 webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick; 152 webkit_event.deltaY = event->y_offset(); 153 webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick; 154 if (event->y_offset_ordinal() != 0.f && event->y_offset() != 0.f) { 155 webkit_event.accelerationRatioY = 156 event->y_offset_ordinal() / event->y_offset(); 157 } 158 159 return webkit_event; 160 } 161 162 // NOTE: ui::ScrollEvent instances come from the touchpad. 163 WebKit::WebGestureEvent MakeWebGestureEventFromAuraEvent( 164 ui::ScrollEvent* event) { 165 WebKit::WebGestureEvent webkit_event; 166 167 switch (event->type()) { 168 case ui::ET_SCROLL_FLING_START: 169 webkit_event.type = WebKit::WebInputEvent::GestureFlingStart; 170 webkit_event.data.flingStart.velocityX = event->x_offset(); 171 webkit_event.data.flingStart.velocityY = event->y_offset(); 172 break; 173 case ui::ET_SCROLL_FLING_CANCEL: 174 webkit_event.type = WebKit::WebInputEvent::GestureFlingCancel; 175 break; 176 case ui::ET_SCROLL: 177 NOTREACHED() << "Invalid gesture type: " << event->type(); 178 break; 179 default: 180 NOTREACHED() << "Unknown gesture type: " << event->type(); 181 } 182 183 webkit_event.sourceDevice = WebKit::WebGestureEvent::Touchpad; 184 webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags()); 185 webkit_event.timeStampSeconds = event->time_stamp().InSecondsF(); 186 187 return webkit_event; 188 } 189 190 WebKit::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent( 191 ui::KeyEvent* event) { 192 base::NativeEvent native_event = event->native_event(); 193 WebKit::WebKeyboardEvent webkit_event; 194 XKeyEvent* native_key_event = &native_event->xkey; 195 196 webkit_event.timeStampSeconds = event->time_stamp().InSecondsF(); 197 webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags()); 198 199 switch (native_event->type) { 200 case KeyPress: 201 webkit_event.type = event->is_char() ? WebKit::WebInputEvent::Char : 202 WebKit::WebInputEvent::RawKeyDown; 203 break; 204 case KeyRelease: 205 webkit_event.type = WebKit::WebInputEvent::KeyUp; 206 break; 207 default: 208 NOTREACHED(); 209 } 210 211 if (webkit_event.modifiers & WebKit::WebInputEvent::AltKey) 212 webkit_event.isSystemKey = true; 213 214 webkit_event.windowsKeyCode = XKeyEventToWindowsKeyCode(native_key_event); 215 webkit_event.nativeKeyCode = native_key_event->keycode; 216 217 if (webkit_event.windowsKeyCode == ui::VKEY_RETURN) 218 webkit_event.unmodifiedText[0] = '\r'; 219 else 220 webkit_event.unmodifiedText[0] = ui::GetCharacterFromXEvent(native_event); 221 222 if (webkit_event.modifiers & WebKit::WebInputEvent::ControlKey) { 223 webkit_event.text[0] = 224 GetControlCharacter( 225 webkit_event.windowsKeyCode, 226 webkit_event.modifiers & WebKit::WebInputEvent::ShiftKey); 227 } else { 228 webkit_event.text[0] = webkit_event.unmodifiedText[0]; 229 } 230 231 webkit_event.setKeyIdentifierFromWindowsKeyCode(); 232 233 // TODO: IsAutoRepeat/IsKeyPad? 234 235 return webkit_event; 236 } 237 238 } // namespace content 239