test the window state stuff

2001-02-26  Havoc Pennington  <hp@redhat.com>

	* gtk/testgtk.c: test the window state stuff

	* gtk/gtkwindow.c (gtk_window_present): new function, makes a
	window come to the user's attention as if it were just created
	(gtk_window_iconify): new function
	(gtk_window_deiconify): new function
	(gtk_window_stick): new function
	(gtk_window_unstick): new function
	(gtk_window_maximize): new function
	(gtk_window_unmaximize): new function

	* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal

	* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE

	* gdk/x11/gdkevents-x11.c: create window state events when
	appropriate
	(gdk_wmspec_supported): new function

	* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
	iconification before showing the window
	(gdk_window_deiconify): new function
	(gdk_window_stick): new function
	(gdk_window_unstick): new function
	(gdk_window_maximize): new function
	(gdk_window_unmaximize): new function

	* gdk/gdkwindow.c: store the window state in the window;
	change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
	window->mapped.
	(gdk_window_get_state): return the current window state

	* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
	(gdk_event_get_state): handle GDK_WINDOW_STATE
	(gdk_synthesize_window_state): function to create the window state
	events

	* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
	event, for changes to "window state" such as maximized, sticky,
	etc.

	* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
	focuses a window

	* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
	finds out if we support a given WM spec hint
This commit is contained in:
Havoc Pennington 2001-02-27 20:40:15 +00:00 committed by Havoc Pennington
parent af03d3855d
commit 75d79abf98
24 changed files with 1853 additions and 38 deletions

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -1,3 +1,52 @@
2001-02-26 Havoc Pennington <hp@redhat.com>
* gtk/testgtk.c: test the window state stuff
* gtk/gtkwindow.c (gtk_window_present): new function, makes a
window come to the user's attention as if it were just created
(gtk_window_iconify): new function
(gtk_window_deiconify): new function
(gtk_window_stick): new function
(gtk_window_unstick): new function
(gtk_window_maximize): new function
(gtk_window_unmaximize): new function
* gtk/gtkwidget.h, gtk/gtkwidget.c: add window_state_event signal
* gtk/gtkmain.c (gtk_main_do_event): handle GDK_WINDOW_STATE
* gdk/x11/gdkevents-x11.c: create window state events when
appropriate
(gdk_wmspec_supported): new function
* gdk/x11/gdkwindow-x11.c (gdk_window_iconify): handle
iconification before showing the window
(gdk_window_deiconify): new function
(gdk_window_stick): new function
(gdk_window_unstick): new function
(gdk_window_maximize): new function
(gdk_window_unmaximize): new function
* gdk/gdkwindow.c: store the window state in the window;
change to using the GDK_WINDOW_STATE_WITHDRAWN flag instead of
window->mapped.
(gdk_window_get_state): return the current window state
* gdk/gdkevents.c (gdk_event_get_time): handle GDK_WINDOW_STATE
(gdk_event_get_state): handle GDK_WINDOW_STATE
(gdk_synthesize_window_state): function to create the window state
events
* gdk/gdkevents.h (struct _GdkEventWindowState): new type of
event, for changes to "window state" such as maximized, sticky,
etc.
* gdk/x11/gdkwindow-x11.c (gdk_window_focus): new function,
focuses a window
* gdk/x11/gdkmain-x11.c (_gdk_wmspec_supported): new function,
finds out if we support a given WM spec hint
Tue Feb 27 13:37:38 GMT 2001 Tony Gale <gale@gtk.org>
* docs/faq/gtk-faq.sgml: New question re memory leaks.
@ -24,7 +73,6 @@ Sat Feb 24 20:11:39 2001 Jonathan Blandford <jrb@webwynk.net>
* gtk/gtkclipboard.h: actually put /* */ around #endif comment.
Fri Feb 23 17:50:13 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtktreeview.c (gtk_tree_view_bin_expose): Only draw the

View File

@ -454,6 +454,7 @@ gdk_event_get_time (GdkEvent *event)
case GDK_EXPOSE:
case GDK_MAP:
case GDK_UNMAP:
case GDK_WINDOW_STATE:
/* return current time */
break;
}
@ -529,6 +530,7 @@ gdk_event_get_state (GdkEvent *event,
case GDK_EXPOSE:
case GDK_MAP:
case GDK_UNMAP:
case GDK_WINDOW_STATE:
/* no state field */
break;
}
@ -803,3 +805,56 @@ gdk_event_button_generate (GdkEvent *event)
button_number[0] = event->button.button;
}
}
void
gdk_synthesize_window_state (GdkWindow *window,
GdkWindowState unset_flags,
GdkWindowState set_flags)
{
GdkEventWindowState temp_event;
GdkWindowState old;
g_return_if_fail (window != NULL);
temp_event.window = window;
temp_event.type = GDK_WINDOW_STATE;
temp_event.send_event = FALSE;
old = ((GdkWindowObject*) temp_event.window)->state;
temp_event.changed_mask = (unset_flags | set_flags) ^ old;
temp_event.new_window_state = old;
temp_event.new_window_state |= set_flags;
temp_event.new_window_state &= ~unset_flags;
if (temp_event.new_window_state == old)
return; /* No actual work to do, nothing changed. */
/* Actually update the field in GdkWindow, this is sort of an odd
* place to do it, but seems like the safest since it ensures we expose no
* inconsistent state to the user.
*/
((GdkWindowObject*) window)->state = temp_event.new_window_state;
/* We only really send the event to toplevels, since
* all the window states don't apply to non-toplevels.
* Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
* internally so we needed to update window->state.
*/
switch (((GdkWindowObject*) window)->window_type)
{
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP: /* ? */
gdk_event_put ((GdkEvent*) &temp_event);
break;
case GDK_WINDOW_FOREIGN:
case GDK_WINDOW_ROOT:
case GDK_WINDOW_CHILD:
break;
}
}

