diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-23 20:26:56 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-23 20:26:56 +0000 |
commit | fdc92726554124b1fb8dbb86c4a5f44168945a73 (patch) | |
tree | 7c947116f03952f4c440eb5a0adbc1a6478b2198 /chrome/views | |
parent | 8205209f3b57a69fe811f18771a533bf01407d7f (diff) | |
download | chromium_src-fdc92726554124b1fb8dbb86c4a5f44168945a73.zip chromium_src-fdc92726554124b1fb8dbb86c4a5f44168945a73.tar.gz chromium_src-fdc92726554124b1fb8dbb86c4a5f44168945a73.tar.bz2 |
Deliver events and notifications to the RootView.
Review URL: http://codereview.chromium.org/42519
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12305 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/views')
-rw-r--r-- | chrome/views/SConscript | 7 | ||||
-rw-r--r-- | chrome/views/event.cc | 56 | ||||
-rw-r--r-- | chrome/views/event.h | 21 | ||||
-rw-r--r-- | chrome/views/event_gtk.cc | 36 | ||||
-rw-r--r-- | chrome/views/event_win.cc | 63 | ||||
-rw-r--r-- | chrome/views/views.vcproj | 4 | ||||
-rw-r--r-- | chrome/views/widget/root_view.cc | 2 | ||||
-rw-r--r-- | chrome/views/widget/root_view_gtk.cc | 4 | ||||
-rw-r--r-- | chrome/views/widget/widget_gtk.cc | 108 | ||||
-rw-r--r-- | chrome/views/widget/widget_gtk.h | 46 |
10 files changed, 254 insertions, 93 deletions
diff --git a/chrome/views/SConscript b/chrome/views/SConscript index 626a420..db986d6 100644 --- a/chrome/views/SConscript +++ b/chrome/views/SConscript @@ -185,9 +185,10 @@ if env.Bit('windows'): if env.Bit('linux'): input_files += [ - "view_gtk.cc", - "widget/root_view_gtk.cc", - "widget/widget_gtk.cc" + 'event_gtk.cc', + 'view_gtk.cc', + 'widget/root_view_gtk.cc', + 'widget/widget_gtk.cc' ] # TODO(port?): Incomplete and undecided Views stuff. These compile but aren't # currently needed, and they break the shared build due to missing symbols diff --git a/chrome/views/event.cc b/chrome/views/event.cc index 242daa2..af603cb 100644 --- a/chrome/views/event.cc +++ b/chrome/views/event.cc @@ -19,37 +19,6 @@ Event::Event(EventType type, int flags) flags_(flags) { } -#if defined(OS_WIN) -int Event::GetWindowsFlags() const { - // TODO: need support for x1/x2. - int result = 0; - result |= (flags_ & EF_SHIFT_DOWN) ? MK_SHIFT : 0; - result |= (flags_ & EF_CONTROL_DOWN) ? MK_CONTROL : 0; - result |= (flags_ & EF_LEFT_BUTTON_DOWN) ? MK_LBUTTON : 0; - result |= (flags_ & EF_MIDDLE_BUTTON_DOWN) ? MK_MBUTTON : 0; - result |= (flags_ & EF_RIGHT_BUTTON_DOWN) ? MK_RBUTTON : 0; - return result; -} - -//static -int Event::ConvertWindowsFlags(UINT win_flags) { - int r = 0; - if (win_flags & MK_CONTROL) - r |= EF_CONTROL_DOWN; - if (win_flags & MK_SHIFT) - r |= EF_SHIFT_DOWN; - if (GetKeyState(VK_MENU) < 0) - r |= EF_ALT_DOWN; - if (win_flags & MK_LBUTTON) - r |= EF_LEFT_BUTTON_DOWN; - if (win_flags & MK_MBUTTON) - r |= EF_MIDDLE_BUTTON_DOWN; - if (win_flags & MK_RBUTTON) - r |= EF_RIGHT_BUTTON_DOWN; - return r; -} -#endif - // static int Event::ConvertWebInputEventFlags(int web_input_event_flags) { int r = 0; @@ -83,30 +52,5 @@ MouseEvent::MouseEvent(const MouseEvent& model, View* from, View* to) : LocatedEvent(model, from, to) { } - -int KeyEvent::GetKeyStateFlags() const { -#if defined(OS_WIN) - // Windows Keyboard messages don't come with control key state as parameters - // like mouse messages do, so we need to explicitly probe for these key - // states. - int flags = 0; - if (GetKeyState(VK_MENU) & 0x80) - flags |= Event::EF_ALT_DOWN; - if (GetKeyState(VK_SHIFT) & 0x80) - flags |= Event::EF_SHIFT_DOWN; - if (GetKeyState(VK_CONTROL) & 0x80) - flags |= Event::EF_CONTROL_DOWN; - return flags; -#else - return 0; -#endif -} - -#if defined(OS_WIN) -bool KeyEvent::IsExtendedKey() const { - return (message_flags_ & KF_EXTENDED) == KF_EXTENDED; -} -#endif - } // namespace views diff --git a/chrome/views/event.h b/chrome/views/event.h index 92f93ef..37524eb 100644 --- a/chrome/views/event.h +++ b/chrome/views/event.h @@ -6,6 +6,11 @@ #define CHROME_VIEWS_EVENT_H_ #include "base/basictypes.h" + +#if defined(OS_LINUX) +#include <gdk/gdk.h> +#endif + #include "base/gfx/point.h" #include "webkit/glue/window_open_disposition.h" @@ -86,6 +91,9 @@ class Event { // Convert windows flags to views::Event flags static int ConvertWindowsFlags(uint32 win_flags); +#elif defined(OS_LINUX) + // Convert the state member on a GdkEvent to views::Event flags + static int GetFlagsFromGdkState(int state); #endif // Convert WebInputEvent::Modifiers flags to views::Event flags. @@ -221,13 +229,12 @@ class MouseEvent : public LocatedEvent { //////////////////////////////////////////////////////////////////////////////// class KeyEvent : public Event { public: +#if defined(OS_WIN) // Create a new key event - KeyEvent(EventType type, int ch, int repeat_count, int message_flags) - : Event(type, GetKeyStateFlags()), - character_(ch), - repeat_count_(repeat_count), - message_flags_(message_flags) { - } + KeyEvent(EventType type, int ch, int repeat_count, int message_flags); +#elif defined(OS_LINUX) + KeyEvent(GdkEventKey* event); +#endif int GetCharacter() const { return character_; @@ -242,7 +249,9 @@ class KeyEvent : public Event { } private: +#if defined(OS_WIN) int GetKeyStateFlags() const; +#endif int character_; int repeat_count_; diff --git a/chrome/views/event_gtk.cc b/chrome/views/event_gtk.cc new file mode 100644 index 0000000..dfe89d2 --- /dev/null +++ b/chrome/views/event_gtk.cc @@ -0,0 +1,36 @@ +// 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 "chrome/views/event.h" + +namespace views { + +KeyEvent::KeyEvent(GdkEventKey* event) + : Event(event->type == GDK_KEY_PRESS ? + Event::ET_KEY_PRESSED : Event::ET_KEY_RELEASED, + GetFlagsFromGdkState(event->state)), + // TODO(erg): All these values are iffy. + character_(event->keyval), + repeat_count_(0), + message_flags_(0) { +} + +int Event::GetFlagsFromGdkState(int state) { + int flags = 0; + if (state & GDK_CONTROL_MASK) + flags |= Event::EF_CONTROL_DOWN; + if (state & GDK_SHIFT_MASK) + flags |= Event::EF_SHIFT_DOWN; + if (state & GDK_MOD1_MASK) + flags |= Event::EF_ALT_DOWN; + if (state & GDK_BUTTON1_MASK) + flags |= Event::EF_LEFT_BUTTON_DOWN; + if (state & GDK_BUTTON2_MASK) + flags |= Event::EF_MIDDLE_BUTTON_DOWN; + if (state & GDK_BUTTON3_MASK) + flags |= Event::EF_RIGHT_BUTTON_DOWN; + return flags; +} + +} // namespace views diff --git a/chrome/views/event_win.cc b/chrome/views/event_win.cc new file mode 100644 index 0000000..16449a5 --- /dev/null +++ b/chrome/views/event_win.cc @@ -0,0 +1,63 @@ +// 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 "chrome/views/event.h" + +namespace views { + +int Event::GetWindowsFlags() const { + // TODO: need support for x1/x2. + int result = 0; + result |= (flags_ & EF_SHIFT_DOWN) ? MK_SHIFT : 0; + result |= (flags_ & EF_CONTROL_DOWN) ? MK_CONTROL : 0; + result |= (flags_ & EF_LEFT_BUTTON_DOWN) ? MK_LBUTTON : 0; + result |= (flags_ & EF_MIDDLE_BUTTON_DOWN) ? MK_MBUTTON : 0; + result |= (flags_ & EF_RIGHT_BUTTON_DOWN) ? MK_RBUTTON : 0; + return result; +} + +//static +int Event::ConvertWindowsFlags(UINT win_flags) { + int r = 0; + if (win_flags & MK_CONTROL) + r |= EF_CONTROL_DOWN; + if (win_flags & MK_SHIFT) + r |= EF_SHIFT_DOWN; + if (GetKeyState(VK_MENU) < 0) + r |= EF_ALT_DOWN; + if (win_flags & MK_LBUTTON) + r |= EF_LEFT_BUTTON_DOWN; + if (win_flags & MK_MBUTTON) + r |= EF_MIDDLE_BUTTON_DOWN; + if (win_flags & MK_RBUTTON) + r |= EF_RIGHT_BUTTON_DOWN; + return r; +} + +KeyEvent::KeyEvent(EventType type, int ch, int repeat_count, int message_flags) + : Event(type, GetKeyStateFlags()), + character_(ch), + repeat_count_(repeat_count), + message_flags_(message_flags) { + } + +int KeyEvent::GetKeyStateFlags() const { + // Windows Keyboard messages don't come with control key state as parameters + // like mouse messages do, so we need to explicitly probe for these key + // states. + int flags = 0; + if (GetKeyState(VK_MENU) & 0x80) + flags |= Event::EF_ALT_DOWN; + if (GetKeyState(VK_SHIFT) & 0x80) + flags |= Event::EF_SHIFT_DOWN; + if (GetKeyState(VK_CONTROL) & 0x80) + flags |= Event::EF_CONTROL_DOWN; + return flags; +} + +bool KeyEvent::IsExtendedKey() const { + return (message_flags_ & KF_EXTENDED) == KF_EXTENDED; +} + +} // namespace views diff --git a/chrome/views/views.vcproj b/chrome/views/views.vcproj index 46622b4..01e5770 100644 --- a/chrome/views/views.vcproj +++ b/chrome/views/views.vcproj @@ -800,6 +800,10 @@ > </File> <File + RelativePath=".\event_win.cc" + > + </File> + <File RelativePath=".\fill_layout.cc" > </File> diff --git a/chrome/views/widget/root_view.cc b/chrome/views/widget/root_view.cc index 5e6bcc8..e185b4a 100644 --- a/chrome/views/widget/root_view.cc +++ b/chrome/views/widget/root_view.cc @@ -403,7 +403,7 @@ void RootView::OnMouseReleased(const MouseEvent& e, bool canceled) { } void RootView::OnMouseMoved(const MouseEvent& e) { - View *v = GetViewForPoint(e.location()); + View* v = GetViewForPoint(e.location()); // Find the first enabled view. while (v && !v->IsEnabled()) v = v->GetParent(); diff --git a/chrome/views/widget/root_view_gtk.cc b/chrome/views/widget/root_view_gtk.cc index 115b37d..241e042 100644 --- a/chrome/views/widget/root_view_gtk.cc +++ b/chrome/views/widget/root_view_gtk.cc @@ -21,10 +21,6 @@ void RootView::OnPaint(GdkEventExpose* event) { SchedulePaint(gfx::Rect(canvas.rectangle()), false); if (NeedsPainting(false)) { ProcessPaint(&canvas); - - canvas.FillRectInt(SK_ColorRED, 5, 5, 10, 10); - canvas.FillRectInt(SK_ColorGREEN, 25, 5, 10, 10); - canvas.FillRectInt(SK_ColorBLUE, 45, 5, 10, 10); } } } diff --git a/chrome/views/widget/widget_gtk.cc b/chrome/views/widget/widget_gtk.cc index a2a7b35..9356c85 100644 --- a/chrome/views/widget/widget_gtk.cc +++ b/chrome/views/widget/widget_gtk.cc @@ -10,7 +10,9 @@ namespace views { WidgetGtk::WidgetGtk() - : widget_(NULL) { + : widget_(NULL), + is_mouse_down_(false), + last_mouse_event_was_move_(false) { } WidgetGtk::~WidgetGtk() { @@ -30,6 +32,17 @@ void WidgetGtk::Init(const gfx::Rect& bounds, gtk_drawing_area_size(GTK_DRAWING_AREA(widget_), 100, 100); gtk_widget_show(widget_); + // Make sure we receive our motion events. + gtk_widget_set_events(widget_, + gtk_widget_get_events(widget_) | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_KEY_PRESS_MASK | + GDK_KEY_RELEASE_MASK); + root_view_->OnWidgetCreated(); // TODO(port): if(has_own_focus_manager) block @@ -111,6 +124,7 @@ void WidgetGtk::GetBounds(gfx::Rect* out, bool including_frame) const { void WidgetGtk::MoveToFront(bool should_activate) { // TODO(erg): I'm not sure about how to do z-ordering on GTK widgets... + NOTIMPLEMENTED(); } gfx::NativeView WidgetGtk::GetNativeView() const { @@ -118,7 +132,9 @@ gfx::NativeView WidgetGtk::GetNativeView() const { } void WidgetGtk::PaintNow(const gfx::Rect& update_rect) { - + // TODO(erg): This is woefully incomplete and is a straw man implementation. + gtk_widget_queue_draw_area(widget_, update_rect.x(), update_rect.y(), + update_rect.width(), update_rect.height()); } RootView* WidgetGtk::GetRootView() { @@ -144,18 +160,106 @@ TooltipManager* WidgetGtk::GetTooltipManager() { } bool WidgetGtk::GetAccelerator(int cmd_id, Accelerator* accelerator) { + NOTIMPLEMENTED(); return false; } +gboolean WidgetGtk::OnMotionNotify(GtkWidget* widget, GdkEventMotion* event) { + gfx::Point screen_loc(event->x_root, event->y_root); + if (last_mouse_event_was_move_ && last_mouse_move_x_ == screen_loc.x() && + last_mouse_move_y_ == screen_loc.y()) { + // Don't generate a mouse event for the same location as the last. + return false; + } + last_mouse_move_x_ = screen_loc.x(); + last_mouse_move_y_ = screen_loc.y(); + last_mouse_event_was_move_ = true; + MouseEvent mouse_move(Event::ET_MOUSE_MOVED, + event->x, + event->y, + Event::GetFlagsFromGdkState(event->state)); + root_view_->OnMouseMoved(mouse_move); + return true; +} + +gboolean WidgetGtk::OnButtonPress(GtkWidget* widget, GdkEventButton* event) { + return ProcessMousePressed(event); +} + +gboolean WidgetGtk::OnButtonRelease(GtkWidget* widget, GdkEventButton* event) { + ProcessMouseReleased(event); + return true; +} + gboolean WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) { root_view_->OnPaint(event); return true; } +gboolean WidgetGtk::OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event) { + // TODO(port): We may not actually need this message; it looks like + // OnNotificationNotify() takes care of this case... + return false; +} + +gboolean WidgetGtk::OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) { + last_mouse_event_was_move_ = false; + root_view_->ProcessOnMouseExited(); + return true; +} + +gboolean WidgetGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) { + KeyEvent key_event(event); + return root_view_->ProcessKeyEvent(key_event); +} + +gboolean WidgetGtk::OnKeyRelease(GtkWidget* widget, GdkEventKey* event) { + KeyEvent key_event(event); + return root_view_->ProcessKeyEvent(key_event); +} + RootView* WidgetGtk::CreateRootView() { return new RootView(this); } +bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) { + last_mouse_event_was_move_ = false; + MouseEvent mouse_pressed(Event::ET_MOUSE_PRESSED, + event->x, event->y, +// (dbl_click ? MouseEvent::EF_IS_DOUBLE_CLICK : 0) | + Event::GetFlagsFromGdkState(event->state)); + if (root_view_->OnMousePressed(mouse_pressed)) { + is_mouse_down_ = true; + // TODO(port): Enable this once I figure out what capture is. + // if (!has_capture_) { + // SetCapture(); + // has_capture_ = true; + // current_action_ = FA_FORWARDING; + // } + return true; + } + + return false; +} + +void WidgetGtk::ProcessMouseReleased(GdkEventButton* event) { + last_mouse_event_was_move_ = false; + MouseEvent mouse_up(Event::ET_MOUSE_RELEASED, + event->x, event->y, + Event::GetFlagsFromGdkState(event->state)); + // Release the capture first, that way we don't get confused if + // OnMouseReleased blocks. + // + // TODO(port): Enable this once I figure out what capture is. + // if (has_capture_ && ReleaseCaptureOnMouseReleased()) { + // has_capture_ = false; + // current_action_ = FA_NONE; + // ReleaseCapture(); + // } + is_mouse_down_ = false; + root_view_->OnMouseReleased(mouse_up, false); +} + // static WidgetGtk* WidgetGtk::GetViewForNative(GtkWidget* widget) { gpointer user_data = g_object_get_data(G_OBJECT(widget), "chrome-views"); diff --git a/chrome/views/widget/widget_gtk.h b/chrome/views/widget/widget_gtk.h index 9669ba3..9f3c813 100644 --- a/chrome/views/widget/widget_gtk.h +++ b/chrome/views/widget/widget_gtk.h @@ -49,33 +49,19 @@ class WidgetGtk : public Widget { protected: virtual void OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) {} virtual gboolean OnPaint(GtkWidget* widget, GdkEventExpose* event); - virtual gboolean OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event) { - return false; - } - virtual gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) { - return false; - } - virtual gboolean OnMotionNotify(GtkWidget* widget, GdkEventMotion* event) { - return false; - } - virtual gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event) { - return false; - } - virtual gboolean OnButtonRelease(GtkWidget* widget, GdkEventButton* event) { - return false; - } + virtual gboolean OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event); + virtual gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event); + virtual gboolean OnMotionNotify(GtkWidget* widget, GdkEventMotion* event); + virtual gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event); + virtual gboolean OnButtonRelease(GtkWidget* widget, GdkEventButton* event); virtual gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { return false; } virtual gboolean OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { return false; } - virtual gboolean OnKeyPress(GtkWidget* widget, GdkEventKey* event) { - return false; - } - virtual gboolean OnKeyRelease(GtkWidget* widget, GdkEventKey* event) { - return false; - } + virtual gboolean OnKeyPress(GtkWidget* widget, GdkEventKey* event); + virtual gboolean OnKeyRelease(GtkWidget* widget, GdkEventKey* event); virtual gboolean OnScroll(GtkWidget* widget, GdkEventScroll* event) { return false; } @@ -87,6 +73,10 @@ class WidgetGtk : public Widget { private: virtual RootView* CreateRootView(); + // Process a mouse click + bool ProcessMousePressed(GdkEventButton* event); + void ProcessMouseReleased(GdkEventButton* event); + // Sets and retrieves the WidgetGtk in the userdata section of the widget. static WidgetGtk* GetViewForNative(GtkWidget* widget); static void SetViewForNative(GtkWidget* widget, WidgetGtk* view); @@ -115,6 +105,20 @@ class WidgetGtk : public Widget { // The root of the View hierarchy attached to this window. scoped_ptr<RootView> root_view_; + + // If true, the mouse is currently down. + bool is_mouse_down_; + + // The following are used to detect duplicate mouse move events and not + // deliver them. Displaying a window may result in the system generating + // duplicate move events even though the mouse hasn't moved. + + // If true, the last event was a mouse move event. + bool last_mouse_event_was_move_; + + // Coordinates of the last mouse move event, in screen coordinates. + int last_mouse_move_x_; + int last_mouse_move_y_; }; } // namespace views |