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
* pixmap to any procedure which accepts a window with the
* exception of the drawing functions).
* Foreign: A window that actually belongs to another application
*/
typedef enum
{
@ -118,7 +119,8 @@ typedef enum
GDK_WINDOW_CHILD,
GDK_WINDOW_DIALOG,
GDK_WINDOW_TEMP,
GDK_WINDOW_PIXMAP
GDK_WINDOW_PIXMAP,
GDK_WINDOW_FOREIGN
} GdkWindowType;
/* Classes of windows.

View File

@ -414,13 +414,21 @@ gdk_window_foreign_new (guint32 anid)
GdkWindow *window;
GdkWindowPrivate *private;
XWindowAttributes attrs;
Window root, parent;
Window *children;
guint nchildren;
private = g_new (GdkWindowPrivate, 1);
window = (GdkWindow*) private;
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->xdisplay = gdk_display;
private->x = attrs.x;
@ -429,15 +437,20 @@ gdk_window_foreign_new (guint32 anid)
private->height = attrs.height;
private->resize_count = 0;
private->ref_count = 1;
if (anid == attrs.root)
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->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
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;
window->user_data = NULL;
@ -455,7 +468,8 @@ gdk_window_foreign_new (guint32 anid)
window. */
static void
gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
gboolean our_destroy)
{
GdkWindowPrivate *private;
GdkWindowPrivate *temp_private;
@ -473,23 +487,28 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
if (!private->destroyed)
{
children = gdk_window_get_children (window);
tmp = children;
while (tmp)
if (private->window_type != GDK_WINDOW_FOREIGN)
{
temp_window = tmp->data;
tmp = tmp->next;
children = gdk_window_get_children (window);
tmp = children;
temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE);
while (tmp)
{
temp_window = tmp->data;
tmp = tmp->next;
temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE,
our_destroy);
}
g_list_free (children);
}
g_list_free (children);
if (private->extension_events != 0)
gdk_input_window_destroy (window);
@ -504,8 +523,47 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
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);
private->destroyed = TRUE;
}
break;
@ -526,7 +584,7 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
void
gdk_window_destroy (GdkWindow *window)
{
gdk_window_internal_destroy (window, TRUE);
gdk_window_internal_destroy (window, TRUE, TRUE);
gdk_window_unref (window);
}
@ -541,6 +599,14 @@ gdk_window_destroy_notify (GdkWindow *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_window_unref (window);
}

View File

@ -414,13 +414,21 @@ gdk_window_foreign_new (guint32 anid)
GdkWindow *window;
GdkWindowPrivate *private;
XWindowAttributes attrs;
Window root, parent;
Window *children;
guint nchildren;
private = g_new (GdkWindowPrivate, 1);
window = (GdkWindow*) private;
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->xdisplay = gdk_display;
private->x = attrs.x;
@ -429,15 +437,20 @@ gdk_window_foreign_new (guint32 anid)
private->height = attrs.height;
private->resize_count = 0;
private->ref_count = 1;
if (anid == attrs.root)
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->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
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;
window->user_data = NULL;
@ -455,7 +468,8 @@ gdk_window_foreign_new (guint32 anid)
window. */
static void
gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
gboolean our_destroy)
{
GdkWindowPrivate *private;
GdkWindowPrivate *temp_private;
@ -473,23 +487,28 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
if (!private->destroyed)
{
children = gdk_window_get_children (window);
tmp = children;
while (tmp)
if (private->window_type != GDK_WINDOW_FOREIGN)
{
temp_window = tmp->data;
tmp = tmp->next;
children = gdk_window_get_children (window);
tmp = children;
temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE);
while (tmp)
{
temp_window = tmp->data;
tmp = tmp->next;
temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE,
our_destroy);
}
g_list_free (children);
}
g_list_free (children);
if (private->extension_events != 0)
gdk_input_window_destroy (window);
@ -504,8 +523,47 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
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);
private->destroyed = TRUE;
}
break;
@ -526,7 +584,7 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy)
void
gdk_window_destroy (GdkWindow *window)
{
gdk_window_internal_destroy (window, TRUE);
gdk_window_internal_destroy (window, TRUE, TRUE);
gdk_window_unref (window);
}
@ -541,6 +599,14 @@ gdk_window_destroy_notify (GdkWindow *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_window_unref (window);
}

View File

@ -718,7 +718,8 @@ gtk_window_configure_event (GtkWidget *widget,
/* If the window was merely moved, do nothing */
if ((widget->allocation.width == event->width) &&
(widget->allocation.height == event->height))
(widget->allocation.height == event->height) &&
(window->resize_count == 0))
return FALSE;
window = GTK_WINDOW (widget);
@ -737,19 +738,7 @@ gtk_window_configure_event (GtkWidget *widget,
gtk_widget_map (window->bin.child);
if (window->resize_count > 0)
{
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->resize_count -= 1;
window->handling_resize = FALSE;
@ -1068,13 +1057,10 @@ gtk_real_window_move_resize (GtkWindow *window,
(width < widget->requisition.width) ||
(height < widget->requisition.height))
{
if (window->resize_count == 0)
{
window->resize_count = 1;
gdk_window_resize (widget->window,
widget->requisition.width,
widget->requisition.height);
}
window->resize_count += 1;
gdk_window_resize (widget->window,
widget->requisition.width,
widget->requisition.height);
}
else
{