resize/move grips
- From: Havoc Pennington <hp redhat com>
- To: gtk-devel-list gnome org
- Subject: resize/move grips
- Date: 09 Mar 2001 18:57:56 -0500
Hi,
This is a rough patch to implement part of the WM spec that we forgot
about, _NET_WM_MOVERESIZE. It also has fallback code for noncompliant
window managers.
Summary of changes in the patch:
- code from gtk_window_constrain_size moved to
gdk_window_constrain_size since it's needed in the fallback code
- gdk_window_get_geometry_hints() added as a static function,
should it be exported?
- GdkWindowEdge enum gives the edge or corner of the resize operation
(I realize the corners aren't edges, but don't have a better name)
- gdk_window_begin_resize_drag(), gdk_window_begin_move_drag() start
a resize or move operation
- gtk_window_begin_resize_drag(), gtk_window_begin_move_drag()
mirroring the GdkWindow functions
- gross hack in gdk_event_translate to support the fallback mode
- GtkStatusbar has a resize grip by default, can be disabled
with gtk_statusbar_set_has_grip() (maybe should rename
set_has_resize_grip() for clarity, function won't be used often)
- GtkStyle can draw a resize grip.
Some thought given to a GtkResizeGrip widget, rejected this idea on
the grounds that it doesn't work for the statusbar anyhow (doesn't
draw properly with the frame), and it's trivial to add a grip to any
existing widget given gtk_paint_resize_grip() and
gtk_window_begin_resize_drag(). Also, couldn't think of anywhere you'd
want to have a resize grip other than in the statusbar. So maybe we'll
add this widget someday but for now it's not there.
I think the resize grip is a nice usability enhancement, the UI
experts of the world seem universally in favor of it.
Havoc
Index: gdk/gdkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.c,v
retrieving revision 1.109
diff -u -u -r1.109 gdkwindow.c
--- gdk/gdkwindow.c 2001/02/27 20:39:47 1.109
+++ gdk/gdkwindow.c 2001/03/09 23:45:05
@@ -2137,3 +2137,122 @@
debug_updates = setting;
}
+/* Constrain a window size to obey the hints passed in geometry
+ * and flags. The result will be stored in *new_width and *new_height
+ *
+ * This routine is partially borrowed from fvwm.
+ *
+ * Copyright 1993, Robert Nation
+ * You may use this code for any purpose, as long as the original
+ * copyright remains in the source code and all documentation
+ *
+ * which in turn borrows parts of the algorithm from uwm
+ */
+void
+gdk_window_constrain_size (GdkGeometry *geometry,
+ guint flags,
+ gint width,
+ gint height,
+ gint *new_width,
+ gint *new_height)
+{
+ gint min_width = 0;
+ gint min_height = 0;
+ gint base_width = 0;
+ gint base_height = 0;
+ gint xinc = 1;
+ gint yinc = 1;
+ gint max_width = G_MAXINT;
+ gint max_height = G_MAXINT;
+
+#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
+
+ if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
+ {
+ base_width = geometry->base_width;
+ base_height = geometry->base_height;
+ min_width = geometry->min_width;
+ min_height = geometry->min_height;
+ }
+ else if (flags & GDK_HINT_BASE_SIZE)
+ {
+ base_width = geometry->base_width;
+ base_height = geometry->base_height;
+ min_width = geometry->base_width;
+ min_height = geometry->base_height;
+ }
+ else if (flags & GDK_HINT_MIN_SIZE)
+ {
+ base_width = geometry->min_width;
+ base_height = geometry->min_height;
+ min_width = geometry->min_width;
+ min_height = geometry->min_height;
+ }
+
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ max_width = geometry->max_width ;
+ max_height = geometry->max_height;
+ }
+
+ if (flags & GDK_HINT_RESIZE_INC)
+ {
+ xinc = MAX (xinc, geometry->width_inc);
+ yinc = MAX (yinc, geometry->height_inc);
+ }
+
+ /* clamp width and height to min and max values
+ */
+ width = CLAMP (width, min_width, max_width);
+ height = CLAMP (height, min_height, max_height);
+
+ /* shrink to base + N * inc
+ */
+ width = base_width + FLOOR (width - base_width, xinc);
+ height = base_height + FLOOR (height - base_height, yinc);
+
+ /* constrain aspect ratio, according to:
+ *
+ * width
+ * min_aspect <= -------- <= max_aspect
+ * height
+ */
+
+ if (flags & GDK_HINT_ASPECT &&
+ geometry->min_aspect > 0 &&
+ geometry->max_aspect > 0)
+ {
+ gint delta;
+
+ if (geometry->min_aspect * height > width)
+ {
+ delta = FLOOR (height - width * geometry->min_aspect, yinc);
+ if (height - delta >= min_height)
+ height -= delta;
+ else
+ {
+ delta = FLOOR (height * geometry->min_aspect - width, xinc);
+ if (width + delta <= max_width)
+ width += delta;
+ }
+ }
+
+ if (geometry->max_aspect * height < width)
+ {
+ delta = FLOOR (width - height * geometry->max_aspect, xinc);
+ if (width - delta >= min_width)
+ width -= delta;
+ else
+ {
+ delta = FLOOR (width / geometry->max_aspect - height, yinc);
+ if (height + delta <= max_height)
+ height += delta;
+ }
+ }
+ }
+
+#undef FLOOR
+
+ *new_width = width;
+ *new_height = height;
+}
Index: gdk/gdkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.h,v
retrieving revision 1.18
diff -u -u -r1.18 gdkwindow.h
--- gdk/gdkwindow.h 2001/03/05 15:08:36 1.18
+++ gdk/gdkwindow.h 2001/03/09 23:45:05
@@ -150,6 +150,19 @@
GDK_GRAVITY_STATIC
} GdkGravity;
+
+typedef enum
+{
+ GDK_WINDOW_EDGE_NORTH_WEST,
+ GDK_WINDOW_EDGE_NORTH,
+ GDK_WINDOW_EDGE_NORTH_EAST,
+ GDK_WINDOW_EDGE_WEST,
+ GDK_WINDOW_EDGE_EAST,
+ GDK_WINDOW_EDGE_SOUTH_WEST,
+ GDK_WINDOW_EDGE_SOUTH,
+ GDK_WINDOW_EDGE_SOUTH_EAST
+} GdkWindowEdge;
+
struct _GdkWindowAttr
{
gchar *title;
@@ -443,6 +456,18 @@
void gdk_window_register_dnd (GdkWindow *window);
+void gdk_window_begin_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp);
+void gdk_window_begin_move_drag (GdkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp);
+
/* Interface for dirty-region queueing */
void gdk_window_invalidate_rect (GdkWindow *window,
GdkRectangle *rect,
@@ -461,6 +486,13 @@
/* Enable/disable flicker, so you can tell if your code is inefficient. */
void gdk_window_set_debug_updates (gboolean setting);
+
+void gdk_window_constrain_size (GdkGeometry *geometry,
+ guint flags,
+ gint width,
+ gint height,
+ gint *new_width,
+ gint *new_height);
#ifdef __cplusplus
}
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.41
diff -u -u -r1.41 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c 2001/03/03 21:34:18 1.41
+++ gdk/x11/gdkevents-x11.c 2001/03/09 23:45:05
@@ -433,6 +433,14 @@
if (window != NULL)
gdk_window_ref (window);
+ if (window != NULL &&
+ window == _gdk_moveresize_emulation_window)
+ {
+ _gdk_moveresize_handle_event (xevent);
+ gdk_window_unref (window);
+ return FALSE;
+ }
+
if (wmspec_check_window != None &&
xevent->xany.window == wmspec_check_window)
{
Index: gdk/x11/gdkprivate-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkprivate-x11.h,v
retrieving revision 1.10
diff -u -u -r1.10 gdkprivate-x11.h
--- gdk/x11/gdkprivate-x11.h 2001/03/03 21:34:19 1.10
+++ gdk/x11/gdkprivate-x11.h 2001/03/09 23:45:05
@@ -92,6 +92,8 @@
XRectangle **rects,
gint *n_rects);
+void _gdk_moveresize_handle_event (XEvent *event);
+
extern GdkDrawableClass _gdk_x11_drawable_class;
extern gboolean gdk_use_xshm;
extern Atom gdk_wm_delete_window;
@@ -123,5 +125,7 @@
* to checking the next event with XPending().
*/
extern gboolean _gdk_have_xkb_autorepeat;
+
+extern GdkWindow *_gdk_moveresize_emulation_window;
#endif /* __GDK_PRIVATE_X11_H__ */
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.109
diff -u -u -r1.109 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c 2001/03/05 15:08:36 1.109
+++ gdk/x11/gdkwindow-x11.c 2001/03/09 23:45:05
@@ -1344,7 +1344,7 @@
if (geom_mask & GDK_HINT_WIN_GRAVITY)
{
size_hints.flags |= PWinGravity;
- size_hints.width_inc = geometry->win_gravity;
+ size_hints.win_gravity = geometry->win_gravity;
}
/* FIXME: Would it be better to delete this property of
@@ -1355,6 +1355,65 @@
&size_hints);
}
+static void
+gdk_window_get_geometry_hints (GdkWindow *window,
+ GdkGeometry *geometry,
+ GdkWindowHints *geom_mask)
+{
+ XSizeHints size_hints;
+ glong junk_size_mask = 0;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (geometry != NULL);
+ g_return_if_fail (geom_mask != NULL);
+
+ *geom_mask = 0;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ &size_hints,
+ &junk_size_mask))
+ return;
+
+ if (size_hints.flags & PMinSize)
+ {
+ *geom_mask |= GDK_HINT_MIN_SIZE;
+ geometry->min_width = size_hints.min_width;
+ geometry->min_height = size_hints.min_height;
+ }
+
+ if (size_hints.flags & PMaxSize)
+ {
+ *geom_mask |= GDK_HINT_MAX_SIZE;
+ geometry->max_width = MAX (size_hints.max_width, 1);
+ geometry->max_height = MAX (size_hints.max_height, 1);
+ }
+
+ if (size_hints.flags & PResizeInc)
+ {
+ *geom_mask |= GDK_HINT_RESIZE_INC;
+ geometry->width_inc = size_hints.width_inc;
+ geometry->height_inc = size_hints.height_inc;
+ }
+
+ if (size_hints.flags & PAspect)
+ {
+ *geom_mask |= GDK_HINT_ASPECT;
+
+ geometry->min_aspect = (gdouble) size_hints.min_aspect.x / (gdouble) size_hints.min_aspect.y;
+ geometry->max_aspect = (gdouble) size_hints.max_aspect.x / (gdouble) size_hints.max_aspect.y;
+ }
+
+ if (size_hints.flags & PWinGravity)
+ {
+ *geom_mask |= GDK_HINT_WIN_GRAVITY;
+ geometry->win_gravity = size_hints.win_gravity;
+ }
+}
+
static gboolean
utf8_is_latin1 (const gchar *str)
{
@@ -3234,5 +3293,345 @@
}
XUngrabServer (xdisplay);
return root;
+}
+
+static void
+wmspec_moveresize (GdkWindow *window,
+ gint direction,
+ gint root_x,
+ gint root_y)
+{
+ XEvent xev;
+
+ /* Release passive grab */
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.display = gdk_display;
+ xev.xclient.window = GDK_WINDOW_XID (window);
+ xev.xclient.message_type = gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE);
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = root_x;
+ xev.xclient.data.l[1] = root_y;
+ xev.xclient.data.l[2] = direction;
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
+
+ XSendEvent (gdk_display, gdk_root_window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+}
+
+/* From the WM spec */
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
+#define _NET_WM_MOVERESIZE_SIZE_TOP 1
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
+#define _NET_WM_MOVERESIZE_MOVE 8
+
+static void
+wmspec_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ gint direction;
+
+ /* Let the compiler turn a switch into a table, instead
+ * of doing the table manually, this way is easier to verify.
+ */
+ switch (edge)
+ {
+ case GDK_WINDOW_EDGE_NORTH_WEST:
+ direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
+ break;
+
+ case GDK_WINDOW_EDGE_NORTH:
+ direction = _NET_WM_MOVERESIZE_SIZE_TOP;
+ break;
+
+ case GDK_WINDOW_EDGE_NORTH_EAST:
+ direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
+ break;
+
+ case GDK_WINDOW_EDGE_WEST:
+ direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
+ break;
+
+ case GDK_WINDOW_EDGE_EAST:
+ direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
+ break;
+
+ case GDK_WINDOW_EDGE_SOUTH_WEST:
+ direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
+ break;
+
+ case GDK_WINDOW_EDGE_SOUTH:
+ direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
+ break;
+
+ case GDK_WINDOW_EDGE_SOUTH_EAST:
+ direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
+ break;
+
+ default:
+ g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
+ edge);
+ return;
+ break;
+ }
+
+ wmspec_moveresize (window, direction, root_x, root_y);
+}
+
+/* This is global for use in gdkevents-x11.c */
+GdkWindow *_gdk_moveresize_emulation_window = NULL;
+
+static GdkWindow *moveresize_window = NULL;
+static gboolean is_resize = FALSE;
+static GdkWindowEdge resize_edge;
+static gint moveresize_button;
+static gint moveresize_x;
+static gint moveresize_y;
+static gint moveresize_orig_x;
+static gint moveresize_orig_y;
+static gint moveresize_orig_width;
+static gint moveresize_orig_height;
+static GdkWindowHints moveresize_geom_mask = 0;
+static GdkGeometry moveresize_geometry;
+
+static void
+update_pos (gint new_root_x,
+ gint new_root_y)
+{
+ gint dx, dy;
+
+ dx = new_root_x - moveresize_x;
+ dy = new_root_y - moveresize_y;
+
+ if (is_resize)
+ {
+ gint w, h;
+
+ w = moveresize_orig_width;
+ h = moveresize_orig_height;
+
+ switch (resize_edge)
+ {
+ case GDK_WINDOW_EDGE_SOUTH_EAST:
+ w += dx;
+ h += dy;
+ break;
+
+ }
+
+ w = MAX (w, 1);
+ h = MAX (h, 1);
+
+ if (moveresize_geom_mask)
+ {
+ gdk_window_constrain_size (&moveresize_geometry,
+ moveresize_geom_mask,
+ w, h,
+ &w, &h);
+ }
+
+ gdk_window_resize (moveresize_window, w, h);
+ }
+ else
+ {
+ gint x, y;
+
+ x = moveresize_orig_x + dx;
+ y = moveresize_orig_y + dy;
+
+ gdk_window_move (moveresize_window, x, y);
+ }
+}
+
+static void
+finish_drag (void)
+{
+ gdk_window_destroy (_gdk_moveresize_emulation_window);
+ _gdk_moveresize_emulation_window = NULL;
+}
+
+void
+_gdk_moveresize_handle_event (XEvent *event)
+{
+ gint i;
+ guint button_mask = 0;
+
+ i = moveresize_button - 1;
+ button_mask = GDK_BUTTON1_MASK;
+ while (i > 0)
+ {
+ button_mask <<= 1;
+ --i;
+ }
+
+ switch (event->xany.type)
+ {
+ case MotionNotify:
+ update_pos (event->xmotion.x_root,
+ event->xmotion.y_root);
+
+ if ((event->xmotion.state & button_mask) == 0)
+ finish_drag ();
+ else
+ gdk_window_get_pointer (_gdk_moveresize_emulation_window, NULL, NULL, NULL);
+ break;
+
+ case ButtonRelease:
+ update_pos (event->xbutton.x_root,
+ event->xbutton.y_root);
+
+ if (event->xbutton.button == moveresize_button)
+ finish_drag ();
+ break;
+ }
+}
+
+static void
+create_moveresize_window (guint32 timestamp)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GdkGrabStatus status;
+
+ g_assert (_gdk_moveresize_emulation_window == NULL);
+
+ attributes.x = -100;
+ attributes.y = -100;
+ attributes.width = 10;
+ attributes.height = 10;
+ attributes.window_type = GDK_WINDOW_TEMP;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.override_redirect = TRUE;
+ attributes.event_mask = GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+ _gdk_moveresize_emulation_window =
+ gdk_window_new (NULL, &attributes, attributes_mask);
+
+ gdk_window_show (_gdk_moveresize_emulation_window);
+
+ /* Note the race; the button release can occur on the window
+ * the user originally clicked on before we do this grab.
+ * To minimize the problem in that case, we check the state
+ * on all motion events in _gdk_moveresize_handle_event()
+ * above.
+ */
+ status = gdk_pointer_grab (_gdk_moveresize_emulation_window,
+ TRUE,
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK,
+ FALSE,
+ NULL,
+ timestamp);
+
+ if (status != GDK_GRAB_SUCCESS)
+ {
+ g_warning ("You can't call gdk_window_begin_resize_drag() or gdk_window_begin_move_drag() while the pointer is grabbed, grab failed with status %d", status);
+ gdk_window_destroy (_gdk_moveresize_emulation_window);
+ _gdk_moveresize_emulation_window = NULL;
+ }
+}
+
+static void
+emulate_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ is_resize = TRUE;
+ moveresize_button = button;
+ resize_edge = edge;
+ moveresize_x = root_x;
+ moveresize_y = root_y;
+ moveresize_window = GDK_WINDOW (g_object_ref (G_OBJECT (window)));
+
+ gdk_window_get_size (window, &moveresize_orig_width, &moveresize_orig_height);
+
+ moveresize_geom_mask = 0;
+ gdk_window_get_geometry_hints (window,
+ &moveresize_geometry,
+ &moveresize_geom_mask);
+
+ create_moveresize_window (timestamp);
+}
+
+static void
+emulate_move_drag (GdkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ is_resize = FALSE;
+ moveresize_button = button;
+ moveresize_x = root_x;
+ moveresize_y = root_y;
+ moveresize_window = GDK_WINDOW (g_object_ref (G_OBJECT (window)));
+
+ gdk_window_get_deskrelative_origin (moveresize_window,
+ &moveresize_orig_x,
+ &moveresize_orig_y);
+
+ create_moveresize_window (timestamp);
+}
+
+void
+gdk_window_begin_resize_drag (GdkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (_gdk_moveresize_emulation_window == NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (gdk_net_wm_supports (gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+ wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
+ else
+ emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
+}
+
+void
+gdk_window_begin_move_drag (GdkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (_gdk_moveresize_emulation_window == NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (gdk_net_wm_supports (gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+ wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
+ root_x, root_y);
+ else
+ emulate_move_drag (window, button, root_x, root_y, timestamp);
}
Index: gtk/gtkstatusbar.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstatusbar.c,v
retrieving revision 1.26
diff -u -u -r1.26 gtkstatusbar.c
--- gtk/gtkstatusbar.c 2001/02/03 01:09:40 1.26
+++ gtk/gtkstatusbar.c 2001/03/09 23:45:05
@@ -29,6 +29,7 @@
#include "gtklabel.h"
#include "gtksignal.h"
#include "gtkstatusbar.h"
+#include "gtkwindow.h"
typedef struct _GtkStatusbarMsg GtkStatusbarMsg;
@@ -52,7 +53,20 @@
static void gtk_statusbar_update (GtkStatusbar *statusbar,
guint context_id,
const gchar *text);
-
+static void gtk_statusbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_statusbar_realize (GtkWidget *widget);
+static void gtk_statusbar_unrealize (GtkWidget *widget);
+static void gtk_statusbar_map (GtkWidget *widget);
+static void gtk_statusbar_unmap (GtkWidget *widget);
+static gint gtk_statusbar_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_statusbar_expose_event (GtkWidget *widget,
+ GdkEventExpose *event);
+
+static void gtk_statusbar_create_window (GtkStatusbar *statusbar);
+static void gtk_statusbar_destroy_window (GtkStatusbar *statusbar);
+
static GtkContainerClass *parent_class;
static guint statusbar_signals[SIGNAL_LAST] = { 0 };
@@ -96,6 +110,16 @@
object_class->destroy = gtk_statusbar_destroy;
+ widget_class->size_allocate = gtk_statusbar_size_allocate;
+
+ widget_class->realize = gtk_statusbar_realize;
+ widget_class->unrealize = gtk_statusbar_unrealize;
+ widget_class->map = gtk_statusbar_map;
+ widget_class->unmap = gtk_statusbar_unmap;
+
+ widget_class->button_press_event = gtk_statusbar_button_press;
+ widget_class->expose_event = gtk_statusbar_expose_event;
+
class->messages_mem_chunk = g_mem_chunk_new ("GtkStatusBar messages mem chunk",
sizeof (GtkStatusbarMsg),
sizeof (GtkStatusbarMsg) * 64,
@@ -103,7 +127,7 @@
class->text_pushed = gtk_statusbar_update;
class->text_popped = gtk_statusbar_update;
-
+
statusbar_signals[SIGNAL_TEXT_PUSHED] =
gtk_signal_new ("text_pushed",
GTK_RUN_LAST,
@@ -134,6 +158,8 @@
box->spacing = 2;
box->homogeneous = FALSE;
+ statusbar->has_grip = TRUE;
+
statusbar->frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (statusbar->frame), GTK_SHADOW_IN);
gtk_box_pack_start (box, statusbar->frame, TRUE, TRUE, 0);
@@ -312,6 +338,37 @@
}
}
+void
+gtk_statusbar_set_has_grip (GtkStatusbar *statusbar,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_STATUSBAR (statusbar));
+
+ setting = setting != FALSE;
+
+ if (setting != statusbar->has_grip)
+ {
+ statusbar->has_grip = setting;
+ gtk_widget_queue_draw (GTK_WIDGET (statusbar));
+
+ if (GTK_WIDGET_REALIZED (statusbar))
+ {
+ if (statusbar->has_grip && statusbar->grip_window == NULL)
+ gtk_statusbar_create_window (statusbar);
+ else if (!statusbar->has_grip && statusbar->grip_window != NULL)
+ gtk_statusbar_destroy_window (statusbar);
+ }
+ }
+}
+
+gboolean
+gtk_statusbar_get_has_grip (GtkStatusbar *statusbar)
+{
+ g_return_val_if_fail (GTK_IS_STATUSBAR (statusbar), FALSE);
+
+ return statusbar->has_grip;
+}
+
static void
gtk_statusbar_destroy (GtkObject *object)
{
@@ -342,4 +399,207 @@
statusbar->keys = NULL;
GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+get_grip_rect (GtkStatusbar *statusbar,
+ GdkRectangle *rect)
+{
+ GtkWidget *widget;
+ gint w, h;
+
+ widget = GTK_WIDGET (statusbar);
+
+ /* These are in effect the max/default size of the grip. */
+ w = 18;
+ h = 18;
+
+ if (w > (widget->allocation.width))
+ w = widget->allocation.width;
+
+ if (h > (widget->allocation.height - widget->style->ythickness))
+ h = widget->allocation.height - widget->style->ythickness;
+
+ rect->x = widget->allocation.x + widget->allocation.width - w;
+ rect->y = widget->allocation.y + widget->allocation.height - h;
+ rect->width = w;
+ rect->height = h;
+}
+
+static void
+gtk_statusbar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkStatusbar *statusbar;
+ GdkRectangle rect;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
+
+ get_grip_rect (statusbar, &rect);
+
+ if (statusbar->grip_window)
+ gdk_window_move_resize (statusbar->grip_window,
+ rect.x, rect.y,
+ rect.width, rect.height);
+}
+
+static void
+gtk_statusbar_create_window (GtkStatusbar *statusbar)
+{
+ GtkWidget *widget;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GdkRectangle rect;
+
+ g_return_if_fail (GTK_WIDGET_REALIZED (statusbar));
+ g_return_if_fail (statusbar->has_grip);
+
+ widget = GTK_WIDGET (statusbar);
+
+ get_grip_rect (statusbar, &rect);
+
+ attributes.x = rect.x;
+ attributes.y = rect.y;
+ attributes.width = rect.width;
+ attributes.height = rect.height;
+ attributes.window_type = GDK_WINDOW_TEMP;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.override_redirect = TRUE;
+ attributes.event_mask = gtk_widget_get_events (widget) |
+ GDK_BUTTON_PRESS_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+ statusbar->grip_window = gdk_window_new (widget->window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (statusbar->grip_window, widget);
+}
+
+static void
+gtk_statusbar_destroy_window (GtkStatusbar *statusbar)
+{
+ gdk_window_set_user_data (statusbar->grip_window, NULL);
+ gdk_window_destroy (statusbar->grip_window);
+ statusbar->grip_window = NULL;
+}
+
+static void
+gtk_statusbar_realize (GtkWidget *widget)
+{
+ GtkStatusbar *statusbar;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
+ if (statusbar->has_grip)
+ gtk_statusbar_create_window (statusbar);
+}
+
+static void
+gtk_statusbar_unrealize (GtkWidget *widget)
+{
+ GtkStatusbar *statusbar;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ if (statusbar->grip_window)
+ gtk_statusbar_destroy_window (statusbar);
+
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_statusbar_map (GtkWidget *widget)
+{
+ GtkStatusbar *statusbar;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+
+ if (statusbar->grip_window)
+ gdk_window_show (statusbar->grip_window);
+}
+
+static void
+gtk_statusbar_unmap (GtkWidget *widget)
+{
+ GtkStatusbar *statusbar;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ if (statusbar->grip_window)
+ gdk_window_hide (statusbar->grip_window);
+
+ (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
+}
+
+static gint
+gtk_statusbar_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ GtkStatusbar *statusbar;
+ GtkWidget *ancestor;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ if (!statusbar->has_grip)
+ return FALSE;
+
+ ancestor = gtk_widget_get_toplevel (widget);
+
+ if (!GTK_IS_WINDOW (ancestor))
+ return FALSE;
+
+ if (event->button == 1)
+ gtk_window_begin_resize_drag (GTK_WINDOW (ancestor),
+ GDK_WINDOW_EDGE_SOUTH_EAST,
+ event->button,
+ event->x_root, event->y_root,
+ event->time);
+ else if (event->button == 2)
+ gtk_window_begin_move_drag (GTK_WINDOW (ancestor),
+ event->button,
+ event->x_root, event->y_root,
+ event->time);
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+static gint
+gtk_statusbar_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkStatusbar *statusbar;
+ GdkRectangle rect;
+
+ statusbar = GTK_STATUSBAR (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+
+ if (statusbar->has_grip)
+ {
+ get_grip_rect (statusbar, &rect);
+
+ gtk_paint_resize_grip (widget->style,
+ widget->window,
+ GTK_WIDGET_STATE (widget),
+ NULL,
+ widget,
+ "statusbar",
+ GDK_WINDOW_EDGE_SOUTH_EAST,
+ rect.x, rect.y,
+ /* don't draw grip over the frame, though you
+ * can click on the frame.
+ */
+ rect.width - widget->style->xthickness,
+ rect.height - widget->style->ythickness);
+ }
+
+ return FALSE;
}
Index: gtk/gtkstatusbar.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstatusbar.h,v
retrieving revision 1.13
diff -u -u -r1.13 gtkstatusbar.h
--- gtk/gtkstatusbar.h 2001/02/03 01:09:40 1.13
+++ gtk/gtkstatusbar.h 2001/03/09 23:45:05
@@ -58,6 +58,10 @@
guint seq_context_id;
guint seq_message_id;
+
+ GdkWindow *grip_window;
+
+ guint has_grip : 1;
};
struct _GtkStatusbarClass
@@ -91,6 +95,9 @@
void gtk_statusbar_remove (GtkStatusbar *statusbar,
guint context_id,
guint message_id);
+void gtk_statusbar_set_has_grip (GtkStatusbar *statusbar,
+ gboolean setting);
+gboolean gtk_statusbar_get_has_grip (GtkStatusbar *statusbar);
Index: gtk/gtkstyle.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstyle.c,v
retrieving revision 1.53
diff -u -u -r1.53 gtkstyle.c
--- gtk/gtkstyle.c 2001/03/02 17:06:11 1.53
+++ gtk/gtkstyle.c 2001/03/09 23:45:05
@@ -285,7 +285,19 @@
gint x,
gint y,
PangoLayout *layout);
+static void gtk_default_draw_resize_grip (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkRectangle *area,
+ GtkWidget *widget,
+ const gchar *detail,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
static void gtk_style_shade (GdkColor *a, GdkColor *b, gdouble k);
static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b);
static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s);
@@ -452,6 +464,7 @@
klass->draw_handle = gtk_default_draw_handle;
klass->draw_expander = gtk_default_draw_expander;
klass->draw_layout = gtk_default_draw_layout;
+ klass->draw_resize_grip = gtk_default_draw_resize_grip;
}
static void
@@ -1008,6 +1021,26 @@
}
void
+gtk_draw_resize_grip (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (GTK_IS_STYLE (style));
+ g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
+
+ GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
+ NULL, NULL, NULL,
+ edge,
+ x, y, width, height);
+}
+
+
+void
gtk_style_set_background (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type)
@@ -3749,6 +3782,79 @@
}
static void
+gtk_default_draw_resize_grip (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkRectangle *area,
+ GtkWidget *widget,
+ const gchar *detail,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ g_return_if_fail (GTK_IS_STYLE (style));
+ g_return_if_fail (window != NULL);
+
+ if (area)
+ {
+ gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
+ gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
+ }
+
+ /* make it square */
+ if (width != height)
+ width = height = MIN (width, height);
+
+ switch (edge)
+ {
+ case GDK_WINDOW_EDGE_SOUTH_EAST:
+ {
+ gint xi, yi;
+
+ xi = x;
+ yi = y;
+
+ while (xi < (x + width - 3))
+ {
+ gdk_draw_line (window,
+ style->light_gc[state_type],
+ xi, y + height,
+ x + width, yi);
+
+ ++xi;
+ ++yi;
+
+ gdk_draw_line (window,
+ style->dark_gc[state_type],
+ xi, y + height,
+ x + width, yi);
+
+ ++xi;
+ ++yi;
+
+ gdk_draw_line (window,
+ style->dark_gc[state_type],
+ xi, y + height,
+ x + width, yi);
+
+ xi += 3;
+ yi += 3;
+ }
+ }
+ break;
+
+ }
+
+ if (area)
+ {
+ gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
+ gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
+ }
+}
+
+static void
gtk_style_shade (GdkColor *a,
GdkColor *b,
gdouble k)
@@ -4313,4 +4419,25 @@
widget, detail, x, y, layout);
}
+void
+gtk_paint_resize_grip (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkRectangle *area,
+ GtkWidget *widget,
+ const gchar *detail,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+
+{
+ g_return_if_fail (GTK_IS_STYLE (style));
+ g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
+
+ GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
+ area, widget, detail,
+ edge, x, y, width, height);
+}
Index: gtk/gtkstyle.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkstyle.h,v
retrieving revision 1.21
diff -u -u -r1.21 gtkstyle.h
--- gtk/gtkstyle.h 2001/02/03 01:09:40 1.21
+++ gtk/gtkstyle.h 2001/03/09 23:45:05
@@ -383,6 +383,17 @@
gint x,
gint y,
PangoLayout *layout);
+ void (*draw_resize_grip) (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkRectangle *area,
+ GtkWidget *widget,
+ const gchar *detail,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
};
@@ -577,6 +588,15 @@
gint y,
PangoLayout *layout);
+void gtk_draw_resize_grip (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
void gtk_paint_hline (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
@@ -797,6 +817,18 @@
gint x,
gint y,
PangoLayout *layout);
+
+void gtk_paint_resize_grip (GtkStyle *style,
+ GdkWindow *window,
+ GtkStateType state_type,
+ GdkRectangle *area,
+ GtkWidget *widget,
+ const gchar *detail,
+ GdkWindowEdge edge,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
#ifdef __cplusplus
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.190
diff -u -u -r1.190 gtkwidget.c
--- gtk/gtkwidget.c 2001/03/08 06:14:42 1.190
+++ gtk/gtkwidget.c 2001/03/09 23:45:05
@@ -4502,7 +4502,7 @@
gtk_default_direction = dir;
- tmp_list = toplevels = gtk_window_list_toplevels ();
+ tmp_list = toplevels = _gtk_window_reference_toplevels ();
while (tmp_list)
{
gtk_widget_set_default_direction_recurse (tmp_list->data,
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.103
diff -u -u -r1.103 gtkwindow.c
--- gtk/gtkwindow.c 2001/03/08 06:14:43 1.103
+++ gtk/gtkwindow.c 2001/03/09 23:45:05
@@ -777,11 +777,10 @@
/**
* gtk_window_list_toplevels:
*
- * Returns a list of all existing toplevel windows. Each widget
- * in the list has a reference added to it; to free the
- * list, first unref each widget in the list, then free the list.
+ * Returns a list of all existing toplevel windows. The list must
+ * be freed with g_list_free(), but the list contents need not be unreferenced.
*
- * Return value: list of referenced toplevel widgets
+ * Return value: list of all toplevel windows
**/
GList*
gtk_window_list_toplevels (void)
@@ -790,6 +789,18 @@
GSList *slist;
for (slist = toplevel_list; slist; slist = slist->next)
+ list = g_list_prepend (list, slist->data);
+
+ return list;
+}
+
+GList*
+_gtk_window_reference_toplevels (void)
+{
+ GList *list = NULL;
+ GSList *slist;
+
+ for (slist = toplevel_list; slist; slist = slist->next)
list = g_list_prepend (list, gtk_widget_ref (slist->data));
return list;
@@ -2002,7 +2013,7 @@
_gtk_icon_set_invalidate_caches ();
- toplevels = gtk_window_list_toplevels ();
+ toplevels = _gtk_window_reference_toplevels ();
for (list = toplevels; list; list = list->next)
{
@@ -2498,18 +2509,6 @@
}
}
-
-/* Constrain a window size to obey the hints passed in geometry
- * and flags. The result will be stored in *new_width and *new_height
- *
- * This routine is partially borrowed from fvwm.
- *
- * Copyright 1993, Robert Nation
- * You may use this code for any purpose, as long as the original
- * copyright remains in the source code and all documentation
- *
- * which in turn borrows parts of the algorithm from uwm
- */
static void
gtk_window_constrain_size (GtkWindow *window,
GdkGeometry *geometry,
@@ -2519,105 +2518,8 @@
gint *new_width,
gint *new_height)
{
- gint min_width = 0;
- gint min_height = 0;
- gint base_width = 0;
- gint base_height = 0;
- gint xinc = 1;
- gint yinc = 1;
- gint max_width = G_MAXINT;
- gint max_height = G_MAXINT;
-
-#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
-
- if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
- {
- base_width = geometry->base_width;
- base_height = geometry->base_height;
- min_width = geometry->min_width;
- min_height = geometry->min_height;
- }
- else if (flags & GDK_HINT_BASE_SIZE)
- {
- base_width = geometry->base_width;
- base_height = geometry->base_height;
- min_width = geometry->base_width;
- min_height = geometry->base_height;
- }
- else if (flags & GDK_HINT_MIN_SIZE)
- {
- base_width = geometry->min_width;
- base_height = geometry->min_height;
- min_width = geometry->min_width;
- min_height = geometry->min_height;
- }
-
- if (flags & GDK_HINT_MAX_SIZE)
- {
- max_width = geometry->max_width ;
- max_height = geometry->max_height;
- }
-
- if (flags & GDK_HINT_RESIZE_INC)
- {
- xinc = MAX (xinc, geometry->width_inc);
- yinc = MAX (yinc, geometry->height_inc);
- }
-
- /* clamp width and height to min and max values
- */
- width = CLAMP (width, min_width, max_width);
- height = CLAMP (height, min_height, max_height);
-
- /* shrink to base + N * inc
- */
- width = base_width + FLOOR (width - base_width, xinc);
- height = base_height + FLOOR (height - base_height, yinc);
-
- /* constrain aspect ratio, according to:
- *
- * width
- * min_aspect <= -------- <= max_aspect
- * height
- */
-
- if (flags & GDK_HINT_ASPECT &&
- geometry->min_aspect > 0 &&
- geometry->max_aspect > 0)
- {
- gint delta;
-
- if (geometry->min_aspect * height > width)
- {
- delta = FLOOR (height - width * geometry->min_aspect, yinc);
- if (height - delta >= min_height)
- height -= delta;
- else
- {
- delta = FLOOR (height * geometry->min_aspect - width, xinc);
- if (width + delta <= max_width)
- width += delta;
- }
- }
-
- if (geometry->max_aspect * height < width)
- {
- delta = FLOOR (width - height * geometry->max_aspect, xinc);
- if (width - delta >= min_width)
- width -= delta;
- else
- {
- delta = FLOOR (width / geometry->max_aspect - height, yinc);
- if (height + delta <= max_height)
- height += delta;
- }
- }
- }
-
-#undef FLOOR
-
- *new_width = width;
- *new_height = height;
+ gdk_window_constrain_size (geometry, flags, width, height,
+ new_width, new_height);
}
/* Compute the set of geometry hints and flags for a window
@@ -3195,9 +3097,87 @@
if (toplevel != NULL)
gdk_window_unmaximize (toplevel);
}
-
-
-
+/**
+ * gtk_window_begin_resize_drag:
+ * @window: a #GtkWindow
+ * @button: mouse button that initiated the drag
+ * @edge: position of the resize control
+ * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
+ * @root_y: Y position where the user clicked to initiate the drag
+ * @timestamp: timestamp from the click event that initiated the drag
+ *
+ * Starts resizing a window. This function is used if an application
+ * has window resizing controls. When GDK can support it, the resize
+ * will be done using the standard mechanism for the window manager or
+ * windowing system. Otherwise, GDK will try to emulate window
+ * resizing, potentially not all that well, depending on the windowing system.
+ *
+ **/
+void
+gtk_window_begin_resize_drag (GtkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_WIDGET_VISIBLE (window));
+
+ widget = GTK_WIDGET (window);
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ gdk_window_begin_resize_drag (toplevel,
+ edge, button,
+ root_x, root_y,
+ timestamp);
+}
+/**
+ * gtk_window_begin_move_drag:
+ * @button: mouse button that initiated the drag
+ * @root_x: X position where the user clicked to initiate the drag, in root window coordinates
+ * @root_y: Y position where the user clicked to initiate the drag
+ * @timestamp: timestamp from the click event that initiated the drag
+ *
+ * Starts moving a window. This function is used if an application
+ * has window movement grips. When GDK can support it, the window movement
+ * will be done using the standard mechanism for the window manager or
+ * windowing system. Otherwise, GDK will try to emulate window
+ * movement, potentially not all that well, depending on the windowing system.
+ *
+ **/
+void
+gtk_window_begin_move_drag (GtkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_WIDGET_VISIBLE (window));
+
+ widget = GTK_WIDGET (window);
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ gdk_window_begin_move_drag (toplevel,
+ button,
+ root_x, root_y,
+ timestamp);
+}
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.28
diff -u -u -r1.28 gtkwindow.h
--- gtk/gtkwindow.h 2001/03/07 21:10:44 1.28
+++ gtk/gtkwindow.h 2001/03/09 23:45:05
@@ -167,7 +167,7 @@
/* If window is set modal, input will be grabbed when show and released when hide */
void gtk_window_set_modal (GtkWindow *window,
gboolean modal);
-GList* gtk_window_list_toplevels (void);
+GList* gtk_window_list_toplevels (void);
/* Get the "built-in" accel group (convenience thing) */
GtkAccelGroup* gtk_window_get_default_accel_group (GtkWindow *window);
@@ -180,7 +180,19 @@
void gtk_window_maximize (GtkWindow *window);
void gtk_window_unmaximize (GtkWindow *window);
+void gtk_window_begin_resize_drag (GtkWindow *window,
+ GdkWindowEdge edge,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp);
+void gtk_window_begin_move_drag (GtkWindow *window,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp);
+
/* --- internal functions --- */
void gtk_window_set_focus (GtkWindow *window,
GtkWidget *focus);
@@ -198,6 +210,7 @@
gint height,
gint *new_width,
gint *new_height);
+GList* _gtk_window_reference_toplevels (void);
#ifdef __cplusplus
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]