* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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
+ * 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 <string.h>
#include <limits.h>
#include "gdk/gdk.h"
#include "gdk/gdkkeysyms.h"
-#include "gdk/gdkx.h"
+#include "gdkx.h" /* For gdk_progclass */
#include "gtkprivate.h"
+#include "gtkrc.h"
#include "gtksignal.h"
#include "gtkwindow.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
enum {
- MOVE_RESIZE,
SET_FOCUS,
LAST_SIGNAL
};
ARG_AUTO_SHRINK,
ARG_ALLOW_SHRINK,
ARG_ALLOW_GROW,
- ARG_WIN_POS
+ ARG_MODAL,
+ ARG_WIN_POS,
+ ARG_DEFAULT_WIDTH,
+ ARG_DEFAULT_HEIGHT
};
-typedef gint (*GtkWindowSignal1) (GtkObject *object,
- gpointer arg1,
- gpointer arg2,
- gint arg3,
- gint arg4,
- gpointer data);
-typedef void (*GtkWindowSignal2) (GtkObject *object,
- gpointer arg1,
- gpointer data);
-
-static void gtk_window_marshal_signal_1 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args);
-static void gtk_window_marshal_signal_2 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args);
+typedef struct {
+ GdkGeometry geometry; /* Last set of geometry hints we set */
+ GdkWindowHints flags;
+ gint width;
+ gint height;
+} GtkWindowLastGeometryInfo;
+
+typedef struct {
+ /* Properties that the app has set on the window
+ */
+ GdkGeometry geometry; /* Geometry hints */
+ GdkWindowHints mask;
+ GtkWidget *widget; /* subwidget to which hints apply */
+ gint width; /* Default size */
+ gint height;
+
+ GtkWindowLastGeometryInfo last;
+} GtkWindowGeometryInfo;
+
static void gtk_window_class_init (GtkWindowClass *klass);
static void gtk_window_init (GtkWindow *window);
-static void gtk_window_set_arg (GtkWindow *window,
+static void gtk_window_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
-static void gtk_window_get_arg (GtkWindow *window,
+static void gtk_window_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
+static void gtk_window_shutdown (GtkObject *object);
static void gtk_window_destroy (GtkObject *object);
static void gtk_window_finalize (GtkObject *object);
static void gtk_window_show (GtkWidget *widget);
GtkRequisition *requisition);
static void gtk_window_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
-static gint gtk_window_expose_event (GtkWidget *widget,
- GdkEventExpose *event);
static gint gtk_window_configure_event (GtkWidget *widget,
GdkEventConfigure *event);
static gint gtk_window_key_press_event (GtkWidget *widget,
GdkEventFocus *event);
static gint gtk_window_client_event (GtkWidget *widget,
GdkEventClient *event);
-static gint gtk_window_need_resize (GtkContainer *container);
-static gint gtk_real_window_move_resize (GtkWindow *window,
- gint *x,
- gint *y,
- gint width,
- gint height);
-static void gtk_real_window_set_focus (GtkWindow *window,
+static void gtk_window_check_resize (GtkContainer *container);
+static void gtk_window_real_set_focus (GtkWindow *window,
GtkWidget *focus);
-static gint gtk_window_move_resize (GtkWidget *widget);
-static void gtk_window_set_hints (GtkWidget *widget,
- GtkRequisition *requisition);
-static gint gtk_window_check_accelerator (GtkWindow *window,
- gint key,
- guint mods);
+static void gtk_window_move_resize (GtkWindow *window);
+static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
+ guint flags_a,
+ GdkGeometry *geometry_b,
+ guint flags_b);
+static void gtk_window_compute_default_size (GtkWindow *window,
+ guint *width,
+ guint *height);
+static void gtk_window_constrain_size (GtkWindow *window,
+ GdkGeometry *geometry,
+ guint flags,
+ gint width,
+ gint height,
+ gint *new_width,
+ gint *new_height);
+static void gtk_window_compute_hints (GtkWindow *window,
+ GdkGeometry *new_geometry,
+ guint *new_flags);
+static void gtk_window_compute_reposition (GtkWindow *window,
+ gint new_width,
+ gint new_height,
+ gint *x,
+ gint *y);
+
+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,
+ GdkEventExpose *event);
+static void gtk_window_unset_transient_for (GtkWindow *window);
+static void gtk_window_transient_parent_realized (GtkWidget *parent,
+ GtkWidget *window);
+static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
+ GtkWidget *window);
+
+static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
+ gboolean create);
+static void gtk_window_geometry_destroy (GtkWindowGeometryInfo *info);
static GtkBinClass *parent_class = NULL;
-static gint window_signals[LAST_SIGNAL] = { 0 };
+static guint window_signals[LAST_SIGNAL] = { 0 };
-guint
-gtk_window_get_type ()
+GtkType
+gtk_window_get_type (void)
{
- static guint window_type = 0;
+ static GtkType window_type = 0;
if (!window_type)
{
- GtkTypeInfo window_info =
+ static const GtkTypeInfo window_info =
{
"GtkWindow",
sizeof (GtkWindow),
sizeof (GtkWindowClass),
(GtkClassInitFunc) gtk_window_class_init,
(GtkObjectInitFunc) gtk_window_init,
- (GtkArgSetFunc) gtk_window_set_arg,
- (GtkArgGetFunc) gtk_window_get_arg,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
};
window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
parent_class = gtk_type_class (gtk_bin_get_type ());
- gtk_object_add_arg_type ("GtkWindow::type", GTK_TYPE_WINDOW_TYPE, ARG_TYPE);
- gtk_object_add_arg_type ("GtkWindow::title", GTK_TYPE_STRING, ARG_TITLE);
- gtk_object_add_arg_type ("GtkWindow::auto_shrink", GTK_TYPE_BOOL, ARG_AUTO_SHRINK);
- gtk_object_add_arg_type ("GtkWindow::allow_shrink", GTK_TYPE_BOOL, ARG_ALLOW_SHRINK);
- gtk_object_add_arg_type ("GtkWindow::allow_grow", GTK_TYPE_BOOL, ARG_ALLOW_GROW);
- gtk_object_add_arg_type ("GtkWindow::window_position", GTK_TYPE_ENUM, ARG_WIN_POS);
-
- window_signals[MOVE_RESIZE] =
- gtk_signal_new ("move_resize",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
- gtk_window_marshal_signal_1,
- GTK_TYPE_BOOL, 4,
- GTK_TYPE_POINTER, GTK_TYPE_POINTER,
- GTK_TYPE_INT, GTK_TYPE_INT);
-
+ 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);
+
window_signals[SET_FOCUS] =
gtk_signal_new ("set_focus",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (GtkWindowClass, set_focus),
- gtk_window_marshal_signal_2,
+ gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
- GTK_TYPE_POINTER);
+ 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->shutdown = gtk_window_shutdown;
object_class->destroy = gtk_window_destroy;
object_class->finalize = gtk_window_finalize;
widget_class->realize = gtk_window_realize;
widget_class->size_request = gtk_window_size_request;
widget_class->size_allocate = gtk_window_size_allocate;
- widget_class->expose_event = gtk_window_expose_event;
widget_class->configure_event = gtk_window_configure_event;
widget_class->key_press_event = gtk_window_key_press_event;
widget_class->key_release_event = gtk_window_key_release_event;
widget_class->focus_out_event = gtk_window_focus_out_event;
widget_class->client_event = gtk_window_client_event;
- container_class->need_resize = gtk_window_need_resize;
+ widget_class->draw = gtk_window_draw;
+ widget_class->expose_event = gtk_window_expose;
+
+ container_class->check_resize = gtk_window_check_resize;
- klass->move_resize = gtk_real_window_move_resize;
- klass->set_focus = gtk_real_window_set_focus;
+ klass->set_focus = gtk_window_real_set_focus;
}
static void
GTK_WIDGET_UNSET_FLAGS (window, GTK_NO_WINDOW);
GTK_WIDGET_SET_FLAGS (window, GTK_TOPLEVEL);
+ gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE);
+
window->title = NULL;
- window->wmclass_name = NULL;
- window->wmclass_class = NULL;
+ window->wmclass_name = g_strdup (g_get_prgname ());
+ window->wmclass_class = g_strdup (gdk_progclass);
window->type = GTK_WINDOW_TOPLEVEL;
- window->accelerator_tables = NULL;
window->focus_widget = NULL;
window->default_widget = NULL;
window->resize_count = 0;
- window->need_resize = FALSE;
window->allow_shrink = FALSE;
window->allow_grow = TRUE;
window->auto_shrink = FALSE;
window->handling_resize = FALSE;
window->position = GTK_WIN_POS_NONE;
window->use_uposition = TRUE;
+ window->modal = FALSE;
gtk_container_register_toplevel (GTK_CONTAINER (window));
}
static void
-gtk_window_set_arg (GtkWindow *window,
+gtk_window_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id)
{
+ GtkWindow *window;
+
+ window = GTK_WINDOW (object);
+
switch (arg_id)
{
case ARG_TYPE:
break;
case ARG_AUTO_SHRINK:
window->auto_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
+ gtk_widget_queue_resize (GTK_WIDGET (window));
break;
case ARG_ALLOW_SHRINK:
window->allow_shrink = (GTK_VALUE_BOOL (*arg) != FALSE);
+ gtk_widget_queue_resize (GTK_WIDGET (window));
break;
case ARG_ALLOW_GROW:
window->allow_grow = (GTK_VALUE_BOOL (*arg) != FALSE);
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+ break;
+ case ARG_MODAL:
+ gtk_window_set_modal (window, GTK_VALUE_BOOL (*arg));
break;
case ARG_WIN_POS:
- gtk_window_position (window, GTK_VALUE_ENUM (*arg));
+ gtk_window_set_position (window, GTK_VALUE_ENUM (*arg));
+ break;
+ case ARG_DEFAULT_WIDTH:
+ gtk_window_set_default_size (window, GTK_VALUE_INT (*arg), -2);
+ break;
+ case ARG_DEFAULT_HEIGHT:
+ gtk_window_set_default_size (window, -2, GTK_VALUE_INT (*arg));
break;
default:
- arg->type = GTK_TYPE_INVALID;
break;
}
}
static void
-gtk_window_get_arg (GtkWindow *window,
+gtk_window_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id)
{
+ GtkWindow *window;
+
+ window = GTK_WINDOW (object);
+
switch (arg_id)
{
+ GtkWindowGeometryInfo *info;
case ARG_TYPE:
GTK_VALUE_ENUM (*arg) = window->type;
break;
case ARG_ALLOW_GROW:
GTK_VALUE_BOOL (*arg) = window->allow_grow;
break;
+ case ARG_MODAL:
+ GTK_VALUE_BOOL (*arg) = window->modal;
+ break;
case ARG_WIN_POS:
GTK_VALUE_ENUM (*arg) = window->position;
break;
+ case ARG_DEFAULT_WIDTH:
+ info = gtk_window_get_geometry_info (window, FALSE);
+ if (!info)
+ GTK_VALUE_INT (*arg) = -1;
+ else
+ GTK_VALUE_INT (*arg) = info->width;
+ break;
+ case ARG_DEFAULT_HEIGHT:
+ info = gtk_window_get_geometry_info (window, FALSE);
+ if (!info)
+ GTK_VALUE_INT (*arg) = -1;
+ else
+ GTK_VALUE_INT (*arg) = info->height;
+ break;
default:
arg->type = GTK_TYPE_INVALID;
break;
{
GtkWindow *window;
- window = gtk_type_new (gtk_window_get_type ());
+ g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
+
+ window = gtk_type_new (GTK_TYPE_WINDOW);
window->type = type;
void
gtk_window_set_wmclass (GtkWindow *window,
- gchar *wmclass_name,
- gchar *wmclass_class)
+ const gchar *wmclass_name,
+ const gchar *wmclass_class)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
- if (window->wmclass_name)
- g_free (window->wmclass_name);
+ g_free (window->wmclass_name);
window->wmclass_name = g_strdup (wmclass_name);
- if (window->wmclass_class)
- g_free (window->wmclass_class);
+ g_free (window->wmclass_class);
window->wmclass_class = g_strdup (wmclass_class);
if (GTK_WIDGET_REALIZED (window))
gtk_window_set_focus (GtkWindow *window,
GtkWidget *focus)
{
- gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ if (focus)
+ {
+ g_return_if_fail (GTK_IS_WIDGET (focus));
+ g_return_if_fail (GTK_WIDGET_CAN_FOCUS (focus));
+ }
+
+ if ((window->focus_widget != focus) ||
+ (focus && !GTK_WIDGET_HAS_FOCUS (focus)))
+ gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
}
void
gtk_window_set_default (GtkWindow *window,
- GtkWidget *defaultw)
+ GtkWidget *default_widget)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
- g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (defaultw));
- if (window->default_widget != defaultw)
+ if (default_widget)
+ g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (default_widget));
+
+ if (window->default_widget != default_widget)
{
if (window->default_widget)
{
gtk_widget_draw_default (window->default_widget);
}
- window->default_widget = defaultw;
+ window->default_widget = default_widget;
if (window->default_widget)
{
window->allow_shrink = (allow_shrink != FALSE);
window->allow_grow = (allow_grow != FALSE);
window->auto_shrink = (auto_shrink != FALSE);
+
+ gtk_widget_queue_resize (GTK_WIDGET (window));
}
void
-gtk_window_add_accelerator_table (GtkWindow *window,
- GtkAcceleratorTable *table)
+gtk_window_add_accel_group (GtkWindow *window,
+ GtkAccelGroup *accel_group)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (accel_group != NULL);
- gtk_accelerator_table_ref (table);
- window->accelerator_tables = g_list_prepend (window->accelerator_tables,
- table);
+ gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
}
void
-gtk_window_remove_accelerator_table (GtkWindow *window,
- GtkAcceleratorTable *table)
+gtk_window_remove_accel_group (GtkWindow *window,
+ GtkAccelGroup *accel_group)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (accel_group != NULL);
- window->accelerator_tables = g_list_remove (window->accelerator_tables,
- table);
- gtk_accelerator_table_unref (table);
+ gtk_accel_group_detach (accel_group, GTK_OBJECT (window));
}
void
-gtk_window_position (GtkWindow *window,
- GtkWindowPosition position)
+gtk_window_set_position (GtkWindow *window,
+ GtkWindowPosition position)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GTK_IS_WINDOW (window));
if (window->focus_widget)
{
- gtk_widget_activate (window->focus_widget);
+ if (GTK_WIDGET_IS_SENSITIVE (window->focus_widget))
+ gtk_widget_activate (window->focus_widget);
return TRUE;
}
g_return_val_if_fail (window != NULL, FALSE);
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
- if (window->default_widget)
+ if (window->default_widget && GTK_WIDGET_IS_SENSITIVE (window->default_widget))
{
gtk_widget_activate (window->default_widget);
return TRUE;
return FALSE;
}
+void
+gtk_window_set_modal (GtkWindow *window,
+ gboolean modal)
+{
+ g_return_if_fail (window != NULL);
+ 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));
+}
+
+void
+gtk_window_add_embedded_xid (GtkWindow *window, guint xid)
+{
+ GList *embedded_windows;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
+ if (embedded_windows)
+ gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
+ g_quark_from_static_string ("gtk-embedded"));
+ embedded_windows = g_list_prepend (embedded_windows,
+ GUINT_TO_POINTER (xid));
+
+ gtk_object_set_data_full (GTK_OBJECT (window), "gtk-embedded",
+ embedded_windows,
+ embedded_windows ?
+ (GtkDestroyNotify) g_list_free : NULL);
+}
+
+void
+gtk_window_remove_embedded_xid (GtkWindow *window, guint xid)
+{
+ GList *embedded_windows;
+ GList *node;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
+ if (embedded_windows)
+ gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
+ g_quark_from_static_string ("gtk-embedded"));
+
+ node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
+ if (node)
+ {
+ embedded_windows = g_list_remove_link (embedded_windows, node);
+ g_list_free_1 (node);
+ }
+
+ gtk_object_set_data_full (GTK_OBJECT (window),
+ "gtk-embedded", embedded_windows,
+ embedded_windows ?
+ (GtkDestroyNotify) g_list_free : NULL);
+}
+
+void
+gtk_window_reposition (GtkWindow *window,
+ gint x,
+ gint y)
+{
+ GtkWindowGeometryInfo *info;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ /* keep this in sync with gtk_window_compute_reposition()
+ */
+ if (GTK_WIDGET_REALIZED (window))
+ {
+ info = gtk_window_get_geometry_info (window, TRUE);
+
+ if (!(info->last.flags & GDK_HINT_POS))
+ {
+ info->last.flags |= GDK_HINT_POS;
+ gdk_window_set_geometry_hints (GTK_WIDGET (window)->window,
+ &info->last.geometry,
+ info->last.flags);
+ }
+
+ gdk_window_move (GTK_WIDGET (window)->window, x, y);
+ }
+}
+
static void
-gtk_window_marshal_signal_1 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args)
+gtk_window_shutdown (GtkObject *object)
{
- GtkWindowSignal1 rfunc;
- gint *return_val;
-
- rfunc = (GtkWindowSignal1) func;
- return_val = GTK_RETLOC_BOOL (args[4]);
-
- *return_val = (* rfunc) (object,
- GTK_VALUE_POINTER (args[0]),
- GTK_VALUE_POINTER (args[1]),
- GTK_VALUE_INT (args[2]),
- GTK_VALUE_INT (args[3]),
- func_data);
+ GtkWindow *window;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (object));
+
+ window = GTK_WINDOW (object);
+
+ gtk_window_set_focus (window, NULL);
+ gtk_window_set_default (window, NULL);
+
+ GTK_OBJECT_CLASS (parent_class)->shutdown (object);
+}
+
+static void
+gtk_window_transient_parent_realized (GtkWidget *parent,
+ GtkWidget *window)
+{
+ if (GTK_WIDGET_REALIZED (window))
+ gdk_window_set_transient_for (window->window, parent->window);
+}
+
+static void
+gtk_window_transient_parent_unrealized (GtkWidget *parent,
+ GtkWidget *window)
+{
+ if (GTK_WIDGET_REALIZED (window))
+ gdk_property_delete (window->window,
+ gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
+}
+
+static void
+gtk_window_unset_transient_for (GtkWindow *window)
+{
+ if (window->transient_parent)
+ {
+ gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+ GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
+ window);
+ gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+ GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
+ window);
+ gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &window->transient_parent);
+
+ window->transient_parent = NULL;
+ }
+}
+
+void
+gtk_window_set_transient_for (GtkWindow *window,
+ GtkWindow *parent)
+{
+ g_return_if_fail (window != 0);
+
+ if (window->transient_parent)
+ {
+ if (GTK_WIDGET_REALIZED (window) &&
+ GTK_WIDGET_REALIZED (window->transient_parent) &&
+ (!parent || !GTK_WIDGET_REALIZED (parent)))
+ gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
+ GTK_WIDGET (window));
+
+ gtk_window_unset_transient_for (window);
+ }
+
+ window->transient_parent = parent;
+
+ if (parent)
+ {
+ gtk_signal_connect (GTK_OBJECT (parent), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &window->transient_parent);
+ gtk_signal_connect (GTK_OBJECT (parent), "realize",
+ GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
+ window);
+ gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
+ GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
+ window);
+
+ if (GTK_WIDGET_REALIZED (window) &&
+ GTK_WIDGET_REALIZED (parent))
+ gtk_window_transient_parent_realized (GTK_WIDGET (parent),
+ GTK_WIDGET (window));
+ }
}
static void
-gtk_window_marshal_signal_2 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args)
+gtk_window_geometry_destroy (GtkWindowGeometryInfo *info)
+{
+ if (info->widget)
+ gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &info->widget);
+ g_free (info);
+}
+
+static GtkWindowGeometryInfo*
+gtk_window_get_geometry_info (GtkWindow *window,
+ gboolean create)
{
- GtkWindowSignal2 rfunc;
+ GtkWindowGeometryInfo *info;
+
+ info = gtk_object_get_data (GTK_OBJECT (window), "gtk-window-geometry");
+
+ if (!info && create)
+ {
+ info = g_new0 (GtkWindowGeometryInfo, 1);
+
+ info->width = 0;
+ info->height = 0;
+ info->last.width = -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);
+ }
+
+ return info;
+}
+
+void
+gtk_window_set_geometry_hints (GtkWindow *window,
+ GtkWidget *geometry_widget,
+ GdkGeometry *geometry,
+ GdkWindowHints geom_mask)
+{
+ GtkWindowGeometryInfo *info;
+
+ g_return_if_fail (window != NULL);
+
+ info = gtk_window_get_geometry_info (window, TRUE);
+
+ if (info->widget)
+ gtk_signal_disconnect_by_func (GTK_OBJECT (info->widget),
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &info->widget);
+
+ info->widget = geometry_widget;
+ if (info->widget)
+ gtk_signal_connect (GTK_OBJECT (geometry_widget), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &info->widget);
- rfunc = (GtkWindowSignal2) func;
+ if (geometry)
+ info->geometry = *geometry;
- (* rfunc) (object, GTK_VALUE_POINTER (args[0]), func_data);
+ info->mask = geom_mask;
+
+ gtk_widget_queue_resize (GTK_WIDGET (window));
}
+void
+gtk_window_set_default_size (GtkWindow *window,
+ gint width,
+ gint height)
+{
+ GtkWindowGeometryInfo *info;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ info = gtk_window_get_geometry_info (window, TRUE);
+
+ if (width >= 0)
+ info->width = width;
+ if (height >= 0)
+ info->height = height;
+
+ gtk_widget_queue_resize (GTK_WIDGET (window));
+}
+
static void
gtk_window_destroy (GtkObject *object)
{
+ GtkWindow *window;
+
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_WINDOW (object));
+ window = GTK_WINDOW (object);
+
gtk_container_unregister_toplevel (GTK_CONTAINER (object));
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ if (window->transient_parent)
+ gtk_window_unset_transient_for (window);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void
window = GTK_WINDOW (object);
g_free (window->title);
+ g_free (window->wmclass_name);
+ g_free (window->wmclass_class);
GTK_OBJECT_CLASS(parent_class)->finalize (object);
}
static void
gtk_window_show (GtkWidget *widget)
{
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_WINDOW (widget));
+ GtkWindow *window = GTK_WINDOW (widget);
+ GtkContainer *container = GTK_CONTAINER (window);
+ gboolean need_resize;
GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
- gtk_container_need_resize (GTK_CONTAINER (widget));
+
+ 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;
+
+ /* 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;
+
+ /* constrain size to geometry */
+ gtk_window_compute_hints (window, &new_geometry, &new_flags);
+ gtk_window_constrain_size (window,
+ &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))
+ gdk_window_resize (widget->window, width, height);
+ else
+ gtk_widget_realize (widget);
+ }
+
+ gtk_container_check_resize (container);
+
gtk_widget_map (widget);
+
+ if (window->modal)
+ gtk_grab_add (widget);
}
static void
gtk_window_hide (GtkWidget *widget)
{
+ GtkWindow *window;
+
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WINDOW (widget));
+ window = GTK_WINDOW (widget);
+
GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
gtk_widget_unmap (widget);
+
+ if (window->modal)
+ gtk_grab_remove (widget);
}
static void
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
- gtk_window_move_resize (widget);
window = GTK_WINDOW (widget);
if (window->bin.child &&
!GTK_WIDGET_MAPPED (window->bin.child))
gtk_widget_map (window->bin.child);
- gtk_window_set_hints (widget, &widget->requisition);
gdk_window_show (widget->window);
}
window = GTK_WINDOW (widget);
window->use_uposition = TRUE;
+ window->resize_count = 0;
+ window->handling_resize = FALSE;
}
static void
GtkWindow *window;
GdkWindowAttr attributes;
gint attributes_mask;
-
- g_return_if_fail (widget != NULL);
+
g_return_if_fail (GTK_IS_WINDOW (widget));
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
window = GTK_WINDOW (widget);
+ /* ensure widget tree is properly size allocated */
+ if (widget->allocation.x == -1 &&
+ widget->allocation.y == -1 &&
+ widget->allocation.width == 1 &&
+ widget->allocation.height == 1)
+ {
+ GtkRequisition requisition;
+ GtkAllocation allocation = { 0, 0, 200, 200 };
+
+ gtk_widget_size_request (widget, &requisition);
+ if (requisition.width || requisition.height)
+ {
+ /* non-empty window */
+ allocation.width = requisition.width;
+ allocation.height = requisition.height;
+ }
+ gtk_widget_size_allocate (widget, &allocation);
+
+ gtk_container_queue_resize (GTK_CONTAINER (widget));
+
+ g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
+ }
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
switch (window->type)
{
case GTK_WINDOW_TOPLEVEL:
attributes.window_type = GDK_WINDOW_TEMP;
break;
}
-
+
attributes.title = window->title;
attributes.wmclass_name = window->wmclass_name;
attributes.wmclass_class = window->wmclass_class;
GDK_LEAVE_NOTIFY_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_STRUCTURE_MASK);
-
+
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);
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->transient_parent &&
+ GTK_WIDGET_REALIZED (window->transient_parent))
+ gdk_window_set_transient_for (widget->window,
+ GTK_WIDGET (window->transient_parent)->window);
}
static void
GtkRequisition *requisition)
{
GtkWindow *window;
+ GtkBin *bin;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WINDOW (widget));
g_return_if_fail (requisition != NULL);
window = GTK_WINDOW (widget);
+ bin = GTK_BIN (window);
+
+ requisition->width = GTK_CONTAINER (window)->border_width * 2;
+ requisition->height = GTK_CONTAINER (window)->border_width * 2;
- if (window->bin.child)
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
{
- requisition->width = GTK_CONTAINER (window)->border_width * 2;
- requisition->height = GTK_CONTAINER (window)->border_width * 2;
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (bin->child, &child_requisition);
- gtk_widget_size_request (window->bin.child, &window->bin.child->requisition);
-
- requisition->width += window->bin.child->requisition.width;
- requisition->height += window->bin.child->requisition.height;
- }
- else
- {
- if (!GTK_WIDGET_VISIBLE (window))
- window->need_resize = TRUE;
+ requisition->width += child_requisition.width;
+ requisition->height += child_requisition.height;
}
}
{
child_allocation.x = GTK_CONTAINER (window)->border_width;
child_allocation.y = GTK_CONTAINER (window)->border_width;
- child_allocation.width = allocation->width - child_allocation.x * 2;
- child_allocation.height = allocation->height - child_allocation.y * 2;
+ child_allocation.width =
+ MAX (1, (gint)allocation->width - child_allocation.x * 2);
+ child_allocation.height =
+ MAX (1, (gint)allocation->height - child_allocation.y * 2);
gtk_widget_size_allocate (window->bin.child, &child_allocation);
}
}
-static gint
-gtk_window_expose_event (GtkWidget *widget,
- GdkEventExpose *event)
-{
- 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);
-
- if (GTK_WIDGET_DRAWABLE (widget))
- if (GTK_WIDGET_CLASS (parent_class)->expose_event)
- return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
-
- return FALSE;
-}
-
static gint
gtk_window_configure_event (GtkWidget *widget,
GdkEventConfigure *event)
{
GtkWindow *window;
- GtkAllocation allocation;
-
+
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->handling_resize = TRUE;
-
- allocation.x = 0;
- allocation.y = 0;
- allocation.width = event->width;
- allocation.height = event->height;
- gtk_widget_size_allocate (widget, &allocation);
-
- if (window->bin.child &&
- GTK_WIDGET_VISIBLE (window->bin.child) &&
- !GTK_WIDGET_MAPPED (window->bin.child))
- gtk_widget_map (window->bin.child);
+ /* we got a configure event specifying the new window size and position,
+ * in principle we have to distinguish 4 cases here:
+ * 1) the size didn't change and resize_count == 0
+ * -> the window was merely moved (sometimes not even that)
+ * 2) the size didn't change and resize_count > 0
+ * -> we requested a new size, but didn't get it
+ * 3) the size changed and resize_count > 0
+ * -> we asked for a new size and we got one
+ * 4) the size changed and resize_count == 0
+ * -> we got resized from outside the toolkit, and have to
+ * accept that size since we don't want to fight neither the
+ * window manager nor the user
+ * in the three latter cases we have to reallocate the widget tree,
+ * which happens in gtk_window_move_resize(), so we set a flag for
+ * that function and assign the new size. if resize_count > 1,
+ * we simply do nothing and wait for more configure events.
+ */
- if (window->resize_count > 1)
- window->resize_count -= 1;
- else
+ if (window->resize_count > 0 ||
+ widget->allocation.width != event->width ||
+ widget->allocation.height != event->height)
{
- if ((window->auto_shrink &&
- ((event->width != widget->requisition.width) ||
- (event->height != widget->requisition.height))) ||
- (event->width < widget->requisition.width) ||
- (event->height < widget->requisition.height))
+ if (window->resize_count > 0)
+ window->resize_count -= 1;
+
+ if (window->resize_count == 0)
{
- window->resize_count = 1;
- gdk_window_resize (widget->window,
- widget->requisition.width,
- widget->requisition.height);
+ window->handling_resize = TRUE;
+
+ widget->allocation.width = event->width;
+ widget->allocation.height = event->height;
+
+ gtk_widget_queue_resize (widget);
}
- else
- window->resize_count = 0;
}
-
- window->handling_resize = FALSE;
-
- return FALSE;
+
+ return TRUE;
}
static gint
{
GtkWindow *window;
GtkDirectionType direction = 0;
- gint return_val;
+ gboolean handled;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
window = GTK_WINDOW (widget);
- return_val = FALSE;
- if (window->focus_widget)
- return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
-
- if (!return_val && gtk_window_check_accelerator (window, event->keyval, event->state))
- return_val = TRUE;
+ handled = FALSE;
+
+ 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);
- if (!return_val)
+ if (!handled)
{
switch (event->keyval)
{
case GDK_space:
if (window->focus_widget)
{
- gtk_widget_activate (window->focus_widget);
- return_val = TRUE;
+ 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)
+ 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_val = TRUE;
+ handled = TRUE;
}
else if (window->focus_widget)
{
- gtk_widget_activate (window->focus_widget);
- return_val = TRUE;
+ 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
if (!GTK_CONTAINER (window)->focus_child)
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
else
- return_val = TRUE;
+ handled = TRUE;
break;
}
}
- return return_val;
+ if (!handled && GTK_WIDGET_CLASS (parent_class)->key_press_event)
+ handled = GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
+
+ return handled;
}
static gint
GdkEventKey *event)
{
GtkWindow *window;
- gint return_val;
-
+ gint handled;
+
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);
- return_val = FALSE;
- if (window->focus_widget)
- return_val = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+ handled = FALSE;
+ if (window->focus_widget &&
+ window->focus_widget != widget &&
+ GTK_WIDGET_SENSITIVE (window->focus_widget))
+ {
+ handled = gtk_widget_event (window->focus_widget, (GdkEvent*) event);
+ }
- return return_val;
+ if (!handled && GTK_WIDGET_CLASS (parent_class)->key_release_event)
+ handled = GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
+
+ return handled;
}
static gint
if (GTK_WIDGET_VISIBLE (widget))
{
window = GTK_WINDOW (widget);
- if (window->focus_widget && !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
+ if (window->focus_widget &&
+ window->focus_widget != widget &&
+ !GTK_WIDGET_HAS_FOCUS (window->focus_widget))
{
fevent.type = GDK_FOCUS_CHANGE;
fevent.window = window->focus_widget->window;
g_return_val_if_fail (event != NULL, FALSE);
window = GTK_WINDOW (widget);
- if (window->focus_widget && GTK_WIDGET_HAS_FOCUS (window->focus_widget))
+ if (window->focus_widget &&
+ window->focus_widget != widget &&
+ GTK_WIDGET_HAS_FOCUS (window->focus_widget))
{
fevent.type = GDK_FOCUS_CHANGE;
fevent.window = window->focus_widget->window;
return FALSE;
}
+static GdkAtom atom_rcfiles = GDK_NONE;
+
static void
-gtk_window_style_set_event (GtkWidget *widget,
- GdkEventClient *event)
+gtk_window_read_rcfiles (GtkWidget *widget,
+ GdkEventClient *event)
{
- GdkAtom atom_default_colors;
- GtkStyle *style_newdefault;
- GdkAtom realtype;
- gint retfmt, retlen;
- GdkColor *data, *stylecolors;
- int i = 0;
- GdkColormap *widget_cmap;
-
- atom_default_colors = gdk_atom_intern("_GTK_DEFAULT_COLORS", FALSE);
-
- if(gdk_property_get (GDK_ROOT_PARENT(),
- atom_default_colors,
- gdk_atom_intern("STRING", FALSE),
- 0,
- sizeof(GdkColor) * GTK_STYLE_NUM_STYLECOLORS(),
- FALSE,
- &realtype,
- &retfmt,
- &retlen,
- (guchar **)&data) != TRUE) {
- g_warning("gdk_property_get() failed in _GTK_STYLE_CHANGED handler\n");
- return;
- }
- if(retfmt != sizeof(gushort)*8) {
- g_warning("retfmt (%d) != sizeof(gushort)*8 (%d)\n", retfmt,
- sizeof(gushort)*8);
- return;
- }
- /* We have the color data, now let's interpret it */
- style_newdefault = gtk_widget_get_default_style();
- gtk_style_ref(style_newdefault);
- stylecolors = (GdkColor *) style_newdefault;
-
- widget_cmap = gtk_widget_get_colormap(widget);
- for(i = 0; i < GTK_STYLE_NUM_STYLECOLORS(); i++) {
- stylecolors[i] = data[i];
- gdk_color_alloc(widget_cmap, &stylecolors[i]);
- }
-
- gtk_widget_set_default_style(style_newdefault);
- gtk_style_unref(style_newdefault);
-
- /* Now we need to redraw everything */
- gtk_widget_draw(widget, NULL);
- gtk_widget_draw_children(widget);
+ GList *embedded_windows;
+
+ embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
+ if (embedded_windows)
+ {
+ GdkEventClient sev;
+ int i;
+
+ for(i = 0; i < 5; i++)
+ sev.data.l[i] = 0;
+ sev.data_format = 32;
+ sev.message_type = atom_rcfiles;
+
+ while (embedded_windows)
+ {
+ guint xid = GPOINTER_TO_UINT (embedded_windows->data);
+ gdk_event_send_client_message ((GdkEvent *) &sev, xid);
+ embedded_windows = embedded_windows->next;
+ }
+ }
+
+ if (gtk_rc_reparse_all ())
+ {
+ /* If the above returned true, some of our RC files are out
+ * 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.
+ */
+ GList *toplevels;
+
+ toplevels = gtk_container_get_toplevels();
+ while (toplevels)
+ {
+ gtk_widget_reset_rc_styles (toplevels->data);
+ toplevels = toplevels->next;
+ }
+ }
}
static gint
gtk_window_client_event (GtkWidget *widget,
GdkEventClient *event)
{
- GdkAtom atom_styleset;
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);
- atom_styleset = gdk_atom_intern("_GTK_STYLE_CHANGED", FALSE);
+ if (!atom_rcfiles)
+ atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
+
+ if(event->message_type == atom_rcfiles)
+ gtk_window_read_rcfiles (widget, event);
- if(event->message_type == atom_styleset) {
- gtk_window_style_set_event(widget, event);
- }
return FALSE;
}
-static gint
-gtk_window_need_resize (GtkContainer *container)
+static void
+gtk_window_check_resize (GtkContainer *container)
{
GtkWindow *window;
- gint return_val;
- g_return_val_if_fail (container != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_WINDOW (container), FALSE);
-
- return_val = FALSE;
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (container));
window = GTK_WINDOW (container);
- if (window->handling_resize)
- return return_val;
if (GTK_WIDGET_VISIBLE (container))
+ gtk_window_move_resize (window);
+}
+
+static void
+gtk_window_real_set_focus (GtkWindow *window,
+ GtkWidget *focus)
+{
+ GdkEventFocus event;
+ gboolean def_flags = 0;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ if (window->default_widget)
+ def_flags = GTK_WIDGET_HAS_DEFAULT (window->default_widget);
+
+ if (window->focus_widget)
{
- window->need_resize = TRUE;
- return_val = gtk_window_move_resize (GTK_WIDGET (window));
- window->need_resize = FALSE;
+ 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);
}
+
+ window->focus_widget = focus;
+
+ if (window->focus_widget)
+ {
+ event.type = GDK_FOCUS_CHANGE;
+ event.window = window->focus_widget->window;
+ event.in = TRUE;
- return return_val;
+ 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);
+ }
+ }
+
+ 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 &&
+ (def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
+ gtk_widget_queue_draw (window->default_widget);
}
-static gint
-gtk_real_window_move_resize (GtkWindow *window,
- gint *x,
- gint *y,
- gint width,
- gint height)
+/*********************************
+ * Functions related to resizing *
+ *********************************/
+
+static void
+gtk_window_move_resize (GtkWindow *window)
{
GtkWidget *widget;
- GtkWidget *resize_container, *child;
- GSList *resize_containers;
- GSList *tmp_list;
- gint return_val;
-
- g_return_val_if_fail (window != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
- g_return_val_if_fail ((x != NULL) || (y != NULL), FALSE);
+ GtkContainer *container;
+ GtkWindowGeometryInfo *info;
+ GtkWindowLastGeometryInfo saved_last_info;
+ GdkGeometry new_geometry;
+ guint new_flags;
+ gint x, y;
+ gint width, height;
+ gint new_width, new_height;
+ gboolean default_size_changed = FALSE;
+ gboolean hints_changed = FALSE;
- return_val = FALSE;
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_WIDGET_REALIZED (window));
widget = GTK_WIDGET (window);
+ container = GTK_CONTAINER (widget);
+ info = gtk_window_get_geometry_info (window, TRUE);
+ saved_last_info = info->last;
- if ((*x != -1) && (*y != -1))
- gdk_window_move (widget->window, *x, *y);
+ gtk_widget_size_request (widget, NULL);
+ gtk_window_compute_default_size (window, &new_width, &new_height);
+
+ if (info->last.width < 0 ||
+ info->last.width != new_width ||
+ info->last.height != new_height)
+ {
+ default_size_changed = TRUE;
+ info->last.width = new_width;
+ info->last.height = new_height;
- if ((widget->requisition.width == 0) ||
- (widget->requisition.height == 0))
+ /* We need to force a reposition in this case
+ */
+ if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
+ window->use_uposition = TRUE;
+ }
+
+ /* Compute new set of hints for the window
+ */
+ gtk_window_compute_hints (window, &new_geometry, &new_flags);
+ if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags,
+ &new_geometry, new_flags))
{
- widget->requisition.width = 200;
- widget->requisition.height = 200;
+ hints_changed = TRUE;
+ info->last.geometry = new_geometry;
+ info->last.flags = new_flags;
}
- gdk_window_get_geometry (widget->window, NULL, NULL, &width, &height, NULL);
-
- resize_containers = NULL;
-
- if ((window->auto_shrink &&
- ((width != widget->requisition.width) ||
- (height != widget->requisition.height))) ||
- (width < widget->requisition.width) ||
- (height < widget->requisition.height))
+ /* From the default size and the allocation, figure out the size
+ * the window should be.
+ */
+ if (!default_size_changed ||
+ (!window->auto_shrink &&
+ new_width <= widget->allocation.width &&
+ new_height <= widget->allocation.height))
{
- if (window->resize_count == 0)
- {
- window->resize_count = 1;
- gdk_window_resize (widget->window,
- widget->requisition.width,
- widget->requisition.height);
- }
+ new_width = widget->allocation.width;
+ new_height = widget->allocation.height;
}
- else
- {
- /* The window hasn't changed size but one of its children
- * queued a resize request. Which means that the allocation
- * is not sufficient for the requisition of some child.
- * We've already performed a size request at this point,
- * so we simply need to run through the list of resize
- * widgets and reallocate their sizes appropriately. We
- * make the optimization of not performing reallocation
- * for a widget who also has a parent in the resize widgets
- * list. GTK_RESIZE_NEEDED is used for flagging those
- * parents inside this function.
- */
- GSList *resize_widgets, *node;
- resize_widgets = GTK_CONTAINER (window)->resize_widgets;
- GTK_CONTAINER (window)->resize_widgets = NULL;
+ /* constrain the window size to the specified geometry */
+ gtk_window_constrain_size (window,
+ &new_geometry, new_flags,
+ new_width, new_height,
+ &new_width, &new_height);
- for (node = resize_widgets; node; node = node->next)
- {
- child = (GtkWidget *)node->data;
-
- GTK_PRIVATE_UNSET_FLAG (child, GTK_RESIZE_NEEDED);
+ /* 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))
+ {
+ new_flags |= GDK_HINT_POS;
+ hints_changed = TRUE;
+ }
- widget = child->parent;
- while (widget &&
- ((widget->allocation.width < widget->requisition.width) ||
- (widget->allocation.height < widget->requisition.height)))
- widget = widget->parent;
- if (widget)
- GTK_PRIVATE_SET_FLAG (widget, GTK_RESIZE_NEEDED);
- }
+ /* handle actual resizing:
+ * - handle reallocations due to configure events
+ * - figure whether we need to request a new window size
+ * - handle simple resizes within our widget tree
+ * - reposition window if neccessary
+ */
+ width = widget->allocation.width;
+ height = widget->allocation.height;
- for (node = resize_widgets; node; node = node->next)
+ if (window->handling_resize)
+ {
+ GtkAllocation allocation;
+
+ /* if we are just responding to a configure event, which
+ * might be due to a resize by the window manager, the
+ * user, or a response to a resizing request we made
+ * earlier, we go ahead, allocate the new size and we're done
+ * (see gtk_window_configure_event() for more details).
+ */
+
+ window->handling_resize = FALSE;
+
+ allocation = widget->allocation;
+
+ 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))
{
- child = (GtkWidget *)node->data;
-
- resize_container = child->parent;
- while (resize_container &&
- !GTK_WIDGET_RESIZE_NEEDED (resize_container))
- resize_container = resize_container->parent;
-
- if (resize_container)
- widget = resize_container->parent;
- else
- widget = NULL;
-
- while (widget)
- {
- if (GTK_WIDGET_RESIZE_NEEDED (widget))
- {
- GTK_PRIVATE_UNSET_FLAG (resize_container, GTK_RESIZE_NEEDED);
- resize_container = widget;
- }
- widget = widget->parent;
- }
-
- if (resize_container &&
- !g_slist_find (resize_containers, resize_container))
- resize_containers = g_slist_prepend (resize_containers,
- resize_container);
+ /* We could be here for two reasons
+ * 1) We coincidentally got a resize while handling
+ * 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.
+ *
+ * For 1), we could just go ahead and ask for the
+ * new size right now, but doing that for 2)
+ * might well be fighting the user (and can even
+ * trigger a loop). Since we really don't want to
+ * do that, we requeue a resize in hopes that
+ * by the time it gets handled, the child has seen
+ * the light and is willing to go along with the
+ * new size. (this happens for the zvt widget, since
+ * the size_allocate() above will have stored the
+ * requisition corresponding to the new size in the
+ * zvt widget)
+ *
+ * This doesn't buy us anything for 1), but it shouldn't
+ * hurt us too badly, since it is what would have
+ * happened if we had gotten the configure event before
+ * the new size had been set.
+ */
+
+ if (x != -1 && y != -1)
+ gdk_window_move (widget->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 */
+ }
- g_slist_free (resize_widgets);
-
- tmp_list = resize_containers;
- while (tmp_list)
- {
- widget = tmp_list->data;
- tmp_list = tmp_list->next;
-
- GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED);
- gtk_widget_size_allocate (widget, &widget->allocation);
- gtk_widget_queue_draw (widget);
- }
+ /* Now set hints if necessary
+ */
+ if (hints_changed)
+ gdk_window_set_geometry_hints (widget->window,
+ &new_geometry,
+ new_flags);
- g_slist_free (resize_containers);
+ if ((default_size_changed || hints_changed) &&
+ (width != new_width || height != new_height))
+ {
+ /* given that (width != new_width || height != new_height), we are in one
+ * of the following situations:
+ *
+ * default_size_changed
+ * our requisition has changed and we need a different window size,
+ * so we request it from the window manager.
+ *
+ * !default_size_changed
+ * the window manager wouldn't assign us the size we requested, in this
+ * case we don't try to request a new size with every resize.
+ *
+ * !default_size_changed && hints_changed
+ * the window manager rejects our size, but we have just changed the
+ * window manager hints, so there's a certain chance our request will
+ * be honoured this time, so we try again.
+ */
+
+ /* request a new window size */
+ if (x != -1 && y != -1)
+ 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);
+ window->resize_count += 1;
+
+ /* we are now awaiting the new configure event in response to our
+ * resizing request. the configure event will cause a new resize
+ * with ->handling_resize=TRUE.
+ * until then, we want to
+ * - discard expose events
+ * - coalesce resizes for our children
+ * - defer any window resizes until the configure event arrived
+ * to achive this, we queue a resize for the window, but remove its
+ * resizing handler, so resizing will not be handled from the next
+ * idle handler but when the configure event arrives.
+ *
+ * FIXME: we should also dequeue the pending redraws here, since
+ * we handle those ourselves in ->handling_resize==TRUE.
+ */
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ if (container->resize_mode == GTK_RESIZE_QUEUE)
+ gtk_container_dequeue_resize_handler (container);
}
+ else
+ {
+ if (x != -1 && y != -1)
+ gdk_window_move (widget->window, x, y);
- return return_val;
+ if (container->resize_widgets)
+ gtk_container_resize_children (GTK_CONTAINER (window));
+ }
}
-static gint
-gtk_window_move_resize (GtkWidget *widget)
+/* Compare two sets of Geometry hints for equality.
+ */
+static gboolean
+gtk_window_compare_hints (GdkGeometry *geometry_a,
+ guint flags_a,
+ GdkGeometry *geometry_b,
+ guint flags_b)
{
- GtkWindow *window;
- gint x, y;
- gint width, height;
- gint screen_width;
- gint screen_height;
- gint return_val;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_WINDOW (widget), FALSE);
+ if (flags_a != flags_b)
+ return FALSE;
+
+ if ((flags_a & GDK_HINT_MIN_SIZE) &&
+ (geometry_a->min_width != geometry_b->min_width ||
+ geometry_a->min_height != geometry_b->min_height))
+ return FALSE;
+
+ if ((flags_a & GDK_HINT_MAX_SIZE) &&
+ (geometry_a->max_width != geometry_b->max_width ||
+ geometry_a->max_height != geometry_b->max_height))
+ return FALSE;
+
+ if ((flags_a & GDK_HINT_BASE_SIZE) &&
+ (geometry_a->base_width != geometry_b->base_width ||
+ geometry_a->base_height != geometry_b->base_height))
+ return FALSE;
+
+ if ((flags_a & GDK_HINT_ASPECT) &&
+ (geometry_a->min_aspect != geometry_b->min_aspect ||
+ geometry_a->max_aspect != geometry_b->max_aspect))
+ return FALSE;
+
+ if ((flags_a & GDK_HINT_RESIZE_INC) &&
+ (geometry_a->width_inc != geometry_b->width_inc ||
+ geometry_a->height_inc != geometry_b->height_inc))
+ return FALSE;
+
+ return TRUE;
+}
- return_val = FALSE;
+/* Compute the default_size for a window. The result will
+ * be stored in *width and *height. The default size is
+ * the size the window should have when initially mapped.
+ * This routine does not attempt to constrain the size
+ * to obey the geometry hints - that must be done elsewhere.
+ */
+static void
+gtk_window_compute_default_size (GtkWindow *window,
+ guint *width,
+ guint *height)
+{
+ GtkRequisition requisition;
+ GtkWindowGeometryInfo *info;
+
+ gtk_widget_get_child_requisition (GTK_WIDGET (window), &requisition);
+ *width = requisition.width;
+ *height = requisition.height;
- if (GTK_WIDGET_REALIZED (widget))
+ info = gtk_window_get_geometry_info (window, FALSE);
+
+ if (*width == 0 && *height == 0)
{
- window = GTK_WINDOW (widget);
-
- /* Remember old size, to know if we have to reset hints */
- width = widget->requisition.width;
- height = widget->requisition.height;
- gtk_widget_size_request (widget, &widget->requisition);
-
- if (GTK_WIDGET_MAPPED (widget) &&
- (width != widget->requisition.width ||
- height != widget->requisition.height))
- gtk_window_set_hints (widget, &widget->requisition);
-
- x = -1;
- y = -1;
- width = widget->requisition.width;
- height = widget->requisition.height;
-
- if (window->use_uposition)
- switch (window->position)
- {
- case GTK_WIN_POS_CENTER:
- x = (gdk_screen_width () - width) / 2;
- y = (gdk_screen_height () - height) / 2;
- gtk_widget_set_uposition (widget, x, y);
- break;
- case GTK_WIN_POS_MOUSE:
- gdk_window_get_pointer (NULL, &x, &y, NULL);
-
- x -= width / 2;
- y -= height / 2;
-
- screen_width = gdk_screen_width ();
- screen_height = gdk_screen_height ();
-
- if (x < 0)
- x = 0;
- else if (x > (screen_width - width))
- x = screen_width - width;
-
- if (y < 0)
- y = 0;
- else if (y > (screen_height - height))
- y = screen_height - height;
-
- gtk_widget_set_uposition (widget, x, y);
- break;
- }
-
- gtk_signal_emit (GTK_OBJECT (widget), window_signals[MOVE_RESIZE],
- &x, &y, width, height, &return_val);
+ /* empty window */
+ *width = 200;
+ *height = 200;
+ }
+
+ if (info)
+ {
+ *width = info->width > 0 ? info->width : *width;
+ *height = info->height > 0 ? info->height : *height;
}
-
- return return_val;
}
-static void
-gtk_real_window_set_focus (GtkWindow *window,
- GtkWidget *focus)
+/* 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,
+ guint flags,
+ gint width,
+ gint height,
+ gint *new_width,
+ gint *new_height)
{
- GdkEventFocus event;
+ 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) )
- g_return_if_fail (window != NULL);
- g_return_if_fail (GTK_IS_WINDOW (window));
+ 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 (focus && !GTK_WIDGET_CAN_FOCUS (focus))
- return;
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ max_width = geometry->max_width ;
+ max_height = geometry->max_height;
+ }
- if (window->focus_widget != focus)
+ if (flags & GDK_HINT_RESIZE_INC)
{
- if (window->focus_widget)
- {
- event.type = GDK_FOCUS_CHANGE;
- event.window = window->focus_widget->window;
- event.in = FALSE;
+ 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;
- gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+ 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;
+ }
}
-
- window->focus_widget = focus;
-
- if (window->focus_widget)
+
+ if (geometry->max_aspect * height < width)
{
- event.type = GDK_FOCUS_CHANGE;
- event.window = window->focus_widget->window;
- event.in = TRUE;
-
- gtk_widget_event (window->focus_widget, (GdkEvent*) &event);
+ 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;
}
+/* Compute the set of geometry hints and flags for a window
+ * based on the application set geometry, and requisiition
+ * of the window. gtk_widget_size_request() must have been
+ * called first.
+ */
static void
-gtk_window_set_hints (GtkWidget *widget,
- GtkRequisition *requisition)
+gtk_window_compute_hints (GtkWindow *window,
+ GdkGeometry *new_geometry,
+ guint *new_flags)
{
- GtkWindow *window;
+ GtkWidget *widget;
GtkWidgetAuxInfo *aux_info;
- gint flags;
gint ux, uy;
+ gint extra_width = 0;
+ gint extra_height = 0;
+ GtkWindowGeometryInfo *geometry_info;
+ GtkRequisition requisition;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_WINDOW (widget));
- g_return_if_fail (requisition != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
- if (GTK_WIDGET_REALIZED (widget))
+ widget = GTK_WIDGET (window);
+
+ gtk_widget_get_child_requisition (widget, &requisition);
+ geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE);
+
+ g_return_if_fail (geometry_info != NULL);
+
+ *new_flags = geometry_info->mask;
+ *new_geometry = geometry_info->geometry;
+
+ if (geometry_info->widget)
{
- window = GTK_WINDOW (widget);
+ extra_width = widget->requisition.width - geometry_info->widget->requisition.width;
+ extra_height = widget->requisition.height - geometry_info->widget->requisition.height;
+ }
+
+ 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))
+ {
+ ux = aux_info->x;
+ uy = aux_info->y;
+ *new_flags |= GDK_HINT_POS;
+ }
+
+ if (*new_flags & GDK_HINT_BASE_SIZE)
+ {
+ new_geometry->base_width += extra_width;
+ new_geometry->base_height += extra_height;
+ }
+ else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
+ (*new_flags & GDK_HINT_RESIZE_INC) &&
+ ((extra_width != 0) || (extra_height != 0)))
+ {
+ *new_flags |= GDK_HINT_BASE_SIZE;
+
+ new_geometry->base_width = extra_width;
+ new_geometry->base_height = extra_height;
+ }
+
+ if (*new_flags & GDK_HINT_MIN_SIZE)
+ {
+ new_geometry->min_width += extra_width;
+ new_geometry->min_height += extra_height;
+ }
+ else if (!window->allow_shrink)
+ {
+ *new_flags |= GDK_HINT_MIN_SIZE;
+
+ new_geometry->min_width = requisition.width;
+ new_geometry->min_height = requisition.height;
+ }
+
+ if (*new_flags & GDK_HINT_MAX_SIZE)
+ {
+ new_geometry->max_width += extra_width;
+ new_geometry->max_height += extra_height;
+ }
+ else if (!window->allow_grow)
+ {
+ *new_flags |= GDK_HINT_MAX_SIZE;
+
+ new_geometry->max_width = requisition.width;
+ new_geometry->max_height = requisition.height;
+ }
+}
+
+/* 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
+ */
+static void
+gtk_window_compute_reposition (GtkWindow *window,
+ gint new_width,
+ gint new_height,
+ gint *x,
+ gint *y)
+{
+ GtkWidget *widget;
- flags = 0;
- ux = 0;
- uy = 0;
+ widget = GTK_WIDGET (window);
- aux_info = gtk_object_get_data (GTK_OBJECT (widget), "gtk-aux-info");
- if (aux_info && (aux_info->x != -1) && (aux_info->y != -1))
+ *x = -1;
+ *y = -1;
+
+ switch (window->position)
+ {
+ case GTK_WIN_POS_CENTER:
+ case GTK_WIN_POS_CENTER_ALWAYS:
+ if (window->use_uposition)
{
- ux = aux_info->x;
- uy = aux_info->y;
- flags |= GDK_HINT_POS;
+ gint screen_width = gdk_screen_width ();
+ gint screen_height = gdk_screen_height ();
+
+ *x = (screen_width - new_width) / 2;
+ *y = (screen_height - new_height) / 2;
}
- if (!window->allow_shrink)
- flags |= GDK_HINT_MIN_SIZE;
- if (!window->allow_grow)
- flags |= GDK_HINT_MAX_SIZE;
-
- gdk_window_set_hints (widget->window, ux, uy,
- requisition->width, requisition->height,
- requisition->width, requisition->height,
- flags);
-
- if (window->use_uposition && (flags & GDK_HINT_POS))
+ break;
+ case GTK_WIN_POS_MOUSE:
+ if (window->use_uposition)
{
- window->use_uposition = FALSE;
- gdk_window_move (widget->window, ux, uy);
+ gint screen_width = gdk_screen_width ();
+ gint screen_height = gdk_screen_height ();
+
+ gdk_window_get_pointer (NULL, x, y, NULL);
+ *x -= new_width / 2;
+ *y -= new_height / 2;
+ *x = CLAMP (*x, 0, screen_width - new_width);
+ *y = CLAMP (*y, 0, screen_height - new_height);
}
+ 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)
+ {
+ *x = aux_info->x;
+ *y = aux_info->y;
+ }
+ }
+ break;
+ }
+
+ if (*x != -1 && *y != -1)
+ {
+ GtkWidgetAuxInfo *aux_info;
+
+ /* 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 = *x;
+ aux_info->y = *y;
+
+ window->use_uposition = FALSE;
}
}
-static gint
-gtk_window_check_accelerator (GtkWindow *window,
- gint key,
- guint mods)
+/***********************
+ * Redrawing functions *
+ ***********************/
+
+static void
+gtk_window_paint (GtkWidget *widget,
+ GdkRectangle *area)
{
- GtkAcceleratorTable *table;
- GList *tmp;
+ gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
+}
- if ((key >= 0x20) && (key <= 0xFF))
- {
- tmp = window->accelerator_tables;
- while (tmp)
- {
- table = tmp->data;
- tmp = tmp->next;
+static gint
+gtk_window_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ 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);
- if (gtk_accelerator_table_check (table, key, mods))
- return TRUE;
- }
+ if (!GTK_WIDGET_APP_PAINTABLE (widget))
+ gtk_window_paint (widget, &event->area);
+
+ if (GTK_WIDGET_CLASS (parent_class)->expose_event)
+ return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
- if (gtk_accelerator_table_check (NULL, key, mods))
- return TRUE;
- }
+ return TRUE;
+}
- return FALSE;
+static void
+gtk_window_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ if (!GTK_WIDGET_APP_PAINTABLE (widget))
+ gtk_window_paint (widget, area);
+
+ if (GTK_WIDGET_CLASS (parent_class)->draw)
+ (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
}