Don't resize windows when request is rejected by WM. Only use the resize

Sat Mar 14 00:03:34 1998  Owen Taylor  <owt1@cornell.edu>

	* gtk/gtkwindow.c:
          Don't resize windows when request is rejected by WM.
	  Only use the resize count to guess whether a Configure
	  event was a rejection by the WM, or a move.

	* gdk/gdk.c gdk/gdktypes.h:
	  - Don't XDestroyWindow foreign windows (If they're a child of
	  one of our windows, reparent them to root and send them a WM
	  delete event, otherwise, just delete the GTK structure.)
	  Handle notification of their deletion properly.
          (Made foreign windows a seperate window type to do this)

	* gtk/gtkobject.c (gtk_object_set_data_full):
	  Call the DestroyNotify when replacing the object data.
This commit is contained in:
Owen Taylor 1998-03-14 05:15:16 +00:00 committed by Owen Taylor
parent 294cfcdb22
commit bc98ea9ce1
4 changed files with 186 additions and 66 deletions

View File

@ -110,6 +110,7 @@ typedef void* GdkIM;
* and pixmaps transparently. (ie. You shouldn't pass a * and pixmaps transparently. (ie. You shouldn't pass a
* pixmap to any procedure which accepts a window with the * pixmap to any procedure which accepts a window with the
* exception of the drawing functions). * exception of the drawing functions).
* Foreign: A window that actually belongs to another application
*/ */
typedef enum typedef enum
{ {
@ -118,7 +119,8 @@ typedef enum
GDK_WINDOW_CHILD, GDK_WINDOW_CHILD,
GDK_WINDOW_DIALOG, GDK_WINDOW_DIALOG,
GDK_WINDOW_TEMP, GDK_WINDOW_TEMP,
GDK_WINDOW_PIXMAP GDK_WINDOW_PIXMAP,
GDK_WINDOW_FOREIGN
} GdkWindowType; } GdkWindowType;
/* Classes of windows. /* Classes of windows.

View File

@ -414,13 +414,21 @@ gdk_window_foreign_new (guint32 anid)
GdkWindow *window; GdkWindow *window;
GdkWindowPrivate *private; GdkWindowPrivate *private;
XWindowAttributes attrs; XWindowAttributes attrs;
Window root, parent;
Window *children;
guint nchildren;
private = g_new (GdkWindowPrivate, 1); private = g_new (GdkWindowPrivate, 1);
window = (GdkWindow*) private; window = (GdkWindow*) private;
XGetWindowAttributes (gdk_display, anid, &attrs); XGetWindowAttributes (gdk_display, anid, &attrs);
private->parent = NULL; /* FIXME: This is pretty expensive. Maybe the caller should supply
* the parent */
XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
XFree (children);
private->parent = gdk_xid_table_lookup (parent);
private->xwindow = anid; private->xwindow = anid;
private->xdisplay = gdk_display; private->xdisplay = gdk_display;
private->x = attrs.x; private->x = attrs.x;
@ -429,15 +437,20 @@ gdk_window_foreign_new (guint32 anid)
private->height = attrs.height; private->height = attrs.height;
private->resize_count = 0; private->resize_count = 0;
private->ref_count = 1; private->ref_count = 1;
if (anid == attrs.root) private->window_type = GDK_WINDOW_FOREIGN;
private->window_type = GDK_WINDOW_ROOT;
else
private->window_type = GDK_WINDOW_TOPLEVEL;
/* the above is probably wrong, but it may not be worth the extra
X call to get it right */
private->destroyed = FALSE; private->destroyed = FALSE;
private->extension_events = 0; private->extension_events = 0;
private->dnd_drag_data_type = None;
private->dnd_drag_data_typesavail =
private->dnd_drop_data_typesavail = NULL;
private->dnd_drop_enabled = private->dnd_drag_enabled =
private->dnd_drag_accepted = private->dnd_drag_datashow =
private->dnd_drop_data_numtypesavail =
private->dnd_drag_data_numtypesavail = 0;
private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
private->filters = NULL; private->filters = NULL;
window->user_data = NULL; window->user_data = NULL;
@ -455,7 +468,8 @@ gdk_window_foreign_new (guint32 anid)
window. */ window. */
static void static void
gdk_window_internal_destroy (GdkWindow *window, int xdestroy) gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
gboolean our_destroy)
{ {
GdkWindowPrivate *private; GdkWindowPrivate *private;
GdkWindowPrivate *temp_private; GdkWindowPrivate *temp_private;
@ -473,7 +487,10 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
case GDK_WINDOW_CHILD: case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG: case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP: case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
if (!private->destroyed) if (!private->destroyed)
{
if (private->window_type != GDK_WINDOW_FOREIGN)
{ {
children = gdk_window_get_children (window); children = gdk_window_get_children (window);
tmp = children; tmp = children;
@ -485,10 +502,12 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
temp_private = (GdkWindowPrivate*) temp_window; temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private) if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE); gdk_window_internal_destroy (temp_window, FALSE,
our_destroy);
} }
g_list_free (children); g_list_free (children);
}
if (private->extension_events != 0) if (private->extension_events != 0)
gdk_input_window_destroy (window); gdk_input_window_destroy (window);
@ -504,8 +523,47 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
private->dnd_drop_data_typesavail = NULL; private->dnd_drop_data_typesavail = NULL;
} }
if (xdestroy) if (private->filters)
{
tmp = private->filters;
while (tmp)
{
g_free (tmp->data);
tmp = tmp->next;
}
g_list_free (private->filters);
private->filters = NULL;
}
if (private->window_type == GDK_WINDOW_FOREIGN)
{
if (our_destroy && (private->parent != NULL))
{
/* It's somebody elses window, but in our heirarchy,
* so reparent it to the root window, and then send
* it a delete event, as if we were a WM
*/
XClientMessageEvent xevent;
gdk_window_hide (window);
gdk_window_reparent (window, NULL, 0, 0);
xevent.type = ClientMessage;
xevent.window = private->xwindow;
xevent.message_type = gdk_wm_protocols;
xevent.format = 32;
xevent.data.l[0] = gdk_wm_delete_window;
xevent.data.l[1] = CurrentTime;
XSendEvent (private->xdisplay, private->xwindow,
False, 0, (XEvent *)&xevent);
}
}
else if (xdestroy)
XDestroyWindow (private->xdisplay, private->xwindow); XDestroyWindow (private->xdisplay, private->xwindow);
private->destroyed = TRUE; private->destroyed = TRUE;
} }
break; break;
@ -526,7 +584,7 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
void void
gdk_window_destroy (GdkWindow *window) gdk_window_destroy (GdkWindow *window)
{ {
gdk_window_internal_destroy (window, TRUE); gdk_window_internal_destroy (window, TRUE, TRUE);
gdk_window_unref (window); gdk_window_unref (window);
} }
@ -541,6 +599,14 @@ gdk_window_destroy_notify (GdkWindow *window)
private = (GdkWindowPrivate*) window; private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
if (private->window_type == GDK_WINDOW_FOREIGN)
gdk_window_internal_destroy (window, FALSE, FALSE);
else
g_warning ("Window %#lx unexpectedly destroyed", private->xwindow);
}
gdk_xid_table_remove (private->xwindow); gdk_xid_table_remove (private->xwindow);
gdk_window_unref (window); gdk_window_unref (window);
} }

