* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
#include <stdlib.h>
#include "gtkhandlebox.h"
+#include "gtkinvisible.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkwindow.h"
+#include "gtkprivate.h"
#include "gtkintl.h"
+#include "gtkalias.h"
+
+typedef struct _GtkHandleBoxPrivate GtkHandleBoxPrivate;
+
+struct _GtkHandleBoxPrivate
+{
+ gint orig_x;
+ gint orig_y;
+};
enum {
PROP_0,
* <--------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_property (GObject *object,
guint param_id,
const GValue *value,
static gint gtk_handle_box_delete_event (GtkWidget *widget,
GdkEventAny *event);
static void gtk_handle_box_reattach (GtkHandleBox *hb);
+static void gtk_handle_box_end_drag (GtkHandleBox *hb,
+ guint32 time);
-
-static GtkBinClass *parent_class;
static guint handle_box_signals[SIGNAL_LAST] = { 0 };
-
-GType
-gtk_handle_box_get_type (void)
-{
- static GType handle_box_type = 0;
-
- if (!handle_box_type)
- {
- static const GTypeInfo handle_box_info =
- {
- sizeof (GtkHandleBoxClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) gtk_handle_box_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GtkHandleBox),
- 0, /* n_preallocs */
- (GInstanceInitFunc) gtk_handle_box_init,
- };
-
- handle_box_type = g_type_register_static (GTK_TYPE_BIN, "GtkHandleBox",
- &handle_box_info, 0);
- }
-
- return handle_box_type;
-}
+G_DEFINE_TYPE (GtkHandleBox, gtk_handle_box, GTK_TYPE_BIN)
static void
gtk_handle_box_class_init (GtkHandleBoxClass *class)
widget_class = (GtkWidgetClass *) class;
container_class = (GtkContainerClass *) class;
- parent_class = g_type_class_peek_parent (class);
-
gobject_class->set_property = gtk_handle_box_set_property;
gobject_class->get_property = gtk_handle_box_get_property;
g_object_class_install_property (gobject_class,
PROP_SHADOW,
g_param_spec_enum ("shadow", NULL,
- _("Deprecated property, use shadow_type instead"),
+ P_("Deprecated property, use shadow_type instead"),
GTK_TYPE_SHADOW_TYPE,
GTK_SHADOW_ETCHED_OUT,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SHADOW_TYPE,
- g_param_spec_enum ("shadow_type",
- _("Shadow type"),
- _("Appearance of the shadow that surrounds the container"),
+ g_param_spec_enum ("shadow-type",
+ P_("Shadow type"),
+ P_("Appearance of the shadow that surrounds the container"),
GTK_TYPE_SHADOW_TYPE,
GTK_SHADOW_ETCHED_OUT,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_HANDLE_POSITION,
- g_param_spec_enum ("handle_position",
- _("Handle position"),
- _("Position of the handle relative to the child widget"),
+ g_param_spec_enum ("handle-position",
+ P_("Handle position"),
+ P_("Position of the handle relative to the child widget"),
GTK_TYPE_POSITION_TYPE,
GTK_POS_LEFT,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SNAP_EDGE,
- g_param_spec_enum ("snap_edge",
- _("Snap edge"),
- _("Side of the handlebox that's lined up with the docking point to dock the handlebox"),
+ g_param_spec_enum ("snap-edge",
+ P_("Snap edge"),
+ P_("Side of the handlebox that's lined up with the docking point to dock the handlebox"),
GTK_TYPE_POSITION_TYPE,
GTK_POS_TOP,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+ GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SNAP_EDGE_SET,
- g_param_spec_boolean ("snap_edge_set",
- _("Snap edge set"),
- _("Whether to use the value from the snap_edge property or a value derived from handle_position"),
+ g_param_spec_boolean ("snap-edge-set",
+ P_("Snap edge set"),
+ P_("Whether to use the value from the snap_edge property or a value derived from handle_position"),
FALSE,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+ GTK_PARAM_READWRITE));
object_class->destroy = gtk_handle_box_destroy;
widget_class->size_allocate = gtk_handle_box_size_allocate;
widget_class->expose_event = gtk_handle_box_expose;
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;
class->child_detached = NULL;
handle_box_signals[SIGNAL_CHILD_ATTACHED] =
- g_signal_new ("child_attached",
+ g_signal_new (I_("child_attached"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkHandleBoxClass, child_attached),
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
handle_box_signals[SIGNAL_CHILD_DETACHED] =
- g_signal_new ("child_detached",
+ g_signal_new (I_("child_detached"),
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkHandleBoxClass, child_detached),
_gtk_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
+
+ g_type_class_add_private (gobject_class, sizeof (GtkHandleBoxPrivate));
+}
+
+static GtkHandleBoxPrivate *
+gtk_handle_box_get_private (GtkHandleBox *hb)
+{
+ return G_TYPE_INSTANCE_GET_PRIVATE (hb, GTK_TYPE_HANDLE_BOX, GtkHandleBoxPrivate);
}
static void
static void
gtk_handle_box_destroy (GtkObject *object)
{
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ if (GTK_OBJECT_CLASS (gtk_handle_box_parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (gtk_handle_box_parent_class)->destroy) (object);
}
static void
gdk_window_destroy (hb->float_window);
hb->float_window = NULL;
- if (GTK_WIDGET_CLASS (parent_class)->unrealize)
- (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+ if (GTK_WIDGET_CLASS (gtk_handle_box_parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (gtk_handle_box_parent_class)->unrealize) (widget);
}
static void
}
/* if our child is not visible, we still request its size, since we
- * won't have any usefull hint for our size otherwise.
+ * won't have any useful hint for our size otherwise.
*/
if (bin->child)
gtk_widget_size_request (bin->child, &child_requisition);
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 = border_width;
if ((GtkShadowType) handle_box->shadow_type != type)
{
handle_box->shadow_type = type;
- g_object_notify (G_OBJECT (handle_box), "shadow_type");
+ g_object_notify (G_OBJECT (handle_box), "shadow-type");
gtk_widget_queue_resize (GTK_WIDGET (handle_box));
}
}
if ((GtkPositionType) handle_box->handle_position != position)
{
handle_box->handle_position = position;
- g_object_notify (G_OBJECT (handle_box), "handle_position");
+ g_object_notify (G_OBJECT (handle_box), "handle-position");
gtk_widget_queue_resize (GTK_WIDGET (handle_box));
}
}
handle_box->snap_edge = edge;
g_object_freeze_notify (G_OBJECT (handle_box));
- g_object_notify (G_OBJECT (handle_box), "snap_edge");
- g_object_notify (G_OBJECT (handle_box), "snap_edge_set");
+ g_object_notify (G_OBJECT (handle_box), "snap-edge");
+ g_object_notify (G_OBJECT (handle_box), "snap-edge-set");
g_object_thaw_notify (G_OBJECT (handle_box));
}
}
{
GtkBin *bin;
GtkHandleBox *hb;
- guint width;
- guint height;
+ guint width, height;
GdkRectangle rect;
GdkRectangle dest;
gint handle_position;
event ? &event->area : area);
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
- (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
+ (* GTK_WIDGET_CLASS (gtk_handle_box_parent_class)->expose_event) (widget, event);
}
static gint
return FALSE;
}
+static GtkWidget *
+gtk_handle_box_get_invisible (void)
+{
+ static GtkWidget *handle_box_invisible = NULL;
+
+ if (!handle_box_invisible)
+ {
+ handle_box_invisible = gtk_invisible_new ();
+ gtk_widget_show (handle_box_invisible);
+ }
+
+ return handle_box_invisible;
+}
+
+static gboolean
+gtk_handle_box_grab_event (GtkWidget *widget,
+ GdkEvent *event,
+ GtkHandleBox *hb)
+{
+ switch (event->type)
+ {
+ case GDK_BUTTON_RELEASE:
+ if (hb->in_drag) /* sanity check */
+ {
+ gtk_handle_box_end_drag (hb, event->button.time);
+ return TRUE;
+ }
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ return gtk_handle_box_motion (GTK_WIDGET (hb), (GdkEventMotion *)event);
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
static gint
gtk_handle_box_button_changed (GtkWidget *widget,
GdkEventButton *event)
{
if (event->type == GDK_BUTTON_PRESS) /* Start a drag */
{
+ GtkHandleBoxPrivate *private = gtk_handle_box_get_private (hb);
+ GtkWidget *invisible = gtk_handle_box_get_invisible ();
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_drawable_get_size (hb->bin_window, &width, &height);
-
+
+ private->orig_x = event->x_root;
+ private->orig_y = event->y_root;
+
hb->float_allocation.x = root_x - event->x_root;
hb->float_allocation.y = root_y - event->y_root;
hb->float_allocation.width = width;
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_drawable_get_size (widget->window, &width, &height);
+ if (gdk_window_is_viewable (widget->window))
+ {
+ gdk_window_get_origin (widget->window, &root_x, &root_y);
+ gdk_drawable_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;
-
+ hb->attach_allocation.x = root_x;
+ hb->attach_allocation.y = root_y;
+ hb->attach_allocation.width = width;
+ hb->attach_allocation.height = height;
+ }
+ else
+ {
+ hb->attach_allocation.x = -1;
+ hb->attach_allocation.y = -1;
+ hb->attach_allocation.width = 0;
+ hb->attach_allocation.height = 0;
+ }
hb->in_drag = TRUE;
fleur = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
GDK_FLEUR);
- if (gdk_pointer_grab (widget->window,
+ if (gdk_pointer_grab (invisible->window,
FALSE,
(GDK_BUTTON1_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_RELEASE_MASK),
NULL,
fleur,
- GDK_CURRENT_TIME) != 0)
+ event->time) != 0)
{
hb->in_drag = FALSE;
}
+ else
+ {
+ gtk_grab_add (invisible);
+ g_signal_connect (invisible, "event",
+ G_CALLBACK (gtk_handle_box_grab_event), hb);
+ }
gdk_cursor_unref (fleur);
event_handled = TRUE;
}
}
}
- else if (event->type == GDK_BUTTON_RELEASE &&
- hb->in_drag)
- {
- if (event->window != widget->window)
- return FALSE;
-
- gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
- GDK_CURRENT_TIME);
- hb->in_drag = FALSE;
- event_handled = TRUE;
- }
return event_handled;
}
gtk_handle_box_motion (GtkWidget *widget,
GdkEventMotion *event)
{
- GtkHandleBox *hb;
+ GtkHandleBox *hb = GTK_HANDLE_BOX (widget);
gint new_x, new_y;
gint snap_edge;
gboolean is_snapped = FALSE;
gint handle_position;
+ GdkGeometry geometry;
+ GdkScreen *screen, *pointer_screen;
- hb = GTK_HANDLE_BOX (widget);
if (!hb->in_drag)
return FALSE;
-
- if (!hb->in_drag || (event->window != widget->window))
- return FALSE;
-
handle_position = effective_handle_position (hb);
/* Calculate the attachment point on the float, if the float
*/
new_x = 0;
new_y = 0;
- gdk_window_get_pointer (gtk_widget_get_root_window (widget),
- &new_x, &new_y, NULL);
+ screen = gtk_widget_get_screen (widget);
+ gdk_display_get_pointer (gdk_screen_get_display (screen),
+ &pointer_screen,
+ &new_x, &new_y, NULL);
+ if (pointer_screen != screen)
+ {
+ GtkHandleBoxPrivate *private = gtk_handle_box_get_private (hb);
+
+ new_x = private->orig_x;
+ new_y = private->orig_y;
+ }
+
new_x += hb->float_allocation.x;
new_y += hb->float_allocation.y;
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_set_geometry_hints (hb->float_window, &geometry, 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
+ /* this extra move is necessary if we use decorations, or our
* window manager insists on decorations.
*/
gdk_display_sync (gtk_widget_get_display (widget));
GtkWidget *widget)
{
gtk_widget_set_parent_window (widget, GTK_HANDLE_BOX (container)->bin_window);
- GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
+ GTK_CONTAINER_CLASS (gtk_handle_box_parent_class)->add (container, widget);
}
static void
gtk_handle_box_remove (GtkContainer *container,
GtkWidget *widget)
{
- GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
+ GTK_CONTAINER_CLASS (gtk_handle_box_parent_class)->remove (container, widget);
gtk_handle_box_reattach (GTK_HANDLE_BOX (container));
}
hb->float_window_mapped = FALSE;
}
if (hb->in_drag)
- {
- gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (hb)),
- GDK_CURRENT_TIME);
- hb->in_drag = FALSE;
- }
+ gtk_handle_box_end_drag (hb, GDK_CURRENT_TIME);
gtk_widget_queue_resize (GTK_WIDGET (hb));
}
+
+static void
+gtk_handle_box_end_drag (GtkHandleBox *hb,
+ guint32 time)
+{
+ GtkWidget *invisible = gtk_handle_box_get_invisible ();
+
+ hb->in_drag = FALSE;
+
+ gtk_grab_remove (invisible);
+ gdk_pointer_ungrab (time);
+ g_signal_handlers_disconnect_by_func (invisible,
+ G_CALLBACK (gtk_handle_box_grab_event),
+ hb);
+}
+
+#define __GTK_HANDLE_BOX_C__
+#include "gtkaliasdef.c"