View File

@ -28,8 +28,8 @@ typedef struct _GdkEventProperty GdkEventProperty;
typedef struct _GdkEventSelection GdkEventSelection;
typedef struct _GdkEventProximity GdkEventProximity;
typedef struct _GdkEventClient GdkEventClient;
typedef struct _GdkEventDND GdkEventDND;
typedef struct _GdkEventWindowState GdkEventWindowState;
typedef union _GdkEvent GdkEvent;
@ -110,7 +110,8 @@ typedef enum
GDK_CLIENT_EVENT = 28,
GDK_VISIBILITY_NOTIFY = 29,
GDK_NO_EXPOSE = 30,
GDK_SCROLL = 31
GDK_SCROLL = 31,
GDK_WINDOW_STATE = 32
} GdkEventType;
/* Event masks. (Used to select what types of events a window
@ -193,6 +194,14 @@ typedef enum
GDK_PROPERTY_DELETE
} GdkPropertyState;
typedef enum
{
GDK_WINDOW_STATE_WITHDRAWN = 1 << 0,
GDK_WINDOW_STATE_ICONIFIED = 1 << 1,
GDK_WINDOW_STATE_MAXIMIZED = 1 << 2,
GDK_WINDOW_STATE_STICKY = 1 << 3
} GdkWindowState;
struct _GdkEventAny
{
GdkEventType type;
@ -366,6 +375,16 @@ struct _GdkEventClient
} data;
};
struct _GdkEventWindowState
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
GdkWindowState changed_mask;
GdkWindowState new_window_state;
};
/* Event types for DND */
struct _GdkEventDND {
@ -397,6 +416,7 @@ union _GdkEvent
GdkEventProximity proximity;
GdkEventClient client;
GdkEventDND dnd;
GdkEventWindowState window_state;
};
gboolean gdk_events_pending (void);

View File

