summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>1999-02-15 21:05:51 +0000
committerOwen Taylor <otaylor@src.gnome.org>1999-02-15 21:05:51 +0000
commit0c9af82e9713256d8764c0d72ee4718b44993193 (patch)
tree123061133bd9dcddc987451c182158d755c94013
parent063bad00a2fb7cb4430c35a98ab83c8c1dc80569 (diff)
downloadgdk-pixbuf-0c9af82e9713256d8764c0d72ee4718b44993193.tar.gz
When we find a match, stop searching. (Because we assume pspec != NULL in
Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkbindings.c (gtk_binding_set_add_path): When we find a match, stop searching. (Because we assume pspec != NULL in the search). Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com> * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix up painting of "ghosts". * gtk/gtkhandlebox.c (gtk_handle_box_button_changed): Add double-click reattachment. * gtk/gtkhandlebox.c: Grab on widget->window, not on handlebox->bin_window. This means we don't have to worry about ungrabbing while reparenting. Don't make a GTK+ grab - that wasn't necessary. * gtk/gtkhandlebox.c: Only compute the root -> desk offset once, when starting the drag, instead of continuously. This should solve the *Bad Window* errors that were occurring because of race conditions with the WM. * gtk/gtkhandlebox.c: Completely reworked the the logic of reattachment. We introduce the concept of the "snap edge", which is an edge that needs to be aligned for reattachmed. We set a reasonable default from handlebox->handle_position, but an application might want to change this in some circumstances. * gtk/gtkhandlebox.[ch]: Add settors: gtk_handle_box_set_handle_position (); gtk_handle_box_set_snap_edge ();
-rw-r--r--ChangeLog38
-rw-r--r--ChangeLog.pre-2-038
-rw-r--r--ChangeLog.pre-2-1038
-rw-r--r--ChangeLog.pre-2-238
-rw-r--r--ChangeLog.pre-2-438
-rw-r--r--ChangeLog.pre-2-638
-rw-r--r--ChangeLog.pre-2-838
-rw-r--r--gtk/gtkbindings.c1
-rw-r--r--gtk/gtkhandlebox.c483
-rw-r--r--gtk/gtkhandlebox.h21
-rw-r--r--gtk/gtkwidget.h4
11 files changed, 581 insertions, 194 deletions
diff --git a/ChangeLog b/ChangeLog
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 0087c0eaf..0bfcb59bd 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,41 @@
+Thu Feb 11 18:43:12 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkbindings.c (gtk_binding_set_add_path): When
+ we find a match, stop searching. (Because we
+ assume pspec != NULL in the search).
+
+Wed Feb 10 01:18:22 1999 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_draw_ghost): Fix
+ up painting of "ghosts".
+
+ * gtk/gtkhandlebox.c (gtk_handle_box_button_changed):
+ Add double-click reattachment.
+
+ * gtk/gtkhandlebox.c: Grab on widget->window,
+ not on handlebox->bin_window. This means we don't
+ have to worry about ungrabbing while reparenting.
+
+ Don't make a GTK+ grab - that wasn't necessary.
+
+ * gtk/gtkhandlebox.c: Only compute the root -> desk
+ offset once, when starting the drag, instead
+ of continuously. This should solve the *Bad Window*
+ errors that were occurring because of race conditions
+ with the WM.
+
+ * gtk/gtkhandlebox.c: Completely reworked the
+ the logic of reattachment. We introduce the
+ concept of the "snap edge", which is an edge
+ that needs to be aligned for reattachmed.
+ We set a reasonable default from
+ handlebox->handle_position, but an application
+ might want to change this in some circumstances.
+
+ * gtk/gtkhandlebox.[ch]: Add settors:
+ gtk_handle_box_set_handle_position ();
+ gtk_handle_box_set_snap_edge ();
+
Mon Feb 15 11:13:01 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwindow.c (gtk_window_set_focus):
diff --git a/gtk/gtkbindings.c b/gtk/gtkbindings.c
index 15097f346..431d175b8 100644
--- a/gtk/gtkbindings.c
+++ b/gtk/gtkbindings.c
@@ -762,6 +762,7 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set,
gtk_pattern_spec_free_segs (pspec);
g_free (pspec);
pspec = NULL;
+ break;
}
}
if (pspec)
diff --git a/gtk/gtkhandlebox.c b/gtk/gtkhandlebox.c
index 4df645ab0..bb85e69ad 100644
--- a/gtk/gtkhandlebox.c
+++ b/gtk/gtkhandlebox.c
@@ -34,6 +34,7 @@ enum {
#define DRAG_HANDLE_SIZE 10
#define CHILDLESS_SIZE 25
#define GHOST_HEIGHT 3
+#define TOLERANCE 5
enum
{
@@ -42,6 +43,46 @@ enum
SIGNAL_LAST
};
+/* The algorithm for docking and redocking implemented here
+ * has a couple of nice properties:
+ *
+ * 1) During a single drag, docking always occurs at the
+ * the same cursor position. This means that the users
+ * motions are reversible, and that you won't
+ * undock/dock oscillations.
+ *
+ * 2) Docking generally occurs at user-visible features.
+ * The user, once they figure out to redock, will
+ * have useful information about doing it again in
+ * the future.
+ *
+ * Please try to preserve these properties if you
+ * change the algorithm. (And the current algorithm
+ * is far from ideal). Briefly, the current algorithm
+ * for deciding whether the handlebox is docked or not:
+ *
+ * 1) The decision is done by comparing two rectangles - the
+ * allocation if the widget at the start of the drag,
+ * and the boundary of hb->bin_window at the start of
+ * of the drag offset by the distance that the cursor
+ * has moved.
+ *
+ * 2) These rectangles must have one edge, the "snap_edge"
+ * of the handlebox, aligned within TOLERANCE.
+ *
+ * 3) On the other dimension, the extents of one rectangle
+ * must be contained in the extents of the other,
+ * extended by tolerance. That is, either we can have:
+ *
+ * <-TOLERANCE-|--------bin_window--------------|-TOLERANCE->
+ * <--------float_window-------------------->
+ *
+ * or we can have:
+ *
+ * <-TOLERANCE-|------float_window--------------|-TOLERANCE->
+ * <--------bin_window-------------------->
+ */
+
static void gtk_handle_box_class_init (GtkHandleBoxClass *klass);
static void gtk_handle_box_init (GtkHandleBox *handle_box);
static void gtk_handle_box_set_arg (GtkObject *object,
@@ -79,6 +120,7 @@ static gint gtk_handle_box_motion (GtkWidget *widget,
GdkEventMotion *event);
static gint gtk_handle_box_delete_event (GtkWidget *widget,
GdkEventAny *event);
+static void gtk_handle_box_reattach (GtkHandleBox *hb);
static GtkBinClass *parent_class;
@@ -182,8 +224,7 @@ gtk_handle_box_init (GtkHandleBox *handle_box)
handle_box->child_detached = FALSE;
handle_box->in_drag = FALSE;
handle_box->shrink_on_detach = TRUE;
- handle_box->dragoff_x = 0;
- handle_box->dragoff_y = 0;
+ handle_box->snap_edge = -1;
}
static void
@@ -441,9 +482,15 @@ gtk_handle_box_size_request (GtkWidget *widget,
*/
if (bin->child)
gtk_widget_size_request (bin->child, &child_requisition);
+ else
+ {
+ child_requisition.width = 0;
+ child_requisition.height = 0;
+ }
if (hb->child_detached)
{
+ /* FIXME: This doesn't work currently */
if (!hb->shrink_on_detach)
{
if (hb->handle_position == GTK_POS_LEFT ||
@@ -494,41 +541,15 @@ gtk_handle_box_size_allocate (GtkWidget *widget,
bin = GTK_BIN (widget);
hb = GTK_HANDLE_BOX (widget);
- widget->allocation.x = allocation->x;
-
if (bin->child)
gtk_widget_get_child_requisition (bin->child, &child_requisition);
else
{
child_requisition.width = 0;
child_requisition.height = 0;
- }
-
- if (hb->child_detached)
- {
- guint max_req_height;
- guint max_req_width;
-
- max_req_height = MAX (widget->requisition.height,
- child_requisition.height +
- 2 * widget->style->klass->ythickness);
- max_req_width = MAX (widget->requisition.width,
- child_requisition.width +
- 2 * widget->style->klass->xthickness);
+ }
- if (allocation->height > max_req_height)
- widget->allocation.y = allocation->y +
- (allocation->height - max_req_height) / 2;
- else
- widget->allocation.y = allocation->y;
-
- widget->allocation.height = MIN (allocation->height, max_req_height);
- widget->allocation.width = MIN (allocation->width, max_req_width);
- }
- else
- {
- widget->allocation = *allocation;
- }
+ widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (hb))
gdk_window_move_resize (widget->window,
@@ -620,7 +641,7 @@ gtk_handle_box_draw_ghost (GtkHandleBox *hb)
if (hb->handle_position == GTK_POS_LEFT ||
hb->handle_position == GTK_POS_RIGHT)
{
- x = hb->handle_position == GTK_POS_LEFT ? 0 : widget->allocation.width;
+ x = hb->handle_position == GTK_POS_LEFT ? 0 : widget->allocation.width - DRAG_HANDLE_SIZE;
y = 0;
width = DRAG_HANDLE_SIZE;
height = widget->allocation.height;
@@ -628,7 +649,7 @@ gtk_handle_box_draw_ghost (GtkHandleBox *hb)
else
{
x = 0;
- y = hb->handle_position == GTK_POS_TOP ? 0 : widget->allocation.height;
+ y = hb->handle_position == GTK_POS_TOP ? 0 : widget->allocation.height - DRAG_HANDLE_SIZE;
width = widget->allocation.width;
height = DRAG_HANDLE_SIZE;
}
@@ -647,16 +668,16 @@ gtk_handle_box_draw_ghost (GtkHandleBox *hb)
widget->window,
GTK_WIDGET_STATE (widget),
NULL, widget, "handlebox",
- hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : widget->allocation.width - DRAG_HANDLE_SIZE,
- widget->allocation.width - DRAG_HANDLE_SIZE,
+ hb->handle_position == GTK_POS_LEFT ? DRAG_HANDLE_SIZE : 0,
+ hb->handle_position == GTK_POS_LEFT ? widget->allocation.width : widget->allocation.width - DRAG_HANDLE_SIZE,
widget->allocation.height / 2);
else
gtk_paint_vline (widget->style,
widget->window,
GTK_WIDGET_STATE (widget),
NULL, widget, "handlebox",
- hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : widget->allocation.height - DRAG_HANDLE_SIZE,
- widget->allocation.height - DRAG_HANDLE_SIZE,
+ hb->handle_position == GTK_POS_TOP ? DRAG_HANDLE_SIZE : 0,
+ hb->handle_position == GTK_POS_TOP ? widget->allocation.height : widget->allocation.height - DRAG_HANDLE_SIZE,
widget->allocation.width / 2);
}
@@ -680,15 +701,31 @@ gtk_handle_box_set_shadow_type (GtkHandleBox *handle_box,
if ((GtkShadowType) handle_box->shadow_type != type)
{
handle_box->shadow_type = type;
+ gtk_widget_queue_resize (GTK_WIDGET (handle_box));
+ }
+}
- if (GTK_WIDGET_DRAWABLE (handle_box))
- {
- gtk_widget_queue_clear (GTK_WIDGET (handle_box));
- }
+void
+gtk_handle_box_set_handle_position (GtkHandleBox *handle_box,
+ GtkPositionType position)
+{
+ if ((GtkPositionType) handle_box->handle_position != position)
+ {
+ handle_box->handle_position = position;
gtk_widget_queue_resize (GTK_WIDGET (handle_box));
}
}
+void
+gtk_handle_box_set_snap_edge (GtkHandleBox *handle_box,
+ GtkPositionType edge)
+{
+ g_return_if_fail (handle_box != NULL);
+ g_return_if_fail (GTK_IS_HANDLE_BOX (handle_box));
+
+ handle_box->snap_edge = edge;
+}
+
static void
gtk_handle_box_paint (GtkWidget *widget,
GdkEventExpose *event,
@@ -698,31 +735,13 @@ gtk_handle_box_paint (GtkWidget *widget,
GtkHandleBox *hb;
guint width;
guint height;
- guint border_width;
GdkRectangle rect;
bin = GTK_BIN (widget);
hb = GTK_HANDLE_BOX (widget);
- border_width = GTK_CONTAINER (hb)->border_width;
-
- 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
- {
- width = widget->allocation.width;
- height = widget->allocation.height - DRAG_HANDLE_SIZE;
- }
-
+ gdk_window_get_size (hb->bin_window, &width, &height);
+
if (!event)
gtk_paint_box(widget->style,
hb->bin_window,
@@ -746,10 +765,33 @@ gtk_handle_box_paint (GtkWidget *widget,
width,
height);*/
- rect.x = 0;
- rect.y = 0;
- rect.width = (hb->handle_position == GTK_POS_LEFT) ? DRAG_HANDLE_SIZE : width;
- rect.height = (hb->handle_position == GTK_POS_TOP) ? DRAG_HANDLE_SIZE : height;
+ switch (hb->handle_position)
+ {
+ case GTK_POS_LEFT:
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = DRAG_HANDLE_SIZE;
+ rect.height = height;
+ break;
+ case GTK_POS_RIGHT:
+ rect.x = width - DRAG_HANDLE_SIZE;
+ rect.y = 0;
+ rect.width = DRAG_HANDLE_SIZE;
+ rect.height = height;
+ break;
+ case GTK_POS_TOP:
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = DRAG_HANDLE_SIZE;
+ break;
+ case GTK_POS_BOTTOM:
+ rect.x = 0;
+ rect.y = height - DRAG_HANDLE_SIZE;
+ rect.width = width;
+ rect.height = DRAG_HANDLE_SIZE;
+ break;
+ }
draw_textured_frame (widget, hb->bin_window, &rect, GTK_SHADOW_OUT, event ? &event->area : area);
@@ -849,16 +891,16 @@ gtk_handle_box_button_changed (GtkWidget *widget,
hb = GTK_HANDLE_BOX (widget);
- if (event->window != hb->bin_window)
- return FALSE;
-
event_handled = FALSE;
- if (event->button == 1 &&
- event->type == GDK_BUTTON_PRESS)
+ if ((event->button == 1) &&
+ (event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS))
{
GtkWidget *child;
gboolean in_handle;
+ if (event->window != hb->bin_window)
+ return FALSE;
+
child = GTK_BIN (hb)->child;
switch (hb->handle_position)
@@ -888,29 +930,64 @@ gtk_handle_box_button_changed (GtkWidget *widget,
if (in_handle)
{
- hb->dragoff_x = event->x;
- hb->dragoff_y = event->y;
-
- gtk_grab_add (widget);
- hb->in_drag = TRUE;
- fleur = gdk_cursor_new (GDK_FLEUR);
- while (gdk_pointer_grab (hb->bin_window,
- FALSE,
- (GDK_BUTTON1_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON_RELEASE_MASK),
- NULL,
- fleur,
- GDK_CURRENT_TIME) != 0); /* wait for success */
- gdk_cursor_destroy (fleur);
- event_handled = TRUE;
+ if (event->type == GDK_BUTTON_PRESS) /* Start a drag */
+ {
+ gint desk_x, desk_y;
+ gint root_x, root_y;
+ gint width, height;
+
+ gdk_window_get_deskrelative_origin (hb->bin_window, &desk_x, &desk_y);
+ gdk_window_get_origin (hb->bin_window, &root_x, &root_y);
+ gdk_window_get_size (hb->bin_window, &width, &height);
+
+ hb->float_allocation.x = root_x - event->x_root;
+ hb->float_allocation.y = root_y - event->y_root;
+ hb->float_allocation.width = width;
+ hb->float_allocation.height = height;
+
+ hb->deskoff_x = desk_x - root_x;
+ hb->deskoff_y = desk_y - root_y;
+
+ gdk_window_get_origin (widget->window, &root_x, &root_y);
+ gdk_window_get_size (widget->window, &width, &height);
+
+ hb->attach_allocation.x = root_x;
+ hb->attach_allocation.y = root_y;
+ hb->attach_allocation.width = width;
+ hb->attach_allocation.height = height;
+
+ g_print ("%d %d\n", width, height);
+
+ hb->in_drag = TRUE;
+ fleur = gdk_cursor_new (GDK_FLEUR);
+ if (gdk_pointer_grab (widget->window,
+ FALSE,
+ (GDK_BUTTON1_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_RELEASE_MASK),
+ NULL,
+ fleur,
+ GDK_CURRENT_TIME) != 0)
+ {
+ hb->in_drag = FALSE;
+ }
+
+ gdk_cursor_destroy (fleur);
+ event_handled = TRUE;
+ }
+ else if (hb->child_detached) /* Double click */
+ {
+ gtk_handle_box_reattach (hb);
+ }
}
}
else if (event->type == GDK_BUTTON_RELEASE &&
hb->in_drag)
{
+ if (event->window != widget->window)
+ return FALSE;
+
gdk_pointer_ungrab (GDK_CURRENT_TIME);
- gtk_grab_remove (widget);
hb->in_drag = FALSE;
event_handled = TRUE;
}
@@ -924,10 +1001,8 @@ gtk_handle_box_motion (GtkWidget *widget,
{
GtkHandleBox *hb;
gint new_x, new_y;
- gint ox, oy;
- gint snap_x, snap_y;
- gboolean in_handle;
- GdkCursor *fleur;
+ gint snap_edge;
+ gboolean is_snapped = FALSE;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_HANDLE_BOX (widget), FALSE);
@@ -937,52 +1012,85 @@ gtk_handle_box_motion (GtkWidget *widget,
if (!hb->in_drag)
return FALSE;
- if (event->window != hb->bin_window)
+ if (!hb->in_drag || (event->window != widget->window))
return FALSE;
-
- ox = 0;
- oy = 0;
- gdk_window_get_deskrelative_origin (hb->float_window, &ox, &oy);
+
+ /* Calculate the attachment point on the float, if the float
+ * were detached
+ */
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_pointer (GDK_ROOT_PARENT(), &new_x, &new_y, NULL);
+ new_x += hb->float_allocation.x;
+ new_y += hb->float_allocation.y;
+
+ snap_edge = hb->snap_edge;
+ if (snap_edge == -1)
+ snap_edge = (hb->handle_position == GTK_POS_LEFT ||
+ hb->handle_position == GTK_POS_RIGHT) ?
+ GTK_POS_TOP : GTK_POS_LEFT;
+
+ /* First, check if the snapped edge is aligned
+ */
+ switch (snap_edge)
{
- 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);
+ is_snapped = abs (hb->attach_allocation.y - new_y) < TOLERANCE;
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);
+ is_snapped = abs (hb->attach_allocation.y + (gint)hb->attach_allocation.height -
+ new_y - (gint)hb->float_allocation.height) < TOLERANCE;
break;
- default:
- in_handle = FALSE;
+ case GTK_POS_LEFT:
+ is_snapped = abs (hb->attach_allocation.x - new_x) < TOLERANCE;
+ break;
+ case GTK_POS_RIGHT:
+ is_snapped = abs (hb->attach_allocation.x + (gint)hb->attach_allocation.width -
+ new_x - (gint)hb->float_allocation.width) < TOLERANCE;
break;
}
- if (in_handle)
+ /* Next, check if coordinates in the other direction are sufficiently
+ * aligned
+ */
+ if (is_snapped)
+ {
+ gint float_pos1 = 0; /* Initialize to suppress warnings */
+ gint float_pos2 = 0;
+ gint attach_pos1 = 0;
+ gint attach_pos2 = 0;
+
+ switch (snap_edge)
+ {
+ case GTK_POS_TOP:
+ case GTK_POS_BOTTOM:
+ attach_pos1 = hb->attach_allocation.x;
+ attach_pos2 = hb->attach_allocation.x + hb->attach_allocation.width;
+ float_pos1 = new_x;
+ float_pos2 = new_x + hb->float_allocation.width;
+ break;
+ case GTK_POS_LEFT:
+ case GTK_POS_RIGHT:
+ attach_pos1 = hb->attach_allocation.y;
+ attach_pos2 = hb->attach_allocation.y + hb->attach_allocation.height;
+ float_pos1 = new_y;
+ float_pos2 = new_y + hb->float_allocation.height;
+ break;
+ }
+
+ g_print ("(%d %d), (%d %d)\n",
+ float_pos1, float_pos2, attach_pos1, attach_pos2);
+
+ is_snapped = ((attach_pos1 - TOLERANCE < float_pos1) &&
+ (attach_pos2 + TOLERANCE > float_pos2)) ||
+ ((float_pos1 - TOLERANCE < attach_pos1) &&
+ (float_pos2 + TOLERANCE > attach_pos2));
+ }
+
+ if (is_snapped)
{
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);
@@ -991,22 +1099,35 @@ gtk_handle_box_motion (GtkWidget *widget,
handle_box_signals[SIGNAL_CHILD_ATTACHED],
GTK_BIN (hb)->child);
- fleur = gdk_cursor_new (GDK_FLEUR);
- while (gdk_pointer_grab (hb->bin_window,
- FALSE,
- (GDK_BUTTON1_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON_RELEASE_MASK),
- NULL,
- fleur,
- GDK_CURRENT_TIME) != 0); /* wait for success */
- gdk_cursor_destroy (fleur);
-
gtk_widget_queue_resize (widget);
}
}
else
{
+ gint width, height;
+
+ gdk_window_get_size (hb->float_window, &width, &height);
+ new_x += hb->deskoff_x;
+ new_y += hb->deskoff_y;
+
+ switch (hb->handle_position)
+ {
+ case GTK_POS_LEFT:
+ new_y += ((gint)hb->float_allocation.height - height) / 2;
+ break;
+ case GTK_POS_RIGHT:
+ new_x += (gint)hb->float_allocation.width - width;
+ new_y += ((gint)hb->float_allocation.height - height) / 2;
+ break;
+ case GTK_POS_TOP:
+ new_x += ((gint)hb->float_allocation.width - width) / 2;
+ break;
+ case GTK_POS_BOTTOM:
+ new_x += ((gint)hb->float_allocation.width - width) / 2;
+ new_y += (gint)hb->float_allocation.height - height;
+ break;
+ }
+
if (hb->child_detached)
{
gdk_window_move (hb->float_window, new_x, new_y);
@@ -1016,13 +1137,20 @@ gtk_handle_box_motion (GtkWidget *widget,
{
gint width;
gint height;
-
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ GtkRequisition child_requisition;
hb->child_detached = TRUE;
- width = 0;
- height = 0;
- gdk_window_get_size (hb->bin_window, &width, &height);
+
+ if (GTK_BIN (hb)->child)
+ gtk_widget_get_child_requisition (GTK_BIN (hb)->child, &child_requisition);
+ else
+ {
+ child_requisition.width = 0;
+ child_requisition.height = 0;
+ }
+
+ width = child_requisition.width + 2 * GTK_CONTAINER (hb)->border_width;
+ height = child_requisition.height + 2 * GTK_CONTAINER (hb)->border_width;
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);
@@ -1041,17 +1169,6 @@ gtk_handle_box_motion (GtkWidget *widget,
GTK_BIN (hb)->child);
gtk_handle_box_draw_ghost (hb);
- fleur = gdk_cursor_new (GDK_FLEUR);
- while (gdk_pointer_grab (hb->bin_window,
- FALSE,
- (GDK_BUTTON1_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON_RELEASE_MASK),
- NULL,
- fleur,
- GDK_CURRENT_TIME) != 0); /* wait for success */
- gdk_cursor_destroy (fleur);
-
gtk_widget_queue_resize (widget);
}
}
@@ -1075,31 +1192,12 @@ 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;
- }
- 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);
+
+ gtk_handle_box_reattach (GTK_HANDLE_BOX (container));
}
static gint
@@ -1113,24 +1211,41 @@ gtk_handle_box_delete_event (GtkWidget *widget,
g_return_val_if_fail (event != NULL, FALSE);
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 (event->window == hb->float_window)
+ {
+ gtk_handle_box_reattach (hb);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_handle_box_reattach (GtkHandleBox *hb)
+{
+ 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);
+
+ if (GTK_BIN (hb)->child)
+ gtk_signal_emit (GTK_OBJECT (hb),
+ handle_box_signals[SIGNAL_CHILD_ATTACHED],
+ GTK_BIN (hb)->child);
+
+ }
+ hb->float_window_mapped = FALSE;
+ }
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));
- return TRUE;
+ gtk_widget_queue_resize (GTK_WIDGET (hb));
}
-
diff --git a/gtk/gtkhandlebox.h b/gtk/gtkhandlebox.h
index 215a7efcb..4a60407e0 100644
--- a/gtk/gtkhandlebox.h
+++ b/gtk/gtkhandlebox.h
@@ -57,14 +57,14 @@ struct _GtkHandleBox
guint in_drag : 1;
guint shrink_on_detach : 1;
+ gint snap_edge : 3; /* -1 == unset */
+
/* Variables used during a drag
*/
- gint dragoff_x, dragoff_y; /* offset from event->root_x/y and
- * attach point on float */
gint deskoff_x, deskoff_y; /* Offset between root relative coordinates
* and deskrelative coordinates */
- gint attach_x, attach_y; /* Root relative-coordinates of attach
- * point on widget->window */
+ GtkAllocation attach_allocation;
+ GtkAllocation float_allocation;
};
struct _GtkHandleBoxClass
@@ -78,10 +78,15 @@ struct _GtkHandleBoxClass
};
-guint gtk_handle_box_get_type (void);
-GtkWidget* gtk_handle_box_new (void);
-void gtk_handle_box_set_shadow_type (GtkHandleBox *handle_box,
- GtkShadowType type);
+guint gtk_handle_box_get_type (void);
+GtkWidget* gtk_handle_box_new (void);
+void gtk_handle_box_set_shadow_type (GtkHandleBox *handle_box,
+ GtkShadowType type);
+void gtk_handle_box_set_handle_position (GtkHandleBox *handle_box,
+ GtkPositionType position);
+void gtk_handle_box_set_snap_edge (GtkHandleBox *handle_box,
+ GtkPositionType edge);
+
#ifdef __cplusplus
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index c54789522..ed04845cf 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -456,8 +456,8 @@ void gtk_widget_size_request (GtkWidget *widget,
GtkRequisition *requisition);
void gtk_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
-void gtk_widget_get_child_requisition (GtkWidget *widget,
- GtkRequisition *requisition);
+void gtk_widget_get_child_requisition (GtkWidget *widget,
+ GtkRequisition *requisition);
void gtk_widget_add_accelerator (GtkWidget *widget,
const gchar *accel_signal,
GtkAccelGroup *accel_group,