1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998 Elliot Lee
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "gtkhandlebox.h"
25 #include "gtksignal.h"
26 #include "gtkwindow.h"
29 #define DRAG_HANDLE_SIZE 10
30 #define CHILDLESS_SIZE 25
31 #define GHOST_HEIGHT 3
35 SIGNAL_CHILD_ATTACHED,
36 SIGNAL_CHILD_DETACHED,
40 typedef void (*SignalChildAttached) (GtkObject *object,
44 static void gtk_handle_box_class_init (GtkHandleBoxClass *klass);
45 static void gtk_handle_box_init (GtkHandleBox *handle_box);
46 static void gtk_handle_box_destroy (GtkObject *object);
47 static void gtk_handle_box_map (GtkWidget *widget);
48 static void gtk_handle_box_unmap (GtkWidget *widget);
49 static void gtk_handle_box_realize (GtkWidget *widget);
50 static void gtk_handle_box_unrealize (GtkWidget *widget);
51 static void gtk_handle_box_size_request (GtkWidget *widget,
52 GtkRequisition *requisition);
53 static void gtk_handle_box_size_allocate (GtkWidget *widget,
54 GtkAllocation *real_allocation);
55 static void gtk_handle_box_add (GtkContainer *container,
57 static void gtk_handle_box_remove (GtkContainer *container,
59 static void gtk_handle_box_draw_ghost (GtkHandleBox *hb);
60 static void gtk_handle_box_paint (GtkWidget *widget,
61 GdkEventExpose *event,
63 static void gtk_handle_box_draw (GtkWidget *widget,
65 static gint gtk_handle_box_expose (GtkWidget *widget,
66 GdkEventExpose *event);
67 static gint gtk_handle_box_button_changed (GtkWidget *widget,
68 GdkEventButton *event);
69 static gint gtk_handle_box_motion (GtkWidget *widget,
70 GdkEventMotion *event);
71 static gint gtk_handle_box_delete_event (GtkWidget *widget,
75 static GtkBinClass *parent_class;
76 static guint handle_box_signals[SIGNAL_LAST] = { 0 };
80 gtk_handle_box_get_type (void)
82 static guint handle_box_type = 0;
86 GtkTypeInfo handle_box_info =
89 sizeof (GtkHandleBox),
90 sizeof (GtkHandleBoxClass),
91 (GtkClassInitFunc) gtk_handle_box_class_init,
92 (GtkObjectInitFunc) gtk_handle_box_init,
97 handle_box_type = gtk_type_unique (gtk_bin_get_type (), &handle_box_info);
100 return handle_box_type;
104 gtk_handle_box_marshal_child_attached (GtkObject *object,
109 SignalChildAttached sfunc = (SignalChildAttached) func;
112 (GtkWidget*) GTK_VALUE_OBJECT (args[0]),
117 gtk_handle_box_class_init (GtkHandleBoxClass *class)
119 GtkObjectClass *object_class;
120 GtkWidgetClass *widget_class;
121 GtkContainerClass *container_class;
123 object_class = (GtkObjectClass *) class;
124 widget_class = (GtkWidgetClass *) class;
125 container_class = (GtkContainerClass *) class;
127 parent_class = gtk_type_class (gtk_bin_get_type ());
129 handle_box_signals[SIGNAL_CHILD_ATTACHED] =
130 gtk_signal_new ("child_attached",
133 GTK_SIGNAL_OFFSET (GtkHandleBoxClass, child_attached),
134 gtk_handle_box_marshal_child_attached,
137 handle_box_signals[SIGNAL_CHILD_DETACHED] =
138 gtk_signal_new ("child_detached",
141 GTK_SIGNAL_OFFSET (GtkHandleBoxClass, child_detached),
142 gtk_handle_box_marshal_child_attached,
145 gtk_object_class_add_signals (object_class, handle_box_signals, SIGNAL_LAST);
147 object_class->destroy = gtk_handle_box_destroy;
149 widget_class->map = gtk_handle_box_map;
150 widget_class->unmap = gtk_handle_box_unmap;
151 widget_class->realize = gtk_handle_box_realize;
152 widget_class->unrealize = gtk_handle_box_unrealize;
153 widget_class->size_request = gtk_handle_box_size_request;
154 widget_class->size_allocate = gtk_handle_box_size_allocate;
155 widget_class->draw = gtk_handle_box_draw;
156 widget_class->expose_event = gtk_handle_box_expose;
157 widget_class->button_press_event = gtk_handle_box_button_changed;
158 widget_class->button_release_event = gtk_handle_box_button_changed;
159 widget_class->motion_notify_event = gtk_handle_box_motion;
160 widget_class->delete_event = gtk_handle_box_delete_event;
162 container_class->add = gtk_handle_box_add;
163 container_class->remove = gtk_handle_box_remove;
165 class->child_attached = NULL;
166 class->child_detached = NULL;
170 gtk_handle_box_init (GtkHandleBox *handle_box)
172 GTK_WIDGET_UNSET_FLAGS (handle_box, GTK_NO_WINDOW);
173 GTK_WIDGET_SET_FLAGS (handle_box, GTK_BASIC); /* FIXME: are we really a basic widget? */
175 handle_box->bin_window = NULL;
176 handle_box->float_window = NULL;
177 handle_box->handle_position = GTK_POS_LEFT;
178 handle_box->float_window_mapped = FALSE;
179 handle_box->child_detached = FALSE;
180 handle_box->in_drag = FALSE;
181 handle_box->shrink_on_detach = TRUE;
182 handle_box->fleur_cursor = gdk_cursor_new (GDK_FLEUR);
183 handle_box->dragoff_x = 0;
184 handle_box->dragoff_y = 0;
188 gtk_handle_box_new (void)
190 return GTK_WIDGET (gtk_type_new (gtk_handle_box_get_type ()));
194 gtk_handle_box_destroy (GtkObject *object)
198 g_return_if_fail (object != NULL);
199 g_return_if_fail (GTK_IS_HANDLE_BOX (object));
201 hb = GTK_HANDLE_BOX (object);
203 if (GTK_OBJECT_CLASS (parent_class)->destroy)
204 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
208 gtk_handle_box_map (GtkWidget *widget)
213 g_return_if_fail (widget != NULL);
214 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
216 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
218 bin = GTK_BIN (widget);
219 hb = GTK_HANDLE_BOX (widget);
221 gdk_window_show (hb->bin_window);
222 gdk_window_show (widget->window);
224 if (hb->child_detached && !hb->float_window_mapped)
226 gdk_window_show (hb->float_window);
227 hb->float_window_mapped = TRUE;
231 GTK_WIDGET_VISIBLE (bin->child) &&
232 !GTK_WIDGET_MAPPED (bin->child))
233 gtk_widget_map (bin->child);
237 gtk_handle_box_unmap (GtkWidget *widget)
241 g_return_if_fail (widget != NULL);
242 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
244 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
246 hb = GTK_HANDLE_BOX (widget);
248 gdk_window_hide (widget->window);
249 if (hb->float_window_mapped)
251 gdk_window_hide (hb->float_window);
252 hb->float_window_mapped = FALSE;
257 gtk_handle_box_realize (GtkWidget *widget)
259 GdkWindowAttr attributes;
260 gint attributes_mask;
263 g_return_if_fail (widget != NULL);
264 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
266 hb = GTK_HANDLE_BOX (widget);
268 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
270 attributes.x = widget->allocation.x;
271 attributes.y = widget->allocation.y;
272 attributes.width = widget->allocation.width;
273 attributes.height = widget->allocation.height;
274 attributes.window_type = GDK_WINDOW_CHILD;
275 attributes.wclass = GDK_INPUT_OUTPUT;
276 attributes.visual = gtk_widget_get_visual (widget);
277 attributes.colormap = gtk_widget_get_colormap (widget);
278 attributes.event_mask = (gtk_widget_get_events (widget)
279 | GDK_EXPOSURE_MASK);
280 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
281 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
282 gdk_window_set_user_data (widget->window, widget);
286 attributes.width = widget->allocation.width;
287 attributes.height = widget->allocation.height;
288 attributes.window_type = GDK_WINDOW_CHILD;
289 attributes.event_mask |= (gtk_widget_get_events (widget) |
291 GDK_BUTTON1_MOTION_MASK |
292 GDK_POINTER_MOTION_HINT_MASK |
293 GDK_BUTTON_PRESS_MASK |
294 GDK_BUTTON_RELEASE_MASK);
295 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
296 hb->bin_window = gdk_window_new (widget->window, &attributes, attributes_mask);
297 gdk_window_set_user_data (hb->bin_window, widget);
298 if (GTK_BIN (hb)->child)
299 gtk_widget_set_parent_window (GTK_BIN (hb)->child, hb->bin_window);
303 attributes.width = widget->requisition.width;
304 attributes.height = widget->requisition.height;
305 attributes.window_type = GDK_WINDOW_TOPLEVEL;
306 attributes.wclass = GDK_INPUT_OUTPUT;
307 attributes.visual = gtk_widget_get_visual (widget);
308 attributes.colormap = gtk_widget_get_colormap (widget);
309 attributes.event_mask = (gtk_widget_get_events (widget) |
311 GDK_ENTER_NOTIFY_MASK |
312 GDK_LEAVE_NOTIFY_MASK |
313 GDK_FOCUS_CHANGE_MASK |
315 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
316 hb->float_window = gdk_window_new (NULL, &attributes, attributes_mask);
317 gdk_window_set_user_data (hb->float_window, widget);
318 gdk_window_set_decorations (hb->float_window, 0);
321 widget->style = gtk_style_attach (widget->style, widget->window);
322 gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (hb));
323 gtk_style_set_background (widget->style, hb->bin_window, GTK_WIDGET_STATE (hb));
324 gtk_style_set_background (widget->style, hb->float_window, GTK_WIDGET_STATE (hb));
328 gtk_handle_box_unrealize (GtkWidget *widget)
332 g_return_if_fail (widget != NULL);
333 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
335 hb = GTK_HANDLE_BOX (widget);
337 gdk_window_set_user_data (hb->bin_window, NULL);
338 gdk_window_destroy (hb->bin_window);
339 hb->bin_window = NULL;
340 gdk_window_set_user_data (hb->float_window, NULL);
341 gdk_window_destroy (hb->float_window);
342 hb->float_window = NULL;
344 gdk_cursor_destroy (hb->fleur_cursor);
345 hb->fleur_cursor = NULL;
347 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
348 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
352 gtk_handle_box_size_request (GtkWidget *widget,
353 GtkRequisition *requisition)
358 g_return_if_fail (widget != NULL);
359 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
360 g_return_if_fail (requisition != NULL);
362 bin = GTK_BIN (widget);
363 hb = GTK_HANDLE_BOX (widget);
365 if (hb->handle_position == GTK_POS_LEFT ||
366 hb->handle_position == GTK_POS_RIGHT)
368 requisition->width = DRAG_HANDLE_SIZE;
369 requisition->height = 0;
373 requisition->width = 0;
374 requisition->height = DRAG_HANDLE_SIZE;
377 /* if our child is not visible, we still request its size, since we
378 * won't have any usefull hint for our size otherwise.
381 gtk_widget_size_request (bin->child, &bin->child->requisition);
383 if (hb->child_detached)
385 if (!hb->shrink_on_detach)
387 if (hb->handle_position == GTK_POS_LEFT ||
388 hb->handle_position == GTK_POS_RIGHT)
389 requisition->height += bin->child->requisition.height;
391 requisition->width += bin->child->requisition.width;
395 if (hb->handle_position == GTK_POS_LEFT ||
396 hb->handle_position == GTK_POS_RIGHT)
397 requisition->height += widget->style->klass->ythickness;
399 requisition->width += widget->style->klass->xthickness;
404 requisition->width += GTK_CONTAINER (widget)->border_width * 2;
405 requisition->height += GTK_CONTAINER (widget)->border_width * 2;
409 requisition->width += bin->child->requisition.width;
410 requisition->height += bin->child->requisition.height;
414 requisition->width += CHILDLESS_SIZE;
415 requisition->height += CHILDLESS_SIZE;
418 g_print ("size_request: width=%d height=%d\n", requisition->width, requisition->height);
422 gtk_handle_box_size_allocate (GtkWidget *widget,
423 GtkAllocation *allocation)
428 g_return_if_fail (widget != NULL);
429 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
430 g_return_if_fail (allocation != NULL);
432 bin = GTK_BIN (widget);
433 hb = GTK_HANDLE_BOX (widget);
435 widget->allocation.x = allocation->x;
437 if (hb->child_detached)
439 guint max_req_height;
442 max_req_height = MAX (widget->requisition.height,
443 bin->child->requisition.height +
444 2 * widget->style->klass->ythickness);
445 max_req_width = MAX (widget->requisition.width,
446 bin->child->requisition.width +
447 2 * widget->style->klass->xthickness);
449 if (allocation->height > max_req_height)
450 widget->allocation.y = allocation->y +
451 (allocation->height - max_req_height) / 2;
453 widget->allocation.y = allocation->y;
455 widget->allocation.height = MIN (allocation->height, max_req_height);
456 widget->allocation.width = MIN (allocation->width, max_req_width);
460 widget->allocation = *allocation;
463 if (GTK_WIDGET_REALIZED (hb))
464 gdk_window_move_resize (widget->window,
465 widget->allocation.x,
466 widget->allocation.y,
467 widget->allocation.width,
468 widget->allocation.height);
471 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
474 GtkAllocation child_allocation;
478 border_width = GTK_CONTAINER (widget)->border_width;
480 child_allocation.x = border_width;
481 child_allocation.y = border_width;
482 if (hb->handle_position == GTK_POS_LEFT)
483 child_allocation.x += DRAG_HANDLE_SIZE;
484 else if (hb->handle_position == GTK_POS_TOP)
485 child_allocation.y += DRAG_HANDLE_SIZE;
487 if (hb->child_detached)
492 child_allocation.width = child->requisition.width;
493 child_allocation.height = child->requisition.height;
495 float_width = child_allocation.width + 2 * border_width;
496 float_height = child_allocation.height + 2 * border_width;
498 if (hb->handle_position == GTK_POS_LEFT ||
499 hb->handle_position == GTK_POS_RIGHT)
500 float_width += DRAG_HANDLE_SIZE;
502 float_height += DRAG_HANDLE_SIZE;
504 if (GTK_WIDGET_REALIZED (hb))
506 gdk_window_resize (hb->float_window,
509 gdk_window_move_resize (hb->bin_window,
518 child_allocation.width = widget->allocation.width - 2 * border_width;
519 child_allocation.height = widget->allocation.height - 2 * border_width;
521 if (hb->handle_position == GTK_POS_LEFT ||
522 hb->handle_position == GTK_POS_RIGHT)
523 child_allocation.width -= DRAG_HANDLE_SIZE;
525 child_allocation.height -= DRAG_HANDLE_SIZE;
527 if (GTK_WIDGET_REALIZED (hb))
528 gdk_window_move_resize (hb->bin_window,
531 widget->allocation.width,
532 widget->allocation.height);
535 gtk_widget_size_allocate (bin->child, &child_allocation);
540 gtk_handle_box_draw_ghost (GtkHandleBox *hb)
548 widget = GTK_WIDGET (hb);
550 if (hb->handle_position == GTK_POS_LEFT ||
551 hb->handle_position == GTK_POS_RIGHT)
553 x = hb->handle_position == GTK_POS_LEFT ? 0 : widget->allocation.width;
555 width = DRAG_HANDLE_SIZE;
556 height = widget->allocation.height;
561 y = hb->handle_position == GTK_POS_TOP ? 0 : widget->allocation.height;
562 width = widget->allocation.width;
563 height = DRAG_HANDLE_SIZE;
565 gtk_draw_shadow (widget->style,
567 GTK_WIDGET_STATE (widget),
568 GTK_SHADOW_ETCHED_IN,
574 if (hb->handle_position == GTK_POS_LEFT ||
575 hb->handle_position == GTK_POS_RIGHT)
576 gtk_draw_hline (widget->style,
578 GTK_WIDGET_STATE (widget),
579 hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : widget->allocation.width - DRAG_HANDLE_SIZE,
580 widget->allocation.width - DRAG_HANDLE_SIZE,
581 widget->allocation.height / 2);
583 gtk_draw_vline (widget->style,
585 GTK_WIDGET_STATE (widget),
586 hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : widget->allocation.height - DRAG_HANDLE_SIZE,
587 widget->allocation.height - DRAG_HANDLE_SIZE,
588 widget->allocation.width / 2);
593 gtk_handle_box_paint (GtkWidget *widget,
594 GdkEventExpose *event,
603 bin = GTK_BIN (widget);
604 hb = GTK_HANDLE_BOX (widget);
606 border_width = GTK_CONTAINER (hb)->border_width;
608 if (hb->child_detached)
610 width = bin->child->allocation.width + 2 * border_width;
611 height = bin->child->allocation.height + 2 * border_width;
613 else if (hb->handle_position == GTK_POS_LEFT ||
614 hb->handle_position == GTK_POS_RIGHT)
616 width = widget->allocation.width - DRAG_HANDLE_SIZE;
617 height = widget->allocation.height;
621 width = widget->allocation.width;
622 height = widget->allocation.height - DRAG_HANDLE_SIZE;
625 gdk_window_clear (hb->bin_window);
626 gtk_draw_shadow (widget->style,
628 GTK_WIDGET_STATE (widget),
630 hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : 0,
631 hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : 0,
635 if (hb->handle_position == GTK_POS_LEFT ||
636 hb->handle_position == GTK_POS_RIGHT)
640 for (x = 1; x < DRAG_HANDLE_SIZE; x += 3)
642 gtk_draw_vline (widget->style,
644 GTK_WIDGET_STATE (widget),
645 widget->style->klass->ythickness,
646 height + DRAG_HANDLE_SIZE - widget->style->klass->ythickness,
647 hb->handle_position == GTK_POS_LEFT ? x : width + x);
648 gtk_draw_hline (widget->style,
650 GTK_WIDGET_STATE (widget),
651 hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : width,
652 hb->handle_position == GTK_POS_LEFT ? 0 : width + DRAG_HANDLE_SIZE,
654 gtk_draw_hline (widget->style,
656 GTK_WIDGET_STATE (widget),
657 hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : width,
658 hb->handle_position == GTK_POS_LEFT ? 0 : width + DRAG_HANDLE_SIZE,
659 height - widget->style->klass->ythickness);
665 for (y = 1; y < DRAG_HANDLE_SIZE; y += 3)
667 gtk_draw_hline (widget->style,
669 GTK_WIDGET_STATE (widget),
670 widget->style->klass->xthickness,
671 width + DRAG_HANDLE_SIZE - widget->style->klass->xthickness,
672 hb->handle_position == GTK_POS_TOP ? y : height + y);
673 gtk_draw_vline (widget->style,
675 GTK_WIDGET_STATE (widget),
676 hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : height,
677 hb->handle_position == GTK_POS_TOP ? 0 : height + DRAG_HANDLE_SIZE,
679 gtk_draw_vline (widget->style,
681 GTK_WIDGET_STATE (widget),
682 hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : height,
683 hb->handle_position == GTK_POS_TOP ? 0 : height + DRAG_HANDLE_SIZE,
684 width - widget->style->klass->xthickness);
688 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
690 GdkRectangle child_area;
691 GdkEventExpose child_event;
693 if (!event) /* we were called from draw() */
695 if (gtk_widget_intersect (bin->child, area, &child_area))
696 gtk_widget_draw (bin->child, &child_area);
698 else /* we were called from expose() */
700 child_event = *event;
702 if (GTK_WIDGET_NO_WINDOW (bin->child) &&
703 gtk_widget_intersect (bin->child, &event->area, &child_event.area))
704 gtk_widget_event (bin->child, (GdkEvent *) &child_event);
710 gtk_handle_box_draw (GtkWidget *widget,
715 g_return_if_fail (widget != NULL);
716 g_return_if_fail (GTK_IS_HANDLE_BOX (widget));
717 g_return_if_fail (area != NULL);
719 hb = GTK_HANDLE_BOX (widget);
721 if (GTK_WIDGET_DRAWABLE (widget))
723 if (hb->child_detached)
725 /* The area parameter does not make sense in this case, so we
726 * repaint everything.
729 gtk_handle_box_draw_ghost (hb);
733 area->width = 2 * GTK_CONTAINER (hb)->border_width + DRAG_HANDLE_SIZE;
734 area->height = area->width + GTK_BIN (hb)->child->allocation.height;
735 area->width += GTK_BIN (hb)->child->allocation.width;
737 gtk_handle_box_paint (widget, NULL, area);
740 gtk_handle_box_paint (widget, NULL, area);
745 gtk_handle_box_expose (GtkWidget *widget,
746 GdkEventExpose *event)
750 g_return_val_if_fail (widget != NULL, FALSE);
751 g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE);
752 g_return_val_if_fail (event != NULL, FALSE);
754 if (GTK_WIDGET_DRAWABLE (widget))
756 hb = GTK_HANDLE_BOX (widget);
758 if (event->window == widget->window)
760 if (hb->child_detached)
761 gtk_handle_box_draw_ghost (hb);
764 gtk_handle_box_paint (widget, event, NULL);
771 gtk_handle_box_button_changed (GtkWidget *widget,
772 GdkEventButton *event)
775 gboolean event_handled;
777 g_return_val_if_fail (widget != NULL, FALSE);
778 g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE);
779 g_return_val_if_fail (event != NULL, FALSE);
781 hb = GTK_HANDLE_BOX (widget);
783 event_handled = FALSE;
784 if (event->button == 1 &&
785 event->type == GDK_BUTTON_PRESS)
790 child = GTK_BIN (hb)->child;
792 switch (hb->handle_position)
795 in_handle = event->x < DRAG_HANDLE_SIZE;
798 in_handle = event->y < DRAG_HANDLE_SIZE;
801 in_handle = event->x > 2 * GTK_CONTAINER (hb)->border_width + child->allocation.width;
804 in_handle = event->y > 2 * GTK_CONTAINER (hb)->border_width + child->allocation.height;
814 event_handled = TRUE;
819 hb->dragoff_x = event->x;
820 hb->dragoff_y = event->y;
822 gtk_grab_add (widget);
824 while (gdk_pointer_grab (hb->bin_window,
826 (GDK_BUTTON1_MOTION_MASK |
827 GDK_POINTER_MOTION_HINT_MASK |
828 GDK_BUTTON_RELEASE_MASK),
831 GDK_CURRENT_TIME) != 0); /* wait for success */
832 event_handled = TRUE;
835 else if (event->type == GDK_BUTTON_RELEASE &&
838 gdk_pointer_ungrab (GDK_CURRENT_TIME);
839 gtk_grab_remove (widget);
841 event_handled = TRUE;
844 return event_handled;
848 gtk_handle_box_motion (GtkWidget *widget,
849 GdkEventMotion *event)
857 g_return_val_if_fail (widget != NULL, FALSE);
858 g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE);
859 g_return_val_if_fail (event != NULL, FALSE);
861 hb = GTK_HANDLE_BOX (widget);
867 gdk_window_get_origin (hb->float_window, &ox, &oy);
870 gdk_window_get_pointer (hb->float_window, &new_x, &new_y, NULL);
873 new_x -= hb->dragoff_x;
874 new_y -= hb->dragoff_y;
877 gdk_window_get_pointer (widget->window, &snap_x, &snap_y, NULL);
879 switch (hb->handle_position)
882 in_handle = (snap_x >= 0 && snap_x <= DRAG_HANDLE_SIZE &&
883 snap_y >= 0 && snap_y <= widget->allocation.height);
886 in_handle = (snap_x >= 0 && snap_x <= widget->allocation.width &&
887 snap_y >= 0 && snap_y <= DRAG_HANDLE_SIZE);
890 in_handle = (snap_x >= widget->allocation.width - DRAG_HANDLE_SIZE && snap_x <= widget->allocation.width &&
891 snap_y >= 0 && snap_y <= widget->allocation.height);
894 in_handle = (snap_x >= 0 && snap_x <= widget->allocation.width &&
895 snap_y >= widget->allocation.height - DRAG_HANDLE_SIZE && snap_y <= widget->allocation.height);
904 if (hb->child_detached)
906 gdk_pointer_ungrab (GDK_CURRENT_TIME);
908 hb->child_detached = FALSE;
909 gdk_window_hide (hb->float_window);
910 gdk_window_reparent (hb->bin_window, widget->window, 0, 0);
911 hb->float_window_mapped = FALSE;
912 gtk_signal_emit (GTK_OBJECT (hb),
913 handle_box_signals[SIGNAL_CHILD_ATTACHED],
914 GTK_BIN (hb)->child);
916 while (gdk_pointer_grab (hb->bin_window,
918 (GDK_BUTTON1_MOTION_MASK |
919 GDK_POINTER_MOTION_HINT_MASK |
920 GDK_BUTTON_RELEASE_MASK),
923 GDK_CURRENT_TIME) != 0); /* wait for success */
925 gtk_widget_queue_resize (widget);
930 if (hb->child_detached)
932 gdk_window_move (hb->float_window, new_x, new_y);
933 gdk_window_raise (hb->float_window);
940 gdk_pointer_ungrab (GDK_CURRENT_TIME);
942 hb->child_detached = TRUE;
945 gdk_window_get_size (hb->bin_window, &width, &height);
946 gdk_window_move_resize (hb->float_window, new_x, new_y, width, height);
947 gdk_window_reparent (hb->bin_window, hb->float_window, 0, 0);
948 gdk_window_set_hints (hb->float_window, new_x, new_y, 0, 0, 0, 0, GDK_HINT_POS);
949 gdk_window_show (hb->float_window);
950 hb->float_window_mapped = TRUE;
952 /* this extra move is neccessary if we use decorations, or our
953 * window manager insists on decorations.
956 gdk_window_move (hb->float_window, new_x, new_y);
959 gtk_signal_emit (GTK_OBJECT (hb),
960 handle_box_signals[SIGNAL_CHILD_DETACHED],
961 GTK_BIN (hb)->child);
962 gtk_handle_box_draw_ghost (hb);
964 while (gdk_pointer_grab (hb->bin_window,
966 (GDK_BUTTON1_MOTION_MASK |
967 GDK_POINTER_MOTION_HINT_MASK |
968 GDK_BUTTON_RELEASE_MASK),
971 GDK_CURRENT_TIME) != 0); /* wait for success */
973 gtk_widget_queue_resize (widget);
981 gtk_handle_box_add (GtkContainer *container,
984 g_return_if_fail (GTK_IS_HANDLE_BOX (container));
985 g_return_if_fail (GTK_BIN (container)->child == NULL);
986 g_return_if_fail (widget->parent == NULL);
988 gtk_widget_set_parent_window (widget, GTK_HANDLE_BOX (container)->bin_window);
989 GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
993 gtk_handle_box_remove (GtkContainer *container,
998 g_return_if_fail (GTK_IS_HANDLE_BOX (container));
999 g_return_if_fail (GTK_BIN (container)->child == widget);
1001 hb = GTK_HANDLE_BOX (container);
1003 if (hb->child_detached)
1005 hb->child_detached = FALSE;
1006 if (GTK_WIDGET_REALIZED (hb))
1008 gdk_window_hide (hb->float_window);
1009 gdk_window_reparent (hb->bin_window, GTK_WIDGET (hb)->window, 0, 0);
1011 hb->float_window_mapped = FALSE;
1015 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1016 gtk_grab_remove (GTK_WIDGET (container));
1017 hb->in_drag = FALSE;
1020 GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
1024 gtk_handle_box_delete_event (GtkWidget *widget,
1029 g_return_val_if_fail (widget != NULL, FALSE);
1030 g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE);
1031 g_return_val_if_fail (event != NULL, FALSE);
1033 hb = GTK_HANDLE_BOX (widget);
1034 g_return_val_if_fail (event->window == hb->float_window, FALSE);
1036 hb->child_detached = FALSE;
1037 gdk_window_hide (hb->float_window);
1038 gdk_window_reparent (hb->bin_window, widget->window, 0, 0);
1039 hb->float_window_mapped = FALSE;
1040 gtk_signal_emit (GTK_OBJECT (hb),
1041 handle_box_signals[SIGNAL_CHILD_ATTACHED],
1042 GTK_BIN (hb)->child);
1045 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1046 gtk_grab_remove (widget);
1047 hb->in_drag = FALSE;
1050 gtk_widget_queue_resize (GTK_WIDGET (hb));