@ -117,6 +117,9 @@ void gdk_event_queue_remove_link (GList *node);
void gdk_event_queue_append (GdkEvent *event);
void gdk_event_button_generate (GdkEvent *event);
void gdk_synthesize_window_state (GdkWindow *window,
GdkWindowState unset_flags,
GdkWindowState set_flags);
/*************************************
* Interfaces used by windowing code *
@ -163,6 +166,8 @@ void _gdk_windowing_window_clear_area_e (GdkWindow *window,
gint width,
gint height);
#define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
/* Called before processing updates for a window. This gives the windowing
* layer a chance to save the region for later use in avoiding duplicate
* exposes. The return value indicates whether the function has a saved

View File

@ -188,6 +188,8 @@ gdk_window_init (GdkWindowObject *window)
window->window_type = GDK_WINDOW_CHILD;
window->state = GDK_WINDOW_STATE_WITHDRAWN;
window->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
}
@ -290,7 +292,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
case GDK_WINDOW_FOREIGN:
if (!GDK_WINDOW_DESTROYED (window))
{
private->mapped = FALSE;
private->state |= GDK_WINDOW_STATE_WITHDRAWN;
private->destroyed = TRUE;
_gdk_windowing_window_destroy (window, recursing, foreign_destroy);
@ -573,12 +575,9 @@ gdk_window_get_toplevels (void)
gboolean
gdk_window_is_visible (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
g_return_val_if_fail (window != NULL, FALSE);
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
return private->mapped;
return GDK_WINDOW_IS_MAPPED (window);
}
/*************************************************************
@ -605,7 +604,7 @@ gdk_window_is_viewable (GdkWindow *window)
(private != (GdkWindowObject *)gdk_parent_root) &&
(GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
{
if (!private->mapped)
if (!GDK_WINDOW_IS_MAPPED (window))
return FALSE;
private = (GdkWindowObject *)private->parent;
@ -614,6 +613,25 @@ gdk_window_is_viewable (GdkWindow *window)
return TRUE;
}
/**
* gdk_window_get_state:
* @window: a #GdkWindow
*
* Gets the bitwise OR of the currently active window state flags,
* from the #GdkWindowState enumeration.
*
* Return value: window state bitfield
**/
GdkWindowState
gdk_window_get_state (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
return private->state;
}
/**
* gdk_window_begin_paint_rect:
* @window: a #GdkWindow
@ -1871,7 +1889,7 @@ gdk_window_invalidate_rect (GdkWindow *window,
if (GDK_WINDOW_DESTROYED (window))
return;
if (private->input_only || !private->mapped)
if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
return;
if (!rect)
@ -1927,7 +1945,7 @@ gdk_window_invalidate_region (GdkWindow *window,
if (GDK_WINDOW_DESTROYED (window))
return;
if (private->input_only || !private->mapped)
if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
return;
visible_region = gdk_drawable_get_visible_region (window);

View File

@ -199,7 +199,9 @@ struct _GdkWindowObject
guint8 window_type;
guint8 depth;
guint8 resize_count;
guint mapped : 1;
GdkWindowState state;
guint guffaw_gravity : 1;
guint input_only : 1;
@ -254,6 +256,8 @@ void gdk_window_clear_area_e (GdkWindow *window,
gint height);
void gdk_window_raise (GdkWindow *window);
void gdk_window_lower (GdkWindow *window);
void gdk_window_focus (GdkWindow *window,
guint32 timestamp);
void gdk_window_set_user_data (GdkWindow *window,
gpointer user_data);
void gdk_window_set_override_redirect (GdkWindow *window,
@ -305,6 +309,8 @@ void gdk_window_merge_child_shapes (GdkWindow *window);
gboolean gdk_window_is_visible (GdkWindow *window);
gboolean gdk_window_is_viewable (GdkWindow *window);
GdkWindowState gdk_window_get_state (GdkWindow *window);
/* Set static bit gravity on the parent, and static
* window gravity on all children.
*/
@ -393,7 +399,13 @@ gboolean gdk_window_get_decorations (GdkWindow *window,
void gdk_window_set_functions (GdkWindow *window,
GdkWMFunction functions);
GList * gdk_window_get_toplevels (void);
void gdk_window_iconify (GdkWindow *window);
void gdk_window_deiconify (GdkWindow *window);
void gdk_window_stick (GdkWindow *window);
void gdk_window_unstick (GdkWindow *window);
void gdk_window_maximize (GdkWindow *window);
void gdk_window_unmaximize (GdkWindow *window);
void gdk_window_register_dnd (GdkWindow *window);

View File

@ -44,6 +44,8 @@
#include <X11/XKBlib.h>
#endif
#include <X11/Xatom.h>
typedef struct _GdkIOClosure GdkIOClosure;
typedef struct _GdkEventPrivate GdkEventPrivate;
@ -119,7 +121,9 @@ static GSourceFuncs event_funcs = {
NULL
};
GPollFD event_poll_fd;
static GPollFD event_poll_fd;
static Window wmspec_check_window = None;
/*********************************************
* Functions for maintaining the event queue *
@ -260,6 +264,128 @@ gdk_add_client_message_filter (GdkAtom message_type,
client_filters = g_list_prepend (client_filters, filter);
}
static GdkAtom wm_state_atom = 0;
static GdkAtom wm_desktop_atom = 0;
static void
gdk_check_wm_state_changed (GdkWindow *window)
{
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
GdkAtom *atoms = NULL;
gulong i;
GdkAtom sticky_atom;
GdkAtom maxvert_atom;
GdkAtom maxhorz_atom;
gboolean found_sticky, found_maxvert, found_maxhorz;
GdkWindowState old_state;
if (GDK_WINDOW_DESTROYED (window))
return;
if (wm_state_atom == 0)
wm_state_atom = gdk_atom_intern ("_NET_WM_STATE", FALSE);
if (wm_desktop_atom == 0)
wm_desktop_atom = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
wm_state_atom, 0, G_MAXLONG,
False, XA_ATOM, &type, &format, &nitems,
&bytes_after, (guchar **)&atoms);
if (type != None)
{
sticky_atom = gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE);
maxvert_atom = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE);
maxhorz_atom = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE);
found_sticky = FALSE;
found_maxvert = FALSE;
found_maxhorz = FALSE;
i = 0;
while (i < nitems)
{
if (atoms[i] == sticky_atom)
found_sticky = TRUE;
else if (atoms[i] == maxvert_atom)
found_maxvert = TRUE;
else if (atoms[i] == maxhorz_atom)
found_maxhorz = TRUE;
++i;
}
XFree (atoms);
}
else
{
found_sticky = FALSE;
found_maxvert = FALSE;
found_maxhorz = FALSE;
}
/* For found_sticky to remain TRUE, we have to also be on desktop
* 0xFFFFFFFF
*/
if (found_sticky)
{
gulong *desktop;
XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
wm_desktop_atom, 0, G_MAXLONG,
False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, (guchar **)&desktop);
if (type != None)
{
if (*desktop != 0xFFFFFFFF)
found_sticky = FALSE;
XFree (desktop);
}
}
old_state = gdk_window_get_state (window);
if (old_state & GDK_WINDOW_STATE_STICKY)
{
if (!found_sticky)
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_STICKY,
0);
}
else
{
if (found_sticky)
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_STICKY);
}
/* Our "maximized" means both vertical and horizontal; if only one,
* we don't expose that via GDK
*/
if (old_state & GDK_WINDOW_STATE_MAXIMIZED)
{
if (!(found_maxvert && found_maxhorz))
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_MAXIMIZED,
0);
}
else
{
if (found_maxvert && found_maxhorz)
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_MAXIMIZED);
}
}
static gint
gdk_event_translate (GdkEvent *event,
XEvent *xevent,
@ -306,6 +432,19 @@ gdk_event_translate (GdkEvent *event,
if (window != NULL)
gdk_window_ref (window);
if (wmspec_check_window != None &&
xevent->xany.window == wmspec_check_window)
{
if (xevent->type == DestroyNotify)
wmspec_check_window = None;
/* Eat events on this window unless someone had wrapped
* it as a foreign window
*/
if (window == NULL)
return FALSE;
}
event->any.window = window;
event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
@ -948,7 +1087,17 @@ gdk_event_translate (GdkEvent *event,
xevent->xmap.window));
event->any.type = GDK_UNMAP;
event->any.window = window;
event->any.window = window;
/* If we are shown (not withdrawn) and get an unmap, it means we
* were iconified in the X sense. If we are withdrawn, and get
* an unmap, it means we hid the window ourselves, so we
* will have already flipped the iconified bit off.
*/
if (GDK_WINDOW_IS_MAPPED (window))
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_ICONIFIED);
if (gdk_xgrab_window == window_private)
gdk_xgrab_window = NULL;
@ -962,6 +1111,12 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_MAP;
event->any.window = window;
/* Unset iconified if it was set */
if (((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_ICONIFIED)
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_ICONIFIED,
0);
break;
@ -1064,6 +1219,19 @@ gdk_event_translate (GdkEvent *event,
event->property.atom = xevent->xproperty.atom;
event->property.time = xevent->xproperty.time;
event->property.state = xevent->xproperty.state;
if (wm_state_atom == 0)
wm_state_atom = gdk_atom_intern ("_NET_WM_STATE", FALSE);
if (wm_desktop_atom == 0)
wm_desktop_atom = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
if (event->property.atom == wm_state_atom ||
event->property.atom == wm_desktop_atom)
{
/* If window state changed, then synthesize those events. */
gdk_check_wm_state_changed (event->property.window);
}
break;
@ -1586,3 +1754,94 @@ gdk_x11_get_server_time (GdkWindow *window)
return xevent.xproperty.time;
}
gboolean
gdk_wmspec_supported (GdkAtom property)
{
static GdkAtom wmspec_check_atom = 0;
static GdkAtom wmspec_supported_atom = 0;
static GdkAtom *atoms = NULL;
static gulong n_atoms = 0;
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
Window *xwindow;
gulong i;
if (wmspec_check_window != None)
{
if (atoms == NULL)
return FALSE;
i = 0;
while (i < n_atoms)
{
if (atoms[i] == property)
return TRUE;
++i;
}
return FALSE;
}
if (atoms)
XFree (atoms);
atoms = NULL;
n_atoms = 0;
/* This function is very slow on every call if you are not running a
* spec-supporting WM. For now not optimized, because it isn't in
* any critical code paths, but if you used it somewhere that had to
* be fast you want to avoid "GTK is slow with old WMs" complaints.
* Probably at that point the function should be changed to query
* _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
*/
if (wmspec_check_atom == 0)
wmspec_check_atom = gdk_atom_intern ("_NET_SUPPORTING_WM_CHECK", FALSE);
if (wmspec_supported_atom == 0)
wmspec_supported_atom = gdk_atom_intern ("_NET_SUPPORTED", FALSE);
XGetWindowProperty (gdk_display, gdk_root_window,
wmspec_check_atom, 0, G_MAXLONG,
False, XA_WINDOW, &type, &format, &nitems,
&bytes_after, (guchar **)&xwindow);
if (type != XA_WINDOW)
return FALSE;
gdk_error_trap_push ();
/* Find out if this WM goes away, so we can reset everything. */
XSelectInput (gdk_display, *xwindow,
StructureNotifyMask);
gdk_flush ();
if (gdk_error_trap_pop ())
{
XFree (xwindow);
return FALSE;
}
XGetWindowProperty (gdk_display, gdk_root_window,
wmspec_supported_atom, 0, G_MAXLONG,
False, XA_ATOM, &type, &format, &n_atoms,
&bytes_after, (guchar **)&atoms);
if (type != XA_ATOM)
return FALSE;
wmspec_check_window = *xwindow;
XFree (xwindow);
/* since wmspec_check_window != None this isn't infinite. ;-) */
return gdk_wmspec_supported (property);
}

View File

@ -28,6 +28,7 @@
#include "gdkprivate-x11.h"
#include "gdkx.h"
#include "gdkregion.h"
#include "gdkinternals.h"
typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
typedef struct _GdkWindowParentPos GdkWindowParentPos;
@ -332,7 +333,7 @@ _gdk_window_move_resize_child (GdkWindow *window,
if (impl->position_info.no_bg)
gdk_window_tmp_reset_bg (window);
if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
XMapWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
impl->position_info = new_info;
@ -378,7 +379,7 @@ _gdk_window_move_resize_child (GdkWindow *window,
if (impl->position_info.no_bg)
gdk_window_tmp_reset_bg (window);
if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
XMapWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
impl->position_info = new_info;
@ -651,7 +652,7 @@ gdk_window_postmove (GdkWindow *window,
new_info.x, new_info.y, new_info.width, new_info.height);
}
if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
if (impl->position_info.no_bg)

View File

@ -737,4 +737,3 @@ gdk_send_xevent (Window window, gboolean propagate, glong event_mask,
return result && !gdk_error_code;
}

View File

@ -635,7 +635,12 @@ gdk_window_foreign_new (GdkNativeWindow anid)
impl->height = attrs.height;
private->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
private->mapped = (attrs.map_state != IsUnmapped);
if (attrs.map_state == IsUnmapped)
private->state = GDK_WINDOW_STATE_WITHDRAWN;
else
private->state = 0;
private->depth = attrs.depth;
gdk_drawable_ref (window);
@ -709,6 +714,73 @@ gdk_window_destroy_notify (GdkWindow *window)
gdk_drawable_unref (window);
}
static void
set_initial_hints (GdkWindow *window)
{
GdkWindowObject *private;
GdkAtom atoms[5];
gint i;
private = (GdkWindowObject*) window;
if (private->state & GDK_WINDOW_STATE_ICONIFIED)
{
XWMHints *wm_hints;
wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window));
if (!wm_hints)
wm_hints = XAllocWMHints ();
wm_hints->flags |= StateHint;
wm_hints->initial_state = IconicState;
XSetWMHints (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), wm_hints);
XFree (wm_hints);
}
/* We set the spec hints regardless of whether the spec is supported,
* since it can't hurt and it's kind of expensive to check whether
* it's supported.
*/
i = 0;
if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
{
atoms[i] = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE);
++i;
atoms[i] = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE);
++i;
}
if (private->state & GDK_WINDOW_STATE_STICKY)
{
atoms[i] = gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE);
++i;
}
if (i > 0)
{
XChangeProperty (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
gdk_atom_intern ("_NET_WM_STATE", FALSE),
XA_ATOM, 32, PropModeReplace,
(guchar*) atoms, i);
}
if (private->state & GDK_WINDOW_STATE_STICKY)
{
atoms[0] = 0xFFFFFFFF;
XChangeProperty (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
gdk_atom_intern ("_NET_WM_DESKTOP", FALSE),
XA_CARDINAL, 32, PropModeReplace,
(guchar*) atoms, 1);
}
}
void
gdk_window_show (GdkWindow *window)
{
@ -719,13 +791,23 @@ gdk_window_show (GdkWindow *window)
private = (GdkWindowObject*) window;
if (!private->destroyed)
{
private->mapped = TRUE;
XRaiseWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window));
if (!GDK_WINDOW_IS_MAPPED (window))
{
set_initial_hints (window);
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_WITHDRAWN,
0);
}
g_assert (GDK_WINDOW_IS_MAPPED (window));
if (GDK_WINDOW_IMPL_X11 (private->impl)->position_info.mapped)
XMapWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window));
XMapWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window));
}
}
@ -737,14 +819,36 @@ gdk_window_hide (GdkWindow *window)
g_return_if_fail (window != NULL);
private = (GdkWindowObject*) window;
/* You can't simply unmap toplevel windows. */
switch (private->window_type)
{
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP: /* ? */
gdk_window_withdraw (window);
return;
break;
case GDK_WINDOW_FOREIGN:
case GDK_WINDOW_ROOT:
case GDK_WINDOW_CHILD:
break;
}
if (!private->destroyed)
{
private->mapped = FALSE;
if (GDK_WINDOW_IS_MAPPED (window))
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_WITHDRAWN);
g_assert (!GDK_WINDOW_IS_MAPPED (window));
_gdk_window_clear_update_area (window);
XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window));
GDK_WINDOW_XID (window));
}
}
@ -757,8 +861,17 @@ gdk_window_withdraw (GdkWindow *window)
private = (GdkWindowObject*) window;
if (!private->destroyed)
XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), 0);
{
if (GDK_WINDOW_IS_MAPPED (window))
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_WITHDRAWN);
g_assert (!GDK_WINDOW_IS_MAPPED (window));
XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), 0);
}
}
void
@ -944,6 +1057,41 @@ gdk_window_lower (GdkWindow *window)
XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
void
gdk_window_focus (GdkWindow *window,
guint32 timestamp)
{
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
if (gdk_wmspec_supported (gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE)))
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
}
else
{
XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (window),
RevertToNone,
timestamp);
}
}
void
gdk_window_set_hints (GdkWindow *window,
gint x,
@ -1807,12 +1955,13 @@ gdk_window_set_icon_name (GdkWindow *window,
GUINT_TO_POINTER (TRUE));
set_text_property (window, gdk_atom_intern ("WM_ICON_NAME", FALSE), name);
}
}
void
gdk_window_iconify (GdkWindow *window)
{
Display *display;
GdkWindowObject *private;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
@ -1821,7 +1970,251 @@ gdk_window_iconify (GdkWindow *window)
return;
display = GDK_WINDOW_XDISPLAY (window);
XIconifyWindow (display, GDK_WINDOW_XWINDOW (window), DefaultScreen (display));
private = (GdkWindowObject*) window;
if (GDK_WINDOW_IS_MAPPED (window))
{
XIconifyWindow (display, GDK_WINDOW_XWINDOW (window), DefaultScreen (display));
}
else
{
/* Flip our client side flag, the real work happens on map. */
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_ICONIFIED);
}
}
void
gdk_window_deiconify (GdkWindow *window)
{
Display *display;
GdkWindowObject *private;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
display = GDK_WINDOW_XDISPLAY (window);
private = (GdkWindowObject*) window;
if (GDK_WINDOW_IS_MAPPED (window))
{
gdk_window_show (window);
}
else
{
/* Flip our client side flag, the real work happens on map. */
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_ICONIFIED,
0);
}
}
void
gdk_window_stick (GdkWindow *window)
{
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
/* "stick" means stick to all desktops _and_ do not scroll with the
* viewport. i.e. glue to the monitor glass in all cases.
*/
XEvent xev;
/* Request stick during viewport scroll */
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = gdk_atom_intern ("_NET_WM_STATE_ADD", FALSE);
xev.xclient.data.l[1] = gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE);
xev.xclient.data.l[2] = 0;
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
/* Request desktop 0xFFFFFFFF */
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0xFFFFFFFF;
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
}
else
{
/* Flip our client side flag, the real work happens on map. */
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_STICKY);
}
}
void
gdk_window_unstick (GdkWindow *window)
{
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
XEvent xev;
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
gulong *current_desktop;
/* Request unstick from viewport */
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = gdk_atom_intern ("_NET_WM_STATE_REMOVE", FALSE);
xev.xclient.data.l[1] = gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE);
xev.xclient.data.l[2] = 0;
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
/* Get current desktop, then set it; this is a race, but not
* one that matters much in practice.
*/
XGetWindowProperty (gdk_display, gdk_root_window,
gdk_atom_intern ("_NET_CURRENT_DESKTOP", FALSE),
0, G_MAXLONG,
False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, (guchar **)&current_desktop);
if (type == XA_CARDINAL)
{
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_WM_DESKTOP", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = *current_desktop;
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFree (current_desktop);
}
}
else
{
/* Flip our client side flag, the real work happens on map. */
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_STICKY,
0);
}
}
void
gdk_window_maximize (GdkWindow *window)
{
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = gdk_atom_intern ("_NET_WM_STATE_ADD", FALSE);
xev.xclient.data.l[1] = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE);
xev.xclient.data.l[2] = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE);
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
}
else
{
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_MAXIMIZED);
}
}
void
gdk_window_unmaximize (GdkWindow *window)
{
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = GDK_WINDOW_XWINDOW (window);
xev.xclient.display = gdk_display;
xev.xclient.message_type = gdk_atom_intern ("_NET_WM_STATE", FALSE);
xev.xclient.format = 32;
xev.xclient.data.l[0] = gdk_atom_intern ("_NET_WM_STATE_REMOVE", FALSE);
xev.xclient.data.l[1] = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE);
xev.xclient.data.l[2] = gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE);
XSendEvent (gdk_display, gdk_root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
}
else
{
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_MAXIMIZED,
0);
}
}
void

