Commit c42c7be0 authored by Richard Hult's avatar Richard Hult Committed by Richard Hult
Browse files

Maintain a list for the stacking order of windows. Implement lower and

2007-10-23  Richard Hult  <richard@imendio.com>

	* gdk/quartz/gdkwindow-quartz.c:
	(gdk_window_raise, gdk_window_lower, gdk_window_new,
	_gdk_windowing_window_destroy): Maintain a list for the stacking
	order of windows. Implement lower and raise for child windows. The
	list for toplevels is created on demand, and cleared when a window
	gets or resigns main status and when new windows are created.
	(find_child_window_helper): Use the sorted list to go through
	windows from top to bottom. Take any titlebar in consideration for
	toplevels, to stop events from sometimes punching through (bugs
	#473813 and #489370).

svn path=/trunk/; revision=18940
parent 1f36660d
2007-10-23 Richard Hult <richard@imendio.com>
* gdk/quartz/gdkwindow-quartz.c:
(gdk_window_raise, gdk_window_lower, gdk_window_new,
_gdk_windowing_window_destroy): Maintain a list for the stacking
order of windows. Implement lower and raise for child windows. The
list for toplevels is created on demand, and cleared when a window
gets or resigns main status and when new windows are created.
(find_child_window_helper): Use the sorted list to go through
windows from top to bottom. Take any titlebar in consideration for
toplevels, to stop events from sometimes punching through (bugs
#473813 and #489370).
2007-10-22 Johan Dahlin <jdahlin@async.com.br> 2007-10-22 Johan Dahlin <jdahlin@async.com.br>
* gtk/gtkbuilder.c: Use gtk_ascii_tolower/toupper instead of the C * gtk/gtkbuilder.c: Use gtk_ascii_tolower/toupper instead of the C
......
...@@ -32,6 +32,9 @@ static guint update_idle; ...@@ -32,6 +32,9 @@ static guint update_idle;
static GSList *main_window_stack; static GSList *main_window_stack;
static void update_toplevel_order (void);
static void clear_toplevel_order (void);
#define WINDOW_IS_TOPLEVEL(window) \ #define WINDOW_IS_TOPLEVEL(window) \
(GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \ (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN) GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
...@@ -467,23 +470,59 @@ find_child_window_helper (GdkWindow *window, ...@@ -467,23 +470,59 @@ find_child_window_helper (GdkWindow *window,
gint x_offset, gint x_offset,
gint y_offset) gint y_offset)
{ {
GdkWindowImplQuartz *impl;
GList *l; GList *l;
for (l = GDK_WINDOW_OBJECT (window)->children; l; l = l->next) impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
if (window == _gdk_root)
update_toplevel_order ();
for (l = impl->sorted_children; l; l = l->next)
{ {
GdkWindowObject *private = l->data; GdkWindowObject *child_private = l->data;
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); GdkWindowImplQuartz *child_impl = GDK_WINDOW_IMPL_QUARTZ (child_private->impl);
int temp_x, temp_y; int temp_x, temp_y;
if (!GDK_WINDOW_IS_MAPPED (private)) if (!GDK_WINDOW_IS_MAPPED (child_private))
continue; continue;
temp_x = x_offset + private->x; temp_x = x_offset + child_private->x;
temp_y = y_offset + private->y; temp_y = y_offset + child_private->y;
/* FIXME: Are there off by one errors here? */ /* Special-case the root window. We have to include the title
* bar in the checks, otherwise the window below the title bar
* will be found i.e. events punch through. (If we can find a
* better way to deal with the events in gdkevents-quartz, this
* might not be needed.)
*/
if (window == _gdk_root)
{
NSRect frame = NSMakeRect (0, 0, 100, 100);
NSRect content;
int mask;
int titlebar_height;
mask = [child_impl->toplevel styleMask];
/* Get the title bar height. */
content = [NSWindow contentRectForFrameRect:frame
styleMask:mask];
titlebar_height = frame.size.height - content.size.height;
if (titlebar_height > 0 &&
x >= temp_x && y >= temp_y - titlebar_height &&
x < temp_x + child_impl->width && y < temp_y)
{
/* The root means "unknown" i.e. a window not managed by
* GDK.
*/
return (GdkWindow *)_gdk_root;
}
}
if (x >= temp_x && y >= temp_y && if (x >= temp_x && y >= temp_y &&
x < temp_x + impl->width && y < temp_y + impl->height) x < temp_x + child_impl->width && y < temp_y + child_impl->height)
{ {
/* Look for child windows. */ /* Look for child windows. */
return find_child_window_helper (l->data, return find_child_window_helper (l->data,
...@@ -520,6 +559,8 @@ _gdk_quartz_window_did_become_main (GdkWindow *window) ...@@ -520,6 +559,8 @@ _gdk_quartz_window_did_become_main (GdkWindow *window)
if (GDK_WINDOW_OBJECT (window)->window_type != GDK_WINDOW_TEMP) if (GDK_WINDOW_OBJECT (window)->window_type != GDK_WINDOW_TEMP)
main_window_stack = g_slist_prepend (main_window_stack, window); main_window_stack = g_slist_prepend (main_window_stack, window);
clear_toplevel_order ();
} }
void void
...@@ -549,6 +590,8 @@ _gdk_quartz_window_did_resign_main (GdkWindow *window) ...@@ -549,6 +590,8 @@ _gdk_quartz_window_did_resign_main (GdkWindow *window)
[impl->toplevel makeKeyAndOrderFront:impl->toplevel]; [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
} }
clear_toplevel_order ();
} }
GdkWindow * GdkWindow *
...@@ -561,6 +604,7 @@ gdk_window_new (GdkWindow *parent, ...@@ -561,6 +604,7 @@ gdk_window_new (GdkWindow *parent,
GdkWindowImplQuartz *impl; GdkWindowImplQuartz *impl;
GdkDrawableImplQuartz *draw_impl; GdkDrawableImplQuartz *draw_impl;
GdkVisual *visual; GdkVisual *visual;
GdkWindowImplQuartz *parent_impl;
if (parent && GDK_WINDOW_DESTROYED (parent)) if (parent && GDK_WINDOW_DESTROYED (parent))
return NULL; return NULL;
...@@ -577,6 +621,7 @@ gdk_window_new (GdkWindow *parent, ...@@ -577,6 +621,7 @@ gdk_window_new (GdkWindow *parent,
draw_impl->wrapper = GDK_DRAWABLE (window); draw_impl->wrapper = GDK_DRAWABLE (window);
private->parent = (GdkWindowObject *)parent; private->parent = (GdkWindowObject *)parent;
parent_impl = GDK_WINDOW_IMPL_QUARTZ (private->parent->impl);
private->accept_focus = TRUE; private->accept_focus = TRUE;
private->focus_on_map = TRUE; private->focus_on_map = TRUE;
...@@ -675,8 +720,13 @@ gdk_window_new (GdkWindow *parent, ...@@ -675,8 +720,13 @@ gdk_window_new (GdkWindow *parent,
g_object_ref (draw_impl->colormap); g_object_ref (draw_impl->colormap);
} }
if (private->parent) private->parent->children = g_list_prepend (private->parent->children, window);
private->parent->children = g_list_prepend (private->parent->children, window);
/* Maintain the z-ordered list of children. */
if (parent != _gdk_root)
parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
else
clear_toplevel_order ();
gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ? gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
(attributes->cursor) : (attributes->cursor) :
...@@ -796,9 +846,27 @@ _gdk_windowing_window_destroy (GdkWindow *window, ...@@ -796,9 +846,27 @@ _gdk_windowing_window_destroy (GdkWindow *window,
gboolean recursing, gboolean recursing,
gboolean foreign_destroy) gboolean foreign_destroy)
{ {
GdkWindowObject *private;
GdkWindowImplQuartz *impl;
GdkWindowObject *parent;
private = GDK_WINDOW_OBJECT (window);
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
update_windows = g_slist_remove (update_windows, window); update_windows = g_slist_remove (update_windows, window);
main_window_stack = g_slist_remove (main_window_stack, window); main_window_stack = g_slist_remove (main_window_stack, window);
g_list_free (impl->sorted_children);
impl->sorted_children = NULL;
parent = private->parent;
if (parent)
{
GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (parent->impl);
parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
}
/* If the destroyed window was targeted for a pointer or keyboard /* If the destroyed window was targeted for a pointer or keyboard
* grab, release the grab. * grab, release the grab.
*/ */
...@@ -1284,6 +1352,53 @@ _gdk_windowing_window_clear_area_e (GdkWindow *window, ...@@ -1284,6 +1352,53 @@ _gdk_windowing_window_clear_area_e (GdkWindow *window,
/* FIXME: Implement */ /* FIXME: Implement */
} }
/* Get the toplevel ordering from NSApp and update our own list. We do
* this on demand since the NSApp's list is not up to date directly
* after we get windowDidBecomeMain.
*/
static void
update_toplevel_order (void)
{
GdkWindowObject *root;
GdkWindowImplQuartz *root_impl;
NSEnumerator *enumerator;
id nswindow;
GList *toplevels = NULL;
root = GDK_WINDOW_OBJECT (_gdk_root);
root_impl = GDK_WINDOW_IMPL_QUARTZ (root->impl);
if (root_impl->sorted_children)
return;
enumerator = [[NSApp orderedWindows] objectEnumerator];
while ((nswindow = [enumerator nextObject]))
{
GdkWindow *window;
if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
continue;
window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
toplevels = g_list_prepend (toplevels, window);
}
root_impl->sorted_children = g_list_reverse (toplevels);
}
static void
clear_toplevel_order (void)
{
GdkWindowObject *root;
GdkWindowImplQuartz *root_impl;
root = GDK_WINDOW_OBJECT (_gdk_root);
root_impl = GDK_WINDOW_IMPL_QUARTZ (root->impl);
g_list_free (root_impl->sorted_children);
root_impl->sorted_children = NULL;
}
void void
gdk_window_raise (GdkWindow *window) gdk_window_raise (GdkWindow *window)
{ {
...@@ -1292,13 +1407,28 @@ gdk_window_raise (GdkWindow *window) ...@@ -1292,13 +1407,28 @@ gdk_window_raise (GdkWindow *window)
if (GDK_WINDOW_DESTROYED (window)) if (GDK_WINDOW_DESTROYED (window))
return; return;
/* FIXME: Only supported for toplevels currently. */
if (WINDOW_IS_TOPLEVEL (window)) if (WINDOW_IS_TOPLEVEL (window))
{ {
GdkWindowImplQuartz *impl; GdkWindowImplQuartz *impl;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl); impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
[impl->toplevel orderFront:impl->toplevel]; [impl->toplevel orderFront:impl->toplevel];
clear_toplevel_order ();
}
else
{
GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
if (parent)
{
GdkWindowImplQuartz *impl;
impl = (GdkWindowImplQuartz *)parent->impl;
impl->sorted_children = g_list_remove (impl->sorted_children, window);
impl->sorted_children = g_list_prepend (impl->sorted_children, window);
}
} }
} }
...@@ -1310,13 +1440,28 @@ gdk_window_lower (GdkWindow *window) ...@@ -1310,13 +1440,28 @@ gdk_window_lower (GdkWindow *window)
if (GDK_WINDOW_DESTROYED (window)) if (GDK_WINDOW_DESTROYED (window))
return; return;
/* FIXME: Only supported for toplevels currently. */
if (WINDOW_IS_TOPLEVEL (window)) if (WINDOW_IS_TOPLEVEL (window))
{ {
GdkWindowImplQuartz *impl; GdkWindowImplQuartz *impl;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl); impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
[impl->toplevel orderBack:impl->toplevel]; [impl->toplevel orderBack:impl->toplevel];
clear_toplevel_order ();
}
else
{
GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
if (parent)
{
GdkWindowImplQuartz *impl;
impl = (GdkWindowImplQuartz *)parent->impl;
impl->sorted_children = g_list_remove (impl->sorted_children, window);
impl->sorted_children = g_list_append (impl->sorted_children, window);
}
} }
} }
...@@ -2572,7 +2717,6 @@ gdk_window_unfullscreen (GdkWindow *window) ...@@ -2572,7 +2717,6 @@ gdk_window_unfullscreen (GdkWindow *window)
if (geometry) if (geometry)
{ {
ShowMenuBar (); ShowMenuBar ();
move_resize_window_internal (window, move_resize_window_internal (window,
......
...@@ -66,6 +66,9 @@ struct _GdkWindowImplQuartz ...@@ -66,6 +66,9 @@ struct _GdkWindowImplQuartz
gint in_paint_rect_count; gint in_paint_rect_count;
GdkWindow *transient_for; GdkWindow *transient_for;
/* Sorted by z-order */
GList *sorted_children;
}; };
struct _GdkWindowImplQuartzClass struct _GdkWindowImplQuartzClass
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment