#include "gtkprivate.h"
#include "gtkrc.h"
-#include "gtksignal.h"
#include "gtkwindow.h"
#include "gtkwindow-decorate.h"
#include "gtkbindings.h"
static void gtk_window_transient_parent_unrealized (GtkWidget *parent,
GtkWidget *window);
+static GdkScreen *gtk_window_check_screen (GtkWindow *window);
+
static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window,
gboolean create);
static guint window_signals[LAST_SIGNAL] = { 0 };
static GList *default_icon_list = NULL;
static guint default_icon_serial = 0;
+static gboolean disable_startup_notification = FALSE;
+static gboolean sent_startup_notification = FALSE;
static void gtk_window_set_property (GObject *object,
guint prop_id,
return private;
}
-GtkType
+GType
gtk_window_get_type (void)
{
- static GtkType window_type = 0;
+ static GType window_type = 0;
if (!window_type)
{
- static const GtkTypeInfo window_info =
+ static const GTypeInfo window_info =
{
- "GtkWindow",
- sizeof (GtkWindow),
sizeof (GtkWindowClass),
- (GtkClassInitFunc) gtk_window_class_init,
- (GtkObjectInitFunc) gtk_window_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gtk_window_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkWindow),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_window_init,
};
- window_type = gtk_type_unique (gtk_bin_get_type (), &window_info);
+ window_type = g_type_register_static (GTK_TYPE_BIN, "GtkWindow",
+ &window_info, 0);
}
return window_type;
widget_class = (GtkWidgetClass*) klass;
container_class = (GtkContainerClass*) klass;
- parent_class = gtk_type_class (gtk_bin_get_type ());
+ parent_class = g_type_class_peek_parent (klass);
mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
window_signals[SET_FOCUS] =
g_signal_new ("set_focus",
- G_TYPE_FROM_CLASS (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWindowClass, set_focus),
NULL, NULL,
window_signals[FRAME_EVENT] =
g_signal_new ("frame_event",
- G_TYPE_FROM_CLASS(object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GtkWindowClass, frame_event),
_gtk_boolean_handled_accumulator, NULL,
window_signals[ACTIVATE_FOCUS] =
g_signal_new ("activate_focus",
- G_OBJECT_CLASS_TYPE (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- GTK_SIGNAL_OFFSET (GtkWindowClass, activate_focus),
+ G_STRUCT_OFFSET (GtkWindowClass, activate_focus),
NULL, NULL,
_gtk_marshal_VOID__VOID,
G_TYPE_NONE,
window_signals[ACTIVATE_DEFAULT] =
g_signal_new ("activate_default",
- G_OBJECT_CLASS_TYPE (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- GTK_SIGNAL_OFFSET (GtkWindowClass, activate_default),
+ G_STRUCT_OFFSET (GtkWindowClass, activate_default),
NULL, NULL,
_gtk_marshal_VOID__VOID,
G_TYPE_NONE,
window_signals[MOVE_FOCUS] =
g_signal_new ("move_focus",
- G_OBJECT_CLASS_TYPE (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- GTK_SIGNAL_OFFSET (GtkWindowClass, move_focus),
+ G_STRUCT_OFFSET (GtkWindowClass, move_focus),
NULL, NULL,
_gtk_marshal_VOID__ENUM,
G_TYPE_NONE,
window_signals[KEYS_CHANGED] =
g_signal_new ("keys_changed",
- G_OBJECT_CLASS_TYPE (object_class),
+ G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_FIRST,
- GTK_SIGNAL_OFFSET (GtkWindowClass, keys_changed),
+ G_STRUCT_OFFSET (GtkWindowClass, keys_changed),
NULL, NULL,
- gtk_marshal_VOID__VOID,
+ _gtk_marshal_VOID__VOID,
G_TYPE_NONE,
0);
if (colormap)
gtk_widget_set_colormap (GTK_WIDGET (window), colormap);
- gtk_widget_ref (GTK_WIDGET (window));
+ g_object_ref (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);
+ g_signal_connect (window,
+ "event",
+ G_CALLBACK (gtk_window_event),
+ NULL);
}
static void
g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL);
- window = gtk_type_new (GTK_TYPE_WINDOW);
+ window = g_object_new (GTK_TYPE_WINDOW, NULL);
window->type = type;
if ((window->focus_widget != focus) ||
(focus && !GTK_WIDGET_HAS_FOCUS (focus)))
- gtk_signal_emit (GTK_OBJECT (window), window_signals[SET_FOCUS], focus);
+ g_signal_emit (window, window_signals[SET_FOCUS], 0, focus);
}
/**
g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
g_signal_handlers_disconnect_by_func (accel_group,
- (gpointer) gtk_window_notify_keys_changed,
+ gtk_window_notify_keys_changed,
window);
_gtk_accel_group_detach (accel_group, G_OBJECT (window));
}
g_object_notify (G_OBJECT (window), "window_position");
}
+/**
+ * gtk_window_activate_focus:
+ * @window: a #GtkWindow
+ *
+ * Activates the current focused widget within the window.
+ *
+ * Return value: %TRUE if a widget got activated.
+ **/
gboolean
gtk_window_activate_focus (GtkWindow *window)
{
return window->focus_widget;
}
+/**
+ * gtk_window_activate_default:
+ * @window: a #GtkWindow
+ *
+ * Activates the default widget for the window, unless the current
+ * focused widget has been configured to receive the default action
+ * (see #GTK_RECEIVES_DEFAULT in #GtkWidgetFlags), in which case the
+ * focused widget is activated.
+ *
+ * Return value: %TRUE if a widget got activated.
+ **/
gboolean
gtk_window_activate_default (GtkWindow *window)
{
{
g_return_if_fail (GTK_IS_WINDOW (window));
- window->modal = modal != FALSE;
+ modal = modal != FALSE;
+ if (window->modal == modal)
+ return;
+
+ window->modal = modal;
/* adjust desired modality state */
- if (GTK_WIDGET_VISIBLE (window) && window->modal)
- gtk_grab_add (GTK_WIDGET (window));
- else
- gtk_grab_remove (GTK_WIDGET (window));
+ if (GTK_WIDGET_REALIZED (window))
+ {
+ GtkWidget *widget = GTK_WIDGET (window);
+
+ if (window->modal)
+ gdk_window_set_modal_hint (widget->window, TRUE);
+ else
+ gdk_window_set_modal_hint (widget->window, FALSE);
+ }
+
+ if (GTK_WIDGET_VISIBLE (window))
+ {
+ if (window->modal)
+ gtk_grab_add (GTK_WIDGET (window));
+ else
+ gtk_grab_remove (GTK_WIDGET (window));
+ }
g_object_notify (G_OBJECT (window), "modal");
}
g_return_if_fail (GTK_IS_WINDOW (window));
- embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
+ embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
if (embedded_windows)
- gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
- g_quark_from_static_string ("gtk-embedded"));
+ g_object_steal_qdata (G_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);
+ g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
+ embedded_windows,
+ embedded_windows ?
+ (GDestroyNotify) g_list_free : NULL);
}
void
g_return_if_fail (GTK_IS_WINDOW (window));
- embedded_windows = gtk_object_get_data (GTK_OBJECT (window), "gtk-embedded");
+ embedded_windows = g_object_get_data (G_OBJECT (window), "gtk-embedded");
if (embedded_windows)
- gtk_object_remove_no_notify_by_id (GTK_OBJECT (window),
- g_quark_from_static_string ("gtk-embedded"));
+ g_object_steal_qdata (G_OBJECT (window),
+ g_quark_from_static_string ("gtk-embedded"));
node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid));
if (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);
+ g_object_set_data_full (G_OBJECT (window), "gtk-embedded",
+ embedded_windows,
+ embedded_windows ?
+ (GDestroyNotify) g_list_free : NULL);
}
void
{
if (window->transient_parent)
{
- gtk_signal_connect (GTK_OBJECT (window->transient_parent),
- "destroy",
- GTK_SIGNAL_FUNC (parent_destroyed_callback),
- window);
+ g_signal_connect (window->transient_parent,
+ "destroy",
+ G_CALLBACK (parent_destroyed_callback),
+ window);
}
}
{
if (window->transient_parent)
{
- gtk_signal_disconnect_by_func (GTK_OBJECT (window->transient_parent),
- GTK_SIGNAL_FUNC (parent_destroyed_callback),
- window);
+ g_signal_handlers_disconnect_by_func (window->transient_parent,
+ parent_destroyed_callback,
+ window);
}
}
gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
}
+static void
+gtk_window_transient_parent_screen_changed (GtkWindow *parent,
+ GParamSpec *pspec,
+ GtkWindow *window)
+{
+ gtk_window_set_screen (window, parent->screen);
+}
+
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);
+ g_signal_handlers_disconnect_by_func (window->transient_parent,
+ gtk_window_transient_parent_realized,
+ window);
+ g_signal_handlers_disconnect_by_func (window->transient_parent,
+ gtk_window_transient_parent_unrealized,
+ window);
+ g_signal_handlers_disconnect_by_func (window->transient_parent,
+ gtk_window_transient_parent_screen_changed,
+ window);
+ g_signal_handlers_disconnect_by_func (window->transient_parent,
+ gtk_widget_destroyed,
+ &window->transient_parent);
if (window->destroy_with_parent)
disconnect_parent_destroyed (window);
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);
+ g_signal_connect (parent, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &window->transient_parent);
+ g_signal_connect (parent, "realize",
+ G_CALLBACK (gtk_window_transient_parent_realized),
+ window);
+ g_signal_connect (parent, "unrealize",
+ G_CALLBACK (gtk_window_transient_parent_unrealized),
+ window);
+ g_signal_connect (parent, "notify::screen",
+ G_CALLBACK (gtk_window_transient_parent_screen_changed),
+ window);
- window->screen = parent->screen;
+ gtk_window_set_screen (window, parent->screen);
if (window->destroy_with_parent)
connect_parent_destroyed (window);
* Windows may set a hint asking the desktop environment not to display
* the window in the task bar. This function toggles this hint.
*
+ * Since: 2.2
**/
void
gtk_window_set_skip_taskbar_hint (GtkWindow *window,
* Gets the value set by gtk_window_set_skip_taskbar_hint()
*
* Return value: %TRUE if window shouldn't be in taskbar
+ *
+ * Since: 2.2
**/
gboolean
gtk_window_get_skip_taskbar_hint (GtkWindow *window)
* switcher that displays a thumbnail representation of the windows
* on the screen.)
*
+ * Since: 2.2
**/
void
gtk_window_set_skip_pager_hint (GtkWindow *window,
* Gets the value set by gtk_window_set_skip_pager_hint().
*
* Return value: %TRUE if window shouldn't be in pager
+ *
+ * Since: 2.2
**/
gboolean
gtk_window_get_skip_pager_hint (GtkWindow *window)
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);
+ g_signal_handlers_disconnect_by_func (info->widget,
+ 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);
+ g_signal_connect (geometry_widget, "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &info->widget);
if (geometry)
info->geometry = *geometry;
* managers</link> 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.
+ * manager not to decorate the window. Depending on the system, this
+ * function may not have any effect when called on a window that is
+ * already visible, so you should call it before calling gtk_window_show().
*
* On Windows, this function always works, since there's no window manager
* policy involved.
/* Use shared icon pixmap for all windows on this screen.
*/
if (default_icon_info->pixmap)
- g_object_ref (G_OBJECT (default_icon_info->pixmap));
+ g_object_ref (default_icon_info->pixmap);
if (default_icon_info->mask)
- g_object_ref (G_OBJECT (default_icon_info->mask));
+ g_object_ref (default_icon_info->mask);
*pmap_return = default_icon_info->pixmap;
*mask_return = default_icon_info->mask;
else if (parent_info && parent_info->icon_pixmap)
{
if (parent_info->icon_pixmap)
- g_object_ref (G_OBJECT (parent_info->icon_pixmap));
+ g_object_ref (parent_info->icon_pixmap);
if (parent_info->icon_mask)
- g_object_ref (G_OBJECT (parent_info->icon_mask));
+ g_object_ref (parent_info->icon_mask);
*pmap_return = parent_info->icon_pixmap;
*mask_return = parent_info->icon_mask;
parent_info->icon_mask = *mask_return;
if (parent_info->icon_pixmap)
- g_object_ref (G_OBJECT (parent_info->icon_pixmap));
+ g_object_ref (parent_info->icon_pixmap);
if (parent_info->icon_mask)
- g_object_ref (G_OBJECT (parent_info->icon_mask));
+ g_object_ref (parent_info->icon_mask);
}
else if (is_default_list)
{
return;
if (info->icon_pixmap)
- g_object_unref (G_OBJECT (info->icon_pixmap));
+ g_object_unref (info->icon_pixmap);
if (info->icon_mask)
- g_object_unref (G_OBJECT (info->icon_mask));
+ g_object_unref (info->icon_mask);
info->icon_pixmap = NULL;
info->icon_mask = NULL;
g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
list = NULL;
- list = g_list_append (list, icon);
+
+ if (icon)
+ list = g_list_append (list, icon);
+
gtk_window_set_icon_list (window, list);
g_list_free (list);
}
return NULL;
}
+/* Load pixbuf, printing warning on failure if error == NULL
+ */
+static GdkPixbuf *
+load_pixbuf_verbosely (const char *filename,
+ GError **err)
+{
+ GError *local_err = NULL;
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (filename, &local_err);
+
+ if (!pixbuf)
+ {
+ if (err)
+ *err = local_err;
+ else
+ {
+ g_warning ("Error loading icon from file '%s':\n\t%s",
+ filename, local_err->message);
+ g_error_free (local_err);
+ }
+ }
+
+ return pixbuf;
+}
+
+/**
+ * gtk_window_set_icon_from_file:
+ * @window: a #GtkWindow
+ * @filename: location of icon file
+ * @err: location to store error, or %NULL.
+ *
+ * Sets the icon for @window.
+ * Warns on failure if @err is %NULL.
+ *
+ * This function is equivalent to calling gtk_window_set_icon()
+ * with a pixbuf created by loading the image from @filename.
+ *
+ * Returns: %TRUE if setting the icon succeeded.
+ *
+ * Since: 2.2
+ **/
+gboolean
+gtk_window_set_icon_from_file (GtkWindow *window,
+ const gchar *filename,
+ GError **err)
+{
+ GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
+
+ if (pixbuf)
+ {
+ gtk_window_set_icon (window, pixbuf);
+ g_object_unref (pixbuf);
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
/**
* gtk_window_set_default_icon_list:
* @list: a list of #GdkPixbuf
g_list_free (toplevels);
}
+/**
+ * gtk_window_set_default_icon_from_file:
+ * @filename: location of icon file
+ * @err: location to store error, or %NULL.
+ *
+ * Sets an icon to be used as fallback for windows that haven't
+ * had gtk_window_set_icon_list() called on them from a file
+ * on disk. Warns on failure if @err is %NULL.
+ *
+ * Returns: %TRUE if setting the icon succeeded.
+ *
+ * Since: 2.2
+ **/
+gboolean
+gtk_window_set_default_icon_from_file (const gchar *filename,
+ GError **err)
+{
+ GdkPixbuf *pixbuf = load_pixbuf_verbosely (filename, err);
+
+ if (pixbuf)
+ {
+ GList *list = g_list_prepend (NULL, pixbuf);
+ gtk_window_set_default_icon_list (list);
+ g_list_free (list);
+
+ g_object_unref (pixbuf);
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
/**
* gtk_window_get_default_icon_list:
*
if (window->has_user_ref_count)
{
window->has_user_ref_count = FALSE;
- gtk_widget_unref (GTK_WIDGET (window));
+ g_object_unref (window);
}
if (window->group)
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_signal_handlers_disconnect_by_func (window->geometry_info->widget,
+ gtk_widget_destroyed,
+ &window->geometry_info->widget);
g_free (window->geometry_info);
}
if (window->frame)
gdk_window_show (window->frame);
+
+ if (!disable_startup_notification &&
+ !sent_startup_notification)
+ {
+ sent_startup_notification = TRUE;
+ gdk_notify_startup_complete ();
+ }
}
static void
if (gtk_window_get_skip_taskbar_hint (window))
gdk_window_set_skip_taskbar_hint (widget->window, TRUE);
- /* transient_for must be set to allow the modal hint */
- if (window->transient_parent && window->modal)
+ if (window->modal)
gdk_window_set_modal_hint (widget->window, TRUE);
else
gdk_window_set_modal_hint (widget->window, FALSE);
(event->type != GDK_KEY_RELEASE) &&
(event->type != GDK_FOCUS_CHANGE))
{
- gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "event");
+ g_signal_stop_emission_by_name (widget, "event");
return_val = FALSE;
- gtk_signal_emit (GTK_OBJECT (widget), window_signals[FRAME_EVENT], event, &return_val);
+ g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val);
return TRUE;
}
else
do_focus_change (GtkWidget *widget,
gboolean in)
{
- GdkEventFocus fevent;
-
+ GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
+
g_object_ref (widget);
-
- if (in)
+
+ if (in)
GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
else
GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
-
- fevent.type = GDK_FOCUS_CHANGE;
- fevent.window = widget->window;
- fevent.in = in;
- gtk_widget_event (widget, (GdkEvent*) &fevent);
+ fevent->focus_change.type = GDK_FOCUS_CHANGE;
+ fevent->focus_change.window = widget->window;
+ if (widget->window)
+ g_object_ref (widget->window);
+ fevent->focus_change.in = in;
+
+ gtk_widget_event (widget, fevent);
g_object_notify (G_OBJECT (widget), "has_focus");
g_object_unref (widget);
+ gdk_event_free (fevent);
}
static gint
{
GList *embedded_windows;
- embedded_windows = gtk_object_get_data (GTK_OBJECT (widget), "gtk-embedded");
+ embedded_windows = g_object_get_data (G_OBJECT (widget), "gtk-embedded");
if (embedded_windows)
{
- GdkEventClient sev;
+ GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
int i;
for (i = 0; i < 5; i++)
- sev.data.l[i] = 0;
- sev.data_format = 32;
- sev.message_type = atom_rcfiles;
+ send_event->client.data.l[i] = 0;
+ send_event->client.data_format = 32;
+ send_event->client.message_type = atom_rcfiles;
while (embedded_windows)
{
guint xid = GPOINTER_TO_UINT (embedded_windows->data);
- gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), (GdkEvent *) &sev, xid);
+ gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid);
embedded_windows = embedded_windows->next;
}
+
+ gdk_event_free (send_event);
}
gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE);
}
}
+/**
+ * _gtk_window_unset_focus_and_default:
+ * @window: a #GtkWindow
+ * @widget: a widget inside of @window
+ *
+ * Checks whether the focus and default widgets of @window are
+ * @widget or a descendent of @widget, and if so, unset them.
+ **/
+void
+_gtk_window_unset_focus_and_default (GtkWindow *window,
+ GtkWidget *widget)
+
+{
+ GtkWidget *child;
+
+ if (GTK_CONTAINER (widget->parent)->focus_child == widget)
+ {
+ child = window->focus_widget;
+
+ while (child && child != widget)
+ child = child->parent;
+
+ if (child == widget)
+ gtk_window_set_focus (GTK_WINDOW (window), NULL);
+ }
+
+ child = window->default_widget;
+
+ while (child && child != widget)
+ child = child->parent;
+
+ if (child == widget)
+ gtk_window_set_default (window, NULL);
+}
+
/*********************************
* Functions related to resizing *
*********************************/
return pos;
}
+static int
+get_center_monitor_of_window (GtkWindow *window)
+{
+ /* We could try to sort out the relative positions of the monitors and
+ * stuff, or we could just be losers and assume you have a row
+ * or column of monitors.
+ */
+ return gdk_screen_get_n_monitors (gtk_window_check_screen (window)) / 2;
+}
+
+static int
+get_monitor_containing_pointer (GtkWindow *window)
+{
+ gint px, py;
+ gint monitor_num;
+ GdkScreen *window_screen;
+ GdkScreen *pointer_screen;
+
+ window_screen = gtk_window_check_screen (window);
+ gdk_display_get_pointer (gdk_screen_get_display (window_screen),
+ &pointer_screen,
+ &px, &py, NULL);
+
+ if (pointer_screen == window_screen)
+ monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py);
+ else
+ monitor_num = -1;
+
+ return monitor_num;
+}
+
+static void
+center_window_on_monitor (GtkWindow *window,
+ gint w,
+ gint h,
+ gint *x,
+ gint *y)
+{
+ GdkRectangle monitor;
+ int monitor_num;
+
+ monitor_num = get_monitor_containing_pointer (window);
+
+ if (monitor_num == -1)
+ monitor_num = get_center_monitor_of_window (window);
+
+ gdk_screen_get_monitor_geometry (gtk_window_check_screen (window),
+ monitor_num, &monitor);
+
+ *x = (monitor.width - w) / 2 + monitor.x;
+ *y = (monitor.height - h) / 2 + monitor.y;
+
+ /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
+ * and WM decorations.
+ */
+ if (*x < monitor.x)
+ *x = monitor.x;
+ if (*y < monitor.y)
+ *y = monitor.y;
+}
+
+static void
+clamp_window_to_rectangle (gint *x,
+ gint *y,
+ gint w,
+ gint h,
+ const GdkRectangle *rect)
+{
+ gint outside_w, outside_h;
+
+ outside_w = (*x + w) - (rect->x + rect->width);
+ if (outside_w > 0)
+ *x -= outside_w;
+
+ outside_h = (*y + h) - (rect->y + rect->height);
+ if (outside_h > 0)
+ *y -= outside_h;
+
+ /* if larger than the screen, center on the screen. */
+ if (*x < rect->x)
+ *x += (rect->x - *x) / 2;
+ if (*y < rect->y)
+ *y += (rect->y - *y) / 2;
+}
+
+
static void
gtk_window_compute_configure_request (GtkWindow *window,
GdkRectangle *request,
GtkWindowPosition pos;
GtkWidget *parent_widget;
GtkWindowGeometryInfo *info;
+ GdkScreen *screen;
int x, y;
widget = GTK_WIDGET (window);
+
+ screen = gtk_window_check_screen (window);
gtk_widget_size_request (widget, NULL);
gtk_window_compute_configure_request_size (window, &w, &h);
*/
case GTK_WIN_POS_CENTER_ALWAYS:
case GTK_WIN_POS_CENTER:
- {
- gint px, py, monitor_num;
- GdkRectangle monitor;
-
- gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
- &px, &py, NULL);
-
- monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
- if (monitor_num == -1)
- monitor_num = 0;
-
- gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
-
- x = (monitor.width - w) / 2 + monitor.x;
- y = (monitor.height - h) / 2 + monitor.y;
- }
+ center_window_on_monitor (window, w, h, &x, &y);
break;
case GTK_WIN_POS_CENTER_ON_PARENT:
{
+ gint monitor_num;
+ GdkRectangle monitor;
gint ox, oy;
g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
+
+ if (parent_widget->window != NULL)
+ monitor_num = gdk_screen_get_monitor_at_window (screen,
+ parent_widget->window);
+ else
+ monitor_num = -1;
gdk_window_get_origin (parent_widget->window,
&ox, &oy);
x = ox + (parent_widget->allocation.width - w) / 2;
y = oy + (parent_widget->allocation.height - h) / 2;
+
+ /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
+ * WM decorations. If parent wasn't on a monitor, just
+ * give up.
+ */
+ if (monitor_num >= 0)
+ {
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+ clamp_window_to_rectangle (&x, &y, w, h, &monitor);
+ }
}
break;
case GTK_WIN_POS_MOUSE:
{
- gint screen_width = gdk_screen_get_width (window->screen);
- gint screen_height = gdk_screen_get_height (window->screen);
- int px, py;
+ gint screen_width = gdk_screen_get_width (screen);
+ gint screen_height = gdk_screen_get_height (screen);
+ gint monitor_num;
+ GdkRectangle monitor;
+ GdkScreen *pointer_screen;
+ gint px, py;
+
+ gdk_display_get_pointer (gdk_screen_get_display (screen),
+ &pointer_screen,
+ &px, &py, NULL);
+
+ if (pointer_screen == screen)
+ monitor_num = gdk_screen_get_monitor_at_point (screen, px, py);
+ else
+ monitor_num = -1;
- gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
- &px, &py, NULL);
x = px - w / 2;
y = py - h / 2;
x = CLAMP (x, 0, screen_width - w);
y = CLAMP (y, 0, screen_height - h);
+
+ /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
+ * WM decorations. Don't try to figure out what's going
+ * on if the mouse wasn't inside a monitor.
+ */
+ if (monitor_num >= 0)
+ {
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+ clamp_window_to_rectangle (&x, &y, w, h, &monitor);
+ }
}
break;
if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
{
gint center_x, center_y;
- gint screen_width = gdk_screen_get_width (window->screen);
- gint screen_height = gdk_screen_get_height (window->screen);
-
- center_x = (screen_width - new_width) / 2;
- center_y = (screen_height - new_height) / 2;
+
+ center_window_on_monitor (window, new_width, new_height, ¢er_x, ¢er_y);
*x = center_x;
*y = center_y;
gtk_widget_queue_resize (widget); /* migth recurse for GTK_RESIZE_IMMEDIATE */
}
+
+ return; /* Bail out, we didn't really process the move/resize */
}
else if ((configure_request_size_changed || hints_changed) &&
(widget->allocation.width != new_request.width ||
new_request.width, new_request.height);
}
else
- if (widget->window)
- gdk_window_move_resize (widget->window,
- new_request.x, new_request.y,
- new_request.width, new_request.height);
+ gdk_window_move_resize (widget->window,
+ new_request.x, new_request.y,
+ new_request.width, new_request.height);
}
else /* only size changed */
{
gdk_window_resize (window->frame,
new_request.width + window->frame_left + window->frame_right,
new_request.height + window->frame_top + window->frame_bottom);
- if (widget->window)
- gdk_window_resize (widget->window,
- new_request.width, new_request.height);
+ gdk_window_resize (widget->window,
+ new_request.width, new_request.height);
}
/* Increment the number of have-not-yet-received-notify requests */
window->configure_request_count += 1;
- /* We have now sent a request since the last position constraint
- * change and definitely don't need a an initial size again (not
- * resetting this here can lead to infinite loops for
- * GTK_RESIZE_IMMEDIATE containers)
- */
- info->position_constraints_changed = FALSE;
- info->initial_pos_set = FALSE;
- info->resize_width = -1;
- info->resize_height = -1;
-
/* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
* configure event in response to our resizing request.
* the configure event will cause a new resize with
else
gdk_window_move (widget->window,
new_request.x, new_request.y);
-
- info->initial_pos_set = FALSE;
}
-
+
/* And run the resize queue.
*/
gtk_container_resize_children (container);
}
+
+ /* We have now processed a move/resize since the last position
+ * constraint change, setting of the initial position, or resize.
+ * (Not resetting these flags here can lead to infinite loops for
+ * GTK_RESIZE_IMMEDIATE containers)
+ */
+ info->position_constraints_changed = FALSE;
+ info->initial_pos_set = FALSE;
+ info->resize_width = -1;
+ info->resize_height = -1;
}
/* Compare two sets of Geometry hints for equality.
* You can track the fullscreen state via the "window_state_event" signal
* on #GtkWidget.
*
+ * Since: 2.2
**/
void
gtk_window_fullscreen (GtkWindow *window)
* You can track the fullscreen state via the "window_state_event" signal
* on #GtkWidget.
*
+ * Since: 2.2
**/
void
gtk_window_unfullscreen (GtkWindow *window)
* Sets the #GdkScreen where the @window is displayed; if
* the window is already mapped, it will be unmapped, and
* then remapped on the new screen.
+ *
+ * Since: 2.2
*/
void
gtk_window_set_screen (GtkWindow *window,
GdkScreen *screen)
{
GtkWidget *widget;
+ GdkScreen *previous_screen;
gboolean was_mapped;
g_return_if_fail (GTK_IS_WINDOW (window));
return;
widget = GTK_WIDGET (window);
-
+
+ previous_screen = window->screen;
was_mapped = GTK_WIDGET_MAPPED (widget);
if (was_mapped)
gtk_widget_unmap (widget);
if (GTK_WIDGET_REALIZED (widget))
gtk_widget_unrealize (widget);
-
+
gtk_window_free_key_hash (window);
window->screen = screen;
gtk_widget_reset_rc_styles (widget);
+ if (screen != previous_screen)
+ _gtk_widget_propagate_screen_changed (widget, previous_screen);
g_object_notify (G_OBJECT (window), "screen");
if (was_mapped)
gtk_widget_map (widget);
}
+static GdkScreen *
+gtk_window_check_screen (GtkWindow *window)
+{
+ if (window->screen)
+ return window->screen;
+ else
+ {
+ g_warning ("Screen for GtkWindow not set; you must always set\n"
+ "a screen for a GtkWindow before using the window");
+ return NULL;
+ }
+}
+
/**
* gtk_window_get_screen:
* @window: a #GtkWindow.
* Returns the #GdkScreen associated with @window.
*
* Return value: a #GdkScreen.
+ *
+ * Since: 2.2
*/
GdkScreen*
gtk_window_get_screen (GtkWindow *window)
{
}
-GtkType
+GType
gtk_window_group_get_type (void)
{
- static GtkType window_group_type = 0;
+ static GType window_group_type = 0;
if (!window_group_type)
{
window_group_cleanup_grabs (window_group, window);
window->group = NULL;
- g_object_unref (G_OBJECT (window_group));
+ g_object_unref (window_group);
g_object_unref (window);
}
guint w, h;
GdkGravity grav;
gboolean size_set, pos_set;
+ GdkScreen *screen;
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
g_return_val_if_fail (geometry != NULL, FALSE);
+
+ screen = gtk_window_check_screen (window);
result = gtk_XParseGeometry (geometry, &x, &y, &w, &h);
if (grav == GDK_GRAVITY_SOUTH_WEST ||
grav == GDK_GRAVITY_SOUTH_EAST)
- y = gdk_screen_get_height (window->screen) - h + y;
+ y = gdk_screen_get_height (screen) - h + y;
if (grav == GDK_GRAVITY_SOUTH_EAST ||
grav == GDK_GRAVITY_NORTH_EAST)
- x = gdk_screen_get_width (window->screen) - w + x;
+ x = gdk_screen_get_width (screen) - w + x;
/* we don't let you put a window offscreen; maybe some people would
* prefer to be able to, but it's kind of a bogus thing to do.
static GtkKeyHash *
gtk_window_get_key_hash (GtkWindow *window)
{
+ GdkScreen *screen = gtk_window_check_screen (window);
GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
+
if (key_hash)
return key_hash;
- key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (window->screen)),
+ key_hash = _gtk_key_hash_new (gdk_keymap_get_for_display (gdk_screen_get_display (screen)),
(GDestroyNotify)g_free);
_gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
g_object_notify (G_OBJECT (window), "has_toplevel_focus");
}
}
+
+/**
+ * gtk_window_set_auto_startup_notification:
+ * @setting: %TRUE to automatically do startup notification
+ *
+ * By default, after showing the first #GtkWindow for each #GdkScreen,
+ * GTK+ calls gdk_screen_notify_startup_complete(). Call this
+ * function to disable the automatic startup notification. You might
+ * do this if your first window is a splash screen, and you want to
+ * delay notification until after your real main window has been
+ * shown, for example.
+ *
+ * In that example, you would disable startup notification
+ * temporarily, show your splash screen, then re-enable it so that
+ * showing the main window would automatically result in notification.
+ *
+ * Since: 2.2
+ **/
+void
+gtk_window_set_auto_startup_notification (gboolean setting)
+{
+ disable_startup_notification = !setting;
+}