OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/panels/panel_drag_gtk.h" | 5 #include "chrome/browser/ui/panels/panel_drag_gtk.h" |
6 | 6 |
7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
8 | 8 |
9 #include "chrome/browser/ui/panels/panel.h" | 9 #include "chrome/browser/ui/panels/panel.h" |
10 #include "chrome/browser/ui/panels/panel_constants.h" | 10 #include "chrome/browser/ui/panels/panel_constants.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 DCHECK(!drag_delegate_); | 141 DCHECK(!drag_delegate_); |
142 DCHECK(!initial_mouse_down_); | 142 DCHECK(!initial_mouse_down_); |
143 DCHECK(!click_handler_); | 143 DCHECK(!click_handler_); |
144 } | 144 } |
145 | 145 |
146 void PanelDragGtk::InitialWindowEdgeMousePress(GdkEventButton* event, | 146 void PanelDragGtk::InitialWindowEdgeMousePress(GdkEventButton* event, |
147 GdkCursor* cursor, | 147 GdkCursor* cursor, |
148 GdkWindowEdge& edge) { | 148 GdkWindowEdge& edge) { |
149 AssertCleanState(); | 149 AssertCleanState(); |
150 drag_delegate_ = new ResizeDragDelegate(panel_, edge); | 150 drag_delegate_ = new ResizeDragDelegate(panel_, edge); |
| 151 drag_state_ = DRAG_CAN_START; |
151 GrabPointerAndKeyboard(event, cursor); | 152 GrabPointerAndKeyboard(event, cursor); |
152 } | 153 } |
153 | 154 |
154 void PanelDragGtk::InitialTitlebarMousePress(GdkEventButton* event, | 155 void PanelDragGtk::InitialTitlebarMousePress(GdkEventButton* event, |
155 GtkWidget* titlebar_widget) { | 156 GtkWidget* titlebar_widget) { |
156 AssertCleanState(); | 157 AssertCleanState(); |
157 click_handler_ = titlebar_widget; | 158 click_handler_ = titlebar_widget; |
158 drag_delegate_ = new MoveDragDelegate(panel_); | 159 drag_delegate_ = new MoveDragDelegate(panel_); |
| 160 drag_state_ = DRAG_CAN_START; |
159 GrabPointerAndKeyboard(event, gfx::GetCursor(GDK_FLEUR)); // Drag cursor. | 161 GrabPointerAndKeyboard(event, gfx::GetCursor(GDK_FLEUR)); // Drag cursor. |
160 } | 162 } |
161 | 163 |
162 void PanelDragGtk::GrabPointerAndKeyboard(GdkEventButton* event, | 164 void PanelDragGtk::GrabPointerAndKeyboard(GdkEventButton* event, |
163 GdkCursor* cursor) { | 165 GdkCursor* cursor) { |
164 // Remember initial mouse event for use in determining when drag | 166 // Remember initial mouse event for use in determining when drag |
165 // threshold has been exceeded. | 167 // threshold has been exceeded. |
166 initial_mouse_down_ = gdk_event_copy(reinterpret_cast<GdkEvent*>(event)); | 168 initial_mouse_down_ = gdk_event_copy(reinterpret_cast<GdkEvent*>(event)); |
167 | 169 |
168 // Grab pointer and keyboard to make sure we have the focus and get | 170 // Grab pointer and keyboard to make sure we have the focus and get |
(...skipping 12 matching lines...) Expand all Loading... |
181 GdkGrabStatus keyboard_grab_status = | 183 GdkGrabStatus keyboard_grab_status = |
182 gdk_keyboard_grab(gdk_window, TRUE, event->time); | 184 gdk_keyboard_grab(gdk_window, TRUE, event->time); |
183 if (pointer_grab_status != GDK_GRAB_SUCCESS || | 185 if (pointer_grab_status != GDK_GRAB_SUCCESS || |
184 keyboard_grab_status != GDK_GRAB_SUCCESS) { | 186 keyboard_grab_status != GDK_GRAB_SUCCESS) { |
185 // Grab could fail if someone else already has the pointer/keyboard | 187 // Grab could fail if someone else already has the pointer/keyboard |
186 // grabbed. Cancel the drag. | 188 // grabbed. Cancel the drag. |
187 DLOG(ERROR) << "Unable to grab pointer or keyboard (pointer_status=" | 189 DLOG(ERROR) << "Unable to grab pointer or keyboard (pointer_status=" |
188 << pointer_grab_status << ", keyboard_status=" | 190 << pointer_grab_status << ", keyboard_status=" |
189 << keyboard_grab_status << ")"; | 191 << keyboard_grab_status << ")"; |
190 EndDrag(true); | 192 EndDrag(true); |
| 193 ReleasePointerAndKeyboardGrab(); |
191 return; | 194 return; |
192 } | 195 } |
193 | 196 |
194 gtk_grab_add(drag_widget_); | 197 gtk_grab_add(drag_widget_); |
195 } | 198 } |
196 | 199 |
197 void PanelDragGtk::ReleasePointerAndKeyboardGrab() { | 200 void PanelDragGtk::ReleasePointerAndKeyboardGrab() { |
| 201 DCHECK(!drag_delegate_); |
198 if (drag_state_ == NOT_DRAGGING) | 202 if (drag_state_ == NOT_DRAGGING) |
199 return; | 203 return; |
200 | 204 |
201 DCHECK_EQ(DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE, drag_state_); | 205 DCHECK_EQ(DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE, drag_state_); |
202 gdk_pointer_ungrab(GDK_CURRENT_TIME); | 206 gdk_pointer_ungrab(GDK_CURRENT_TIME); |
203 gdk_keyboard_ungrab(GDK_CURRENT_TIME); | 207 gdk_keyboard_ungrab(GDK_CURRENT_TIME); |
204 gtk_grab_remove(drag_widget_); | 208 gtk_grab_remove(drag_widget_); |
205 drag_state_ = NOT_DRAGGING; // Drag is truly over now. | 209 drag_state_ = NOT_DRAGGING; // Drag is truly over now. |
206 } | 210 } |
207 | 211 |
208 void PanelDragGtk::EndDrag(bool canceled) { | 212 void PanelDragGtk::EndDrag(bool canceled) { |
| 213 if (drag_state_ == NOT_DRAGGING || |
| 214 drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE) { |
| 215 DCHECK(!drag_delegate_); |
| 216 return; |
| 217 } |
| 218 |
| 219 DCHECK(drag_delegate_); |
| 220 |
209 if (initial_mouse_down_) { | 221 if (initial_mouse_down_) { |
210 gdk_event_free(initial_mouse_down_); | 222 gdk_event_free(initial_mouse_down_); |
211 initial_mouse_down_ = NULL; | 223 initial_mouse_down_ = NULL; |
212 } | 224 } |
213 | 225 |
214 if (drag_delegate_) { | 226 if (drag_state_ == DRAG_IN_PROGRESS) { |
215 if (drag_state_ == DRAG_IN_PROGRESS) { | 227 drag_delegate_->DragEnded(canceled); |
216 drag_delegate_->DragEnded(canceled); | 228 } |
217 drag_state_ = DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE; | 229 drag_state_ = DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE; |
218 } | |
219 | 230 |
220 delete drag_delegate_; | 231 delete drag_delegate_; |
221 drag_delegate_ = NULL; | 232 drag_delegate_ = NULL; |
222 } | |
223 | 233 |
224 click_handler_ = NULL; | 234 click_handler_ = NULL; |
225 } | 235 } |
226 | 236 |
227 gboolean PanelDragGtk::OnMouseMoveEvent(GtkWidget* widget, | 237 gboolean PanelDragGtk::OnMouseMoveEvent(GtkWidget* widget, |
228 GdkEventMotion* event) { | 238 GdkEventMotion* event) { |
229 DCHECK(drag_delegate_ || drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE); | 239 DCHECK(drag_state_ != NOT_DRAGGING); |
230 if (!drag_delegate_) | 240 |
| 241 if (drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE) { |
| 242 DCHECK(!drag_delegate_); |
231 return TRUE; | 243 return TRUE; |
| 244 } |
| 245 |
| 246 DCHECK(drag_delegate_); |
232 | 247 |
233 gdouble new_x_double; | 248 gdouble new_x_double; |
234 gdouble new_y_double; | 249 gdouble new_y_double; |
235 gdk_event_get_root_coords(reinterpret_cast<GdkEvent*>(event), | 250 gdk_event_get_root_coords(reinterpret_cast<GdkEvent*>(event), |
236 &new_x_double, &new_y_double); | 251 &new_x_double, &new_y_double); |
237 gint new_x = static_cast<gint>(new_x_double); | 252 gint new_x = static_cast<gint>(new_x_double); |
238 gint new_y = static_cast<gint>(new_y_double); | 253 gint new_y = static_cast<gint>(new_y_double); |
239 | 254 |
240 // Begin dragging only after mouse has moved beyond the drag threshold. | 255 // Begin dragging only after mouse has moved beyond the drag threshold. |
241 if (drag_state_ == NOT_DRAGGING) { | 256 if (drag_state_ == DRAG_CAN_START) { |
242 DCHECK(initial_mouse_down_); | 257 DCHECK(initial_mouse_down_); |
243 gdouble old_x_double; | 258 gdouble old_x_double; |
244 gdouble old_y_double; | 259 gdouble old_y_double; |
245 gdk_event_get_root_coords(initial_mouse_down_, | 260 gdk_event_get_root_coords(initial_mouse_down_, |
246 &old_x_double, &old_y_double); | 261 &old_x_double, &old_y_double); |
247 gint old_x = static_cast<gint>(old_x_double); | 262 gint old_x = static_cast<gint>(old_x_double); |
248 gint old_y = static_cast<gint>(old_y_double); | 263 gint old_y = static_cast<gint>(old_y_double); |
249 | 264 |
250 if (gtk_drag_check_threshold(drag_widget_, old_x, old_y, | 265 if (gtk_drag_check_threshold(drag_widget_, old_x, old_y, |
251 new_x, new_y)) { | 266 new_x, new_y)) { |
252 drag_state_ = DRAG_IN_PROGRESS; | 267 drag_state_ = DRAG_IN_PROGRESS; |
253 drag_delegate_->DragStarted(gfx::Point(old_x, old_y)); | 268 drag_delegate_->DragStarted(gfx::Point(old_x, old_y)); |
254 gdk_event_free(initial_mouse_down_); | 269 gdk_event_free(initial_mouse_down_); |
255 initial_mouse_down_ = NULL; | 270 initial_mouse_down_ = NULL; |
256 } | 271 } |
257 } | 272 } |
258 | 273 |
259 if (drag_state_ == DRAG_IN_PROGRESS) | 274 if (drag_state_ == DRAG_IN_PROGRESS) |
260 drag_delegate_->Dragged(gfx::Point(new_x, new_y)); | 275 drag_delegate_->Dragged(gfx::Point(new_x, new_y)); |
261 | 276 |
262 return TRUE; | 277 return TRUE; |
263 } | 278 } |
264 | 279 |
265 gboolean PanelDragGtk::OnButtonPressEvent(GtkWidget* widget, | 280 gboolean PanelDragGtk::OnButtonPressEvent(GtkWidget* widget, |
266 GdkEventButton* event) { | 281 GdkEventButton* event) { |
267 DCHECK(drag_delegate_ || drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE); | 282 DCHECK(drag_state_ != NOT_DRAGGING); |
268 return TRUE; | 283 return TRUE; |
269 } | 284 } |
270 | 285 |
271 gboolean PanelDragGtk::OnButtonReleaseEvent(GtkWidget* widget, | 286 gboolean PanelDragGtk::OnButtonReleaseEvent(GtkWidget* widget, |
272 GdkEventButton* event) { | 287 GdkEventButton* event) { |
273 DCHECK(drag_delegate_ || drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE); | 288 DCHECK(drag_state_ != NOT_DRAGGING); |
| 289 |
274 if (event->button == 1) { | 290 if (event->button == 1) { |
275 // There will be no drag delegate if drag was canceled/ended using | 291 // Treat release as a mouse click if drag was never started. |
276 // the keyboard before the mouse was released. | 292 if (drag_state_ == DRAG_CAN_START && click_handler_) { |
277 if (drag_delegate_) { | 293 gtk_propagate_event(click_handler_, |
278 // Treat release as a mouse click if drag was never started. | 294 reinterpret_cast<GdkEvent*>(event)); |
279 if (drag_state_ == NOT_DRAGGING && click_handler_) { | |
280 gtk_propagate_event(click_handler_, | |
281 reinterpret_cast<GdkEvent*>(event)); | |
282 } | |
283 // Cleanup state regardless. | |
284 EndDrag(false); | |
285 } | 295 } |
| 296 // Cleanup state regardless. |
| 297 EndDrag(false); |
286 ReleasePointerAndKeyboardGrab(); | 298 ReleasePointerAndKeyboardGrab(); |
287 } | 299 } |
288 | 300 |
289 return TRUE; | 301 return TRUE; |
290 } | 302 } |
291 | 303 |
292 gboolean PanelDragGtk::OnKeyPressEvent(GtkWidget* widget, | 304 gboolean PanelDragGtk::OnKeyPressEvent(GtkWidget* widget, |
293 GdkEventKey* event) { | 305 GdkEventKey* event) { |
294 DCHECK(drag_delegate_ || drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE); | 306 DCHECK(drag_state_ != NOT_DRAGGING); |
295 return TRUE; | 307 return TRUE; |
296 } | 308 } |
297 | 309 |
298 gboolean PanelDragGtk::OnKeyReleaseEvent(GtkWidget* widget, | 310 gboolean PanelDragGtk::OnKeyReleaseEvent(GtkWidget* widget, |
299 GdkEventKey* event) { | 311 GdkEventKey* event) { |
300 DCHECK(drag_delegate_ || drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE); | 312 DCHECK(drag_state_ != NOT_DRAGGING); |
301 if (!drag_delegate_) | 313 |
| 314 if (drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE) { |
| 315 DCHECK(!drag_delegate_); |
302 return TRUE; | 316 return TRUE; |
| 317 } |
| 318 |
| 319 DCHECK(drag_delegate_); |
303 | 320 |
304 switch (event->keyval) { | 321 switch (event->keyval) { |
305 case GDK_Escape: | 322 case GDK_Escape: |
306 EndDrag(true); // Cancel drag. | 323 EndDrag(true); // Cancel drag. |
307 break; | 324 break; |
308 case GDK_Return: | 325 case GDK_Return: |
309 case GDK_KP_Enter: | 326 case GDK_KP_Enter: |
310 case GDK_ISO_Enter: | 327 case GDK_ISO_Enter: |
311 case GDK_space: | 328 case GDK_space: |
312 EndDrag(false); // Normal end. | 329 EndDrag(false); // Normal end. |
313 break; | 330 break; |
314 } | 331 } |
315 return TRUE; | 332 return TRUE; |
316 } | 333 } |
317 | 334 |
318 gboolean PanelDragGtk::OnGrabBrokenEvent(GtkWidget* widget, | 335 gboolean PanelDragGtk::OnGrabBrokenEvent(GtkWidget* widget, |
319 GdkEventGrabBroken* event) { | 336 GdkEventGrabBroken* event) { |
320 DCHECK(drag_delegate_ || drag_state_ == DRAG_ENDED_WAITING_FOR_MOUSE_RELEASE); | 337 DCHECK(drag_state_ != NOT_DRAGGING); |
321 EndDrag(true); // Cancel drag. | 338 EndDrag(true); // Cancel drag. |
322 ReleasePointerAndKeyboardGrab(); | 339 ReleasePointerAndKeyboardGrab(); |
323 return TRUE; | 340 return TRUE; |
324 } | 341 } |
OLD | NEW |