Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: chrome/browser/ui/panels/panel_drag_gtk.cc

Issue 10266021: GTK Panels - fix crash when clicking on titlebar to restore a panel. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add extra drag state to make code clearer Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/panels/panel_drag_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/panels/panel_drag_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698