diff options
author | Tim Janik <timj@gtk.org> | 1998-03-21 22:11:26 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 1998-03-21 22:11:26 +0000 |
commit | 995d97b0018ec12aec7d238fa45bb890f90f98a5 (patch) | |
tree | f7baa33cb98c31e092c785779d40a6b410f37a50 /gtk/gtkhandlebox.c | |
parent | a7960ed953ee1832de599efe93130d41d02d890c (diff) | |
download | gtk+-995d97b0018ec12aec7d238fa45bb890f90f98a5.tar.gz |
major overhaul of the code, fixed all known bugs (hopefully ;).
Sat Mar 21 22:54:31 1998 Tim Janik <timj@gtk.org>
* gtk/gtkhandlebox.h:
* gtk/gtkhandlebox.c: major overhaul of the code, fixed all
known bugs (hopefully ;).
Sat Mar 20 15:33:17 1998 Tim Janik <timj@gtk.org>
* gtk/gtkwidget.c (gtk_widget_real_show): queue the resize for the
parent.
Thu Mar 19 02:00:50 1998 Tim Janik <timj@gtk.org>
* gtk/gtkwidget.c (gtk_widget_unrealize): unset flags after emission,
especially GTK_MAPPED, since that might not have been taken care of
by an UNMAP emission.
Diffstat (limited to 'gtk/gtkhandlebox.c')
-rw-r--r-- | gtk/gtkhandlebox.c | 834 |
1 files changed, 541 insertions, 293 deletions
diff --git a/gtk/gtkhandlebox.c b/gtk/gtkhandlebox.c index 4db5ab0de2..04954b0ad0 100644 --- a/gtk/gtkhandlebox.c +++ b/gtk/gtkhandlebox.c @@ -27,9 +27,8 @@ #define DRAG_HANDLE_SIZE 10 -#define BORDER_SIZE 5 +#define CHILDLESS_SIZE 25 #define GHOST_HEIGHT 3 -#define SNAP_TOLERANCE 16 enum { @@ -53,9 +52,11 @@ static void gtk_handle_box_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_handle_box_size_allocate (GtkWidget *widget, GtkAllocation *real_allocation); +static void gtk_handle_box_add (GtkContainer *container, + GtkWidget *widget); static void gtk_handle_box_remove (GtkContainer *container, GtkWidget *widget); -static void gtk_handle_box_draw_ghost (GtkWidget *widget); +static void gtk_handle_box_draw_ghost (GtkHandleBox *hb); static void gtk_handle_box_paint (GtkWidget *widget, GdkEventExpose *event, GdkRectangle *area); @@ -67,9 +68,8 @@ static gint gtk_handle_box_button_changed (GtkWidget *widget, GdkEventButton *event); static gint gtk_handle_box_motion (GtkWidget *widget, GdkEventMotion *event); -static gint gtk_handle_box_delete_float (GtkWidget *widget, - GdkEvent *event, - gpointer data); +static gint gtk_handle_box_delete_event (GtkWidget *widget, + GdkEventAny *event); static GtkBinClass *parent_class; @@ -157,7 +157,9 @@ gtk_handle_box_class_init (GtkHandleBoxClass *class) widget_class->button_press_event = gtk_handle_box_button_changed; widget_class->button_release_event = gtk_handle_box_button_changed; widget_class->motion_notify_event = gtk_handle_box_motion; + widget_class->delete_event = gtk_handle_box_delete_event; + container_class->add = gtk_handle_box_add; container_class->remove = gtk_handle_box_remove; class->child_attached = NULL; @@ -170,16 +172,15 @@ gtk_handle_box_init (GtkHandleBox *handle_box) GTK_WIDGET_UNSET_FLAGS (handle_box, GTK_NO_WINDOW); GTK_WIDGET_SET_FLAGS (handle_box, GTK_BASIC); /* FIXME: are we really a basic widget? */ - handle_box->steady_window = NULL; + handle_box->bin_window = NULL; handle_box->float_window = NULL; - handle_box->is_being_dragged = FALSE; - handle_box->is_onroot = FALSE; - handle_box->overlap_attaches = FALSE; + handle_box->handle_position = GTK_POS_LEFT; + handle_box->float_window_mapped = FALSE; + handle_box->child_detached = FALSE; + handle_box->in_drag = FALSE; handle_box->fleur_cursor = gdk_cursor_new (GDK_FLEUR); handle_box->dragoff_x = 0; handle_box->dragoff_y = 0; - handle_box->steady_x = 0; - handle_box->steady_x = 0; } GtkWidget* @@ -198,9 +199,6 @@ gtk_handle_box_destroy (GtkObject *object) hb = GTK_HANDLE_BOX (object); - gdk_cursor_destroy (hb->fleur_cursor); - hb->fleur_cursor = NULL; - if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } @@ -219,12 +217,18 @@ gtk_handle_box_map (GtkWidget *widget) bin = GTK_BIN (widget); hb = GTK_HANDLE_BOX (widget); - gdk_window_show (hb->steady_window); + gdk_window_show (hb->bin_window); gdk_window_show (widget->window); - if (bin->child - && GTK_WIDGET_VISIBLE (bin->child) - && !GTK_WIDGET_MAPPED (bin->child)) + if (hb->child_detached && !hb->float_window_mapped) + { + gdk_window_show (hb->float_window); + hb->float_window_mapped = TRUE; + } + + if (bin->child && + GTK_WIDGET_VISIBLE (bin->child) && + !GTK_WIDGET_MAPPED (bin->child)) gtk_widget_map (bin->child); } @@ -241,7 +245,11 @@ gtk_handle_box_unmap (GtkWidget *widget) hb = GTK_HANDLE_BOX (widget); gdk_window_hide (widget->window); - gdk_window_hide (hb->steady_window); + if (hb->float_window_mapped) + { + gdk_window_hide (hb->float_window); + hb->float_window_mapped = FALSE; + } } static void @@ -258,15 +266,6 @@ gtk_handle_box_realize (GtkWidget *widget) GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - hb->float_window = gtk_window_new (GTK_WINDOW_DIALOG); - gtk_window_set_policy (GTK_WINDOW (hb->float_window), FALSE, FALSE, TRUE); - gtk_container_border_width (GTK_CONTAINER (hb->float_window), 0); - gtk_signal_connect (GTK_OBJECT (hb->float_window), "delete_event", - (GtkSignalFunc) gtk_handle_box_delete_float, - hb); - gtk_widget_realize (hb->float_window); - gdk_window_set_decorations (hb->float_window->window, 0); - attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; @@ -277,25 +276,51 @@ gtk_handle_box_realize (GtkWidget *widget) attributes.colormap = gtk_widget_get_colormap (widget); attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK); - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - hb->steady_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); - gdk_window_set_user_data (hb->steady_window, widget); + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); attributes.x = 0; attributes.y = 0; - attributes.event_mask |= (GDK_BUTTON1_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK); - - widget->window = gdk_window_new (hb->steady_window, &attributes, attributes_mask); - gdk_window_set_user_data (widget->window, widget); + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask |= (gtk_widget_get_events (widget) | + GDK_EXPOSURE_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK); + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + hb->bin_window = gdk_window_new (widget->window, &attributes, attributes_mask); + gdk_window_set_user_data (hb->bin_window, widget); + if (GTK_BIN (hb)->child) + gtk_widget_set_parent_window (GTK_BIN (hb)->child, hb->bin_window); + + attributes.x = 0; + attributes.y = 0; + attributes.width = widget->requisition.width; + attributes.height = widget->requisition.height; + attributes.window_type = GDK_WINDOW_TOPLEVEL; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = (gtk_widget_get_events (widget) | + GDK_KEY_PRESS_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK | + GDK_FOCUS_CHANGE_MASK | + GDK_STRUCTURE_MASK); + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + hb->float_window = gdk_window_new (NULL, &attributes, attributes_mask); + gdk_window_set_user_data (hb->float_window, widget); + gdk_window_set_decorations (hb->float_window, 0); + widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, hb->steady_window, GTK_STATE_NORMAL); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (hb)); + gtk_style_set_background (widget->style, hb->bin_window, GTK_WIDGET_STATE (hb)); + gtk_style_set_background (widget->style, hb->float_window, GTK_WIDGET_STATE (hb)); } static void @@ -308,16 +333,16 @@ gtk_handle_box_unrealize (GtkWidget *widget) hb = GTK_HANDLE_BOX (widget); - if (hb->steady_window) - { - gdk_window_set_user_data (hb->steady_window, NULL); - gdk_window_destroy (hb->steady_window); - hb->steady_window = NULL; - } - - gtk_widget_destroy (hb->float_window); + gdk_window_set_user_data (hb->bin_window, NULL); + gdk_window_destroy (hb->bin_window); + hb->bin_window = NULL; + gdk_window_set_user_data (hb->float_window, NULL); + gdk_window_destroy (hb->float_window); hb->float_window = NULL; + gdk_cursor_destroy (hb->fleur_cursor); + hb->fleur_cursor = NULL; + if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } @@ -336,101 +361,138 @@ gtk_handle_box_size_request (GtkWidget *widget, bin = GTK_BIN (widget); hb = GTK_HANDLE_BOX (widget); - requisition->width = DRAG_HANDLE_SIZE + GTK_CONTAINER (widget)->border_width * 2; - requisition->height = GTK_CONTAINER (widget)->border_width * 2; - - if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + { + requisition->width = DRAG_HANDLE_SIZE; + requisition->height = 0; + } + else { - gtk_widget_size_request (bin->child, &bin->child->requisition); + requisition->width = 0; + requisition->height = DRAG_HANDLE_SIZE; + } + requisition->width += GTK_CONTAINER (widget)->border_width * 2; + requisition->height += GTK_CONTAINER (widget)->border_width * 2; + /* if our child is not visible, we still request its size, since we + * won't have any usefull hint for our size otherwise. + */ + if (bin->child) + gtk_widget_size_request (bin->child, &bin->child->requisition); + + if (hb->child_detached) + { + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + requisition->height += bin->child->requisition.height; + else + requisition->width += bin->child->requisition.width; + } + else if (bin->child) + { requisition->width += bin->child->requisition.width; requisition->height += bin->child->requisition.height; } - - hb->real_requisition = *requisition; - if (hb->is_onroot) - requisition->height = GHOST_HEIGHT; - /* FIXME: Should also set requisition->width to a small value? */ + else + { + requisition->width += CHILDLESS_SIZE; + requisition->height += CHILDLESS_SIZE; + } } static void gtk_handle_box_size_allocate (GtkWidget *widget, - GtkAllocation *real_allocation) + GtkAllocation *allocation) { GtkBin *bin; - GtkAllocation *allocation; GtkHandleBox *hb; - gint border_width; - + g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_HANDLE_BOX (widget)); - g_return_if_fail (real_allocation != NULL); - + g_return_if_fail (allocation != NULL); + bin = GTK_BIN (widget); hb = GTK_HANDLE_BOX (widget); - - allocation = &widget->allocation; - - allocation->x = real_allocation->x; - if (real_allocation->height > widget->requisition.height) - allocation->y = real_allocation->y + (real_allocation->height - widget->requisition.height) / 2; + + widget->allocation.x = allocation->x; + if (allocation->height > widget->requisition.height) + widget->allocation.y = allocation->y + (allocation->height - widget->requisition.height) / 2; else - allocation->y = real_allocation->y; - allocation->height = MIN (real_allocation->height, widget->requisition.height); - allocation->width = real_allocation->width; - /* this will refuse to allocate width greater than neccessary: - * allocation->width = MIN (real_allocation->width, widget->requisition.width); - */ - - border_width = GTK_CONTAINER (widget)->border_width; + widget->allocation.y = allocation->y; + widget->allocation.height = MIN (allocation->height, widget->requisition.height); + widget->allocation.width = MIN (allocation->width, widget->requisition.width); + + if (GTK_WIDGET_REALIZED (hb)) + gdk_window_move_resize (widget->window, + widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); - if (GTK_WIDGET_REALIZED (widget)) - { - if (!hb->is_onroot) - { - gdk_window_move_resize (hb->steady_window, - allocation->x + border_width, - allocation->y + border_width, - allocation->width - border_width * 2, - allocation->height - border_width * 2); - gdk_window_move_resize (widget->window, - 0, - 0, - allocation->width - border_width * 2, - allocation->height - border_width * 2); - } - else - { - gtk_widget_set_usize (hb->float_window, - hb->real_requisition.width, - hb->real_requisition.height); - gdk_window_resize (widget->window, - hb->real_requisition.width, - hb->real_requisition.height); - gdk_window_move_resize (hb->steady_window, - allocation->x + border_width, - allocation->y + border_width, - allocation->width - border_width * 2, - GHOST_HEIGHT); - } - } if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) { + GtkWidget *child; GtkAllocation child_allocation; + guint border_width; + + child = bin->child; + border_width = GTK_CONTAINER (widget)->border_width; - child_allocation.x = DRAG_HANDLE_SIZE; - child_allocation.y = 0; + child_allocation.x = border_width; + child_allocation.y = border_width; + if (hb->handle_position == GTK_POS_LEFT) + child_allocation.x += DRAG_HANDLE_SIZE; + else if (hb->handle_position == GTK_POS_TOP) + child_allocation.y += DRAG_HANDLE_SIZE; - if (hb->is_onroot) + if (hb->child_detached) { - child_allocation.width = hb->real_requisition.width - DRAG_HANDLE_SIZE; - child_allocation.height = hb->real_requisition.height; + guint float_width; + guint float_height; + + child_allocation.width = child->requisition.width; + child_allocation.height = child->requisition.height; + + float_width = child_allocation.width + 2 * border_width; + float_height = child_allocation.height + 2 * border_width; + + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + float_width += DRAG_HANDLE_SIZE; + else + float_height += DRAG_HANDLE_SIZE; + + if (GTK_WIDGET_REALIZED (hb)) + { + gdk_window_resize (hb->float_window, + float_width, + float_height); + gdk_window_move_resize (hb->bin_window, + 0, + 0, + float_width, + float_height); + } } else { - child_allocation.width = allocation->width - DRAG_HANDLE_SIZE - border_width * 2; - child_allocation.height = allocation->height - border_width * 2; + child_allocation.width = widget->allocation.width - 2 * border_width; + child_allocation.height = widget->allocation.height - 2 * border_width; + + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + child_allocation.width -= DRAG_HANDLE_SIZE; + else + child_allocation.height -= DRAG_HANDLE_SIZE; + + if (GTK_WIDGET_REALIZED (hb)) + gdk_window_move_resize (hb->bin_window, + 0, + 0, + widget->allocation.width, + widget->allocation.height); } gtk_widget_size_allocate (bin->child, &child_allocation); @@ -438,42 +500,56 @@ gtk_handle_box_size_allocate (GtkWidget *widget, } static void -gtk_handle_box_remove (GtkContainer *container, - GtkWidget *widget) +gtk_handle_box_draw_ghost (GtkHandleBox *hb) { - GtkHandleBox *hb; + GtkWidget *widget; + guint x; + guint y; + guint width; + guint height; - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_HANDLE_BOX (container)); - g_return_if_fail (widget != NULL); - - hb = GTK_HANDLE_BOX (container); + widget = GTK_WIDGET (hb); - if (widget == GTK_BIN (container)->child && - GTK_WIDGET_REALIZED (hb) && - hb->is_onroot) + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) { - hb->is_onroot = FALSE; - - gdk_pointer_ungrab (GDK_CURRENT_TIME); - - gdk_window_reparent (widget->window, hb->steady_window, 0, 0); - - gtk_widget_hide (hb->float_window); + x = hb->handle_position == GTK_POS_LEFT ? 0 : widget->allocation.width; + y = 0; + width = DRAG_HANDLE_SIZE; + height = widget->allocation.height; } - - GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); -} - -static void -gtk_handle_box_draw_ghost (GtkWidget *widget) -{ - gtk_draw_hline (widget->style, - GTK_HANDLE_BOX (widget)->steady_window, - GTK_WIDGET_STATE (widget), - 0, - widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2, - 0); + else + { + x = 0; + y = hb->handle_position == GTK_POS_TOP ? 0 : widget->allocation.height; + width = widget->allocation.width; + height = DRAG_HANDLE_SIZE; + } + gtk_draw_shadow (widget->style, + widget->window, + GTK_WIDGET_STATE (widget), + GTK_SHADOW_ETCHED_IN, + x, + y, + width, + height); + /* + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + gtk_draw_hline (widget->style, + widget->window, + GTK_WIDGET_STATE (widget), + hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : widget->allocation.width - DRAG_HANDLE_SIZE, + widget->allocation.width - DRAG_HANDLE_SIZE, + widget->allocation.height / 2); + else + gtk_draw_vline (widget->style, + widget->window, + GTK_WIDGET_STATE (widget), + hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : widget->allocation.height - DRAG_HANDLE_SIZE, + widget->allocation.height - DRAG_HANDLE_SIZE, + widget->allocation.width / 2); + */ } static void @@ -483,43 +559,101 @@ gtk_handle_box_paint (GtkWidget *widget, { GtkBin *bin; GtkHandleBox *hb; - GdkRectangle child_area; - GdkEventExpose child_event; - gint x; + guint width; + guint height; + guint border_width; bin = GTK_BIN (widget); hb = GTK_HANDLE_BOX (widget); - if (event != NULL) - area = &event->area; + border_width = GTK_CONTAINER (hb)->border_width; - for (x = 1; x < DRAG_HANDLE_SIZE; x += 3) - gtk_draw_vline (widget->style, - widget->window, - GTK_WIDGET_STATE (widget), - 0, hb->is_onroot ? hb->real_requisition.height : widget->allocation.height, - x); - - if (hb->is_onroot) - gtk_draw_shadow (widget->style, - widget->window, - GTK_WIDGET_STATE (widget), - GTK_SHADOW_OUT, - 0, 0, - hb->real_requisition.width, - hb->real_requisition.height); + if (hb->child_detached) + { + width = bin->child->allocation.width + 2 * border_width; + height = bin->child->allocation.height + 2 * border_width; + } + else if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + { + width = widget->allocation.width - DRAG_HANDLE_SIZE; + height = widget->allocation.height; + } else - gtk_draw_shadow (widget->style, - widget->window, - GTK_WIDGET_STATE (widget), - GTK_SHADOW_OUT, - 0, 0, - widget->allocation.width, - widget->allocation.height); + { + width = widget->allocation.width; + height = widget->allocation.height - DRAG_HANDLE_SIZE; + } - if (bin->child) + gdk_window_clear (hb->bin_window); + gtk_draw_shadow (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + GTK_SHADOW_OUT, + hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : 0, + hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : 0, + width, + height); + + if (hb->handle_position == GTK_POS_LEFT || + hb->handle_position == GTK_POS_RIGHT) + { + guint x; + + for (x = 1; x < DRAG_HANDLE_SIZE; x += 3) + + gtk_draw_vline (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + widget->style->klass->ythickness, + height + DRAG_HANDLE_SIZE - widget->style->klass->ythickness, + hb->handle_position == GTK_POS_LEFT ? x : width + x); + gtk_draw_hline (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : width, + hb->handle_position == GTK_POS_LEFT ? 0 : width + DRAG_HANDLE_SIZE, + 0); + gtk_draw_hline (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : width, + hb->handle_position == GTK_POS_LEFT ? 0 : width + DRAG_HANDLE_SIZE, + height - widget->style->klass->ythickness); + } + else + { + guint y; + + for (y = 1; y < DRAG_HANDLE_SIZE; y += 3) + + gtk_draw_hline (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + widget->style->klass->xthickness, + width + DRAG_HANDLE_SIZE - widget->style->klass->xthickness, + hb->handle_position == GTK_POS_TOP ? y : height + y); + gtk_draw_vline (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : height, + hb->handle_position == GTK_POS_TOP ? 0 : height + DRAG_HANDLE_SIZE, + 0); + gtk_draw_vline (widget->style, + hb->bin_window, + GTK_WIDGET_STATE (widget), + hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : height, + hb->handle_position == GTK_POS_TOP ? 0 : height + DRAG_HANDLE_SIZE, + width - widget->style->klass->xthickness); + } + + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) { - if (event == NULL) /* we were called from draw() */ + GdkRectangle child_area; + GdkEventExpose child_event; + + if (!event) /* we were called from draw() */ { if (gtk_widget_intersect (bin->child, area, &child_area)) gtk_widget_draw (bin->child, &child_area); @@ -528,8 +662,8 @@ gtk_handle_box_paint (GtkWidget *widget, { child_event = *event; - if (GTK_WIDGET_NO_WINDOW (bin->child) - && gtk_widget_intersect (bin->child, &event->area, &child_event.area)) + if (GTK_WIDGET_NO_WINDOW (bin->child) && + gtk_widget_intersect (bin->child, &event->area, &child_event.area)) gtk_widget_event (bin->child, (GdkEvent *) &child_event); } } @@ -539,7 +673,6 @@ static void gtk_handle_box_draw (GtkWidget *widget, GdkRectangle *area) { - GdkRectangle child_area; GtkHandleBox *hb; g_return_if_fail (widget != NULL); @@ -550,20 +683,21 @@ gtk_handle_box_draw (GtkWidget *widget, if (GTK_WIDGET_DRAWABLE (widget)) { - if (hb->is_onroot) + if (hb->child_detached) { /* The area parameter does not make sense in this case, so we * repaint everything. */ - gtk_handle_box_draw_ghost (widget); + gtk_handle_box_draw_ghost (hb); - child_area.x = 0; - child_area.y = 0; - child_area.width = hb->real_requisition.width; - child_area.height = hb->real_requisition.height; + area->x = 0; + area->y = 0; + area->width = 2 * GTK_CONTAINER (hb)->border_width + DRAG_HANDLE_SIZE; + area->height = area->width + GTK_BIN (hb)->child->allocation.height; + area->width += GTK_BIN (hb)->child->allocation.width; - gtk_handle_box_paint (widget, NULL, &child_area); + gtk_handle_box_paint (widget, NULL, area); } else gtk_handle_box_paint (widget, NULL, area); @@ -584,12 +718,15 @@ gtk_handle_box_expose (GtkWidget *widget, { hb = GTK_HANDLE_BOX (widget); - if (event->window == hb->steady_window) - gtk_handle_box_draw_ghost (widget); - else if (event->window == widget->window) + if (event->window == widget->window) + { + if (hb->child_detached) + gtk_handle_box_draw_ghost (hb); + } + else gtk_handle_box_paint (widget, event, NULL); } - + return FALSE; } @@ -598,43 +735,76 @@ gtk_handle_box_button_changed (GtkWidget *widget, GdkEventButton *event) { GtkHandleBox *hb; - + gboolean event_handled; + g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); hb = GTK_HANDLE_BOX (widget); - if (event->button == 1) + event_handled = FALSE; + if (event->button == 1 && + event->type == GDK_BUTTON_PRESS) { - if ((event->type == GDK_BUTTON_PRESS) && (event->x < DRAG_HANDLE_SIZE)) + GtkWidget *child; + gboolean in_handle; + + child = GTK_BIN (hb)->child; + + switch (hb->handle_position) + { + case GTK_POS_LEFT: + in_handle = event->x < DRAG_HANDLE_SIZE; + break; + case GTK_POS_TOP: + in_handle = event->y < DRAG_HANDLE_SIZE; + break; + case GTK_POS_RIGHT: + in_handle = event->x > 2 * GTK_CONTAINER (hb)->border_width + child->allocation.width; + break; + case GTK_POS_BOTTOM: + in_handle = event->y > 2 * GTK_CONTAINER (hb)->border_width + child->allocation.height; + break; + default: + in_handle = FALSE; + break; + } + + if (!child) + { + in_handle = FALSE; + event_handled = TRUE; + } + + if (in_handle) { hb->dragoff_x = event->x; hb->dragoff_y = event->y; - gdk_window_get_origin (hb->steady_window, &hb->steady_x, &hb->steady_y); - - hb->is_being_dragged = TRUE; - - gdk_flush(); gtk_grab_add (widget); - while (gdk_pointer_grab (widget->window, + hb->in_drag = TRUE; + while (gdk_pointer_grab (hb->bin_window, FALSE, - (GDK_BUTTON1_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_RELEASE_MASK), + (GDK_BUTTON1_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_RELEASE_MASK), NULL, hb->fleur_cursor, GDK_CURRENT_TIME) != 0); /* wait for success */ - } - else if ((event->type == GDK_BUTTON_RELEASE) && hb->is_being_dragged) - { - gdk_pointer_ungrab (GDK_CURRENT_TIME); - gtk_grab_remove (widget); - hb->is_being_dragged = FALSE; + event_handled = TRUE; } } - return TRUE; + else if (event->type == GDK_BUTTON_RELEASE && + hb->in_drag) + { + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gtk_grab_remove (widget); + hb->in_drag = FALSE; + event_handled = TRUE; + } + + return event_handled; } static gint @@ -642,125 +812,203 @@ gtk_handle_box_motion (GtkWidget *widget, GdkEventMotion *event) { GtkHandleBox *hb; - gint newx, newy; + gint new_x, new_y; gint ox, oy; + gint snap_x, snap_y; + gboolean in_handle; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); hb = GTK_HANDLE_BOX (widget); - - if (event->is_hint) + if (!hb->in_drag) + return FALSE; + + ox = 0; + oy = 0; + gdk_window_get_origin (hb->float_window, &ox, &oy); + new_x = 0; + new_y = 0; + gdk_window_get_pointer (hb->float_window, &new_x, &new_y, NULL); + new_x += ox; + new_y += oy; + new_x -= hb->dragoff_x; + new_y -= hb->dragoff_y; + snap_x = 0; + snap_y = 0; + gdk_window_get_pointer (widget->window, &snap_x, &snap_y, NULL); + + switch (hb->handle_position) { - gdk_window_get_origin (widget->window, &ox, &oy); - gdk_window_get_pointer (widget->window, &newx, &newy, NULL); - newx += ox; - newy += oy; + case GTK_POS_LEFT: + in_handle = (snap_x >= 0 && snap_x <= DRAG_HANDLE_SIZE && + snap_y >= 0 && snap_y <= widget->allocation.height); + break; + case GTK_POS_TOP: + in_handle = (snap_x >= 0 && snap_x <= widget->allocation.width && + snap_y >= 0 && snap_y <= DRAG_HANDLE_SIZE); + break; + case GTK_POS_RIGHT: + in_handle = (snap_x >= widget->allocation.width - DRAG_HANDLE_SIZE && snap_x <= widget->allocation.width && + snap_y >= 0 && snap_y <= widget->allocation.height); + break; + case GTK_POS_BOTTOM: + in_handle = (snap_x >= 0 && snap_x <= widget->allocation.width && + snap_y >= widget->allocation.height - DRAG_HANDLE_SIZE && snap_y <= widget->allocation.height); + break; + default: + in_handle = FALSE; + break; } - else + + if (in_handle) { - newx = event->x_root; - newy = event->y_root; + if (hb->child_detached) + { + gdk_pointer_ungrab (GDK_CURRENT_TIME); + + hb->child_detached = FALSE; + gdk_window_hide (hb->float_window); + gdk_window_reparent (hb->bin_window, widget->window, 0, 0); + hb->float_window_mapped = FALSE; + gtk_signal_emit (GTK_OBJECT (hb), + handle_box_signals[SIGNAL_CHILD_ATTACHED], + GTK_BIN (hb)->child); + + while (gdk_pointer_grab (hb->bin_window, + FALSE, + (GDK_BUTTON1_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_RELEASE_MASK), + NULL, + hb->fleur_cursor, + GDK_CURRENT_TIME) != 0); /* wait for success */ + + gtk_widget_queue_resize (widget); + } } - - newx -= hb->dragoff_x; - newy -= hb->dragoff_y; - - if (hb->is_being_dragged) + else { - if ((abs (hb->steady_x - newx) < SNAP_TOLERANCE) - && (abs (hb->steady_y - newy) < SNAP_TOLERANCE)) + if (hb->child_detached) { - if (hb->is_onroot) - { - hb->is_onroot = FALSE; - - gdk_pointer_ungrab (GDK_CURRENT_TIME); - - gdk_window_reparent (widget->window, hb->steady_window, 0, 0); - - gtk_widget_hide (hb->float_window); - - gtk_signal_emit (GTK_OBJECT (hb), - handle_box_signals[SIGNAL_CHILD_ATTACHED], - GTK_BIN (hb)->child); - - while (gdk_pointer_grab (widget->window, - FALSE, - (GDK_BUTTON1_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_RELEASE_MASK), - NULL, - hb->fleur_cursor, - GDK_CURRENT_TIME) != 0); /* wait for success */ - - gtk_widget_queue_resize (widget); - } + gdk_window_move (hb->float_window, new_x, new_y); + gdk_window_raise (hb->float_window); } else { - if (hb->is_onroot) - { - gtk_widget_set_uposition (hb->float_window, newx, newy); - gdk_window_raise (hb->float_window->window); - } - else - { - hb->is_onroot = TRUE; + gint width; + gint height; - gdk_pointer_ungrab (GDK_CURRENT_TIME); + gdk_pointer_ungrab (GDK_CURRENT_TIME); - if (!GTK_WIDGET_REALIZED (hb->float_window)) - gtk_widget_realize (hb->float_window); + hb->child_detached = TRUE; + width = 0; + height = 0; + gdk_window_get_size (hb->bin_window, &width, &height); + gdk_window_move_resize (hb->float_window, new_x, new_y, width, height); + gdk_window_reparent (hb->bin_window, hb->float_window, 0, 0); + gdk_window_set_hints (hb->float_window, new_x, new_y, 0, 0, 0, 0, GDK_HINT_POS); + gdk_window_show (hb->float_window); + hb->float_window_mapped = TRUE; +#if 0 + /* this extra move is neccessary if we use decorations, or our + * window manager insists on decorations. + */ + gdk_flush (); + gdk_window_move (hb->float_window, new_x, new_y); + gdk_flush (); +#endif /* 0 */ + gtk_signal_emit (GTK_OBJECT (hb), + handle_box_signals[SIGNAL_CHILD_DETACHED], + GTK_BIN (hb)->child); + gtk_handle_box_draw_ghost (hb); + + while (gdk_pointer_grab (hb->bin_window, + FALSE, + (GDK_BUTTON1_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_RELEASE_MASK), + NULL, + hb->fleur_cursor, + GDK_CURRENT_TIME) != 0); /* wait for success */ + + gtk_widget_queue_resize (widget); + } + } - gtk_widget_set_uposition (hb->float_window, newx, newy); - gdk_window_reparent (widget->window, hb->float_window->window, 0, 0); - gtk_widget_show (hb->float_window); + return TRUE; +} - gtk_signal_emit (GTK_OBJECT (hb), - handle_box_signals[SIGNAL_CHILD_DETACHED], - GTK_BIN (hb)->child); +static void +gtk_handle_box_add (GtkContainer *container, + GtkWidget *widget) +{ + g_return_if_fail (GTK_IS_HANDLE_BOX (container)); + g_return_if_fail (GTK_BIN (container)->child == NULL); + g_return_if_fail (widget->parent == NULL); - while (gdk_pointer_grab (widget->window, - FALSE, - (GDK_BUTTON1_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK - | GDK_BUTTON_RELEASE_MASK), - NULL, - hb->fleur_cursor, - GDK_CURRENT_TIME) != 0); /* wait for success */ + gtk_widget_set_parent_window (widget, GTK_HANDLE_BOX (container)->bin_window); + GTK_CONTAINER_CLASS (parent_class)->add (container, widget); +} - gtk_widget_queue_resize (widget); - } +static void +gtk_handle_box_remove (GtkContainer *container, + GtkWidget *widget) +{ + GtkHandleBox *hb; + + g_return_if_fail (GTK_IS_HANDLE_BOX (container)); + g_return_if_fail (GTK_BIN (container)->child == widget); + + hb = GTK_HANDLE_BOX (container); + + if (hb->child_detached) + { + hb->child_detached = FALSE; + if (GTK_WIDGET_REALIZED (hb)) + { + gdk_window_hide (hb->float_window); + gdk_window_reparent (hb->bin_window, GTK_WIDGET (hb)->window, 0, 0); } + hb->float_window_mapped = FALSE; } - - return TRUE; + if (hb->in_drag) + { + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gtk_grab_remove (GTK_WIDGET (container)); + hb->in_drag = FALSE; + } + + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); } static gint -gtk_handle_box_delete_float (GtkWidget *widget, - GdkEvent *event, - gpointer data) +gtk_handle_box_delete_event (GtkWidget *widget, + GdkEventAny *event) { GtkHandleBox *hb; g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (GTK_IS_HANDLE_BOX (data), FALSE); - - hb = GTK_HANDLE_BOX (data); - - hb->is_onroot = FALSE; - - gdk_window_reparent (GTK_WIDGET (hb)->window, hb->steady_window, 0, 0); - gtk_widget_hide (hb->float_window); + hb = GTK_HANDLE_BOX (widget); + g_return_val_if_fail (event->window == hb->float_window, FALSE); + + hb->child_detached = FALSE; + gdk_window_hide (hb->float_window); + gdk_window_reparent (hb->bin_window, widget->window, 0, 0); + hb->float_window_mapped = FALSE; gtk_signal_emit (GTK_OBJECT (hb), handle_box_signals[SIGNAL_CHILD_ATTACHED], GTK_BIN (hb)->child); + if (hb->in_drag) + { + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gtk_grab_remove (widget); + hb->in_drag = FALSE; + } gtk_widget_queue_resize (GTK_WIDGET (hb)); |