Home | History | Annotate | Download | only in gtk
      1 // Copyright (c) 2011 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 #include "ui/base/gtk/event_synthesis_gtk.h"
      6 
      7 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
      8 
      9 namespace ui {
     10 
     11 GdkEvent* SynthesizeKeyEvent(GdkWindow* window,
     12                              bool press, guint gdk_key, guint state) {
     13   GdkEvent* event = gdk_event_new(press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
     14 
     15   event->key.type = press ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
     16   event->key.window = window;
     17   if (window)
     18     g_object_ref(window);
     19   event->key.send_event = false;
     20 
     21   struct timespec ts;
     22   clock_gettime(CLOCK_MONOTONIC, &ts);
     23   event->key.time = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
     24 
     25   event->key.state = state;
     26   event->key.keyval = gdk_key;
     27 
     28   GdkKeymapKey* keys;
     29   gint n_keys;
     30   if (event->key.keyval != 0 &&
     31       gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(),
     32                                         event->key.keyval, &keys, &n_keys)) {
     33     event->key.hardware_keycode = keys[0].keycode;
     34     event->key.group = keys[0].group;
     35     g_free(keys);
     36   }
     37 
     38   return event;
     39 }
     40 
     41 void SynthesizeKeyPressEvents(GdkWindow* window,
     42                               KeyboardCode key,
     43                               bool control, bool shift, bool alt,
     44                               std::vector<GdkEvent*>* events) {
     45   if (control)
     46     events->push_back(
     47         SynthesizeKeyEvent(window, true, GDK_Control_L, 0));
     48 
     49   if (shift) {
     50     events->push_back(SynthesizeKeyEvent(window, true, GDK_Shift_L,
     51                                          control ? GDK_CONTROL_MASK : 0));
     52   }
     53 
     54   if (alt) {
     55     guint state = (control ? GDK_CONTROL_MASK : 0) |
     56                   (shift ? GDK_SHIFT_MASK : 0);
     57     events->push_back(
     58         SynthesizeKeyEvent(window, true, GDK_Alt_L, state));
     59   }
     60 
     61   // TODO(estade): handle other state flags besides control, shift, alt?
     62   // For example caps lock.
     63   guint state = (control ? GDK_CONTROL_MASK : 0) |
     64                 (shift ? GDK_SHIFT_MASK : 0) |
     65                 (alt ? GDK_MOD1_MASK : 0);
     66 
     67   guint gdk_key = GdkKeyCodeForWindowsKeyCode(key, shift);
     68   events->push_back(SynthesizeKeyEvent(window, true, gdk_key, state));
     69   events->push_back(SynthesizeKeyEvent(window, false, gdk_key, state));
     70 
     71   if (alt) {
     72     guint state = (control ? GDK_CONTROL_MASK : 0) |
     73                   (shift ? GDK_SHIFT_MASK : 0) | GDK_MOD1_MASK;
     74     events->push_back(
     75         SynthesizeKeyEvent(window, false, GDK_Alt_L, state));
     76   }
     77 
     78   if (shift) {
     79     events->push_back(
     80         SynthesizeKeyEvent(window, false, GDK_Shift_L,
     81                            (control ? GDK_CONTROL_MASK : 0) | GDK_SHIFT_MASK));
     82   }
     83 
     84   if (control) {
     85     events->push_back(
     86         SynthesizeKeyEvent(window, false, GDK_Control_L, GDK_CONTROL_MASK));
     87   }
     88 }
     89 
     90 }  // namespace ui
     91