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

@ -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);
}