View File

@ -414,13 +414,21 @@ gdk_window_foreign_new (guint32 anid)
GdkWindow *window; GdkWindow *window;
GdkWindowPrivate *private; GdkWindowPrivate *private;
XWindowAttributes attrs; XWindowAttributes attrs;
Window root, parent;
Window *children;
guint nchildren;
private = g_new (GdkWindowPrivate, 1); private = g_new (GdkWindowPrivate, 1);
window = (GdkWindow*) private; window = (GdkWindow*) private;
XGetWindowAttributes (gdk_display, anid, &attrs); XGetWindowAttributes (gdk_display, anid, &attrs);
private->parent = NULL; /* FIXME: This is pretty expensive. Maybe the caller should supply
* the parent */
XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
XFree (children);
private->parent = gdk_xid_table_lookup (parent);
private->xwindow = anid; private->xwindow = anid;
private->xdisplay = gdk_display; private->xdisplay = gdk_display;
private->x = attrs.x; private->x = attrs.x;
@ -429,15 +437,20 @@ gdk_window_foreign_new (guint32 anid)
private->height = attrs.height; private->height = attrs.height;
private->resize_count = 0; private->resize_count = 0;
private->ref_count = 1; private->ref_count = 1;
if (anid == attrs.root) private->window_type = GDK_WINDOW_FOREIGN;
private->window_type = GDK_WINDOW_ROOT;
else
private->window_type = GDK_WINDOW_TOPLEVEL;
/* the above is probably wrong, but it may not be worth the extra
X call to get it right */
private->destroyed = FALSE; private->destroyed = FALSE;
private->extension_events = 0; private->extension_events = 0;
private->dnd_drag_data_type = None;
private->dnd_drag_data_typesavail =
private->dnd_drop_data_typesavail = NULL;
private->dnd_drop_enabled = private->dnd_drag_enabled =
private->dnd_drag_accepted = private->dnd_drag_datashow =
private->dnd_drop_data_numtypesavail =
private->dnd_drag_data_numtypesavail = 0;
private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
private->filters = NULL; private->filters = NULL;
window->user_data = NULL; window->user_data = NULL;
@ -455,7 +468,8 @@ gdk_window_foreign_new (guint32 anid)
window. */ window. */
static void static void
gdk_window_internal_destroy (GdkWindow *window, int xdestroy) gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
gboolean our_destroy)
{ {
GdkWindowPrivate *private; GdkWindowPrivate *private;
GdkWindowPrivate *temp_private; GdkWindowPrivate *temp_private;
@ -473,7 +487,10 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
case GDK_WINDOW_CHILD: case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG: case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP: case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
if (!private->destroyed) if (!private->destroyed)
{
if (private->window_type != GDK_WINDOW_FOREIGN)
{ {
children = gdk_window_get_children (window); children = gdk_window_get_children (window);
tmp = children; tmp = children;
@ -485,10 +502,12 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
temp_private = (GdkWindowPrivate*) temp_window; temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private) if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE); gdk_window_internal_destroy (temp_window, FALSE,
our_destroy);
} }
g_list_free (children); g_list_free (children);
}
if (private->extension_events != 0) if (private->extension_events != 0)
gdk_input_window_destroy (window); gdk_input_window_destroy (window);
@ -504,8 +523,47 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
private->dnd_drop_data_typesavail = NULL; private->dnd_drop_data_typesavail = NULL;
} }
if (xdestroy) if (private->filters)
{
tmp = private->filters;
while (tmp)
{
g_free (tmp->data);
tmp = tmp->next;
}
g_list_free (private->filters);
private->filters = NULL;
}
if (private->window_type == GDK_WINDOW_FOREIGN)
{
if (our_destroy && (private->parent != NULL))
{
/* It's somebody elses window, but in our heirarchy,
* so reparent it to the root window, and then send
* it a delete event, as if we were a WM
*/
XClientMessageEvent xevent;
gdk_window_hide (window);
gdk_window_reparent (window, NULL, 0, 0);
xevent.type = ClientMessage;
xevent.window = private->xwindow;
xevent.message_type = gdk_wm_protocols;
xevent.format = 32;
xevent.data.l[0] = gdk_wm_delete_window;
xevent.data.l[1] = CurrentTime;
XSendEvent (private->xdisplay, private->xwindow,
False, 0, (XEvent *)&xevent);
}
}
else if (xdestroy)
XDestroyWindow (private->xdisplay, private->xwindow); XDestroyWindow (private->xdisplay, private->xwindow);
private->destroyed = TRUE; private->destroyed = TRUE;
} }
break; break;
@ -526,7 +584,7 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
void void
gdk_window_destroy (GdkWindow *window) gdk_window_destroy (GdkWindow *window)
{ {
gdk_window_internal_destroy (window, TRUE); gdk_window_internal_destroy (window, TRUE, TRUE);
gdk_window_unref (window); gdk_window_unref (window);
} }
@ -541,6 +599,14 @@ gdk_window_destroy_notify (GdkWindow *window)
private = (GdkWindowPrivate*) window; private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
if (private->window_type == GDK_WINDOW_FOREIGN)
gdk_window_internal_destroy (window, FALSE, FALSE);
else
g_warning ("Window %#lx unexpectedly destroyed", private->xwindow);
}
gdk_xid_table_remove (private->xwindow); gdk_xid_table_remove (private->xwindow);
gdk_window_unref (window); gdk_window_unref (window);
} }

