diff options
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 202 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider.h | 3 | ||||
-rw-r--r-- | chrome/browser/views/tabs/dragged_tab_controller.cc | 21 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.cc | 2 | ||||
-rw-r--r-- | chrome/test/automation/automation_messages_internal.h | 4 | ||||
-rw-r--r-- | chrome/test/automation/browser_proxy.cc | 6 |
6 files changed, 79 insertions, 159 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index aaf7978..e3ff56a 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -1296,160 +1296,70 @@ void AutomationProvider::WindowSimulateClick(const IPC::Message& message, } } -namespace { - -// Available mouse buttons. -enum Button { - Button_None, - Button_Left, - Button_Middle, - Button_Right -}; - -// A type of user gesture for a keyboard or mouse button. -enum Gesture { - Gesture_None, - Gesture_Press, - Gesture_Release -}; - -// SendInput inserts the messages generated into the message queue, which means -// if we want to process these messages immediately we need to force the -// message queue to be processed. -void PostAndPumpInput(INPUT* input) { - SendInput(1, input, sizeof(INPUT)); - MessageLoop::current()->RunAllPending(); -} - -// MOUSEINPUT coordinates are described by MSDN to fall within the range -// 0..65535 (for the primary monitor). We need to convert the client -// coordinates supplied into values in this range. -void GetScreenCoordsForSendInput(HWND window, const POINT& client_point, - LONG* x, LONG* y) { - POINT screen_point = client_point; - MapWindowPoints(window, HWND_DESKTOP, &screen_point, 1); - - HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY); - MONITORINFO mi; - mi.cbSize = sizeof(mi); - GetMonitorInfo(monitor, &mi); - - int monitor_width = mi.rcMonitor.right - mi.rcMonitor.left; - int monitor_height = mi.rcMonitor.bottom - mi.rcMonitor.top; - int point_x = screen_point.x - mi.rcMonitor.left; - int point_y = screen_point.y - mi.rcMonitor.top; - - *x = (point_x * 65535) / monitor_width; - *y = (point_y * 65535) / monitor_height; -} - -// Pack up and send a MOUSEINPUT for a mouse press or release action. -void SendMouseInput(Button button, HWND window, const POINT& client_point, - Gesture gesture) { - INPUT input; - input.type = INPUT_MOUSE; - GetScreenCoordsForSendInput(window, client_point, &input.mi.dx, - &input.mi.dy); - input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; - switch (button) { - case Button_Left: - input.mi.dwFlags |= (gesture == Gesture_Press) ? MOUSEEVENTF_LEFTDOWN - : MOUSEEVENTF_LEFTUP; - break; - case Button_Middle: - input.mi.dwFlags |= (gesture == Gesture_Press) ? MOUSEEVENTF_MIDDLEDOWN - : MOUSEEVENTF_MIDDLEUP; - break; - case Button_Right: - input.mi.dwFlags |= (gesture == Gesture_Press) ? MOUSEEVENTF_RIGHTDOWN - : MOUSEEVENTF_RIGHTUP; - break; - } - input.mi.time = 0; - input.mi.dwExtraInfo = 0; - input.mi.mouseData = 0; - PostAndPumpInput(&input); -} - -// Pack up and send a KEYBDINPUT for a key press or release action. -void SendKeyboardInput(WORD vkey, Gesture gesture) { - INPUT input; - input.type = INPUT_KEYBOARD; - input.ki.wVk = vkey; - input.ki.wScan = 0; - input.ki.dwFlags = gesture == Gesture_Release ? KEYEVENTF_KEYUP : 0; - input.ki.dwExtraInfo = 0; - input.ki.time = 0; - PostAndPumpInput(&input); -} - -Button GetButtonFromFlags(int flags) { - if (flags & views::Event::EF_LEFT_BUTTON_DOWN) - return Button_Left; - if (flags & views::Event::EF_MIDDLE_BUTTON_DOWN) - return Button_Middle; - if (flags & views::Event::EF_RIGHT_BUTTON_DOWN) - return Button_Right; - return Button_None; -} - -} // namespace - void AutomationProvider::WindowSimulateDrag(const IPC::Message& message, int handle, - const POINT& start_point, - const POINT& end_point, + std::vector<POINT> drag_path, int flags, bool press_escape_en_route) { bool succeeded = false; - if (browser_tracker_->ContainsHandle(handle)) { - // TODO(beng): this probably doesn't even need to be done in this process, - // since SendInput is system-wide. - Browser* browser = browser_tracker_->GetResource(handle); - DCHECK(browser); - HWND browser_hwnd = - reinterpret_cast<HWND>(browser->window()->GetNativeHandle()); - - // We can't simulate drags to the non-client area of the window, because - // Windows spawns a nested modal message loop in cases where drags occur - // in many of these locations, so we just don't bother with the test in - // clicks to non-client coordinates. - POINT start_screen_point = start_point; - MapWindowPoints(browser_hwnd, HWND_DESKTOP, &start_screen_point, 1); - LRESULT hittest_code = SendMessage(browser_hwnd, WM_NCHITTEST, 0, - MAKELPARAM(start_screen_point.x, - start_screen_point.y)); - if (hittest_code == HTCLIENT) { - succeeded = true; - - // Press down any optionally specified modifier keys. - if (flags & views::Event::EF_SHIFT_DOWN) - SendKeyboardInput(VK_SHIFT, Gesture_Press); - if (flags & views::Event::EF_CONTROL_DOWN) - SendKeyboardInput(VK_CONTROL, Gesture_Press); - - // Move the mouse along the drag path. - Button button = GetButtonFromFlags(flags); - SendMouseInput(button, browser_hwnd, start_point, Gesture_Press); - SendMouseInput(button, browser_hwnd, end_point, Gesture_Press); - - // Optionally press the escape key if requested. - if (press_escape_en_route) { - SendKeyboardInput(VK_ESCAPE, Gesture_Press); - SendKeyboardInput(VK_ESCAPE, Gesture_Release); - } + if (browser_tracker_->ContainsHandle(handle) && (drag_path.size() > 1)) { + succeeded = true; - // Release the specified mouse button. - SendMouseInput(button, browser_hwnd, end_point, Gesture_Release); + UINT down_message = 0; + UINT up_message = 0; + WPARAM wparam_flags = 0; + if (flags & views::Event::EF_SHIFT_DOWN) + wparam_flags |= MK_SHIFT; + if (flags & views::Event::EF_CONTROL_DOWN) + wparam_flags |= MK_CONTROL; + if (flags & views::Event::EF_LEFT_BUTTON_DOWN) { + wparam_flags |= MK_LBUTTON; + down_message = WM_LBUTTONDOWN; + up_message = WM_LBUTTONUP; + } + if (flags & views::Event::EF_MIDDLE_BUTTON_DOWN) { + wparam_flags |= MK_MBUTTON; + down_message = WM_MBUTTONDOWN; + up_message = WM_MBUTTONUP; + } + if (flags & views::Event::EF_RIGHT_BUTTON_DOWN) { + wparam_flags |= MK_RBUTTON; + down_message = WM_LBUTTONDOWN; + up_message = WM_LBUTTONUP; + } - // Release any optionally specified modifier keys. - if (flags & views::Event::EF_CONTROL_DOWN) - SendKeyboardInput(VK_CONTROL, Gesture_Release); - if (flags & views::Event::EF_SHIFT_DOWN) - SendKeyboardInput(VK_SHIFT, Gesture_Release); + Browser* browser = browser_tracker_->GetResource(handle); + DCHECK(browser); + HWND top_level_hwnd = browser->GetTopLevelHWND(); + POINT temp = drag_path[0]; + MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &temp, 1); + SetCursorPos(temp.x, temp.y); + SendMessage(top_level_hwnd, down_message, wparam_flags, + MAKELPARAM(drag_path[0].x, drag_path[0].y)); + for (int i = 1; i < static_cast<int>(drag_path.size()); ++i) { + temp = drag_path[i]; + MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &temp, 1); + SetCursorPos(temp.x, temp.y); + SendMessage(top_level_hwnd, WM_MOUSEMOVE, wparam_flags, + MAKELPARAM(drag_path[i].x, drag_path[i].y)); } - } - if (succeeded) { + POINT end = drag_path[drag_path.size() - 1]; + MapWindowPoints(top_level_hwnd, HWND_DESKTOP, &end, 1); + SetCursorPos(end.x, end.y); + + if (press_escape_en_route) { + // Press Escape. + ui_controls::SendKeyPress(VK_ESCAPE, + ((flags & views::Event::EF_CONTROL_DOWN) + == views::Event::EF_CONTROL_DOWN), + ((flags & views::Event::EF_SHIFT_DOWN) == + views::Event::EF_SHIFT_DOWN), + ((flags & views::Event::EF_ALT_DOWN) == + views::Event::EF_ALT_DOWN)); + } + SendMessage(top_level_hwnd, up_message, wparam_flags, + MAKELPARAM(end.x, end.y)); + MessageLoop::current()->PostTask(FROM_HERE, new InvokeTaskLaterTask( new WindowDragResponseTask(this, message.routing_id()))); diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index cb9ff00..401e0b5 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -119,8 +119,7 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, bool screen_coordinates); void WindowSimulateDrag(const IPC::Message& message, int handle, - const POINT& start_point, - const POINT& end_point, + std::vector<POINT> drag_path, int flags, bool press_escape_en_route); void WindowSimulateClick(const IPC::Message& message, diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index 0bca5f1..db605a4 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -152,9 +152,6 @@ DraggedTabController::~DraggedTabController() { // bounds, it won't be able to clean up properly since its cleanup routine // uses GetIndexForDraggedContents, which will be invalid. view_.reset(NULL); - // Make sure the TabContents doesn't think we're still its delegate. - if (dragged_contents_ && dragged_contents_->delegate() == this) - dragged_contents_->set_delegate(NULL); ChangeDraggedContents(NULL); // This removes our observer. } @@ -219,6 +216,8 @@ void DraggedTabController::NavigationStateChanged(const TabContents* source, void DraggedTabController::ReplaceContents(TabContents* source, TabContents* new_contents) { DCHECK(dragged_contents_ == source); + source->set_delegate(NULL); + new_contents->set_delegate(this); // If we're attached to a TabStrip, we need to tell the TabStrip that this // TabContents was replaced. @@ -338,14 +337,14 @@ gfx::Point DraggedTabController::GetWindowCreatePoint() const { void DraggedTabController::ChangeDraggedContents(TabContents* new_contents) { if (dragged_contents_) { NotificationService::current()->RemoveObserver(this, - NOTIFY_TAB_CONTENTS_DESTROYED, - Source<TabContents>(dragged_contents_)); + NOTIFY_TAB_CONTENTS_DESTROYED, + Source<TabContents>(dragged_contents_)); } dragged_contents_ = new_contents; if (dragged_contents_) { NotificationService::current()->AddObserver(this, - NOTIFY_TAB_CONTENTS_DESTROYED, - Source<TabContents>(dragged_contents_)); + NOTIFY_TAB_CONTENTS_DESTROYED, + Source<TabContents>(dragged_contents_)); } } @@ -687,6 +686,14 @@ void DraggedTabController::EndDragImpl(EndDragType type) { destroy_now = CompleteDrag(); } } + } else { + // If we get here it means the NavigationController is going down. Don't + // attempt to do any cleanup other than resetting the delegate (if we're + // still the delegate). + if (dragged_contents_ && dragged_contents_->delegate() == this) + dragged_contents_->set_delegate(NULL); + dragged_contents_ = NULL; + attached_tabstrip_ = NULL; } // If we're not destroyed now, we'll be destroyed asynchronously later. if (destroy_now) diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index 8a3db08..47329c5 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -570,7 +570,7 @@ void TabStrip::DestroyDraggedSourceTab(Tab* tab) { std::vector<TabData>::iterator it = tab_data_.begin(); for (; it != tab_data_.end(); ++it) { if (it->tab == tab) { - //NOTREACHED() << "Leaving in an inconsistent state!"; + NOTREACHED() << "Leaving in an inconsistent state!"; tab_data_.erase(it); break; } diff --git a/chrome/test/automation/automation_messages_internal.h b/chrome/test/automation/automation_messages_internal.h index 4d19a89..3eb8498 100644 --- a/chrome/test/automation/automation_messages_internal.h +++ b/chrome/test/automation/automation_messages_internal.h @@ -293,8 +293,8 @@ IPC_BEGIN_MESSAGES(Automation, 0) // defined in chrome/views/event.h // Response: // bool - true if the drag could be performed - IPC_MESSAGE_ROUTED5(AutomationMsg_WindowDragRequest, - int, POINT, POINT, int, bool) + IPC_MESSAGE_ROUTED4(AutomationMsg_WindowDragRequest, + int, std::vector<POINT>, int, bool) IPC_MESSAGE_ROUTED1(AutomationMsg_WindowDragResponse, bool) // Similar to AutomationMsg_InitialLoadsComplete, this indicates that the diff --git a/chrome/test/automation/browser_proxy.cc b/chrome/test/automation/browser_proxy.cc index 58543e1..ce47335 100644 --- a/chrome/test/automation/browser_proxy.cc +++ b/chrome/test/automation/browser_proxy.cc @@ -247,9 +247,13 @@ bool BrowserProxy::SimulateDragWithTimeout(const POINT& start, if (!is_valid()) return false; + std::vector<POINT> drag_path; + drag_path.push_back(start); + drag_path.push_back(end); + IPC::Message* response = NULL; bool succeeded = sender_->SendAndWaitForResponseWithTimeout( - new AutomationMsg_WindowDragRequest(0, handle_, start, end, flags, + new AutomationMsg_WindowDragRequest(0, handle_, drag_path, flags, press_escape_en_route), &response, AutomationMsg_WindowDragResponse::ID, timeout_ms, is_timeout); |