View File

@ -185,6 +185,9 @@ gpointer gdk_xid_table_lookup (XID xid);
guint32 gdk_x11_get_server_time (GdkWindow *window);
/* returns TRUE if we support the given WM spec feature */
gboolean gdk_wmspec_supported (GdkAtom property);
#define gdk_window_lookup(xid) ((GdkWindow*) gdk_xid_table_lookup (xid))
#define gdk_pixmap_lookup(xid) ((GdkPixmap*) gdk_xid_table_lookup (xid))
#define gdk_font_lookup(xid) ((GdkFont*) gdk_xid_table_lookup (xid))

View File

@ -888,6 +888,7 @@ gtk_main_do_event (GdkEvent *event)
case GDK_SELECTION_NOTIFY:
case GDK_CLIENT_EVENT:
case GDK_VISIBILITY_NOTIFY:
case GDK_WINDOW_STATE:
gtk_widget_event (event_widget, event);
break;

View File

@ -99,6 +99,7 @@ enum {
CLIENT_EVENT,
NO_EXPOSE_EVENT,
VISIBILITY_NOTIFY_EVENT,
WINDOW_STATE_EVENT,
DEBUG_MSG,
LAST_SIGNAL
};
@ -314,6 +315,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->focus_out_event = NULL;
klass->map_event = NULL;
klass->unmap_event = NULL;
klass->window_state_event = NULL;
klass->property_notify_event = gtk_selection_property_notify;
klass->selection_clear_event = gtk_selection_clear;
klass->selection_request_event = gtk_selection_request;
@ -775,6 +777,14 @@ gtk_widget_class_init (GtkWidgetClass *klass)
gtk_marshal_BOOLEAN__POINTER,
GTK_TYPE_BOOL, 1,
GTK_TYPE_GDK_EVENT);
widget_signals[WINDOW_STATE_EVENT] =
gtk_signal_new ("window_state_event",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkWidgetClass, no_expose_event),
gtk_marshal_BOOLEAN__POINTER,
GTK_TYPE_BOOL, 1,
GTK_TYPE_GDK_EVENT);
widget_signals[DEBUG_MSG] =
gtk_signal_new ("debug_msg",
GTK_RUN_LAST | GTK_RUN_ACTION,
@ -2337,6 +2347,9 @@ gtk_widget_event (GtkWidget *widget,
case GDK_UNMAP:
signal_num = UNMAP_EVENT;
break;
case GDK_WINDOW_STATE:
signal_num = WINDOW_STATE_EVENT;
break;
case GDK_PROPERTY_NOTIFY:
signal_num = PROPERTY_NOTIFY_EVENT;
break;

View File

@ -325,7 +325,9 @@ struct _GtkWidgetClass
GdkEventClient *event);
gint (* no_expose_event) (GtkWidget *widget,
GdkEventAny *event);
gint (* window_state_event) (GtkWidget *widget,
GdkEventWindowState *event);
/* selection */
void (* selection_get) (GtkWidget *widget,
GtkSelectionData *selection_data,

View File

@ -1247,7 +1247,8 @@ static void
gtk_window_map (GtkWidget *widget)
{
GtkWindow *window;
GdkWindow *toplevel;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WINDOW (widget));
@ -1260,7 +1261,28 @@ gtk_window_map (GtkWidget *widget)
!GTK_WIDGET_MAPPED (window->bin.child))
gtk_widget_map (window->bin.child);
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (window->maximize_initially)
gdk_window_maximize (toplevel);
else
gdk_window_unmaximize (toplevel);
if (window->stick_initially)
gdk_window_stick (toplevel);
else
gdk_window_unstick (toplevel);
if (window->iconify_initially)
gdk_window_iconify (toplevel);
else
gdk_window_deiconify (toplevel);
gdk_window_show (widget->window);
if (window->frame)
gdk_window_show (window->frame);
}
@ -1398,7 +1420,8 @@ gtk_window_realize (GtkWidget *widget)
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
if (window->frame)
gtk_style_set_background (widget->style, window->frame, GTK_STATE_NORMAL);
/* This is a bad hack to set the window background. */
gtk_window_paint (widget, NULL);
if (window->transient_parent &&
@ -1407,7 +1430,6 @@ gtk_window_realize (GtkWidget *widget)
GTK_WIDGET (window->transient_parent)->window);
}
static void
gtk_window_unrealize (GtkWidget *widget)
{
@ -2786,3 +2808,278 @@ gtk_window_set_frame_dimensions (GtkWindow *window,
}
/**
* gtk_window_present:
* @window: a #GtkWindow
*
* Presents a window to the user. This may mean raising the window
* in the stacking order, deiconifying it, moving it to the current
* desktop, and/or giving it the keyboard focus, possibly dependent
* on the user's platform, window manager, and preferences.
*
* If @window is hidden, this function calls gtk_widget_show()
* as well.
*
* This function should be used when the user tries to open a window
* that's already open. Say for example the preferences dialog is
* currently open, and the user chooses Preferences from the menu
* a second time; use gtk_window_present() to move the already-open dialog
* where the user can see it.
*
**/
void
gtk_window_present (GtkWindow *window)
{
GtkWidget *widget;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
if (GTK_WIDGET_VISIBLE (window))
{
g_assert (widget->window != NULL);
gdk_window_show (widget->window);
/* note that gdk_window_focus() will also move the window to
* the current desktop, for WM spec compliant window managers.
*/
gdk_window_focus (widget->window,
gtk_get_current_event_time ());
}
else
{
gtk_widget_show (widget);
}
}
/**
* gtk_window_iconify:
* @window: a #GtkWindow
*
* Asks to iconify @window. Note that you shouldn't assume the window
* is definitely iconified afterward, because other entities (e.g. the
* user or window manager) could deiconify it again, or there may not
* be a window manager in which case iconification isn't possible,
* etc. But normally the window will end up iconified. Just don't write
* code that crashes if not.
*
* It's permitted to call this function before showing a window,
* in which case the window will be iconified before it ever appears
* onscreen.
*
* You can track iconification via the "window_state_event" signal
* on #GtkWidget.
*
**/
void
gtk_window_iconify (GtkWindow *window)
{
GtkWidget *widget;
GdkWindow *toplevel;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
window->iconify_initially = TRUE;
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (toplevel != NULL)
gdk_window_iconify (toplevel);
}
/**
* gtk_window_deiconify:
* @window: a #GtkWindow
*
* Asks to deiconify @window. Note that you shouldn't assume the
* window is definitely deiconified afterward, because other entities
* (e.g. the user or window manager) could iconify it again before
* your code which assumes deiconification gets to run.
*
* You can track iconification via the "window_state_event" signal
* on #GtkWidget.
**/
void
gtk_window_deiconify (GtkWindow *window)
{
GtkWidget *widget;
GdkWindow *toplevel;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
window->iconify_initially = FALSE;
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (toplevel != NULL)
gdk_window_deiconify (toplevel);
}
/**
* gtk_window_stick:
* @window: a #GtkWindow
*
* Asks to stick @window, which means that it will appear on all user
* desktops. Note that you shouldn't assume the window is definitely
* stuck afterward, because other entities (e.g. the user or window
* manager) could unstick it again, and some window managers do not
* support sticking windows. But normally the window will end up
* stuck. Just don't write code that crashes if not.
*
* It's permitted to call this function before showing a window.
*
* You can track stickiness via the "window_state_event" signal
* on #GtkWidget.
*
**/
void
gtk_window_stick (GtkWindow *window)
{
GtkWidget *widget;
GdkWindow *toplevel;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
window->stick_initially = TRUE;
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (toplevel != NULL)
gdk_window_stick (toplevel);
}
/**
* gtk_window_unstick:
* @window: a #GtkWindow
*
* Asks to unstick @window, which means that it will appear on only
* one of the user's desktops. Note that you shouldn't assume the
* window is definitely unstuck afterward, because other entities
* (e.g. the user or window manager) could stick it again. But
* normally the window will end up stuck. Just don't write code that
* crashes if not.
*
* You can track stickiness via the "window_state_event" signal
* on #GtkWidget.
*
**/
void
gtk_window_unstick (GtkWindow *window)
{
GtkWidget *widget;
GdkWindow *toplevel;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
window->stick_initially = FALSE;
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (toplevel != NULL)
gdk_window_unstick (toplevel);
}
/**
* gtk_window_maximize:
* @window: a #GtkWindow
*
* Asks to maximize @window, so that it becomes full-screen. Note that
* you shouldn't assume the window is definitely maximized afterward,
* because other entities (e.g. the user or window manager) could
* unmaximize it again, and not all window managers support
* maximization. But normally the window will end up maximized. Just
* don't write code that crashes if not.
*
* It's permitted to call this function before showing a window,
* in which case the window will be maximized when it appears onscreen
* initially.
*
* You can track maximization via the "window_state_event" signal
* on #GtkWidget.
*
**/
void
gtk_window_maximize (GtkWindow *window)
{
GtkWidget *widget;
GdkWindow *toplevel;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
window->maximize_initially = TRUE;
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (toplevel != NULL)
gdk_window_maximize (toplevel);
}
/**
* gtk_window_unmaximize:
* @window: a #GtkWindow
*
* Asks to unmaximize @window. Note that you shouldn't assume the
* window is definitely unmaximized afterward, because other entities
* (e.g. the user or window manager) could maximize it again, and not
* all window managers honor requests to unmaximize. But normally the
* window will end up unmaximized. Just don't write code that crashes
* if not.
*
* You can track maximization via the "window_state_event" signal
* on #GtkWidget.
*
**/
void
gtk_window_unmaximize (GtkWindow *window)
{
GtkWidget *widget;
GdkWindow *toplevel;
g_return_if_fail (GTK_IS_WINDOW (window));
widget = GTK_WIDGET (window);
window->maximize_initially = FALSE;
if (window->frame)
toplevel = window->frame;
else
toplevel = widget->window;
if (toplevel != NULL)
gdk_window_unmaximize (toplevel);
}

View File

@ -85,6 +85,11 @@ struct _GtkWindow
guint has_frame : 1;
/* gtk_window_iconify() called before realization */
guint iconify_initially : 1;
guint stick_initially : 1;
guint maximize_initially : 1;
guint frame_left;
guint frame_top;
guint frame_right;
@ -153,6 +158,14 @@ GList* gtk_window_list_toplevels (void);
/* Get the "built-in" accel group (convenience thing) */
GtkAccelGroup* gtk_window_get_default_accel_group (GtkWindow *window);
void gtk_window_present (GtkWindow *window);
void gtk_window_iconify (GtkWindow *window);
void gtk_window_deiconify (GtkWindow *window);
void gtk_window_stick (GtkWindow *window);
void gtk_window_unstick (GtkWindow *window);
void gtk_window_maximize (GtkWindow *window);
void gtk_window_unmaximize (GtkWindow *window);
/* --- internal functions --- */
void gtk_window_set_focus (GtkWindow *window,

View File

@ -7663,6 +7663,199 @@ create_wmhints (void)
gtk_widget_destroy (window);
}
/*
* Window state tracking
*/
static gint
window_state_callback (GtkWidget *widget,
GdkEventWindowState *event,
gpointer data)
{
GtkWidget *label = data;
gchar *msg;
msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
"withdrawn" : "not withdrawn", ", ",
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
"iconified" : "not iconified", ", ",
(event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
"sticky" : "not sticky", ", ",
(event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
"maximized" : "not maximized",
NULL);
gtk_label_set_text (GTK_LABEL (label), msg);
g_free (msg);
return FALSE;
}
static GtkWidget*
tracking_label (GtkWidget *window)
{
GtkWidget *label;
GtkWidget *hbox;
GtkWidget *button;
hbox = gtk_hbox_new (FALSE, 5);
gtk_signal_connect_object (GTK_OBJECT (hbox),
"destroy",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
GTK_OBJECT (window));
label = gtk_label_new ("<no window state events received>");
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (window),
"window_state_event",
GTK_SIGNAL_FUNC (window_state_callback),
label);
button = gtk_button_new_with_label ("Deiconify");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_deiconify),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Iconify");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_iconify),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Present");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_present),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Show");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_widget_show),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (hbox);
return hbox;
}
static GtkWidget*
get_state_controls (GtkWidget *window)
{
GtkWidget *vbox;
GtkWidget *button;
vbox = gtk_vbox_new (FALSE, 0);
button = gtk_button_new_with_label ("Stick");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_stick),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Unstick");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_unstick),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Maximize");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_maximize),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Unmaximize");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_unmaximize),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Iconify");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_iconify),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Hide (withdraw)");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_widget_hide),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (vbox);
return vbox;
}
void
create_window_states (void)
{
static GtkWidget *window = NULL;
GtkWidget *label;
GtkWidget *box1;
GtkWidget *iconified;
GtkWidget *normal;
GtkWidget *controls;
if (!window)
{
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
&window);
gtk_window_set_title (GTK_WINDOW (window), "Window states");
box1 = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box1);
iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_iconify (iconified);
gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
controls = get_state_controls (iconified);
gtk_container_add (GTK_CONTAINER (iconified), controls);
normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
controls = get_state_controls (normal);
gtk_container_add (GTK_CONTAINER (normal), controls);
label = tracking_label (iconified);
gtk_container_add (GTK_CONTAINER (box1), label);
label = tracking_label (normal);
gtk_container_add (GTK_CONTAINER (box1), label);
gtk_widget_show_all (iconified);
gtk_widget_show_all (normal);
gtk_widget_show_all (box1);
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
}
/*
* GtkProgressBar
*/
@ -9361,6 +9554,7 @@ create_main_window (void)
{ "tooltips", create_tooltips },
{ "tree", create_tree_mode_window},
{ "WM hints", create_wmhints },
{ "window states", create_window_states }
};
int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
GtkWidget *window;

