diff options
author | Anders Carlsson <andersca@imendio.com> | 2005-11-22 10:03:32 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@src.gnome.org> | 2005-11-22 10:03:32 +0000 |
commit | 1097260aa7ed40e508e181feed4d736727268eb5 (patch) | |
tree | fc2cf27583bbe96d0e464d90e9fbec2f07d7b76a | |
parent | fbebb232db61324e89406a27bc914ace62c68e79 (diff) | |
download | gdk-pixbuf-1097260aa7ed40e508e181feed4d736727268eb5.tar.gz |
Add quartz backend.
2005-11-21 Anders Carlsson <andersca@imendio.com>
* configure.in:
* gtk/Makefile.am:
* gdk/Makefile.am:
* gdk/quartz/*:
Add quartz backend.
* docs/tools/Makefile.am:
Only build docshooter when the X11 backend is used.
* gtk/gtkplug-stub.c:
Include gtkplug.h here.
* gtk/gtksocket-stub.c:
Include gtksocket.h here.
41 files changed, 7228 insertions, 9 deletions
@@ -38,7 +38,6 @@ (gtk_combo_box_child_show, gtk_combo_box_child_hide): Use g_signal_emit, not g_signal_emit_by_name. ->>>>>>> 1.7265 2005-11-18 Matthias Clasen <mclasen@redhat.com> Fix crashes in connection with pathbar scrolling (#321560, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index a71cfecf5..951070137 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -38,7 +38,6 @@ (gtk_combo_box_child_show, gtk_combo_box_child_hide): Use g_signal_emit, not g_signal_emit_by_name. ->>>>>>> 1.7265 2005-11-18 Matthias Clasen <mclasen@redhat.com> Fix crashes in connection with pathbar scrolling (#321560, diff --git a/configure.in b/configure.in index 7741c3720..3fb359992 100644 --- a/configure.in +++ b/configure.in @@ -224,13 +224,13 @@ else gdktarget=x11 fi -AC_ARG_WITH(gdktarget, [ --with-gdktarget=[[x11/linux-fb/win32]] select non-default GDK target], +AC_ARG_WITH(gdktarget, [ --with-gdktarget=[[x11/linux-fb/win32/quartz]] select non-default GDK target], gdktarget=$with_gdktarget) AC_SUBST(gdktarget) case $gdktarget in - x11|linux-fb|win32) ;; - *) AC_MSG_ERROR([Invalid target for GDK: use x11, linux-fb or win32.]);; + x11|linux-fb|win32|quartz) ;; + *) AC_MSG_ERROR([Invalid target for GDK: use x11, linux-fb, quartz or win32.]);; esac gdktargetlib=libgdk-$gdktarget-$GTK_API_VERSION.la @@ -1325,6 +1325,13 @@ else AM_CONDITIONAL(USE_WIN32, false) fi +if test "x$gdktarget" = "xquartz"; then + GDK_EXTRA_LIBS="$GDK_EXTRA_LIBS -framework Cocoa" + AM_CONDITIONAL(USE_QUARTZ, true) +else + AM_CONDITIONAL(USE_QUARTZ, false) +fi + GDK_PIXBUF_XLIB_DEP_LIBS="`$PKG_CONFIG --libs $GDK_PIXBUF_PACKAGES $GDK_PIXBUF_XLIB_PACKAGES` $GDK_PIXBUF_XLIB_EXTRA_LIBS $GDK_PIXBUF_EXTRA_LIBS" GDK_PIXBUF_XLIB_DEP_CFLAGS="`$PKG_CONFIG --cflags gthread-2.0 $GDK_PIXBUF_PACKAGES $GDK_PIXBUF_XLIB_PACKAGES` $GDK_PIXBUF_EXTRA_CFLAGS $GDK_PIXBUF_XLIB_EXTRA_CFLAGS" @@ -1569,6 +1576,9 @@ elif test "x$gdktarget" = "xlinux-fb" ; then gdk_windowing=' #define GDK_WINDOWING_FB #define GDK_NATIVE_WINDOW_POINTER' +elif test "x$gdktarget" = "xquartz" ; then + gdk_windowing=' +#define GDK_WINDOWING_QUARTZ' fi if test x$gdk_wchar_h = xyes; then @@ -1625,6 +1635,7 @@ gdk/win32/Makefile gdk/win32/rc/Makefile gdk/win32/rc/gdk.rc gdk/linux-fb/Makefile +gdk/quartz/Makefile gtk/Makefile gtk/makefile.msc gtk/gtkversion.h diff --git a/docs/tools/Makefile.am b/docs/tools/Makefile.am index 6d6c95631..97ec058f2 100644 --- a/docs/tools/Makefile.am +++ b/docs/tools/Makefile.am @@ -17,7 +17,7 @@ LDADDS = \ $(top_builddir)/gtk/$(gtktargetlib) \ $(GTK_DEP_LIBS) -if OS_UNIX +if USE_X11 noinst_PROGRAMS = \ doc-shooter endif diff --git a/gdk/Makefile.am b/gdk/Makefile.am index 56c47b199..c2a4f8de8 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -1,7 +1,7 @@ ## Makefile.am for gtk+/gdk SUBDIRS = $(gdktarget) -DIST_SUBDIRS = linux-fb win32 x11 +DIST_SUBDIRS = linux-fb win32 x11 quartz EXTRA_DIST = \ keynames.txt \ @@ -144,6 +144,11 @@ libgdk_linux_fb_2_0_la_LIBADD = linux-fb/libgdk-linux-fb.la $(GDK_DEP_LIBS) \ $(top_builddir)/gdk-pixbuf/libgdk_pixbuf-$(GTK_API_VERSION).la libgdk_linux_fb_2_0_la_LDFLAGS = $(LDADD) +libgdk_quartz_2_0_la_SOURCES = $(common_sources) gdkkeynames.c +libgdk_quartz_2_0_la_LIBADD = quartz/libgdk-quartz.la $(GDK_DEP_LIBS) \ + $(top_builddir)/gdk-pixbuf/libgdk_pixbuf-$(GTK_API_VERSION).la +libgdk_quartz_2_0_la_LDFLAGS = $(LDADD) + libgdk_win32_2_0_la_SOURCES = $(common_sources) gdkkeynames.c libgdk_win32_2_0_la_LIBADD = win32/libgdk-win32.la $(GDK_DEP_LIBS) \ $(top_builddir)/gdk-pixbuf/libgdk_pixbuf-$(GTK_API_VERSION).la @@ -198,7 +203,7 @@ endif lib_LTLIBRARIES = $(gdktargetlib) -EXTRA_LTLIBRARIES = libgdk-x11-2.0.la libgdk-linux-fb-2.0.la libgdk-win32-2.0.la +EXTRA_LTLIBRARIES = libgdk-x11-2.0.la libgdk-linux-fb-2.0.la libgdk-win32-2.0.la libgdk-quartz-2.0.la MAINTAINERCLEANFILES = gdkenumtypes.h stamp-gdkenumtypes.h gdkenumtypes.c \ gdkmarshalers.h gdkmarshalers.c diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c new file mode 100644 index 000000000..979e0e354 --- /dev/null +++ b/gdk/quartz/GdkQuartzView.c @@ -0,0 +1,83 @@ +/* GdkQuartzView.m + * + * Copyright (C) 2005 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. + */ + + +#import "GdkQuartzView.h" +#include "gdkwindow-quartz.h" +#include "gdkprivate-quartz.h" + +@implementation GdkQuartzView + +-(void)setGdkWindow:(GdkWindow *)window +{ + gdk_window = window; +} + +-(GdkWindow *)gdkWindow +{ + return gdk_window; +} + +-(BOOL)isFlipped +{ + return YES; +} + +-(BOOL)isOpaque +{ + /* A view is opaque if its GdkWindow doesn't have the RGBA colormap */ + return gdk_drawable_get_colormap (gdk_window) != gdk_screen_get_rgba_colormap (_gdk_screen); +} + +-(void)drawRect:(NSRect)rect +{ + NSRect bounds = [self bounds]; + GdkRectangle gdk_rect; + + GDK_QUARTZ_ALLOC_POOL; + + /* Draw background */ + if (GDK_WINDOW_OBJECT (gdk_window)->bg_pixmap == NULL) + { + CGContextRef context; + + context = [[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState (context); + + _gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (gdk_window), + GDK_WINDOW_OBJECT (gdk_window)->bg_color.pixel); + + CGContextFillRect (context, CGRectMake (bounds.origin.x, bounds.origin.y, + bounds.size.width, bounds.size.height)); + CGContextRestoreGState (context); + } + + gdk_rect.x = bounds.origin.x; + gdk_rect.y = bounds.origin.y; + gdk_rect.width = bounds.size.width; + gdk_rect.height = bounds.size.height; + + gdk_window_invalidate_rect (gdk_window, &gdk_rect, FALSE); + gdk_window_process_updates (gdk_window, FALSE); + + GDK_QUARTZ_RELEASE_POOL; +} + +@end diff --git a/gdk/quartz/GdkQuartzView.h b/gdk/quartz/GdkQuartzView.h new file mode 100644 index 000000000..0e25b2ecc --- /dev/null +++ b/gdk/quartz/GdkQuartzView.h @@ -0,0 +1,35 @@ +/* GdkQuartzView.h + * + * Copyright (C) 2005 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. + */ + +#import <Quartz/Quartz.h> +#include "gdkwindow.h" + +@interface GdkQuartzView : NSView { + GdkWindow *gdk_window; +} + +-(void)setGdkWindow:(GdkWindow *)window; +-(GdkWindow *)gdkWindow; + +@end + + + + diff --git a/gdk/quartz/GdkQuartzWindow.c b/gdk/quartz/GdkQuartzWindow.c new file mode 100644 index 000000000..2365dd4a4 --- /dev/null +++ b/gdk/quartz/GdkQuartzWindow.c @@ -0,0 +1,114 @@ +/* GdkQuartzWindow.m + * + * Copyright (C) 2005 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. + */ + + +#import "GdkQuartzWindow.h" +#include "gdkwindow-quartz.h" +#include "gdkprivate-quartz.h" + +@implementation GdkQuartzWindow + +-(BOOL)windowShouldClose:(id)sender +{ + GdkWindow *window = [[self contentView] gdkWindow]; + GdkEvent *event; + + event = gdk_event_new (GDK_DELETE); + + event->any.window = g_object_ref (window); + event->any.send_event = FALSE; + + _gdk_event_queue_append (gdk_display_get_default (), event); + + return NO; +} + +-(void)windowDidMiniaturize:(NSNotification *)aNotification +{ + GdkWindow *window = [[self contentView] gdkWindow]; + + gdk_synthesize_window_state (window, 0, + GDK_WINDOW_STATE_ICONIFIED); +} + +-(void)windowDidDeminiaturize:(NSNotification *)aNotification +{ + GdkWindow *window = [[self contentView] gdkWindow]; + + gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0); +} + +-(void)windowDidBecomeKey:(NSNotification *)aNotification +{ + GdkWindow *window = [[self contentView] gdkWindow]; + + _gdk_quartz_update_focus_window (window); +} + +-(void)windowDidResize:(NSNotification *)aNotification +{ + NSRect content_rect = [self contentRectForFrameRect:[self frame]]; + GdkWindow *window = [[self contentView] gdkWindow]; + GdkWindowObject *private = (GdkWindowObject *)window; + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + GdkEvent *event; + + impl->width = content_rect.size.width; + impl->height = content_rect.size.height; + + /* Synthesize a configure event */ + + event = gdk_event_new (GDK_CONFIGURE); + event->configure.window = g_object_ref (window); + event->configure.x = private->x; + event->configure.y = private->y; + event->configure.width = impl->width; + event->configure.height = impl->height; + + _gdk_event_queue_append (gdk_display_get_default (), event); + + /* Update tracking rectangle */ + [[self contentView] removeTrackingRect:impl->tracking_rect]; + impl->tracking_rect = [impl->view addTrackingRect:NSMakeRect(0, 0, impl->width, impl->height) + owner:impl->view + userData:nil + assumeInside:NO]; +} + +-(id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag +{ + self = [super initWithContentRect:contentRect + styleMask:styleMask + backing:backingType + defer:flag]; + + + /* A possible modification here would be to only accept mouse moved events + * if any of the child GdkWindows are interested in mouse moved events. + */ + [self setAcceptsMouseMovedEvents:YES]; + + [self setDelegate:self]; + [self setReleasedWhenClosed:YES]; + + return self; +} + +@end diff --git a/gdk/quartz/GdkQuartzWindow.h b/gdk/quartz/GdkQuartzWindow.h new file mode 100644 index 000000000..c73da5582 --- /dev/null +++ b/gdk/quartz/GdkQuartzWindow.h @@ -0,0 +1,31 @@ +/* GdkQuartzWindow.h + * + * Copyright (C) 2005 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. + */ + +#import <Quartz/Quartz.h> +#include "gdkwindow.h" + +@interface GdkQuartzWindow : NSWindow { +} + +@end + + + + diff --git a/gdk/quartz/Makefile.am b/gdk/quartz/Makefile.am new file mode 100644 index 000000000..b9d0b98a2 --- /dev/null +++ b/gdk/quartz/Makefile.am @@ -0,0 +1,45 @@ +libgdkincludedir = $(includedir)/gtk-2.0/gdk + +INCLUDES = \ + -DG_LOG_DOMAIN=\"Gdk\" \ + -DGDK_COMPILATION \ + -I$(top_srcdir) \ + -I$(top_srcdir)/gdk \ + -I$(top_builddir)/gdk \ + -DG_DISABLE_DEPRECATED \ + -DGDK_PIXBUF_DISABLE_DEPRECATED \ + -DGDK_DISABLE_DEPRECATED \ + $(GTK_DEBUG_FLAGS) \ + $(GDK_DEP_CFLAGS) \ + "-xobjective-c" + +LDADDS = $(GDK_DEP_LIBS) + +noinst_LTLIBRARIES = libgdk-quartz.la + +libgdk_quartz_la_SOURCES = \ + GdkQuartzView.c \ + GdkQuartzView.h \ + GdkQuartzWindow.c \ + GdkQuartzWindow.h \ + gdkcolor-quartz.c \ + gdkcursor-quartz.c \ + gdkdisplay-quartz.c \ + gdkdnd-quartz.c \ + gdkdrawable-quartz.c \ + gdkevents-quartz.c \ + gdkfont-quartz.c \ + gdkgc-quartz.c \ + gdkgeometry-quartz.c \ + gdkglobals-quartz.c \ + gdkim-quartz.c \ + gdkimage-quartz.c \ + gdkinput.c \ + gdkkeys-quartz.c \ + gdkmain-quartz.c \ + gdkpixmap-quartz.c \ + gdkproperty-quartz.c \ + gdkscreen-quartz.c \ + gdkselection-quartz.c \ + gdkvisual-quartz.c \ + gdkwindow-quartz.c diff --git a/gdk/quartz/gdkcolor-quartz.c b/gdk/quartz/gdkcolor-quartz.c new file mode 100644 index 000000000..92a9e3f2a --- /dev/null +++ b/gdk/quartz/gdkcolor-quartz.c @@ -0,0 +1,195 @@ +/* gdkcolor-quartz.c + * + * Copyright (C) 2005 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 "gdkcolor.h" +#include "gdkprivate-quartz.h" + +GType +gdk_colormap_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkColormapClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkColormap), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkColormap", + &object_info, + 0); + } + + return object_type; +} + +GdkColormap * +gdk_colormap_new (GdkVisual *visual, + gint private_cmap) +{ + g_return_val_if_fail (visual != NULL, NULL); + + /* FIXME: Implement */ + return NULL; +} + +GdkColormap * +gdk_screen_get_system_colormap (GdkScreen *screen) +{ + static GdkColormap *colormap = NULL; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + if (!colormap) + { + colormap = g_object_new (GDK_TYPE_COLORMAP, NULL); + + colormap->visual = gdk_visual_get_system (); + colormap->size = colormap->visual->colormap_size; + } + + return colormap; +} + + +GdkColormap * +gdk_screen_get_rgba_colormap (GdkScreen *screen) +{ + static GdkColormap *colormap = NULL; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + if (!colormap) + { + colormap = g_object_new (GDK_TYPE_COLORMAP, NULL); + + colormap->visual = gdk_screen_get_rgba_visual (screen); + colormap->size = colormap->visual->colormap_size; + } + + return colormap; +} + +void +gdk_colormap_change (GdkColormap *colormap, + gint ncolors) +{ + /* FIXME: Implement */ +} + +void +gdk_colormap_free_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors) +{ + /* This function shouldn't do anything since + * colors are neve allocated. + */ +} + +gint +gdk_colormap_alloc_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + int i; + + for (i = 0; i < ncolors; i++) + { + colors[i].pixel = ((colors[i].red >> 8) & 0xff) << 16 | + ((colors[i].green >> 8) & 0xff) << 8 | + ((colors[i].blue >> 8) & 0xff); + } + + return ncolors; +} + +void +gdk_colormap_query_color (GdkColormap *colormap, + gulong pixel, + GdkColor *result) +{ + result->red = pixel >> 16 & 0xff; + result->red += result->red << 8; + + result->green = pixel >> 8 & 0xff; + result->green += result->green << 8; + + result->blue = pixel & 0xff; + result->blue += result->blue << 8; +} + +GdkScreen* +gdk_colormap_get_screen (GdkColormap *cmap) +{ + g_return_val_if_fail (cmap != NULL, NULL); + + return gdk_screen_get_default (); +} + +void +_gdk_quartz_set_context_fill_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel) +{ + float red, green, blue, alpha; + + red = (pixel >> 16 & 0xff) / 255.0; + green = (pixel >> 8 & 0xff) / 255.0; + blue = (pixel & 0xff) / 255.0; + + if (colormap && gdk_colormap_get_visual (colormap)->depth == 32) + alpha = (pixel >> 24 & 0xff) / 255.0; + else + alpha = 1.0; + + CGContextSetRGBFillColor (context, red, green, blue, alpha); +} + +void +_gdk_quartz_set_context_stroke_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel) +{ + float red, green, blue, alpha; + + red = (pixel >> 16 & 0xff) / 255.0; + green = (pixel >> 8 & 0xff) / 255.0; + blue = (pixel & 0xff) / 255.0; + + if (colormap && gdk_colormap_get_visual (colormap)->depth == 32) + alpha = (pixel >> 24 & 0xff) / 255.0; + else + alpha = 1.0; + + CGContextSetRGBStrokeColor (context, red, green, blue, 1.0); +} + diff --git a/gdk/quartz/gdkcursor-quartz.c b/gdk/quartz/gdkcursor-quartz.c new file mode 100644 index 000000000..e87d0481b --- /dev/null +++ b/gdk/quartz/gdkcursor-quartz.c @@ -0,0 +1,310 @@ +/* gdkcursor-quartz.c + * + * Copyright (C) 2005 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 "gdkdisplay.h" +#include "gdkcursor.h" +#include "gdkprivate-quartz.h" + +static GdkCursor * +gdk_quartz_cursor_new_from_nscursor (NSCursor *nscursor, GdkCursorType cursor_type) +{ + GdkCursorPrivate *private; + GdkCursor *cursor; + + private = g_new (GdkCursorPrivate, 1); + private->nscursor = nscursor; + cursor = (GdkCursor *)private; + cursor->type = cursor_type; + cursor->ref_count = 1; + + return cursor; +} + +GdkCursor* +gdk_cursor_new_for_display (GdkDisplay *display, + GdkCursorType cursor_type) +{ + NSCursor *nscursor; + + g_return_val_if_fail (display == gdk_display_get_default (), NULL); + + switch (cursor_type) + { + case GDK_XTERM: + nscursor = [NSCursor IBeamCursor]; + break; + case GDK_SB_H_DOUBLE_ARROW: + nscursor = [NSCursor resizeLeftRightCursor]; + break; + case GDK_SB_V_DOUBLE_ARROW: + nscursor = [NSCursor resizeUpDownCursor]; + break; + default: + g_warning ("Unsupported cursor type %d, using default", cursor_type); + nscursor = [NSCursor arrowCursor]; + } + + [nscursor retain]; + + return gdk_quartz_cursor_new_from_nscursor (nscursor, cursor_type); +} + +GdkCursor* +gdk_cursor_new_from_pixmap (GdkPixmap *source, + GdkPixmap *mask, + const GdkColor *fg, + const GdkColor *bg, + gint x, + gint y) +{ + NSAutoreleasePool *pool; + NSBitmapImageRep *bitmap_rep; + NSImage *image; + NSCursor *nscursor; + GdkCursor *cursor; + gint width, height; + gint tmp_x, tmp_y; + guchar *dst_data, *mask_data, *src_data; + guchar *mask_start, *src_start; + int dst_stride; + + gdk_drawable_get_size (source, &width, &height); + + g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL); + g_return_val_if_fail (GDK_IS_PIXMAP (mask), NULL); + g_return_val_if_fail (fg != NULL, NULL); + g_return_val_if_fail (bg != NULL, NULL); + + pool = [[NSAutoreleasePool alloc] init]; + + bitmap_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:width pixelsHigh:height + bitsPerSample:8 samplesPerPixel:4 + hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:0 bitsPerPixel:0]; + + dst_stride = [bitmap_rep bytesPerRow]; + mask_start = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (mask)->impl)->data; + src_start = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (source)->impl)->data; + + for (tmp_y = 0; tmp_y < height; tmp_y++) + { + dst_data = [bitmap_rep bitmapData] + tmp_y * dst_stride; + mask_data = mask_start + tmp_y * width; + src_data = src_start + tmp_y * width; + + for (tmp_x = 0; tmp_x < width; tmp_x++) + { + if (*mask_data++) + { + const GdkColor *color; + + if (*src_data++) + color = fg; + else + color = bg; + + *dst_data++ = (color->red >> 8) & 0xff; + *dst_data++ = (color->green >> 8) & 0xff; + *dst_data++ = (color->blue >> 8) & 0xff; + *dst_data++ = 0xff; + + } + else + { + *dst_data++ = 0x00; + *dst_data++ = 0x00; + *dst_data++ = 0x00; + *dst_data++ = 0x00; + + src_data++; + } + } + } + image = [[NSImage alloc] init]; + [image addRepresentation:bitmap_rep]; + [bitmap_rep release]; + + nscursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(x, y)]; + [image release]; + + cursor = gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP); + [pool release]; + + return cursor; +} + +GdkCursor * +gdk_cursor_new_from_pixbuf (GdkDisplay *display, + GdkPixbuf *pixbuf, + gint x, + gint y) +{ + NSAutoreleasePool *pool; + NSBitmapImageRep *bitmap_rep; + NSImage *image; + NSCursor *nscursor; + GdkCursor *cursor; + gboolean has_alpha; + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); + g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL); + g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL); + + pool = [[NSAutoreleasePool alloc] init]; + + has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); + + /* Create a bitmap image rep */ + bitmap_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:gdk_pixbuf_get_width (pixbuf) + pixelsHigh:gdk_pixbuf_get_height (pixbuf) + bitsPerSample:8 samplesPerPixel:has_alpha ? 4 : 3 + hasAlpha:has_alpha isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:0 bitsPerPixel:0]; + + { + /* Add pixel data to bitmap rep */ + guchar *src, *dst; + int src_stride, dst_stride; + int x, y; + + src_stride = gdk_pixbuf_get_rowstride (pixbuf); + dst_stride = [bitmap_rep bytesPerRow]; + + for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++) + { + src = gdk_pixbuf_get_pixels (pixbuf) + y * src_stride; + dst = [bitmap_rep bitmapData] + y * dst_stride; + + for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++) + { + if (has_alpha) + { + guchar red, green, blue, alpha; + + red = *src++; + green = *src++; + blue = *src++; + alpha = *src++; + + *dst++ = (red * alpha) / 255; + *dst++ = (green * alpha) / 255; + *dst++ = (blue * alpha) / 255; + *dst++ = alpha; + } + else + { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + } + } + } + } + + image = [[NSImage alloc] init]; + [image addRepresentation:bitmap_rep]; + [bitmap_rep release]; + + nscursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(x, y)]; + [image release]; + + cursor = gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP); + [pool release]; + + return cursor; +} + +GdkCursor* +gdk_cursor_new_from_name (GdkDisplay *display, + const gchar *name) +{ + /* FIXME: Implement */ + return NULL; +} + +void +_gdk_cursor_destroy (GdkCursor *cursor) +{ + GdkCursorPrivate *private; + + g_return_if_fail (cursor != NULL); + g_return_if_fail (cursor->ref_count == 0); + + private = (GdkCursorPrivate *)cursor; + [private->nscursor release]; + + g_free (private); +} + +gboolean +gdk_display_supports_cursor_alpha (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + + return TRUE; +} + +gboolean +gdk_display_supports_cursor_color (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + + return TRUE; +} + +guint +gdk_display_get_default_cursor_size (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), 0); + + /* Mac OS X doesn't have the notion of a default size */ + return 32; +} + +void +gdk_display_get_maximal_cursor_size (GdkDisplay *display, + guint *width, + guint *height) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); + + /* Cursor sizes in Mac OS X can be arbitrarily large */ + *width = 65536; + *height = 65536; +} + +GdkDisplay * +gdk_cursor_get_display (GdkCursor *cursor) +{ + g_return_val_if_fail (cursor != NULL, NULL); + + return gdk_display_get_default (); +} + +GdkPixbuf * +gdk_cursor_get_image (GdkCursor *cursor) +{ + /* FIXME: Implement */ + return NULL; +} diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c new file mode 100644 index 000000000..5d064716d --- /dev/null +++ b/gdk/quartz/gdkdisplay-quartz.c @@ -0,0 +1,143 @@ +/* gdkdisplay-quartz.c + * + * Copyright (C) 2005 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 "gdk.h" +#include "gdkprivate-quartz.h" + +void +_gdk_windowing_set_default_display (GdkDisplay *display) +{ + g_assert (_gdk_display == display); +} + +GdkDisplay * +gdk_display_open (const gchar *display_name) +{ + if (_gdk_display != NULL) + return NULL; + + _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL); + _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL); + + /* Initialize application */ + [NSApplication sharedApplication]; + + _gdk_visual_init (); + gdk_screen_set_default_colormap (_gdk_screen, + gdk_screen_get_system_colormap (_gdk_screen)); + _gdk_windowing_window_init (); + + + _gdk_events_init (); +#if 0 + /* FIXME: Remove the #if 0 when we have these functions */ + _gdk_input_init (); + _gdk_dnd_init (); +#endif + + g_signal_emit_by_name (gdk_display_manager_get (), + "display_opened", _gdk_display); + + return _gdk_display; +} + +G_CONST_RETURN gchar * +gdk_display_get_name (GdkDisplay *display) +{ + /* FIXME: Implement */ + return NULL; +} + +int +gdk_display_get_n_screens (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), 0); + + return 1; +} + +GdkScreen * +gdk_display_get_screen (GdkDisplay *display, + gint screen_num) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + g_return_val_if_fail (screen_num == 0, NULL); + + return _gdk_screen; +} + +GdkScreen * +gdk_display_get_default_screen (GdkDisplay *display) +{ + return _gdk_screen; +} + +void +gdk_display_keyboard_ungrab (GdkDisplay *display, + guint32 time) +{ + /* FIXME: Implement */ +} + +void +gdk_display_beep (GdkDisplay *display) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); + + NSBeep(); +} + +gboolean +gdk_display_supports_selection_notification (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + + /* FIXME: Implement */ + return FALSE; +} + +gboolean +gdk_display_request_selection_notification (GdkDisplay *display, + GdkAtom selection) + +{ + /* FIXME: Implement */ + return FALSE; +} + +gboolean +gdk_display_supports_clipboard_persistence (GdkDisplay *display) +{ + /* FIXME: Implement */ + return FALSE; +} + +void +gdk_display_store_clipboard (GdkDisplay *display, + GdkWindow *clipboard_window, + guint32 time_, + GdkAtom *targets, + gint n_targets) +{ + /* FIXME: Implement */ +} + diff --git a/gdk/quartz/gdkdnd-quartz.c b/gdk/quartz/gdkdnd-quartz.c new file mode 100644 index 000000000..9ff4c1c8b --- /dev/null +++ b/gdk/quartz/gdkdnd-quartz.c @@ -0,0 +1,178 @@ +/* gdkdnd-quartz.c + * + * Copyright (C) 2005 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 "gdkdnd.h" + +static void +gdk_drag_context_init (GdkDragContext *dragcontext) +{ + /* FIXME: Implement */ +} + +static void +gdk_drag_context_class_init (GdkDragContextClass *klass) +{ + /* FIXME: Implement */ +} + +GType +gdk_drag_context_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkDragContextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_drag_context_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkDragContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) gdk_drag_context_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkDragContext", + &object_info, + 0); + } + + return object_type; +} + +GdkDragContext * +gdk_drag_context_new (void) +{ + return (GdkDragContext *)g_object_new (gdk_drag_context_get_type (), NULL); +} + +void +gdk_drag_context_ref (GdkDragContext *context) +{ + g_object_ref (context); +} + +void +gdk_drag_context_unref (GdkDragContext *context) +{ + g_object_unref (context); +} + +GdkDragContext * +gdk_drag_begin (GdkWindow *window, + GList *targets) +{ + /* FIXME: Implement */ + return NULL; +} + +gboolean +gdk_drag_motion (GdkDragContext *context, + GdkWindow *dest_window, + GdkDragProtocol protocol, + gint x_root, + gint y_root, + GdkDragAction suggested_action, + GdkDragAction possible_actions, + guint32 time) +{ + /* FIXME: Implement */ + return FALSE; +} + +guint32 +gdk_drag_get_protocol_for_display (GdkDisplay *display, + guint32 xid, + GdkDragProtocol *protocol) +{ + /* FIXME: Implement */ + return 0; +} + +void +gdk_drag_find_window_for_screen (GdkDragContext *context, + GdkWindow *drag_window, + GdkScreen *screen, + gint x_root, + gint y_root, + GdkWindow **dest_window, + GdkDragProtocol *protocol) +{ + /* FIXME: Implement */ +} + +void +gdk_drag_drop (GdkDragContext *context, + guint32 time) +{ + /* FIXME: Implement */ +} + +void +gdk_drag_abort (GdkDragContext *context, + guint32 time) +{ + g_return_if_fail (context != NULL); + + /* FIXME: Implement */ +} + +void +gdk_drag_status (GdkDragContext *context, + GdkDragAction action, + guint32 time) +{ + /* FIXME: Implement */ +} + +void +gdk_drop_reply (GdkDragContext *context, + gboolean ok, + guint32 time) +{ + g_return_if_fail (context != NULL); + + /* FIXME: Implement */ +} + +void +gdk_drop_finish (GdkDragContext *context, + gboolean success, + guint32 time) +{ + /* FIXME: Implement */ +} + +void +gdk_window_register_dnd (GdkWindow *window) +{ + /* FIXME: Implement */ +} + +GdkAtom +gdk_drag_get_selection (GdkDragContext *context) +{ + /* FIXME: Implement */ + return GDK_NONE; +} diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c new file mode 100644 index 000000000..d3adb8d2d --- /dev/null +++ b/gdk/quartz/gdkdrawable-quartz.c @@ -0,0 +1,597 @@ +/* gdkdrawable-quartz.c + * + * Copyright (C) 2005 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 <cairo/cairo-quartz.h> +#include "gdkprivate-quartz.h" + +static gpointer parent_class; + +typedef struct { + GdkDrawable *drawable; + CGContextRef context; +} SurfaceInfo; + +static cairo_user_data_key_t surface_info_key; + +static void +surface_info_destroy (void *data) +{ + SurfaceInfo *info = data; + + _gdk_quartz_drawable_release_context (info->drawable, info->context); + + g_free (info); +} + +static cairo_surface_t * +gdk_quartz_ref_cairo_surface (GdkDrawable *drawable) +{ + GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable); + CGContextRef context; + int width, height; + cairo_surface_t *surface; + SurfaceInfo *info; + + if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable) && + GDK_WINDOW_DESTROYED (impl->wrapper)) + return NULL; + + context = _gdk_quartz_drawable_get_context (drawable, TRUE, FALSE); + if (!context) + return NULL; + + gdk_drawable_get_size (drawable, &width, &height); + + surface = cairo_quartz_surface_create (context, TRUE, width, height); + + info = g_new (SurfaceInfo, 1); + info->drawable = drawable; + info->context = context; + + cairo_surface_set_user_data (surface, &surface_info_key, + info, surface_info_destroy); + return surface; +} + +static void +gdk_quartz_set_colormap (GdkDrawable *drawable, + GdkColormap *colormap) +{ + GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable); + + if (impl->colormap == colormap) + return; + + if (impl->colormap) + g_object_unref (impl->colormap); + impl->colormap = colormap; + if (impl->colormap) + g_object_ref (impl->colormap); +} + +static GdkColormap* +gdk_quartz_get_colormap (GdkDrawable *drawable) +{ + return GDK_DRAWABLE_IMPL_QUARTZ (drawable)->colormap; +} + +static GdkScreen* +gdk_quartz_get_screen (GdkDrawable *drawable) +{ + return _gdk_screen; +} + +static GdkVisual* +gdk_quartz_get_visual (GdkDrawable *drawable) +{ + return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper); +} + +static int +gdk_quartz_get_depth (GdkDrawable *drawable) +{ + /* This is a bit bogus but I'm not sure the other way is better */ + + return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper); +} + +static void +gdk_quartz_draw_rectangle (GdkDrawable *drawable, + GdkGC *gc, + gboolean filled, + gint x, + gint y, + gint width, + gint height) +{ + CGContextRef context = _gdk_quartz_drawable_get_context (drawable, FALSE, TRUE); + CGRect rect = CGRectMake (x, y, width, height); + + if (!context) + return; + + _gdk_quartz_update_context_from_gc (context, gc); + + if (filled) + { + _gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (drawable), + _gdk_gc_get_fg_pixel (gc)); + CGContextFillRect (context, rect); + } + else + { + _gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable), + _gdk_gc_get_fg_pixel (gc)); + CGContextStrokeRect (context, rect); + } + + _gdk_quartz_drawable_release_context (drawable, context); +} + +static void +gdk_quartz_draw_arc (GdkDrawable *drawable, + GdkGC *gc, + gboolean filled, + gint x, + gint y, + gint width, + gint height, + gint angle1, + gint angle2) +{ + CGContextRef context = _gdk_quartz_drawable_get_context (drawable, FALSE, TRUE); + float start_angle, end_angle; + + if (!context) + return; + + _gdk_quartz_update_context_from_gc (context, gc); + + CGContextSaveGState (context); + + CGContextTranslateCTM (context, + x + width / 2, + y + height / 2); + CGContextScaleCTM (context, 1.0, (float)height / width); + start_angle = (2 - (angle1 / (180.0 * 64.0))) * G_PI; + end_angle = start_angle - (angle2 / (180.0 * 64.0)) * G_PI; + + if (filled) + { + _gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (drawable), + _gdk_gc_get_fg_pixel (gc)); + + CGContextMoveToPoint (context, 0, 0); + CGContextAddArc (context, 0, 0, width / 2, + start_angle, end_angle, + TRUE); + CGContextClosePath (context); + CGContextFillPath (context); + } + else + { + _gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable), + _gdk_gc_get_fg_pixel (gc)); + CGContextAddArc (context, 0, 0, width / 2, + start_angle, end_angle, + TRUE); + CGContextStrokePath (context); + } + + CGContextRestoreGState (context); + + _gdk_quartz_drawable_release_context (drawable, context); +} + +static void +gdk_quartz_draw_polygon (GdkDrawable *drawable, + GdkGC *gc, + gboolean filled, + GdkPoint *points, + gint npoints) +{ + /* FIXME: Implement */ +} + +static void +gdk_quartz_draw_text (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const gchar *text, + gint text_length) +{ + /* FIXME: Implement */ +} + +static void +gdk_quartz_draw_text_wc (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const GdkWChar *text, + gint text_length) +{ + /* FIXME: Implement */ +} + +static void +gdk_quartz_draw_drawable (GdkDrawable *drawable, + GdkGC *gc, + GdkPixmap *src, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + int src_depth = gdk_drawable_get_depth (src); + int dest_depth = gdk_drawable_get_depth (drawable); + GdkDrawableImplQuartz *impl; + GdkDrawableImplQuartz *src_impl; + + impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable); + + if (GDK_IS_DRAWABLE_IMPL_QUARTZ (src)) + src_impl = GDK_DRAWABLE_IMPL_QUARTZ (src); + else + src_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (src)->impl); + + if (src_depth == 1) + { + /* FIXME: src depth 1 is not supported yet */ + } + else if (dest_depth != 0 && src_depth == dest_depth) + { + CGContextRef context = _gdk_quartz_drawable_get_context (drawable, FALSE, FALSE); + + if (!context) + return; + + _gdk_quartz_update_context_from_gc (context, gc); + + CGContextSetBlendMode (context, kCGBlendModeNormal); + + CGContextClipToRect (context, CGRectMake (xdest, ydest, width, height)); + CGContextTranslateCTM (context, xdest - xsrc, ydest - ysrc); + CGContextDrawImage (context, CGRectMake(0, 0, + GDK_PIXMAP_IMPL_QUARTZ (src_impl)->width, + GDK_PIXMAP_IMPL_QUARTZ (src_impl)->height), + GDK_PIXMAP_IMPL_QUARTZ (src_impl)->image); + + _gdk_quartz_drawable_release_context (drawable, context); + } + else + g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d", + src_depth, dest_depth); +} + +static void +gdk_quartz_draw_points (GdkDrawable *drawable, + GdkGC *gc, + GdkPoint *points, + gint npoints) +{ + int i; + + /* Just draw 1x1 rectangles */ + for (i = 0; i < npoints; i++) + { + gdk_draw_rectangle (drawable, gc, TRUE, + points[i].x, points[i].y, + 1, 1); + } +} + +static void +gdk_quartz_draw_segments (GdkDrawable *drawable, + GdkGC *gc, + GdkSegment *segs, + gint nsegs) +{ + CGContextRef context = _gdk_quartz_drawable_get_context (drawable, FALSE, TRUE); + int i; + + if (!context) + return; + + _gdk_quartz_update_context_from_gc (context, gc); + _gdk_quartz_set_context_stroke_color_from_pixel (context, gdk_drawable_get_colormap (drawable), + _gdk_gc_get_fg_pixel (gc)); + + for (i = 0; i < nsegs; i++) + { + CGContextMoveToPoint (context, segs[i].x1, segs[i].y1); + CGContextAddLineToPoint (context, segs[i].x2, segs[i].y2); + } + + CGContextStrokePath (context); + + _gdk_quartz_drawable_release_context (drawable, context); +} + +static void +gdk_quartz_draw_lines (GdkDrawable *drawable, + GdkGC *gc, + GdkPoint *points, + gint npoints) +{ + /* FIXME: Implement */ +} + +static void +gdk_quartz_draw_pixbuf (GdkDrawable *drawable, + GdkGC *gc, + GdkPixbuf *pixbuf, + gint src_x, + gint src_y, + gint dest_x, + gint dest_y, + gint width, + gint height, + GdkRgbDither dither, + gint x_dither, + gint y_dither) +{ + CGContextRef context = _gdk_quartz_drawable_get_context (drawable, FALSE, FALSE); + CGColorSpaceRef colorspace; + CGDataProviderRef data_provider; + CGImageRef image; + void *data; + int rowstride, pixbuf_width, pixbuf_height; + gboolean has_alpha; + + if (!context) + return; + + pixbuf_width = gdk_pixbuf_get_width (pixbuf); + pixbuf_height = gdk_pixbuf_get_height (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); + + data = gdk_pixbuf_get_pixels (pixbuf); + + colorspace = CGColorSpaceCreateDeviceRGB (); + data_provider = CGDataProviderCreateWithData (NULL, data, pixbuf_height * rowstride, NULL); + + image = CGImageCreate (pixbuf_width, pixbuf_height, 8, + has_alpha ? 32 : 24, rowstride, + colorspace, + has_alpha ? kCGImageAlphaLast : 0, + data_provider, NULL, FALSE, + kCGRenderingIntentDefault); + + CGDataProviderRelease (data_provider); + CGColorSpaceRelease (colorspace); + + _gdk_quartz_update_context_from_gc (context, gc); + + CGContextSetBlendMode (context, kCGBlendModeNormal); + + CGContextClipToRect (context, CGRectMake (dest_x, dest_y, width, height)); + CGContextTranslateCTM (context, dest_x - src_x, dest_y - src_y + pixbuf_height); + CGContextScaleCTM (context, 1, -1); + + CGContextDrawImage (context, CGRectMake(0, 0, pixbuf_width, pixbuf_height), image); + CGImageRelease (image); + + _gdk_quartz_drawable_release_context (drawable, context); +} + +static void +gdk_quartz_draw_image (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + CGContextRef context = _gdk_quartz_drawable_get_context (drawable, FALSE, FALSE); + CGColorSpaceRef colorspace; + CGDataProviderRef data_provider; + CGImageRef cgimage; + + if (!context) + return; + + colorspace = CGColorSpaceCreateDeviceRGB (); + data_provider = CGDataProviderCreateWithData (NULL, image->mem, image->height * image->bpl, NULL); + + /* FIXME: Make sure that this function draws 32-bit images correctly, + * also check endianness wrt kCGImageAlphaNoneSkipFirst */ + cgimage = CGImageCreate (image->width, image->height, 8, + 32, image->bpl, + colorspace, + kCGImageAlphaNoneSkipFirst, + data_provider, NULL, FALSE, kCGRenderingIntentDefault); + + CGDataProviderRelease (data_provider); + CGColorSpaceRelease (colorspace); + + _gdk_quartz_update_context_from_gc (context, gc); + + CGContextSetBlendMode (context, kCGBlendModeNormal); + + CGContextClipToRect (context, CGRectMake (xdest, ydest, width, height)); + CGContextTranslateCTM (context, xdest - xsrc, ydest - ysrc + image->height); + CGContextScaleCTM (context, 1, -1); + + CGContextDrawImage (context, CGRectMake (0, 0, image->width, image->height), cgimage); + CGImageRelease (cgimage); + + _gdk_quartz_drawable_release_context (drawable, context); +} + +static void +gdk_drawable_impl_quartz_finalize (GObject *object) +{ + GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (object); + + if (impl->colormap) + g_object_unref (impl->colormap); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gdk_drawable_impl_quartz_class_init (GdkDrawableImplQuartzClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_drawable_impl_quartz_finalize; + + drawable_class->create_gc = _gdk_quartz_gc_new; + drawable_class->draw_rectangle = gdk_quartz_draw_rectangle; + drawable_class->draw_arc = gdk_quartz_draw_arc; + drawable_class->draw_polygon = gdk_quartz_draw_polygon; + drawable_class->draw_text = gdk_quartz_draw_text; + drawable_class->draw_text_wc = gdk_quartz_draw_text_wc; + drawable_class->draw_drawable = gdk_quartz_draw_drawable; + drawable_class->draw_points = gdk_quartz_draw_points; + drawable_class->draw_segments = gdk_quartz_draw_segments; + drawable_class->draw_lines = gdk_quartz_draw_lines; + drawable_class->draw_image = gdk_quartz_draw_image; + drawable_class->draw_pixbuf = gdk_quartz_draw_pixbuf; + + drawable_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface; + + drawable_class->set_colormap = gdk_quartz_set_colormap; + drawable_class->get_colormap = gdk_quartz_get_colormap; + + drawable_class->get_depth = gdk_quartz_get_depth; + drawable_class->get_screen = gdk_quartz_get_screen; + drawable_class->get_visual = gdk_quartz_get_visual; + + drawable_class->_copy_to_image = _gdk_quartz_copy_to_image; +} + +GType +gdk_drawable_impl_quartz_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkDrawableImplQuartzClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_drawable_impl_quartz_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkDrawableImplQuartz), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_DRAWABLE, + "GdkDrawableImplQuartz", + &object_info, 0); + } + + return object_type; +} + +CGContextRef +_gdk_quartz_drawable_get_context (GdkDrawable *drawable, gboolean antialias, gboolean y_axis_is_off_by_one) +{ + if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable)) + { + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (drawable); + CGContextRef context; + + impl->pool = [[NSAutoreleasePool alloc] init]; + + if (![impl->view lockFocusIfCanDraw]) + { + [impl->pool release]; + return NULL; + } + + context = [[NSGraphicsContext currentContext] graphicsPort]; + + CGContextSaveGState (context); + CGContextSetAllowsAntialiasing (context, antialias); + + /* Sometimes when drawing certain primitives there's a one pixel + * difference when drawing to a CGImage and when drawing to a window, + * so we translate the ctm by 1 pixel here. + */ + if (y_axis_is_off_by_one) + CGContextTranslateCTM (context, 0, 1); + + return context; + } + else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable)) + { + GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (drawable); + CGContextRef context; + + context = CGBitmapContextCreate (impl->data, + CGImageGetWidth (impl->image), + CGImageGetHeight (impl->image), + CGImageGetBitsPerComponent (impl->image), + CGImageGetBytesPerRow (impl->image), + CGImageGetColorSpace (impl->image), + CGImageGetBitmapInfo (impl->image)); + CGContextSetAllowsAntialiasing (context, antialias); + + return context; + } + + g_assert_not_reached (); + + return NULL; +} + +void +_gdk_quartz_drawable_release_context (GdkDrawable *drawable, CGContextRef context) +{ + if (!context) + return; + + if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable)) + { + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (drawable); + + CGContextRestoreGState (context); + CGContextSetAllowsAntialiasing (context, TRUE); + + [[NSGraphicsContext currentContext] flushGraphics]; + [impl->view unlockFocus]; + [impl->pool release]; + } + else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable)) + { + CGContextRelease (context); + } +} diff --git a/gdk/quartz/gdkdrawable-quartz.h b/gdk/quartz/gdkdrawable-quartz.h new file mode 100644 index 000000000..36b996840 --- /dev/null +++ b/gdk/quartz/gdkdrawable-quartz.h @@ -0,0 +1,63 @@ +/* gdkdrawable-quartz.h + * + * Copyright (C) 2005 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. + */ + +#ifndef __GDK_DRAWABLE_QUARTZ_H__ +#define __GDK_DRAWABLE_QUARTZ_H__ + +#include <gdk/gdkdrawable.h> +#include <gdk/quartz/gdkquartz.h> + +G_BEGIN_DECLS + +/* Drawable implementation for Quartz + */ + +typedef struct _GdkDrawableImplQuartz GdkDrawableImplQuartz; +typedef struct _GdkDrawableImplQuartzClass GdkDrawableImplQuartzClass; + +#define GDK_TYPE_DRAWABLE_IMPL_QUARTZ (gdk_drawable_impl_quartz_get_type ()) +#define GDK_DRAWABLE_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAWABLE_IMPL_QUARTZ, GdkDrawableImplQuartz)) +#define GDK_DRAWABLE_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAWABLE_IMPL_QUARTZ, GdkDrawableImplQuartzClass)) +#define GDK_IS_DRAWABLE_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAWABLE_IMPL_QUARTZ)) +#define GDK_IS_DRAWABLE_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAWABLE_IMPL_QUARTZ)) +#define GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAWABLE_IMPL_QUARTZ, GdkDrawableImplQuartzClass)) + +struct _GdkDrawableImplQuartz +{ + GdkDrawable parent_instance; + + GdkDrawable *wrapper; + + GdkColormap *colormap; +}; + +struct _GdkDrawableImplQuartzClass +{ + GdkDrawableClass parent_class; +}; + +GType gdk_drawable_impl_quartz_get_type (void); + +CGContextRef _gdk_quartz_drawable_get_context (GdkDrawable *drawable, gboolean antialias, gboolean translate_y_axis); +void _gdk_quartz_drawable_release_context (GdkDrawable *drawable, CGContextRef context); + +G_END_DECLS + +#endif /* __GDK_DRAWABLE_QUARTZ_H__ */ diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c new file mode 100644 index 000000000..ac9eaf131 --- /dev/null +++ b/gdk/quartz/gdkevents-quartz.c @@ -0,0 +1,1286 @@ +/* gdkevents-quartz.c + * + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * Copyright (C) 1998-2002 Tor Lillqvist + * Copyright (C) 2005 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 <sys/types.h> +#include <sys/sysctl.h> + +#include "gdkscreen.h" +#include "gdkprivate-quartz.h" + +static GPollFD event_poll_fd; +static NSEvent *current_event; + +/* This is the window the mouse is currently over */ +static GdkWindow *current_mouse_window; + +/* This is the window corresponding to the key window */ +static GdkWindow *current_keyboard_window; + +/* This is the pointer grab window */ +static GdkWindow *pointer_grab_window; +static gboolean pointer_grab_owner_events; +static GdkEventMask pointer_grab_event_mask; +static gboolean pointer_grab_implicit; + +static gboolean +gdk_event_prepare (GSource *source, + gint *timeout) +{ + NSEvent *event; + gboolean retval; + + GDK_QUARTZ_ALLOC_POOL; + + *timeout = -1; + + event = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantPast] + inMode: NSDefaultRunLoopMode + dequeue: NO]; + + retval = (_gdk_event_queue_find_first (_gdk_display) != NULL || + event != NULL); + + GDK_QUARTZ_RELEASE_POOL; + + return retval; +} + +static gboolean +gdk_event_check (GSource *source) +{ + if (_gdk_event_queue_find_first (_gdk_display) != NULL || + current_event) + return TRUE; + + /* FIXME: We should maybe try to fetch an event again here */ + + return FALSE; +} + +static gboolean +gdk_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GdkEvent *event; + + GDK_QUARTZ_ALLOC_POOL; + + _gdk_events_queue (_gdk_display); + + event = _gdk_event_unqueue (_gdk_display); + + if (event) + { + if (_gdk_event_func) + (*_gdk_event_func) (event, _gdk_event_data); + + gdk_event_free (event); + } + + GDK_QUARTZ_RELEASE_POOL; + + return TRUE; +} + +static GSourceFuncs event_funcs = { + gdk_event_prepare, + gdk_event_check, + gdk_event_dispatch, + NULL +}; + +static GPollFunc old_poll_func; + +static gint +poll_func (GPollFD *ufds, guint nfds, gint timeout_) +{ + NSEvent *event; + NSDate *limit_date; + int n_active = 0; + + GDK_QUARTZ_ALLOC_POOL; + + /* FIXME: Support more than one pollfd */ + g_assert (nfds == 1); + + if (timeout_ == -1) + limit_date = [NSDate distantFuture]; + else if (timeout_ == 0) + limit_date = [NSDate distantPast]; + else + limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0]; + + event = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: limit_date + inMode: NSDefaultRunLoopMode + dequeue: YES]; + + if (event) + { + ufds[0].revents = G_IO_IN; + + g_assert (current_event == NULL); + + current_event = [event retain]; + + n_active ++; + } + + GDK_QUARTZ_RELEASE_POOL; + + return n_active; +} + +void +_gdk_events_init (void) +{ + GSource *source; + + event_poll_fd.events = G_IO_IN; + event_poll_fd.fd = -1; + + source = g_source_new (&event_funcs, sizeof (GSource)); + g_source_add_poll (source, &event_poll_fd); + g_source_set_priority (source, GDK_PRIORITY_EVENTS); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); + + /* FIXME: I really hate it that we need a custom poll function here. + * I think we can do better using threads. + */ + old_poll_func = g_main_context_get_poll_func (NULL); + g_main_context_set_poll_func (NULL, poll_func); + + current_mouse_window = g_object_ref (_gdk_root); + current_keyboard_window = g_object_ref (_gdk_root); +} + +gboolean +gdk_events_pending (void) +{ + /* FIXME: Implement */ + return FALSE; +} + +GdkEvent* +gdk_event_get_graphics_expose (GdkWindow *window) +{ + /* FIXME: Implement */ + return NULL; +} + +static void +pointer_ungrab_internal (gboolean implicit) +{ + if (!pointer_grab_window) + return; + + if (pointer_grab_implicit && !implicit) + return; + + g_object_unref (pointer_grab_window); + + pointer_grab_window = NULL; + /* FIXME: Send crossing events */ +} + + +gboolean +gdk_display_pointer_is_grabbed (GdkDisplay *display) +{ + return pointer_grab_window != NULL; +} + +gboolean +gdk_pointer_grab_info_libgtk_only (GdkDisplay *display, + GdkWindow **grab_window, + gboolean *owner_events) +{ + if (!pointer_grab_window) + return FALSE; + + if (grab_window) + *grab_window = pointer_grab_window; + + if (owner_events) + *owner_events = pointer_grab_owner_events; + + return FALSE; +} + +void +gdk_display_pointer_ungrab (GdkDisplay *display, + guint32 time) +{ + pointer_ungrab_internal (FALSE); +} + +static GdkGrabStatus +pointer_grab_internal (GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + gboolean implicit) +{ + /* FIXME: Send crossing events */ + + pointer_grab_window = g_object_ref (window); + pointer_grab_owner_events = owner_events; + pointer_grab_event_mask = event_mask; + pointer_grab_implicit = implicit; + + /* FIXME: Implement */ + return GDK_GRAB_SUCCESS; +} + +GdkGrabStatus +gdk_pointer_grab (GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time) +{ + g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0); + + if (pointer_grab_window) + { + if (!pointer_grab_implicit) + return GDK_GRAB_ALREADY_GRABBED; + else + pointer_ungrab_internal (TRUE); + } + + return pointer_grab_internal (window, owner_events, event_mask, + confine_to, cursor, FALSE); +} + +static void +fixup_event (GdkEvent *event) +{ + if (event->any.window) + g_object_ref (event->any.window); + if (((event->any.type == GDK_ENTER_NOTIFY) || + (event->any.type == GDK_LEAVE_NOTIFY)) && + (event->crossing.subwindow != NULL)) + g_object_ref (event->crossing.subwindow); + event->any.send_event = FALSE; +} + +static void +append_event (GdkEvent *event) +{ + fixup_event (event); + _gdk_event_queue_append (_gdk_display, event); +} + +static GdkFilterReturn +apply_filters (GdkWindow *window, + NSEvent *nsevent, + GList *filters) +{ + GdkFilterReturn result = GDK_FILTER_CONTINUE; + GdkEvent *event; + GList *node; + GList *tmp_list; + + event = gdk_event_new (GDK_NOTHING); + if (window != NULL) + event->any.window = g_object_ref (window); + ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING; + + /* I think GdkFilterFunc semantics require the passed-in event + * to already be in the queue. The filter func can generate + * more events and append them after it if it likes. + */ + node = _gdk_event_queue_append (_gdk_display, event); + + tmp_list = filters; + while (tmp_list) + { + GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data; + + tmp_list = tmp_list->next; + result = filter->function (nsevent, event, filter->data); + if (result != GDK_FILTER_CONTINUE) + break; + } + + if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE) + { + _gdk_event_queue_remove_link (_gdk_display, node); + g_list_free_1 (node); + gdk_event_free (event); + } + else /* GDK_FILTER_TRANSLATE */ + { + ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING; + fixup_event (event); + } + return result; +} + +static GdkWindow * +find_child_window_by_point_helper (GdkWindow *window, int x, int y, int x_offset, int y_offset, int *x_ret, int *y_ret) +{ + GList *children; + + for (children = GDK_WINDOW_OBJECT (window)->children; + children; children = children->next) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (children->data); + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + int temp_x, temp_y; + + if (!GDK_WINDOW_IS_MAPPED (private)) + continue; + + temp_x = x_offset + private->x; + temp_y = y_offset + private->y; + + /* FIXME: Are there off by one errors here? */ + if (x >= temp_x && y >= temp_y && + x < temp_x + impl->width && y < temp_y + impl->height) + { + *x_ret = x - private->x; + *y_ret = y - private->y; + + /* Look for child windows */ + return find_child_window_by_point_helper (GDK_WINDOW (children->data), x, y, temp_x, temp_y, x_ret, y_ret); + } + } + + return window; +} + +/* Given a toplevel window and coordinates, returns the window + * in which the point is. + */ +static GdkWindow * +find_child_window_by_point (GdkWindow *toplevel, int x, int y, int *x_ret, int *y_ret) +{ + GdkWindowObject *private = (GdkWindowObject *)toplevel; + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + + /* If the point is in the title bar, ignore it */ + if (y > impl->height) + return NULL; + + /* FIXME: Check this for off-by-one errors */ + /* First flip the y coordinate */ + y = impl->height - y; + + return find_child_window_by_point_helper (toplevel, x, y, 0, 0, x_ret, y_ret); +} + +/* Returns the current keyboard window */ +static GdkWindow * +find_current_keyboard_window (void) +{ + /* FIXME: Handle keyboard grabs */ + + return current_keyboard_window; +} + +/* this function checks if the passed in window is interested in the + * event mask. If so, it's returned. If not, the event can be propagated + * to its parent. + */ +static GdkWindow * +find_window_interested_in_event_mask (GdkWindow *window, + GdkEventMask event_mask, + gboolean propagate) +{ + while (window) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + + if (private->event_mask & event_mask) + return window; + + if (!propagate) + return NULL; + else + window = GDK_WINDOW (private->parent); + } + + return NULL; +} + +static guint32 +get_event_time (NSEvent *event) +{ + double time = [event timestamp]; + + return time * 1000.0; +} + +static int +convert_mouse_button_number (int button) +{ + switch (button) + { + case 0: + return 1; + case 1: + return 3; + case 2: + return 2; + default: + return button + 1; + } +} + +/* Return an event mask from an NSEvent */ +static GdkEventMask +get_event_mask_from_ns_event (NSEvent *nsevent) +{ + NSEventType event_type = [nsevent type]; + + switch (event_type) + { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + return GDK_BUTTON_PRESS_MASK; + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + return GDK_BUTTON_RELEASE_MASK; + case NSMouseMoved: + return GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK; + case NSScrollWheel: + /* Since applications that want button press events can get + * scroll events on X11 (since scroll wheel events are really + * button press events there), we need to use GDK_BUTTON_PRESS_MASK too. + */ + return GDK_SCROLL_MASK|GDK_BUTTON_PRESS_MASK; + case NSLeftMouseDragged: + return GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK| + GDK_BUTTON_MOTION_MASK|GDK_BUTTON1_MOTION_MASK; + case NSRightMouseDragged: + return GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK| + GDK_BUTTON_MOTION_MASK|GDK_BUTTON3_MOTION_MASK; + case NSOtherMouseDragged: + { + GdkEventMask mask = GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK| + GDK_BUTTON_MOTION_MASK; + if (convert_mouse_button_number ([nsevent buttonNumber]) == 2) + mask |= GDK_BUTTON2_MOTION_MASK; + + return mask; + } + case NSKeyDown: + return GDK_KEY_PRESS_MASK; + case NSKeyUp: + return GDK_KEY_RELEASE_MASK; + default: + g_assert_not_reached (); + } + + return 0; +} + +static GdkEvent * +create_focus_event (GdkWindow *window, + gboolean in) +{ + GdkEvent *event; + + event = gdk_event_new (GDK_FOCUS_CHANGE); + event->focus_change.window = window; + /* FIXME: send event */ + event->focus_change.in = in; + + return event; +} + +void +_gdk_quartz_update_focus_window (GdkWindow *new_window) +{ + /* FIXME: Don't do this when grabbed */ + + if (new_window != current_keyboard_window) + { + GdkEvent *event; + + event = create_focus_event (current_keyboard_window, FALSE); + append_event (event); + + event = create_focus_event (new_window, TRUE); + append_event (event); + + g_object_unref (current_keyboard_window); + + current_keyboard_window = g_object_ref (new_window); + } +} + +static gboolean +gdk_window_is_ancestor (GdkWindow *ancestor, + GdkWindow *window) +{ + if (ancestor == NULL || window == NULL) + return FALSE; + + return (gdk_window_get_parent (window) == ancestor || + gdk_window_is_ancestor (ancestor, gdk_window_get_parent (window))); +} + +static GdkModifierType +get_keyboard_modifiers_from_nsevent (NSEvent *nsevent) +{ + GdkModifierType modifiers = 0; + int nsflags; + + nsflags = [nsevent modifierFlags]; + + if (nsflags & NSAlphaShiftKeyMask) + modifiers |= GDK_LOCK_MASK; + if (nsflags & NSShiftKeyMask) + modifiers |= GDK_SHIFT_MASK; + if (nsflags & NSControlKeyMask) + modifiers |= GDK_CONTROL_MASK; + if (nsflags & NSControlKeyMask) + modifiers |= GDK_MOD1_MASK; + + /* FIXME: Support GDK_BUTTON_MASK */ + + return modifiers; +} + +static void +convert_window_coordinates_to_root (GdkWindow *window, gdouble x, gdouble y, + gdouble *x_root, gdouble *y_root) +{ + /* FIXME: Implement */ + *x_root = 0; + *y_root = 0; +} + +static GdkEvent * +create_crossing_event (GdkWindow *window, + NSEvent *nsevent, + GdkEventType event_type, + GdkCrossingMode mode, + GdkNotifyType detail) +{ + GdkEvent *event; + + event = gdk_event_new (event_type); + + event->crossing.window = window; + event->crossing.subwindow = NULL; /* FIXME */ + event->crossing.time = get_event_time (nsevent); + /* FIXME: x, y, x_root, y_root */ + event->crossing.mode = mode; + event->crossing.detail = detail; + /* FIXME: focus */ + /* FIXME: state, (button state too) */ + + return event; +} + +static void +synthesize_enter_event (GdkWindow *window, + NSEvent *nsevent, + GdkCrossingMode mode, + GdkNotifyType detail) +{ + GdkEvent *event; + + if (!(GDK_WINDOW_OBJECT (window)->event_mask & GDK_ENTER_NOTIFY_MASK)) + return; + + event = create_crossing_event (window, nsevent, GDK_ENTER_NOTIFY, + mode, detail); + + append_event (event); +} + +static void +synthesize_enter_events (GdkWindow *from, + GdkWindow *to, + NSEvent *nsevent, + GdkCrossingMode mode, + GdkNotifyType detail) +{ + GdkWindow *prev = gdk_window_get_parent (to); + + if (prev != from) + synthesize_enter_events (from, prev, nsevent, mode, detail); + synthesize_enter_event (to, nsevent, mode, detail); +} + +static void +synthesize_leave_event (GdkWindow *window, + NSEvent *nsevent, + GdkCrossingMode mode, + GdkNotifyType detail) +{ + GdkEvent *event; + + if (!(GDK_WINDOW_OBJECT (window)->event_mask & GDK_LEAVE_NOTIFY_MASK)) + return; + + event = create_crossing_event (window, nsevent, GDK_LEAVE_NOTIFY, + mode, detail); + + append_event (event); +} + +static void +synthesize_leave_events (GdkWindow *from, + GdkWindow *to, + NSEvent *nsevent, + GdkCrossingMode mode, + GdkNotifyType detail) +{ + GdkWindow *next = gdk_window_get_parent (from); + + synthesize_leave_event (from, nsevent, mode, detail); + if (next != to) + synthesize_leave_events (next, to, nsevent, mode, detail); +} + +static void +synthesize_crossing_events (GdkWindow *window, + GdkCrossingMode mode, + NSEvent *nsevent, + gint x, + gint y) +{ + GdkWindow *intermediate, *tem, *common_ancestor; + + if (gdk_window_is_ancestor (current_mouse_window, window)) + { + /* Pointer has moved to an inferior window. */ + synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_INFERIOR); + + /* If there are intermediate windows, generate ENTER_NOTIFY + * events for them + */ + intermediate = gdk_window_get_parent (window); + + if (intermediate != current_mouse_window) + { + synthesize_enter_events (current_mouse_window, intermediate, nsevent, mode, GDK_NOTIFY_VIRTUAL); + } + + synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_ANCESTOR); + } + else if (gdk_window_is_ancestor (window, current_mouse_window)) + { + /* Pointer has moved to an ancestor window. */ + synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_ANCESTOR); + + /* If there are intermediate windows, generate LEAVE_NOTIFY + * events for them + */ + intermediate = gdk_window_get_parent (current_mouse_window); + if (intermediate != window) + { + synthesize_leave_events (intermediate, window, nsevent, mode, GDK_NOTIFY_VIRTUAL); + } + + synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_INFERIOR); + } + else if (current_mouse_window) + { + /* Find least common ancestor of current_mouse_window and window */ + tem = current_mouse_window; + do { + common_ancestor = gdk_window_get_parent (tem); + tem = common_ancestor; + } while (common_ancestor && + !gdk_window_is_ancestor (common_ancestor, window)); + if (common_ancestor) + { + synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_NONLINEAR); + intermediate = gdk_window_get_parent (current_mouse_window); + if (intermediate != common_ancestor) + { + synthesize_leave_events (intermediate, common_ancestor, + nsevent, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL); + } + intermediate = gdk_window_get_parent (window); + if (intermediate != common_ancestor) + { + synthesize_enter_events (common_ancestor, intermediate, + nsevent, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL); + } + synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_NONLINEAR); + } + } + else + { + /* Dunno where we are coming from */ + synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_UNKNOWN); + } + + _gdk_quartz_update_mouse_window (window); +} + +/* Get current mouse window */ +GdkWindow * +_gdk_quartz_get_mouse_window (void) +{ + /* FIXME: What about grabs? */ + return current_mouse_window; +} + +/* Update mouse window */ +void +_gdk_quartz_update_mouse_window (GdkWindow *window) +{ + if (window) + g_object_ref (window); + if (current_mouse_window) + g_object_unref (current_mouse_window); + + current_mouse_window = window; +} + +/* Update current cursor */ +void +_gdk_quartz_update_cursor (GdkWindow *window) +{ + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + NSCursor *nscursor = nil; + + while (private) { + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + + nscursor = impl->nscursor; + if (nscursor) + break; + + private = private->parent; + } + + if (!nscursor) + nscursor = [NSCursor arrowCursor]; + + if ([NSCursor currentCursor] != nscursor) + [nscursor set]; +} + +/* This function finds the correct window to send an event to, + * taking into account grabs (FIXME: not done yet), event propagation, + * and event masks. + */ +static GdkWindow * +find_window_for_event (NSEvent *nsevent, gint *x, gint *y) +{ + NSWindow *nswindow = [nsevent window]; + NSEventType event_type = [nsevent type]; + + if (!nswindow) + return NULL; + + if (event_type == NSMouseMoved || + event_type == NSLeftMouseDragged || + event_type == NSRightMouseDragged || + event_type == NSOtherMouseDragged) + { + GdkWindow *toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow]; + NSPoint point = [nsevent locationInWindow]; + GdkWindow *mouse_window; + + mouse_window = find_child_window_by_point (toplevel, point.x, point.y, x, y); + + if (!mouse_window) + mouse_window = _gdk_root; + + if (pointer_grab_window) + { + if (mouse_window != current_mouse_window) + synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y); + } + else + { + if (current_mouse_window != mouse_window) + { + synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y); + + _gdk_quartz_update_cursor (mouse_window); + } + } + } + + switch (event_type) + { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + case NSMouseMoved: + case NSScrollWheel: + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + { + GdkWindow *toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow]; + NSPoint point = [nsevent locationInWindow]; + GdkWindow *mouse_window; + GdkEventMask event_mask; + GdkWindow *real_window; + + + if (pointer_grab_window) + { + if (pointer_grab_event_mask & get_event_mask_from_ns_event (nsevent)) + { + int tempx, tempy; + GdkWindowObject *w = GDK_WINDOW_OBJECT (pointer_grab_window); + + tempx = point.x; + tempy = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl)->height - + point.y; + + while (w != GDK_WINDOW_OBJECT (toplevel)) + { + tempx -= w->x; + tempy -= w->y; + + w = w->parent; + } + + *x = tempx; + *y = tempy; + + return pointer_grab_window; + } + else + { + return NULL; + } + } + + if (!nswindow) + { + mouse_window = _gdk_root; + } + else + { + mouse_window = find_child_window_by_point (toplevel, point.x, point.y, x, y); + } + + event_mask = get_event_mask_from_ns_event (nsevent); + real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE); + + return real_window; + } + case NSMouseEntered: + { + NSPoint point; + GdkWindow *toplevel; + GdkWindow *mouse_window; + + point = [nsevent locationInWindow]; + + toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow]; + + mouse_window = find_child_window_by_point (toplevel, point.x, point.y, x, y); + + synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, *x, *y); + + break; + } + case NSMouseExited: + synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, *x, *y); + break; + + case NSKeyDown: + case NSKeyUp: + { + GdkWindow *keyboard_window; + GdkEventMask event_mask; + GdkWindow *real_window; + + keyboard_window = find_current_keyboard_window (); + event_mask = get_event_mask_from_ns_event (nsevent); + real_window = find_window_interested_in_event_mask (keyboard_window, event_mask, TRUE); + + return real_window; + } + break; + + case NSAppKitDefined: + case NSSystemDefined: + /* We ignore these events */ + break; + default: + NSLog(@"Unhandled event %@", nsevent); + } + + return NULL; +} + +static GdkEvent * +create_button_event (GdkWindow *window, NSEvent *nsevent, + gint x, gint y) +{ + GdkEvent *event; + GdkEventType type; + guint button; + + switch ([nsevent type]) + { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + type = GDK_BUTTON_PRESS; + button = convert_mouse_button_number ([nsevent buttonNumber]); + break; + case NSLeftMouseUp: + type = GDK_BUTTON_RELEASE; + button = 1; + break; + case NSRightMouseUp: + type = GDK_BUTTON_RELEASE; + button = 3; + break; + case NSOtherMouseUp: + type = GDK_BUTTON_RELEASE; + button = convert_mouse_button_number ([nsevent buttonNumber]); + break; + default: + g_assert_not_reached (); + } + + event = gdk_event_new (type); + event->button.window = window; + event->button.time = get_event_time (nsevent); + event->button.x = x; + event->button.y = y; + /* FIXME event->axes */ + event->button.state = get_keyboard_modifiers_from_nsevent (nsevent); + event->button.button = button; + event->button.device = _gdk_display->core_pointer; + convert_window_coordinates_to_root (window, x, y, + &event->button.x_root, + &event->button.y_root); + + return event; +} + +static GdkEvent * +create_motion_event (GdkWindow *window, NSEvent *nsevent, gint x, gint y) +{ + GdkEvent *event; + GdkEventType type; + GdkModifierType state = 0; + int button = 0; + + switch ([nsevent type]) + { + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + button = convert_mouse_button_number ([nsevent buttonNumber]); + /* Fall through */ + case NSMouseMoved: + type = GDK_MOTION_NOTIFY; + break; + default: + g_assert_not_reached (); + } + + /* This maps buttons 1 to 5 to GDK_BUTTON[1-5]_MASK */ + if (button >= 1 && button <= 5) + state = (1 << (button + 7)); + + state |= get_keyboard_modifiers_from_nsevent (nsevent); + + event = gdk_event_new (type); + event->motion.window = window; + event->motion.time = get_event_time (nsevent); + event->motion.x = x; + event->motion.y = y; + /* FIXME event->axes */ + event->motion.state = state; + event->motion.is_hint = FALSE; + event->motion.device = _gdk_display->core_pointer; + convert_window_coordinates_to_root (window, x, y, + &event->motion.x_root, &event->motion.y_root); + + return event; +} + +static GdkEvent * +create_scroll_event (GdkWindow *window, NSEvent *nsevent, GdkScrollDirection direction) +{ + GdkEvent *event; + + event = gdk_event_new (GDK_SCROLL); + event->scroll.window = window; + event->scroll.time = get_event_time (nsevent); + /* FIXME event->x, event->y */ + /* FIXME event->state; */ + /* FIXME event->is_hint; */ + event->scroll.direction = direction; + event->scroll.device = _gdk_display->core_pointer; + /* FIXME: event->x_root, event->y_root */ + + return event; +} + +static GdkEvent * +create_key_event (GdkWindow *window, NSEvent *nsevent) +{ + GdkEventType event_type; + GdkEvent *event; + + switch ([nsevent type]) + { + case NSKeyDown: + event_type = GDK_KEY_PRESS; + break; + case NSKeyUp: + event_type = GDK_KEY_RELEASE; + break; + default: + g_assert_not_reached (); + } + + event = gdk_event_new (event_type); + event->key.window = window; + event->key.time = get_event_time (nsevent); + event->key.state = get_keyboard_modifiers_from_nsevent (nsevent); + event->key.hardware_keycode = [nsevent keyCode]; + event->key.group = ([nsevent modifierFlags] & NSAlternateKeyMask) ? 1 : 0; + + gdk_keymap_translate_keyboard_state (NULL, + event->key.hardware_keycode, + event->key.state, + event->key.group, + &event->key.keyval, + NULL, NULL, NULL); + + return event; +} + +static gboolean +gdk_event_translate (NSEvent *nsevent) +{ + NSWindow *nswindow = [nsevent window]; + GdkWindow *window; + GdkFilterReturn result; + GdkEvent *event; + int x, y; + + if (_gdk_default_filters) + { + /* Apply global filters */ + + GdkFilterReturn result = apply_filters (NULL, nsevent, _gdk_default_filters); + + /* If result is GDK_FILTER_CONTINUE, we continue as if nothing + * happened. If it is GDK_FILTER_REMOVE, + * we return TRUE and won't send the message to Quartz. + */ + if (result == GDK_FILTER_REMOVE) + return TRUE; + } + + window = find_window_for_event (nsevent, &x, &y); + + if (!window) + return FALSE; + + result = apply_filters (window, nsevent, ((GdkWindowObject *) window)->filters); + + if (result == GDK_FILTER_REMOVE) + return TRUE; + + switch ([nsevent type]) + { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + /* Emulate implicit grab */ + if (!pointer_grab_window) + { + pointer_grab_internal (window, FALSE, GDK_WINDOW_OBJECT (window)->event_mask, + NULL, NULL, TRUE); + } + + event = create_button_event (window, nsevent, x, y); + append_event (event); + + _gdk_event_button_generate (_gdk_display, event); + break; + + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + event = create_button_event (window, nsevent, x, y); + + append_event (event); + + _gdk_event_button_generate (_gdk_display, event); + + /* Ungrab implicit grab */ + if (pointer_grab_window && + pointer_grab_implicit) + pointer_ungrab_internal (TRUE); + break; + + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + case NSMouseMoved: + event = create_motion_event (window, nsevent, x, y); + append_event (event); + break; + + case NSScrollWheel: + { + float dx = [nsevent deltaX]; + float dy = [nsevent deltaY]; + GdkScrollDirection direction; + + /* The delta is how much the mouse wheel has moved. Since there's no such thing in GTK+ + * we accomodate by sending a different number of scroll wheel events. + */ + + /* First do y events */ + if (dy < 0.0) + { + dy = -dy; + direction = GDK_SCROLL_DOWN; + } + else + direction = GDK_SCROLL_UP; + + while (dy > 0.0) + { + event = create_scroll_event (window, nsevent, direction); + append_event (event); + dy--; + } + + /* Now do x events */ + if (dx < 0.0) + { + dx = -dx; + direction = GDK_SCROLL_RIGHT; + } + else + direction = GDK_SCROLL_LEFT; + + while (dx > 0.0) + { + event = create_scroll_event (window, nsevent, direction); + append_event (event); + dx--; + } + + break; + } + case NSKeyDown: + case NSKeyUp: + event = create_key_event (window, nsevent); + append_event (event); + return TRUE; + break; + + default: + NSLog(@"Untranslated: %@", nsevent); + } + + return FALSE; +} + +void +_gdk_events_queue (GdkDisplay *display) +{ + if (current_event) + { + + if (!gdk_event_translate (current_event)) + { + [NSApp sendEvent:current_event]; + } + + [current_event release]; + current_event = NULL; + } +} + +void +gdk_flush (void) +{ + gdk_display_flush (NULL); +} + +void +gdk_display_sync (GdkDisplay *display) +{ + /* FIXME: Implement */ +} + +void +gdk_display_flush (GdkDisplay *display) +{ + /* FIXME: Implement */ +} + +gboolean +gdk_event_send_client_message_for_display (GdkDisplay *display, + GdkEvent *event, + GdkNativeWindow winid) +{ + return FALSE; +} + +void +gdk_screen_broadcast_client_message (GdkScreen *screen, + GdkEvent *event) +{ +} + +gboolean +gdk_screen_get_setting (GdkScreen *screen, + const gchar *name, + GValue *value) +{ + if (strcmp (name, "gtk-font-name") == 0) + { + /* FIXME: This should be fetched from the correct preference value */ + g_value_set_string (value, "Lucida Grande 13"); + return TRUE; + } + + /* FIXME: Add more settings */ + + return FALSE; +} + diff --git a/gdk/quartz/gdkfont-quartz.c b/gdk/quartz/gdkfont-quartz.c new file mode 100644 index 000000000..e179bd4c7 --- /dev/null +++ b/gdk/quartz/gdkfont-quartz.c @@ -0,0 +1,114 @@ +/* gdkwindow-quartz.c + * + * Copyright (C) 2005 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 "gdkfont.h" + +GdkFont* +gdk_font_load_for_display (GdkDisplay *display, + const gchar *font_name) +{ + /* FIXME: Implement */ + return NULL; +} + +GdkFont* +gdk_font_from_description_for_display (GdkDisplay *display, + PangoFontDescription *desc) +{ + /* FIXME: Implement */ + return NULL; +} + +gint +gdk_text_width (GdkFont *font, + const gchar *text, + gint text_length) +{ + /* FIXME: Implement */ + return -1; +} + +void +gdk_text_extents (GdkFont *font, + const gchar *text, + gint text_length, + gint *lbearing, + gint *rbearing, + gint *width, + gint *ascent, + gint *descent) +{ + /* FIXME: Implement */ +} + +gint +gdk_text_width_wc (GdkFont *font, + const GdkWChar *text, + gint text_length) +{ + /* FIXME: Implement */ + return 0; +} + + +void +gdk_text_extents_wc (GdkFont *font, + const GdkWChar *text, + gint text_length, + gint *lbearing, + gint *rbearing, + gint *width, + gint *ascent, + gint *descent) +{ + /* FIXME: Implement */ +} + +void +_gdk_font_destroy (GdkFont *font) +{ + /* FIXME: Implement */ +} + +gint +_gdk_font_strlen (GdkFont *font, + const gchar *str) +{ + /* FIXME: Implement */ + return -1; +} + +gint +gdk_font_id (const GdkFont *font) +{ + /* FIXME: Implement */ + return 0; +} + +gboolean +gdk_font_equal (const GdkFont *fonta, + const GdkFont *fontb) +{ + /* FIXME: Implement */ + return FALSE; +} diff --git a/gdk/quartz/gdkgc-quartz.c b/gdk/quartz/gdkgc-quartz.c new file mode 100644 index 000000000..c68e3bab2 --- /dev/null +++ b/gdk/quartz/gdkgc-quartz.c @@ -0,0 +1,216 @@ +/* gdkgc-quartz.c + * + * Copyright (C) 2005 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 "gdkgc.h" +#include "gdkprivate-quartz.h" + +static gpointer parent_class = NULL; + +static void +gdk_quartz_gc_get_values (GdkGC *gc, + GdkGCValues *values) +{ + /* FIXME: Implement */ +} + +static void +gdk_quartz_gc_set_values (GdkGC *gc, + GdkGCValues *values, + GdkGCValuesMask mask) +{ + GdkGCQuartz *private = GDK_GC_QUARTZ (gc); + + private->values_mask |= mask; + + if (mask & GDK_GC_CLIP_MASK) + { + private->have_clip_region = FALSE; + private->have_clip_mask = values->clip_mask != NULL; + if (private->clip_mask) + CGImageRelease (private->clip_mask); + + if (values->clip_mask) + private->clip_mask = CGImageCreateCopy (GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (values->clip_mask)->impl)->image); + else + private->clip_mask = NULL; + } +} + +static void +gdk_quartz_gc_set_dashes (GdkGC *gc, + gint dash_offset, + gint8 dash_list[], + gint n) +{ + /* FIXME: Implement */ +} + +static void +gdk_gc_quartz_finalize (GObject *object) +{ + GdkGCQuartz *private = GDK_GC_QUARTZ (object); + + if (private->clip_mask) + CGImageRelease (private->clip_mask); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gdk_gc_quartz_class_init (GdkGCQuartzClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkGCClass *gc_class = GDK_GC_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_gc_quartz_finalize; + + gc_class->get_values = gdk_quartz_gc_get_values; + gc_class->set_values = gdk_quartz_gc_set_values; + gc_class->set_dashes = gdk_quartz_gc_set_dashes; +} + +GType +_gdk_gc_quartz_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkGCQuartzClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_gc_quartz_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkGCQuartz), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_GC, + "GdkGCQuartz", + &object_info, 0); + } + + return object_type; +} + +GdkGC * +_gdk_quartz_gc_new (GdkDrawable *drawable, + GdkGCValues *values, + GdkGCValuesMask values_mask) +{ + GdkGC *gc; + + gc = g_object_new (GDK_TYPE_GC_QUARTZ, NULL); + + _gdk_gc_init (gc, drawable, values, values_mask); + + gdk_quartz_gc_set_values (gc, values, values_mask); + + return gc; +} + +void +_gdk_windowing_gc_set_clip_region (GdkGC *gc, + GdkRegion *region) +{ + GdkGCQuartz *private = GDK_GC_QUARTZ (gc); + + if ((private->have_clip_region && ! region) || private->have_clip_mask) + { + if (private->clip_mask) + { + CGImageRelease (private->clip_mask); + private->clip_mask = NULL; + } + private->have_clip_mask = FALSE; + } + + private->have_clip_region = region != NULL; + + gc->clip_x_origin = 0; + gc->clip_y_origin = 0; +} + +void +_gdk_windowing_gc_copy (GdkGC *dst_gc, + GdkGC *src_gc) +{ + /* FIXME: Implement */ +} + +void +_gdk_quartz_update_context_from_gc (CGContextRef context, GdkGC *gc) +{ + GdkGCQuartz *private; + + if (gc == NULL) + return; + + private = GDK_GC_QUARTZ (gc); + + if (private->have_clip_region) + { + CGRect rect; + CGRect *cg_rects; + GdkRectangle *rects; + gint n_rects, i; + + gdk_region_get_rectangles (_gdk_gc_get_clip_region (gc), + &rects, &n_rects); + + if (n_rects == 1) + cg_rects = ▭ + else + cg_rects = g_new (CGRect, n_rects); + + for (i = 0; i < n_rects; i++) + { + cg_rects[i].origin.x = rects[i].x + gc->clip_x_origin; + cg_rects[i].origin.y = rects[i].y + gc->clip_y_origin; + cg_rects[i].size.width = rects[i].width; + cg_rects[i].size.height = rects[i].height; + } + + CGContextClipToRects (context, cg_rects, n_rects); + + g_free (rects); + if (cg_rects != &rect) + g_free (cg_rects); + } + else if (private->have_clip_mask && private->clip_mask) + { + /* FIXME: This is 10.4 only. For lower versions, we need to transform the + * mask into a region. + */ + CGContextClipToMask (context, + CGRectMake(gc->clip_x_origin, gc->clip_y_origin, + CGImageGetWidth (private->clip_mask), + CGImageGetHeight (private->clip_mask)), + private->clip_mask); + } +} diff --git a/gdk/quartz/gdkgeometry-quartz.c b/gdk/quartz/gdkgeometry-quartz.c new file mode 100644 index 000000000..b7ad4c95b --- /dev/null +++ b/gdk/quartz/gdkgeometry-quartz.c @@ -0,0 +1,34 @@ +/* gdkgeometry-quartz.c + * + * Copyright (C) 2005 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 "gdkprivate-quartz.h" + +void +gdk_window_scroll (GdkWindow *window, + gint dx, + gint dy) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + diff --git a/gdk/quartz/gdkglobals-quartz.c b/gdk/quartz/gdkglobals-quartz.c new file mode 100644 index 000000000..d60485604 --- /dev/null +++ b/gdk/quartz/gdkglobals-quartz.c @@ -0,0 +1,27 @@ +/* gdkglobals-quartz.c + * + * Copyright (C) 2005 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 "gdktypes.h" +#include "gdkprivate.h" + +GdkDisplay *_gdk_display = NULL; +GdkScreen *_gdk_screen = NULL; +GdkWindow *_gdk_root = NULL; diff --git a/gdk/quartz/gdkim-quartz.c b/gdk/quartz/gdkim-quartz.c new file mode 100644 index 000000000..37bd5f777 --- /dev/null +++ b/gdk/quartz/gdkim-quartz.c @@ -0,0 +1,73 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <config.h> + +#include <locale.h> + +#include "gdki18n.h" +#include "gdkinternals.h" +#include "gdkprivate-quartz.h" + +gchar* +gdk_set_locale (void) +{ + if (!setlocale (LC_ALL,"")) + g_warning ("locale not supported by C library"); + + return setlocale (LC_ALL, NULL); +} + +gchar * +gdk_wcstombs (const GdkWChar *src) +{ + gchar *mbstr; + + gint length = 0; + gint i; + + while (src[length] != 0) + length++; + + mbstr = g_new (gchar, length + 1); + + for (i = 0; i < length + 1; i++) + mbstr[i] = src[i]; + + return mbstr; +} + +gint +gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max) +{ + gint i; + + for (i = 0; i < dest_max && src[i]; i++) + dest[i] = src[i]; + + return i; +} + diff --git a/gdk/quartz/gdkimage-quartz.c b/gdk/quartz/gdkimage-quartz.c new file mode 100644 index 000000000..ca4d654ca --- /dev/null +++ b/gdk/quartz/gdkimage-quartz.c @@ -0,0 +1,176 @@ +/* gdkimage-quartz.c + * + * Copyright (C) 2005 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 "gdk.h" +#include "gdkimage.h" +#include "gdkprivate-quartz.h" + +static GObjectClass *parent_class; + +GdkImage * +_gdk_quartz_copy_to_image (GdkDrawable *drawable, + GdkImage *image, + gint src_x, + gint src_y, + gint dest_x, + gint dest_y, + gint width, + gint height) +{ + /* FIXME: Implement */ + return NULL; +} + +static void +gdk_image_finalize (GObject *object) +{ + GdkImage *image = GDK_IMAGE (object); + + g_free (image->mem); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gdk_image_class_init (GdkImageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_image_finalize; +} + +GType +gdk_image_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkImageClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_image_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkImage), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkImage", + &object_info, + 0); + } + + return object_type; +} + +GdkImage * +gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint width, gint height) +{ + /* We don't implement this function because it's broken, deprecated and + * tricky to implement. */ + g_warning ("This function is unimplemented"); + + return NULL; +} + +GdkImage* +_gdk_image_new_for_depth (GdkScreen *screen, + GdkImageType type, + GdkVisual *visual, + gint width, + gint height, + gint depth) +{ + GdkImage *image; + + if (visual) + depth = visual->depth; + + g_assert (depth == 24 || depth == 32); + + image = g_object_new (gdk_image_get_type (), NULL); + image->type = type; + image->visual = visual; + image->width = width; + image->height = height; + image->depth = depth; + + image->byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? GDK_LSB_FIRST : GDK_MSB_FIRST; + + /* We only support images with bpp 4 */ + image->bpp = 4; + image->bpl = image->width * image->bpp; + image->bits_per_pixel = image->bpp * 8; + + image->mem = g_malloc (image->bpl * image->height); + memset (image->mem, 0x00, image->bpl * image->height); + + return image; +} + +guint32 +gdk_image_get_pixel (GdkImage *image, + gint x, + gint y) +{ + guchar *ptr; + + g_return_val_if_fail (image != NULL, 0); + g_return_val_if_fail (x >= 0 && x < image->width, 0); + g_return_val_if_fail (y >= 0 && y < image->height, 0); + + ptr = image->mem + y * image->bpl + x * image->bpp; + + return *(guint32 *)ptr; +} + +void +gdk_image_put_pixel (GdkImage *image, + gint x, + gint y, + guint32 pixel) +{ + guchar *ptr; + + ptr = image->mem + y * image->bpl + x * image->bpp; + + *(guint32 *)ptr = pixel; +} + +gint +_gdk_windowing_get_bits_for_depth (GdkDisplay *display, + gint depth) +{ + if (depth == 24 || depth == 32) + return 32; + else + g_assert_not_reached (); + + return 0; +} diff --git a/gdk/quartz/gdkinput-old.c b/gdk/quartz/gdkinput-old.c new file mode 100644 index 000000000..d3b79d71c --- /dev/null +++ b/gdk/quartz/gdkinput-old.c @@ -0,0 +1,68 @@ +/* gdkinput.c + * + * Copyright (C) 2005 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 "gdkinput.h" + +GType +gdk_device_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkDeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkDevicePrivate), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkDevice", + &object_info, 0); + } + + return object_type; +} + +void +gdk_device_set_key (GdkDevice *device, + guint index, + guint keyval, + GdkModifierType modifiers) +{ + /* FIXME: Implement */ +} + +gboolean +gdk_device_get_axis (GdkDevice *device, gdouble *axes, GdkAxisUse use, gdouble *value) +{ + /* FIXME: Implement */ + return FALSE; +} + diff --git a/gdk/quartz/gdkinput.c b/gdk/quartz/gdkinput.c new file mode 100644 index 000000000..7615fbe94 --- /dev/null +++ b/gdk/quartz/gdkinput.c @@ -0,0 +1,387 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <config.h> +#include <stdlib.h> + +#include "gdkprivate-quartz.h" +#include "gdkinput.h" +#include "gdkprivate.h" +#include "gdkinputprivate.h" + +static GdkDeviceAxis gdk_input_core_axes[] = { + { GDK_AXIS_X, 0, 0 }, + { GDK_AXIS_Y, 0, 0 } +}; + +GdkDevice *_gdk_core_pointer = NULL; + +/* Global variables */ + +gchar *_gdk_input_gxid_host; +gint _gdk_input_gxid_port; +gint _gdk_input_ignore_core; +GList *_gdk_input_windows; +GList *_gdk_input_devices; + +void +_gdk_init_input_core (void) +{ + _gdk_core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL); + + _gdk_core_pointer->name = "Core Pointer"; + _gdk_core_pointer->source = GDK_SOURCE_MOUSE; + _gdk_core_pointer->mode = GDK_MODE_SCREEN; + _gdk_core_pointer->has_cursor = TRUE; + _gdk_core_pointer->num_axes = 2; + _gdk_core_pointer->axes = gdk_input_core_axes; + _gdk_core_pointer->num_keys = 0; + _gdk_core_pointer->keys = NULL; + + _gdk_display->core_pointer = _gdk_core_pointer; +} + +static void +gdk_device_finalize (GObject *object) +{ + g_error ("A GdkDevice object was finalized. This should not happen"); +} + +static void +gdk_device_class_init (GObjectClass *class) +{ + class->finalize = gdk_device_finalize; +} + +GType +gdk_device_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkDeviceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_device_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkDevicePrivate), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkDevice", + &object_info, 0); + } + + return object_type; +} + +GList * +gdk_devices_list (void) +{ + return _gdk_input_devices; +} + +GList * +gdk_display_list_devices (GdkDisplay *dpy) +{ + return _gdk_input_devices; +} + +void +gdk_device_set_source (GdkDevice *device, + GdkInputSource source) +{ + device->source = source; +} + + +void +gdk_device_set_key (GdkDevice *device, + guint index, + guint keyval, + GdkModifierType modifiers) +{ + g_return_if_fail (device != NULL); + g_return_if_fail (index < device->num_keys); + + device->keys[index].keyval = keyval; + device->keys[index].modifiers = modifiers; +} + +void +gdk_device_set_axis_use (GdkDevice *device, + guint index, + GdkAxisUse use) +{ + g_return_if_fail (device != NULL); + g_return_if_fail (index < device->num_axes); + + device->axes[index].use = use; + + switch (use) + { + case GDK_AXIS_X: + case GDK_AXIS_Y: + device->axes[index].min = 0.; + device->axes[index].max = 0.; + break; + case GDK_AXIS_XTILT: + case GDK_AXIS_YTILT: + device->axes[index].min = -1.; + device->axes[index].max = 1; + break; + default: + device->axes[index].min = 0.; + device->axes[index].max = 1; + break; + } +} + +void +gdk_device_get_state (GdkDevice *device, + GdkWindow *window, + gdouble *axes, + GdkModifierType *mask) +{ + gint x_int, y_int; + + g_assert (device == _gdk_core_pointer); + + gdk_window_get_pointer (window, &x_int, &y_int, mask); + + if (axes) + { + axes[0] = x_int; + axes[1] = y_int; + } +} + +void +gdk_device_free_history (GdkTimeCoord **events, + gint n_events) +{ + gint i; + + for (i = 0; i < n_events; i++) + g_free (events[i]); + + g_free (events); +} + +gboolean +gdk_device_get_history (GdkDevice *device, + GdkWindow *window, + guint32 start, + guint32 stop, + GdkTimeCoord ***events, + gint *n_events) +{ + g_return_val_if_fail (window != NULL, FALSE); + g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + g_return_val_if_fail (events != NULL, FALSE); + g_return_val_if_fail (n_events != NULL, FALSE); + + *n_events = 0; + *events = NULL; + return FALSE; +} + +gboolean +gdk_device_set_mode (GdkDevice *device, + GdkInputMode mode) +{ + return FALSE; +} + +gint +_gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev) +{ + return TRUE; +} + +gint +_gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev) +{ + return TRUE; +} + + +GdkInputWindow * +_gdk_input_window_find(GdkWindow *window) +{ + GList *tmp_list; + + for (tmp_list=_gdk_input_windows; tmp_list; tmp_list=tmp_list->next) + if (((GdkInputWindow *)(tmp_list->data))->window == window) + return (GdkInputWindow *)(tmp_list->data); + + return NULL; /* Not found */ +} + +/* FIXME: this routine currently needs to be called between creation + and the corresponding configure event (because it doesn't get the + root_relative_geometry). This should work with + gtk_window_set_extension_events, but will likely fail in other + cases */ + +void +gdk_input_set_extension_events (GdkWindow *window, gint mask, + GdkExtensionMode mode) +{ + GdkWindowObject *window_private; + GList *tmp_list; + GdkInputWindow *iw; + + g_return_if_fail (window != NULL); + g_return_if_fail (GDK_IS_WINDOW (window)); + + window_private = (GdkWindowObject*) window; + + if (mode == GDK_EXTENSION_EVENTS_NONE) + mask = 0; + + if (mask != 0) + { + iw = g_new(GdkInputWindow,1); + + iw->window = window; + iw->mode = mode; + + iw->obscuring = NULL; + iw->num_obscuring = 0; + iw->grabbed = FALSE; + + _gdk_input_windows = g_list_append (_gdk_input_windows,iw); + window_private->extension_events = mask; + + /* Add enter window events to the event mask */ + /* FIXME, this is not needed for XINPUT_NONE */ + gdk_window_set_events (window, + gdk_window_get_events (window) | + GDK_ENTER_NOTIFY_MASK); + } + else + { + iw = _gdk_input_window_find (window); + if (iw) + { + _gdk_input_windows = g_list_remove (_gdk_input_windows,iw); + g_free (iw); + } + + window_private->extension_events = 0; + } + + for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next) + { + GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data); + + if (gdkdev != (GdkDevicePrivate *)_gdk_core_pointer) + { + if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED + && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL)) + _gdk_input_enable_window (window,gdkdev); + else + _gdk_input_disable_window (window,gdkdev); + } + } +} + +void +_gdk_input_window_destroy (GdkWindow *window) +{ + GdkInputWindow *input_window; + + input_window = _gdk_input_window_find (window); + g_return_if_fail (input_window != NULL); + + _gdk_input_windows = g_list_remove (_gdk_input_windows,input_window); + g_free (input_window); +} + +void +_gdk_input_init (void) +{ + _gdk_init_input_core (); + _gdk_input_devices = g_list_append (NULL, _gdk_core_pointer); + _gdk_input_ignore_core = FALSE; +} + +void +_gdk_input_exit (void) +{ + GList *tmp_list; + GdkDevicePrivate *gdkdev; + + for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next) + { + gdkdev = (GdkDevicePrivate *)(tmp_list->data); + if (gdkdev != (GdkDevicePrivate *)_gdk_core_pointer) + { + gdk_device_set_mode ((GdkDevice *)gdkdev, GDK_MODE_DISABLED); + + g_free (gdkdev->info.name); + g_free (gdkdev->info.axes); + g_free (gdkdev->info.keys); + g_free (gdkdev); + } + } + + g_list_free (_gdk_input_devices); + + for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) + { + g_free (tmp_list->data); + } + g_list_free (_gdk_input_windows); +} + +gboolean +gdk_device_get_axis (GdkDevice *device, gdouble *axes, GdkAxisUse use, gdouble *value) +{ + gint i; + + g_return_val_if_fail (device != NULL, FALSE); + + if (axes == NULL) + return FALSE; + + for (i = 0; i < device->num_axes; i++) + if (device->axes[i].use == use) + { + if (value) + *value = axes[i]; + return TRUE; + } + + return FALSE; +} diff --git a/gdk/quartz/gdkinputprivate.h b/gdk/quartz/gdkinputprivate.h new file mode 100644 index 000000000..8dbfa0b68 --- /dev/null +++ b/gdk/quartz/gdkinputprivate.h @@ -0,0 +1,153 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GDK_INPUTPRIVATE_H__ +#define __GDK_INPUTPRIVATE_H__ + +#include "config.h" +#include "gdkinput.h" +#include "gdkevents.h" +#include "gdkquartz.h" + +typedef struct _GdkAxisInfo GdkAxisInfo; +typedef struct _GdkInputVTable GdkInputVTable; +typedef struct _GdkDevicePrivate GdkDevicePrivate; +typedef struct _GdkInputWindow GdkInputWindow; + +struct _GdkInputVTable { + gint (*set_mode) (guint32 deviceid, GdkInputMode mode); + void (*set_axes) (guint32 deviceid, GdkAxisUse *axes); + void (*set_key) (guint32 deviceid, + guint index, + guint keyval, + GdkModifierType modifiers); + + GdkTimeCoord* (*motion_events) (GdkWindow *window, + guint32 deviceid, + guint32 start, + guint32 stop, + gint *nevents_return); + void (*get_pointer) (GdkWindow *window, + guint32 deviceid, + gdouble *x, + gdouble *y, + gdouble *pressure, + gdouble *xtilt, + gdouble *ytilt, + GdkModifierType *mask); + gint (*grab_pointer) (GdkWindow * window, + gint owner_events, + GdkEventMask event_mask, + GdkWindow * confine_to, + guint32 time); + void (*ungrab_pointer) (guint32 time); + + void (*configure_event) (GdkEventConfigure *event, GdkWindow *window); + void (*enter_event) (GdkEventCrossing *event, GdkWindow *window); + gint (*other_event) (GdkEvent *event, GdkWindow *window); + /* Handle an unidentified event. Returns TRUE if handled, FALSE + otherwise */ + gint (*window_none_event) (GdkEvent *event); + gint (*enable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev); + gint (*disable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev); +}; + +/* information about a device axis */ +struct _GdkAxisInfo +{ + /* reported x resolution */ + gint xresolution; + + /* reported x minimum/maximum values */ + gint xmin_value, xmax_value; + + /* calibrated resolution (for aspect ration) - only relative values + between axes used */ + gint resolution; + + /* calibrated minimum/maximum values */ + gint min_value, max_value; +}; + +#define GDK_INPUT_NUM_EVENTC 6 + +struct _GdkDevicePrivate { + GdkDevice info; +}; + +struct _GdkDeviceClass +{ + GObjectClass parent_class; +}; + +struct _GdkInputWindow +{ + /* gdk window */ + GdkWindow *window; + + /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */ + GdkExtensionMode mode; + + /* position relative to root window */ + gint root_x; + gint root_y; + + /* rectangles relative to window of windows obscuring this one */ + GdkRectangle *obscuring; + gint num_obscuring; + + /* Is there a pointer grab for this window ? */ + gint grabbed; +}; + +/* Global data */ + +extern const GdkDevice gdk_input_core_info; +extern GdkDevice *_gdk_core_pointer; +extern GList *_gdk_input_devices; +extern GList *_gdk_input_windows; + +extern GdkInputVTable gdk_input_vtable; +/* information about network port and host for gxid daemon */ +extern gchar *_gdk_input_gxid_host; +extern gint _gdk_input_gxid_port; +extern gint _gdk_input_ignore_core; + +/* Function declarations */ + +GdkInputWindow * _gdk_input_window_find (GdkWindow *window); +void _gdk_input_window_destroy (GdkWindow *window); +void _gdk_input_init (void); +void _gdk_input_exit (void); +gint _gdk_input_enable_window (GdkWindow *window, + GdkDevicePrivate *gdkdev); +gint _gdk_input_disable_window (GdkWindow *window, + GdkDevicePrivate *gdkdev); +void _gdk_init_input_core (void); + +void _gdk_input_exit (void); + +#endif /* __GDK_INPUTPRIVATE_H__ */ diff --git a/gdk/quartz/gdkkeys-quartz.c b/gdk/quartz/gdkkeys-quartz.c new file mode 100644 index 000000000..55ff3d407 --- /dev/null +++ b/gdk/quartz/gdkkeys-quartz.c @@ -0,0 +1,487 @@ +/* gdkkeys-quartz.c + * + * Copyright (C) 2000 Red Hat, Inc. + * Copyright (C) 2005 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. + */ +/* Some parts of this code come from quartzKeyboard.c, + * from the Apple X11 Server. + * + * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above + * copyright holders shall not be used in advertising or otherwise to + * promote the sale, use or other dealings in this Software without + * prior written authorization. + */ + +#include <config.h> + +#include <Carbon/Carbon.h> +#include "gdk.h" +#include "gdkkeysyms.h" + +#define NUM_KEYCODES 128 +#define KEYVALS_PER_KEYCODE 4 + +static GdkKeymap *default_keymap = NULL; + +static KeyboardLayoutRef current_layout = NULL; + +/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries. + * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt); + */ +static guint *keyval_array = NULL; + +static inline UniChar +macroman2ucs (unsigned char c) +{ + /* Precalculated table mapping MacRoman-128 to Unicode. Generated + by creating single element CFStringRefs then extracting the + first character. */ + + static const unsigned short table[128] = { + 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, + 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, + 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, + 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, + 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf, + 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8, + 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211, + 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8, + 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab, + 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153, + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca, + 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, + 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1, + 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, + 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc, + 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7, + }; + + if (c < 128) + return c; + else + return table[c - 128]; +} + +const static struct { + guint keycode; + guint keyval; +} known_keys[] = { + { 55, GDK_Meta_L }, + { 56, GDK_Shift_L }, + { 57, GDK_Caps_Lock }, + { 58, GDK_Alt_L }, + { 59, GDK_Control_L }, + { 60, GDK_Shift_R }, + { 61, GDK_Alt_R }, + { 62, GDK_Control_R }, + { 122, GDK_F1 }, + { 120, GDK_F2 }, + { 99, GDK_F3 }, + { 118, GDK_F4 }, + { 96, GDK_F5 }, + { 97, GDK_F6 }, + { 98, GDK_F7 }, + { 100, GDK_F8 }, + { 101, GDK_F9 }, + { 109, GDK_F10 }, + { 103, GDK_F11 }, + { 111, GDK_F12 }, + { 105, GDK_F13 }, + { 107, GDK_F14 }, + { 113, GDK_F15 }, +}; + +const static struct { + guint keycode; + guint normal_keyval, keypad_keyval; +} known_numeric_keys[] = { + { 65, GDK_period, GDK_KP_Decimal }, + { 67, GDK_asterisk, GDK_KP_Multiply }, + { 69, GDK_plus, GDK_KP_Add }, + { 75, GDK_slash, GDK_KP_Divide }, + { 76, 0x01000003, GDK_KP_Enter }, + { 78, GDK_minus, GDK_KP_Subtract }, + { 81, GDK_equal, GDK_KP_Equal }, + { 82, GDK_0, GDK_KP_0 }, + { 83, GDK_1, GDK_KP_1 }, + { 84, GDK_2, GDK_KP_2 }, + { 85, GDK_3, GDK_KP_3 }, + { 86, GDK_4, GDK_KP_4 }, + { 87, GDK_5, GDK_KP_5 }, + { 88, GDK_6, GDK_KP_6 }, + { 89, GDK_7, GDK_KP_7 }, + { 91, GDK_8, GDK_KP_8 }, + { 92, GDK_9, GDK_KP_9 }, +}; + +/* These values aren't covered by gdk_unicode_to_keyval */ +const static struct { + gunichar ucs_value; + guint keyval; +} special_ucs_table [] = { + { 0x0001, GDK_Home }, + { 0x0008, GDK_BackSpace }, + { 0x0009, GDK_Tab }, + { 0x000d, GDK_Return }, + { 0x001c, GDK_Left }, + { 0x001d, GDK_Right }, + { 0x001e, GDK_Up }, + { 0x001f, GDK_Down }, +}; + +static void +maybe_update_keymap (void) +{ + KeyboardLayoutRef new_layout; + + KLGetCurrentKeyboardLayout (&new_layout); + + if (new_layout != current_layout) + { + guint *p; + int i; + + KeyboardLayoutKind layout_kind; + + g_free (keyval_array); + keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE); + + /* Get the layout kind */ + KLGetKeyboardLayoutProperty (new_layout, kKLKind, &layout_kind); + + /* FIXME: When we have UCHR support, I think that should be preffered + * if a keymap has both. + */ + if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLKCHRKind) + { + const void *chr_data; + + /* Get chr data */ + KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (void **)&chr_data); + + for (i = 0; i < NUM_KEYCODES; i++) + { + int j; + UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey|optionKey}; + + p = keyval_array + i * KEYVALS_PER_KEYCODE; + + for (j = 0; j < KEYVALS_PER_KEYCODE; j++) + { + UInt32 c, state = 0; + UInt16 key_code; + UniChar uc; + + key_code = modifiers[j]|i; + c = KeyTranslate (chr_data, key_code, &state); + + if (state != 0) + { + UInt32 state2 = 0; + c = KeyTranslate (chr_data, key_code | 128, &state2); + } + + if (c != 0 && c != 0x10) + { + guint keyval; + int k; + gboolean found = FALSE; + + uc = macroman2ucs (c); + + for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++) + { + if (special_ucs_table[k].ucs_value == uc) + { + p[j] = special_ucs_table[k].keyval; + found = TRUE; + break; + } + } + + if (!found) + p[j] = gdk_unicode_to_keyval (uc); + } + } + + if (p[3] == p[2]) + p[3] = 0; + if (p[2] == p[1]) + p[2] = 0; + if (p[1] == p[0]) + p[1] = 0; + if (p[0] == p[2] && + p[1] == p[3]) + p[2] = p[3] = 0; + } + } + else + { + g_error ("uchr type layouts aren't supported right now"); + } + + for (i = 0; i < G_N_ELEMENTS (known_keys); i++) + { + p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE; + + if (p[0] == 0 && p[1] == 0 && + p[2] == 0 && p[3] == 0) + p[0] = known_keys[i].keyval; + } + + for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++) + { + p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE; + + if (p[0] == known_numeric_keys[i].normal_keyval); + p[0] = known_numeric_keys[i].keypad_keyval; + } + + if (current_layout) + g_signal_emit_by_name (default_keymap, "keys_changed"); + + current_layout = new_layout; + } +} + +GdkKeymap * +gdk_keymap_get_for_display (GdkDisplay *display) +{ + g_return_val_if_fail (display == gdk_display_get_default (), NULL); + + if (default_keymap == NULL) + default_keymap = g_object_new (gdk_keymap_get_type (), NULL); + + return default_keymap; +} + +PangoDirection +gdk_keymap_get_direction (GdkKeymap *keymap) +{ + return PANGO_DIRECTION_NEUTRAL; +} + +gboolean +gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap, + guint keyval, + GdkKeymapKey **keys, + gint *n_keys) +{ + GArray *keys_array; + int i; + + g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (keys != NULL, FALSE); + g_return_val_if_fail (n_keys != NULL, FALSE); + g_return_val_if_fail (keyval != 0, FALSE); + + maybe_update_keymap (); + + *n_keys = 0; + keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); + + for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++) + { + GdkKeymapKey key; + + if (keyval_array[i] != keyval) + continue; + + (*n_keys)++; + + key.keycode = i / KEYVALS_PER_KEYCODE; + key.group = 0; + key.level = i % KEYVALS_PER_KEYCODE; + + g_array_append_val (keys_array, key); + } + + *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE); + + return *n_keys > 0;; +} + +gboolean +gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap, + guint hardware_keycode, + GdkKeymapKey **keys, + guint **keyvals, + gint *n_entries) +{ + GArray *keys_array, *keyvals_array; + int i; + guint *p; + + g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (n_entries != NULL, FALSE); + + maybe_update_keymap (); + + *n_entries = 0; + + if (hardware_keycode > NUM_KEYCODES) + return FALSE; + + if (keys) + keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); + else + keys_array = NULL; + + if (keyvals) + keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint)); + else + keyvals_array = NULL; + + p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE; + + for (i = 0; i < KEYVALS_PER_KEYCODE; i++) + { + if (!p[i]) + continue; + + (*n_entries)++; + + if (keyvals_array) + g_array_append_val (keyvals_array, p[i]); + + if (keys_array) + { + GdkKeymapKey key; + + key.keycode = hardware_keycode; + key.group = i / 2; + key.level = i % 2; + + g_array_append_val (keys_array, key); + } + } + + if (keys) + *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE); + + if (keyvals) + *keyvals = (guint *)g_array_free (keyvals_array, FALSE); + + return *n_entries > 0; +} + +#define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)]) + +static guint +translate_keysym (guint hardware_keycode, + gint group, + GdkModifierType state, + guint *effective_group, + guint *effective_level) +{ + gint level; + guint tmp_keyval; + + level = (state & GDK_SHIFT_MASK) ? 1 : 0; + + if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) && + (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1))) + group = 0; + + if (!GET_KEYVAL (hardware_keycode, group, level) && + GET_KEYVAL (hardware_keycode, group, 0)) + level = 0; + + tmp_keyval = GET_KEYVAL (hardware_keycode, group, level); + + if (state & GDK_LOCK_MASK) + { + guint upper = gdk_keyval_to_upper (tmp_keyval); + if (upper != tmp_keyval) + tmp_keyval = upper; + } + + return tmp_keyval; +} + +gboolean +gdk_keymap_translate_keyboard_state (GdkKeymap *keymap, + guint hardware_keycode, + GdkModifierType state, + gint group, + guint *keyval, + gint *effective_group, + gint *level, + GdkModifierType *consumed_modifiers) +{ + guint tmp_keyval; + GdkModifierType bit; + guint tmp_modifiers = 0; + + g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (group >= 0 && group <= 1, FALSE); + + maybe_update_keymap (); + + if (keyval) + *keyval = 0; + if (effective_group) + *effective_group = 0; + if (level) + *level = 0; + if (consumed_modifiers) + *consumed_modifiers = 0; + + if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES) + return FALSE; + + /* Check if shift or capslock modify the keyval */ + for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1) + { + if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) != + translate_keysym (hardware_keycode, group, state | bit, NULL, NULL)) + tmp_modifiers |= bit; + } + + tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group); + + if (consumed_modifiers) + *consumed_modifiers = tmp_modifiers; + + if (keyval) + *keyval = tmp_keyval; + + return TRUE; +} diff --git a/gdk/quartz/gdkmain-quartz.c b/gdk/quartz/gdkmain-quartz.c new file mode 100644 index 000000000..1c066ab89 --- /dev/null +++ b/gdk/quartz/gdkmain-quartz.c @@ -0,0 +1,78 @@ +/* gdkmain-quartz.c + * + * Copyright (C) 2005 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 "gdk.h" + +GOptionEntry _gdk_windowing_args[] = { + { NULL } +}; + +void +_gdk_windowing_init (void) +{ +} + +GdkGrabStatus +gdk_keyboard_grab (GdkWindow *window, + gint owner_events, + guint32 time) +{ + /* FIXME: Implement */ + + return GDK_GRAB_SUCCESS; +} + + +gboolean +gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display, + GdkWindow **grab_window, + gboolean *owner_events) +{ + /* FIXME: Implement */ + return FALSE; +} + +void +gdk_error_trap_push (void) +{ +} + +gint +gdk_error_trap_pop (void) +{ + return 0; +} + +void +gdk_notify_startup_complete (void) +{ + /* FIXME: Implement */ +} + + +void +_gdk_windowing_display_set_sm_client_id (GdkDisplay *display, + const gchar *sm_client_id) +{ +} + + diff --git a/gdk/quartz/gdkpixmap-quartz.c b/gdk/quartz/gdkpixmap-quartz.c new file mode 100644 index 000000000..b1297f770 --- /dev/null +++ b/gdk/quartz/gdkpixmap-quartz.c @@ -0,0 +1,232 @@ +/* gdkpixmap-quartz.c + * + * Copyright (C) 2005 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 "gdkpixmap.h" +#include "gdkprivate-quartz.h" + +static gpointer parent_class; + +static void +gdk_pixmap_impl_quartz_init (GdkPixmapImplQuartz *impl) +{ +} + +static void +gdk_pixmap_impl_quartz_get_size (GdkDrawable *drawable, + gint *width, + gint *height) +{ + if (width) + *width = GDK_PIXMAP_IMPL_QUARTZ (drawable)->width; + if (height) + *height = GDK_PIXMAP_IMPL_QUARTZ (drawable)->height; +} + +static void +gdk_pixmap_impl_quartz_finalize (GObject *object) +{ + GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (object); + + CGImageRelease (impl->image); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gdk_pixmap_impl_quartz_class_init (GdkPixmapImplQuartzClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_pixmap_impl_quartz_finalize; + + drawable_class->get_size = gdk_pixmap_impl_quartz_get_size; +} + +GType +_gdk_pixmap_impl_quartz_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkPixmapImplQuartzClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_pixmap_impl_quartz_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkPixmapImplQuartz), + 0, /* n_preallocs */ + (GInstanceInitFunc) gdk_pixmap_impl_quartz_init + }; + + object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ, + "GdkPixmapImplQuartz", + &object_info, + 0); + } + + return object_type; +} + +GType +_gdk_pixmap_impl_get_type (void) +{ + return _gdk_pixmap_impl_quartz_get_type (); +} + +static void +data_provider_release (void *info, const void *data, size_t size) +{ + g_free (info); +} + +GdkPixmap* +gdk_pixmap_new (GdkDrawable *drawable, + gint width, + gint height, + gint depth) +{ + GdkPixmap *pixmap; + GdkDrawableImplQuartz *draw_impl; + GdkPixmapImplQuartz *pix_impl; + GdkColormap *cmap; + gint window_depth; + CGColorSpaceRef colorspace; + CGDataProviderRef data_provider; + CGImageAlphaInfo alpha_info; + gint bytes_per_row, bits_per_pixel; + + g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL); + g_return_val_if_fail ((width != 0) && (height != 0), NULL); + + if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)) + return NULL; + + if (!drawable) + drawable = gdk_screen_get_root_window (gdk_screen_get_default ()); + + window_depth = gdk_drawable_get_depth (GDK_DRAWABLE (drawable)); + + if (depth == -1) + depth = window_depth; + + switch (depth) + { + case 24: + alpha_info = kCGImageAlphaNoneSkipLast; + bytes_per_row = width * 4; + bits_per_pixel = 32; + colorspace = CGColorSpaceCreateDeviceRGB (); + break; + case 32: + alpha_info = kCGImageAlphaPremultipliedFirst; + bytes_per_row = width * 4; + bits_per_pixel = 32; + colorspace = CGColorSpaceCreateDeviceRGB (); + break; + case 1: + alpha_info = kCGImageAlphaNone; + bytes_per_row = width; + bits_per_pixel = 8; + colorspace = CGColorSpaceCreateDeviceGray (); + break; + default: + g_warning ("Unsupported bit depth %d\n", depth); + return NULL; + } + + pixmap = g_object_new (gdk_pixmap_get_type (), NULL); + draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl); + pix_impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl); + draw_impl->wrapper = GDK_DRAWABLE (pixmap); + + g_assert (depth == 24 || depth == 32 || depth == 1); + + pix_impl->data = g_malloc (height * bytes_per_row); + data_provider = CGDataProviderCreateWithData (pix_impl->data, pix_impl->data, + height * bytes_per_row, data_provider_release); + pix_impl->image = CGImageCreate (width, height, 8, bits_per_pixel, + bytes_per_row, colorspace, + alpha_info, + data_provider, NULL, FALSE, + kCGRenderingIntentDefault); + CGDataProviderRelease (data_provider); + CGColorSpaceRelease (colorspace); + + pix_impl->width = width; + pix_impl->height = height; + GDK_PIXMAP_OBJECT (pixmap)->depth = depth; + + if (depth == window_depth) { + GdkColormap *colormap = gdk_drawable_get_colormap (drawable); + + if (colormap) + gdk_drawable_set_colormap (pixmap, colormap); + } + + return pixmap; +} + +GdkPixmap * +gdk_bitmap_create_from_data (GdkDrawable *window, + const gchar *data, + gint width, + gint height) +{ + GdkPixmap *pixmap; + GdkPixmapImplQuartz *impl; + int x, y; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail ((width != 0) && (height != 0), NULL); + g_return_val_if_fail (window == NULL || GDK_IS_DRAWABLE (window), NULL); + + pixmap = gdk_pixmap_new (window, width, height, 1); + impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl); + + g_assert (CGImageGetBytesPerRow (impl->image) == width); + + for (y = 0; y < height; y++) + { + guchar *ptr = impl->data + y * width; + gint idx; + + for (x = 0; x < width; x++) + { + if ((data[(y * width + x) / 8] >> x % 8) & 1) + *ptr = 0xff; + else + *ptr = 0; + + ptr++; + } + } + + return pixmap; +} diff --git a/gdk/quartz/gdkpixmap-quartz.h b/gdk/quartz/gdkpixmap-quartz.h new file mode 100644 index 000000000..bb2122ad4 --- /dev/null +++ b/gdk/quartz/gdkpixmap-quartz.h @@ -0,0 +1,64 @@ +/* gdkdrawable-quartz.h + * + * Copyright (C) 2005 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. + */ + +#ifndef __GDK_PIXMAP_QUARTZ_H__ +#define __GDK_PIXMAP_QUARTZ_H__ + +#include <ApplicationServices/ApplicationServices.h> +#include <gdk/quartz/gdkdrawable-quartz.h> +#include <gdk/gdkpixmap.h> + +G_BEGIN_DECLS + +/* Pixmap implementation for Quartz + */ + +typedef struct _GdkPixmapImplQuartz GdkPixmapImplQuartz; +typedef struct _GdkPixmapImplQuartzClass GdkPixmapImplQuartzClass; + +#define GDK_TYPE_PIXMAP_IMPL_QUARTZ (_gdk_pixmap_impl_quartz_get_type ()) +#define GDK_PIXMAP_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXMAP_IMPL_QUARTZ, GdkPixmapImplQuartz)) +#define GDK_PIXMAP_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXMAP_IMPL_QUARTZ, GdkPixmapImplQuartzClass)) +#define GDK_IS_PIXMAP_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXMAP_IMPL_QUARTZ)) +#define GDK_IS_PIXMAP_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXMAP_IMPL_QUARTZ)) +#define GDK_PIXMAP_IMPL_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXMAP_IMPL_QUARTZ, GdkPixmapImplQuartzClass)) + +struct _GdkPixmapImplQuartz +{ + GdkDrawableImplQuartz parent_instance; + + gint width; + gint height; + + void *data; + + CGImageRef image; +}; + +struct _GdkPixmapImplQuartzClass +{ + GdkDrawableImplQuartzClass parent_class; +}; + +GType _gdk_pixmap_impl_quartz_get_type (void); + +G_END_DECLS + +#endif /* __GDK_PIXMAP_QUARTZ_H__ */ diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h new file mode 100644 index 000000000..181d3a5fa --- /dev/null +++ b/gdk/quartz/gdkprivate-quartz.h @@ -0,0 +1,113 @@ +/* gdkwindow-quartz.c + * + * Copyright (C) 2005 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. + */ + +#ifndef __GDK_PRIVATE_QUARTZ_H__ +#define __GDK_PRIVATE_QUARTZ_H__ + +#include <config.h> + +#define GDK_QUARTZ_ALLOC_POOL NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] +#define GDK_QUARTZ_RELEASE_POOL [pool release] + +#include <gdk/gdkprivate.h> +#include <gdk/quartz/gdkpixmap-quartz.h> +#include <gdk/quartz/gdkwindow-quartz.h> + +#include <gdk/gdk.h> + +#include "gdkinternals.h" + +#define GDK_TYPE_GC_QUARTZ (_gdk_gc_quartz_get_type ()) +#define GDK_GC_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_QUARTZ, GdkGCQuartz)) +#define GDK_GC_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GC_QUARTZ, GdkGCQuartzClass)) +#define GDK_IS_GC_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_GC_QUARTZ)) +#define GDK_IS_GC_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GC_QUARTZ)) +#define GDK_GC_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GC_QUARTZ, GdkGCQuartzClass)) + +typedef struct _GdkCursorPrivate GdkCursorPrivate; +typedef struct _GdkGCQuartz GdkGCQuartz; +typedef struct _GdkGCQuartzClass GdkGCQuartzClass; + +struct _GdkGCQuartz +{ + GdkGC parent_instance; + + GdkGCValuesMask values_mask; + + gboolean have_clip_region; + gboolean have_clip_mask; + CGImageRef clip_mask; +}; + +struct _GdkGCQuartzClass +{ + GdkGCClass parent_class; +}; + +struct _GdkVisualClass +{ + GObjectClass parent_class; +}; + +struct _GdkCursorPrivate +{ + GdkCursor cursor; + NSCursor *nscursor; +}; + +extern GdkDisplay *_gdk_display; +extern GdkScreen *_gdk_screen; +extern GdkWindow *_gdk_root; + +GType _gdk_gc_quartz_get_type (void); + +GdkGC *_gdk_quartz_gc_new (GdkDrawable *drawable, + GdkGCValues *values, + GdkGCValuesMask values_mask); + +/* Initialization */ +void _gdk_windowing_window_init (void); +void _gdk_events_init (void); +void _gdk_visual_init (void); + +void _gdk_quartz_set_context_fill_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel); +void _gdk_quartz_set_context_stroke_color_from_pixel (CGContextRef context, GdkColormap *colormap, guint32 pixel); + +void _gdk_quartz_update_context_from_gc (CGContextRef context, GdkGC *gc); + +void _gdk_quartz_update_focus_window (GdkWindow *new_window); + +gint _gdk_quartz_get_inverted_screen_y (gint y); + +GdkWindow *_gdk_quartz_get_mouse_window (void); +void _gdk_quartz_update_mouse_window (GdkWindow *window); + +void _gdk_quartz_update_cursor (GdkWindow *window); + +GdkImage *_gdk_quartz_copy_to_image (GdkDrawable *drawable, + GdkImage *image, + gint src_x, + gint src_y, + gint dest_x, + gint dest_y, + gint width, + gint height); + +#endif /* __GDK_PRIVATE_QUARTZ_H__ */ diff --git a/gdk/quartz/gdkproperty-quartz.c b/gdk/quartz/gdkproperty-quartz.c new file mode 100644 index 000000000..e0da15214 --- /dev/null +++ b/gdk/quartz/gdkproperty-quartz.c @@ -0,0 +1,85 @@ +/* gdkproperty-quartz.c + * + * Copyright (C) 2005 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 "gdkproperty.h" + +GdkAtom +gdk_atom_intern (const gchar *atom_name, + gboolean only_if_exists) +{ + g_return_val_if_fail (atom_name != NULL, GDK_NONE); + + /* FIXME: Implement */ + return GDK_NONE; +} + +GdkAtom +gdk_atom_intern_static_string (const gchar *atom_name) +{ + g_return_val_if_fail (atom_name != NULL, GDK_NONE); + + /* FIXME: Implement */ + return GDK_NONE; +} + + +gchar * +gdk_atom_name (GdkAtom atom) +{ + /* FIXME: Implement */ + return NULL; +} + +void +gdk_property_delete (GdkWindow *window, + GdkAtom property) +{ + /* FIXME: Implement */ +} + +gint +gdk_property_get (GdkWindow *window, + GdkAtom property, + GdkAtom type, + gulong offset, + gulong length, + gint pdelete, + GdkAtom *actual_property_type, + gint *actual_format_type, + gint *actual_length, + guchar **data) +{ + /* FIXME: Implement */ + return 0; +} + +void +gdk_property_change (GdkWindow *window, + GdkAtom property, + GdkAtom type, + gint format, + GdkPropMode mode, + const guchar *data, + gint nelements) +{ + /* FIXME: Implement */ +} diff --git a/gdk/quartz/gdkquartz.h b/gdk/quartz/gdkquartz.h new file mode 100644 index 000000000..d9cd548cd --- /dev/null +++ b/gdk/quartz/gdkquartz.h @@ -0,0 +1,7 @@ +#ifndef __GDK_QUARTZ_H__ +#define __GDK_QUARTZ_H__ + +#include <Quartz/Quartz.h> +#include "gdk/gdkprivate.h" + +#endif /* __GDK_QUARTZ_H__ */ diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c new file mode 100644 index 000000000..dbb82bce1 --- /dev/null +++ b/gdk/quartz/gdkscreen-quartz.c @@ -0,0 +1,196 @@ +/* gdkscreen-quartz.c + * + * Copyright (C) 2005 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 "gdk.h" +#include "gdkprivate-quartz.h" + +static GdkColormap *default_colormap = NULL; + +GdkDisplay * +gdk_screen_get_display (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return _gdk_display; +} + + +GdkWindow * +gdk_screen_get_root_window (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return _gdk_root; +} + +gint +gdk_screen_get_number (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return 0; +} + +gchar * +_gdk_windowing_substitute_screen_number (const gchar *display_name, + int screen_number) +{ + if (screen_number != 0) + return NULL; + + return g_strdup (display_name); +} + +GdkColormap* +gdk_screen_get_default_colormap (GdkScreen *screen) +{ + return default_colormap; +} + +void +gdk_screen_set_default_colormap (GdkScreen *screen, + GdkColormap *colormap) +{ + GdkColormap *old_colormap; + + g_return_if_fail (GDK_IS_SCREEN (screen)); + g_return_if_fail (GDK_IS_COLORMAP (colormap)); + + old_colormap = default_colormap; + + default_colormap = g_object_ref (colormap); + + if (old_colormap) + g_object_unref (old_colormap); +} + +gint +gdk_screen_get_width (GdkScreen *screen) +{ + int i; + int width; + NSArray *array; + NSAutoreleasePool *pool; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + pool = [[NSAutoreleasePool alloc] init]; + array = [NSScreen screens]; + + width = 0; + for (i = 0; i < [array count]; i++) + { + NSRect rect = [[array objectAtIndex:i] frame]; + width += rect.size.width; + } + + [pool release]; + + return width; +} + +gint +gdk_screen_get_height (GdkScreen *screen) +{ + int i; + int height; + NSArray *array; + NSAutoreleasePool *pool; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + pool = [[NSAutoreleasePool alloc] init]; + array = [NSScreen screens]; + + height = 0; + for (i = 0; i < [array count]; i++) + { + NSRect rect = [[array objectAtIndex:i] frame]; + height = MAX (height, rect.size.height); + } + + [pool release]; + + return height; +} + +gint +gdk_screen_get_width_mm (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + /* FIXME: Implement */ + return 0; +} + +gint +gdk_screen_get_height_mm (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + /* FIXME: Implement */ + return 0; +} + +int +gdk_screen_get_n_monitors (GdkScreen *screen) +{ + int n; + GDK_QUARTZ_ALLOC_POOL; + NSArray *array = [NSScreen screens]; + + n = [array count]; + + GDK_QUARTZ_RELEASE_POOL; + + return n; +} + +void +gdk_screen_get_monitor_geometry (GdkScreen *screen, + gint monitor_num, + GdkRectangle *dest) +{ + NSArray *array; + NSRect rect; + NSAutoreleasePool *pool; + + g_return_if_fail (GDK_IS_SCREEN (screen)); + g_return_if_fail (monitor_num < gdk_screen_get_n_monitors (screen)); + g_return_if_fail (monitor_num >= 0); + + pool = [[NSAutoreleasePool alloc] init]; + array = [NSScreen screens]; + rect = [[array objectAtIndex:monitor_num] frame]; + + dest->x = rect.origin.x; + dest->y = rect.origin.y; + dest->width = rect.size.width; + dest->height = rect.size.height; + + [pool release]; +} + +gchar * +gdk_screen_make_display_name (GdkScreen *screen) +{ + return g_strdup (gdk_display_get_name (_gdk_display)); +} diff --git a/gdk/quartz/gdkselection-quartz.c b/gdk/quartz/gdkselection-quartz.c new file mode 100644 index 000000000..375c36672 --- /dev/null +++ b/gdk/quartz/gdkselection-quartz.c @@ -0,0 +1,132 @@ +/* gdkselection-quartz.c + * + * Copyright (C) 2005 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 "gdkselection.h" + +gboolean +gdk_selection_owner_set_for_display (GdkDisplay *display, + GdkWindow *owner, + GdkAtom selection, + guint32 time, + gint send_event) +{ + /* FIXME: Implement */ + return TRUE; +} + +GdkWindow* +gdk_selection_owner_get_for_display (GdkDisplay *display, + GdkAtom selection) +{ + /* FIXME: Implement */ + return NULL; +} + +void +gdk_selection_convert (GdkWindow *requestor, + GdkAtom selection, + GdkAtom target, + guint32 time) +{ + /* FIXME: Implement */ +} + +gint +gdk_selection_property_get (GdkWindow *requestor, + guchar **data, + GdkAtom *ret_type, + gint *ret_format) +{ + /* FIXME: Implement */ + return 0; +} + +void +gdk_selection_send_notify_for_display (GdkDisplay *display, + guint32 requestor, + GdkAtom selection, + GdkAtom target, + GdkAtom property, + guint32 time) +{ + /* FIXME: Implement */ +} + +gint +gdk_text_property_to_text_list_for_display (GdkDisplay *display, + GdkAtom encoding, + gint format, + const guchar *text, + gint length, + gchar ***list) +{ + /* FIXME: Implement */ + return 0; +} + +gint +gdk_string_to_compound_text_for_display (GdkDisplay *display, + const gchar *str, + GdkAtom *encoding, + gint *format, + guchar **ctext, + gint *length) +{ + /* FIXME: Implement */ + return 0; +} + +void gdk_free_compound_text (guchar *ctext) +{ + /* FIXME: Implement */ +} + +gchar * +gdk_utf8_to_string_target (const gchar *str) +{ + /* FIXME: Implement */ + return NULL; +} + +gboolean +gdk_utf8_to_compound_text_for_display (GdkDisplay *display, + const gchar *str, + GdkAtom *encoding, + gint *format, + guchar **ctext, + gint *length) +{ + /* FIXME: Implement */ + return 0; +} + +gint +gdk_text_property_to_utf8_list_for_display (GdkDisplay *display, + GdkAtom encoding, + gint format, + const guchar *text, + gint length, + gchar ***list) +{ + /* FIXME: Implement */ + return 0; +} diff --git a/gdk/quartz/gdkvisual-quartz.c b/gdk/quartz/gdkvisual-quartz.c new file mode 100644 index 000000000..1dd068e2e --- /dev/null +++ b/gdk/quartz/gdkvisual-quartz.c @@ -0,0 +1,219 @@ +/* gdkvisual-quartz.c + * + * Copyright (C) 2005 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 "gdkvisual.h" +#include "gdkprivate-quartz.h" + +/* FIXME: We might want to include the rgba visual in the query functions */ + +static GdkVisual *system_visual; +static GdkVisual *rgba_visual; + +static void +gdk_visual_finalize (GObject *object) +{ + g_error ("A GdkVisual object was finalized. This should not happen"); +} + +static void +gdk_visual_class_init (GObjectClass *class) +{ + class->finalize = gdk_visual_finalize; +} + +GType +gdk_visual_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkVisualClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_visual_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkVisual), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkVisual", + &object_info, 0); + } + + return object_type; +} + +static void +gdk_visual_decompose_mask (gulong mask, + gint *shift, + gint *prec) +{ + *shift = 0; + *prec = 0; + + while (!(mask & 0x1)) + { + (*shift)++; + mask >>= 1; + } + + while (mask & 0x1) + { + (*prec)++; + mask >>= 1; + } +} + +static GdkVisual * +create_standard_visual (gint depth) +{ + GdkVisual *visual = g_object_new (GDK_TYPE_VISUAL, NULL); + + visual->depth = depth; + visual->byte_order = GDK_MSB_FIRST; /* FIXME: Should this be different on intel macs? */ + visual->colormap_size = 0; + + visual->type = GDK_VISUAL_TRUE_COLOR; + + visual->red_mask = 0xff0000; + visual->green_mask = 0xff00; + visual->blue_mask = 0xff; + + gdk_visual_decompose_mask (visual->red_mask, + &visual->red_shift, + &visual->red_prec); + gdk_visual_decompose_mask (visual->green_mask, + &visual->green_shift, + &visual->green_prec); + gdk_visual_decompose_mask (visual->blue_mask, + &visual->blue_shift, + &visual->blue_prec); + + return visual; +} + +void +_gdk_visual_init (void) +{ + system_visual = create_standard_visual (24); + rgba_visual = create_standard_visual (32); +} + +gint +gdk_visual_get_best_depth (void) +{ + return system_visual->depth; +} + +GdkVisualType +gdk_visual_get_best_type (void) +{ + return system_visual->type; +} + +GdkVisual * +gdk_screen_get_rgba_visual (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return rgba_visual; +} + +GdkVisual* +gdk_screen_get_system_visual (GdkScreen *screen) +{ + return system_visual; +} + +GdkVisual* +gdk_visual_get_best (void) +{ + return system_visual; +} + +GdkVisual* +gdk_visual_get_best_with_depth (gint depth) +{ + if (system_visual->depth != depth) + return NULL; + + return system_visual; +} + +GdkVisual* +gdk_visual_get_best_with_type (GdkVisualType visual_type) +{ + if (system_visual->type != visual_type) + return NULL; + + return system_visual; +} + +GdkVisual* +gdk_visual_get_best_with_both (gint depth, + GdkVisualType visual_type) +{ + if (system_visual->depth != depth) + return NULL; + + if (system_visual->type != visual_type) + return NULL; + + return system_visual; +} + +void +gdk_query_depths (gint **depths, + gint *count) +{ + *count = 1; + *depths = &system_visual->depth; +} + +void +gdk_query_visual_types (GdkVisualType **visual_types, + gint *count) +{ + *count = 1; + *visual_types = &system_visual->type; +} + +GList* +gdk_screen_list_visuals (GdkScreen *screen) +{ + return g_list_append (NULL, gdk_visual_get_system ()); +} + +GdkScreen * +gdk_visual_get_screen (GdkVisual *visual) +{ + g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL); + + return gdk_screen_get_default (); +} + diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c new file mode 100644 index 000000000..0d6e4c4c9 --- /dev/null +++ b/gdk/quartz/gdkwindow-quartz.c @@ -0,0 +1,1187 @@ +/* gdkwindow-quartz.c + * + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * Copyright (C) 2005 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 "gdk.h" +#include "gdkprivate-quartz.h" + +static gpointer parent_class; + +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]; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass) +{ + GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + 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; +} + +GType +_gdk_window_impl_quartz_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static 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, + }; + + object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ, + "GdkWindowImplQuartz", + &object_info, 0); + } + + 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; +} + +gint +_gdk_quartz_get_inverted_screen_y (gint y) +{ + NSRect rect = [[NSScreen mainScreen] frame]; + + return rect.size.height - y; +} + +GdkWindow * +gdk_window_new (GdkWindow *parent, + GdkWindowAttr *attributes, + gint attributes_mask) +{ + GdkWindow *window; + GdkWindowObject *private; + GdkWindowImplQuartz *impl; + GdkDrawableImplQuartz *draw_impl; + GdkVisual *visual; + + GDK_QUARTZ_ALLOC_POOL; + + if (parent && GDK_WINDOW_DESTROYED (parent)) + { + GDK_QUARTZ_RELEASE_POOL; + return NULL; + } + + 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; + + 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); + 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); + } + + if (private->parent) + private->parent->children = g_list_prepend (private->parent->children, window); + + 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 = NSMakeRect (private->x, + _gdk_quartz_get_inverted_screen_y (private->y) - impl->height, + impl->width, impl->height); + const char *title; + int 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]; + + /* Add a tracking rect */ + impl->tracking_rect = [impl->view addTrackingRect:NSMakeRect(0, 0, impl->width, impl->height) + owner:impl->view + userData:nil + assumeInside:NO]; + } + 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; + + return window; +} + +void +_gdk_windowing_window_init (void) +{ + GdkWindowObject *private; + + g_assert (_gdk_root == NULL); + + _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL); + private = (GdkWindowObject *)_gdk_root; + + private->window_type = GDK_WINDOW_ROOT; + private->depth = 24; +} + +void +_gdk_windowing_window_destroy (GdkWindow *window, + gboolean recursing, + gboolean foreign_destroy) +{ + if (!recursing && ! foreign_destroy) + { + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl); + + if (window == _gdk_quartz_get_mouse_window ()) + { + _gdk_quartz_update_mouse_window (_gdk_root); + } + + if (impl->toplevel) + [impl->toplevel close]; + else if (impl->view) + [impl->view release]; + + } +} + +void +_gdk_windowing_window_destroy_foreign (GdkWindow *window) +{ + /* FIXME: Implement */ +} + +static void +show_window_internal (GdkWindow *window, gboolean raise) +{ + GdkWindowObject *private; + GdkWindowImplQuartz *impl; + + private = (GdkWindowObject *)window; + + if (private->destroyed) + return; + + GDK_QUARTZ_ALLOC_POOL; + + impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + + /* FIXME: We need to raise the window (move it to the top in the list)*/ + + if (impl->toplevel) + { + [impl->toplevel orderFront:nil]; + [impl->view setNeedsDisplay:YES]; + } + else + { + [impl->view setHidden:NO]; + [impl->view setNeedsDisplay:YES]; + } + + gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0); + + GDK_QUARTZ_RELEASE_POOL; +} + +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; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + if (GDK_WINDOW_DESTROYED (window)) + return; + + 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) + { + /* FIXME: Support hiding toplevel windows */ + } + else if (impl->view) + { + [impl->view setHidden:YES]; + } +} + +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; + + if (GDK_WINDOW_DESTROYED (window)) + return; + + impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); + + if (x != -1) + private->x = x; + + if (y != -1) + private->y = y; + + if (width != -1) + impl->width = width; + + if (height != -1) + impl->height = height; + + if (impl->toplevel) + { + NSRect content_rect = NSMakeRect (private->x, + _gdk_quartz_get_inverted_screen_y (private->y) , + impl->width, impl->height); + NSRect frame_rect = [impl->toplevel frameRectForContentRect:content_rect]; + + frame_rect.origin.y -= frame_rect.size.height; + + [impl->toplevel setFrame:frame_rect display:YES]; + } + else + { + if (!private->input_only) + { + [impl->view setFrame:NSMakeRect (private->x, private->y, + impl->width, impl->height)]; + + /* FIXME: Maybe we should use setNeedsDisplayInRect instead */ + [impl->view setNeedsDisplay:YES]; + } + } +} + +void +gdk_window_move (GdkWindow *window, + gint x, + gint y) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + 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 (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) +{ + g_warning ("gdk_window_reparent: %p %p (%d, %d)", + window, new_parent, x, y); + + /* FIXME: Implement */ +} + +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 */ +} + +void +gdk_window_raise (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_lower (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +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) +{ + 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)); + + /* FIXME: Implement */ +} + +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; + + if (!cursor) + nscursor = NULL; + else + nscursor = [cursor_private->nscursor retain]; + + if (impl->nscursor) + [impl->nscursor release]; + + impl->nscursor = nscursor; + + _gdk_quartz_update_cursor (_gdk_quartz_get_mouse_window ()); +} + +void +gdk_window_get_geometry (GdkWindow *window, + gint *x, + gint *y, + gint *width, + gint *height, + gint *depth) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +gboolean +gdk_window_get_origin (GdkWindow *window, + gint *x, + gint *y) +{ + g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + + /* FIXME: Implement */ + return FALSE; +} + +gboolean +gdk_window_get_deskrelative_origin (GdkWindow *window, + gint *x, + gint *y) +{ + g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + + /* FIXME: Implement */ + return FALSE; +} + +void +gdk_window_get_root_origin (GdkWindow *window, + gint *x, + gint *y) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +_gdk_windowing_get_pointer (GdkDisplay *display, + GdkScreen **screen, + gint *x, + gint *y, + GdkModifierType *mask) +{ +} + +GdkWindow * +_gdk_windowing_window_get_pointer (GdkDisplay *display, + GdkWindow *window, + gint *x, + gint *y, + GdkModifierType *mask) +{ + if (window == _gdk_root) + { + g_error ("FIXME: support get_pointer with root window"); + } + else + { + GdkWindow *toplevel = gdk_window_get_toplevel (window); + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl); + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + NSWindow *nswindow = impl->toplevel; + NSPoint point = [nswindow mouseLocationOutsideOfEventStream]; + int x_tmp, y_tmp; + + /* First flip the y coordinate */ + x_tmp = point.x; + y_tmp = impl->height - point.y; + + while (private != GDK_WINDOW_OBJECT (toplevel)) { + x_tmp -= private->x; + y_tmp -= private->y; + + private = private->parent; + } + + if (x) + *x = x_tmp; + if (y) + *y = y_tmp; + } + + /* FIXME: Implement return value */ + return NULL; +} + +GdkWindow * +_gdk_windowing_window_at_pointer (GdkDisplay *display, + gint *win_x, + gint *win_y) +{ + /* FIXME: Implement */ + return NULL; +} + +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, + GdkGeometry *geometry, + GdkWindowHints geom_mask) +{ + /* 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) + { + [impl->toplevel setTitle:[NSString stringWithUTF8String:title]]; + } +} + +void +gdk_window_set_role (GdkWindow *window, + const gchar *role) +{ + /* FIXME: Implement */ +} + +void +gdk_window_set_transient_for (GdkWindow *window, + GdkWindow *parent) +{ + /* FIXME: Implement */ +} + +void +gdk_window_shape_combine_region (GdkWindow *window, + 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_set_accept_focus (GdkWindow *window, + gboolean accept_focus) +{ + /* FIXME: Implement */ +} + +void +gdk_window_set_focus_on_map (GdkWindow *window, + gboolean focus_on_map) +{ + /* FIXME: Implement */ +} + +void +gdk_window_set_icon (GdkWindow *window, + GdkWindow *icon_window, + GdkPixmap *pixmap, + GdkBitmap *mask) +{ + g_return_if_fail (window != NULL); + 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 (window != NULL); + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_focus (GdkWindow *window, + guint32 timestamp) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_set_type_hint (GdkWindow *window, + GdkWindowTypeHint hint) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +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) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_begin_move_drag (GdkWindow *window, + gint button, + gint root_x, + gint root_y, + guint32 timestamp) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_set_icon_list (GdkWindow *window, + GList *pixbufs) +{ + /* FIXME: Implement */ +} + +void +gdk_window_get_frame_extents (GdkWindow *window, + GdkRectangle *rect) +{ + /* FIXME: Implement */ +} + +void +gdk_window_set_decorations (GdkWindow *window, + GdkWMDecoration decorations) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +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) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_unmaximize (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_iconify (GdkWindow *window) +{ + GdkWindowImplQuartz *impl; + NSAutoreleasePool *pool; + + 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 (!impl->toplevel) + return; + + pool = [[NSAutoreleasePool alloc] init]; + [impl->toplevel miniaturize:nil]; + [pool release]; +} + +void +gdk_window_deiconify (GdkWindow *window) +{ + GdkWindowImplQuartz *impl; + NSAutoreleasePool *pool; + + 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 (!impl->toplevel) + return; + + pool = [[NSAutoreleasePool alloc] init]; + [impl->toplevel deminiaturize:nil]; + [pool release]; +} + +void +gdk_window_fullscreen (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_unfullscreen (GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_set_keep_above (GdkWindow *window, gboolean setting) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* FIXME: Implement */ +} + +void +gdk_window_set_keep_below (GdkWindow *window, gboolean setting) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + /* 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) +{ +} diff --git a/gdk/quartz/gdkwindow-quartz.h b/gdk/quartz/gdkwindow-quartz.h new file mode 100644 index 000000000..0fe45d1f2 --- /dev/null +++ b/gdk/quartz/gdkwindow-quartz.h @@ -0,0 +1,72 @@ +/* gdkdrawable-quartz.h + * + * Copyright (C) 2005 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. + */ + +#ifndef __GDK_WINDOW_QUARTZ_H__ +#define __GDK_WINDOW_QUARTZ_H__ + +#include <gdk/quartz/gdkdrawable-quartz.h> +#import <gdk/quartz/GdkQuartzView.h> +#import <gdk/quartz/GdkQuartzWindow.h> + + +G_BEGIN_DECLS + +/* Window implementation for Quartz + */ + +typedef struct _GdkWindowImplQuartz GdkWindowImplQuartz; +typedef struct _GdkWindowImplQuartzClass GdkWindowImplQuartzClass; + +#define GDK_TYPE_WINDOW_IMPL_QUARTZ (_gdk_window_impl_quartz_get_type ()) +#define GDK_WINDOW_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_QUARTZ, GdkWindowImplQuartz)) +#define GDK_WINDOW_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_QUARTZ, GdkWindowImplQuartzClass)) +#define GDK_IS_WINDOW_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_QUARTZ)) +#define GDK_IS_WINDOW_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_QUARTZ)) +#define GDK_WINDOW_IMPL_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_QUARTZ, GdkWindowImplQuartzClass)) + +struct _GdkWindowImplQuartz +{ + GdkDrawableImplQuartz parent_instance; + + gint width; + gint height; + + NSWindow *toplevel; + NSTrackingRectTag tracking_rect; + GdkQuartzView *view; + + /* This is the autorelease pool which is retained + * while the context is being held + */ + NSAutoreleasePool *pool; + + NSCursor *nscursor; +}; + +struct _GdkWindowImplQuartzClass +{ + GdkDrawableImplQuartzClass parent_class; +}; + +GType _gdk_window_impl_quartz_get_type (void); + +G_END_DECLS + +#endif /* __GDK_WINDOW_QUARTZ_H__ */ diff --git a/gtk/Makefile.am b/gtk/Makefile.am index c6a1f01e8..eb5e7b916 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -675,20 +675,23 @@ gtkinclude_HEADERS = $(gtk_public_h_sources) $(gtk_semi_private_h_sources) $(gtk libgtk_x11_2_0_la_SOURCES = $(gtk_c_sources) libgtk_linux_fb_2_0_la_SOURCES = $(gtk_c_sources) libgtk_win32_2_0_la_SOURCES = $(gtk_c_sources) +libgtk_quartz_2_0_la_SOURCES = $(gtk_c_sources) libgtk_x11_2_0_la_LDFLAGS = $(libtool_opts) libgtk_linux_fb_2_0_la_LDFLAGS = $(libtool_opts) libgtk_win32_2_0_la_LDFLAGS = $(libtool_opts) +libgtk_quartz_2_0_la_LDFLAGS = $(libtool_opts) libgtk_x11_2_0_la_LIBADD = $(libadd) libgtk_linux_fb_2_0_la_LIBADD = $(libadd) libgtk_win32_2_0_la_LIBADD = $(libadd) -lole32 -lgdi32 libgtk_win32_2_0_la_DEPENDENCIES = $(gtk_def) $(gtk_win32_res) +libgtk_quartz_2_0_la_LIBADD = $(libadd) if USE_WIN32 libgtk_target_ldflags = $(gtk_win32_res_ldflag) $(gtk_win32_symbols) endif -EXTRA_LTLIBRARIES = libgtk-x11-2.0.la libgtk-linux-fb-2.0.la libgtk-win32-2.0.la +EXTRA_LTLIBRARIES = libgtk-x11-2.0.la libgtk-linux-fb-2.0.la libgtk-win32-2.0.la libgtk-quartz-2.0.la install-exec-hook: if DISABLE_EXPLICIT_DEPS diff --git a/gtk/gtkplug-stub.c b/gtk/gtkplug-stub.c index 3346f36ed..3bd1024aa 100644 --- a/gtk/gtkplug-stub.c +++ b/gtk/gtkplug-stub.c @@ -25,6 +25,7 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include "gtkplug.h" #include "gtkplugprivate.h" GdkNativeWindow diff --git a/gtk/gtksocket-stub.c b/gtk/gtksocket-stub.c index 9895c227b..b839048b8 100644 --- a/gtk/gtksocket-stub.c +++ b/gtk/gtksocket-stub.c @@ -25,6 +25,7 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include "gtksocket.h" #include "gtksocketprivate.h" GdkNativeWindow |