View File

@ -718,7 +718,8 @@ gtk_window_configure_event (GtkWidget *widget,
/* If the window was merely moved, do nothing */ /* If the window was merely moved, do nothing */
if ((widget->allocation.width == event->width) && if ((widget->allocation.width == event->width) &&
(widget->allocation.height == event->height)) (widget->allocation.height == event->height) &&
(window->resize_count == 0))
return FALSE; return FALSE;
window = GTK_WINDOW (widget); window = GTK_WINDOW (widget);
@ -737,20 +738,8 @@ gtk_window_configure_event (GtkWidget *widget,
gtk_widget_map (window->bin.child); gtk_widget_map (window->bin.child);
if (window->resize_count > 0) if (window->resize_count > 0)
{
window->resize_count -= 1; window->resize_count -= 1;
if ((window->resize_count == 0) &&
((event->width != widget->requisition.width) ||
(event->height != widget->requisition.height)))
{
window->resize_count = 1;
gdk_window_resize (widget->window,
widget->requisition.width,
widget->requisition.height);
}
}
window->handling_resize = FALSE; window->handling_resize = FALSE;
return FALSE; return FALSE;
@ -1068,14 +1057,11 @@ gtk_real_window_move_resize (GtkWindow *window,
(width < widget->requisition.width) || (width < widget->requisition.width) ||
(height < widget->requisition.height)) (height < widget->requisition.height))
{ {
if (window->resize_count == 0) window->resize_count += 1;
{
window->resize_count = 1;
gdk_window_resize (widget->window, gdk_window_resize (widget->window,
widget->requisition.width, widget->requisition.width,
widget->requisition.height); widget->requisition.height);
} }
}
else else
{ {
/* The window hasn't changed size but one of its children /* The window hasn't changed size but one of its children