View File

@ -7663,6 +7663,199 @@ create_wmhints (void)
gtk_widget_destroy (window);
}
/*
* Window state tracking
*/
static gint
window_state_callback (GtkWidget *widget,
GdkEventWindowState *event,
gpointer data)
{
GtkWidget *label = data;
gchar *msg;
msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
"withdrawn" : "not withdrawn", ", ",
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
"iconified" : "not iconified", ", ",
(event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
"sticky" : "not sticky", ", ",
(event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
"maximized" : "not maximized",
NULL);
gtk_label_set_text (GTK_LABEL (label), msg);
g_free (msg);
return FALSE;
}
static GtkWidget*
tracking_label (GtkWidget *window)
{
GtkWidget *label;
GtkWidget *hbox;
GtkWidget *button;
hbox = gtk_hbox_new (FALSE, 5);
gtk_signal_connect_object (GTK_OBJECT (hbox),
"destroy",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
GTK_OBJECT (window));
label = gtk_label_new ("<no window state events received>");
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (window),
"window_state_event",
GTK_SIGNAL_FUNC (window_state_callback),
label);
button = gtk_button_new_with_label ("Deiconify");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_deiconify),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Iconify");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_iconify),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Present");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_present),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Show");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_widget_show),
GTK_OBJECT (window));
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (hbox);
return hbox;
}
static GtkWidget*
get_state_controls (GtkWidget *window)
{
GtkWidget *vbox;
GtkWidget *button;
vbox = gtk_vbox_new (FALSE, 0);
button = gtk_button_new_with_label ("Stick");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_stick),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Unstick");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_unstick),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Maximize");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_maximize),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Unmaximize");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_unmaximize),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Iconify");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_window_iconify),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Hide (withdraw)");
gtk_signal_connect_object (GTK_WIDGET (button),
"clicked",
GTK_SIGNAL_FUNC (gtk_widget_hide),
GTK_OBJECT (window));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (vbox);
return vbox;
}
void
create_window_states (void)
{
static GtkWidget *window = NULL;
GtkWidget *label;
GtkWidget *box1;
GtkWidget *iconified;
GtkWidget *normal;
GtkWidget *controls;
if (!window)
{
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
&window);
gtk_window_set_title (GTK_WINDOW (window), "Window states");
box1 = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box1);
iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_iconify (iconified);
gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
controls = get_state_controls (iconified);
gtk_container_add (GTK_CONTAINER (iconified), controls);
normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
controls = get_state_controls (normal);
gtk_container_add (GTK_CONTAINER (normal), controls);
label = tracking_label (iconified);
gtk_container_add (GTK_CONTAINER (box1), label);
label = tracking_label (normal);
gtk_container_add (GTK_CONTAINER (box1), label);
gtk_widget_show_all (iconified);
gtk_widget_show_all (normal);
gtk_widget_show_all (box1);
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
}
/*
* GtkProgressBar
*/
@ -9361,6 +9554,7 @@ create_main_window (void)
{ "tooltips", create_tooltips },
{ "tree", create_tree_mode_window},
{ "WM hints", create_wmhints },
{ "window states", create_window_states }
};
int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
GtkWidget *window;