summaryrefslogtreecommitdiff
path: root/gtk/gtkhandlebox.c
diff options
context:
space:
mode:
authorTim Janik <timj@gtk.org>1998-03-21 22:11:26 +0000
committerTim Janik <timj@src.gnome.org>1998-03-21 22:11:26 +0000
commit995d97b0018ec12aec7d238fa45bb890f90f98a5 (patch)
treef7baa33cb98c31e092c785779d40a6b410f37a50 /gtk/gtkhandlebox.c
parenta7960ed953ee1832de599efe93130d41d02d890c (diff)
downloadgtk+-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.c834
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));