mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-13 20:30:11 +00:00
a63c87c5da
2008-03-28 Richard Hult <richard@imendio.com> * gdk/quartz/gdkevents-quartz.c: (gdk_event_translate), (_gdk_quartz_events_trigger_crossing_events): Defer the generated event to the mainloop and don't generate one at all if the toplevel didn't change. Use the actual window and not the toplevel as event window. These changes make the generated crossing events match the X11 behavior and fixes issues with e.g. tooltips, comboboxes and menus. * gdk/quartz/GdkQuartzView.c: Don't update the tracking rect if the view has no window, it will be updated as soon as it's put inside a window. * gdk/quartz/gdkwindow-quartz.c: (_gdk_quartz_window_debug_highlight): Make it possible to track multiple windows with debug highlighting. (show_window_internal): Remove workaround for tooltips and popups that is no longer needed with the above changes. svn path=/trunk/; revision=19951
3130 lines
76 KiB
C
3130 lines
76 KiB
C
/* gdkwindow-quartz.c
|
|
*
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
* Copyright (C) 2005-2007 Imendio AB
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <Carbon/Carbon.h>
|
|
|
|
#include "gdk.h"
|
|
#include "gdkprivate-quartz.h"
|
|
|
|
static gpointer parent_class;
|
|
|
|
static GSList *update_windows;
|
|
static guint update_idle;
|
|
|
|
static GSList *main_window_stack;
|
|
|
|
#define FULLSCREEN_DATA "fullscreen-data"
|
|
|
|
typedef struct
|
|
{
|
|
gint x, y;
|
|
gint width, height;
|
|
GdkWMDecoration decor;
|
|
} FullscreenSavedGeometry;
|
|
|
|
|
|
static void update_toplevel_order (void);
|
|
static void clear_toplevel_order (void);
|
|
|
|
static FullscreenSavedGeometry *get_fullscreen_geometry (GdkWindow *window);
|
|
|
|
#define WINDOW_IS_TOPLEVEL(window) \
|
|
(GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
|
|
GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
|
|
|
|
NSView *
|
|
gdk_quartz_window_get_nsview (GdkWindow *window)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *)window;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return NULL;
|
|
|
|
return ((GdkWindowImplQuartz *)private->impl)->view;
|
|
}
|
|
|
|
NSWindow *
|
|
gdk_quartz_window_get_nswindow (GdkWindow *window)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *)window;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return NULL;
|
|
|
|
return ((GdkWindowImplQuartz *)private->impl)->toplevel;
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_get_size (GdkDrawable *drawable,
|
|
gint *width,
|
|
gint *height)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW_IMPL_QUARTZ (drawable));
|
|
|
|
if (width)
|
|
*width = GDK_WINDOW_IMPL_QUARTZ (drawable)->width;
|
|
if (height)
|
|
*height = GDK_WINDOW_IMPL_QUARTZ (drawable)->height;
|
|
}
|
|
|
|
static GdkRegion*
|
|
gdk_window_impl_quartz_get_visible_region (GdkDrawable *drawable)
|
|
{
|
|
GdkWindowObject *private = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper);
|
|
GdkRectangle rect;
|
|
GdkWindowImplQuartz *impl;
|
|
GList *windows = NULL, *l;
|
|
|
|
/* FIXME: The clip rectangle should really be cached
|
|
* and recalculated when the window rectangle changes.
|
|
*/
|
|
while (private)
|
|
{
|
|
windows = g_list_prepend (windows, private);
|
|
|
|
if (private->parent == GDK_WINDOW_OBJECT (_gdk_root))
|
|
break;
|
|
|
|
private = private->parent;
|
|
}
|
|
|
|
/* Get rectangle for toplevel window */
|
|
private = GDK_WINDOW_OBJECT (windows->data);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
rect.x = 0;
|
|
rect.y = 0;
|
|
rect.width = impl->width;
|
|
rect.height = impl->height;
|
|
|
|
/* Skip toplevel window since we have its rect */
|
|
for (l = windows->next; l; l = l->next)
|
|
{
|
|
private = GDK_WINDOW_OBJECT (l->data);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
GdkRectangle tmp_rect;
|
|
|
|
tmp_rect.x = -MIN (0, private->x - rect.x);
|
|
tmp_rect.y = -MIN (0, private->y - rect.y);
|
|
tmp_rect.width = MIN (rect.width, impl->width + private->x - rect.x) - MAX (0, private->x - rect.x);
|
|
tmp_rect.height = MIN (rect.height, impl->height + private->y - rect.y) - MAX (0, private->y - rect.y);
|
|
|
|
rect = tmp_rect;
|
|
}
|
|
|
|
g_list_free (windows);
|
|
|
|
return gdk_region_rectangle (&rect);
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_finalize (GObject *object)
|
|
{
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
|
|
|
|
if (impl->nscursor)
|
|
[impl->nscursor release];
|
|
|
|
if (impl->paint_clip_region)
|
|
gdk_region_destroy (impl->paint_clip_region);
|
|
|
|
if (impl->transient_for)
|
|
g_object_unref (impl->transient_for);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
|
|
{
|
|
GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
object_class->finalize = gdk_window_impl_quartz_finalize;
|
|
|
|
drawable_class->get_size = gdk_window_impl_quartz_get_size;
|
|
|
|
/* Visible and clip regions are the same */
|
|
drawable_class->get_clip_region = gdk_window_impl_quartz_get_visible_region;
|
|
drawable_class->get_visible_region = gdk_window_impl_quartz_get_visible_region;
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
|
|
{
|
|
impl->width = 1;
|
|
impl->height = 1;
|
|
impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
|
|
const GdkRegion *region)
|
|
{
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
|
|
GdkDrawableImplQuartz *drawable_impl;
|
|
int n_rects;
|
|
GdkRectangle *rects;
|
|
GdkPixmap *bg_pixmap;
|
|
GdkWindow *window;
|
|
|
|
drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
|
|
bg_pixmap = GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_pixmap;
|
|
|
|
if (impl->begin_paint_count == 0)
|
|
impl->paint_clip_region = gdk_region_copy (region);
|
|
else
|
|
gdk_region_union (impl->paint_clip_region, region);
|
|
|
|
impl->begin_paint_count++;
|
|
|
|
if (bg_pixmap == GDK_NO_BG)
|
|
return;
|
|
|
|
gdk_region_get_rectangles (region, &rects, &n_rects);
|
|
|
|
if (bg_pixmap == NULL)
|
|
{
|
|
CGContextRef cg_context;
|
|
gfloat r, g, b, a;
|
|
gint i;
|
|
|
|
cg_context = gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE);
|
|
_gdk_quartz_colormap_get_rgba_from_pixel (gdk_drawable_get_colormap (drawable_impl->wrapper),
|
|
GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_color.pixel,
|
|
&r, &g, &b, &a);
|
|
|
|
for (i = 0; i < n_rects; i++)
|
|
{
|
|
CGContextSetRGBFillColor (cg_context, r, g, b, a);
|
|
CGContextFillRect (cg_context,
|
|
CGRectMake (rects[i].x, rects[i].y,
|
|
rects[i].width, rects[i].height));
|
|
}
|
|
|
|
gdk_quartz_drawable_release_context (GDK_DRAWABLE (impl), cg_context);
|
|
}
|
|
else
|
|
{
|
|
int x, y;
|
|
int x_offset, y_offset;
|
|
int width, height;
|
|
GdkGC *gc;
|
|
|
|
x_offset = y_offset = 0;
|
|
|
|
window = GDK_WINDOW (drawable_impl->wrapper);
|
|
while (window && bg_pixmap == GDK_PARENT_RELATIVE_BG)
|
|
{
|
|
/* If this window should have the same background as the parent,
|
|
* fetch the parent. (And if the same goes for the parent, fetch
|
|
* the grandparent, etc.)
|
|
*/
|
|
x_offset += ((GdkWindowObject *) window)->x;
|
|
y_offset += ((GdkWindowObject *) window)->y;
|
|
window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
|
|
bg_pixmap = ((GdkWindowObject *) window)->bg_pixmap;
|
|
}
|
|
|
|
if (bg_pixmap == NULL || bg_pixmap == GDK_NO_BG || bg_pixmap == GDK_PARENT_RELATIVE_BG)
|
|
{
|
|
/* Parent relative background but the parent doesn't have a
|
|
* pixmap.
|
|
*/
|
|
g_free (rects);
|
|
return;
|
|
}
|
|
|
|
/* Note: There should be a CG API to draw tiled images, we might
|
|
* want to look into that for this.
|
|
*/
|
|
gc = gdk_gc_new (GDK_DRAWABLE (impl));
|
|
|
|
gdk_drawable_get_size (GDK_DRAWABLE (bg_pixmap), &width, &height);
|
|
|
|
x = -x_offset;
|
|
while (x < (rects[0].x + rects[0].width))
|
|
{
|
|
if (x + width >= rects[0].x)
|
|
{
|
|
y = -y_offset;
|
|
while (y < (rects[0].y + rects[0].height))
|
|
{
|
|
if (y + height >= rects[0].y)
|
|
gdk_draw_drawable (GDK_DRAWABLE (impl), gc, bg_pixmap, 0, 0, x, y, width, height);
|
|
|
|
y += height;
|
|
}
|
|
}
|
|
x += width;
|
|
}
|
|
|
|
g_object_unref (gc);
|
|
}
|
|
|
|
g_free (rects);
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
|
|
{
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
|
|
|
|
impl->begin_paint_count--;
|
|
|
|
if (impl->begin_paint_count == 0)
|
|
{
|
|
gdk_region_destroy (impl->paint_clip_region);
|
|
impl->paint_clip_region = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_window_quartz_process_updates_internal (GdkWindow *window)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *) window;
|
|
GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *) private->impl;
|
|
|
|
if (private->update_area)
|
|
{
|
|
int i, n_rects;
|
|
GdkRectangle *rects;
|
|
|
|
gdk_region_get_rectangles (private->update_area, &rects, &n_rects);
|
|
|
|
gdk_region_destroy (private->update_area);
|
|
private->update_area = NULL;
|
|
|
|
for (i = 0; i < n_rects; i++)
|
|
{
|
|
[impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
|
|
rects[i].width, rects[i].height)];
|
|
}
|
|
|
|
[impl->view displayIfNeeded];
|
|
|
|
g_free (rects);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_window_quartz_process_all_updates (void)
|
|
{
|
|
GSList *old_update_windows = update_windows;
|
|
GSList *tmp_list = update_windows;
|
|
GSList *nswindows;
|
|
|
|
update_idle = 0;
|
|
update_windows = NULL;
|
|
nswindows = NULL;
|
|
|
|
g_slist_foreach (old_update_windows, (GFunc) g_object_ref, NULL);
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
while (tmp_list)
|
|
{
|
|
GdkWindow *window = tmp_list->data;
|
|
GdkWindow *toplevel;
|
|
|
|
/* Only flush each toplevel at most once. */
|
|
toplevel = gdk_window_get_toplevel (window);
|
|
if (toplevel)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
NSWindow *nswindow;
|
|
|
|
private = (GdkWindowObject *) toplevel;
|
|
impl = (GdkWindowImplQuartz *) private->impl;
|
|
nswindow = impl->toplevel;
|
|
|
|
if (nswindow && ![nswindow isFlushWindowDisabled])
|
|
{
|
|
[nswindow disableFlushWindow];
|
|
nswindows = g_slist_prepend (nswindows, nswindow);
|
|
}
|
|
}
|
|
|
|
gdk_window_quartz_process_updates_internal (tmp_list->data);
|
|
|
|
g_object_unref (tmp_list->data);
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
|
|
tmp_list = nswindows;
|
|
while (tmp_list)
|
|
{
|
|
NSWindow *nswindow = tmp_list->data;
|
|
|
|
[nswindow enableFlushWindow];
|
|
[nswindow flushWindow];
|
|
|
|
tmp_list = tmp_list->next;
|
|
}
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
|
|
g_slist_free (old_update_windows);
|
|
g_slist_free (nswindows);
|
|
}
|
|
|
|
static gboolean
|
|
gdk_window_quartz_update_idle (gpointer data)
|
|
{
|
|
GDK_THREADS_ENTER ();
|
|
gdk_window_quartz_process_all_updates ();
|
|
GDK_THREADS_LEAVE ();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_invalidate_maybe_recurse (GdkPaintable *paintable,
|
|
const GdkRegion *region,
|
|
gboolean (*child_func) (GdkWindow *, gpointer),
|
|
gpointer user_data)
|
|
{
|
|
GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
|
|
GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) window_impl;
|
|
GdkWindow *window = (GdkWindow *) drawable_impl->wrapper;
|
|
GdkWindowObject *private = (GdkWindowObject *) window;
|
|
GdkRegion *visible_region;
|
|
|
|
visible_region = gdk_drawable_get_visible_region (window);
|
|
gdk_region_intersect (visible_region, region);
|
|
|
|
if (private->update_area)
|
|
{
|
|
gdk_region_union (private->update_area, visible_region);
|
|
gdk_region_destroy (visible_region);
|
|
}
|
|
else
|
|
{
|
|
update_windows = g_slist_prepend (update_windows, window);
|
|
private->update_area = visible_region;
|
|
|
|
if (update_idle == 0)
|
|
update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
|
|
gdk_window_quartz_update_idle, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_process_updates (GdkPaintable *paintable,
|
|
gboolean update_children)
|
|
{
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
|
|
GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) impl;
|
|
GdkWindowObject *private = (GdkWindowObject *) drawable_impl->wrapper;
|
|
|
|
if (private->update_area)
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
gdk_window_quartz_process_updates_internal ((GdkWindow *) private);
|
|
update_windows = g_slist_remove (update_windows, private);
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface)
|
|
{
|
|
iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
|
|
iface->end_paint = gdk_window_impl_quartz_end_paint;
|
|
|
|
iface->invalidate_maybe_recurse = gdk_window_impl_quartz_invalidate_maybe_recurse;
|
|
iface->process_updates = gdk_window_impl_quartz_process_updates;
|
|
}
|
|
|
|
GType
|
|
_gdk_window_impl_quartz_get_type (void)
|
|
{
|
|
static GType object_type = 0;
|
|
|
|
if (!object_type)
|
|
{
|
|
const GTypeInfo object_info =
|
|
{
|
|
sizeof (GdkWindowImplQuartzClass),
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
(GClassInitFunc) gdk_window_impl_quartz_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (GdkWindowImplQuartz),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) gdk_window_impl_quartz_init,
|
|
};
|
|
|
|
const GInterfaceInfo paintable_info =
|
|
{
|
|
(GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ,
|
|
"GdkWindowImplQuartz",
|
|
&object_info, 0);
|
|
g_type_add_interface_static (object_type,
|
|
GDK_TYPE_PAINTABLE,
|
|
&paintable_info);
|
|
}
|
|
|
|
return object_type;
|
|
}
|
|
|
|
GType
|
|
_gdk_window_impl_get_type (void)
|
|
{
|
|
return _gdk_window_impl_quartz_get_type ();
|
|
}
|
|
|
|
static const gchar *
|
|
get_default_title (void)
|
|
{
|
|
const char *title;
|
|
|
|
title = g_get_application_name ();
|
|
if (!title)
|
|
title = g_get_prgname ();
|
|
|
|
return title;
|
|
}
|
|
|
|
static void
|
|
get_ancestor_coordinates_from_child (GdkWindow *child_window,
|
|
gint child_x,
|
|
gint child_y,
|
|
GdkWindow *ancestor_window,
|
|
gint *ancestor_x,
|
|
gint *ancestor_y)
|
|
{
|
|
GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
|
|
GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
|
|
|
|
while (child_private != ancestor_private)
|
|
{
|
|
child_x += child_private->x;
|
|
child_y += child_private->y;
|
|
|
|
child_private = child_private->parent;
|
|
}
|
|
|
|
*ancestor_x = child_x;
|
|
*ancestor_y = child_y;
|
|
}
|
|
|
|
void
|
|
_gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
|
|
{
|
|
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
gint x, y;
|
|
GdkWindow *toplevel;
|
|
gint tx, ty;
|
|
static NSWindow *debug_window[10];
|
|
static NSRect old_rect[10];
|
|
NSRect rect;
|
|
NSColor *color;
|
|
|
|
g_return_if_fail (number >= 0 && number <= 9);
|
|
|
|
if (window == _gdk_root)
|
|
return;
|
|
|
|
if (window == NULL)
|
|
{
|
|
if (debug_window[number])
|
|
[debug_window[number] close];
|
|
debug_window[number] = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
toplevel = gdk_window_get_toplevel (window);
|
|
get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
|
|
|
|
gdk_window_get_origin (toplevel, &tx, &ty);
|
|
x += tx;
|
|
y += ty;
|
|
|
|
rect = NSMakeRect (x,
|
|
_gdk_quartz_window_get_inverted_screen_y (y + impl->height),
|
|
impl->width, impl->height);
|
|
|
|
if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
|
|
return;
|
|
|
|
old_rect[number] = rect;
|
|
|
|
if (debug_window[number])
|
|
[debug_window[number] close];
|
|
|
|
debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
|
|
styleMask:NSBorderlessWindowMask
|
|
backing:NSBackingStoreBuffered
|
|
defer:NO];
|
|
|
|
switch (number)
|
|
{
|
|
case 0:
|
|
color = [NSColor redColor];
|
|
break;
|
|
case 1:
|
|
color = [NSColor blueColor];
|
|
break;
|
|
case 2:
|
|
color = [NSColor greenColor];
|
|
break;
|
|
case 3:
|
|
color = [NSColor yellowColor];
|
|
break;
|
|
case 4:
|
|
color = [NSColor brownColor];
|
|
break;
|
|
case 5:
|
|
color = [NSColor purpleColor];
|
|
break;
|
|
default:
|
|
color = [NSColor blackColor];
|
|
break;
|
|
}
|
|
|
|
[debug_window[number] setBackgroundColor:color];
|
|
[debug_window[number] setAlphaValue:0.4];
|
|
[debug_window[number] setOpaque:NO];
|
|
[debug_window[number] setReleasedWhenClosed:YES];
|
|
[debug_window[number] setIgnoresMouseEvents:YES];
|
|
[debug_window[number] setLevel:NSFloatingWindowLevel];
|
|
|
|
[debug_window[number] orderFront:nil];
|
|
}
|
|
|
|
gboolean
|
|
_gdk_quartz_window_is_ancestor (GdkWindow *ancestor,
|
|
GdkWindow *window)
|
|
{
|
|
if (ancestor == NULL || window == NULL)
|
|
return FALSE;
|
|
|
|
return (gdk_window_get_parent (window) == ancestor ||
|
|
_gdk_quartz_window_is_ancestor (ancestor,
|
|
gdk_window_get_parent (window)));
|
|
}
|
|
|
|
/* FIXME: It would be nice to have one function that takes an NSPoint
|
|
* and flips the coords for any window.
|
|
*/
|
|
gint
|
|
_gdk_quartz_window_get_inverted_screen_y (gint y)
|
|
{
|
|
NSRect rect = [[NSScreen mainScreen] frame];
|
|
|
|
return rect.size.height - y;
|
|
}
|
|
|
|
static GdkWindow *
|
|
find_child_window_helper (GdkWindow *window,
|
|
gint x,
|
|
gint y,
|
|
gint x_offset,
|
|
gint y_offset)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
GList *l;
|
|
|
|
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 *child_private = l->data;
|
|
GdkWindowImplQuartz *child_impl = GDK_WINDOW_IMPL_QUARTZ (child_private->impl);
|
|
int temp_x, temp_y;
|
|
|
|
if (!GDK_WINDOW_IS_MAPPED (child_private))
|
|
continue;
|
|
|
|
temp_x = x_offset + child_private->x;
|
|
temp_y = y_offset + child_private->y;
|
|
|
|
/* 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 &&
|
|
x < temp_x + child_impl->width && y < temp_y + child_impl->height)
|
|
{
|
|
/* Look for child windows. */
|
|
return find_child_window_helper (l->data,
|
|
x, y,
|
|
temp_x, temp_y);
|
|
}
|
|
}
|
|
|
|
return window;
|
|
}
|
|
|
|
/* Given a GdkWindow and coordinates relative to it, returns the
|
|
* innermost subwindow that contains the point. If the coordinates are
|
|
* outside the passed in window, NULL is returned.
|
|
*/
|
|
GdkWindow *
|
|
_gdk_quartz_window_find_child (GdkWindow *window,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if (x >= 0 && y >= 0 && x < impl->width && y < impl->height)
|
|
return find_child_window_helper (window, x, y, 0, 0);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
_gdk_quartz_window_did_become_main (GdkWindow *window)
|
|
{
|
|
main_window_stack = g_slist_remove (main_window_stack, window);
|
|
|
|
if (GDK_WINDOW_OBJECT (window)->window_type != GDK_WINDOW_TEMP)
|
|
main_window_stack = g_slist_prepend (main_window_stack, window);
|
|
|
|
clear_toplevel_order ();
|
|
}
|
|
|
|
void
|
|
_gdk_quartz_window_did_resign_main (GdkWindow *window)
|
|
{
|
|
GdkWindow *new_window = NULL;
|
|
|
|
if (main_window_stack)
|
|
new_window = main_window_stack->data;
|
|
else
|
|
{
|
|
GList *toplevels;
|
|
|
|
toplevels = gdk_window_get_toplevels ();
|
|
if (toplevels)
|
|
new_window = toplevels->data;
|
|
g_list_free (toplevels);
|
|
}
|
|
|
|
if (new_window &&
|
|
new_window != window &&
|
|
GDK_WINDOW_IS_MAPPED (new_window) &&
|
|
GDK_WINDOW_OBJECT (new_window)->window_type != GDK_WINDOW_TEMP)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *) new_window;
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
[impl->toplevel makeKeyAndOrderFront:impl->toplevel];
|
|
}
|
|
|
|
clear_toplevel_order ();
|
|
}
|
|
|
|
GdkWindow *
|
|
gdk_window_new (GdkWindow *parent,
|
|
GdkWindowAttr *attributes,
|
|
gint attributes_mask)
|
|
{
|
|
GdkWindow *window;
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
GdkDrawableImplQuartz *draw_impl;
|
|
GdkVisual *visual;
|
|
GdkWindowImplQuartz *parent_impl;
|
|
|
|
if (parent && GDK_WINDOW_DESTROYED (parent))
|
|
return NULL;
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (!parent)
|
|
parent = _gdk_root;
|
|
|
|
window = g_object_new (GDK_TYPE_WINDOW, NULL);
|
|
private = (GdkWindowObject *)window;
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
|
|
draw_impl->wrapper = GDK_DRAWABLE (window);
|
|
|
|
private->parent = (GdkWindowObject *)parent;
|
|
parent_impl = GDK_WINDOW_IMPL_QUARTZ (private->parent->impl);
|
|
|
|
private->accept_focus = TRUE;
|
|
private->focus_on_map = TRUE;
|
|
|
|
if (attributes_mask & GDK_WA_X)
|
|
private->x = attributes->x;
|
|
else
|
|
private->x = 0;
|
|
|
|
if (attributes_mask & GDK_WA_Y)
|
|
private->y = attributes->y;
|
|
else if (attributes_mask & GDK_WA_X)
|
|
private->y = 100;
|
|
else
|
|
private->y = 0;
|
|
|
|
private->event_mask = attributes->event_mask;
|
|
|
|
impl->width = attributes->width > 1 ? attributes->width : 1;
|
|
impl->height = attributes->height > 1 ? attributes->height : 1;
|
|
|
|
if (attributes_mask & GDK_WA_VISUAL)
|
|
visual = attributes->visual;
|
|
else
|
|
visual = gdk_screen_get_system_visual (_gdk_screen);
|
|
|
|
if (attributes->wclass == GDK_INPUT_ONLY)
|
|
{
|
|
/* Backwards compatiblity - we've always ignored
|
|
* attributes->window_type for input-only windows
|
|
* before
|
|
*/
|
|
if (parent == _gdk_root)
|
|
private->window_type = GDK_WINDOW_TEMP;
|
|
else
|
|
private->window_type = GDK_WINDOW_CHILD;
|
|
}
|
|
else
|
|
private->window_type = attributes->window_type;
|
|
|
|
/* Sanity checks */
|
|
switch (private->window_type)
|
|
{
|
|
case GDK_WINDOW_TOPLEVEL:
|
|
case GDK_WINDOW_DIALOG:
|
|
case GDK_WINDOW_TEMP:
|
|
if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
|
|
{
|
|
g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
|
|
"of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
|
|
}
|
|
case GDK_WINDOW_CHILD:
|
|
break;
|
|
default:
|
|
g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
return NULL;
|
|
}
|
|
|
|
if (attributes->wclass == GDK_INPUT_OUTPUT)
|
|
{
|
|
private->input_only = FALSE;
|
|
private->depth = visual->depth;
|
|
|
|
if (attributes_mask & GDK_WA_COLORMAP)
|
|
{
|
|
draw_impl->colormap = attributes->colormap;
|
|
g_object_ref (attributes->colormap);
|
|
}
|
|
else
|
|
{
|
|
if (visual == gdk_screen_get_system_visual (_gdk_screen))
|
|
{
|
|
draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
|
|
g_object_ref (draw_impl->colormap);
|
|
}
|
|
else if (visual == gdk_screen_get_rgba_visual (_gdk_screen))
|
|
{
|
|
draw_impl->colormap = gdk_screen_get_rgba_colormap (_gdk_screen);
|
|
g_object_ref (draw_impl->colormap);
|
|
}
|
|
else
|
|
{
|
|
draw_impl->colormap = gdk_colormap_new (visual, FALSE);
|
|
}
|
|
}
|
|
|
|
private->bg_color.pixel = 0;
|
|
private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
|
|
}
|
|
else
|
|
{
|
|
private->depth = 0;
|
|
private->input_only = TRUE;
|
|
draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
|
|
g_object_ref (draw_impl->colormap);
|
|
}
|
|
|
|
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) ?
|
|
(attributes->cursor) :
|
|
NULL));
|
|
|
|
switch (attributes->window_type)
|
|
{
|
|
case GDK_WINDOW_TOPLEVEL:
|
|
case GDK_WINDOW_DIALOG:
|
|
case GDK_WINDOW_TEMP:
|
|
{
|
|
NSRect content_rect;
|
|
int style_mask;
|
|
const char *title;
|
|
|
|
/* Big hack: We start out outside the screen and move the
|
|
* window in before showing it. This makes the initial
|
|
* MouseEntered event work if the window ends up right under
|
|
* the mouse pointer, bad quartz.
|
|
*/
|
|
content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height,
|
|
impl->width, impl->height);
|
|
|
|
switch (attributes->window_type)
|
|
{
|
|
case GDK_WINDOW_TEMP:
|
|
style_mask = NSBorderlessWindowMask;
|
|
break;
|
|
default:
|
|
style_mask = (NSTitledWindowMask |
|
|
NSClosableWindowMask |
|
|
NSMiniaturizableWindowMask |
|
|
NSResizableWindowMask);
|
|
}
|
|
|
|
impl->toplevel = [[GdkQuartzWindow alloc] initWithContentRect:content_rect
|
|
styleMask:style_mask
|
|
backing:NSBackingStoreBuffered
|
|
defer:NO];
|
|
|
|
if (attributes_mask & GDK_WA_TITLE)
|
|
title = attributes->title;
|
|
else
|
|
title = get_default_title ();
|
|
|
|
gdk_window_set_title (window, title);
|
|
|
|
if (draw_impl->colormap == gdk_screen_get_rgba_colormap (_gdk_screen))
|
|
{
|
|
[impl->toplevel setOpaque:NO];
|
|
[impl->toplevel setBackgroundColor:[NSColor clearColor]];
|
|
}
|
|
|
|
impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
|
|
[impl->view setGdkWindow:window];
|
|
[impl->toplevel setContentView:impl->view];
|
|
}
|
|
break;
|
|
|
|
case GDK_WINDOW_CHILD:
|
|
{
|
|
GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
|
|
|
|
if (attributes->wclass == GDK_INPUT_OUTPUT)
|
|
{
|
|
NSRect frame_rect = NSMakeRect (private->x, private->y, impl->width, impl->height);
|
|
|
|
impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
|
|
|
|
[impl->view setGdkWindow:window];
|
|
|
|
/* GdkWindows should be hidden by default */
|
|
[impl->view setHidden:YES];
|
|
[parent_impl->view addSubview:impl->view];
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
|
|
if (attributes_mask & GDK_WA_TYPE_HINT)
|
|
gdk_window_set_type_hint (window, attributes->type_hint);
|
|
|
|
return window;
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_init (void)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
GdkDrawableImplQuartz *drawable_impl;
|
|
NSRect rect;
|
|
|
|
g_assert (_gdk_root == NULL);
|
|
|
|
_gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
|
|
|
|
/* Note: This needs to be reworked for multi-screen support. */
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
|
|
rect = [[NSScreen mainScreen] frame];
|
|
impl->width = rect.size.width;
|
|
impl->height = rect.size.height;
|
|
|
|
private = (GdkWindowObject *)_gdk_root;
|
|
|
|
private->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
|
|
private->window_type = GDK_WINDOW_ROOT;
|
|
private->depth = 24;
|
|
|
|
drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
|
|
|
|
drawable_impl->wrapper = GDK_DRAWABLE (private);
|
|
drawable_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
|
|
g_object_ref (drawable_impl->colormap);
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_destroy (GdkWindow *window,
|
|
gboolean recursing,
|
|
gboolean foreign_destroy)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
GdkWindowObject *parent;
|
|
GdkWindow *mouse_window;
|
|
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
update_windows = g_slist_remove (update_windows, 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
|
|
* grab, release the grab.
|
|
*/
|
|
if (window == _gdk_quartz_pointer_grab_window)
|
|
gdk_pointer_ungrab (0);
|
|
|
|
if (window == _gdk_quartz_keyboard_grab_window)
|
|
gdk_keyboard_ungrab (0);
|
|
|
|
_gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
|
|
|
|
mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
|
|
if (window == mouse_window ||
|
|
_gdk_quartz_window_is_ancestor (window, mouse_window))
|
|
_gdk_quartz_events_update_mouse_window (_gdk_root);
|
|
|
|
if (!recursing && !foreign_destroy)
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (impl->toplevel)
|
|
[impl->toplevel close];
|
|
else if (impl->view)
|
|
[impl->view removeFromSuperview];
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_destroy_foreign (GdkWindow *window)
|
|
{
|
|
/* Foreign windows aren't supported in OSX. */
|
|
}
|
|
|
|
static gboolean
|
|
all_parents_shown (GdkWindowObject *private)
|
|
{
|
|
while (GDK_WINDOW_IS_MAPPED (private))
|
|
{
|
|
if (private->parent)
|
|
private = (GdkWindowObject *)private->parent;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* Note: the raise argument is not really used, it doesn't seem
|
|
* possible to show a window without raising it?
|
|
*/
|
|
static void
|
|
show_window_internal (GdkWindow *window,
|
|
gboolean raise)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
gboolean focus_on_map;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
private = (GdkWindowObject *)window;
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if (!GDK_WINDOW_IS_MAPPED (window))
|
|
focus_on_map = private->focus_on_map;
|
|
else
|
|
focus_on_map = TRUE;
|
|
|
|
if (impl->toplevel)
|
|
{
|
|
gboolean make_key;
|
|
|
|
/* Move the window into place, to guarantee that we get the
|
|
* initial MouseEntered event.
|
|
*/
|
|
make_key = (private->accept_focus && focus_on_map && raise &&
|
|
private->window_type != GDK_WINDOW_TEMP);
|
|
|
|
[(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key];
|
|
clear_toplevel_order ();
|
|
}
|
|
else
|
|
{
|
|
[impl->view setHidden:NO];
|
|
}
|
|
|
|
[impl->view setNeedsDisplay:YES];
|
|
|
|
if (all_parents_shown (private->parent))
|
|
_gdk_quartz_events_send_map_events (window);
|
|
|
|
gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
|
|
|
|
if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
|
|
gdk_window_maximize (window);
|
|
|
|
if (private->state & GDK_WINDOW_STATE_ICONIFIED)
|
|
gdk_window_iconify (window);
|
|
|
|
if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
|
|
_gdk_quartz_window_attach_to_parent (window);
|
|
|
|
/* Create a crossing event for windows that pop up under the mouse. Part
|
|
* of the workarounds for problems with the tracking rect API.
|
|
*/
|
|
if (impl->toplevel)
|
|
_gdk_quartz_events_trigger_crossing_events (TRUE);
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
|
|
/* Temporarily unsets the parent window, if the window is a
|
|
* transient.
|
|
*/
|
|
void
|
|
_gdk_quartz_window_detach_from_parent (GdkWindow *window)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
g_return_if_fail (impl->toplevel != NULL);
|
|
|
|
if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
|
|
{
|
|
GdkWindowImplQuartz *parent_impl;
|
|
|
|
parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (impl->transient_for)->impl);
|
|
[parent_impl->toplevel removeChildWindow:impl->toplevel];
|
|
clear_toplevel_order ();
|
|
}
|
|
}
|
|
|
|
/* Re-sets the parent window, if the window is a transient. */
|
|
void
|
|
_gdk_quartz_window_attach_to_parent (GdkWindow *window)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
g_return_if_fail (impl->toplevel != NULL);
|
|
|
|
if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
|
|
{
|
|
GdkWindowImplQuartz *parent_impl;
|
|
|
|
parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (impl->transient_for)->impl);
|
|
[parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
|
|
clear_toplevel_order ();
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_show_unraised (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
show_window_internal (window, FALSE);
|
|
}
|
|
|
|
void
|
|
gdk_window_show (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
show_window_internal (window, TRUE);
|
|
}
|
|
|
|
void
|
|
gdk_window_hide (GdkWindow *window)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *)window;
|
|
GdkWindowImplQuartz *impl;
|
|
GdkWindow *mouse_window;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* Make sure we're not stuck in fullscreen mode. */
|
|
if (get_fullscreen_geometry (window))
|
|
ShowMenuBar ();
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
|
|
if (window == mouse_window ||
|
|
_gdk_quartz_window_is_ancestor (window, mouse_window))
|
|
_gdk_quartz_events_update_mouse_window (_gdk_root);
|
|
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
gdk_synthesize_window_state (window,
|
|
0,
|
|
GDK_WINDOW_STATE_WITHDRAWN);
|
|
|
|
_gdk_window_clear_update_area (window);
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if (impl->toplevel)
|
|
{
|
|
/* Update main window. */
|
|
main_window_stack = g_slist_remove (main_window_stack, window);
|
|
if ([NSApp mainWindow] == impl->toplevel)
|
|
_gdk_quartz_window_did_resign_main (window);
|
|
|
|
if (impl->transient_for)
|
|
_gdk_quartz_window_detach_from_parent (window);
|
|
|
|
[(GdkQuartzWindow*)impl->toplevel hide];
|
|
}
|
|
else if (impl->view)
|
|
{
|
|
[impl->view setHidden:YES];
|
|
}
|
|
|
|
if (window == _gdk_quartz_pointer_grab_window)
|
|
gdk_pointer_ungrab (0);
|
|
|
|
if (window == _gdk_quartz_keyboard_grab_window)
|
|
gdk_keyboard_ungrab (0);
|
|
}
|
|
|
|
void
|
|
gdk_window_withdraw (GdkWindow *window)
|
|
{
|
|
gdk_window_hide (window);
|
|
}
|
|
|
|
static void
|
|
move_resize_window_internal (GdkWindow *window,
|
|
gint x,
|
|
gint y,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *)window;
|
|
GdkWindowImplQuartz *impl;
|
|
GdkRectangle old_visible;
|
|
GdkRectangle new_visible;
|
|
GdkRectangle scroll_rect;
|
|
GdkRegion *old_region;
|
|
GdkRegion *expose_region;
|
|
NSSize delta;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if ((x == -1 || (x == private->x)) &&
|
|
(y == -1 || (y == private->y)) &&
|
|
(width == -1 || (width == impl->width)) &&
|
|
(height == -1 || (height == impl->height)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!impl->toplevel)
|
|
{
|
|
/* The previously visible area of this window in a coordinate
|
|
* system rooted at the origin of this window.
|
|
*/
|
|
old_visible.x = -private->x;
|
|
old_visible.y = -private->y;
|
|
|
|
gdk_window_get_size (GDK_DRAWABLE (private->parent),
|
|
&old_visible.width,
|
|
&old_visible.height);
|
|
}
|
|
|
|
if (x != -1)
|
|
{
|
|
delta.width = x - private->x;
|
|
private->x = x;
|
|
}
|
|
else
|
|
{
|
|
delta.width = 0;
|
|
}
|
|
|
|
if (y != -1)
|
|
{
|
|
delta.height = y - private->y;
|
|
private->y = y;
|
|
}
|
|
else
|
|
{
|
|
delta.height = 0;
|
|
}
|
|
|
|
if (width != -1)
|
|
impl->width = width;
|
|
|
|
if (height != -1)
|
|
impl->height = height;
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (impl->toplevel)
|
|
{
|
|
NSRect content_rect;
|
|
NSRect frame_rect;
|
|
|
|
/* We don't update the NSWindow while unmapped, since we move windows
|
|
* off-screen when hiding in order for MouseEntered to be triggered
|
|
* reliably when showing windows and they appear under the mouse.
|
|
*/
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
{
|
|
content_rect = NSMakeRect (private->x,
|
|
_gdk_quartz_window_get_inverted_screen_y (private->y + impl->height),
|
|
impl->width, impl->height);
|
|
|
|
frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
|
|
[impl->toplevel setFrame:frame_rect display:YES];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!private->input_only)
|
|
{
|
|
NSRect nsrect;
|
|
|
|
nsrect = NSMakeRect (private->x, private->y, impl->width, impl->height);
|
|
|
|
/* The newly visible area of this window in a coordinate
|
|
* system rooted at the origin of this window.
|
|
*/
|
|
new_visible.x = -private->x;
|
|
new_visible.y = -private->y;
|
|
new_visible.width = old_visible.width; /* parent has not changed size */
|
|
new_visible.height = old_visible.height; /* parent has not changed size */
|
|
|
|
expose_region = gdk_region_rectangle (&new_visible);
|
|
old_region = gdk_region_rectangle (&old_visible);
|
|
gdk_region_subtract (expose_region, old_region);
|
|
|
|
/* Determine what (if any) part of the previously visible
|
|
* part of the window can be copied without a redraw
|
|
*/
|
|
scroll_rect = old_visible;
|
|
scroll_rect.x -= delta.width;
|
|
scroll_rect.y -= delta.height;
|
|
gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
|
|
|
|
if (!gdk_region_empty (expose_region))
|
|
{
|
|
GdkRectangle* rects;
|
|
gint n_rects;
|
|
gint n;
|
|
|
|
if (scroll_rect.width != 0 && scroll_rect.height != 0)
|
|
{
|
|
[impl->view scrollRect:NSMakeRect (scroll_rect.x,
|
|
scroll_rect.y,
|
|
scroll_rect.width,
|
|
scroll_rect.height)
|
|
by:delta];
|
|
}
|
|
|
|
[impl->view setFrame:nsrect];
|
|
|
|
gdk_region_get_rectangles (expose_region, &rects, &n_rects);
|
|
|
|
for (n = 0; n < n_rects; ++n)
|
|
{
|
|
[impl->view setNeedsDisplayInRect:NSMakeRect (rects[n].x,
|
|
rects[n].y,
|
|
rects[n].width,
|
|
rects[n].height)];
|
|
}
|
|
|
|
g_free (rects);
|
|
}
|
|
else
|
|
{
|
|
[impl->view setFrame:nsrect];
|
|
[impl->view setNeedsDisplay:YES];
|
|
}
|
|
|
|
gdk_region_destroy (expose_region);
|
|
gdk_region_destroy (old_region);
|
|
}
|
|
}
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
|
|
void
|
|
gdk_window_move (GdkWindow *window,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (((GdkWindowObject *)window)->state & GDK_WINDOW_STATE_FULLSCREEN)
|
|
return;
|
|
|
|
move_resize_window_internal (window, x, y, -1, -1);
|
|
}
|
|
|
|
void
|
|
gdk_window_resize (GdkWindow *window,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (((GdkWindowObject *)window)->state & GDK_WINDOW_STATE_FULLSCREEN)
|
|
return;
|
|
|
|
if (width < 1)
|
|
width = 1;
|
|
if (height < 1)
|
|
height = 1;
|
|
|
|
move_resize_window_internal (window, -1, -1, width, height);
|
|
}
|
|
|
|
void
|
|
gdk_window_move_resize (GdkWindow *window,
|
|
gint x,
|
|
gint y,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
if (width < 1)
|
|
width = 1;
|
|
if (height < 1)
|
|
height = 1;
|
|
|
|
move_resize_window_internal (window, x, y, width, height);
|
|
}
|
|
|
|
void
|
|
gdk_window_reparent (GdkWindow *window,
|
|
GdkWindow *new_parent,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
GdkWindowObject *private, *old_parent_private, *new_parent_private;
|
|
GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
|
|
NSView *view, *new_parent_view;
|
|
|
|
if (!new_parent || new_parent == _gdk_root)
|
|
{
|
|
/* Could be added, just needs implementing. */
|
|
g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
|
|
return;
|
|
}
|
|
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
view = impl->view;
|
|
|
|
new_parent_private = GDK_WINDOW_OBJECT (new_parent);
|
|
new_parent_impl = GDK_WINDOW_IMPL_QUARTZ (new_parent_private->impl);
|
|
new_parent_view = new_parent_impl->view;
|
|
|
|
old_parent_private = GDK_WINDOW_OBJECT (private->parent);
|
|
old_parent_impl = GDK_WINDOW_IMPL_QUARTZ (old_parent_private->impl);
|
|
|
|
[view retain];
|
|
|
|
[view removeFromSuperview];
|
|
[new_parent_view addSubview:view];
|
|
|
|
[view release];
|
|
|
|
private->x = x;
|
|
private->y = y;
|
|
private->parent = (GdkWindowObject *)new_parent;
|
|
|
|
if (old_parent_private)
|
|
{
|
|
old_parent_private->children = g_list_remove (old_parent_private->children, window);
|
|
old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
|
|
}
|
|
|
|
new_parent_private->children = g_list_prepend (new_parent_private->children, window);
|
|
new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_clear_area (GdkWindow *window,
|
|
gint x,
|
|
gint y,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_clear_area_e (GdkWindow *window,
|
|
gint x,
|
|
gint y,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
/* 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;
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
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);
|
|
}
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
|
|
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
|
|
gdk_window_raise (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
if (WINDOW_IS_TOPLEVEL (window))
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_lower (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
if (WINDOW_IS_TOPLEVEL (window))
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_background (GdkWindow *window,
|
|
const GdkColor *color)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *)window;
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
private->bg_color = *color;
|
|
|
|
if (private->bg_pixmap &&
|
|
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
|
|
private->bg_pixmap != GDK_NO_BG)
|
|
g_object_unref (private->bg_pixmap);
|
|
|
|
private->bg_pixmap = NULL;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_back_pixmap (GdkWindow *window,
|
|
GdkPixmap *pixmap,
|
|
gboolean parent_relative)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *)window;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (pixmap == NULL || !parent_relative);
|
|
g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
if (private->bg_pixmap &&
|
|
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
|
|
private->bg_pixmap != GDK_NO_BG)
|
|
g_object_unref (private->bg_pixmap);
|
|
|
|
if (parent_relative)
|
|
{
|
|
private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
|
|
GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
|
|
}
|
|
else
|
|
{
|
|
if (pixmap)
|
|
{
|
|
g_object_ref (pixmap);
|
|
private->bg_pixmap = pixmap;
|
|
}
|
|
else
|
|
{
|
|
private->bg_pixmap = GDK_NO_BG;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_cursor (GdkWindow *window,
|
|
GdkCursor *cursor)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
GdkCursorPrivate *cursor_private;
|
|
NSCursor *nscursor;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
cursor_private = (GdkCursorPrivate *)cursor;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (!cursor)
|
|
nscursor = NULL;
|
|
else
|
|
nscursor = [cursor_private->nscursor retain];
|
|
|
|
if (impl->nscursor)
|
|
[impl->nscursor release];
|
|
|
|
impl->nscursor = nscursor;
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
|
|
_gdk_quartz_events_update_cursor (_gdk_quartz_events_get_mouse_window (TRUE));
|
|
}
|
|
|
|
void
|
|
gdk_window_get_geometry (GdkWindow *window,
|
|
gint *x,
|
|
gint *y,
|
|
gint *width,
|
|
gint *height,
|
|
gint *depth)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
NSRect ns_rect;
|
|
|
|
g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
|
|
|
|
if (!window)
|
|
window = _gdk_root;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
if (window == _gdk_root)
|
|
{
|
|
if (x)
|
|
*x = 0;
|
|
if (y)
|
|
*y = 0;
|
|
|
|
if (width)
|
|
*width = impl->width;
|
|
if (height)
|
|
*height = impl->height;
|
|
}
|
|
else if (WINDOW_IS_TOPLEVEL (window))
|
|
{
|
|
ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
|
|
|
|
/* This doesn't work exactly as in X. There doesn't seem to be a
|
|
* way to get the coords relative to the parent window (usually
|
|
* the window frame), but that seems useless except for
|
|
* borderless windows where it's relative to the root window. So
|
|
* we return (0, 0) (should be something like (0, 22)) for
|
|
* windows with borders and the root relative coordinates
|
|
* otherwise.
|
|
*/
|
|
if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
|
|
{
|
|
if (x)
|
|
*x = ns_rect.origin.x;
|
|
if (y)
|
|
*y = _gdk_quartz_window_get_inverted_screen_y (ns_rect.origin.y + ns_rect.size.height);
|
|
}
|
|
else
|
|
{
|
|
if (x)
|
|
*x = 0;
|
|
if (y)
|
|
*y = 0;
|
|
}
|
|
|
|
if (width)
|
|
*width = ns_rect.size.width;
|
|
if (height)
|
|
*height = ns_rect.size.height;
|
|
}
|
|
else
|
|
{
|
|
ns_rect = [impl->view frame];
|
|
|
|
if (x)
|
|
*x = ns_rect.origin.x;
|
|
if (y)
|
|
*y = ns_rect.origin.y;
|
|
if (width)
|
|
*width = ns_rect.size.width;
|
|
if (height)
|
|
*height = ns_rect.size.height;
|
|
}
|
|
|
|
if (depth)
|
|
*depth = gdk_drawable_get_depth (window);
|
|
}
|
|
|
|
gboolean
|
|
gdk_window_get_origin (GdkWindow *window,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
GdkWindowObject *private;
|
|
int tmp_x = 0, tmp_y = 0;
|
|
GdkWindow *toplevel;
|
|
NSRect content_rect;
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
{
|
|
if (x)
|
|
*x = 0;
|
|
if (y)
|
|
*y = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (window == _gdk_root)
|
|
{
|
|
*x = 0;
|
|
*y = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
|
|
toplevel = gdk_window_get_toplevel (window);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
|
|
|
|
content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
|
|
|
|
tmp_x = content_rect.origin.x;
|
|
tmp_y = _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height);
|
|
|
|
while (private != GDK_WINDOW_OBJECT (toplevel))
|
|
{
|
|
tmp_x += private->x;
|
|
tmp_y += private->y;
|
|
|
|
private = private->parent;
|
|
}
|
|
|
|
if (x)
|
|
*x = tmp_x;
|
|
if (y)
|
|
*y = tmp_y;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gdk_window_get_deskrelative_origin (GdkWindow *window,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
|
|
|
|
return gdk_window_get_origin (window, x, y);
|
|
}
|
|
|
|
void
|
|
gdk_window_get_root_origin (GdkWindow *window,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
GdkRectangle rect;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
rect.x = 0;
|
|
rect.y = 0;
|
|
|
|
gdk_window_get_frame_extents (window, &rect);
|
|
|
|
if (x)
|
|
*x = rect.x;
|
|
|
|
if (y)
|
|
*y = rect.y;
|
|
}
|
|
|
|
/* Returns coordinates relative to the root. */
|
|
void
|
|
_gdk_windowing_get_pointer (GdkDisplay *display,
|
|
GdkScreen **screen,
|
|
gint *x,
|
|
gint *y,
|
|
GdkModifierType *mask)
|
|
{
|
|
g_return_if_fail (display == _gdk_display);
|
|
|
|
*screen = _gdk_screen;
|
|
_gdk_windowing_window_get_pointer (_gdk_display, _gdk_root, x, y, mask);
|
|
}
|
|
|
|
/* Returns coordinates relative to the passed in window. */
|
|
GdkWindow *
|
|
_gdk_windowing_window_get_pointer (GdkDisplay *display,
|
|
GdkWindow *window,
|
|
gint *x,
|
|
gint *y,
|
|
GdkModifierType *mask)
|
|
{
|
|
GdkWindowObject *toplevel;
|
|
GdkWindowObject *private;
|
|
NSPoint point;
|
|
gint x_tmp, y_tmp;
|
|
GdkWindow *found_window;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
{
|
|
*x = 0;
|
|
*y = 0;
|
|
*mask = 0;
|
|
return NULL;
|
|
}
|
|
|
|
toplevel = GDK_WINDOW_OBJECT (gdk_window_get_toplevel (window));
|
|
|
|
*mask = _gdk_quartz_events_get_current_event_mask ();
|
|
|
|
/* Get the y coordinate, needs to be flipped. */
|
|
if (window == _gdk_root)
|
|
{
|
|
point = [NSEvent mouseLocation];
|
|
x_tmp = point.x;
|
|
y_tmp = _gdk_quartz_window_get_inverted_screen_y (point.y);
|
|
}
|
|
else
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
NSWindow *nswindow;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
|
|
nswindow = impl->toplevel;
|
|
|
|
point = [nswindow mouseLocationOutsideOfEventStream];
|
|
x_tmp = point.x;
|
|
y_tmp = impl->height - point.y;
|
|
}
|
|
|
|
/* The coords are relative to the toplevel of the passed in window
|
|
* at this point, make them relative to the passed in window:
|
|
*/
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
while (private != toplevel)
|
|
{
|
|
x_tmp -= private->x;
|
|
y_tmp -= private->y;
|
|
|
|
private = private->parent;
|
|
}
|
|
|
|
found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp);
|
|
|
|
/* We never return the root window. */
|
|
if (found_window == _gdk_root)
|
|
found_window = NULL;
|
|
|
|
*x = x_tmp;
|
|
*y = y_tmp;
|
|
|
|
return found_window;
|
|
}
|
|
|
|
void
|
|
gdk_display_warp_pointer (GdkDisplay *display,
|
|
GdkScreen *screen,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
|
|
}
|
|
|
|
/* Returns coordinates relative to the found window. */
|
|
GdkWindow *
|
|
_gdk_windowing_window_at_pointer (GdkDisplay *display,
|
|
gint *win_x,
|
|
gint *win_y)
|
|
{
|
|
GdkModifierType mask;
|
|
GdkWindow *found_window;
|
|
gint x, y;
|
|
|
|
found_window = _gdk_windowing_window_get_pointer (display,
|
|
_gdk_root,
|
|
&x, &y,
|
|
&mask);
|
|
if (found_window)
|
|
{
|
|
GdkWindowObject *private;
|
|
|
|
/* The coordinates returned above are relative the root, we want
|
|
* coordinates relative the window here.
|
|
*/
|
|
private = GDK_WINDOW_OBJECT (found_window);
|
|
while (private != GDK_WINDOW_OBJECT (_gdk_root))
|
|
{
|
|
x -= private->x;
|
|
y -= private->y;
|
|
|
|
private = private->parent;
|
|
}
|
|
|
|
*win_x = x;
|
|
*win_y = y;
|
|
}
|
|
else
|
|
{
|
|
/* Mimic the X backend here, -1,-1 for unknown windows. */
|
|
*win_x = -1;
|
|
*win_y = -1;
|
|
}
|
|
|
|
return found_window;
|
|
}
|
|
|
|
GdkEventMask
|
|
gdk_window_get_events (GdkWindow *window)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return 0;
|
|
else
|
|
return GDK_WINDOW_OBJECT (window)->event_mask;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_events (GdkWindow *window,
|
|
GdkEventMask event_mask)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (!GDK_WINDOW_DESTROYED (window))
|
|
{
|
|
GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_urgency_hint (GdkWindow *window,
|
|
gboolean urgent)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_geometry_hints (GdkWindow *window,
|
|
const GdkGeometry *geometry,
|
|
GdkWindowHints geom_mask)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (geometry != NULL);
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
|
|
if (!impl->toplevel)
|
|
return;
|
|
|
|
if (geom_mask & GDK_HINT_POS)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_USER_POS)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_USER_SIZE)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_MIN_SIZE)
|
|
{
|
|
NSSize size;
|
|
|
|
size.width = geometry->min_width;
|
|
size.height = geometry->min_height;
|
|
|
|
[impl->toplevel setContentMinSize:size];
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_MAX_SIZE)
|
|
{
|
|
NSSize size;
|
|
|
|
size.width = geometry->max_width;
|
|
size.height = geometry->max_height;
|
|
|
|
[impl->toplevel setContentMaxSize:size];
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_BASE_SIZE)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_RESIZE_INC)
|
|
{
|
|
NSSize size;
|
|
|
|
size.width = geometry->width_inc;
|
|
size.height = geometry->height_inc;
|
|
|
|
[impl->toplevel setContentResizeIncrements:size];
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_ASPECT)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
if (geom_mask & GDK_HINT_WIN_GRAVITY)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_title (GdkWindow *window,
|
|
const gchar *title)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (title != NULL);
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)window)->impl);
|
|
|
|
if (impl->toplevel)
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
[impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_role (GdkWindow *window,
|
|
const gchar *role)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_transient_for (GdkWindow *window,
|
|
GdkWindow *parent)
|
|
{
|
|
GdkWindowImplQuartz *window_impl;
|
|
GdkWindowImplQuartz *parent_impl;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent))
|
|
return;
|
|
|
|
window_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
if (!window_impl->toplevel)
|
|
return;
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (window_impl->transient_for)
|
|
{
|
|
_gdk_quartz_window_detach_from_parent (window);
|
|
|
|
g_object_unref (window_impl->transient_for);
|
|
window_impl->transient_for = NULL;
|
|
}
|
|
|
|
parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
|
|
if (parent_impl->toplevel)
|
|
{
|
|
/* We save the parent because it needs to be unset/reset when
|
|
* hiding and showing the window.
|
|
*/
|
|
|
|
/* We don't set transients for tooltips, they are already
|
|
* handled by the window level being the top one. If we do, then
|
|
* the parent window will be brought to the top just because the
|
|
* tooltip is, which is not what we want.
|
|
*/
|
|
if (gdk_window_get_type_hint (window) != GDK_WINDOW_TYPE_HINT_TOOLTIP)
|
|
{
|
|
window_impl->transient_for = g_object_ref (parent);
|
|
|
|
/* We only add the window if it is shown, otherwise it will
|
|
* be shown unconditionally here. If it is not shown, the
|
|
* window will be added in show() instead.
|
|
*/
|
|
if (!(GDK_WINDOW_OBJECT (window)->state & GDK_WINDOW_STATE_WITHDRAWN))
|
|
_gdk_quartz_window_attach_to_parent (window);
|
|
}
|
|
}
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
|
|
void
|
|
gdk_window_shape_combine_region (GdkWindow *window,
|
|
const GdkRegion *shape,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_shape_combine_mask (GdkWindow *window,
|
|
GdkBitmap *mask,
|
|
gint x, gint y)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_input_shape_combine_mask (GdkWindow *window,
|
|
GdkBitmap *mask,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_input_shape_combine_region (GdkWindow *window,
|
|
const GdkRegion *shape_region,
|
|
gint offset_x,
|
|
gint offset_y)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_child_input_shapes (GdkWindow *window)
|
|
{
|
|
/* FIXME: IMplement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_override_redirect (GdkWindow *window,
|
|
gboolean override_redirect)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_accept_focus (GdkWindow *window,
|
|
gboolean accept_focus)
|
|
{
|
|
GdkWindowObject *private;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
private = (GdkWindowObject *)window;
|
|
|
|
private->accept_focus = accept_focus != FALSE;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_child_shapes (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_merge_child_shapes (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_merge_child_input_shapes (GdkWindow *window)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
gboolean
|
|
gdk_window_set_static_gravities (GdkWindow *window,
|
|
gboolean use_static)
|
|
{
|
|
/* FIXME: Implement */
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_focus_on_map (GdkWindow *window,
|
|
gboolean focus_on_map)
|
|
{
|
|
GdkWindowObject *private;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
private = (GdkWindowObject *)window;
|
|
|
|
private->focus_on_map = focus_on_map != FALSE;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_icon (GdkWindow *window,
|
|
GdkWindow *icon_window,
|
|
GdkPixmap *pixmap,
|
|
GdkBitmap *mask)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_icon_name (GdkWindow *window,
|
|
const gchar *name)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_focus (GdkWindow *window,
|
|
guint32 timestamp)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
private = (GdkWindowObject*) window;
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if (impl->toplevel)
|
|
{
|
|
if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP)
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
[impl->toplevel makeKeyAndOrderFront:impl->toplevel];
|
|
clear_toplevel_order ();
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_hints (GdkWindow *window,
|
|
gint x,
|
|
gint y,
|
|
gint min_width,
|
|
gint min_height,
|
|
gint max_width,
|
|
gint max_height,
|
|
gint flags)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
static
|
|
gint window_type_hint_to_level (GdkWindowTypeHint hint)
|
|
{
|
|
switch (hint)
|
|
{
|
|
case GDK_WINDOW_TYPE_HINT_DOCK:
|
|
case GDK_WINDOW_TYPE_HINT_UTILITY:
|
|
return NSFloatingWindowLevel;
|
|
|
|
case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
|
|
case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
|
|
return NSTornOffMenuWindowLevel;
|
|
|
|
case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
|
|
case GDK_WINDOW_TYPE_HINT_TOOLTIP:
|
|
return NSStatusWindowLevel;
|
|
|
|
case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
|
|
case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
|
|
case GDK_WINDOW_TYPE_HINT_COMBO:
|
|
case GDK_WINDOW_TYPE_HINT_DND:
|
|
return NSPopUpMenuWindowLevel;
|
|
|
|
case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
|
|
case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
|
|
case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
|
|
case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return NSNormalWindowLevel;
|
|
}
|
|
|
|
static gboolean
|
|
window_type_hint_to_shadow (GdkWindowTypeHint hint)
|
|
{
|
|
switch (hint)
|
|
{
|
|
case GDK_WINDOW_TYPE_HINT_NORMAL: /* Normal toplevel window */
|
|
case GDK_WINDOW_TYPE_HINT_DIALOG: /* Dialog window */
|
|
case GDK_WINDOW_TYPE_HINT_DOCK:
|
|
case GDK_WINDOW_TYPE_HINT_UTILITY:
|
|
case GDK_WINDOW_TYPE_HINT_MENU: /* Torn-off menu */
|
|
case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
|
|
case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
|
|
case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
|
|
case GDK_WINDOW_TYPE_HINT_COMBO:
|
|
case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
|
|
case GDK_WINDOW_TYPE_HINT_TOOLTIP:
|
|
return TRUE;
|
|
|
|
case GDK_WINDOW_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
|
|
case GDK_WINDOW_TYPE_HINT_DESKTOP: /* N/A */
|
|
case GDK_WINDOW_TYPE_HINT_DND:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void
|
|
gdk_window_set_type_hint (GdkWindow *window,
|
|
GdkWindowTypeHint hint)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
|
|
|
|
impl->type_hint = hint;
|
|
|
|
/* Match the documentation, only do something if we're not mapped yet. */
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
return;
|
|
|
|
[impl->toplevel setHasShadow: window_type_hint_to_shadow (hint)];
|
|
[impl->toplevel setLevel: window_type_hint_to_level (hint)];
|
|
}
|
|
|
|
GdkWindowTypeHint
|
|
gdk_window_get_type_hint (GdkWindow *window)
|
|
{
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return GDK_WINDOW_TYPE_HINT_NORMAL;
|
|
|
|
return GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_modal_hint (GdkWindow *window,
|
|
gboolean modal)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_skip_taskbar_hint (GdkWindow *window,
|
|
gboolean skips_taskbar)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_set_skip_pager_hint (GdkWindow *window,
|
|
gboolean skips_pager)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_begin_resize_drag (GdkWindow *window,
|
|
GdkWindowEdge edge,
|
|
gint button,
|
|
gint root_x,
|
|
gint root_y,
|
|
guint32 timestamp)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (edge != GDK_WINDOW_EDGE_SOUTH_EAST)
|
|
{
|
|
g_warning ("Resizing is only implemented for GDK_WINDOW_EDGE_SOUTH_EAST on Mac OS");
|
|
return;
|
|
}
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if (!impl->toplevel)
|
|
{
|
|
g_warning ("Can't call gdk_window_begin_resize_drag on non-toplevel window");
|
|
return;
|
|
}
|
|
|
|
[(GdkQuartzWindow *)impl->toplevel beginManualResize];
|
|
}
|
|
|
|
void
|
|
gdk_window_begin_move_drag (GdkWindow *window,
|
|
gint button,
|
|
gint root_x,
|
|
gint root_y,
|
|
guint32 timestamp)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
if (!impl->toplevel)
|
|
{
|
|
g_warning ("Can't call gdk_window_begin_move_drag on non-toplevel window");
|
|
return;
|
|
}
|
|
|
|
[(GdkQuartzWindow *)impl->toplevel beginManualMove];
|
|
}
|
|
|
|
void
|
|
gdk_window_set_icon_list (GdkWindow *window,
|
|
GList *pixbufs)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
gdk_window_get_frame_extents (GdkWindow *window,
|
|
GdkRectangle *rect)
|
|
{
|
|
GdkWindowObject *private;
|
|
GdkWindow *toplevel;
|
|
GdkWindowImplQuartz *impl;
|
|
NSRect ns_rect;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (rect != NULL);
|
|
|
|
private = GDK_WINDOW_OBJECT (window);
|
|
|
|
rect->x = 0;
|
|
rect->y = 0;
|
|
rect->width = 1;
|
|
rect->height = 1;
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
toplevel = gdk_window_get_toplevel (window);
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
|
|
|
|
ns_rect = [impl->toplevel frame];
|
|
|
|
rect->x = ns_rect.origin.x;
|
|
rect->y = _gdk_quartz_window_get_inverted_screen_y (ns_rect.origin.y + ns_rect.size.height);
|
|
rect->width = ns_rect.size.width;
|
|
rect->height = ns_rect.size.height;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_decorations (GdkWindow *window,
|
|
GdkWMDecoration decorations)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
int old_mask, new_mask;
|
|
NSView *old_view;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
if (decorations == 0 || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP)
|
|
{
|
|
new_mask = NSBorderlessWindowMask;
|
|
}
|
|
else
|
|
{
|
|
/* FIXME: Honor other GDK_DECOR_* flags. */
|
|
new_mask = (NSTitledWindowMask | NSClosableWindowMask |
|
|
NSMiniaturizableWindowMask | NSResizableWindowMask);
|
|
}
|
|
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
old_mask = [impl->toplevel styleMask];
|
|
|
|
/* Note, there doesn't seem to be a way to change this without
|
|
* recreating the toplevel. There might be bad side-effects of doing
|
|
* that, but it seems alright.
|
|
*/
|
|
if (old_mask != new_mask)
|
|
{
|
|
NSRect rect;
|
|
|
|
old_view = [impl->toplevel contentView];
|
|
|
|
rect = [impl->toplevel frame];
|
|
|
|
/* Properly update the size of the window when the titlebar is
|
|
* added or removed.
|
|
*/
|
|
if (old_mask == NSBorderlessWindowMask &&
|
|
new_mask != NSBorderlessWindowMask)
|
|
{
|
|
rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
|
|
|
|
}
|
|
else if (old_mask != NSBorderlessWindowMask &&
|
|
new_mask == NSBorderlessWindowMask)
|
|
{
|
|
rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
|
|
}
|
|
|
|
impl->toplevel = [impl->toplevel initWithContentRect:rect
|
|
styleMask:new_mask
|
|
backing:NSBackingStoreBuffered
|
|
defer:NO];
|
|
|
|
[impl->toplevel setHasShadow: window_type_hint_to_shadow (impl->type_hint)];
|
|
[impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
|
|
|
|
[impl->toplevel setContentView:old_view];
|
|
[impl->toplevel setFrame:rect display:YES];
|
|
|
|
/* Invalidate the window shadow for non-opaque views that have shadow
|
|
* enabled, to get the shadow shape updated.
|
|
*/
|
|
if (![old_view isOpaque] && [impl->toplevel hasShadow])
|
|
[(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
|
|
}
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
|
|
gboolean
|
|
gdk_window_get_decorations (GdkWindow *window,
|
|
GdkWMDecoration *decorations)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
|
|
g_return_val_if_fail (WINDOW_IS_TOPLEVEL (window), FALSE);
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return FALSE;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
if (decorations)
|
|
{
|
|
/* Borderless is 0, so we can't check it as a bit being set. */
|
|
if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
|
|
{
|
|
*decorations = 0;
|
|
}
|
|
else
|
|
{
|
|
/* FIXME: Honor the other GDK_DECOR_* flags. */
|
|
*decorations = GDK_DECOR_ALL;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_functions (GdkWindow *window,
|
|
GdkWMFunction functions)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_get_offsets (GdkWindow *window,
|
|
gint *x_offset,
|
|
gint *y_offset)
|
|
{
|
|
*x_offset = *y_offset = 0;
|
|
}
|
|
|
|
gboolean
|
|
_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
|
|
GdkRegion *area)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
gdk_window_stick (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
}
|
|
|
|
void
|
|
gdk_window_unstick (GdkWindow *window)
|
|
{
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
}
|
|
|
|
void
|
|
gdk_window_maximize (GdkWindow *window)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (impl->toplevel && ![impl->toplevel isZoomed])
|
|
[impl->toplevel zoom:nil];
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
else
|
|
{
|
|
gdk_synthesize_window_state (window,
|
|
0,
|
|
GDK_WINDOW_STATE_MAXIMIZED);
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_unmaximize (GdkWindow *window)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (impl->toplevel && [impl->toplevel isZoomed])
|
|
[impl->toplevel zoom:nil];
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
else
|
|
{
|
|
gdk_synthesize_window_state (window,
|
|
GDK_WINDOW_STATE_MAXIMIZED,
|
|
0);
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_iconify (GdkWindow *window)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (impl->toplevel)
|
|
[impl->toplevel miniaturize:nil];
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
else
|
|
{
|
|
gdk_synthesize_window_state (window,
|
|
0,
|
|
GDK_WINDOW_STATE_ICONIFIED);
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_deiconify (GdkWindow *window)
|
|
{
|
|
GdkWindowImplQuartz *impl;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
|
|
|
|
if (GDK_WINDOW_IS_MAPPED (window))
|
|
{
|
|
GDK_QUARTZ_ALLOC_POOL;
|
|
|
|
if (impl->toplevel)
|
|
[impl->toplevel deminiaturize:nil];
|
|
|
|
GDK_QUARTZ_RELEASE_POOL;
|
|
}
|
|
else
|
|
{
|
|
gdk_synthesize_window_state (window,
|
|
GDK_WINDOW_STATE_ICONIFIED,
|
|
0);
|
|
}
|
|
}
|
|
|
|
static FullscreenSavedGeometry *
|
|
get_fullscreen_geometry (GdkWindow *window)
|
|
{
|
|
return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
|
|
}
|
|
|
|
void
|
|
gdk_window_fullscreen (GdkWindow *window)
|
|
{
|
|
FullscreenSavedGeometry *geometry;
|
|
GdkWindowObject *private = (GdkWindowObject *) window;
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
NSRect frame;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
|
|
|
|
geometry = get_fullscreen_geometry (window);
|
|
if (!geometry)
|
|
{
|
|
geometry = g_new (FullscreenSavedGeometry, 1);
|
|
|
|
geometry->x = private->x;
|
|
geometry->y = private->y;
|
|
geometry->width = impl->width;
|
|
geometry->height = impl->height;
|
|
|
|
if (!gdk_window_get_decorations (window, &geometry->decor))
|
|
geometry->decor = GDK_DECOR_ALL;
|
|
|
|
g_object_set_data_full (G_OBJECT (window),
|
|
FULLSCREEN_DATA, geometry,
|
|
g_free);
|
|
|
|
gdk_window_set_decorations (window, 0);
|
|
|
|
frame = [[NSScreen mainScreen] frame];
|
|
move_resize_window_internal (window,
|
|
0, 0,
|
|
frame.size.width, frame.size.height);
|
|
}
|
|
|
|
HideMenuBar ();
|
|
|
|
gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
|
|
}
|
|
|
|
void
|
|
gdk_window_unfullscreen (GdkWindow *window)
|
|
{
|
|
FullscreenSavedGeometry *geometry;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
|
|
|
|
geometry = get_fullscreen_geometry (window);
|
|
if (geometry)
|
|
{
|
|
ShowMenuBar ();
|
|
|
|
move_resize_window_internal (window,
|
|
geometry->x,
|
|
geometry->y,
|
|
geometry->width,
|
|
geometry->height);
|
|
|
|
gdk_window_set_decorations (window, geometry->decor);
|
|
|
|
g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
|
|
|
|
gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *) window;
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
gint level;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
level = window_type_hint_to_level (gdk_window_get_type_hint (window));
|
|
|
|
/* Adjust normal window level by one if necessary. */
|
|
[impl->toplevel setLevel: level + (setting ? 1 : 0)];
|
|
}
|
|
|
|
void
|
|
gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *) window;
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
gint level;
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
level = window_type_hint_to_level (gdk_window_get_type_hint (window));
|
|
|
|
/* Adjust normal window level by one if necessary. */
|
|
[impl->toplevel setLevel: level - (setting ? 1 : 0)];
|
|
}
|
|
|
|
GdkWindow *
|
|
gdk_window_get_group (GdkWindow *window)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
|
|
g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
|
|
|
|
/* FIXME: Implement */
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gdk_window_set_group (GdkWindow *window,
|
|
GdkWindow *leader)
|
|
{
|
|
/* FIXME: Implement */
|
|
}
|
|
|
|
GdkWindow*
|
|
gdk_window_foreign_new_for_display (GdkDisplay *display,
|
|
GdkNativeWindow anid)
|
|
{
|
|
/* Foreign windows aren't supported in Mac OS X */
|
|
return NULL;
|
|
}
|
|
|
|
GdkWindow*
|
|
gdk_window_lookup (GdkNativeWindow anid)
|
|
{
|
|
/* Foreign windows aren't supported in Mac OS X */
|
|
return NULL;
|
|
}
|
|
|
|
GdkWindow *
|
|
gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
|
|
{
|
|
/* Foreign windows aren't supported in Mac OS X */
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gdk_window_enable_synchronized_configure (GdkWindow *window)
|
|
{
|
|
}
|
|
|
|
void
|
|
gdk_window_configure_finished (GdkWindow *window)
|
|
{
|
|
}
|
|
|
|
void
|
|
gdk_window_destroy_notify (GdkWindow *window)
|
|
{
|
|
}
|
|
|
|
void
|
|
gdk_window_beep (GdkWindow *window)
|
|
{
|
|
gdk_display_beep (_gdk_display);
|
|
}
|
|
|
|
void
|
|
gdk_window_set_opacity (GdkWindow *window,
|
|
gdouble opacity)
|
|
{
|
|
GdkWindowObject *private = (GdkWindowObject *) window;
|
|
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
|
|
|
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
|
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
|
|
|
|
if (GDK_WINDOW_DESTROYED (window))
|
|
return;
|
|
|
|
if (opacity < 0)
|
|
opacity = 0;
|
|
else if (opacity > 1)
|
|
opacity = 1;
|
|
|
|
[impl->toplevel setAlphaValue: opacity];
|
|
}
|
|
|
|
void
|
|
_gdk_windowing_window_set_composited (GdkWindow *window, gboolean composited)
|
|
{
|
|
}
|