diff options
Diffstat (limited to 'chrome/browser/automation/automation_provider_gtk.cc')
-rw-r--r-- | chrome/browser/automation/automation_provider_gtk.cc | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/chrome/browser/automation/automation_provider_gtk.cc b/chrome/browser/automation/automation_provider_gtk.cc new file mode 100644 index 0000000..8b391ee --- /dev/null +++ b/chrome/browser/automation/automation_provider_gtk.cc @@ -0,0 +1,221 @@ +// 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/browser/automation/automation_provider.h" + +#include <gtk/gtk.h> + +#include "chrome/browser/automation/ui_controls.h" +#include "chrome/browser/automation/automation_browser_tracker.h" +#include "chrome/browser/automation/automation_window_tracker.h" +#include "chrome/browser/gtk/browser_window_gtk.h" +#include "chrome/browser/gtk/gtk_util.h" +#include "chrome/browser/gtk/view_id_util.h" +#include "chrome/test/automation/automation_messages.h" +#include "gfx/point.h" +#include "gfx/rect.h" + +void AutomationProvider::SetWindowBounds(int handle, const gfx::Rect& bounds, + bool* success) { + *success = false; + GtkWindow* window = window_tracker_->GetResource(handle); + if (window) { + gtk_window_move(window, bounds.x(), bounds.height()); + gtk_window_resize(window, bounds.width(), bounds.height()); + *success = true; + } +} + +void AutomationProvider::SetWindowVisible(int handle, bool visible, + bool* result) { + *result = false; + GtkWindow* window = window_tracker_->GetResource(handle); + if (window) { + if (visible) { + gtk_window_present(window); + } else { + gtk_widget_hide(GTK_WIDGET(window)); + } + *result = true; + } +} + +#if !defined(TOOLKIT_VIEWS) +void AutomationProvider::WindowGetViewBounds(int handle, int view_id, + bool screen_coordinates, + bool* success, + gfx::Rect* bounds) { + *success = false; + + GtkWindow* window = window_tracker_->GetResource(handle); + if (window) { + GtkWidget* widget = ViewIDUtil::GetWidget(GTK_WIDGET(window), + static_cast<ViewID>(view_id)); + if (!widget) + return; + *success = true; + *bounds = gfx::Rect(widget->allocation.width, widget->allocation.height); + gint x, y; + if (screen_coordinates) { + gfx::Point point = gtk_util::GetWidgetScreenPosition(widget); + x = point.x(); + y = point.y(); + } else { + gtk_widget_translate_coordinates(widget, GTK_WIDGET(window), + 0, 0, &x, &y); + } + bounds->set_origin(gfx::Point(x, y)); + } +} +#endif + +void AutomationProvider::ActivateWindow(int handle) { + NOTIMPLEMENTED(); +} + +void AutomationProvider::IsWindowMaximized(int handle, bool* is_maximized, + bool* success) { + *success = false; + NOTIMPLEMENTED(); +} + +void AutomationProvider::PrintAsync(int tab_handle) { + NOTIMPLEMENTED(); +} + +// This task sends a WindowDragResponse message with the appropriate +// routing ID to the automation proxy. This is implemented as a task so that +// we know that the mouse events (and any tasks that they spawn on the message +// loop) have been processed by the time this is sent. +class WindowDragResponseTask : public Task { + public: + WindowDragResponseTask(AutomationProvider* provider, + IPC::Message* reply_message) + : provider_(provider), + reply_message_(reply_message) { + DCHECK(provider_); + DCHECK(reply_message_); + } + + virtual ~WindowDragResponseTask() { + } + + virtual void Run() { + AutomationMsg_WindowDrag::WriteReplyParams(reply_message_, true); + provider_->Send(reply_message_); + } + + private: + AutomationProvider* provider_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask); +}; + +// A task that just runs a SendMouseEvent and performs another task when done. +class MouseEventTask : public Task { + public: + MouseEventTask(Task* next_task, ui_controls::MouseButtonState state) + : next_task_(next_task), + state_(state) {} + + virtual ~MouseEventTask() { + } + + virtual void Run() { + ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT, state_, + next_task_); + } + + private: + // The task to execute when we are done. + Task* next_task_; + + // Mouse press or mouse release. + ui_controls::MouseButtonState state_; + + DISALLOW_COPY_AND_ASSIGN(MouseEventTask); +}; + +// A task that just runs a SendMouseMove and performs another task when done. +class MouseMoveTask : public Task { + public: + MouseMoveTask(Task* next_task, int absolute_x, int absolute_y) + : next_task_(next_task), + x_(absolute_x), + y_(absolute_y) { + } + + virtual ~MouseMoveTask() { + } + + virtual void Run() { + ui_controls::SendMouseMoveNotifyWhenDone(x_, y_, next_task_); + } + + private: + // The task to execute when we are done. + Task* next_task_; + + // Coordinates of the press. + int x_; + int y_; + + DISALLOW_COPY_AND_ASSIGN(MouseMoveTask); +}; + +void AutomationProvider::WindowSimulateDrag(int handle, + std::vector<gfx::Point> drag_path, + int flags, + bool press_escape_en_route, + IPC::Message* reply_message) { + // TODO(estade): don't ignore |flags| or |escape_en_route|. + gfx::NativeWindow window = + browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); + if (window && (drag_path.size() > 1)) { + int x, y; + gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); + + // Create a nested stack of tasks to run. + Task* next_task = new WindowDragResponseTask(this, reply_message); + next_task = new MouseEventTask(next_task, ui_controls::UP); + next_task = new MouseEventTask(next_task, ui_controls::UP); + for (size_t i = drag_path.size() - 1; i > 0; --i) { + // Smooth out the mouse movements by adding intermediate points. This + // better simulates a real user drag. + int dest_x = drag_path[i].x() + x; + int dest_y = drag_path[i].y() + y; + int half_step_x = (dest_x + drag_path[i - 1].x() + x) / 2; + int half_step_y = (dest_y + drag_path[i - 1].y() + y) / 2; + + next_task = new MouseMoveTask(next_task, dest_x, dest_y); + next_task = new MouseMoveTask(next_task, half_step_x, half_step_y); + } + next_task = new MouseEventTask(next_task, ui_controls::DOWN); + + ui_controls::SendMouseMoveNotifyWhenDone(x + drag_path[0].x(), + y + drag_path[0].y(), + next_task); + } else { + AutomationMsg_WindowDrag::WriteReplyParams(reply_message, false); + Send(reply_message); + } +} + +void AutomationProvider::TerminateSession(int handle, bool* success) { + *success = false; + NOTIMPLEMENTED(); +} + +void AutomationProvider::GetWindowBounds(int handle, gfx::Rect* bounds, + bool* result) { + *result = false; + NOTIMPLEMENTED(); +} + +void AutomationProvider::GetWindowTitle(int handle, string16* text) { + gfx::NativeWindow window = window_tracker_->GetResource(handle); + const gchar* title = gtk_window_get_title(window); + text->assign(UTF8ToUTF16(title)); +} |