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 "chrome/browser/ui/views/panels/x11_panel_resizer.h" 6 7 #include "chrome/browser/ui/panels/panel.h" 8 #include "chrome/browser/ui/panels/panel_manager.h" 9 #include "ui/aura/window.h" 10 #include "ui/aura/window_delegate.h" 11 #include "ui/base/hit_test.h" 12 #include "ui/events/event.h" 13 #include "ui/events/event_utils.h" 14 #include "ui/views/view.h" 15 16 namespace { 17 18 // Returns true if the window can be resized via |component|. 19 bool IsWindowBorder(int component) { 20 return component == HTBOTTOM || 21 component == HTBOTTOMLEFT || 22 component == HTBOTTOMRIGHT || 23 component == HTLEFT || 24 component == HTRIGHT || 25 component == HTTOP || 26 component == HTTOPLEFT || 27 component == HTTOPRIGHT; 28 } 29 30 } // namespace 31 32 X11PanelResizer::X11PanelResizer(Panel* panel, aura::Window* window) 33 : panel_(panel), 34 window_(window), 35 resize_state_(NOT_RESIZING), 36 resize_component_(HTNOWHERE) { 37 } 38 39 X11PanelResizer::~X11PanelResizer() { 40 StopResizing(NULL, true); 41 } 42 43 void X11PanelResizer::OnMousePressed(ui::MouseEvent* event) { 44 if (resize_state_ != NOT_RESIZING || 45 event->type() != ui::ET_MOUSE_PRESSED || 46 !event->IsLeftMouseButton() || 47 !event->native_event()) { 48 return; 49 } 50 51 int component = window_->delegate()->GetNonClientComponent(event->location()); 52 if (!IsWindowBorder(component)) 53 return; 54 55 // Set capture so that we get notified of all subsequent events. 56 window_->SetCapture(); 57 58 resize_state_ = RESIZE_CAN_START; 59 initial_press_location_in_screen_ = ui::EventSystemLocationFromNative( 60 event->native_event()); 61 resize_component_ = component; 62 event->StopPropagation(); 63 } 64 65 void X11PanelResizer::OnMouseDragged(ui::MouseEvent* event) { 66 if (resize_state_ != RESIZE_CAN_START && 67 resize_state_ != RESIZE_IN_PROGRESS) { 68 return; 69 } 70 71 if (!event->native_event()) 72 return; 73 74 // Get the location in screen coordinates from the XEvent because converting 75 // the mouse location to screen coordinates using ScreenPositionClient returns 76 // an incorrect location while the panel is moving. See crbug.com/353393 for 77 // more details. 78 // TODO: Fix conversion to screen coordinates. 79 gfx::Point location_in_screen = ui::EventSystemLocationFromNative( 80 event->native_event()); 81 if (resize_state_ == RESIZE_CAN_START) { 82 gfx::Vector2d delta = 83 location_in_screen - initial_press_location_in_screen_; 84 if (views::View::ExceededDragThreshold(delta)) { 85 resize_state_ = RESIZE_IN_PROGRESS; 86 panel_->manager()->StartResizingByMouse(panel_, location_in_screen, 87 resize_component_); 88 } 89 } 90 91 if (resize_state_ == RESIZE_IN_PROGRESS) 92 panel_->manager()->ResizeByMouse(location_in_screen); 93 94 event->StopPropagation(); 95 } 96 97 void X11PanelResizer::StopResizing(ui::MouseEvent* event, bool canceled) { 98 if (resize_state_ == NOT_RESIZING) 99 return; 100 101 if (resize_state_ == RESIZE_IN_PROGRESS) { 102 panel_->manager()->EndResizingByMouse(canceled); 103 window_->ReleaseCapture(); 104 } 105 if (event) 106 event->StopPropagation(); 107 resize_state_ = NOT_RESIZING; 108 } 109 110 void X11PanelResizer::OnMouseEvent(ui::MouseEvent* event) { 111 switch (event->type()) { 112 case ui::ET_MOUSE_PRESSED: 113 OnMousePressed(event); 114 break; 115 case ui::ET_MOUSE_DRAGGED: 116 OnMouseDragged(event); 117 break; 118 case ui::ET_MOUSE_RELEASED: 119 StopResizing(event, false); 120 break; 121 case ui::ET_MOUSE_CAPTURE_CHANGED: 122 StopResizing(event, true); 123 break; 124 default: 125 break; 126 } 127 } 128