* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
- * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
#include "win32/gdkwin32.h"
#elif defined (GDK_WINDOWING_NANOX)
#include "nanox/gdkprivate-nanox.h"
+#elif defined (GDK_WINDOWING_FB)
+#include "linux-fb/gdkfb.h"
#endif
#include "gtkprivate.h"
#include "gtkrc.h"
#include "gtksignal.h"
#include "gtkwindow.h"
+#include "gtkwindow-decorate.h"
#include "gtkbindings.h"
#include "gtkmain.h"
-
-/* TODO: remove this define and assorted code in 1.3 and fix up the
- * real culprits.
- */
-#define FIXME_ZVT_ME_HARDER
+#include "gtkiconfactory.h"
+#include "gtkintl.h"
enum {
SET_FOCUS,
+ FRAME_EVENT,
+ ACTIVATE_FOCUS,
+ ACTIVATE_DEFAULT,
+ MOVE_FOCUS,
LAST_SIGNAL
};
+
enum {
- ARG_0,
- ARG_TYPE,
- ARG_TITLE,
- ARG_AUTO_SHRINK,
- ARG_ALLOW_SHRINK,
- ARG_ALLOW_GROW,
- ARG_MODAL,
- ARG_WIN_POS,
- ARG_DEFAULT_WIDTH,
- ARG_DEFAULT_HEIGHT
+ PROP_0,
+
+ /* Construct */
+ PROP_TYPE,
+
+ /* Style Props */
+ PROP_TITLE,
+ PROP_AUTO_SHRINK,
+ PROP_ALLOW_SHRINK,
+ PROP_ALLOW_GROW,
+ PROP_MODAL,
+ PROP_WIN_POS,
+ PROP_DEFAULT_WIDTH,
+ PROP_DEFAULT_HEIGHT,
+ PROP_DESTROY_WITH_PARENT,
+
+ LAST_ARG
};
typedef struct {
gint height;
} GtkWindowLastGeometryInfo;
-typedef struct {
+struct _GtkWindowGeometryInfo
+{
/* Properties that the app has set on the window
*/
GdkGeometry geometry; /* Geometry hints */
GtkWidget *widget; /* subwidget to which hints apply */
gint width; /* Default size */
gint height;
+ guint may_shrink : 1; /* one-shot auto_shrink behaviour after set_default_size */
GtkWindowLastGeometryInfo last;
-} GtkWindowGeometryInfo;
+};
+
+typedef struct {
+ GtkWindow *window;
+ guint keyval;
+
+ GSList *targets;
+} GtkWindowMnemonic;
+
static void gtk_window_class_init (GtkWindowClass *klass);
static void gtk_window_init (GtkWindow *window);
-static void gtk_window_set_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id);
-static void gtk_window_get_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id);
static void gtk_window_shutdown (GObject *object);
static void gtk_window_destroy (GtkObject *object);
static void gtk_window_finalize (GObject *object);
static void gtk_window_map (GtkWidget *widget);
static void gtk_window_unmap (GtkWidget *widget);
static void gtk_window_realize (GtkWidget *widget);
+static void gtk_window_unrealize (GtkWidget *widget);
static void gtk_window_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_window_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
+static gint gtk_window_event (GtkWidget *widget,
+ GdkEvent *event);
+static gboolean gtk_window_frame_event (GtkWidget *widget,
+ GdkEvent *event);
static gint gtk_window_configure_event (GtkWidget *widget,
GdkEventConfigure *event);
static gint gtk_window_key_press_event (GtkWidget *widget,
static gint gtk_window_client_event (GtkWidget *widget,
GdkEventClient *event);
static void gtk_window_check_resize (GtkContainer *container);
+static gint gtk_window_focus (GtkContainer *container,
+ GtkDirectionType direction);
static void gtk_window_real_set_focus (GtkWindow *window,
GtkWidget *focus);
+static void gtk_window_real_activate_default (GtkWindow *window);
+static void gtk_window_real_activate_focus (GtkWindow *window);
+static void gtk_window_move_focus (GtkWindow *window,
+ GtkDirectionType dir);
+
static void gtk_window_move_resize (GtkWindow *window);
static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
guint flags_a,
static void gtk_window_compute_hints (GtkWindow *window,
GdkGeometry *new_geometry,
guint *new_flags);
-static void gtk_window_compute_reposition (GtkWindow *window,
+static gint gtk_window_compute_reposition (GtkWindow *window,
gint new_width,
gint new_height,
gint *x,
static void gtk_window_read_rcfiles (GtkWidget *widget,
GdkEventClient *event);
-static void gtk_window_draw (GtkWidget *widget,
- GdkRectangle *area);
static void gtk_window_paint (GtkWidget *widget,
GdkRectangle *area);
static gint gtk_window_expose (GtkWidget *widget,
static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
gboolean create);
-static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info);
+
static GSList *toplevel_list = NULL;
+static GHashTable *mnemonic_hash_table = NULL;
static GtkBinClass *parent_class = NULL;
static guint window_signals[LAST_SIGNAL] = { 0 };
+static void gtk_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+
+static guint
+mnemonic_hash (gconstpointer key)
+{
+ const GtkWindowMnemonic *k;
+ guint h;
+
+ k = (GtkWindowMnemonic *)key;
+
+ h = (gulong) k->window;
+ h ^= k->keyval << 16;
+ h ^= k->keyval >> 16;
+
+ return h;
+}
+
+static gboolean
+mnemonic_equal (gconstpointer a, gconstpointer b)
+{
+ const GtkWindowMnemonic *ka;
+ const GtkWindowMnemonic *kb;
+
+ ka = (GtkWindowMnemonic *)a;
+ kb = (GtkWindowMnemonic *)b;
+
+ return
+ (ka->window == kb->window) &&
+ (ka->keyval == kb->keyval);
+}
GtkType
gtk_window_get_type (void)
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
-
+ GtkBindingSet *binding_set;
+
object_class = (GtkObjectClass*) klass;
widget_class = (GtkWidgetClass*) klass;
container_class = (GtkContainerClass*) klass;
-
+
parent_class = gtk_type_class (gtk_bin_get_type ());
gobject_class->shutdown = gtk_window_shutdown;
gobject_class->finalize = gtk_window_finalize;
- gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, GTK_ARG_READWRITE, ARG_TYPE);
- gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_TITLE);
- gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_SHRINK);
- gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_SHRINK);
- gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ALLOW_GROW);
- gtk_object_add_arg_type ("GtkWindow::modal", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_MODAL);
- gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_WINDOW_POSITION, GTK_ARG_READWRITE, ARG_WIN_POS);
- gtk_object_add_arg_type ("GtkWindow::default_width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_WIDTH);
- gtk_object_add_arg_type ("GtkWindow::default_height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_DEFAULT_HEIGHT);
+ gobject_class->set_property = gtk_window_set_property;
+ gobject_class->get_property = gtk_window_get_property;
- window_signals[SET_FOCUS] =
- gtk_signal_new ("set_focus",
- GTK_RUN_LAST,
- GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
- gtk_marshal_NONE__POINTER,
- GTK_TYPE_NONE, 1,
- GTK_TYPE_WIDGET);
-
- gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
-
- object_class->set_arg = gtk_window_set_arg;
- object_class->get_arg = gtk_window_get_arg;
object_class->destroy = gtk_window_destroy;
widget_class->show = gtk_window_show;
widget_class->map = gtk_window_map;
widget_class->unmap = gtk_window_unmap;
widget_class->realize = gtk_window_realize;
+ widget_class->unrealize = gtk_window_unrealize;
widget_class->size_request = gtk_window_size_request;
widget_class->size_allocate = gtk_window_size_allocate;
widget_class->configure_event = gtk_window_configure_event;
widget_class->focus_in_event = gtk_window_focus_in_event;
widget_class->focus_out_event = gtk_window_focus_out_event;
widget_class->client_event = gtk_window_client_event;
-
- widget_class->draw = gtk_window_draw;
+
widget_class->expose_event = gtk_window_expose;
container_class->check_resize = gtk_window_check_resize;
+ container_class->focus = gtk_window_focus;
klass->set_focus = gtk_window_real_set_focus;
+ klass->frame_event = gtk_window_frame_event;
+
+ klass->activate_default = gtk_window_real_activate_default;
+ klass->activate_focus = gtk_window_real_activate_focus;
+ klass->move_focus = gtk_window_move_focus;
+
+ /* Construct */
+ g_object_class_install_property (gobject_class,
+ PROP_TYPE,
+ g_param_spec_enum ("type",
+ _("Window Type"),
+ _("The type of the window"),
+ GTK_TYPE_WINDOW_TYPE,
+ GTK_WINDOW_TOPLEVEL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /* Style Props */
+ g_object_class_install_property (gobject_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ _("Window Title"),
+ _("The title of the window"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_AUTO_SHRINK,
+ g_param_spec_boolean ("auto_shrink",
+ _("Auto Shrink"),
+ _("If TRUE, the window automatically shrinks to its size request anytime a resize occurs. Don't use this feature, it makes no sense."),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ALLOW_SHRINK,
+ g_param_spec_boolean ("allow_shrink",
+ _("Allow Shrink"),
+ _("If TRUE, the window has no mimimum size. Don't use this feature, it makes no sense."),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ALLOW_GROW,
+ g_param_spec_boolean ("allow_grow",
+ _("Allow Grow"),
+ _("If TRUE, users can expand the window beyond its minimum size."),
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MODAL,
+ g_param_spec_boolean ("modal",
+ _("Modal"),
+ _("If TRUE, the window is modal (other windows are not usable while this one is up)."),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_WIN_POS,
+ g_param_spec_enum ("window_position",
+ _("Window Position"),
+ _("The initial position of the window."),
+ GTK_TYPE_WINDOW_POSITION,
+ GTK_WIN_POS_NONE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEFAULT_WIDTH,
+ g_param_spec_int ("default_width",
+ _("Default Width"),
+ _("The default width of the window, or 0 to use the size request."),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DEFAULT_HEIGHT,
+ g_param_spec_int ("default_height",
+ _("Default Height"),
+ _("The default height of the windo, or 0 to use the size request."),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_DESTROY_WITH_PARENT,
+ g_param_spec_boolean ("destroy_with_parent",
+ _("Destroy with Parent"),
+ _("If this window should be destroyed when the parent is destroyed,"),
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /* Style props are set or not */
+
+ window_signals[SET_FOCUS] =
+ g_signal_newc ("set_focus",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkWindowClass, set_focus),
+ NULL, NULL,
+ gtk_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+
+ window_signals[FRAME_EVENT] =
+ g_signal_newc ("frame_event",
+ G_TYPE_FROM_CLASS(object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkWindowClass, frame_event),
+ _gtk_boolean_handled_accumulator, NULL,
+ gtk_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1,
+ GDK_TYPE_EVENT);
+
+ window_signals[ACTIVATE_FOCUS] =
+ g_signal_newc ("activate_focus",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
+ NULL, NULL,
+ gtk_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ window_signals[ACTIVATE_DEFAULT] =
+ g_signal_newc ("activate_default",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
+ NULL, NULL,
+ gtk_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ window_signals[MOVE_FOCUS] =
+ g_signal_newc ("move_focus",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
+ NULL, NULL,
+ gtk_marshal_VOID__ENUM,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_DIRECTION_TYPE);
+
+ if (!mnemonic_hash_table)
+ mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
+ mnemonic_equal);
+
+ /*
+ * Key bindings
+ */
+
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
+ "activate_focus", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
+ "activate_default", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
+ "activate_default", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_UP);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_DOWN);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_LEFT);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_RIGHT);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Tab, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, 0,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK,
+ "move_focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
}
static void
GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
+ GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED);
+
gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
window->title = NULL;
window->wmclass_name = g_strdup (g_get_prgname ());
window->wmclass_class = g_strdup (gdk_progclass);
+ window->wm_role = NULL;
+ window->geometry_info = NULL;
window->type = GTK_WINDOW_TOPLEVEL;
window->focus_widget = NULL;
window->default_widget = NULL;
window->position = GTK_WIN_POS_NONE;
window->use_uposition = TRUE;
window->modal = FALSE;
-
+ window->frame = NULL;
+ window->has_frame = FALSE;
+ window->frame_left = 0;
+ window->frame_right = 0;
+ window->frame_top = 0;
+ window->frame_bottom = 0;
+ window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
+ window->gravity = GDK_GRAVITY_NORTH_WEST;
+ window->decorated = TRUE;
+ window->mnemonic_modifier = GDK_MOD1_MASK;
+
gtk_widget_ref (GTK_WIDGET (window));
gtk_object_sink (GTK_OBJECT (window));
window->has_user_ref_count = TRUE;
toplevel_list = g_slist_prepend (toplevel_list, window);
+
+ gtk_decorated_window_init (window);
+
+ gtk_signal_connect (GTK_OBJECT (window),
+ "event",
+ GTK_SIGNAL_FUNC (gtk_window_event),
+ NULL);
}
static void
-gtk_window_set_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id)
+gtk_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GtkWindow *window;
window = GTK_WINDOW (object);
- switch (arg_id)
+ switch (prop_id)
{
- case ARG_TYPE:
- window->type = GTK_VALUE_ENUM (*arg);
+ case PROP_TYPE:
+ window->type = g_value_get_enum (value);
break;
- case ARG_TITLE:
- gtk_window_set_title (window, GTK_VALUE_STRING (*arg));
+ case PROP_TITLE:
+ gtk_window_set_title (window, g_value_get_string (value));
break;
- case ARG_AUTO_SHRINK:
- window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
+ case PROP_AUTO_SHRINK:
+ window->auto_shrink = g_value_get_boolean (value);
gtk_widget_queue_resize (GTK_WIDGET (window));
break;
- case ARG_ALLOW_SHRINK:
- window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
+ case PROP_ALLOW_SHRINK:
+ window->allow_shrink = g_value_get_boolean (value);
gtk_widget_queue_resize (GTK_WIDGET (window));
break;
- case ARG_ALLOW_GROW:
- window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
+ case PROP_ALLOW_GROW:
+ window->allow_grow = g_value_get_boolean (value);
gtk_widget_queue_resize (GTK_WIDGET (window));
break;
- case ARG_MODAL:
- gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
+ case PROP_MODAL:
+ gtk_window_set_modal (window, g_value_get_boolean (value));
+ break;
+ case PROP_WIN_POS:
+ gtk_window_set_position (window, g_value_get_enum (value));
break;
- case ARG_WIN_POS:
- gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
+ case PROP_DEFAULT_WIDTH:
+ gtk_window_set_default_size (window, g_value_get_int (value), -1);
break;
- case ARG_DEFAULT_WIDTH:
- gtk_window_set_default_size (window, GTK_VALUE_INT (*arg), -2);
+ case PROP_DEFAULT_HEIGHT:
+ gtk_window_set_default_size (window, -1, g_value_get_int (value));
break;
- case ARG_DEFAULT_HEIGHT:
- gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg));
+ case PROP_DESTROY_WITH_PARENT:
+ gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value));
break;
default:
break;
}
static void
-gtk_window_get_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id)
+gtk_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GtkWindow *window;
window = GTK_WINDOW (object);
- switch (arg_id)
+ switch (prop_id)
{
GtkWindowGeometryInfo *info;
- case ARG_TYPE:
- GTK_VALUE_ENUM (*arg) = window->type;
+ case PROP_TYPE:
+ g_value_set_enum (value, window->type);
break;
- case ARG_TITLE:
- GTK_VALUE_STRING (*arg) = g_strdup (window->title);
+ case PROP_TITLE:
+ g_value_set_string (value, window->title);
break;
- case ARG_AUTO_SHRINK:
- GTK_VALUE_BOOL (*arg) = window->auto_shrink;
+ case PROP_AUTO_SHRINK:
+ g_value_set_boolean (value, window->auto_shrink);
break;
- case ARG_ALLOW_SHRINK:
- GTK_VALUE_BOOL (*arg) = window->allow_shrink;
+ case PROP_ALLOW_SHRINK:
+ g_value_set_boolean (value, window->allow_shrink);
break;
- case ARG_ALLOW_GROW:
- GTK_VALUE_BOOL (*arg) = window->allow_grow;
+ case PROP_ALLOW_GROW:
+ g_value_set_boolean (value, window->allow_grow);
break;
- case ARG_MODAL:
- GTK_VALUE_BOOL (*arg) = window->modal;
+ case PROP_MODAL:
+ g_value_set_boolean (value, window->modal);
break;
- case ARG_WIN_POS:
- GTK_VALUE_ENUM (*arg) = window->position;
+ case PROP_WIN_POS:
+ g_value_set_enum (value, window->position);
break;
- case ARG_DEFAULT_WIDTH:
+ case PROP_DEFAULT_WIDTH:
info = gtk_window_get_geometry_info (window, FALSE);
if (!info)
- GTK_VALUE_INT (*arg) = -1;
+ g_value_set_int (value, 0);
else
- GTK_VALUE_INT (*arg) = info->width;
+ g_value_set_int (value, info->width);
break;
- case ARG_DEFAULT_HEIGHT:
+ case PROP_DEFAULT_HEIGHT:
info = gtk_window_get_geometry_info (window, FALSE);
if (!info)
- GTK_VALUE_INT (*arg) = -1;
+ g_value_set_int (value, 0);
else
- GTK_VALUE_INT (*arg) = info->height;
+ g_value_set_int (value, info->height);
+ break;
+ case PROP_DESTROY_WITH_PARENT:
+ g_value_set_boolean (value, window->destroy_with_parent);
break;
default:
- arg->type = GTK_TYPE_INVALID;
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+/**
+ * gtk_window_new:
+ * @type: type of window
+ *
+ * Creates a new #GtkWindow, which is a toplevel window that can
+ * contain other widgets. Nearly always, the type of the window should
+ * be #GTK_WINDOW_TOPLEVEL. If you're implementing something like a
+ * popup menu from scratch (which is a bad idea, just use #GtkMenu),
+ * you might use #GTK_WINDOW_POPUP. #GTK_WINDOW_POPUP is not for
+ * dialogs, though in some other toolkits dialogs are called "popups."
+ * In GTK+, #GTK_WINDOW_POPUP means a pop-up menu or pop-up tooltip.
+ * Popup windows are not controlled by the window manager.
+ *
+ * If you simply want an undecorated window (no window borders), use
+ * gtk_window_set_decorated(), don't use #GTK_WINDOW_POPUP.
+ *
+ * Return value: a new #GtkWindow.
+ **/
GtkWidget*
gtk_window_new (GtkWindowType type)
{
return GTK_WIDGET (window);
}
+/**
+ * gtk_window_set_title:
+ * @window: a #GtkWindow
+ * @title: title of the window
+ *
+ * Sets the title of the #GtkWindow. The title of a window will be displayed in
+ * its title bar; on the X Window System, the title bar is rendered by the
+ * window manager, so exactly how the title appears to users may vary according
+ * to a user's exact configuration. The title should help a user distinguish
+ * this window from other windows they may have open. A good title might
+ * include the application name and current document filename, for example.
+ *
+ **/
void
gtk_window_set_title (GtkWindow *window,
const gchar *title)
window->title = g_strdup (title);
if (GTK_WIDGET_REALIZED (window))
- gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
+ {
+ gdk_window_set_title (GTK_WIDGET (window)->window, window->title);
+
+ gtk_decorated_window_set_title (window, title);
+ }
+
+ g_object_notify (G_OBJECT (window), "title");
}
+/**
+ * gtk_window_set_wmclass:
+ * @window: a #GtkWindow
+ * @wmclass_name: window name hint
+ * @wmclass_class: window class hint
+ *
+ * Don't use this function. It sets the X Window System "class" and
+ * "name" hints for a window. According to the ICCCM, you should
+ * always set these to the same value for all windows in an
+ * application, and GTK sets them to that value by default, so calling
+ * this function is sort of pointless. However, you may want to call
+ * gtk_window_set_role() on each window in your application, for the
+ * benefit of the session manager. Setting the role allows the window
+ * manager to restore window positions when loading a saved session.
+ *
+ **/
void
gtk_window_set_wmclass (GtkWindow *window,
const gchar *wmclass_name,
window->wmclass_class = g_strdup (wmclass_class);
if (GTK_WIDGET_REALIZED (window))
- g_warning ("shouldn't set wmclass after window is realized!\n");
+ g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n");
+}
+
+/**
+ * gtk_window_set_role:
+ * @window: a #GtkWindow
+ * @role: unique identifier for the window to be used when restoring a session
+ *
+ * In combination with the window title, the window role allows a
+ * window manager to identify "the same" window when an application is
+ * restarted. So for example you might set the "toolbox" role on your
+ * app's toolbox window, so that when the user restarts their session,
+ * the window manager can put the toolbox back in the same place.
+ *
+ * If a window already has a unique title, you don't need to set the
+ * role, since the WM can use the title to identify the window when
+ * restoring the session.
+ *
+ **/
+void
+gtk_window_set_role (GtkWindow *window,
+ const gchar *role)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (role == window->wm_role)
+ return;
+
+ g_free (window->wm_role);
+ window->wm_role = g_strdup (role);
+
+ if (GTK_WIDGET_REALIZED (window))
+ g_warning ("gtk_window_set_role(): shouldn't set role after window is realized!\n");
}
+/**
+ * gtk_window_set_focus:
+ * @window: a #GtkWindow
+ * @focus: widget to be the new focus widget
+ *
+ * If @focus is not the current focus widget, and is focusable, emits
+ * the "set_focus" signal to set @focus as the focus widget for the
+ * window. This function is more or less GTK-internal; to focus an
+ * entry widget or the like, you should use gtk_widget_grab_focus()
+ * instead of this function.
+ *
+ **/
void
gtk_window_set_focus (GtkWindow *window,
GtkWidget *focus)
gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
}
+/**
+ * gtk_window_set_default:
+ * @window: a #GtkWindow
+ * @default_widget: widget to be the default
+ *
+ * The default widget is the widget that's activated when the user
+ * presses Enter in a dialog (for example). This function tells a
+ * #GtkWindow about the current default widget; it's really a GTK
+ * internal function and you shouldn't need it. Instead, to change the
+ * default widget, first set the #GTK_CAN_DEFAULT flag on the widget
+ * you'd like to make the default using GTK_WIDGET_SET_FLAGS(), then
+ * call gtk_widget_grab_default() to move the default.
+ *
+ **/
void
gtk_window_set_default (GtkWindow *window,
GtkWidget *default_widget)
{
if (window->default_widget)
{
- GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
- gtk_widget_draw_default (window->default_widget);
+ if (window->focus_widget != window->default_widget ||
+ !GTK_WIDGET_RECEIVES_DEFAULT (window->default_widget))
+ GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+ gtk_widget_queue_draw (window->default_widget);
}
window->default_widget = default_widget;
if (window->default_widget)
{
- GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
- gtk_widget_draw_default (window->default_widget);
+ if (window->focus_widget == NULL ||
+ !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget))
+ GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+ gtk_widget_queue_draw (window->default_widget);
}
}
}
void
gtk_window_set_policy (GtkWindow *window,
- gint allow_shrink,
- gint allow_grow,
- gint auto_shrink)
+ gboolean allow_shrink,
+ gboolean allow_grow,
+ gboolean auto_shrink)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
window->allow_grow = (allow_grow != FALSE);
window->auto_shrink = (auto_shrink != FALSE);
+ g_object_notify (G_OBJECT (window), "allow_shrink");
+ g_object_notify (G_OBJECT (window), "allow_grow");
+ g_object_notify (G_OBJECT (window), "auto_shrink");
+
gtk_widget_queue_resize (GTK_WIDGET (window));
}
gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
}
+void
+gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ key.window = window;
+ key.keyval = keyval;
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ if (mnemonic)
+ {
+ g_return_if_fail (g_slist_find (mnemonic->targets, target) == NULL);
+ mnemonic->targets = g_slist_prepend (mnemonic->targets, target);
+ }
+ else
+ {
+ mnemonic = g_new (GtkWindowMnemonic, 1);
+ *mnemonic = key;
+ mnemonic->targets = g_slist_prepend (NULL, target);
+ g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
+ }
+}
+
+void
+gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ key.window = window;
+ key.keyval = keyval;
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ g_return_if_fail (mnemonic && g_slist_find (mnemonic->targets, target) != NULL);
+
+ mnemonic->targets = g_slist_remove (mnemonic->targets, target);
+ if (mnemonic->targets == NULL)
+ {
+ g_hash_table_remove (mnemonic_hash_table, mnemonic);
+ g_free (mnemonic);
+ }
+}
+
+gboolean
+gtk_window_mnemonic_activate (GtkWindow *window,
+ guint keyval,
+ GdkModifierType modifier)
+{
+ GtkWindowMnemonic key;
+ GtkWindowMnemonic *mnemonic;
+ GSList *list;
+ GtkWidget *widget, *chosen_widget;
+ gboolean overloaded;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ if (window->mnemonic_modifier != (modifier & gtk_accelerator_get_default_mod_mask ()))
+ return FALSE;
+
+ key.window = window;
+ key.keyval = keyval;
+ mnemonic = g_hash_table_lookup (mnemonic_hash_table, &key);
+
+ if (!mnemonic)
+ return FALSE;
+
+ overloaded = FALSE;
+ chosen_widget = NULL;
+ list = mnemonic->targets;
+ while (list)
+ {
+ widget = GTK_WIDGET (list->data);
+
+ if (GTK_WIDGET_IS_SENSITIVE (widget) &&
+ GTK_WIDGET_MAPPED (widget))
+ {
+ if (chosen_widget)
+ {
+ overloaded = TRUE;
+ break;
+ }
+ else
+ chosen_widget = widget;
+ }
+ list = g_slist_next (list);
+ }
+
+ if (chosen_widget)
+ {
+ /* For round robin we put the activated entry on
+ * the end of the list after activation
+ */
+ mnemonic->targets = g_slist_remove (mnemonic->targets, chosen_widget);
+ mnemonic->targets = g_slist_append (mnemonic->targets, chosen_widget);
+
+ return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
+ }
+ return FALSE;
+}
+
+void
+gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ GdkModifierType modifier)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
+
+ window->mnemonic_modifier = modifier;
+}
+
void
gtk_window_set_position (GtkWindow *window,
GtkWindowPosition position)
{
- g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
window->position = position;
+
+ g_object_notify (G_OBJECT (window), "window_position");
}
-gint
-gtk_window_activate_focus (GtkWindow *window)
+gboolean
+gtk_window_activate_focus (GtkWindow *window)
{
g_return_val_if_fail (window != NULL, FALSE);
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
if (window->focus_widget)
{
if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
- gtk_widget_activate (window->focus_widget);
+ gtk_widget_activate (window->focus_widget);
return TRUE;
}
return FALSE;
}
-gint
-gtk_window_activate_default (GtkWindow *window)
+gboolean
+gtk_window_activate_default (GtkWindow *window)
{
g_return_val_if_fail (window != NULL, FALSE);
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
- if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
+ if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
+ (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
{
gtk_widget_activate (window->default_widget);
return TRUE;
}
+ else if (window->focus_widget)
+ {
+ if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
+ gtk_widget_activate (window->focus_widget);
+ return TRUE;
+ }
return FALSE;
}
+/**
+ * gtk_window_set_modal:
+ * @window: a #GtkWindow
+ * @modal: whether the window is modal
+ *
+ * Sets a window modal or non-modal. Modal windows prevent interaction
+ * with other windows in the same application. To keep modal dialogs
+ * on top of main application windows, use
+ * gtk_window_set_transient_for() to make the dialog transient for the
+ * parent; most window managers will then disallow lowering the dialog
+ * below the parent.
+ *
+ *
+ **/
void
gtk_window_set_modal (GtkWindow *window,
gboolean modal)
g_return_if_fail (GTK_IS_WINDOW (window));
window->modal = modal != FALSE;
-
+
/* adjust desired modality state */
if (GTK_WIDGET_VISIBLE (window) && window->modal)
gtk_grab_add (GTK_WIDGET (window));
else
gtk_grab_remove (GTK_WIDGET (window));
+
+ g_object_notify (G_OBJECT (window), "modal");
}
+/**
+ * gtk_window_list_toplevels:
+ *
+ * Returns a list of all existing toplevel windows. The widgets
+ * in the list are not individually referenced. If you want
+ * to iterate through the list and perform actions involving
+ * callbacks that might destroy the widgets, you MUST call
+ * g_list_foreach (result, (GFunc)g_object_ref, NULL) first, and
+ * then unref all the widgets afterwards.
+ *
+ * Return value: list of toplevel widgets
+ **/
GList*
gtk_window_list_toplevels (void)
{
GSList *slist;
for (slist = toplevel_list; slist; slist = slist->next)
- list = g_list_prepend (list, gtk_widget_ref (slist->data));
+ list = g_list_prepend (list, slist->data);
return list;
}
}
void
-gtk_window_reposition (GtkWindow *window,
- gint x,
- gint y)
+_gtk_window_reposition (GtkWindow *window,
+ gint x,
+ gint y)
{
GtkWindowGeometryInfo *info;
&info->last.geometry,
info->last.flags);
}
-
- gdk_window_move (GTK_WIDGET (window)->window, x, y);
+
+ if (window->frame)
+ gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
+ else
+ gdk_window_move (GTK_WIDGET (window)->window, x, y);
}
}
G_OBJECT_CLASS (parent_class)->shutdown (object);
}
+static void
+parent_destroyed_callback (GtkWindow *parent, GtkWindow *child)
+{
+ gtk_widget_destroy (GTK_WIDGET (child));
+}
+
+static void
+connect_parent_destroyed (GtkWindow *window)
+{
+ if (window->transient_parent)
+ {
+ gtk_signal_connect (GTK_OBJECT (window->transient_parent),
+ "destroy",
+ GTK_SIGNAL_FUNC (parent_destroyed_callback),
+ window);
+ }
+}
+
+static void
+disconnect_parent_destroyed (GtkWindow *window)
+{
+ if (window->transient_parent)
+ {
+ gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+ GTK_SIGNAL_FUNC (parent_destroyed_callback),
+ window);
+ }
+}
+
static void
gtk_window_transient_parent_realized (GtkWidget *parent,
GtkWidget *window)
GTK_SIGNAL_FUNC (gtk_widget_destroyed),
&window->transient_parent);
+ if (window->destroy_with_parent)
+ disconnect_parent_destroyed (window);
+
window->transient_parent = NULL;
}
}
+/**
+ * gtk_window_set_transient_for:
+ * @window: a #GtkWindow
+ * @parent: parent window
+ *
+ * Dialog windows should be set transient for the main application
+ * window they were spawned from. This allows window managers to
+ * e.g. keep the dialog on top of the main window, or center the
+ * dialog over the main window. gtk_dialog_new_with_buttons() and
+ * other convenience functions in GTK+ will sometimes call
+ * gtk_window_set_transient_for() on your behalf.
+ *
+ **/
void
gtk_window_set_transient_for (GtkWindow *window,
GtkWindow *parent)
{
- g_return_if_fail (window != 0);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
+ g_return_if_fail (window != parent);
+
if (window->transient_parent)
{
if (GTK_WIDGET_REALIZED (window) &&
GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
window);
+ if (window->destroy_with_parent)
+ connect_parent_destroyed (window);
+
if (GTK_WIDGET_REALIZED (window) &&
GTK_WIDGET_REALIZED (parent))
gtk_window_transient_parent_realized (GTK_WIDGET (parent),
}
}
-static void
-gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
+/**
+ * gtk_window_set_type_hint:
+ * @window: a #GtkWindow
+ * @hint: the window type
+ *
+ * By setting the type hint for the window, you allow the window
+ * manager to decorate and handle the window in a way which is
+ * suitable to the function of the window in your application.
+ *
+ * This function should be called before the window becomes visible.
+ *
+ * gtk_dialog_new_with_buttons() and other convenience functions in GTK+
+ * will sometimes call gtk_window_set_type_hint() on your behalf.
+ *
+ **/
+void
+gtk_window_set_type_hint (GtkWindow *window,
+ GdkWindowTypeHint hint)
{
- if (info->widget)
- gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
- GTK_SIGNAL_FUNC (gtk_widget_destroyed),
- &info->widget);
- g_free (info);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (!GTK_WIDGET_VISIBLE (window));
+ window->type_hint = hint;
+}
+
+/**
+ * gtk_window_set_destroy_with_parent:
+ * @window: a #GtkWindow
+ * @setting: whether to destroy @window with its transient parent
+ *
+ * If @setting is TRUE, then destroying the transient parent of @window
+ * will also destroy @window itself. This is useful for dialogs that
+ * shouldn't persist beyond the lifetime of the main window they're
+ * associated with, for example.
+ **/
+void
+gtk_window_set_destroy_with_parent (GtkWindow *window,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (window->destroy_with_parent == (setting != FALSE))
+ return;
+
+ if (window->destroy_with_parent)
+ {
+ disconnect_parent_destroyed (window);
+ }
+ else
+ {
+ connect_parent_destroyed (window);
+ }
+
+ window->destroy_with_parent = setting;
+
+ g_object_notify (G_OBJECT (window), "destroy_with_parent");
}
static GtkWindowGeometryInfo*
{
GtkWindowGeometryInfo *info;
- info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
-
+ info = window->geometry_info;
if (!info && create)
{
info = g_new0 (GtkWindowGeometryInfo, 1);
info->last.height = -1;
info->widget = NULL;
info->mask = 0;
-
- gtk_object_set_data_full (GTK_OBJECT (window),
- "gtk-window-geometry",
- info,
- (GtkDestroyNotify) gtk_window_geometry_destroy);
+ info->may_shrink = FALSE;
+ window->geometry_info = info;
}
return info;
}
+/**
+ * gtk_window_set_geometry_hints:
+ * @window: a #GdkWindow
+ * @geometry_widget: widget the geometry hints will be applied to
+ * @geometry: struct containing geometry information
+ * @geom_mask: mask indicating which struct fields should be paid attention to
+ *
+ * This function sets up hints about how a window can be resized by
+ * the user. You can set a minimum and maximum size; allowed resize
+ * increments (e.g. for xterm, you can only resize by the size of a
+ * character); aspect ratios; and more. See the #GdkGeometry struct.
+ *
+ **/
void
gtk_window_set_geometry_hints (GtkWindow *window,
GtkWidget *geometry_widget,
gtk_widget_queue_resize (GTK_WIDGET (window));
}
+/**
+ * gtk_window_set_decorated:
+ * @window: a #GtkWindow
+ * @setting: %TRUE to decorate the window
+ *
+ * By default, windows are decorated with a title bar, resize
+ * controls, etc. Some window managers allow GTK+ to disable these
+ * decorations, creating a borderless window. If you set the decorated
+ * property to %FALSE using this function, GTK+ will do its best to
+ * convince the window manager not to decorate the window.
+ *
+ **/
+void
+gtk_window_set_decorated (GtkWindow *window,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ setting = setting != FALSE;
+
+ if (setting == window->decorated)
+ return;
+
+ if (GTK_WIDGET (window)->window)
+ {
+ if (window->decorated)
+ gdk_window_set_decorations (GTK_WIDGET (window)->window,
+ GDK_DECOR_ALL);
+ else
+ gdk_window_set_decorations (GTK_WIDGET (window)->window,
+ 0);
+ }
+}
+
+/**
+ * gtk_window_set_default_size:
+ * @window: a #GtkWindow
+ * @width: width in pixels, 0 to unset, or -1 to leave the width unchanged
+ * @height: height in pixels, 0 to unset, or -1 to leave the height unchanged
+ *
+ * Sets the default size of a window. If the window's "natural" size
+ * (its size request) is larger than the default, the default will be
+ * ignored. So the default size is a minimum initial size. Unlike
+ * gtk_widget_set_usize(), which sets a size request for a widget and
+ * thus would keep users from shrinking the window, this function only
+ * sets the initial size, just as if the user had resized the window
+ * themselves. Users can still shrink the window again as they
+ * normally would. Setting a default size of 0 means to use the
+ * "natural" default size (the size request of the window).
+ *
+ * For more control over a window's initial size and how resizing works,
+ * investigate gtk_window_set_geometry_hints().
+ *
+ * A useful feature: if you set the "geometry widget" via
+ * gtk_window_set_geometry_hints(), the default size specified by
+ * gtk_window_set_default_size() will be the default size of that
+ * widget, not of the entire window.
+ *
+ **/
void
gtk_window_set_default_size (GtkWindow *window,
gint width,
info = gtk_window_get_geometry_info (window, TRUE);
+ g_object_freeze_notify (G_OBJECT (window));
if (width >= 0)
- info->width = width;
+ {
+ info->width = width;
+ g_object_notify (G_OBJECT (window), "default_width");
+ info->may_shrink = TRUE;
+ }
if (height >= 0)
- info->height = height;
-
+ {
+ info->height = height;
+ g_object_notify (G_OBJECT (window), "default_height");
+ info->may_shrink = TRUE;
+ }
+ g_object_thaw_notify (G_OBJECT (window));
+
gtk_widget_queue_resize (GTK_WIDGET (window));
}
window = GTK_WINDOW (object);
if (window->transient_parent)
- gtk_window_unset_transient_for (window);
+ gtk_window_set_transient_for (window, NULL);
if (window->has_user_ref_count)
{
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
+static gboolean
+gtk_window_mnemonic_hash_remove (gpointer key,
+ gpointer value,
+ gpointer user)
+{
+ GtkWindowMnemonic *mnemonic = key;
+ GtkWindow *window = user;
+
+ if (mnemonic->window == window)
+ {
+ if (mnemonic->targets)
+ {
+ gchar *name = gtk_accelerator_name (mnemonic->keyval, 0);
+
+ g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
+ name, mnemonic->targets->data);
+ g_free (name);
+ }
+ g_slist_free (mnemonic->targets);
+ g_free (mnemonic);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void
gtk_window_finalize (GObject *object)
{
g_free (window->title);
g_free (window->wmclass_name);
g_free (window->wmclass_class);
+ g_free (window->wm_role);
- G_OBJECT_CLASS(parent_class)->finalize (object);
+ g_hash_table_foreach_remove (mnemonic_hash_table,
+ gtk_window_mnemonic_hash_remove,
+ window);
+ if (window->geometry_info)
+ {
+ if (window->geometry_info->widget)
+ gtk_signal_disconnect_by_func (GTK_OBJECT (window->geometry_info->widget),
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &window->geometry_info->widget);
+ g_free (window->geometry_info);
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
GtkWindow *window = GTK_WINDOW (widget);
GtkContainer *container = GTK_CONTAINER (window);
gboolean need_resize;
-
+
GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
-
+
need_resize = container->need_resize || !GTK_WIDGET_REALIZED (widget);
container->need_resize = FALSE;
-
+
if (need_resize)
{
GtkWindowGeometryInfo *info = gtk_window_get_geometry_info (window, TRUE);
GtkAllocation allocation = { 0, 0 };
GdkGeometry new_geometry;
guint width, height, new_flags;
-
+ gboolean was_realized;
+
/* determine default size to initially show the window with */
gtk_widget_size_request (widget, NULL);
gtk_window_compute_default_size (window, &width, &height);
-
+
/* save away the last default size for later comparisions */
info->last.width = width;
info->last.height = height;
&new_geometry, new_flags,
width, height,
&width, &height);
-
+
/* and allocate the window */
allocation.width = width;
allocation.height = height;
gtk_widget_size_allocate (widget, &allocation);
- if (GTK_WIDGET_REALIZED (widget))
+ was_realized = FALSE;
+ if (!GTK_WIDGET_REALIZED (widget))
+ {
+ gtk_widget_realize (widget);
+ was_realized = TRUE;;
+ }
+
+ /* Must be done after the windows are realized,
+ * so that the decorations can be read
+ */
+ gtk_decorated_window_calculate_frame_size (window);
+
+ if (!was_realized)
gdk_window_resize (widget->window, width, height);
- else
- gtk_widget_realize (widget);
}
gtk_container_check_resize (container);
gtk_window_map (GtkWidget *widget)
{
GtkWindow *window;
-
+ GdkWindow *toplevel;
+
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WINDOW (widget));
!GTK_WIDGET_MAPPED (window->bin.child))
gtk_widget_map (window->bin.child);
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (window->maximize_initially)
+ gdk_window_maximize (toplevel);
+ else
+ gdk_window_unmaximize (toplevel);
+
+ if (window->stick_initially)
+ gdk_window_stick (toplevel);
+ else
+ gdk_window_unstick (toplevel);
+
+ if (window->iconify_initially)
+ gdk_window_iconify (toplevel);
+ else
+ gdk_window_deiconify (toplevel);
+
gdk_window_show (widget->window);
+
+ if (window->frame)
+ gdk_window_show (window->frame);
}
static void
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WINDOW (widget));
+ window = GTK_WINDOW (widget);
+
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
- gdk_window_withdraw (widget->window);
+ if (window->frame)
+ gdk_window_withdraw (window->frame);
+ else
+ gdk_window_withdraw (widget->window);
- window = GTK_WINDOW (widget);
window->use_uposition = TRUE;
window->resize_count = 0;
window->handling_resize = FALSE;
+
}
static void
gtk_window_realize (GtkWidget *widget)
{
GtkWindow *window;
+ GdkWindow *parent_window;
GdkWindowAttr attributes;
gint attributes_mask;
case GTK_WINDOW_TOPLEVEL:
attributes.window_type = GDK_WINDOW_TOPLEVEL;
break;
- case GTK_WINDOW_DIALOG:
- attributes.window_type = GDK_WINDOW_DIALOG;
- break;
case GTK_WINDOW_POPUP:
attributes.window_type = GDK_WINDOW_TEMP;
break;
+ default:
+ g_warning (G_STRLOC": Unknown window type %d!", window->type);
+ break;
}
attributes.title = window->title;
attributes.wmclass_name = window->wmclass_name;
attributes.wmclass_class = window->wmclass_class;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);
+
+ if (window->has_frame)
+ {
+ attributes.width = widget->allocation.width + window->frame_left + window->frame_right;
+ attributes.height = widget->allocation.height + window->frame_top + window->frame_bottom;
+ attributes.event_mask = (GDK_EXPOSURE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_FOCUS_CHANGE_MASK |
+ GDK_STRUCTURE_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK);
+
+ attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ window->frame = gdk_window_new (NULL, &attributes, attributes_mask);
+ gdk_window_set_user_data (window->frame, widget);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = window->frame_left;
+ attributes.y = window->frame_right;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ parent_window = window->frame;
+ }
+ else
+ {
+ attributes_mask = 0;
+ parent_window = NULL;
+ }
+
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
attributes.event_mask = gtk_widget_get_events (widget);
attributes.event_mask |= (GDK_EXPOSURE_MASK |
GDK_KEY_PRESS_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_STRUCTURE_MASK);
-
- attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
-
- widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
+ widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
gdk_window_set_user_data (widget->window, window);
-
+
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- gtk_window_paint (widget, NULL);
+ if (window->frame)
+ gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
+ /* This is a bad hack to set the window background. */
+ gtk_window_paint (widget, NULL);
+
if (window->transient_parent &&
GTK_WIDGET_REALIZED (window->transient_parent))
gdk_window_set_transient_for (widget->window,
GTK_WIDGET (window->transient_parent)->window);
+
+ if (window->wm_role)
+ gdk_window_set_role (widget->window, window->wm_role);
+
+ if (!window->decorated)
+ gdk_window_set_decorations (widget->window, 0);
+
+ gdk_window_set_type_hint (widget->window, window->type_hint);
+
+ /* transient_for must be set to allow the modal hint */
+ if (window->transient_parent && window->modal)
+ gdk_window_set_modal_hint (widget->window, TRUE);
+ else
+ gdk_window_set_modal_hint (widget->window, FALSE);
+}
+
+static void
+gtk_window_unrealize (GtkWidget *widget)
+{
+ GtkWindow *window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (widget));
+
+ window = GTK_WINDOW (widget);
+
+ if (window->frame)
+ {
+ gdk_window_set_user_data (window->frame, NULL);
+ gdk_window_destroy (window->frame);
+ window->frame = NULL;
+ }
+
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}
static void
gtk_widget_size_allocate (window->bin.child, &child_allocation);
}
+
+ if (GTK_WIDGET_REALIZED (widget) && window->frame)
+ {
+ gdk_window_resize (window->frame,
+ allocation->width + window->frame_left + window->frame_right,
+ allocation->height + window->frame_top + window->frame_bottom);
+ }
+}
+
+static gint
+gtk_window_event (GtkWidget *widget, GdkEvent *event)
+{
+ GtkWindow *window;
+ gboolean return_val;
+
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ window = GTK_WINDOW (widget);
+
+ if (window->frame && (event->any.window == window->frame))
+ {
+ if ((event->type != GDK_KEY_PRESS) &&
+ (event->type != GDK_KEY_RELEASE) &&
+ (event->type != GDK_FOCUS_CHANGE))
+ {
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
+ return_val = FALSE;
+ gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
+ return TRUE;
+ }
+ else
+ {
+ g_object_unref (event->any.window);
+ event->any.window = g_object_ref (widget->window);
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gtk_window_frame_event (GtkWidget *widget, GdkEvent *event)
+{
+ GdkEventConfigure *configure_event;
+ GtkWindow *window = GTK_WINDOW (widget);
+ GdkRectangle rect;
+
+ switch (event->type)
+ {
+ case GDK_CONFIGURE:
+ configure_event = (GdkEventConfigure *)event;
+
+ /* Invalidate the decorations */
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = configure_event->width;
+ rect.height = configure_event->height;
+
+ gdk_window_invalidate_rect (window->frame, &rect, FALSE);
+
+ /* Pass on the (modified) configure event */
+ configure_event->width -= window->frame_left + window->frame_right;
+ configure_event->height -= window->frame_top + window->frame_bottom;
+ return gtk_window_configure_event (widget, configure_event);
+ break;
+ default:
+ break;
+ }
+ return FALSE;
}
static gint
GdkEventKey *event)
{
GtkWindow *window;
- GtkDirectionType direction = 0;
gboolean handled;
g_return_val_if_fail (widget != NULL, FALSE);
handled = FALSE;
- if (window->focus_widget &&
- window->focus_widget != widget &&
+ if (window->focus_widget && window->focus_widget != widget &&
GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
- {
- handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
- }
-
- if (!handled)
- handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
+ handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
if (!handled)
- {
- switch (event->keyval)
- {
- case GDK_space:
- if (window->focus_widget)
- {
- if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
- gtk_widget_activate (window->focus_widget);
- handled = TRUE;
- }
- break;
- case GDK_Return:
- case GDK_KP_Enter:
- if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget) &&
- (!window->focus_widget || !GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget)))
- {
- gtk_widget_activate (window->default_widget);
- handled = TRUE;
- }
- else if (window->focus_widget)
- {
- if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
- gtk_widget_activate (window->focus_widget);
- handled = TRUE;
- }
- break;
- case GDK_Up:
- case GDK_Down:
- case GDK_Left:
- case GDK_Right:
- case GDK_KP_Up:
- case GDK_KP_Down:
- case GDK_KP_Left:
- case GDK_KP_Right:
- case GDK_Tab:
- case GDK_ISO_Left_Tab:
- switch (event->keyval)
- {
- case GDK_Up:
- case GDK_KP_Up:
- direction = GTK_DIR_UP;
- break;
- case GDK_Down:
- case GDK_KP_Down:
- direction = GTK_DIR_DOWN;
- break;
- case GDK_Left:
- case GDK_KP_Left:
- direction = GTK_DIR_LEFT;
- break;
- case GDK_Right:
- case GDK_KP_Right:
- direction = GTK_DIR_RIGHT;
- break;
- case GDK_Tab:
- case GDK_ISO_Left_Tab:
- if (event->state & GDK_SHIFT_MASK)
- direction = GTK_DIR_TAB_BACKWARD;
- else
- direction = GTK_DIR_TAB_FORWARD;
- break;
- default :
- direction = GTK_DIR_UP; /* never reached, but makes compiler happy */
- }
-
- gtk_container_focus (GTK_CONTAINER (widget), direction);
+ handled = gtk_window_mnemonic_activate (window,
+ event->keyval,
+ event->state);
- if (!GTK_CONTAINER (window)->focus_child)
- gtk_window_set_focus (GTK_WINDOW (widget), NULL);
- else
- handled = TRUE;
- break;
- }
- }
+ if (!handled)
+ handled = gtk_accel_groups_activate (GTK_OBJECT (window), event->keyval, event->state);
+ /* Chain up, invokes binding set */
if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
return handled;
}
+
+static void
+gtk_window_real_activate_default (GtkWindow *window)
+{
+ gtk_window_activate_default (window);
+}
+
+static void
+gtk_window_real_activate_focus (GtkWindow *window)
+{
+ gtk_window_activate_focus (window);
+}
+
+static void
+gtk_window_move_focus (GtkWindow *window,
+ GtkDirectionType dir)
+{
+ gtk_container_focus (GTK_CONTAINER (window), dir);
+
+ if (!GTK_CONTAINER (window)->focus_child)
+ gtk_window_set_focus (window, NULL);
+}
+
static gint
gtk_window_key_release_event (GtkWidget *widget,
GdkEventKey *event)
gtk_window_focus_in_event (GtkWidget *widget,
GdkEventFocus *event)
{
- GtkWindow *window;
+ GtkWindow *window = GTK_WINDOW (widget);
GdkEventFocus fevent;
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
/* It appears spurious focus in events can occur when
* the window is hidden. So we'll just check to see if
* the window is visible before actually handling the
*/
if (GTK_WIDGET_VISIBLE (widget))
{
- window = GTK_WINDOW (widget);
+ window->has_focus = TRUE;
+
if (window->focus_widget &&
window->focus_widget != widget &&
!GTK_WIDGET_HAS_FOCUS (window->focus_widget))
gtk_window_focus_out_event (GtkWidget *widget,
GdkEventFocus *event)
{
- GtkWindow *window;
+ GtkWindow *window = GTK_WINDOW (widget);
GdkEventFocus fevent;
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- window = GTK_WINDOW (widget);
+ window->has_focus = FALSE;
+
if (window->focus_widget &&
window->focus_widget != widget &&
GTK_WIDGET_HAS_FOCUS (window->focus_widget))
* of date, so we need to reset all our widgets. Our other
* toplevel windows will also get the message, but by
* then, the RC file will up to date, so we have to tell
- * them now.
+ * them now. Also, we have to invalidate cached icons in
+ * icon sets so they get re-rendered.
*/
- GList *list, *toplevels = gtk_window_list_toplevels ();
+ GList *list, *toplevels;
+ _gtk_icon_set_invalidate_caches ();
+
+ toplevels = gtk_window_list_toplevels ();
+ g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
+
for (list = toplevels; list; list = list->next)
{
gtk_widget_reset_rc_styles (list->data);
gtk_window_move_resize (window);
}
+static gboolean
+gtk_window_focus (GtkContainer *container,
+ GtkDirectionType direction)
+{
+ GtkBin *bin = GTK_BIN (container);
+ GtkWindow *window = GTK_WINDOW (container);
+ GtkWidget *old_focus_child = container->focus_child;
+ GtkWidget *parent;
+
+ /* We need a special implementation here to deal properly with wrapping
+ * around in the tab chain without the danger of going into an
+ * infinite loop.
+ */
+ if (old_focus_child)
+ {
+ if (GTK_IS_CONTAINER (old_focus_child) &&
+ GTK_WIDGET_DRAWABLE (old_focus_child) &&
+ GTK_WIDGET_IS_SENSITIVE (old_focus_child) &&
+ gtk_container_focus (GTK_CONTAINER (old_focus_child), direction))
+ return TRUE;
+ }
+
+ if (window->focus_widget)
+ {
+ /* Wrapped off the end, clear the focus setting for the toplpevel */
+ parent = window->focus_widget->parent;
+ while (parent)
+ {
+ gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
+ parent = GTK_WIDGET (parent)->parent;
+ }
+
+ gtk_window_set_focus (GTK_WINDOW (container), NULL);
+ }
+
+ /* Now try to focus the first widget in the window */
+ if (GTK_WIDGET_DRAWABLE (bin->child) &&
+ GTK_WIDGET_IS_SENSITIVE (bin->child))
+ {
+ if (GTK_IS_CONTAINER (bin->child))
+ {
+ if (gtk_container_focus (GTK_CONTAINER (bin->child), direction))
+ return TRUE;
+ }
+ else if (GTK_WIDGET_CAN_FOCUS (bin->child))
+ {
+ gtk_widget_grab_focus (bin->child);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
gtk_window_real_set_focus (GtkWindow *window,
GtkWidget *focus)
if (window->focus_widget)
{
- event.type = GDK_FOCUS_CHANGE;
- event.window = window->focus_widget->window;
- event.in = FALSE;
-
if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
(window->focus_widget != window->default_widget))
{
GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
- /* if any widget had the default set there should be
- a default_widget, but might not so this is a sanity
- check */
+
if (window->default_widget)
GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
}
-
- gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+
+ if (window->has_focus)
+ {
+ event.type = GDK_FOCUS_CHANGE;
+ event.window = window->focus_widget->window;
+ event.in = FALSE;
+
+ gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+ }
}
window->focus_widget = focus;
if (window->focus_widget)
{
- event.type = GDK_FOCUS_CHANGE;
- event.window = window->focus_widget->window;
- event.in = TRUE;
+ if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
+ (window->focus_widget != window->default_widget))
+ {
+ if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
+ GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
- if (window->default_widget)
- {
- if (GTK_WIDGET_RECEIVES_DEFAULT (window->focus_widget) &&
- (window->focus_widget != window->default_widget))
- {
- if (GTK_WIDGET_CAN_DEFAULT (window->focus_widget))
- GTK_WIDGET_SET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT);
- GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
- }
- else
- {
- GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
- }
+ if (window->default_widget)
+ GTK_WIDGET_UNSET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
+ }
+
+ if (window->has_focus)
+ {
+ event.type = GDK_FOCUS_CHANGE;
+ event.window = window->focus_widget->window;
+ event.in = TRUE;
+
+ gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
}
-
- gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
- }
- else if (window->default_widget)
- {
- GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT);
}
if (window->default_widget &&
gtk_widget_queue_draw (window->default_widget);
}
+
+
/*********************************
* Functions related to resizing *
*********************************/
gint x, y;
gint width, height;
gint new_width, new_height;
+ gboolean need_reposition;
gboolean default_size_changed = FALSE;
gboolean hints_changed = FALSE;
+ gboolean may_shrink = window->auto_shrink;
- g_return_if_fail (GTK_IS_WINDOW (window));
g_return_if_fail (GTK_WIDGET_REALIZED (window));
widget = GTK_WIDGET (window);
info->last.height != new_height)
{
default_size_changed = TRUE;
+ may_shrink |= info->may_shrink;
info->last.width = new_width;
info->last.height = new_height;
if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
window->use_uposition = TRUE;
}
+ info->may_shrink = FALSE;
/* Compute new set of hints for the window
*/
* the window should be.
*/
if (!default_size_changed ||
- (!window->auto_shrink &&
+ (!may_shrink &&
new_width <= widget->allocation.width &&
new_height <= widget->allocation.height))
{
/* compute new window position if a move is required
*/
- gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
- if (x != 1 && y != -1 && !(new_flags & GDK_HINT_POS))
+ need_reposition = gtk_window_compute_reposition (window, new_width, new_height, &x, &y);
+ if (need_reposition && !(new_flags & GDK_HINT_POS))
{
new_flags |= GDK_HINT_POS;
hints_changed = TRUE;
gtk_widget_size_allocate (widget, &allocation);
gtk_widget_queue_draw (widget);
-#ifdef FIXME_ZVT_ME_HARDER
if ((default_size_changed || hints_changed) && (width != new_width || height != new_height))
{
/* We could be here for two reasons
* another resize.
* 2) Our computation of default_size_changed was completely
* screwed up, probably because one of our children
- * is broken (i.e. changes requisition during
- * size allocation). It's probably a zvt widget.
+ * is changed requisition during size allocation).
*
* For 1), we could just go ahead and ask for the
* new size right now, but doing that for 2)
* the new size had been set.
*/
- if (x != -1 && y != -1)
- gdk_window_move (widget->window, x, y);
+ if (need_reposition)
+ {
+ if (window->frame)
+ gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
+ else
+ gdk_window_move (GTK_WIDGET (window)->window, x, y);
+ }
/* we have to preserve the values and flags that are used
* for computation of default_size_changed and hints_changed
*/
-
info->last = saved_last_info;
gtk_widget_queue_resize (widget);
return;
}
-#endif /* FIXME_ZVT_ME_HARDER */
}
/* Now set hints if necessary
*/
/* request a new window size */
- if (x != -1 && y != -1)
- gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
+ if (need_reposition)
+ {
+ if (window->frame)
+ {
+ gdk_window_move_resize (window->frame,
+ x - window->frame_left, y - window->frame_top,
+ new_width + window->frame_left + window->frame_right,
+ new_height + window->frame_top + window->frame_bottom);
+ gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+ }
+ else
+ gdk_window_move_resize (GTK_WIDGET (window)->window, x, y, new_width, new_height);
+ }
else
- gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+ {
+ if (window->frame)
+ gdk_window_resize (window->frame,
+ new_width + window->frame_left + window->frame_right,
+ new_height + window->frame_top + window->frame_bottom);
+ gdk_window_resize (GTK_WIDGET (window)->window, new_width, new_height);
+ }
window->resize_count += 1;
/* we are now awaiting the new configure event in response to our
}
else
{
- if (x != -1 && y != -1)
- gdk_window_move (widget->window, x, y);
+ if (need_reposition)
+ {
+ if (window->frame)
+ gdk_window_move (window->frame, x - window->frame_left, y - window->frame_top);
+ else
+ gdk_window_move (widget->window, x, y);
+ }
if (container->resize_widgets)
gtk_container_resize_children (GTK_CONTAINER (window));
geometry_a->height_inc != geometry_b->height_inc))
return FALSE;
+ if ((flags_a & GDK_HINT_WIN_GRAVITY) &&
+ geometry_a->win_gravity != geometry_b->win_gravity)
+ return FALSE;
+
return TRUE;
}
}
}
-/* 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
+_gtk_window_constrain_size (GtkWindow *window,
+ gint width,
+ gint height,
+ gint *new_width,
+ gint *new_height)
+{
+ GtkWindowGeometryInfo *info;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ info = window->geometry_info;
+ if (info)
+ {
+ GdkWindowHints flags = info->last.flags;
+ GdkGeometry *geometry = &info->last.geometry;
+
+ gtk_window_constrain_size (window,
+ geometry,
+ flags,
+ width,
+ height,
+ new_width,
+ new_height);
+ }
+}
+
static void
gtk_window_constrain_size (GtkWindow *window,
GdkGeometry *geometry,
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
ux = 0;
uy = 0;
- aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
- if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
+ aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+ if (aux_info && aux_info->x_set && aux_info->y_set)
{
ux = aux_info->x;
uy = aux_info->y;
if (*new_flags & GDK_HINT_MIN_SIZE)
{
- new_geometry->min_width += extra_width;
- new_geometry->min_height += extra_height;
+ if (new_geometry->min_width < 0)
+ new_geometry->min_width = requisition.width;
+ else
+ new_geometry->min_width += extra_width;
+
+ if (new_geometry->min_height < 0)
+ new_geometry->min_width = requisition.height;
+ else
+ new_geometry->min_height += extra_height;
}
else if (!window->allow_shrink)
{
if (*new_flags & GDK_HINT_MAX_SIZE)
{
- new_geometry->max_width += extra_width;
- new_geometry->max_height += extra_height;
+ if (new_geometry->max_width < 0)
+ new_geometry->max_width = requisition.width;
+ else
+ new_geometry->max_width += extra_width;
+
+ if (new_geometry->max_height < 0)
+ new_geometry->max_width = requisition.height;
+ else
+ new_geometry->max_height += extra_height;
}
else if (!window->allow_grow)
{
new_geometry->max_width = requisition.width;
new_geometry->max_height = requisition.height;
}
+
+ *new_flags |= GDK_HINT_WIN_GRAVITY;
+ new_geometry->win_gravity = window->gravity;
}
/* Compute a new position for the window based on a new
- * size. *x and *y will be set to the new coordinates, or to -1 if the
- * window does not need to be moved
+ * size. *x and *y will be set to the new coordinates. Returns
+ * TRUE if the window needs to be moved (and thus x and y got
+ * assigned)
*/
-static void
-gtk_window_compute_reposition (GtkWindow *window,
- gint new_width,
- gint new_height,
- gint *x,
- gint *y)
+static gint
+gtk_window_compute_reposition (GtkWindow *window,
+ gint new_width,
+ gint new_height,
+ gint *x,
+ gint *y)
{
- GtkWidget *widget;
-
- widget = GTK_WIDGET (window);
+ GtkWidget *widget = GTK_WIDGET (window);
+ GtkWindowPosition pos;
+ GtkWidget *parent_widget;
+ gboolean needs_move = FALSE;
- *x = -1;
- *y = -1;
+ parent_widget = (GtkWidget*) window->transient_parent;
- switch (window->position)
- {
+ pos = window->position;
+ if (pos == GTK_WIN_POS_CENTER_ON_PARENT &&
+ (parent_widget == NULL ||
+ !GTK_WIDGET_MAPPED (parent_widget)))
+ pos = GTK_WIN_POS_NONE;
+
+ switch (pos)
+ {
case GTK_WIN_POS_CENTER:
case GTK_WIN_POS_CENTER_ALWAYS:
if (window->use_uposition)
*x = (screen_width - new_width) / 2;
*y = (screen_height - new_height) / 2;
+ needs_move = TRUE;
+ }
+ break;
+
+ case GTK_WIN_POS_CENTER_ON_PARENT:
+ if (window->use_uposition)
+ {
+ gint ox, oy;
+ gdk_window_get_origin (parent_widget->window,
+ &ox, &oy);
+
+ *x = ox + (parent_widget->allocation.width - new_width) / 2;
+ *y = oy + (parent_widget->allocation.height - new_height) / 2;
+ needs_move = TRUE;
}
break;
+
case GTK_WIN_POS_MOUSE:
if (window->use_uposition)
{
*y -= new_height / 2;
*x = CLAMP (*x, 0, screen_width - new_width);
*y = CLAMP (*y, 0, screen_height - new_height);
+ needs_move = TRUE;
}
break;
default:
if (window->use_uposition)
{
- GtkWidgetAuxInfo *aux_info;
-
- aux_info = gtk_object_get_data (GTK_OBJECT (window), "gtk-aux-info");
- if (aux_info &&
- aux_info->x != -1 && aux_info->y != -1 &&
- aux_info->x != -2 && aux_info->y != -2)
+ GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+
+ if (aux_info && aux_info->x_set && aux_info->y_set)
{
*x = aux_info->x;
*y = aux_info->y;
+ needs_move = TRUE;
}
}
break;
}
- if (*x != -1 && *y != -1)
+ if (needs_move)
{
- GtkWidgetAuxInfo *aux_info;
-
+ GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, TRUE);
+
/* we handle necessary window positioning by hand here,
* so we can coalesce the window movement with possible
* resizes to get only one configure event.
- * keep this in sync with gtk_widget_set_uposition()
- * and gtk_window_reposition().
*/
- gtk_widget_set_uposition (widget, -1, -1); /* ensure we have aux_info */
-
- aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
+ aux_info->x_set = TRUE;
+ aux_info->y_set = TRUE;
aux_info->x = *x;
aux_info->y = *y;
-
window->use_uposition = FALSE;
}
+
+ return needs_move;
}
/***********************
return TRUE;
}
-static void
-gtk_window_draw (GtkWidget *widget,
- GdkRectangle *area)
+/**
+ * gtk_window_set_has_frame:
+ * @window: a #GtkWindow
+ *
+ * If this function is called on a window before it is realized
+ * or showed it will have a "frame" window around widget-window,
+ * accessible in window->frame. Using the signal frame_event
+ * you can recieve all events targeted at the frame.
+ *
+ * This function is used by the linux-fb port to implement managed
+ * windows, but it could concievably be used by X-programs that
+ * want to do their own window decorations.
+ **/
+void
+gtk_window_set_has_frame (GtkWindow *window)
{
- if (!GTK_WIDGET_APP_PAINTABLE (widget))
- gtk_window_paint (widget, area);
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (!GTK_WIDGET_REALIZED (window));
+
+ window->has_frame = TRUE;
+}
+
+/**
+ * gtk_window_set_frame_dimensions:
+ * @window: a #GtkWindow that has a frame
+ * @left: The width of the left border
+ * @top: The height of the top border
+ * @right: The width of the right border
+ * @bottom: The height of the bottom border
+ *
+ * For windows with frames (see #gtk_window_set_has_frame) this function
+ * can be used to change the size of the frame border.
+ **/
+void
+gtk_window_set_frame_dimensions (GtkWindow *window,
+ gint left,
+ gint top,
+ gint right,
+ gint bottom)
+{
+ GtkWidget *widget = GTK_WIDGET (window);
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (window->frame_left == left &&
+ window->frame_top == top &&
+ window->frame_right == right &&
+ window->frame_bottom == bottom)
+ return;
+
+ window->frame_left = left;
+ window->frame_top = top;
+ window->frame_right = right;
+ window->frame_bottom = bottom;
+
+ if (GTK_WIDGET_REALIZED (widget) && window->frame)
+ {
+ gint width = widget->allocation.width + left + right;
+ gint height = widget->allocation.height + top + bottom;
+ gdk_window_resize (window->frame, width, height);
+ gtk_decorated_window_move_resize_window (window,
+ left, top,
+ widget->allocation.width,
+ widget->allocation.height);
+ }
+}
+
+
+
+/**
+ * gtk_window_present:
+ * @window: a #GtkWindow
+ *
+ * Presents a window to the user. This may mean raising the window
+ * in the stacking order, deiconifying it, moving it to the current
+ * desktop, and/or giving it the keyboard focus, possibly dependent
+ * on the user's platform, window manager, and preferences.
+ *
+ * If @window is hidden, this function calls gtk_widget_show()
+ * as well.
+ *
+ * This function should be used when the user tries to open a window
+ * that's already open. Say for example the preferences dialog is
+ * currently open, and the user chooses Preferences from the menu
+ * a second time; use gtk_window_present() to move the already-open dialog
+ * where the user can see it.
+ *
+ **/
+void
+gtk_window_present (GtkWindow *window)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ if (GTK_WIDGET_VISIBLE (window))
+ {
+ g_assert (widget->window != NULL);
+
+ gdk_window_show (widget->window);
+
+ /* note that gdk_window_focus() will also move the window to
+ * the current desktop, for WM spec compliant window managers.
+ */
+ gdk_window_focus (widget->window,
+ gtk_get_current_event_time ());
+ }
+ else
+ {
+ gtk_widget_show (widget);
+ }
+}
+
+/**
+ * gtk_window_iconify:
+ * @window: a #GtkWindow
+ *
+ * Asks to iconify @window. Note that you shouldn't assume the window
+ * is definitely iconified afterward, because other entities (e.g. the
+ * user or window manager) could deiconify it again, or there may not
+ * be a window manager in which case iconification isn't possible,
+ * etc. But normally the window will end up iconified. Just don't write
+ * code that crashes if not.
+ *
+ * It's permitted to call this function before showing a window,
+ * in which case the window will be iconified before it ever appears
+ * onscreen.
+ *
+ * You can track iconification via the "window_state_event" signal
+ * on #GtkWidget.
+ *
+ **/
+void
+gtk_window_iconify (GtkWindow *window)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ window->iconify_initially = TRUE;
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (toplevel != NULL)
+ gdk_window_iconify (toplevel);
+}
+
+/**
+ * gtk_window_deiconify:
+ * @window: a #GtkWindow
+ *
+ * Asks to deiconify @window. Note that you shouldn't assume the
+ * window is definitely deiconified afterward, because other entities
+ * (e.g. the user or window manager) could iconify it again before
+ * your code which assumes deiconification gets to run.
+ *
+ * You can track iconification via the "window_state_event" signal
+ * on #GtkWidget.
+ **/
+void
+gtk_window_deiconify (GtkWindow *window)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ window->iconify_initially = FALSE;
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (toplevel != NULL)
+ gdk_window_deiconify (toplevel);
+}
+
+/**
+ * gtk_window_stick:
+ * @window: a #GtkWindow
+ *
+ * Asks to stick @window, which means that it will appear on all user
+ * desktops. Note that you shouldn't assume the window is definitely
+ * stuck afterward, because other entities (e.g. the user or window
+ * manager) could unstick it again, and some window managers do not
+ * support sticking windows. But normally the window will end up
+ * stuck. Just don't write code that crashes if not.
+ *
+ * It's permitted to call this function before showing a window.
+ *
+ * You can track stickiness via the "window_state_event" signal
+ * on #GtkWidget.
+ *
+ **/
+void
+gtk_window_stick (GtkWindow *window)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ window->stick_initially = TRUE;
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (toplevel != NULL)
+ gdk_window_stick (toplevel);
+}
+
+/**
+ * gtk_window_unstick:
+ * @window: a #GtkWindow
+ *
+ * Asks to unstick @window, which means that it will appear on only
+ * one of the user's desktops. Note that you shouldn't assume the
+ * window is definitely unstuck afterward, because other entities
+ * (e.g. the user or window manager) could stick it again. But
+ * normally the window will end up stuck. Just don't write code that
+ * crashes if not.
+ *
+ * You can track stickiness via the "window_state_event" signal
+ * on #GtkWidget.
+ *
+ **/
+void
+gtk_window_unstick (GtkWindow *window)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ window->stick_initially = FALSE;
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (toplevel != NULL)
+ gdk_window_unstick (toplevel);
+}
+
+/**
+ * gtk_window_maximize:
+ * @window: a #GtkWindow
+ *
+ * Asks to maximize @window, so that it becomes full-screen. Note that
+ * you shouldn't assume the window is definitely maximized afterward,
+ * because other entities (e.g. the user or window manager) could
+ * unmaximize it again, and not all window managers support
+ * maximization. But normally the window will end up maximized. Just
+ * don't write code that crashes if not.
+ *
+ * It's permitted to call this function before showing a window,
+ * in which case the window will be maximized when it appears onscreen
+ * initially.
+ *
+ * You can track maximization via the "window_state_event" signal
+ * on #GtkWidget.
+ *
+ **/
+void
+gtk_window_maximize (GtkWindow *window)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ window->maximize_initially = TRUE;
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (toplevel != NULL)
+ gdk_window_maximize (toplevel);
+}
+
+/**
+ * gtk_window_unmaximize:
+ * @window: a #GtkWindow
+ *
+ * Asks to unmaximize @window. Note that you shouldn't assume the
+ * window is definitely unmaximized afterward, because other entities
+ * (e.g. the user or window manager) could maximize it again, and not
+ * all window managers honor requests to unmaximize. But normally the
+ * window will end up unmaximized. Just don't write code that crashes
+ * if not.
+ *
+ * You can track maximization via the "window_state_event" signal
+ * on #GtkWidget.
+ *
+ **/
+void
+gtk_window_unmaximize (GtkWindow *window)
+{
+ GtkWidget *widget;
+ GdkWindow *toplevel;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ widget = GTK_WIDGET (window);
+
+ window->maximize_initially = FALSE;
+
+ if (window->frame)
+ toplevel = window->frame;
+ else
+ toplevel = widget->window;
+
+ if (toplevel != NULL)
+ gdk_window_unmaximize (toplevel);
+}
+
+/**
+ * gtk_window_set_resizeable:
+ * @window: a #GtkWindow
+ * @resizeable: %TRUE if the user can resize this window
+ *
+ * Sets whether the user can resize a window. Windows are user resizeable
+ * by default.
+ **/
+void
+gtk_window_set_resizeable (GtkWindow *window,
+ gboolean resizeable)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ gtk_window_set_policy (window, FALSE, resizeable, FALSE);
+}
+
+/**
+ * gtk_window_get_resizeable:
+ * @window: a #GtkWindow
+ *
+ * Gets the value set by gtk_window_set_resizeable().
+ *
+ * Return value: %TRUE if the user can resize the window
+ **/
+gboolean
+gtk_window_get_resizeable (GtkWindow *window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ /* allow_grow is most likely to indicate the semantic concept we
+ * mean by "resizeable" (and will be a reliable indicator if
+ * set_policy() hasn't been called)
+ */
+ return window->allow_grow;
+}
+
+/**
+ * gtk_window_set_gravity:
+ * @window: a #GtkWindow
+ * @gravity: window gravity
+ *
+ * Window gravity defines the "reference point" to be used when
+ * positioning or resizing a window. Calls to
+ * gtk_widget_set_uposition() will position a different point on the
+ * window depending on the window gravity. When the window changes size
+ * the reference point determined by the window's gravity will stay in
+ * a fixed location.
+ *
+ * See #GdkGravity for full details. To briefly summarize,
+ * #GDK_GRAVITY_NORTH_WEST means that the reference point is the
+ * northwest (top left) corner of the window
+ * frame. #GDK_GRAVITY_SOUTH_EAST would be the bottom right corner of
+ * the frame, and so on. If you want to position the window contents,
+ * rather than the window manager's frame, #GDK_GRAVITY_STATIC moves
+ * the reference point to the northwest corner of the #GtkWindow
+ * itself.
+ *
+ * The default window gravity is #GDK_GRAVITY_NORTH_WEST.
+ *
+ **/
+void
+gtk_window_set_gravity (GtkWindow *window,
+ GdkGravity gravity)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (gravity != window->gravity)
+ {
+ window->gravity = gravity;
+
+ /* gtk_window_move_resize() will adapt gravity
+ */
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+ }
+}
+
+/**
+ * gtk_window_get_gravity:
+ * @window: a #GtkWindow
+ *
+ * Gets the value set by gtk_window_set_gravity().
+ *
+ * Return value: window gravity
+ **/
+GdkGravity
+gtk_window_get_gravity (GtkWindow *window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
+
+ return window->gravity;
+}
+
+/**
+ * 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:
+ * @window: a #GtkWindow
+ * @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;
- if (GTK_WIDGET_CLASS (parent_class)->draw)
- (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
+ gdk_window_begin_move_drag (toplevel,
+ button,
+ root_x, root_y,
+ timestamp);
}