WebKit/chromium/src/gtk/WebInputEventFactory.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006-2009 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "WebInputEventFactory.h"
       
    33 
       
    34 #include "KeyboardCodes.h"
       
    35 #include "KeyCodeConversion.h"
       
    36 
       
    37 #include "WebInputEvent.h"
       
    38 
       
    39 #include <gdk/gdk.h>
       
    40 #include <gdk/gdkkeysyms.h>
       
    41 #include <gtk/gtk.h>
       
    42 #include <gtk/gtkversion.h>
       
    43 
       
    44 #include <wtf/Assertions.h>
       
    45 
       
    46 namespace {
       
    47 
       
    48 gint getDoubleClickTime()
       
    49 {
       
    50     static GtkSettings* settings = gtk_settings_get_default();
       
    51     gint doubleClickTime = 250;
       
    52     g_object_get(G_OBJECT(settings), "gtk-double-click-time", &doubleClickTime, NULL);
       
    53     return doubleClickTime;
       
    54 }
       
    55 
       
    56 }  // namespace
       
    57 
       
    58 namespace WebKit {
       
    59 
       
    60 static double gdkEventTimeToWebEventTime(guint32 time)
       
    61 {
       
    62     // Convert from time in ms to time in sec.
       
    63     return time / 1000.0;
       
    64 }
       
    65 
       
    66 static int gdkStateToWebEventModifiers(guint state)
       
    67 {
       
    68     int modifiers = 0;
       
    69     if (state & GDK_SHIFT_MASK)
       
    70         modifiers |= WebInputEvent::ShiftKey;
       
    71     if (state & GDK_CONTROL_MASK)
       
    72         modifiers |= WebInputEvent::ControlKey;
       
    73     if (state & GDK_MOD1_MASK)
       
    74         modifiers |= WebInputEvent::AltKey;
       
    75 #if GTK_CHECK_VERSION(2, 10, 0)
       
    76     if (state & GDK_META_MASK)
       
    77         modifiers |= WebInputEvent::MetaKey;
       
    78 #endif
       
    79     if (state & GDK_BUTTON1_MASK)
       
    80         modifiers |= WebInputEvent::LeftButtonDown;
       
    81     if (state & GDK_BUTTON2_MASK)
       
    82         modifiers |= WebInputEvent::MiddleButtonDown;
       
    83     if (state & GDK_BUTTON3_MASK)
       
    84         modifiers |= WebInputEvent::RightButtonDown;
       
    85     return modifiers;
       
    86 }
       
    87 
       
    88 static int gdkEventToWindowsKeyCode(const GdkEventKey* event)
       
    89 {
       
    90     static const unsigned int hardwareCodeToGDKKeyval[] = {
       
    91         0,                 // 0x00:
       
    92         0,                 // 0x01:
       
    93         0,                 // 0x02:
       
    94         0,                 // 0x03:
       
    95         0,                 // 0x04:
       
    96         0,                 // 0x05:
       
    97         0,                 // 0x06:
       
    98         0,                 // 0x07:
       
    99         0,                 // 0x08:
       
   100         0,                 // 0x09: GDK_Escape
       
   101         GDK_1,             // 0x0A: GDK_1
       
   102         GDK_2,             // 0x0B: GDK_2
       
   103         GDK_3,             // 0x0C: GDK_3
       
   104         GDK_4,             // 0x0D: GDK_4
       
   105         GDK_5,             // 0x0E: GDK_5
       
   106         GDK_6,             // 0x0F: GDK_6
       
   107         GDK_7,             // 0x10: GDK_7
       
   108         GDK_8,             // 0x11: GDK_8
       
   109         GDK_9,             // 0x12: GDK_9
       
   110         GDK_0,             // 0x13: GDK_0
       
   111         GDK_minus,         // 0x14: GDK_minus
       
   112         GDK_equal,         // 0x15: GDK_equal
       
   113         0,                 // 0x16: GDK_BackSpace
       
   114         0,                 // 0x17: GDK_Tab
       
   115         GDK_q,             // 0x18: GDK_q
       
   116         GDK_w,             // 0x19: GDK_w
       
   117         GDK_e,             // 0x1A: GDK_e
       
   118         GDK_r,             // 0x1B: GDK_r
       
   119         GDK_t,             // 0x1C: GDK_t
       
   120         GDK_y,             // 0x1D: GDK_y
       
   121         GDK_u,             // 0x1E: GDK_u
       
   122         GDK_i,             // 0x1F: GDK_i
       
   123         GDK_o,             // 0x20: GDK_o
       
   124         GDK_p,             // 0x21: GDK_p
       
   125         GDK_bracketleft,   // 0x22: GDK_bracketleft
       
   126         GDK_bracketright,  // 0x23: GDK_bracketright
       
   127         0,                 // 0x24: GDK_Return
       
   128         0,                 // 0x25: GDK_Control_L
       
   129         GDK_a,             // 0x26: GDK_a
       
   130         GDK_s,             // 0x27: GDK_s
       
   131         GDK_d,             // 0x28: GDK_d
       
   132         GDK_f,             // 0x29: GDK_f
       
   133         GDK_g,             // 0x2A: GDK_g
       
   134         GDK_h,             // 0x2B: GDK_h
       
   135         GDK_j,             // 0x2C: GDK_j
       
   136         GDK_k,             // 0x2D: GDK_k
       
   137         GDK_l,             // 0x2E: GDK_l
       
   138         GDK_semicolon,     // 0x2F: GDK_semicolon
       
   139         GDK_apostrophe,    // 0x30: GDK_apostrophe
       
   140         GDK_grave,         // 0x31: GDK_grave
       
   141         0,                 // 0x32: GDK_Shift_L
       
   142         GDK_backslash,     // 0x33: GDK_backslash
       
   143         GDK_z,             // 0x34: GDK_z
       
   144         GDK_x,             // 0x35: GDK_x
       
   145         GDK_c,             // 0x36: GDK_c
       
   146         GDK_v,             // 0x37: GDK_v
       
   147         GDK_b,             // 0x38: GDK_b
       
   148         GDK_n,             // 0x39: GDK_n
       
   149         GDK_m,             // 0x3A: GDK_m
       
   150         GDK_comma,         // 0x3B: GDK_comma
       
   151         GDK_period,        // 0x3C: GDK_period
       
   152         GDK_slash,         // 0x3D: GDK_slash
       
   153         0,                 // 0x3E: GDK_Shift_R
       
   154         0,                 // 0x3F:
       
   155         0,                 // 0x40:
       
   156         0,                 // 0x41:
       
   157         0,                 // 0x42:
       
   158         0,                 // 0x43:
       
   159         0,                 // 0x44:
       
   160         0,                 // 0x45:
       
   161         0,                 // 0x46:
       
   162         0,                 // 0x47:
       
   163         0,                 // 0x48:
       
   164         0,                 // 0x49:
       
   165         0,                 // 0x4A:
       
   166         0,                 // 0x4B:
       
   167         0,                 // 0x4C:
       
   168         0,                 // 0x4D:
       
   169         0,                 // 0x4E:
       
   170         0,                 // 0x4F:
       
   171         0,                 // 0x50:
       
   172         0,                 // 0x51:
       
   173         0,                 // 0x52:
       
   174         0,                 // 0x53:
       
   175         0,                 // 0x54:
       
   176         0,                 // 0x55:
       
   177         0,                 // 0x56:
       
   178         0,                 // 0x57:
       
   179         0,                 // 0x58:
       
   180         0,                 // 0x59:
       
   181         0,                 // 0x5A:
       
   182         0,                 // 0x5B:
       
   183         0,                 // 0x5C:
       
   184         0,                 // 0x5D:
       
   185         0,                 // 0x5E:
       
   186         0,                 // 0x5F:
       
   187         0,                 // 0x60:
       
   188         0,                 // 0x61:
       
   189         0,                 // 0x62:
       
   190         0,                 // 0x63:
       
   191         0,                 // 0x64:
       
   192         0,                 // 0x65:
       
   193         0,                 // 0x66:
       
   194         0,                 // 0x67:
       
   195         0,                 // 0x68:
       
   196         0,                 // 0x69:
       
   197         0,                 // 0x6A:
       
   198         0,                 // 0x6B:
       
   199         0,                 // 0x6C:
       
   200         0,                 // 0x6D:
       
   201         0,                 // 0x6E:
       
   202         0,                 // 0x6F:
       
   203         0,                 // 0x70:
       
   204         0,                 // 0x71:
       
   205         0,                 // 0x72:
       
   206         GDK_Super_L,       // 0x73: GDK_Super_L
       
   207         GDK_Super_R,       // 0x74: GDK_Super_R
       
   208     };
       
   209 
       
   210     // |windowsKeyCode| has to include a valid virtual-key code even when we
       
   211     // use non-US layouts, e.g. even when we type an 'A' key of a US keyboard
       
   212     // on the Hebrew layout, |windowsKeyCode| should be VK_A.
       
   213     // On the other hand, |event->keyval| value depends on the current
       
   214     // GdkKeymap object, i.e. when we type an 'A' key of a US keyboard on
       
   215     // the Hebrew layout, |event->keyval| becomes GDK_hebrew_shin and this
       
   216     // WebCore::windowsKeyCodeForKeyEvent() call returns 0.
       
   217     // To improve compatibilty with Windows, we use |event->hardware_keycode|
       
   218     // for retrieving its Windows key-code for the keys when the
       
   219     // WebCore::windowsKeyCodeForEvent() call returns 0.
       
   220     // We shouldn't use |event->hardware_keycode| for keys that GdkKeymap
       
   221     // objects cannot change because |event->hardware_keycode| doesn't change
       
   222     // even when we change the layout options, e.g. when we swap a control
       
   223     // key and a caps-lock key, GTK doesn't swap their
       
   224     // |event->hardware_keycode| values but swap their |event->keyval| values.
       
   225     int windowsKeyCode = WebCore::windowsKeyCodeForKeyEvent(event->keyval);
       
   226     if (windowsKeyCode)
       
   227         return windowsKeyCode;
       
   228 
       
   229     const int tableSize = sizeof(hardwareCodeToGDKKeyval) / sizeof(hardwareCodeToGDKKeyval[0]);
       
   230     if (event->hardware_keycode < tableSize) {
       
   231         int keyval = hardwareCodeToGDKKeyval[event->hardware_keycode];
       
   232         if (keyval)
       
   233             return WebCore::windowsKeyCodeForKeyEvent(keyval);
       
   234     }
       
   235 
       
   236     // This key is one that keyboard-layout drivers cannot change.
       
   237     // Use |event->keyval| to retrieve its |windowsKeyCode| value.
       
   238     return WebCore::windowsKeyCodeForKeyEvent(event->keyval);
       
   239 }
       
   240 
       
   241 // Gets the corresponding control character of a specified key code. See:
       
   242 // http://en.wikipedia.org/wiki/Control_characters
       
   243 // We emulate Windows behavior here.
       
   244 static WebUChar getControlCharacter(int windowsKeyCode, bool shift)
       
   245 {
       
   246     if (windowsKeyCode >= WebCore::VKEY_A && windowsKeyCode <= WebCore::VKEY_Z) {
       
   247         // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
       
   248         return windowsKeyCode - WebCore::VKEY_A + 1;
       
   249     }
       
   250     if (shift) {
       
   251         // following graphics chars require shift key to input.
       
   252         switch (windowsKeyCode) {
       
   253         // ctrl-@ maps to \x00 (Null byte)
       
   254         case WebCore::VKEY_2:
       
   255             return 0;
       
   256         // ctrl-^ maps to \x1E (Record separator, Information separator two)
       
   257         case WebCore::VKEY_6:
       
   258             return 0x1E;
       
   259         // ctrl-_ maps to \x1F (Unit separator, Information separator one)
       
   260         case WebCore::VKEY_OEM_MINUS:
       
   261             return 0x1F;
       
   262         // Returns 0 for all other keys to avoid inputting unexpected chars.
       
   263         default:
       
   264             return 0;
       
   265         }
       
   266     } else {
       
   267         switch (windowsKeyCode) {
       
   268         // ctrl-[ maps to \x1B (Escape)
       
   269         case WebCore::VKEY_OEM_4:
       
   270             return 0x1B;
       
   271         // ctrl-\ maps to \x1C (File separator, Information separator four)
       
   272         case WebCore::VKEY_OEM_5:
       
   273             return 0x1C;
       
   274         // ctrl-] maps to \x1D (Group separator, Information separator three)
       
   275         case WebCore::VKEY_OEM_6:
       
   276             return 0x1D;
       
   277         // ctrl-Enter maps to \x0A (Line feed)
       
   278         case WebCore::VKEY_RETURN:
       
   279             return 0x0A;
       
   280         // Returns 0 for all other keys to avoid inputting unexpected chars.
       
   281         default:
       
   282             return 0;
       
   283         }
       
   284     }
       
   285 }
       
   286 
       
   287 // WebKeyboardEvent -----------------------------------------------------------
       
   288 
       
   289 WebKeyboardEvent WebInputEventFactory::keyboardEvent(const GdkEventKey* event)
       
   290 {
       
   291     WebKeyboardEvent result;
       
   292 
       
   293     result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
       
   294     result.modifiers = gdkStateToWebEventModifiers(event->state);
       
   295 
       
   296     switch (event->type) {
       
   297     case GDK_KEY_RELEASE:
       
   298         result.type = WebInputEvent::KeyUp;
       
   299         break;
       
   300     case GDK_KEY_PRESS:
       
   301         result.type = WebInputEvent::RawKeyDown;
       
   302         break;
       
   303     default:
       
   304         ASSERT_NOT_REACHED();
       
   305     }
       
   306 
       
   307     // According to MSDN:
       
   308     // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
       
   309     // Key events with Alt modifier and F10 are system key events.
       
   310     // We just emulate this behavior. It's necessary to prevent webkit from
       
   311     // processing keypress event generated by alt-d, etc.
       
   312     // F10 is not special on Linux, so don't treat it as system key.
       
   313     if (result.modifiers & WebInputEvent::AltKey)
       
   314         result.isSystemKey = true;
       
   315 
       
   316     // The key code tells us which physical key was pressed (for example, the
       
   317     // A key went down or up).  It does not determine whether A should be lower
       
   318     // or upper case.  This is what text does, which should be the keyval.
       
   319     result.windowsKeyCode = gdkEventToWindowsKeyCode(event);
       
   320     result.nativeKeyCode = event->hardware_keycode;
       
   321 
       
   322     if (result.windowsKeyCode == WebCore::VKEY_RETURN)
       
   323         // We need to treat the enter key as a key press of character \r.  This
       
   324         // is apparently just how webkit handles it and what it expects.
       
   325         result.unmodifiedText[0] = '\r';
       
   326     else
       
   327         // FIXME: fix for non BMP chars
       
   328         result.unmodifiedText[0] =
       
   329             static_cast<WebUChar>(gdk_keyval_to_unicode(event->keyval));
       
   330 
       
   331     // If ctrl key is pressed down, then control character shall be input.
       
   332     if (result.modifiers & WebInputEvent::ControlKey)
       
   333         result.text[0] = getControlCharacter(
       
   334             result.windowsKeyCode, result.modifiers & WebInputEvent::ShiftKey);
       
   335     else
       
   336         result.text[0] = result.unmodifiedText[0];
       
   337 
       
   338     result.setKeyIdentifierFromWindowsKeyCode();
       
   339 
       
   340     // FIXME: Do we need to set IsAutoRepeat or IsKeyPad?
       
   341 
       
   342     return result;
       
   343 }
       
   344 
       
   345 WebKeyboardEvent WebInputEventFactory::keyboardEvent(wchar_t character, int state, double timeStampSeconds)
       
   346 {
       
   347     // keyboardEvent(const GdkEventKey*) depends on the GdkEventKey object and
       
   348     // it is hard to use/ it from signal handlers which don't use GdkEventKey
       
   349     // objects (e.g. GtkIMContext signal handlers.) For such handlers, this
       
   350     // function creates a WebInputEvent::Char event without using a
       
   351     // GdkEventKey object.
       
   352     WebKeyboardEvent result;
       
   353     result.type = WebKit::WebInputEvent::Char;
       
   354     result.timeStampSeconds = timeStampSeconds;
       
   355     result.modifiers = gdkStateToWebEventModifiers(state);
       
   356     result.windowsKeyCode = character;
       
   357     result.nativeKeyCode = character;
       
   358     result.text[0] = character;
       
   359     result.unmodifiedText[0] = character;
       
   360 
       
   361     // According to MSDN:
       
   362     // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
       
   363     // Key events with Alt modifier and F10 are system key events.
       
   364     // We just emulate this behavior. It's necessary to prevent webkit from
       
   365     // processing keypress event generated by alt-d, etc.
       
   366     // F10 is not special on Linux, so don't treat it as system key.
       
   367     if (result.modifiers & WebInputEvent::AltKey)
       
   368         result.isSystemKey = true;
       
   369 
       
   370     return result;
       
   371 }
       
   372 
       
   373 // WebMouseEvent --------------------------------------------------------------
       
   374 
       
   375 WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventButton* event)
       
   376 {
       
   377     WebMouseEvent result;
       
   378 
       
   379     result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
       
   380 
       
   381     result.modifiers = gdkStateToWebEventModifiers(event->state);
       
   382     result.x = static_cast<int>(event->x);
       
   383     result.y = static_cast<int>(event->y);
       
   384     result.windowX = result.x;
       
   385     result.windowY = result.y;
       
   386     result.globalX = static_cast<int>(event->x_root);
       
   387     result.globalY = static_cast<int>(event->y_root);
       
   388     result.clickCount = 0;
       
   389 
       
   390     switch (event->type) {
       
   391     case GDK_BUTTON_PRESS:
       
   392         result.type = WebInputEvent::MouseDown;
       
   393         break;
       
   394     case GDK_BUTTON_RELEASE:
       
   395         result.type = WebInputEvent::MouseUp;
       
   396         break;
       
   397     case GDK_3BUTTON_PRESS:
       
   398     case GDK_2BUTTON_PRESS:
       
   399     default:
       
   400         ASSERT_NOT_REACHED();
       
   401     };
       
   402 
       
   403     if (GDK_BUTTON_PRESS == event->type) {
       
   404         static int numClicks = 0;
       
   405         static GdkWindow* eventWindow = 0;
       
   406         static gint lastLeftClickTime = 0;
       
   407 
       
   408         gint time_diff = event->time - lastLeftClickTime;
       
   409         if (eventWindow == event->window && time_diff < getDoubleClickTime())
       
   410             numClicks++;
       
   411         else
       
   412             numClicks = 1;
       
   413 
       
   414         result.clickCount = numClicks;
       
   415         eventWindow = event->window;
       
   416         lastLeftClickTime = event->time;
       
   417     }
       
   418 
       
   419     result.button = WebMouseEvent::ButtonNone;
       
   420     if (event->button == 1)
       
   421         result.button = WebMouseEvent::ButtonLeft;
       
   422     else if (event->button == 2)
       
   423         result.button = WebMouseEvent::ButtonMiddle;
       
   424     else if (event->button == 3)
       
   425         result.button = WebMouseEvent::ButtonRight;
       
   426 
       
   427     return result;
       
   428 }
       
   429 
       
   430 WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventMotion* event)
       
   431 {
       
   432     WebMouseEvent result;
       
   433 
       
   434     result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
       
   435     result.modifiers = gdkStateToWebEventModifiers(event->state);
       
   436     result.x = static_cast<int>(event->x);
       
   437     result.y = static_cast<int>(event->y);
       
   438     result.windowX = result.x;
       
   439     result.windowY = result.y;
       
   440     result.globalX = static_cast<int>(event->x_root);
       
   441     result.globalY = static_cast<int>(event->y_root);
       
   442 
       
   443     switch (event->type) {
       
   444     case GDK_MOTION_NOTIFY:
       
   445         result.type = WebInputEvent::MouseMove;
       
   446         break;
       
   447     default:
       
   448         ASSERT_NOT_REACHED();
       
   449     }
       
   450 
       
   451     result.button = WebMouseEvent::ButtonNone;
       
   452     if (event->state & GDK_BUTTON1_MASK)
       
   453         result.button = WebMouseEvent::ButtonLeft;
       
   454     else if (event->state & GDK_BUTTON2_MASK)
       
   455         result.button = WebMouseEvent::ButtonMiddle;
       
   456     else if (event->state & GDK_BUTTON3_MASK)
       
   457         result.button = WebMouseEvent::ButtonRight;
       
   458 
       
   459     return result;
       
   460 }
       
   461 
       
   462 WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventCrossing* event)
       
   463 {
       
   464     WebMouseEvent result;
       
   465 
       
   466     result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
       
   467     result.modifiers = gdkStateToWebEventModifiers(event->state);
       
   468     result.x = static_cast<int>(event->x);
       
   469     result.y = static_cast<int>(event->y);
       
   470     result.windowX = result.x;
       
   471     result.windowY = result.y;
       
   472     result.globalX = static_cast<int>(event->x_root);
       
   473     result.globalY = static_cast<int>(event->y_root);
       
   474 
       
   475     switch (event->type) {
       
   476     case GDK_ENTER_NOTIFY:
       
   477     case GDK_LEAVE_NOTIFY:
       
   478         // Note that if we sent MouseEnter or MouseLeave to WebKit, it
       
   479         // wouldn't work - they don't result in the proper JavaScript events.
       
   480         // MouseMove does the right thing.
       
   481         result.type = WebInputEvent::MouseMove;
       
   482         break;
       
   483     default:
       
   484         ASSERT_NOT_REACHED();
       
   485     }
       
   486 
       
   487     result.button = WebMouseEvent::ButtonNone;
       
   488     if (event->state & GDK_BUTTON1_MASK)
       
   489         result.button = WebMouseEvent::ButtonLeft;
       
   490     else if (event->state & GDK_BUTTON2_MASK)
       
   491         result.button = WebMouseEvent::ButtonMiddle;
       
   492     else if (event->state & GDK_BUTTON3_MASK)
       
   493         result.button = WebMouseEvent::ButtonRight;
       
   494 
       
   495     return result;
       
   496 }
       
   497 
       
   498 // WebMouseWheelEvent ---------------------------------------------------------
       
   499 
       
   500 WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(const GdkEventScroll* event)
       
   501 {
       
   502     WebMouseWheelEvent result;
       
   503 
       
   504     result.type = WebInputEvent::MouseWheel;
       
   505     result.button = WebMouseEvent::ButtonNone;
       
   506 
       
   507     result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
       
   508     result.modifiers = gdkStateToWebEventModifiers(event->state);
       
   509     result.x = static_cast<int>(event->x);
       
   510     result.y = static_cast<int>(event->y);
       
   511     result.windowX = result.x;
       
   512     result.windowY = result.y;
       
   513     result.globalX = static_cast<int>(event->x_root);
       
   514     result.globalY = static_cast<int>(event->y_root);
       
   515 
       
   516     // How much should we scroll per mouse wheel event?
       
   517     // - Windows uses 3 lines by default and obeys a system setting.
       
   518     // - Mozilla has a pref that lets you either use the "system" number of lines
       
   519     //   to scroll, or lets the user override it.
       
   520     //   For the "system" number of lines, it appears they've hardcoded 3.
       
   521     //   See case NS_MOUSE_SCROLL in content/events/src/nsEventStateManager.cpp
       
   522     //   and InitMouseScrollEvent in widget/src/gtk2/nsCommonWidget.cpp .
       
   523     // - Gtk makes the scroll amount a function of the size of the scroll bar,
       
   524     //   which is not available to us here.
       
   525     // Instead, we pick a number that empirically matches Firefox's behavior.
       
   526     static const float scrollbarPixelsPerTick = 160.0f / 3.0f;
       
   527 
       
   528     switch (event->direction) {
       
   529     case GDK_SCROLL_UP:
       
   530         result.deltaY = scrollbarPixelsPerTick;
       
   531         result.wheelTicksY = 1;
       
   532         break;
       
   533     case GDK_SCROLL_DOWN:
       
   534         result.deltaY = -scrollbarPixelsPerTick;
       
   535         result.wheelTicksY = -1;
       
   536         break;
       
   537     case GDK_SCROLL_LEFT:
       
   538         result.deltaX = scrollbarPixelsPerTick;
       
   539         result.wheelTicksX = 1;
       
   540         break;
       
   541     case GDK_SCROLL_RIGHT:
       
   542         result.deltaX = -scrollbarPixelsPerTick;
       
   543         result.wheelTicksX = -1;
       
   544         break;
       
   545     }
       
   546 
       
   547     return result;
       
   548 }
       
   549 
       
   550 } // namespace WebKit