Home | History | Annotate | Download | only in caca
      1 // Copyright 2014 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/ozone/platform/caca/caca_event_source.h"
      6 
      7 #include <caca.h>
      8 
      9 #include "base/bind.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "ui/events/event.h"
     12 #include "ui/events/keycodes/keyboard_codes.h"
     13 #include "ui/ozone/platform/caca/caca_window.h"
     14 
     15 namespace ui {
     16 
     17 namespace {
     18 
     19 ui::KeyboardCode GetKeyboardCode(const caca_event_t& event) {
     20   // List of special mappings the Caca provides.
     21   static const ui::KeyboardCode kCacaKeyMap[] = {
     22     ui::VKEY_UNKNOWN,
     23     ui::VKEY_A,
     24     ui::VKEY_B,
     25     ui::VKEY_C,
     26     ui::VKEY_D,
     27     ui::VKEY_E,
     28     ui::VKEY_F,
     29     ui::VKEY_G,
     30     ui::VKEY_BACK,
     31     ui::VKEY_TAB,
     32     ui::VKEY_J,
     33     ui::VKEY_K,
     34     ui::VKEY_L,
     35     ui::VKEY_RETURN,
     36     ui::VKEY_N,
     37     ui::VKEY_O,
     38     ui::VKEY_P,
     39     ui::VKEY_Q,
     40     ui::VKEY_R,
     41     ui::VKEY_PAUSE,
     42     ui::VKEY_T,
     43     ui::VKEY_U,
     44     ui::VKEY_V,
     45     ui::VKEY_W,
     46     ui::VKEY_X,
     47     ui::VKEY_Y,
     48     ui::VKEY_Z,
     49     ui::VKEY_ESCAPE,
     50     ui::VKEY_DELETE,
     51     ui::VKEY_UP,
     52     ui::VKEY_DOWN,
     53     ui::VKEY_LEFT,
     54     ui::VKEY_RIGHT,
     55     ui::VKEY_INSERT,
     56     ui::VKEY_HOME,
     57     ui::VKEY_END,
     58     ui::VKEY_PRIOR,
     59     ui::VKEY_NEXT,
     60     ui::VKEY_F1,
     61     ui::VKEY_F2,
     62     ui::VKEY_F3,
     63     ui::VKEY_F4,
     64     ui::VKEY_F5,
     65     ui::VKEY_F6,
     66     ui::VKEY_F7,
     67     ui::VKEY_F8,
     68     ui::VKEY_F9,
     69     ui::VKEY_F10,
     70     ui::VKEY_F11,
     71     ui::VKEY_F12,
     72   };
     73 
     74   int key_code = caca_get_event_key_ch(&event);
     75   if (key_code >= 'a' && key_code <= 'z')
     76     return static_cast<ui::KeyboardCode>(key_code - ('a' - 'A'));
     77   if (key_code >= '0' && key_code <= 'Z')
     78     return static_cast<ui::KeyboardCode>(key_code);
     79   if (static_cast<unsigned int>(key_code) < arraysize(kCacaKeyMap))
     80     return kCacaKeyMap[key_code];
     81 
     82   return ui::VKEY_UNKNOWN;
     83 }
     84 
     85 int ModifierFromKey(const caca_event_t& event) {
     86   int key_code = caca_get_event_key_ch(&event);
     87   if (key_code >= 'A' && key_code <= 'Z')
     88     return ui::EF_SHIFT_DOWN;
     89   if ((key_code >= CACA_KEY_CTRL_A && key_code <= CACA_KEY_CTRL_G) ||
     90       (key_code >= CACA_KEY_CTRL_J && key_code <= CACA_KEY_CTRL_L) ||
     91       (key_code >= CACA_KEY_CTRL_N && key_code <= CACA_KEY_CTRL_R) ||
     92       (key_code >= CACA_KEY_CTRL_T && key_code <= CACA_KEY_CTRL_Z))
     93     return ui::EF_CONTROL_DOWN;
     94 
     95   return ui::EF_NONE;
     96 }
     97 
     98 int ModifierFromButton(const caca_event_t& event) {
     99   switch (caca_get_event_mouse_button(&event)) {
    100     case 1:
    101       return ui::EF_LEFT_MOUSE_BUTTON;
    102     case 2:
    103       return ui::EF_RIGHT_MOUSE_BUTTON;
    104     case 3:
    105       return ui::EF_MIDDLE_MOUSE_BUTTON;
    106   }
    107   return 0;
    108 }
    109 
    110 // Translate coordinates to bitmap coordinates.
    111 gfx::PointF TranslateLocation(const gfx::PointF& location, CacaWindow* window) {
    112   gfx::Size physical_size = window->physical_size();
    113   gfx::Size bitmap_size = window->bitmap_size();
    114   return gfx::PointF(
    115       location.x() * bitmap_size.width() / physical_size.width(),
    116       location.y() * bitmap_size.height() / physical_size.height());
    117 }
    118 
    119 ui::EventType GetEventTypeFromNative(const caca_event_t& event) {
    120   switch (caca_get_event_type(&event)) {
    121     case CACA_EVENT_KEY_PRESS:
    122       return ui::ET_KEY_PRESSED;
    123     case CACA_EVENT_KEY_RELEASE:
    124       return ui::ET_KEY_RELEASED;
    125     case CACA_EVENT_MOUSE_PRESS:
    126       return ui::ET_MOUSE_PRESSED;
    127     case CACA_EVENT_MOUSE_RELEASE:
    128       return ui::ET_MOUSE_RELEASED;
    129     case CACA_EVENT_MOUSE_MOTION:
    130       return ui::ET_MOUSE_MOVED;
    131     default:
    132       return ui::ET_UNKNOWN;
    133   }
    134 }
    135 
    136 }  // namespace
    137 
    138 CacaEventSource::CacaEventSource() : modifier_flags_(0) {
    139 }
    140 
    141 CacaEventSource::~CacaEventSource() {
    142 }
    143 
    144 void CacaEventSource::TryProcessingEvent(CacaWindow* window) {
    145   if (!window->display())
    146     return;
    147 
    148   caca_event_t event;
    149   int event_mask = CACA_EVENT_KEY_PRESS | CACA_EVENT_KEY_RELEASE |
    150                    CACA_EVENT_MOUSE_PRESS | CACA_EVENT_MOUSE_RELEASE |
    151                    CACA_EVENT_MOUSE_MOTION | CACA_EVENT_RESIZE |
    152                    CACA_EVENT_QUIT;
    153 
    154   if (!caca_get_event(window->display(), event_mask, &event, 0))
    155     return;
    156 
    157   switch (caca_get_event_type(&event)) {
    158     case CACA_EVENT_KEY_PRESS:
    159     case CACA_EVENT_KEY_RELEASE:
    160     case CACA_EVENT_MOUSE_PRESS:
    161     case CACA_EVENT_MOUSE_RELEASE:
    162     case CACA_EVENT_MOUSE_MOTION:
    163       OnInputEvent(&event, window);
    164       break;
    165     case CACA_EVENT_RESIZE:
    166       window->OnCacaResize();
    167       break;
    168     case CACA_EVENT_QUIT:
    169       window->OnCacaQuit();
    170       break;
    171     default:
    172       NOTIMPLEMENTED();
    173   }
    174 }
    175 
    176 void CacaEventSource::OnInputEvent(caca_event_t* event, CacaWindow* window) {
    177   ui::EventType type = GetEventTypeFromNative(*event);
    178   bool pressed = type == ui::ET_KEY_PRESSED || type == ui::ET_MOUSE_PRESSED;
    179 
    180   switch (type) {
    181     case ui::ET_KEY_PRESSED:
    182     case ui::ET_KEY_RELEASED: {
    183       if (pressed)
    184         modifier_flags_ |= ModifierFromKey(*event);
    185       else
    186         modifier_flags_ &= ~ModifierFromKey(*event);
    187 
    188       ui::KeyEvent key_event(
    189           type, GetKeyboardCode(*event), modifier_flags_);
    190       window->OnCacaEvent(&key_event);
    191       break;
    192     }
    193     case ui::ET_MOUSE_MOVED:
    194       last_cursor_location_.SetPoint(caca_get_event_mouse_x(event),
    195                                      caca_get_event_mouse_y(event));
    196       // Update cursor location.
    197       caca_gotoxy(caca_get_canvas(window->display()),
    198                   last_cursor_location_.x(),
    199                   last_cursor_location_.y());
    200 
    201     // fallthrough
    202     case ui::ET_MOUSE_PRESSED:
    203     case ui::ET_MOUSE_RELEASED: {
    204       int flags = 0;
    205       int changed_flags = 0;
    206       if (type != ui::ET_MOUSE_MOVED) {
    207         if (pressed) {
    208           changed_flags = ModifierFromButton(*event);
    209           modifier_flags_ |= changed_flags;
    210         } else {
    211           modifier_flags_ &= ~changed_flags;
    212         }
    213         // On release the button pressed is removed from |modifier_flags_|,
    214         // but sending the event needs it set.
    215         flags = modifier_flags_ | changed_flags;
    216       }
    217       gfx::PointF location = TranslateLocation(last_cursor_location_, window);
    218       ui::MouseEvent mouse_event(
    219           type, location, location, flags, changed_flags);
    220       window->OnCacaEvent(&mouse_event);
    221       break;
    222     }
    223     default:
    224       NOTIMPLEMENTED();
    225       break;
    226   }
    227 }
    228 
    229 }  // namespace ui
    230