summaryrefslogtreecommitdiffstats
path: root/views/focus/accelerator_handler_gtk.cc
blob: 8b52b981401f3aa38132cc9f964e20c7633dc8f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <gtk/gtk.h>

#include "views/focus/accelerator_handler.h"

#include "views/focus/focus_manager.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window_gtk.h"

namespace views {

AcceleratorHandler::AcceleratorHandler() : last_key_pressed_(0) {
}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  if (event->type != GDK_KEY_PRESS && event->type != GDK_KEY_RELEASE) {
    gtk_main_do_event(event);
    return true;
  }

  GdkEventKey* key_event = reinterpret_cast<GdkEventKey*>(event);
  // Let's retrieve the focus manager for the GdkWindow.
  GdkWindow* window = gdk_window_get_toplevel(key_event->window);
  gpointer ptr;
  gdk_window_get_user_data(window, &ptr);
  DCHECK(ptr);  // The top-level window is expected to always be associated
                // with the top-level gtk widget.
  WindowGtk* widget =
      WidgetGtk::GetWindowForNative(reinterpret_cast<GtkWidget*>(ptr));
  if (!widget) {
    // During dnd we get events for windows we don't control (such as the
    // window being dragged).
    gtk_main_do_event(event);
    return true;
  }
  FocusManager* focus_manager = widget->GetFocusManager();
  if (!focus_manager) {
    NOTREACHED();
    return true;
  }

  if (event->type == GDK_KEY_PRESS) {
    KeyEvent view_key_event(key_event, true);
    // FocusManager::OnKeyPressed and OnKeyReleased return false if this
    // message has been consumed and should not be propagated further.
    if (!focus_manager->OnKeyEvent(view_key_event)) {
      last_key_pressed_ = key_event->keyval;
      return true;
    }
  }

  // Key release, make sure to filter-out the key release for key press consumed
  // as accelerators to avoid unpaired key release.
  if (event->type == GDK_KEY_RELEASE &&
      key_event->keyval == last_key_pressed_) {
    last_key_pressed_ = 0;
    return true;
  }

  gtk_main_do_event(event);
  return true;
}

}  // namespace views