? makefile.cygwin ? makefile.msc ? archaeo-changes-18Dec2001.diff ? win32/gdkdnd-ole2-win32.c ? win32/makefile.cygwin Index: gdk.def =================================================================== RCS file: /cvs/gnome/gtk+/gdk/gdk.def,v retrieving revision 1.4.6.2 diff -c -r1.4.6.2 gdk.def *** gdk.def 2001/02/23 00:13:58 1.4.6.2 --- gdk.def 2001/12/18 15:37:36 *************** *** 1,6 **** --- 1,7 ---- EXPORTS gdk_atom_intern gdk_atom_name + gdk_add_client_message_filter gdk_beep gdk_bitmap_create_from_data gdk_char_height *************** *** 150,162 **** gdk_get_display gdk_get_show_events gdk_get_use_xshm - gdk_ic_attr_destroy - gdk_ic_attr_new gdk_ic_destroy gdk_ic_get_attr gdk_ic_get_events gdk_ic_get_style gdk_ic_get_values gdk_ic_new gdk_ic_set_attr gdk_ic_set_values --- 151,163 ---- gdk_get_display gdk_get_show_events gdk_get_use_xshm gdk_ic_destroy gdk_ic_get_attr gdk_ic_get_events gdk_ic_get_style gdk_ic_get_values + gdk_ic_attr_new + gdk_ic_attr_destroy gdk_ic_new gdk_ic_set_attr gdk_ic_set_values *************** *** 209,214 **** --- 210,216 ---- gdk_pixmap_create_from_xpm_d gdk_pixmap_create_on_shared_image gdk_pixmap_foreign_new + gdk_pixmap_native_gc_new gdk_pixmap_new gdk_pointer_grab gdk_pointer_is_grabbed *************** *** 286,293 **** --- 288,299 ---- gdk_visual_ref gdk_visual_unref gdk_wcstombs + gdk_win32_begin_modal_call + gdk_win32_end_modal_call gdk_win32_hdc_get gdk_win32_hdc_release + gdk_win32_global_hdc_set + gdk_win32_set_allow_expose_callback gdk_window_add_filter gdk_window_at_pointer gdk_window_clear Index: gdkconfig.h.win32 =================================================================== RCS file: /cvs/gnome/gtk+/gdk/gdkconfig.h.win32,v retrieving revision 1.1.18.1 diff -c -r1.1.18.1 gdkconfig.h.win32 *** gdkconfig.h.win32 2001/10/28 00:52:13 1.1.18.1 --- gdkconfig.h.win32 2001/12/18 15:37:39 *************** *** 1,24 **** ! /* gdkconfig.h ! * ! * This is a generated file. Please modify `configure.in' ! */ - #ifndef GDKCONFIG_H - #define GDKCONFIG_H - - #ifdef __cplusplus - extern "C" { - #endif /* __cplusplus */ - - #define GDK_WINDOWING_WIN32 - #define GDK_USE_UTF8_MBS - #define GDK_HAVE_WCHAR_H 1 #define GDK_HAVE_WCTYPE_H 1 - #ifdef __cplusplus - } - #endif /* __cplusplus */ - - #endif /* GDKCONFIG_H */ --- 1,9 ---- ! /* Handcrafted for Win32 */ #define GDK_WINDOWING_WIN32 #define GDK_HAVE_WCHAR_H 1 + #ifdef _MSC_VER #define GDK_HAVE_WCTYPE_H 1 + #endif + #define GDK_USE_UTF8_MBS 1 Index: gdkdnd.h =================================================================== RCS file: /cvs/gnome/gtk+/gdk/gdkdnd.h,v retrieving revision 1.2.6.1 diff -c -r1.2.6.1 gdkdnd.h *** gdkdnd.h 2001/11/14 00:51:10 1.2.6.1 --- gdkdnd.h 2001/12/18 15:37:40 *************** *** 25,32 **** * drags */ GDK_DRAG_PROTO_NONE, /* Not a valid drag window */ GDK_DRAG_PROTO_WIN32_DROPFILES, /* The simple WM_DROPFILES dnd */ ! GDK_DRAG_PROTO_OLE2, /* The complex OLE2 dnd (not implemented) */ ! GDK_DRAG_PROTO_LOCAL /* Intra-app */ } GdkDragProtocol; /* Structure that holds information about a drag in progress. --- 25,31 ---- * drags */ GDK_DRAG_PROTO_NONE, /* Not a valid drag window */ GDK_DRAG_PROTO_WIN32_DROPFILES, /* The simple WM_DROPFILES dnd */ ! GDK_DRAG_PROTO_OLE2, /* The OLE2 dnd */ } GdkDragProtocol; /* Structure that holds information about a drag in progress. Index: gdkdrawable.h =================================================================== RCS file: /cvs/gnome/gtk+/gdk/gdkdrawable.h,v retrieving revision 1.4.4.1 diff -c -r1.4.4.1 gdkdrawable.h *** gdkdrawable.h 2001/11/14 00:51:10 1.4.4.1 --- gdkdrawable.h 2001/12/18 15:37:44 *************** *** 29,34 **** --- 29,37 ---- * pixmap to any procedure which accepts a window with the * exception of the drawing functions). * Foreign: A window that actually belongs to another application + * Native: A window-less native drawing context created outside of GTK + * These are used, e.g., to print on win32 using the native + * printing support. */ typedef enum { *************** *** 38,44 **** GDK_WINDOW_DIALOG, GDK_WINDOW_TEMP, GDK_DRAWABLE_PIXMAP, ! GDK_WINDOW_FOREIGN } GdkDrawableType; struct _GdkDrawable --- 41,48 ---- GDK_WINDOW_DIALOG, GDK_WINDOW_TEMP, GDK_DRAWABLE_PIXMAP, ! GDK_WINDOW_FOREIGN, ! GDK_DRAWABLE_NATIVE } GdkDrawableType; struct _GdkDrawable Index: gdkevents.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/gdkevents.c,v retrieving revision 1.26 diff -c -r1.26 gdkevents.c *** gdkevents.c 2000/03/14 19:57:22 1.26 --- gdkevents.c 2001/12/18 15:37:45 *************** *** 30,37 **** typedef struct _GdkIOClosure GdkIOClosure; typedef struct _GdkEventPrivate GdkEventPrivate; ! #define DOUBLE_CLICK_TIME 250 ! #define TRIPLE_CLICK_TIME 500 #define DOUBLE_CLICK_DIST 5 #define TRIPLE_CLICK_DIST 5 --- 30,37 ---- typedef struct _GdkIOClosure GdkIOClosure; typedef struct _GdkEventPrivate GdkEventPrivate; ! #define DOUBLE_CLICK_TIME 500 ! #define TRIPLE_CLICK_TIME 750 #define DOUBLE_CLICK_DIST 5 #define TRIPLE_CLICK_DIST 5 Index: gdkevents.h =================================================================== RCS file: /cvs/gnome/gtk+/gdk/gdkevents.h,v retrieving revision 1.3 diff -c -r1.3 gdkevents.h *** gdkevents.h 2000/03/14 19:57:22 1.3 --- gdkevents.h 2001/12/18 15:37:45 *************** *** 430,435 **** --- 430,436 ---- GdkFilterFunc func, gpointer data); + void gdk_win32_set_allow_expose_callback (gboolean value); #ifdef __cplusplus } Index: testgdk.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/testgdk.c,v retrieving revision 1.3.2.1 diff -c -r1.3.2.1 testgdk.c *** testgdk.c 2001/02/23 01:00:18 1.3.2.1 --- testgdk.c 2001/12/18 15:38:23 *************** *** 1,931 **** ! /* testgdk -- validation program for GDK ! * Copyright (C) 2000 Tor Lillqvist ! * ! * 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. ! */ ! ! /* This program is intended to be used to validate the correctness of ! * the basic graphics operations in a GDK backend. The results of the ! * operations are compared against those produced by a correctly ! * functioning X11 backend (and X11 server). ! * ! * Obviously, only the most basic operations reasonably be expected to ! * produce pixel-by-pixel identical results as the X11 backend. We ! * don't even try to test the correctness of ellipses, tiles or ! * stipples. Not to mention fonts. ! * ! * But, for those operations we do test, we should try to test quite ! * many combinations of parameters. ! * ! * This is just a quick hack, and could be improved a lot. There are ! * copy-pasted code snippets all over that need to be factored out ! * into separate functions. ! */ ! ! #include ! #include ! #include ! #include ! ! #include ! ! /* CQTESTF -- "Conditionally Quiet TEST with Fail message" ! * macro that prints PASS or FAIL messages ! * parms: quiet: if TRUE, only print FAIL messages ! * expr: the expression to test ! * failfmt:if expr is FALSE, print this message ! * (both format and args) ! */ ! ! #define CQTESTF(quiet, expr, failfmt) \ ! (tmpb = (expr), \ ! (tmpb ? (quiet ? 0 : printf ("PASS: %d %s\n", __LINE__, #expr)) \ ! : (printf ("FAIL: %d %s", __LINE__, #expr), \ ! printf failfmt, \ ! printf ("\n"), \ ! retval = FALSE, \ ! error (), \ ! return_value++)), \ ! tmpb) ! ! /* Variations with less parms */ ! ! #define CQTEST(quiet, expr) \ ! CQTESTF (quiet, expr, ("")) ! ! #define TEST(expr) \ ! CQTEST (FALSE, expr) ! ! #define QTEST(expr) \ ! CQTEST (TRUE, expr) ! ! #define TESTF(expr, failfmt) \ ! CQTESTF (FALSE, expr, failfmt) ! ! #define QTESTF(expr, failfmt) \ ! CQTESTF (TRUE, expr, failfmt) ! ! #ifndef _DEBUG ! #define ASSERT(expr) \ ! do { \ ! if (!QTEST (expr)) \ ! printf ("That is fatal. Goodbye\n"), exit (1);\ ! } while (0) ! #else ! static void ! my_break() ! { ! G_BREAKPOINT(); ! } ! #define ASSERT(expr) \ ! do { \ ! if (!QTEST (expr)) \ ! printf ("That is fatal. Goodbye\n"), my_break();\ ! } while (0) ! #endif ! ! #define N(a) (sizeof(a)/sizeof(*a)) ! ! static int return_value = 0; ! ! static gboolean retval; ! static gboolean tmpb; ! ! static GdkVisual *system_visual; ! static GdkVisual *best_visual; ! static GdkWindow *w; ! ! static GdkColormap *system_colourmap; ! ! static GdkColor white, black, red, green, blue, rand1_colour, rand2_colour; ! ! static GdkGC *black_gc, *white_gc, *red_gc, *rand1_gc, *rand2_gc; ! static GdkGC *gcs[5]; ! static GdkGC *black_bitmap_gc; ! ! static int ! error (void) ! { ! /* Place breakpoint here to catch failures */ ! return 0; ! } ! ! static gboolean ! test_visual_coherency (gboolean quiet, ! GdkVisual *visual) ! { ! gboolean retval = TRUE; ! ! CQTEST (quiet, visual->type >= GDK_VISUAL_STATIC_GRAY && ! visual->type <= GDK_VISUAL_DIRECT_COLOR); ! CQTEST (quiet, visual->depth >= 1 && visual->depth <= 32); ! CQTEST (quiet, visual->byte_order == GDK_LSB_FIRST || visual->byte_order == ! GDK_MSB_FIRST); ! ! return retval; ! } ! ! /* Test visuals ! */ ! static void ! test_visuals (void) ! { ! GdkVisual *visual; ! GList *visuals; ! ! system_visual = gdk_visual_get_system (); ! ASSERT (system_visual != NULL); ! TEST (test_visual_coherency (FALSE, system_visual)); ! ! best_visual = gdk_visual_get_best (); ! if (best_visual != system_visual) ! TEST (test_visual_coherency (TRUE, best_visual)); ! ! visuals = gdk_list_visuals (); ! while (visuals) ! { ! visual = visuals->data; ! TEST (test_visual_coherency (TRUE, visual)); ! visuals = visuals->next; ! } ! } ! ! /* Create a top-level window used by other tests ! */ ! static void ! test_first_window (void) ! { ! GdkWindowAttr wa; ! ! wa.width = 100; ! wa.height = 100; ! wa.window_type = GDK_WINDOW_TOPLEVEL; ! wa.wclass = GDK_INPUT_OUTPUT; ! ! w = gdk_window_new (NULL, &wa, 0); ! ! ASSERT (w != NULL); ! } ! ! /* Test colourmaps. ! */ ! static void ! test_colourmaps (void) ! { ! system_colourmap = gdk_colormap_get_system (); ! ASSERT (system_colourmap != NULL); ! } ! ! /* Test colours. ! */ ! static void ! test_colours (void) ! { ! ASSERT (gdk_color_white (system_colourmap, &white)); ! ASSERT (gdk_color_black (system_colourmap, &black)); ! red.red = 65535; ! red.green = red.blue = 0; ! TEST (gdk_colormap_alloc_color (system_colourmap, &red, FALSE, TRUE)); ! ! rand1_colour.red = rand () % 65536; ! rand1_colour.green = rand () % 65536; ! rand1_colour.blue = rand () % 65536; ! TEST (gdk_colormap_alloc_color (system_colourmap, &rand1_colour, FALSE, ! TRUE)); ! ! rand2_colour.red = rand () % 65536; ! rand2_colour.green = rand () % 65536; ! rand2_colour.blue = rand () % 65536; ! TEST (gdk_colormap_alloc_color (system_colourmap, &rand2_colour, FALSE, ! TRUE)); ! } ! ! static gboolean ! test_default_gc (GdkGCValues *gcvalues, ! gboolean quiet) ! { ! gboolean retval = TRUE; ! ! CQTEST (quiet, gcvalues->foreground.pixel == 0); ! CQTEST (quiet, gcvalues->background.pixel == 1); ! CQTEST (quiet, gcvalues->function == GDK_COPY); ! CQTEST (quiet, gcvalues->fill == GDK_SOLID); ! CQTEST (quiet, gcvalues->tile == NULL); ! CQTEST (quiet, gcvalues->stipple == NULL); ! CQTEST (quiet, gcvalues->clip_mask == NULL); ! CQTEST (quiet, gcvalues->subwindow_mode == GDK_CLIP_BY_CHILDREN); ! CQTEST (quiet, gcvalues->line_width == 0); ! CQTEST (quiet, gcvalues->line_style == GDK_LINE_SOLID); ! CQTEST (quiet, gcvalues->cap_style == GDK_CAP_BUTT); ! CQTEST (quiet, gcvalues->join_style == GDK_JOIN_MITER); ! ! return retval; ! } ! ! /* Create GdkGCs with various values, ! * check that gdk_gc_get_values returns the same, ! * or something reasonably close. ! */ ! static void ! test_gcs (void) ! { ! GdkPixmap *pixmap; ! GdkGC *gc; ! GdkGCValues gcvalues; ! GdkColor colour; ! GdkFunction function; ! GdkFill fill; ! gboolean retval; ! ! gc = gdk_gc_new (w); ! gdk_gc_get_values (gc, &gcvalues); ! test_default_gc (&gcvalues, FALSE); ! ! colour.pixel = 1234; ! gdk_gc_set_foreground (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == 1234); ! ! colour.pixel = 0; ! gdk_gc_set_foreground (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (test_default_gc (&gcvalues, TRUE)); ! ! colour.pixel = 5678; ! gdk_gc_set_background (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (gcvalues.background.pixel == 5678); ! ! colour.pixel = 1; ! gdk_gc_set_background (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (test_default_gc (&gcvalues, TRUE)); ! ! retval = TRUE; ! for (function = GDK_COPY; function <= GDK_SET; function++) ! { ! gdk_gc_set_function (gc, function); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (gcvalues.function == function); ! gdk_gc_set_function (gc, GDK_COPY); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (test_default_gc (&gcvalues, TRUE)); ! } ! TEST (retval); ! ! retval = TRUE; ! for (fill = GDK_SOLID; fill <= GDK_OPAQUE_STIPPLED; fill++) ! { ! gdk_gc_set_fill (gc, fill); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (gcvalues.fill == fill); ! gdk_gc_set_fill (gc, GDK_SOLID); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (test_default_gc (&gcvalues, TRUE)); ! } ! TEST (retval); ! ! black_gc = gdk_gc_new (w); ! gdk_gc_copy (black_gc, gc); ! gdk_gc_get_values (black_gc, &gcvalues); ! TEST (test_default_gc (&gcvalues, TRUE)); ! gdk_gc_unref (gc); ! ! gdk_gc_set_foreground (black_gc, &black); ! gdk_gc_get_values (black_gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == black.pixel); ! ! white_gc = gdk_gc_new (w); ! ! gdk_gc_set_foreground (white_gc, &white); ! gdk_gc_get_values (white_gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == white.pixel); ! ! red_gc = gdk_gc_new (w); ! gdk_gc_set_foreground (red_gc, &red); ! gdk_gc_get_values (red_gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == red.pixel); ! ! rand1_gc = gdk_gc_new (w); ! gdk_gc_set_foreground (rand1_gc, &rand1_colour); ! gdk_gc_get_values (rand1_gc, &gcvalues); ! TESTF (gcvalues.foreground.pixel == rand1_colour.pixel, ! (" %#06x != %#06x", gcvalues.foreground.pixel, rand1_colour.pixel)); ! ! rand2_gc = gdk_gc_new (w); ! gdk_gc_set_foreground (rand2_gc, &rand2_colour); ! gdk_gc_get_values (rand2_gc, &gcvalues); ! TESTF (gcvalues.foreground.pixel == rand2_colour.pixel, ! (" %#06x != %#06x", gcvalues.foreground.pixel, rand2_colour.pixel)); ! ! gcs[0] = black_gc; ! gcs[1] = white_gc; ! gcs[2] = red_gc; ! gcs[3] = rand1_gc; ! gcs[4] = rand2_gc; ! ! pixmap = gdk_pixmap_new (NULL, 1, 1, 1); ! black_bitmap_gc = gdk_gc_new (pixmap); ! gdk_pixmap_unref (pixmap); ! } ! ! /* Create pixmaps, check that properties are as expected. ! * No graphic operations tested yet. ! */ ! static void ! test_pixmaps (gint depth) ! { ! GdkPixmap *pixmap; ! GdkImage *image; ! GdkGC *gc; ! gint width, height; ! gint w, h; ! gboolean retval = TRUE; ! ! for (width = 1; width <= 64; width += 2) ! for (height = 1; height <= 32; height += 3) ! { ! pixmap = gdk_pixmap_new (NULL, width, height, depth); ! ASSERT (pixmap != NULL); ! gdk_window_get_size (pixmap, &w, &h); ! QTESTF (w == width, (" w:%d", w)); ! QTESTF (h == height, (" h:%d", h)); ! image = gdk_image_get (pixmap, 0, 0, w, h); ! QTEST (image != NULL); ! QTEST (image->width == width); ! QTEST (image->height == height); ! QTEST (image->depth == depth); ! gdk_image_destroy (image); ! gdk_pixmap_unref (pixmap); ! } ! TEST (retval); ! } ! ! /* Ditto for images. ! */ ! static void ! test_images (void) ! { ! GdkImage *image; ! GdkImageType image_type; ! gint width, height; ! gboolean retval = TRUE; ! ! for (width = 1; width <= 64; width += 3) ! for (height = 1; height <= 32; height += 7) ! for (image_type = GDK_IMAGE_NORMAL; ! image_type <= GDK_IMAGE_FASTEST; ! image_type++) ! { ! image = gdk_image_new (image_type, system_visual, width, height); ! if (image == NULL && image_type == GDK_IMAGE_SHARED) ! /* Ignore failure to create shared image, ! * display might not be local. ! */ ! ; ! else ! { ! ASSERT (image != NULL); ! QTEST (image->width == width); ! QTEST (image->height == height); ! QTEST (image->depth == system_visual->depth); ! QTEST (image->bpp >= (image->depth-1)/8 + 1); ! QTEST (image->mem != NULL); ! gdk_image_destroy (image); ! } ! } ! TEST (retval); ! } ! ! /* Test creating temp windows. ! */ ! static void ! test_temp_windows (void) ! { ! GdkWindow *window; ! GdkWindowAttr wa; ! GdkVisual *visual; ! gint width, height; ! gint w, h, x, y, d; ! gboolean retval = TRUE; ! ! wa.window_type = GDK_WINDOW_TEMP; ! wa.wclass = GDK_INPUT_OUTPUT; ! ! for (width = 1; width <= 64; width += 4) ! for (height = 1; height <= 32; height += 7) ! { ! wa.width = width; ! wa.height = height; ! window = gdk_window_new (NULL, &wa, 0); ! ASSERT (window != NULL); ! gdk_window_get_geometry (window, &x, &y, &w, &h, &d); ! QTESTF (w == width, ("w:%d", w)); ! QTESTF (h == height, ("h:%d", h)); ! gdk_window_show (window); ! gdk_window_get_geometry (window, &x, &y, &w, &h, &d); ! QTESTF (w == width, ("w:%d", w)); ! QTESTF (h == height, ("h:%d", h)); ! gdk_window_resize (window, 37, 19); ! gdk_window_get_geometry (window, &x, &y, &w, &h, &d); ! QTESTF (w == 37, ("w:%d", w)); ! QTESTF (h == 19, ("h:%d", h)); ! visual = gdk_window_get_visual (window); ! QTEST (visual == system_visual); ! gdk_window_hide (window); ! gdk_window_unref (window); ! } ! TEST (retval); ! } ! ! static void ! test_gc_function (GdkFunction function, ! guint32 oldpixel, ! guint32 newpixel, ! guint32 foreground, ! guint32 mask) ! { ! switch (function) ! { ! case GDK_COPY: ! QTEST (newpixel == (foreground & mask)); break; ! case GDK_INVERT: ! QTEST (newpixel == ((~oldpixel) & mask)); break; ! case GDK_XOR: ! QTEST (newpixel == ((oldpixel ^ foreground) & mask)); break; ! case GDK_CLEAR: ! QTEST (newpixel == 0); break; ! case GDK_AND: ! QTEST (newpixel == ((oldpixel & foreground) & mask)); break; ! case GDK_AND_REVERSE: ! QTEST (newpixel == (((~oldpixel) & foreground) & mask)); break; ! case GDK_AND_INVERT: ! QTEST (newpixel == ((oldpixel & (~foreground)) & mask)); break; ! case GDK_NOOP: ! QTEST (newpixel == (oldpixel & mask)); break; ! case GDK_OR: ! QTEST (newpixel == ((oldpixel | foreground) & mask)); break; ! case GDK_EQUIV: ! QTEST (newpixel == ((oldpixel ^ (~foreground)) & mask)); break; ! case GDK_OR_REVERSE: ! QTEST (newpixel == (((~oldpixel) | foreground) & mask)); break; ! case GDK_COPY_INVERT: ! QTEST (newpixel == ((~foreground) & mask)); break; ! case GDK_OR_INVERT: ! QTEST (newpixel == ((oldpixel | (~foreground)) & mask)); break; ! case GDK_NAND: ! QTEST (newpixel == (((~oldpixel) | (~foreground)) & mask)); break; ! #ifdef GDK_NOR ! case GDK_NOR: ! QTEST (newpixel == (~oldpixel & ~mask)); break; ! #endif ! case GDK_SET: ! QTEST (newpixel == ((~0) & mask)); break; ! default: ! ASSERT (FALSE); ! } ! } ! ! static void ! test_one_point_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth) ! { ! GdkImage *image; ! GdkGCValues gcvalues; ! gint xoff, yoff; ! guint32 oldpixels[3][3], newpixel, mask; ! const gint x = 4; ! const gint y = 5; ! ! gdk_gc_get_values (gc, &gcvalues); ! ! image = gdk_image_get (drawable, x+-1, y+-1, 3, 3); ! QTEST (image != NULL); ! for (xoff = -1; xoff <= 1; xoff++) ! for (yoff = -1; yoff <= 1; yoff++) ! { ! oldpixels[xoff+1][yoff+1] = gdk_image_get_pixel (image, xoff+1, yoff+1); ! } ! gdk_image_destroy (image); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! gdk_draw_point (drawable, gc, x, y); ! ! image = gdk_image_get (drawable, x-1, y-1, 3, 3); ! QTEST (image != NULL); ! for (xoff = -1; xoff <= 1; xoff++) ! for (yoff = -1; yoff <= 1; yoff++) ! { ! newpixel = gdk_image_get_pixel (image, xoff+1, yoff+1); ! if (xoff == 0 && yoff == 0) ! test_gc_function (gcvalues.function, oldpixels[1][1], newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (newpixel == oldpixels[xoff+1][yoff+1]); ! } ! gdk_image_destroy (image); ! } ! ! ! /* Test drawing points. ! */ ! static void ! test_points (void) ! { ! GdkPixmap *pixmap; ! GdkWindow *window; ! GdkFunction function; ! gint width, height; ! int i, j; ! ! width = 8; ! height = 8; ! pixmap = gdk_pixmap_new (w, width, height, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, width, height); ! gdk_gc_set_function (gcs[j], function); ! test_one_point_on_drawable (pixmap, gcs[j], system_visual->depth); ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! ! pixmap = gdk_pixmap_new (w, width, height, 1); ! test_one_point_on_drawable (pixmap, black_bitmap_gc, 1); ! for (function = GDK_COPY; function <= GDK_SET; function++) ! { ! gdk_gc_set_function (black_bitmap_gc, function); ! test_one_point_on_drawable (pixmap, black_bitmap_gc, 1); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! static void ! test_one_line_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth, ! gboolean horisontal) ! { ! GdkImage *oldimage, *newimage; ! GdkGCValues gcvalues; ! gint line_width; ! gint w, h; ! gint w_up, w_down, w_left, w_right; ! gint x, y; ! guint32 oldpixel, newpixel, mask; ! ! gdk_gc_get_values (gc, &gcvalues); ! line_width = gcvalues.line_width > 0 ? gcvalues.line_width : 1; ! w_up = w_left = line_width/2; ! w_down = w_right = (line_width & 1) ? line_width/2 : line_width/2-1; ! gdk_window_get_size (drawable, &w, &h); ! oldimage = gdk_image_get (drawable, 0, 0, w, h); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! if (horisontal) ! { ! const gint x1 = 10; ! const gint y1 = 10; ! const gint x2 = 13; ! const gint y2 = y1; ! ! gdk_draw_line (drawable, gc, x1, y1, x2, y2); ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! for (x = x1-1; x <= x2+1; x++) ! for (y = y1-w_up-1; y <= y1+w_down+1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! if (x >= x1 && x < x2 && y >= y1-w_up && y <= y1+w_down) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! } ! else /* vertical */ ! { ! const gint x1 = 10; ! const gint y1 = 10; ! const gint x2 = 10; ! const gint y2 = 13; ! ! gdk_draw_line (drawable, gc, x1, y1, x2, y2); ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! for (x = x1-w_left-1; x <= x1+w_right+1; x++) ! for (y = y1-1; y <= y2+1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! if (x >= x1-w_left && x <= x1+w_right && y >= y1 && y < y2) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! } ! ! gdk_image_destroy (oldimage); ! gdk_image_destroy (newimage); ! } ! ! /* Test drawing lines. ! */ ! static void ! test_lines (void) ! { ! GdkPixmap *pixmap; ! GdkFunction function; ! gint width; ! int i, j; ! gboolean horisontal = TRUE; ! ! pixmap = gdk_pixmap_new (w, 30, 30, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! for (width = 1; width <= 4; width++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, 30, 30); ! gdk_gc_set_function (gcs[j], function); ! gdk_gc_set_line_attributes (gcs[j], width, ! GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); ! test_one_line_on_drawable (pixmap, gcs[j], system_visual->depth, ! horisontal); ! /* Toggle between horisontal and vertical... */ ! horisontal = !horisontal; ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! static void ! test_one_rectangle_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth, ! gboolean filled) ! { ! GdkImage *oldimage, *newimage; ! GdkGCValues gcvalues; ! gint line_width; ! gint w, h; ! gint w_up, w_down, w_left, w_right; ! gint x, y; ! guint32 oldpixel, newpixel, mask; ! const gint x0 = 10; ! const gint y0 = 13; ! const gint width = 7; ! const gint height = 9; ! ! gdk_gc_get_values (gc, &gcvalues); ! ! if (!filled) ! { ! line_width = gcvalues.line_width > 0 ? gcvalues.line_width : 1; ! w_up = w_left = line_width/2; ! w_down = w_right = (line_width & 1) ? line_width/2 : line_width/2-1; ! } ! ! gdk_window_get_size (drawable, &w, &h); ! oldimage = gdk_image_get (drawable, 0, 0, w, h); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! gdk_draw_rectangle (drawable, gc, filled, x0, y0, width, height); ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! ! for (x = x0 - 1; x <= x0 + width + 1; x++) ! for (y = y0 - 1; y < y0 + height + 1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! ! if (filled) ! { ! if (x >= x0 && x < x0+width && ! y >= y0 && y < y0+height) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! else ! { ! if ((x >= x0-w_left && x <= x0+width+w_right && ! y >= y0-w_up && y <= y0+w_down) || ! (x >= x0-w_left && x <= x0+width+w_right && ! y >= y0+height-w_up && y <= y0+height+w_down) || ! (x >= x0-w_left && x <= x0+w_right && ! y >= y0-w_up && y <= y0+height+w_down) || ! (x >= x0+width-w_left && x <= x0+width+w_right && ! y >= y0-w_up && y <= y0+height+w_down)) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! } ! ! gdk_image_destroy (oldimage); ! gdk_image_destroy (newimage); ! } ! ! /* Test drawing rectangles. ! */ ! static void ! test_rectangles (void) ! { ! GdkPixmap *pixmap; ! GdkFunction function; ! gint width; ! int i, j; ! gboolean filled = FALSE; ! ! pixmap = gdk_pixmap_new (w, 30, 30, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! for (width = 1; width <= 4; width++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, 30, 30); ! gdk_gc_set_function (gcs[j], function); ! gdk_gc_set_line_attributes (gcs[j], width, ! GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); ! test_one_rectangle_on_drawable (pixmap, gcs[j], ! system_visual->depth, filled); ! filled = !filled; ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! static void ! test_some_arcs_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth, ! gboolean filled) ! { ! GdkImage *oldimage, *newimage; ! GdkGCValues gcvalues; ! gint line_width; ! gint w, h; ! gint w_up, w_down, w_left, w_right; ! gint x, y; ! guint32 oldpixel, newpixel, mask; ! /* XXX */ ! const gint x0 = 10; ! const gint y0 = 13; ! const gint width = 7; ! const gint height = 9; ! ! gdk_gc_get_values (gc, &gcvalues); ! ! if (!filled) ! { ! line_width = gcvalues.line_width > 0 ? gcvalues.line_width : 1; ! w_up = w_left = line_width/2; ! w_down = w_right = (line_width & 1) ? line_width/2 : line_width/2-1; ! } ! ! gdk_window_get_size (drawable, &w, &h); ! oldimage = gdk_image_get (drawable, 0, 0, w, h); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! /* XXX */ ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! ! for (x = x0 - 1; x <= x0 + width + 1; x++) ! for (y = y0 - 1; y < y0 + height + 1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! ! if (filled) ! { ! /* XXX */ ! } ! else ! { ! /* XXX */ ! } ! } ! ! gdk_image_destroy (oldimage); ! gdk_image_destroy (newimage); ! } ! ! /* Test drawing arcs. Results don't have to be exactly as on X11, ! * but "close". ! */ ! static void ! test_arcs (void) ! { ! GdkPixmap *pixmap; ! GdkFunction function; ! gint width; ! int i, j; ! gboolean filled = FALSE; ! ! pixmap = gdk_pixmap_new (w, 30, 30, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! for (width = 1; width <= 4; width++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, 30, 30); ! gdk_gc_set_function (gcs[j], function); ! gdk_gc_set_line_attributes (gcs[j], width, ! GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); ! test_some_arcs_on_drawable (pixmap, gcs[j], system_visual->depth, ! filled); ! filled = !filled; ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! /* Test region operations. ! */ ! static void ! test_regions (void) ! { ! } ! ! static void ! tests (void) ! { ! srand (time (NULL)); ! ! test_visuals (); ! test_first_window (); ! test_colourmaps (); ! test_colours (); ! test_gcs (); ! test_pixmaps (1); ! test_pixmaps (system_visual->depth); ! if (best_visual->depth != system_visual->depth) ! test_pixmaps (best_visual->depth); ! test_images (); ! test_temp_windows (); ! test_points (); ! test_lines (); ! test_rectangles (); ! test_arcs (); ! test_regions (); ! } ! ! int ! main (int argc, char **argv) ! { ! GLogLevelFlags fatal_mask; ! ! gdk_init (&argc, &argv); ! ! fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); ! fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; ! g_log_set_always_fatal (fatal_mask); ! ! tests (); ! ! return return_value; ! } --- 1,931 ---- ! /* testgdk -- validation program for GDK ! * Copyright (C) 2000 Tor Lillqvist ! * ! * 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. ! */ ! ! /* This program is intended to be used to validate the correctness of ! * the basic graphics operations in a GDK backend. The results of the ! * operations are compared against those produced by a correctly ! * functioning X11 backend (and X11 server). ! * ! * Obviously, only the most basic operations reasonably be expected to ! * produce pixel-by-pixel identical results as the X11 backend. We ! * don't even try to test the correctness of ellipses, tiles or ! * stipples. Not to mention fonts. ! * ! * But, for those operations we do test, we should try to test quite ! * many combinations of parameters. ! * ! * This is just a quick hack, and could be improved a lot. There are ! * copy-pasted code snippets all over that need to be factored out ! * into separate functions. ! */ ! ! #include ! #include ! #include ! #include ! ! #include ! ! /* CQTESTF -- "Conditionally Quiet TEST with Fail message" ! * macro that prints PASS or FAIL messages ! * parms: quiet: if TRUE, only print FAIL messages ! * expr: the expression to test ! * failfmt:if expr is FALSE, print this message ! * (both format and args) ! */ ! ! #define CQTESTF(quiet, expr, failfmt) \ ! (tmpb = (expr), \ ! (tmpb ? (quiet ? 0 : printf ("PASS: %d %s\n", __LINE__, #expr)) \ ! : (printf ("FAIL: %d %s", __LINE__, #expr), \ ! printf failfmt, \ ! printf ("\n"), \ ! retval = FALSE, \ ! error (), \ ! return_value++)), \ ! tmpb) ! ! /* Variations with less parms */ ! ! #define CQTEST(quiet, expr) \ ! CQTESTF (quiet, expr, ("")) ! ! #define TEST(expr) \ ! CQTEST (FALSE, expr) ! ! #define QTEST(expr) \ ! CQTEST (TRUE, expr) ! ! #define TESTF(expr, failfmt) \ ! CQTESTF (FALSE, expr, failfmt) ! ! #define QTESTF(expr, failfmt) \ ! CQTESTF (TRUE, expr, failfmt) ! ! #ifndef _DEBUG ! #define ASSERT(expr) \ ! do { \ ! if (!QTEST (expr)) \ ! printf ("That is fatal. Goodbye\n"), exit (1);\ ! } while (0) ! #else ! static void ! my_break() ! { ! G_BREAKPOINT(); ! } ! #define ASSERT(expr) \ ! do { \ ! if (!QTEST (expr)) \ ! printf ("That is fatal. Goodbye\n"), my_break();\ ! } while (0) ! #endif ! ! #define N(a) (sizeof(a)/sizeof(*a)) ! ! static int return_value = 0; ! ! static gboolean retval; ! static gboolean tmpb; ! ! static GdkVisual *system_visual; ! static GdkVisual *best_visual; ! static GdkWindow *w; ! ! static GdkColormap *system_colourmap; ! ! static GdkColor white, black, red, green, blue, rand1_colour, rand2_colour; ! ! static GdkGC *black_gc, *white_gc, *red_gc, *rand1_gc, *rand2_gc; ! static GdkGC *gcs[5]; ! static GdkGC *black_bitmap_gc; ! ! static int ! error (void) ! { ! /* Place breakpoint here to catch failures */ ! return 0; ! } ! ! static gboolean ! test_visual_coherency (gboolean quiet, ! GdkVisual *visual) ! { ! gboolean retval = TRUE; ! ! CQTEST (quiet, visual->type >= GDK_VISUAL_STATIC_GRAY && ! visual->type <= GDK_VISUAL_DIRECT_COLOR); ! CQTEST (quiet, visual->depth >= 1 && visual->depth <= 32); ! CQTEST (quiet, visual->byte_order == GDK_LSB_FIRST || visual->byte_order == ! GDK_MSB_FIRST); ! ! return retval; ! } ! ! /* Test visuals ! */ ! static void ! test_visuals (void) ! { ! GdkVisual *visual; ! GList *visuals; ! ! system_visual = gdk_visual_get_system (); ! ASSERT (system_visual != NULL); ! TEST (test_visual_coherency (FALSE, system_visual)); ! ! best_visual = gdk_visual_get_best (); ! if (best_visual != system_visual) ! TEST (test_visual_coherency (TRUE, best_visual)); ! ! visuals = gdk_list_visuals (); ! while (visuals) ! { ! visual = visuals->data; ! TEST (test_visual_coherency (TRUE, visual)); ! visuals = visuals->next; ! } ! } ! ! /* Create a top-level window used by other tests ! */ ! static void ! test_first_window (void) ! { ! GdkWindowAttr wa; ! ! wa.width = 100; ! wa.height = 100; ! wa.window_type = GDK_WINDOW_TOPLEVEL; ! wa.wclass = GDK_INPUT_OUTPUT; ! ! w = gdk_window_new (NULL, &wa, 0); ! ! ASSERT (w != NULL); ! } ! ! /* Test colourmaps. ! */ ! static void ! test_colourmaps (void) ! { ! system_colourmap = gdk_colormap_get_system (); ! ASSERT (system_colourmap != NULL); ! } ! ! /* Test colours. ! */ ! static void ! test_colours (void) ! { ! ASSERT (gdk_color_white (system_colourmap, &white)); ! ASSERT (gdk_color_black (system_colourmap, &black)); ! red.red = 65535; ! red.green = red.blue = 0; ! TEST (gdk_colormap_alloc_color (system_colourmap, &red, FALSE, TRUE)); ! ! rand1_colour.red = rand () % 65536; ! rand1_colour.green = rand () % 65536; ! rand1_colour.blue = rand () % 65536; ! TEST (gdk_colormap_alloc_color (system_colourmap, &rand1_colour, FALSE, ! TRUE)); ! ! rand2_colour.red = rand () % 65536; ! rand2_colour.green = rand () % 65536; ! rand2_colour.blue = rand () % 65536; ! TEST (gdk_colormap_alloc_color (system_colourmap, &rand2_colour, FALSE, ! TRUE)); ! } ! ! static gboolean ! test_default_gc (GdkGCValues *gcvalues, ! gboolean quiet) ! { ! gboolean retval = TRUE; ! ! CQTEST (quiet, gcvalues->foreground.pixel == 0); ! CQTEST (quiet, gcvalues->background.pixel == 1); ! CQTEST (quiet, gcvalues->function == GDK_COPY); ! CQTEST (quiet, gcvalues->fill == GDK_SOLID); ! CQTEST (quiet, gcvalues->tile == NULL); ! CQTEST (quiet, gcvalues->stipple == NULL); ! CQTEST (quiet, gcvalues->clip_mask == NULL); ! CQTEST (quiet, gcvalues->subwindow_mode == GDK_CLIP_BY_CHILDREN); ! CQTEST (quiet, gcvalues->line_width == 0); ! CQTEST (quiet, gcvalues->line_style == GDK_LINE_SOLID); ! CQTEST (quiet, gcvalues->cap_style == GDK_CAP_BUTT); ! CQTEST (quiet, gcvalues->join_style == GDK_JOIN_MITER); ! ! return retval; ! } ! ! /* Create GdkGCs with various values, ! * check that gdk_gc_get_values returns the same, ! * or something reasonably close. ! */ ! static void ! test_gcs (void) ! { ! GdkPixmap *pixmap; ! GdkGC *gc; ! GdkGCValues gcvalues; ! GdkColor colour; ! GdkFunction function; ! GdkFill fill; ! gboolean retval; ! ! gc = gdk_gc_new (w); ! gdk_gc_get_values (gc, &gcvalues); ! test_default_gc (&gcvalues, FALSE); ! ! colour.pixel = 1234; ! gdk_gc_set_foreground (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == 1234); ! ! colour.pixel = 0; ! gdk_gc_set_foreground (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (test_default_gc (&gcvalues, TRUE)); ! ! colour.pixel = 5678; ! gdk_gc_set_background (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (gcvalues.background.pixel == 5678); ! ! colour.pixel = 1; ! gdk_gc_set_background (gc, &colour); ! gdk_gc_get_values (gc, &gcvalues); ! TEST (test_default_gc (&gcvalues, TRUE)); ! ! retval = TRUE; ! for (function = GDK_COPY; function <= GDK_SET; function++) ! { ! gdk_gc_set_function (gc, function); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (gcvalues.function == function); ! gdk_gc_set_function (gc, GDK_COPY); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (test_default_gc (&gcvalues, TRUE)); ! } ! TEST (retval); ! ! retval = TRUE; ! for (fill = GDK_SOLID; fill <= GDK_OPAQUE_STIPPLED; fill++) ! { ! gdk_gc_set_fill (gc, fill); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (gcvalues.fill == fill); ! gdk_gc_set_fill (gc, GDK_SOLID); ! gdk_gc_get_values (gc, &gcvalues); ! QTEST (test_default_gc (&gcvalues, TRUE)); ! } ! TEST (retval); ! ! black_gc = gdk_gc_new (w); ! gdk_gc_copy (black_gc, gc); ! gdk_gc_get_values (black_gc, &gcvalues); ! TEST (test_default_gc (&gcvalues, TRUE)); ! gdk_gc_unref (gc); ! ! gdk_gc_set_foreground (black_gc, &black); ! gdk_gc_get_values (black_gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == black.pixel); ! ! white_gc = gdk_gc_new (w); ! ! gdk_gc_set_foreground (white_gc, &white); ! gdk_gc_get_values (white_gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == white.pixel); ! ! red_gc = gdk_gc_new (w); ! gdk_gc_set_foreground (red_gc, &red); ! gdk_gc_get_values (red_gc, &gcvalues); ! TEST (gcvalues.foreground.pixel == red.pixel); ! ! rand1_gc = gdk_gc_new (w); ! gdk_gc_set_foreground (rand1_gc, &rand1_colour); ! gdk_gc_get_values (rand1_gc, &gcvalues); ! TESTF (gcvalues.foreground.pixel == rand1_colour.pixel, ! (" %#06x != %#06x", gcvalues.foreground.pixel, rand1_colour.pixel)); ! ! rand2_gc = gdk_gc_new (w); ! gdk_gc_set_foreground (rand2_gc, &rand2_colour); ! gdk_gc_get_values (rand2_gc, &gcvalues); ! TESTF (gcvalues.foreground.pixel == rand2_colour.pixel, ! (" %#06x != %#06x", gcvalues.foreground.pixel, rand2_colour.pixel)); ! ! gcs[0] = black_gc; ! gcs[1] = white_gc; ! gcs[2] = red_gc; ! gcs[3] = rand1_gc; ! gcs[4] = rand2_gc; ! ! pixmap = gdk_pixmap_new (NULL, 1, 1, 1); ! black_bitmap_gc = gdk_gc_new (pixmap); ! gdk_pixmap_unref (pixmap); ! } ! ! /* Create pixmaps, check that properties are as expected. ! * No graphic operations tested yet. ! */ ! static void ! test_pixmaps (gint depth) ! { ! GdkPixmap *pixmap; ! GdkImage *image; ! GdkGC *gc; ! gint width, height; ! gint w, h; ! gboolean retval = TRUE; ! ! for (width = 1; width <= 64; width += 2) ! for (height = 1; height <= 32; height += 3) ! { ! pixmap = gdk_pixmap_new (NULL, width, height, depth); ! ASSERT (pixmap != NULL); ! gdk_window_get_size (pixmap, &w, &h); ! QTESTF (w == width, (" w:%d", w)); ! QTESTF (h == height, (" h:%d", h)); ! image = gdk_image_get (pixmap, 0, 0, w, h); ! QTEST (image != NULL); ! QTEST (image->width == width); ! QTEST (image->height == height); ! QTEST (image->depth == depth); ! gdk_image_destroy (image); ! gdk_pixmap_unref (pixmap); ! } ! TEST (retval); ! } ! ! /* Ditto for images. ! */ ! static void ! test_images (void) ! { ! GdkImage *image; ! GdkImageType image_type; ! gint width, height; ! gboolean retval = TRUE; ! ! for (width = 1; width <= 64; width += 3) ! for (height = 1; height <= 32; height += 7) ! for (image_type = GDK_IMAGE_NORMAL; ! image_type <= GDK_IMAGE_FASTEST; ! image_type++) ! { ! image = gdk_image_new (image_type, system_visual, width, height); ! if (image == NULL && image_type == GDK_IMAGE_SHARED) ! /* Ignore failure to create shared image, ! * display might not be local. ! */ ! ; ! else ! { ! ASSERT (image != NULL); ! QTEST (image->width == width); ! QTEST (image->height == height); ! QTEST (image->depth == system_visual->depth); ! QTEST (image->bpp >= (image->depth-1)/8 + 1); ! QTEST (image->mem != NULL); ! gdk_image_destroy (image); ! } ! } ! TEST (retval); ! } ! ! /* Test creating temp windows. ! */ ! static void ! test_temp_windows (void) ! { ! GdkWindow *window; ! GdkWindowAttr wa; ! GdkVisual *visual; ! gint width, height; ! gint w, h, x, y, d; ! gboolean retval = TRUE; ! ! wa.window_type = GDK_WINDOW_TEMP; ! wa.wclass = GDK_INPUT_OUTPUT; ! ! for (width = 1; width <= 64; width += 4) ! for (height = 1; height <= 32; height += 7) ! { ! wa.width = width; ! wa.height = height; ! window = gdk_window_new (NULL, &wa, 0); ! ASSERT (window != NULL); ! gdk_window_get_geometry (window, &x, &y, &w, &h, &d); ! QTESTF (w == width, ("w:%d", w)); ! QTESTF (h == height, ("h:%d", h)); ! gdk_window_show (window); ! gdk_window_get_geometry (window, &x, &y, &w, &h, &d); ! QTESTF (w == width, ("w:%d", w)); ! QTESTF (h == height, ("h:%d", h)); ! gdk_window_resize (window, 37, 19); ! gdk_window_get_geometry (window, &x, &y, &w, &h, &d); ! QTESTF (w == 37, ("w:%d", w)); ! QTESTF (h == 19, ("h:%d", h)); ! visual = gdk_window_get_visual (window); ! QTEST (visual == system_visual); ! gdk_window_hide (window); ! gdk_window_unref (window); ! } ! TEST (retval); ! } ! ! static void ! test_gc_function (GdkFunction function, ! guint32 oldpixel, ! guint32 newpixel, ! guint32 foreground, ! guint32 mask) ! { ! switch (function) ! { ! case GDK_COPY: ! QTEST (newpixel == (foreground & mask)); break; ! case GDK_INVERT: ! QTEST (newpixel == ((~oldpixel) & mask)); break; ! case GDK_XOR: ! QTEST (newpixel == ((oldpixel ^ foreground) & mask)); break; ! case GDK_CLEAR: ! QTEST (newpixel == 0); break; ! case GDK_AND: ! QTEST (newpixel == ((oldpixel & foreground) & mask)); break; ! case GDK_AND_REVERSE: ! QTEST (newpixel == (((~oldpixel) & foreground) & mask)); break; ! case GDK_AND_INVERT: ! QTEST (newpixel == ((oldpixel & (~foreground)) & mask)); break; ! case GDK_NOOP: ! QTEST (newpixel == (oldpixel & mask)); break; ! case GDK_OR: ! QTEST (newpixel == ((oldpixel | foreground) & mask)); break; ! case GDK_EQUIV: ! QTEST (newpixel == ((oldpixel ^ (~foreground)) & mask)); break; ! case GDK_OR_REVERSE: ! QTEST (newpixel == (((~oldpixel) | foreground) & mask)); break; ! case GDK_COPY_INVERT: ! QTEST (newpixel == ((~foreground) & mask)); break; ! case GDK_OR_INVERT: ! QTEST (newpixel == ((oldpixel | (~foreground)) & mask)); break; ! case GDK_NAND: ! QTEST (newpixel == (((~oldpixel) | (~foreground)) & mask)); break; ! #ifdef GDK_NOR ! case GDK_NOR: ! QTEST (newpixel == (~oldpixel & ~mask)); break; ! #endif ! case GDK_SET: ! QTEST (newpixel == ((~0) & mask)); break; ! default: ! ASSERT (FALSE); ! } ! } ! ! static void ! test_one_point_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth) ! { ! GdkImage *image; ! GdkGCValues gcvalues; ! gint xoff, yoff; ! guint32 oldpixels[3][3], newpixel, mask; ! const gint x = 4; ! const gint y = 5; ! ! gdk_gc_get_values (gc, &gcvalues); ! ! image = gdk_image_get (drawable, x+-1, y+-1, 3, 3); ! QTEST (image != NULL); ! for (xoff = -1; xoff <= 1; xoff++) ! for (yoff = -1; yoff <= 1; yoff++) ! { ! oldpixels[xoff+1][yoff+1] = gdk_image_get_pixel (image, xoff+1, yoff+1); ! } ! gdk_image_destroy (image); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! gdk_draw_point (drawable, gc, x, y); ! ! image = gdk_image_get (drawable, x-1, y-1, 3, 3); ! QTEST (image != NULL); ! for (xoff = -1; xoff <= 1; xoff++) ! for (yoff = -1; yoff <= 1; yoff++) ! { ! newpixel = gdk_image_get_pixel (image, xoff+1, yoff+1); ! if (xoff == 0 && yoff == 0) ! test_gc_function (gcvalues.function, oldpixels[1][1], newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (newpixel == oldpixels[xoff+1][yoff+1]); ! } ! gdk_image_destroy (image); ! } ! ! ! /* Test drawing points. ! */ ! static void ! test_points (void) ! { ! GdkPixmap *pixmap; ! GdkWindow *window; ! GdkFunction function; ! gint width, height; ! int i, j; ! ! width = 8; ! height = 8; ! pixmap = gdk_pixmap_new (w, width, height, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, width, height); ! gdk_gc_set_function (gcs[j], function); ! test_one_point_on_drawable (pixmap, gcs[j], system_visual->depth); ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! ! pixmap = gdk_pixmap_new (w, width, height, 1); ! test_one_point_on_drawable (pixmap, black_bitmap_gc, 1); ! for (function = GDK_COPY; function <= GDK_SET; function++) ! { ! gdk_gc_set_function (black_bitmap_gc, function); ! test_one_point_on_drawable (pixmap, black_bitmap_gc, 1); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! static void ! test_one_line_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth, ! gboolean horisontal) ! { ! GdkImage *oldimage, *newimage; ! GdkGCValues gcvalues; ! gint line_width; ! gint w, h; ! gint w_up, w_down, w_left, w_right; ! gint x, y; ! guint32 oldpixel, newpixel, mask; ! ! gdk_gc_get_values (gc, &gcvalues); ! line_width = gcvalues.line_width > 0 ? gcvalues.line_width : 1; ! w_up = w_left = line_width/2; ! w_down = w_right = (line_width & 1) ? line_width/2 : line_width/2-1; ! gdk_window_get_size (drawable, &w, &h); ! oldimage = gdk_image_get (drawable, 0, 0, w, h); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! if (horisontal) ! { ! const gint x1 = 10; ! const gint y1 = 10; ! const gint x2 = 13; ! const gint y2 = y1; ! ! gdk_draw_line (drawable, gc, x1, y1, x2, y2); ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! for (x = x1-1; x <= x2+1; x++) ! for (y = y1-w_up-1; y <= y1+w_down+1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! if (x >= x1 && x < x2 && y >= y1-w_up && y <= y1+w_down) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! } ! else /* vertical */ ! { ! const gint x1 = 10; ! const gint y1 = 10; ! const gint x2 = 10; ! const gint y2 = 13; ! ! gdk_draw_line (drawable, gc, x1, y1, x2, y2); ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! for (x = x1-w_left-1; x <= x1+w_right+1; x++) ! for (y = y1-1; y <= y2+1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! if (x >= x1-w_left && x <= x1+w_right && y >= y1 && y < y2) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! } ! ! gdk_image_destroy (oldimage); ! gdk_image_destroy (newimage); ! } ! ! /* Test drawing lines. ! */ ! static void ! test_lines (void) ! { ! GdkPixmap *pixmap; ! GdkFunction function; ! gint width; ! int i, j; ! gboolean horisontal = TRUE; ! ! pixmap = gdk_pixmap_new (w, 30, 30, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! for (width = 1; width <= 4; width++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, 30, 30); ! gdk_gc_set_function (gcs[j], function); ! gdk_gc_set_line_attributes (gcs[j], width, ! GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); ! test_one_line_on_drawable (pixmap, gcs[j], system_visual->depth, ! horisontal); ! /* Toggle between horisontal and vertical... */ ! horisontal = !horisontal; ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! static void ! test_one_rectangle_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth, ! gboolean filled) ! { ! GdkImage *oldimage, *newimage; ! GdkGCValues gcvalues; ! gint line_width; ! gint w, h; ! gint w_up, w_down, w_left, w_right; ! gint x, y; ! guint32 oldpixel, newpixel, mask; ! const gint x0 = 10; ! const gint y0 = 13; ! const gint width = 7; ! const gint height = 9; ! ! gdk_gc_get_values (gc, &gcvalues); ! ! if (!filled) ! { ! line_width = gcvalues.line_width > 0 ? gcvalues.line_width : 1; ! w_up = w_left = line_width/2; ! w_down = w_right = (line_width & 1) ? line_width/2 : line_width/2-1; ! } ! ! gdk_window_get_size (drawable, &w, &h); ! oldimage = gdk_image_get (drawable, 0, 0, w, h); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! gdk_draw_rectangle (drawable, gc, filled, x0, y0, width, height); ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! ! for (x = x0 - 1; x <= x0 + width + 1; x++) ! for (y = y0 - 1; y < y0 + height + 1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! ! if (filled) ! { ! if (x >= x0 && x < x0+width && ! y >= y0 && y < y0+height) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! else ! { ! if ((x >= x0-w_left && x <= x0+width+w_right && ! y >= y0-w_up && y <= y0+w_down) || ! (x >= x0-w_left && x <= x0+width+w_right && ! y >= y0+height-w_up && y <= y0+height+w_down) || ! (x >= x0-w_left && x <= x0+w_right && ! y >= y0-w_up && y <= y0+height+w_down) || ! (x >= x0+width-w_left && x <= x0+width+w_right && ! y >= y0-w_up && y <= y0+height+w_down)) ! test_gc_function (gcvalues.function, oldpixel, newpixel, ! gcvalues.foreground.pixel, mask); ! else ! QTEST (oldpixel == newpixel); ! } ! } ! ! gdk_image_destroy (oldimage); ! gdk_image_destroy (newimage); ! } ! ! /* Test drawing rectangles. ! */ ! static void ! test_rectangles (void) ! { ! GdkPixmap *pixmap; ! GdkFunction function; ! gint width; ! int i, j; ! gboolean filled = FALSE; ! ! pixmap = gdk_pixmap_new (w, 30, 30, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! for (width = 1; width <= 4; width++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, 30, 30); ! gdk_gc_set_function (gcs[j], function); ! gdk_gc_set_line_attributes (gcs[j], width, ! GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); ! test_one_rectangle_on_drawable (pixmap, gcs[j], ! system_visual->depth, filled); ! filled = !filled; ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! static void ! test_some_arcs_on_drawable (GdkDrawable *drawable, ! GdkGC *gc, ! int depth, ! gboolean filled) ! { ! GdkImage *oldimage, *newimage; ! GdkGCValues gcvalues; ! gint line_width; ! gint w, h; ! gint w_up, w_down, w_left, w_right; ! gint x, y; ! guint32 oldpixel, newpixel, mask; ! /* XXX */ ! const gint x0 = 10; ! const gint y0 = 13; ! const gint width = 7; ! const gint height = 9; ! ! gdk_gc_get_values (gc, &gcvalues); ! ! if (!filled) ! { ! line_width = gcvalues.line_width > 0 ? gcvalues.line_width : 1; ! w_up = w_left = line_width/2; ! w_down = w_right = (line_width & 1) ? line_width/2 : line_width/2-1; ! } ! ! gdk_window_get_size (drawable, &w, &h); ! oldimage = gdk_image_get (drawable, 0, 0, w, h); ! ! if (depth == 32) ! mask = 0xFFFFFFFF; ! else ! mask = (1 << depth) - 1; ! ! /* XXX */ ! newimage = gdk_image_get (drawable, 0, 0, w, h); ! ! for (x = x0 - 1; x <= x0 + width + 1; x++) ! for (y = y0 - 1; y < y0 + height + 1; y++) ! { ! oldpixel = gdk_image_get_pixel (oldimage, x, y); ! newpixel = gdk_image_get_pixel (newimage, x, y); ! ! if (filled) ! { ! /* XXX */ ! } ! else ! { ! /* XXX */ ! } ! } ! ! gdk_image_destroy (oldimage); ! gdk_image_destroy (newimage); ! } ! ! /* Test drawing arcs. Results don't have to be exactly as on X11, ! * but "close". ! */ ! static void ! test_arcs (void) ! { ! GdkPixmap *pixmap; ! GdkFunction function; ! gint width; ! int i, j; ! gboolean filled = FALSE; ! ! pixmap = gdk_pixmap_new (w, 30, 30, -1); ! ! for (i = 0; i < N(gcs); i++) ! for (j = 0; j < N(gcs); j++) ! for (function = GDK_COPY; function <= GDK_SET; function++) ! for (width = 1; width <= 4; width++) ! { ! gdk_draw_rectangle (pixmap, gcs[i], TRUE, 0, 0, 30, 30); ! gdk_gc_set_function (gcs[j], function); ! gdk_gc_set_line_attributes (gcs[j], width, ! GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); ! test_some_arcs_on_drawable (pixmap, gcs[j], system_visual->depth, ! filled); ! filled = !filled; ! gdk_gc_set_function (gcs[j], GDK_COPY); ! } ! ! gdk_pixmap_unref (pixmap); ! } ! ! /* Test region operations. ! */ ! static void ! test_regions (void) ! { ! } ! ! static void ! tests (void) ! { ! srand (time (NULL)); ! ! test_visuals (); ! test_first_window (); ! test_colourmaps (); ! test_colours (); ! test_gcs (); ! test_pixmaps (1); ! test_pixmaps (system_visual->depth); ! if (best_visual->depth != system_visual->depth) ! test_pixmaps (best_visual->depth); ! test_images (); ! test_temp_windows (); ! test_points (); ! test_lines (); ! test_rectangles (); ! test_arcs (); ! test_regions (); ! } ! ! int ! main (int argc, char **argv) ! { ! GLogLevelFlags fatal_mask; ! ! gdk_init (&argc, &argv); ! ! fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); ! fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; ! g_log_set_always_fatal (fatal_mask); ! ! tests (); ! ! return return_value; ! } Index: win32/gdkcolor-win32.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/win32/gdkcolor-win32.c,v retrieving revision 1.10.6.3 diff -c -r1.10.6.3 gdkcolor-win32.c *** win32/gdkcolor-win32.c 2001/10/23 22:47:26 1.10.6.3 --- win32/gdkcolor-win32.c 2001/12/18 15:38:32 *************** *** 392,398 **** for (i = logPalettePtr->palNumEntries; i < colormap->sizepalette; i++) colormap->in_use[i] = FALSE; } ! ReleaseDC (NULL, hdc); return colormap; } --- 392,399 ---- for (i = logPalettePtr->palNumEntries; i < colormap->sizepalette; i++) colormap->in_use[i] = FALSE; } ! if (!ReleaseDC (NULL, hdc)) ! WIN32_GDI_FAILED ("ReleaseDC"); return colormap; } Index: win32/gdkcursor-win32.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/win32/gdkcursor-win32.c,v retrieving revision 1.14.6.4 diff -c -r1.14.6.4 gdkcursor-win32.c *** win32/gdkcursor-win32.c 2001/10/22 23:27:20 1.14.6.4 --- win32/gdkcursor-win32.c 2001/12/18 15:38:34 *************** *** 74,80 **** rv = CreateCursor (gdk_ProgInstance, cursors[i].hotx, cursors[i].hoty, w, h, ANDplane, XORplane); ! return rv; } --- 74,84 ---- rv = CreateCursor (gdk_ProgInstance, cursors[i].hotx, cursors[i].hoty, w, h, ANDplane, XORplane); ! if (rv == NULL) ! WIN32_API_FAILED ("CreateCursor"); ! g_free (ANDplane); ! g_free (XORplane); ! return rv; } *************** *** 250,255 **** --- 254,261 ---- GDK_NOTE (MISC, g_print ("_gdk_cursor_destroy: %#x\n", (guint) private->xcursor)); + if (GetCursor() == private->xcursor) + SetCursor(NULL); if (!DestroyCursor (private->xcursor)) WIN32_API_FAILED ("DestroyCursor"); Index: win32/gdkdnd-win32.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/win32/gdkdnd-win32.c,v retrieving revision 1.15.6.4 diff -c -r1.15.6.4 gdkdnd-win32.c *** win32/gdkdnd-win32.c 2001/11/15 00:08:14 1.15.6.4 --- win32/gdkdnd-win32.c 2001/12/18 15:38:37 *************** *** 1,6 **** --- 1,7 ---- /* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald * Copyright (C) 1998-1999 Tor Lillqvist + * Copyright (C) 2001 Archaeopteryx Software, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public *************** *** 25,37 **** * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ ! #include "config.h" ! #include ! /* #define OLE2_DND */ ! #define INITGUID #include "gdkdnd.h" #include "gdkproperty.h" --- 26,42 ---- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ ! /* Modified by Archaeopteryx Software 2001 to add support for OLE2 drag and drop ! * For more information, contact Stephan R.A. Deibel (sdeibel@archaeopteryx.com) ! */ ! /* Set this to use OLE2 drag and drop instead of the default dnd impl (which */ ! /* doesn't work anyway at this point on win32) */ ! #define OLE2_DND ! #include "config.h" ! #include #include "gdkdnd.h" #include "gdkproperty.h" *************** *** 63,103 **** GDK_DRAG_TARGET } GdkDragKind; - #ifdef OLE2_DND - - #define PRINT_GUID(guid) \ - g_print ("guid = %.08x-%.04x-%.04x-%.02x%.02x-%.02x%.02x%.02x%.02x%.02x%.02x", \ - ((gulong *) guid)[0], \ - ((gushort *) guid)[2], \ - ((gushort *) guid)[3], \ - ((guchar *) guid)[8], \ - ((guchar *) guid)[9], \ - ((guchar *) guid)[10], \ - ((guchar *) guid)[11], \ - ((guchar *) guid)[12], \ - ((guchar *) guid)[13], \ - ((guchar *) guid)[14], \ - ((guchar *) guid)[15]); - - - #endif /* OLE2_DND */ - /* Structure that holds information about a drag in progress. * this is used on both source and destination sides. */ struct _GdkDragContextPrivate { GdkDragContext context; - GdkAtom local_selection; guint ref_count; - guint16 last_x; /* Coordinates from last event */ - guint16 last_y; - HWND dest_xid; - guint drag_status; /* Current status of drag */ }; GdkDragContext *current_dest_drag = NULL; /* Drag Contexts */ --- 68,89 ---- GDK_DRAG_TARGET } GdkDragKind; /* Structure that holds information about a drag in progress. * this is used on both source and destination sides. */ struct _GdkDragContextPrivate { GdkDragContext context; guint ref_count; + + POINT last_pt; + DWORD last_key_state; }; GdkDragContext *current_dest_drag = NULL; + GdkWin32DndState gdk_win32_dnd_target_state = GDK_WIN32_DND_NONE; + GdkWin32DndState gdk_win32_dnd_source_state = GDK_WIN32_DND_NONE; /* Drag Contexts */ *************** *** 111,116 **** --- 97,105 ---- result = g_new0 (GdkDragContextPrivate, 1); result->ref_count = 1; + result->last_pt.x = -1; + result->last_pt.y = -1; + result->last_key_state = 0; contexts = g_list_prepend (contexts, result); *************** *** 155,533 **** } } - static GdkDragContext * - gdk_drag_context_find (gboolean is_source, - GdkWindow *source, - GdkWindow *dest) - { - GList *tmp_list = contexts; - GdkDragContext *context; - - while (tmp_list) - { - context = (GdkDragContext *)tmp_list->data; - - if ((!context->is_source == !is_source) && - ((source == NULL) || (context->source_window && (context->source_window == source))) && - ((dest == NULL) || (context->dest_window && (context->dest_window == dest)))) - return context; - - tmp_list = tmp_list->next; - } - - return NULL; - } - typedef struct { #ifdef OLE2_DND IDropTarget idt; #endif GdkDragContext *context; ! } target_drag_context; typedef struct { #ifdef OLE2_DND IDropSource ids; #endif GdkDragContext *context; ! } source_drag_context; #ifdef OLE2_DND ! ! static ULONG STDMETHODCALLTYPE ! m_add_ref_target (IDropTarget __RPC_FAR *This) ! { ! target_drag_context *ctx = (target_drag_context *) This; ! GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context; ! ! GDK_NOTE (DND, g_print ("m_add_ref_target\n")); ! gdk_drag_context_ref (ctx->context); ! ! return private->ref_count; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_query_interface_target (IDropTarget __RPC_FAR *This, ! REFIID riid, ! void __RPC_FAR *__RPC_FAR *ppvObject) ! { ! GDK_NOTE (DND, g_print ("m_query_interface_target\n")); ! ! *ppvObject = NULL; ! ! PRINT_GUID (riid); ! ! if (IsEqualGUID (riid, &IID_IUnknown)) ! { ! g_print ("...IUnknown\n"); ! m_add_ref_target (This); ! *ppvObject = This; ! return S_OK; ! } ! else if (IsEqualGUID (riid, &IID_IDropTarget)) ! { ! g_print ("...IDropTarget\n"); ! m_add_ref_target (This); ! *ppvObject = This; ! return S_OK; ! } ! else ! { ! g_print ("...Huh?\n"); ! return E_NOINTERFACE; ! } ! } ! ! static ULONG STDMETHODCALLTYPE ! m_release_target (IDropTarget __RPC_FAR *This) ! { ! target_drag_context *ctx = (target_drag_context *) This; ! GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context; ! ! GDK_NOTE (DND, g_print ("m_release_target\n")); ! gdk_drag_context_unref (ctx->context); ! ! if (private->ref_count == 1) ! { ! gdk_drag_context_unref (ctx->context); ! return 0; ! } ! else ! return private->ref_count - 1; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_drag_enter (IDropTarget __RPC_FAR *This, ! IDataObject __RPC_FAR *pDataObj, ! DWORD grfKeyState, ! POINTL pt, ! DWORD __RPC_FAR *pdwEffect) ! { ! GDK_NOTE (DND, g_print ("m_drag_enter\n")); ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_drag_over (IDropTarget __RPC_FAR *This, ! DWORD grfKeyState, ! POINTL pt, ! DWORD __RPC_FAR *pdwEffect) ! { ! GDK_NOTE (DND, g_print ("m_drag_over\n")); ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_drag_leave (IDropTarget __RPC_FAR *This) ! { ! GDK_NOTE (DND, g_print ("m_drag_leave\n")); ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_drop (IDropTarget __RPC_FAR *This, ! IDataObject __RPC_FAR *pDataObj, ! DWORD grfKeyState, ! POINTL pt, ! DWORD __RPC_FAR *pdwEffect) ! { ! GDK_NOTE (DND, g_print ("m_drop\n")); ! return E_UNEXPECTED; ! } ! ! static ULONG STDMETHODCALLTYPE ! m_add_ref_source (IDropSource __RPC_FAR *This) ! { ! source_drag_context *ctx = (source_drag_context *) This; ! GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context; ! ! GDK_NOTE (DND, g_print ("m_add_ref_source\n")); ! gdk_drag_context_ref (ctx->context); ! ! return private->ref_count; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_query_interface_source (IDropSource __RPC_FAR *This, ! REFIID riid, ! void __RPC_FAR *__RPC_FAR *ppvObject) ! { ! GDK_NOTE (DND, g_print ("m_query_interface_source\n")); ! ! *ppvObject = NULL; ! ! PRINT_GUID (riid); ! if (IsEqualGUID (riid, &IID_IUnknown)) ! { ! g_print ("...IUnknown\n"); ! m_add_ref_source (This); ! *ppvObject = This; ! return S_OK; ! } ! else if (IsEqualGUID (riid, &IID_IDropSource)) ! { ! g_print ("...IDropSource\n"); ! m_add_ref_source (This); ! *ppvObject = This; ! return S_OK; ! } ! else ! { ! g_print ("...Huh?\n"); ! return E_NOINTERFACE; ! } ! } ! ! static ULONG STDMETHODCALLTYPE ! m_release_source (IDropSource __RPC_FAR *This) ! { ! source_drag_context *ctx = (source_drag_context *) This; ! GdkDragContextPrivate *private = (GdkDragContextPrivate *) ctx->context; ! ! GDK_NOTE (DND, g_print ("m_release_source\n")); ! gdk_drag_context_unref (ctx->context); ! ! if (private->ref_count == 1) ! { ! gdk_drag_context_unref (ctx->context); ! return 0; ! } ! else ! return private->ref_count - 1; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_query_continue_drag (IDropSource __RPC_FAR *This, ! BOOL fEscapePressed, ! DWORD grfKeyState) ! { ! GDK_NOTE (DND, g_print ("m_query_continue_drag\n")); ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_give_feedback (IDropSource __RPC_FAR *This, ! DWORD dwEffect) ! { ! GDK_NOTE (DND, g_print ("m_give_feedback\n")); ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_query_interface_object (IDataObject __RPC_FAR *This, ! REFIID riid, ! void __RPC_FAR *__RPC_FAR *ppvObject) ! { ! return E_UNEXPECTED; ! } ! ! static ULONG STDMETHODCALLTYPE ! m_add_ref_object (IDataObject __RPC_FAR *This) ! { ! return E_UNEXPECTED; ! } ! ! static ULONG STDMETHODCALLTYPE ! m_release_object (IDataObject __RPC_FAR *This) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_get_data (IDataObject __RPC_FAR *This, ! FORMATETC *pFormatEtc, ! STGMEDIUM *pMedium) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_get_data_here (IDataObject __RPC_FAR *This, ! FORMATETC *pFormatEtc, ! STGMEDIUM *pMedium) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_query_get_data (IDataObject __RPC_FAR *This, ! FORMATETC *pFormatEtc) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_get_canonical_format_etc (IDataObject __RPC_FAR *This, ! FORMATETC *pFormatEtcIn, ! FORMATETC *pFormatEtcOut) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_set_data (IDataObject __RPC_FAR *This, ! FORMATETC *pFormatEtc, ! STGMEDIUM *pMedium, ! BOOL fRelease) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_enum_format_etc (IDataObject __RPC_FAR *This, ! DWORD dwDirection, ! IEnumFORMATETC **ppEnumFormatEtc) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_d_advise (IDataObject __RPC_FAR *This, ! FORMATETC *pFormatetc, ! DWORD advf, ! IAdviseSink *pAdvSink, ! DWORD *pdwConnection) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_d_unadvise (IDataObject __RPC_FAR *This, ! DWORD dwConnection) ! { ! return E_UNEXPECTED; ! } ! ! static HRESULT STDMETHODCALLTYPE ! m_enum_d_advise (IDataObject __RPC_FAR *This, ! IEnumSTATDATA **ppenumAdvise) ! { ! return E_UNEXPECTED; ! } ! ! static IDropTargetVtbl idt_vtbl = { ! m_query_interface_target, ! m_add_ref_target, ! m_release_target, ! m_drag_enter, ! m_drag_over, ! m_drag_leave, ! m_drop ! }; ! ! static IDropSourceVtbl ids_vtbl = { ! m_query_interface_source, ! m_add_ref_source, ! m_release_source, ! m_query_continue_drag, ! m_give_feedback ! }; ! ! static IDataObjectVtbl ido_vtbl = { ! m_query_interface_object, ! m_add_ref_object, ! m_release_object, ! m_get_data, ! m_get_data_here, ! m_query_get_data, ! m_get_canonical_format_etc, ! m_set_data, ! m_enum_format_etc, ! m_d_advise, ! m_d_unadvise, ! m_enum_d_advise ! }; ! ! #endif /* OLE2_DND */ ! static target_drag_context * ! target_context_new (void) { ! target_drag_context *result; ! result = g_new0 (target_drag_context, 1); #ifdef OLE2_DND result->idt.lpVtbl = &idt_vtbl; - #endif result->context = gdk_drag_context_new (); return result; } ! static source_drag_context * source_context_new (void) { ! source_drag_context *result; ! result = g_new0 (source_drag_context, 1); #ifdef OLE2_DND result->ids.lpVtbl = &ids_vtbl; #endif result->context = gdk_drag_context_new (); return result; } --- 144,252 ---- } } typedef struct { #ifdef OLE2_DND IDropTarget idt; #endif + gint ref_count; GdkDragContext *context; ! } GdkOle2DragTarget; typedef struct { #ifdef OLE2_DND IDropSource ids; #endif + gint ref_count; GdkDragContext *context; ! } GdkOle2DragSource; + /* Include OLE2 support machinery only if used */ #ifdef OLE2_DND ! #include "gdkdnd-ole2-win32.c" ! #endif ! static GdkOle2DragTarget * ! target_context_new (GdkWindow *window) { ! GdkOle2DragTarget *result; ! #ifdef OLE2_DND ! static GdkAtom string_atom = GDK_NONE; ! static GdkAtom text_atom = GDK_NONE; ! static GdkAtom text_uri_list_atom = GDK_NONE; ! static GdkAtom compound_text_atom = GDK_NONE; ! static GdkAtom pixmap_atom = GDK_NONE; ! static GdkAtom bitmap_atom = GDK_NONE; ! int i; ! #endif ! result = g_new0 (GdkOle2DragTarget, 1); ! result->ref_count = 1; #ifdef OLE2_DND result->idt.lpVtbl = &idt_vtbl; + if (string_atom == GDK_NONE) { + string_atom = gdk_atom_intern("STRING", FALSE); + text_atom = gdk_atom_intern("TEXT", FALSE); + text_uri_list_atom = gdk_atom_intern("text/uri-list", FALSE); + compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", FALSE); + pixmap_atom = gdk_atom_intern("PIXMAP", FALSE); + bitmap_atom = gdk_atom_intern("BITMAP", FALSE); + } + #endif + result->context = gdk_drag_context_new (); + #ifdef OLE2_DND + result->context->protocol = GDK_DRAG_PROTO_OLE2; + result->context->is_source = FALSE; + result->context->source_window = NULL; + result->context->dest_window = window; + gdk_window_ref (window); + + + /* Targets are hardwired and limited to text and file lists for now */ + /* The actual target may accept fewer types, but this needs to enumerate */ + /* all possible, since this is called in a way that we cannot tell */ + /* what the actual target does. */ + result->context->targets = g_list_append (NULL, GUINT_TO_POINTER(text_uri_list_atom)); + result->context->targets = g_list_append (result->context->targets, + GUINT_TO_POINTER(string_atom)); + result->context->targets = g_list_append (result->context->targets, + GUINT_TO_POINTER(text_atom)); + #if 0 // Currently unsupported + result->context->targets = g_list_append (result->context->targets, + GUINT_TO_POINTER(compound_text_atom)); + result->context->targets = g_list_append (result->context->targets, + GUINT_TO_POINTER(pixmap_atom)); + result->context->targets = g_list_append (result->context->targets, + GUINT_TO_POINTER(bitmap_atom)); + #endif + + /* Actions are also hardwired to all possible */ + result->context->actions = GDK_ACTION_DEFAULT | GDK_ACTION_COPY | GDK_ACTION_MOVE; + result->context->suggested_action = GDK_ACTION_MOVE; + result->context->action = GDK_ACTION_MOVE; + #endif // OLE2_DND + return result; } ! static GdkOle2DragSource * source_context_new (void) { ! GdkOle2DragSource *result; ! result = g_new0 (GdkOle2DragSource, 1); ! result->ref_count = 1; #ifdef OLE2_DND result->ids.lpVtbl = &ids_vtbl; #endif result->context = gdk_drag_context_new (); + result->context->protocol = GDK_DRAG_PROTO_OLE2; + result->context->is_source = TRUE; return result; } *************** *** 553,558 **** --- 272,279 ---- IShellLink *psl; WIN32_FIND_DATA wfd; + GDK_NOTE (DND, g_print("resolve_link()\n")); + /* Assume Failure to start with: */ *lpszPath = 0; if (lpszDescription) *************** *** 728,890 **** /* Source side */ static void - local_send_leave (GdkDragContext *context, - guint32 time) - { - GdkEvent tmp_event; - - if ((current_dest_drag != NULL) && - (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && - (current_dest_drag->source_window == context->source_window)) - { - tmp_event.dnd.type = GDK_DRAG_LEAVE; - tmp_event.dnd.window = context->dest_window; - /* Pass ownership of context to the event */ - tmp_event.dnd.context = current_dest_drag; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ - - current_dest_drag = NULL; - - gdk_event_put (&tmp_event); - } - } - - static void - local_send_enter (GdkDragContext *context, - guint32 time) - { - GdkEvent tmp_event; - GdkDragContextPrivate *private; - GdkDragContext *new_context; - - private = (GdkDragContextPrivate *) context; - - if (!private->local_selection) - private->local_selection = gdk_atom_intern ("LocalDndSelection", FALSE); - - if (current_dest_drag != NULL) - { - gdk_drag_context_unref (current_dest_drag); - current_dest_drag = NULL; - } - - new_context = gdk_drag_context_new (); - new_context->protocol = GDK_DRAG_PROTO_LOCAL; - new_context->is_source = FALSE; - - new_context->source_window = context->source_window; - gdk_window_ref (new_context->source_window); - new_context->dest_window = context->dest_window; - gdk_window_ref (new_context->dest_window); - - - new_context->targets = g_list_copy (context->targets); - - gdk_window_set_events (new_context->source_window, - gdk_window_get_events (new_context->source_window) | - GDK_PROPERTY_CHANGE_MASK); - new_context->actions = context->actions; - - tmp_event.dnd.type = GDK_DRAG_ENTER; - tmp_event.dnd.window = context->dest_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = new_context; - gdk_drag_context_ref (new_context); - - tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ - - current_dest_drag = new_context; - - ((GdkDragContextPrivate *) new_context)->local_selection = - private->local_selection; - - gdk_event_put (&tmp_event); - } - - static void - local_send_motion (GdkDragContext *context, - gint x_root, - gint y_root, - GdkDragAction action, - guint32 time) - { - GdkEvent tmp_event; - - if ((current_dest_drag != NULL) && - (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && - (current_dest_drag->source_window == context->source_window)) - { - tmp_event.dnd.type = GDK_DRAG_MOTION; - tmp_event.dnd.window = current_dest_drag->dest_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = current_dest_drag; - gdk_drag_context_ref (current_dest_drag); - - tmp_event.dnd.time = time; - - current_dest_drag->suggested_action = action; - current_dest_drag->actions = current_dest_drag->suggested_action; - - tmp_event.dnd.x_root = x_root; - tmp_event.dnd.y_root = y_root; - - ((GdkDragContextPrivate *) current_dest_drag)->last_x = x_root; - ((GdkDragContextPrivate *) current_dest_drag)->last_y = y_root; - - ((GdkDragContextPrivate *) context)->drag_status = GDK_DRAG_STATUS_MOTION_WAIT; - - gdk_event_put (&tmp_event); - } - } - - static void - local_send_drop (GdkDragContext *context, guint32 time) - { - GdkEvent tmp_event; - - if ((current_dest_drag != NULL) && - (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && - (current_dest_drag->source_window == context->source_window)) - { - GdkDragContextPrivate *private; - private = (GdkDragContextPrivate *) current_dest_drag; - - tmp_event.dnd.type = GDK_DROP_START; - tmp_event.dnd.window = current_dest_drag->dest_window; - tmp_event.dnd.send_event = FALSE; - - tmp_event.dnd.context = current_dest_drag; - gdk_drag_context_ref (current_dest_drag); - - tmp_event.dnd.time = GDK_CURRENT_TIME; - - tmp_event.dnd.x_root = private->last_x; - tmp_event.dnd.y_root = private->last_y; - - gdk_event_put (&tmp_event); - } - - } - - static void gdk_drag_do_leave (GdkDragContext *context, guint32 time) { ! if (context->dest_window) ! { ! GDK_NOTE (DND, g_print ("gdk_drag_do_leave\n")); ! switch (context->protocol) ! { ! case GDK_DRAG_PROTO_LOCAL: ! local_send_leave (context, time); ! break; ! ! default: ! break; ! } ! gdk_window_unref (context->dest_window); ! context->dest_window = NULL; ! } } GdkDragContext * --- 449,457 ---- /* Source side */ static void gdk_drag_do_leave (GdkDragContext *context, guint32 time) { ! GDK_NOTE (DND, g_print ("gdk_drag_do_leave\n")); } GdkDragContext * *************** *** 892,903 **** GList *targets) { GList *tmp_list; ! source_drag_context *ctx; g_return_val_if_fail (window != NULL, NULL); GDK_NOTE (DND, g_print ("gdk_drag_begin\n")); ctx = source_context_new (); ctx->context->is_source = TRUE; ctx->context->source_window = window; --- 459,471 ---- GList *targets) { GList *tmp_list; ! GdkOle2DragSource *ctx; g_return_val_if_fail (window != NULL, NULL); GDK_NOTE (DND, g_print ("gdk_drag_begin\n")); + /* Create and set up source context */ ctx = source_context_new (); ctx->context->is_source = TRUE; ctx->context->source_window = window; *************** *** 914,931 **** ctx->context->actions = 0; ! #if 0 ! DoDragDrop (...); ! #endif return ctx->context; } guint32 gdk_drag_get_protocol (guint32 xid, GdkDragProtocol *protocol) { /* This isn't used */ - g_assert_not_reached (); return 0; } --- 482,571 ---- ctx->context->actions = 0; ! gdk_win32_dnd_source_state = GDK_WIN32_DND_PENDING; ! pending_src_context = ctx; ! gdk_drag_context_ref (ctx->context); return ctx->context; } + void + gdk_win32_dnd_do_dragdrop () + { + GdkOle2DataObject* do_ctx; + GdkDragContext* drag_ctx; + GdkDragContextPrivate* priv_ctx; + BYTE key_states[256]; + HRESULT hr; + DWORD dwEffect = 0; + POINT pt; + POINTL ptl; + + if (pending_src_context == NULL) + return; + drag_ctx = pending_src_context->context; + priv_ctx = (GdkDragContextPrivate*) drag_ctx; + + /* Create a data object */ + do_ctx = data_context_new(drag_ctx); + g_assert (drag_ctx->protocol == GDK_DRAG_PROTO_OLE2); + + /* Get initial mouse & key state */ + if (!GetCursorPos(&priv_ctx->last_pt)) + WIN32_API_FAILED ("GetCursorPos"); + if (!ScreenToClient (GDK_DRAWABLE_XID (drag_ctx->source_window), &priv_ctx->last_pt)) + WIN32_API_FAILED ("ScreenToClient"); + priv_ctx->last_key_state = 0; + if (!GetKeyboardState(key_states)) + WIN32_API_FAILED("GetKeyboardState"); + else + { + if (key_states[VK_CONTROL]) + priv_ctx->last_key_state |= MK_CONTROL; + if (key_states[VK_SHIFT]) + priv_ctx->last_key_state |= MK_SHIFT; + if (key_states[VK_LBUTTON]) + priv_ctx->last_key_state |= MK_LBUTTON; + if (key_states[VK_MBUTTON]) + priv_ctx->last_key_state |= MK_MBUTTON; + if (key_states[VK_RBUTTON]) + priv_ctx->last_key_state |= MK_RBUTTON; + } + + /* Start dragging with mainloop inside the OLE2 API; exits only when done */ + gdk_win32_begin_modal_call (TRUE, TRUE); + hr = DoDragDrop ((IDataObject *) do_ctx, (IDropSource *) pending_src_context, + DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect); + gdk_win32_end_modal_call (); + + /* Delete dnd selection after successful move */ + if (hr == DRAGDROP_S_DROP && dwEffect == DROPEFFECT_MOVE) + { + gdk_append_selection_get_event (drag_ctx->source_window, + gdk_atom_intern ("DELETE", FALSE), + gdk_ole2_dnd_atom, gdk_ole2_dnd_atom); + } + + // Send a GDK_DROP_FINISHED to the source window + GetCursorPos (&pt); + ptl.x = pt.x; + ptl.y = pt.y; + if ( pending_src_context != NULL && pending_src_context->context != NULL + && pending_src_context->context->source_window != NULL ) + push_dnd_event (GDK_DROP_FINISHED, pending_src_context->context, ptl, FALSE); + + m_release_object(&do_ctx->ido); + if ( pending_src_context != NULL ) + { + m_release_source((IDropSource *) pending_src_context); + pending_src_context = NULL; + } + } + guint32 gdk_drag_get_protocol (guint32 xid, GdkDragProtocol *protocol) { /* This isn't used */ return 0; } *************** *** 937,942 **** --- 577,584 ---- GdkWindow **dest_window, GdkDragProtocol *protocol) { + GdkDragContextPrivate *private = (GdkDragContextPrivate *)context; + GdkDrawablePrivate *drag_window_private = (GdkDrawablePrivate*) drag_window; HWND recipient; POINT pt; *************** *** 954,964 **** *dest_window = gdk_window_lookup (recipient); if (*dest_window) gdk_window_ref (*dest_window); ! ! if (context->source_window) ! *protocol = GDK_DRAG_PROTO_LOCAL; ! else ! *protocol = GDK_DRAG_PROTO_WIN32_DROPFILES; } } --- 596,602 ---- *dest_window = gdk_window_lookup (recipient); if (*dest_window) gdk_window_ref (*dest_window); ! *protocol = GDK_DRAG_PROTO_OLE2; } } *************** *** 972,1064 **** GdkDragAction possible_actions, guint32 time) { ! GdkDragContextPrivate *private; ! ! g_return_val_if_fail (context != NULL, FALSE); ! ! GDK_NOTE (DND, g_print ("gdk_drag_motion\n")); ! ! private = (GdkDragContextPrivate *) context; ! ! if (context->dest_window != dest_window) ! { ! GdkEvent temp_event; ! ! /* Send a leave to the last destination */ ! gdk_drag_do_leave (context, time); ! private->drag_status = GDK_DRAG_STATUS_DRAG; ! ! /* Check if new destination accepts drags, and which protocol */ ! if (dest_window) ! { ! context->dest_window = dest_window; ! gdk_window_ref (context->dest_window); ! context->protocol = protocol; ! ! switch (protocol) ! { ! case GDK_DRAG_PROTO_LOCAL: ! local_send_enter (context, time); ! break; ! ! default: ! break; ! } ! context->suggested_action = suggested_action; ! } ! else ! { ! context->dest_window = NULL; ! context->action = 0; ! } ! ! /* Push a status event, to let the client know that ! * the drag changed ! */ ! ! temp_event.dnd.type = GDK_DRAG_STATUS; ! temp_event.dnd.window = context->source_window; ! /* We use this to signal a synthetic status. Perhaps ! * we should use an extra field... ! */ ! temp_event.dnd.send_event = TRUE; ! ! temp_event.dnd.context = context; ! temp_event.dnd.time = time; ! ! gdk_event_put (&temp_event); ! } ! else ! { ! context->suggested_action = suggested_action; ! } ! ! /* Send a drag-motion event */ ! ! private->last_x = x_root; ! private->last_y = y_root; ! ! if (context->dest_window) ! { ! if (private->drag_status == GDK_DRAG_STATUS_DRAG) ! { ! switch (context->protocol) ! { ! case GDK_DRAG_PROTO_LOCAL: ! local_send_motion (context, x_root, y_root, suggested_action, time); ! break; ! ! case GDK_DRAG_PROTO_NONE: ! g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()"); ! break; ! ! default: ! break; ! } ! } ! else ! return TRUE; ! } return FALSE; } --- 610,617 ---- GdkDragAction possible_actions, guint32 time) { ! GDK_NOTE (DND, g_print("gdk_drag_motion %ld, (%ld, %ld), suggested=%x, possible=%x\n", ! dest_window, x_root, y_root, suggested_action, possible_actions)); return FALSE; } *************** *** 1068,1090 **** guint32 time) { g_return_if_fail (context != NULL); ! ! if (context->dest_window) ! { ! switch (context->protocol) ! { ! case GDK_DRAG_PROTO_LOCAL: ! local_send_drop (context, time); ! break; ! ! case GDK_DRAG_PROTO_NONE: ! g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()"); ! break; ! ! default: ! break; ! } ! } } void --- 621,629 ---- guint32 time) { g_return_if_fail (context != NULL); ! GDK_NOTE (DND, g_print("gdk_drag_drop\n")); ! ! gdk_win32_dnd_source_state = GDK_WIN32_DND_DROPPED; } void *************** *** 1092,1099 **** guint32 time) { g_return_if_fail (context != NULL); ! ! gdk_drag_do_leave (context, time); } /* Destination side */ --- 631,640 ---- guint32 time) { g_return_if_fail (context != NULL); ! GDK_NOTE (DND, g_print("gdk_drag_abort\n")); ! ! gdk_drag_do_leave(context, time); ! gdk_win32_dnd_source_state = GDK_WIN32_DND_NONE; } /* Destination side */ *************** *** 1103,1139 **** GdkDragAction action, guint32 time) { ! GdkDragContext *src_context; ! GdkEvent tmp_event; ! ! g_return_if_fail (context != NULL); ! ! src_context = gdk_drag_context_find (TRUE, ! context->source_window, ! context->dest_window); ! ! if (src_context) ! { ! GdkDragContextPrivate *private = (GdkDragContextPrivate *) src_context; ! ! if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) ! private->drag_status = GDK_DRAG_STATUS_DRAG; ! ! tmp_event.dnd.type = GDK_DRAG_STATUS; ! tmp_event.dnd.window = context->source_window; ! tmp_event.dnd.send_event = FALSE; ! tmp_event.dnd.context = src_context; ! gdk_drag_context_ref (src_context); ! ! tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ ! ! if (action == GDK_ACTION_DEFAULT) ! action = 0; ! ! src_context->action = action; ! ! gdk_event_put (&tmp_event); ! } } void --- 644,651 ---- GdkDragAction action, guint32 time) { ! GDK_NOTE (DND, g_print ("gdk_drag_status, action = %d\n", action)); ! context->action = action; } void *************** *** 1141,1149 **** gboolean ok, guint32 time) { ! g_return_if_fail (context != NULL); ! ! GDK_NOTE (DND, g_print ("gdk_drop_reply\n")); } void --- 653,659 ---- gboolean ok, guint32 time) { ! GDK_NOTE (DND, g_print("gdk_drop_reply\n")); } void *************** *** 1151,1216 **** gboolean success, guint32 time) { - GdkDragContextPrivate *private; - GdkDragContext *src_context; - GdkEvent tmp_event; - g_return_if_fail (context != NULL); ! ! GDK_NOTE (DND, g_print ("gdk_drop_finish\n")); ! ! private = (GdkDragContextPrivate *) context; ! ! src_context = gdk_drag_context_find (TRUE, ! context->source_window, ! context->dest_window); ! if (src_context) ! { ! tmp_event.dnd.type = GDK_DROP_FINISHED; ! tmp_event.dnd.window = src_context->source_window; ! tmp_event.dnd.send_event = FALSE; ! tmp_event.dnd.context = src_context; ! gdk_drag_context_ref (src_context); ! ! gdk_event_put (&tmp_event); ! } } - - static GdkFilterReturn - gdk_destroy_filter (GdkXEvent *xev, - GdkEvent *event, - gpointer data) - { - #ifdef OLE2_DND - MSG *msg = (MSG *) xev; ! if (msg->message == WM_DESTROY) ! { ! IDropTarget *idtp = (IDropTarget *) data; ! GDK_NOTE (DND, g_print ("gdk_destroy_filter: WM_DESTROY: %#x\n", (guint) msg->hwnd)); ! RevokeDragDrop (msg->hwnd); ! CoLockObjectExternal (idtp, FALSE, TRUE); ! } ! #endif ! return GDK_FILTER_CONTINUE; } void gdk_window_register_dnd (GdkWindow *window) { #ifdef OLE2_DND ! target_drag_context *context; HRESULT hres; #endif g_return_if_fail (window != NULL); - if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered"))) - return; - - gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL); - GDK_NOTE (DND, g_print ("gdk_window_register_dnd: %#x\n", (guint) GDK_DRAWABLE_XID (window))); --- 661,697 ---- gboolean success, guint32 time) { g_return_if_fail (context != NULL); ! GDK_NOTE (DND, g_print("gdk_drop_finish\n")); ! ! gdk_drag_do_leave(context, time); ! if (success) ! gdk_win32_dnd_target_state = GDK_WIN32_DND_DROPPED; ! else ! gdk_win32_dnd_target_state = GDK_WIN32_DND_FAILED; } ! /* Private hash table mapping windows -> target drag contexts. The table ! owns a ref to both objects. */ ! static GHashTable* target_ctx_for_window = NULL; ! static void ! initialize_target_ctx_for_window () ! { ! if (target_ctx_for_window == NULL) ! target_ctx_for_window = g_hash_table_new (g_direct_hash, g_direct_equal); } void gdk_window_register_dnd (GdkWindow *window) { #ifdef OLE2_DND ! GdkOle2DragTarget *context; HRESULT hres; #endif g_return_if_fail (window != NULL); GDK_NOTE (DND, g_print ("gdk_window_register_dnd: %#x\n", (guint) GDK_DRAWABLE_XID (window))); *************** *** 1223,1251 **** DragAcceptFiles (GDK_DRAWABLE_XID (window), TRUE); #ifdef OLE2_DND ! /* Register for OLE2 d&d */ ! context = target_context_new (); hres = CoLockObjectExternal ((IUnknown *) &context->idt, TRUE, FALSE); if (!SUCCEEDED (hres)) OTHER_API_FAILED ("CoLockObjectExternal"); else { ! hres = RegisterDragDrop (GDK_DRAWABLE_XID (window), &context->idt); if (hres == DRAGDROP_E_ALREADYREGISTERED) { - g_print ("DRAGDROP_E_ALREADYREGISTERED\n"); CoLockObjectExternal ((IUnknown *) &context->idt, FALSE, FALSE); } else if (!SUCCEEDED (hres)) OTHER_API_FAILED ("RegisterDragDrop"); else { ! gdk_window_add_filter (window, gdk_destroy_filter, &context->idt); } } #endif } /************************************************************* * gdk_drag_get_selection: * Returns the selection atom for the current source window --- 704,767 ---- DragAcceptFiles (GDK_DRAWABLE_XID (window), TRUE); #ifdef OLE2_DND ! /* Simply return if window is already setup for DND. */ ! initialize_target_ctx_for_window (); ! if (g_hash_table_lookup (target_ctx_for_window, GDK_DRAWABLE_XID (window)) != NULL) ! return; ! ! /* Register for OLE2 d&d : similarly, claim to accept all supported */ ! /* data types because we cannot know from here what the window actually */ ! /* accepts. */ ! /* FIX ME: This of course won't work with user-extensible data types! */ ! context = target_context_new (window); hres = CoLockObjectExternal ((IUnknown *) &context->idt, TRUE, FALSE); if (!SUCCEEDED (hres)) OTHER_API_FAILED ("CoLockObjectExternal"); else { ! HWND h_wnd = GDK_DRAWABLE_XID (window); ! hres = RegisterDragDrop (h_wnd, &context->idt); if (hres == DRAGDROP_E_ALREADYREGISTERED) { CoLockObjectExternal ((IUnknown *) &context->idt, FALSE, FALSE); } else if (!SUCCEEDED (hres)) OTHER_API_FAILED ("RegisterDragDrop"); else { ! gdk_window_ref (window); ! g_hash_table_insert (target_ctx_for_window, GDK_DRAWABLE_XID (window), context); } } #endif } + void + gdk_window_unregister_dnd (GdkWindow *window) + { + GdkOle2DragTarget* ole2_ctx; + + g_return_if_fail (window != NULL); + + GDK_NOTE (DND, g_print ("gdk_window_unregister_dnd: %#x\n", + GDK_DRAWABLE_XID (window))); + + /* Simply return if window isn't in hash table */ + if ( target_ctx_for_window == NULL) + return; + ole2_ctx = g_hash_table_lookup (target_ctx_for_window, GDK_DRAWABLE_XID (window)); + if (ole2_ctx == NULL) + return; + + RevokeDragDrop (GDK_DRAWABLE_XID (window)); + CoLockObjectExternal ((struct IUnknown *) ole2_ctx, FALSE, TRUE); + + g_hash_table_remove (target_ctx_for_window, GDK_DRAWABLE_XID (window)); + m_release_target ((IDropTarget*) ole2_ctx); + gdk_window_unref (window); + + } + /************************************************************* * gdk_drag_get_selection: * Returns the selection atom for the current source window *************** *** 1257,1265 **** GdkAtom gdk_drag_get_selection (GdkDragContext *context) { ! if (context->protocol == GDK_DRAG_PROTO_LOCAL) ! return ((GdkDragContextPrivate *) context)->local_selection; ! else if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES) return gdk_win32_dropfiles_atom; else if (context->protocol == GDK_DRAG_PROTO_OLE2) return gdk_ole2_dnd_atom; --- 773,779 ---- GdkAtom gdk_drag_get_selection (GdkDragContext *context) { ! if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES) return gdk_win32_dropfiles_atom; else if (context->protocol == GDK_DRAG_PROTO_OLE2) return gdk_ole2_dnd_atom; Index: win32/gdkdrawable-win32.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/win32/gdkdrawable-win32.c,v retrieving revision 1.23.6.7 diff -c -r1.23.6.7 gdkdrawable-win32.c *** win32/gdkdrawable-win32.c 2001/11/05 23:31:19 1.23.6.7 --- win32/gdkdrawable-win32.c 2001/12/18 15:38:40 *************** *** 509,515 **** { if (!GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size)) WIN32_GDI_FAILED ("GetTextExtentPoint32W"); ! argp->x += size.cx; } if (oldfont != singlefont->xfont) --- 509,516 ---- { if (!GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size)) WIN32_GDI_FAILED ("GetTextExtentPoint32W"); ! else ! argp->x += size.cx; } if (oldfont != singlefont->xfont) *************** *** 546,552 **** arg.x = x; arg.y = y; ! arg.hdc = gdk_gc_predraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT); --- 547,553 ---- arg.x = x; arg.y = y; ! arg.total_len = text_length; arg.hdc = gdk_gc_predraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT); *************** *** 560,569 **** if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1) g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed"); else ! { ! arg.total_len = wlen; ! gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg); ! } g_free (wcstr); --- 561,568 ---- if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1) g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed"); else ! gdk_wchar_text_handle (font, wcstr, wlen, ! gdk_draw_text_handler, &arg); g_free (wcstr); *************** *** 597,603 **** arg.x = x; arg.y = y; ! arg.hdc = gdk_gc_predraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT); --- 596,602 ---- arg.x = x; arg.y = y; ! arg.total_len = text_length; arg.hdc = gdk_gc_predraw (drawable, gc_private, GDK_GC_FOREGROUND|GDK_GC_FONT); *************** *** 614,621 **** else wcstr = (wchar_t *) text; ! arg.total_len = text_length; ! gdk_wchar_text_handle (font, wcstr, text_length, gdk_draw_text_handler, &arg); if (sizeof (wchar_t) != sizeof (GdkWChar)) g_free (wcstr); --- 613,620 ---- else wcstr = (wchar_t *) text; ! gdk_wchar_text_handle (font, wcstr, text_length, ! gdk_draw_text_handler, &arg); if (sizeof (wchar_t) != sizeof (GdkWChar)) g_free (wcstr); *************** *** 659,665 **** SetRectEmpty (&r); outside_rgn = CreateRectRgnIndirect (&r); ! if (GDK_DRAWABLE_TYPE (drawable) != GDK_DRAWABLE_PIXMAP) { /* If we are drawing on a window, calculate the region that is * outside the source pixmap, and invalidate that, causing it to --- 658,665 ---- SetRectEmpty (&r); outside_rgn = CreateRectRgnIndirect (&r); ! if ((GDK_DRAWABLE_TYPE (drawable) != GDK_DRAWABLE_PIXMAP) && ! (GDK_DRAWABLE_TYPE (drawable) != GDK_DRAWABLE_NATIVE)) { /* If we are drawing on a window, calculate the region that is * outside the source pixmap, and invalidate that, causing it to *************** *** 716,722 **** if (!BitBlt (hdc, xdest, ydest, width, height, srcdc, xsrc, ysrc, SRCCOPY)) WIN32_GDI_FAILED ("BitBlt"); ! gdk_win32_release_hdc (NULL, srcdc); } } else --- 716,722 ---- if (!BitBlt (hdc, xdest, ydest, width, height, srcdc, xsrc, ysrc, SRCCOPY)) WIN32_GDI_FAILED ("BitBlt"); ! gdk_win32_release_offscreen_hdc (srcdc); } } else *************** *** 760,770 **** { if ((srcdc = GetDC (GDK_DRAWABLE_XID (src))) == NULL) WIN32_GDI_FAILED ("GetDC"); ! ! if (!BitBlt (hdc, xdest, ydest, width, height, ! srcdc, xsrc, ysrc, SRCCOPY)) ! WIN32_GDI_FAILED ("BitBlt"); ! ReleaseDC (GDK_DRAWABLE_XID (src), srcdc); } } gdk_gc_postdraw (drawable, gc_private, 0); --- 760,772 ---- { if ((srcdc = GetDC (GDK_DRAWABLE_XID (src))) == NULL) WIN32_GDI_FAILED ("GetDC"); ! else ! { ! if (!BitBlt (hdc, xdest, ydest, width, height, ! srcdc, xsrc, ysrc, SRCCOPY)) ! WIN32_GDI_FAILED ("BitBlt"); ! ReleaseDC (GDK_DRAWABLE_XID (src), srcdc); ! } } } gdk_gc_postdraw (drawable, gc_private, 0); Index: win32/gdkevents-win32.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/win32/gdkevents-win32.c,v retrieving revision 1.32.6.10 diff -c -r1.32.6.10 gdkevents-win32.c *** win32/gdkevents-win32.c 2001/11/24 23:56:52 1.32.6.10 --- win32/gdkevents-win32.c 2001/12/18 15:39:06 *************** *** 106,111 **** --- 106,115 ---- GSourceFunc callback, gpointer user_data); + static void gdk_synthesize_click (GdkEvent *event, + gint nclicks); + static void print_event(GdkEvent* event); + /* Private variable declarations */ *************** *** 117,131 **** * keyboard grab */ ! static GList *client_filters; /* Filters for client messages */ static gboolean p_grab_automatic; static GdkEventMask p_grab_mask; static gboolean p_grab_owner_events, k_grab_owner_events; static HCURSOR p_grab_cursor = NULL; - static GList *client_filters; /* Filters for client messages */ - static GSourceFuncs event_funcs = { gdk_event_prepare, gdk_event_check, --- 121,133 ---- * keyboard grab */ ! static GList *client_filters = NULL; /* Filters for client messages */ static gboolean p_grab_automatic; static GdkEventMask p_grab_mask; static gboolean p_grab_owner_events, k_grab_owner_events; static HCURSOR p_grab_cursor = NULL; static GSourceFuncs event_funcs = { gdk_event_prepare, gdk_event_check, *************** *** 154,159 **** --- 156,238 ---- static gboolean use_IME_COMPOSITION = FALSE; + static guint32 last_mouse_wheel_time = FALSE; + + + typedef struct { + gboolean in_call; + gboolean allow_idle; + gboolean allow_expose; + UINT timer_id; + } GdkWin32ModalInfo; + + static GdkWin32ModalInfo current_modal_info = { FALSE, FALSE, 0 }; + + static void CALLBACK + modal_timer_callback (HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) + { + g_main_context_iteration (NULL, FALSE); + } + + void + gdk_win32_begin_modal_call (gboolean allow_expose, gboolean allow_idle) + { + g_assert(!current_modal_info.in_call); + + current_modal_info.in_call = TRUE; + current_modal_info.allow_expose = allow_expose; + current_modal_info.allow_idle = allow_idle; + + if (allow_expose) + gdk_win32_set_allow_expose_callback (TRUE); + if (allow_idle) + { + current_modal_info.timer_id = SetTimer (NULL, 0, 0, modal_timer_callback); + if (current_modal_info.timer_id == 0) + WIN32_API_FAILED ("SetTimer"); + } + } + + void + gdk_win32_end_modal_call () + { + g_assert(current_modal_info.in_call); + + if (current_modal_info.timer_id != 0) + { + if (!KillTimer (NULL, current_modal_info.timer_id)) + WIN32_API_FAILED ("KillTimer"); + current_modal_info.timer_id = 0; + } + if (current_modal_info.allow_expose) + gdk_win32_set_allow_expose_callback (FALSE); + + current_modal_info.in_call = FALSE; + current_modal_info.allow_idle = FALSE; + current_modal_info.allow_expose = FALSE; + } + + static gint allow_expose_callback = 0; + + void + gdk_win32_set_allow_expose_callback (gboolean value) + { + if (value) + allow_expose_callback++; + else + allow_expose_callback--; + } + + void + gdk_win32_dispatch_event (GdkEvent* event) + { + GDK_THREADS_ENTER (); + + (*gdk_event_func) (event, gdk_event_data); + + GDK_THREADS_LEAVE (); + } + static LRESULT inner_window_proc (HWND hWnd, UINT message, *************** *** 204,232 **** } else if (event.event.any.type == GDK_EXPOSE) { ! /* Compress expose events */ ! GList *list = gdk_queued_events; ! ! while (list != NULL ! && (((GdkEvent *)list->data)->any.type != GDK_EXPOSE ! || ((GdkEvent *)list->data)->any.window != event.event.any.window)) ! list = list->next; ! if (list != NULL) { ! GdkRectangle u; ! ! GDK_NOTE (EVENTS, g_print ("... compressing an EXPOSE event\n")); ! gdk_rectangle_union (&event.event.expose.area, ! &((GdkEvent *)list->data)->expose.area, ! &u); ! ((GdkEvent *)list->data)->expose.area = u; gdk_window_unref (event.event.any.window); ! #if 0 ! /* Wake up WaitMessage */ ! PostMessage (NULL, gdk_ping_msg, 0, 0); ! #endif return FALSE; } } #endif eventp = gdk_event_new (); --- 283,322 ---- } else if (event.event.any.type == GDK_EXPOSE) { ! if (allow_expose_callback > 0 && gdk_event_func) { ! gdk_win32_set_allow_expose_callback (FALSE); ! gdk_win32_dispatch_event((GdkEvent*)&event); gdk_window_unref (event.event.any.window); ! gdk_win32_set_allow_expose_callback (TRUE); return FALSE; } + else + { + /* Compress expose events */ + GList *list = gdk_queued_events; + + while (list != NULL + && (((GdkEvent *)list->data)->any.type != GDK_EXPOSE + || ((GdkEvent *)list->data)->any.window != event.event.any.window)) + list = list->next; + if (list != NULL) + { + GdkRectangle u; + + GDK_NOTE (EVENTS, g_print ("... compressing an EXPOSE event\n")); + gdk_rectangle_union (&event.event.expose.area, + &((GdkEvent *)list->data)->expose.area, + &u); + ((GdkEvent *)list->data)->expose.area = u; + gdk_window_unref (event.event.any.window); + #if 0 + /* Wake up WaitMessage */ + PostMessage (NULL, gdk_ping_msg, 0, 0); + #endif + return FALSE; + } + } } #endif eventp = gdk_event_new (); *************** *** 558,567 **** --- 648,668 ---- SetCapture (xwindow); + if (p_grab_window) + gdk_window_unref(p_grab_window); p_grab_window = window; + gdk_window_ref(p_grab_window); if (xcursor != NULL) { + if (p_grab_cursor) + { + SetCursor (NULL); + if (!DestroyCursor (p_grab_cursor)) + WIN32_API_FAILED ("DestroyCursor"); + } p_grab_cursor = CopyCursor (xcursor); + if (p_grab_cursor == NULL) + WIN32_API_FAILED ("CopyCursor"); SetCursor (p_grab_cursor); } *************** *** 597,602 **** --- 698,705 ---- gdk_input_vtable.ungrab_pointer (time); if (GetCapture () != NULL) { + if (p_grab_window) + gdk_window_unref(p_grab_window); p_grab_window = NULL; ReleaseCapture (); } *************** *** 722,729 **** else return_val = AlreadyGrabbed; ! if (return_val == GrabSuccess) k_grab_window = window; return return_val; } --- 825,836 ---- else return_val = AlreadyGrabbed; ! if (return_val == GrabSuccess) { ! if (k_grab_window) ! gdk_window_unref(k_grab_window); k_grab_window = window; + gdk_window_ref(k_grab_window); + } return return_val; } *************** *** 748,753 **** --- 855,862 ---- { GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n")); + if (k_grab_window) + gdk_window_unref(k_grab_window); k_grab_window = NULL; } *************** *** 776,781 **** --- 885,917 ---- return GDK_FILTER_CONTINUE; } + static GdkFilterReturn + apply_client_message_filters (MSG *xevent, + GdkEvent *event) + { + GdkClientFilter *filter; + GList *tmp_list; + GdkFilterReturn result; + + tmp_list = client_filters; + + while (tmp_list) + { + filter = (GdkClientFilter *) tmp_list->data; + + if (xevent->message == filter->type) + { + result = (*filter->function) (xevent, event, filter->data); + if (result != GDK_FILTER_CONTINUE) + return result; + } + + tmp_list = tmp_list->next; + } + + return GDK_FILTER_CONTINUE; + } + void gdk_add_client_message_filter (GdkAtom message_type, GdkFilterFunc func, *************** *** 2954,2960 **** synthesize_leave_events (intermediate, gdk_parent_root, xevent, GDK_NOTIFY_NONLINEAR_VIRTUAL, mode); } ! gdk_window_unref (curWnd); curWnd = NULL; } --- 3090,3097 ---- synthesize_leave_events (intermediate, gdk_parent_root, xevent, GDK_NOTIFY_NONLINEAR_VIRTUAL, mode); } ! if (curWnd) ! gdk_window_unref (curWnd); curWnd = NULL; } *************** *** 3252,3258 **** /* If this window should have the same background as the * parent, fetch the parent. (And if the same goes for * the parent, fetch the grandparent, etc.) We don't need to ! * ref the ancestors becauspose they will be valid as long as * the leaf is valid. ` */ while (window --- 3389,3395 ---- /* If this window should have the same background as the * parent, fetch the parent. (And if the same goes for * the parent, fetch the grandparent, etc.) We don't need to ! * ref the ancestors because they will be valid as long as * the leaf is valid. ` */ while (window *************** *** 3351,3357 **** if (oldbitmap != NULL && bgdc != NULL) SelectObject (bgdc, oldbitmap); if (bgdc != NULL) ! gdk_win32_release_hdc (NULL, bgdc); } static gboolean --- 3488,3494 ---- if (oldbitmap != NULL && bgdc != NULL) SelectObject (bgdc, oldbitmap); if (bgdc != NULL) ! gdk_win32_release_offscreen_hdc (bgdc); } static gboolean *************** *** 3384,3389 **** --- 3521,3540 ---- window = gdk_window_lookup (xevent->hwnd); orig_window = window; + + // Gross hack for QUERYENDSESSION for now -- if xevent->message is set + // to 0 by filter, return 0; else return 1 + if ( xevent->message == WM_QUERYENDSESSION ) { + GdkFilterReturn result; + event->any.window = window; + result = apply_client_message_filters (xevent, event); + if ( xevent->message == 0 ) + *ret_valp = 0; + else + *ret_valp = 1; + *ret_val_flagp = TRUE; + return FALSE; + } /* InSendMessage() does not really mean the same as X11's send_event flag, * but it is close enough, says jpe@archaeopteryx.com. *************** *** 3480,3485 **** --- 3631,3637 ---- { GDK_NOTE (EVENTS, g_print ("MSH_MOUSEWHEEL: %#x %d\n", (guint) xevent->hwnd, xevent->wParam)); + last_mouse_wheel_time = GetTickCount(); event->scroll.type = GDK_SCROLL; *************** *** 3498,3504 **** if (newwindow != window) { ! gdk_window_unref (window); window = newwindow; gdk_window_ref (window); } --- 3650,3657 ---- if (newwindow != window) { ! if (window) ! gdk_window_unref (window); window = newwindow; gdk_window_ref (window); } *************** *** 3528,3534 **** event->scroll.pressure = 0.5; event->scroll.xtilt = 0; event->scroll.ytilt = 0; ! event->scroll.state = 0; /* No state information with MSH_MOUSEWHEEL */ event->scroll.source = GDK_SOURCE_MOUSE; event->scroll.deviceid = GDK_CORE_POINTER; return_val = !GDK_DRAWABLE_DESTROYED (window); --- 3681,3695 ---- event->scroll.pressure = 0.5; event->scroll.xtilt = 0; event->scroll.ytilt = 0; ! event->scroll.state = 0; ! if (GetKeyState (VK_SHIFT) < 0) ! event->scroll.state |= GDK_SHIFT_MASK; ! if (GetKeyState (VK_CAPITAL) & 0x1) ! event->scroll.state |= GDK_LOCK_MASK; ! if (GetKeyState (VK_CONTROL) < 0) ! event->scroll.state |= GDK_CONTROL_MASK; ! if (GetKeyState (VK_MENU) < 0) ! event->scroll.state |= GDK_MOD1_MASK; event->scroll.source = GDK_SOURCE_MOUSE; event->scroll.deviceid = GDK_CORE_POINTER; return_val = !GDK_DRAWABLE_DESTROYED (window); *************** *** 3602,3618 **** /* Let the system handle Alt-Tab and Alt-Enter */ if (xevent->wParam == VK_TAB || xevent->wParam == VK_RETURN ! || xevent->wParam == VK_F4) break; /* If posted without us having keyboard focus, ignore */ if (!(xevent->lParam & 0x20000000)) break; #if 0 /* don't generate events for just the Alt key */ if (xevent->wParam == VK_MENU) break; #endif /* Jump to code in common with WM_KEYUP and WM_KEYDOWN */ goto keyup_or_down; case WM_KEYUP: --- 3763,3783 ---- /* Let the system handle Alt-Tab and Alt-Enter */ if (xevent->wParam == VK_TAB || xevent->wParam == VK_RETURN ! || xevent->wParam == VK_F4 ! || xevent->wParam == VK_SPACE) break; + #if 0 /* What does the following have to do with having the keyboard focus? */ /* If posted without us having keyboard focus, ignore */ if (!(xevent->lParam & 0x20000000)) break; + #endif #if 0 /* don't generate events for just the Alt key */ if (xevent->wParam == VK_MENU) break; #endif /* Jump to code in common with WM_KEYUP and WM_KEYDOWN */ + ignore_WM_CHAR = TRUE; goto keyup_or_down; case WM_KEYUP: *************** *** 3794,3799 **** --- 3959,3966 ---- event->key.keyval = GDK_F15; break; case VK_F16: event->key.keyval = GDK_F16; break; + + /* Handle numbers and punctuation */ case '0': case '1': case '2': *************** *** 3804,3831 **** case '7': case '8': case '9': ! if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0 ! || GetKeyState (VK_MENU) < 0)) ! /* Control- or Alt- digits won't come in as a WM_CHAR, but ! * beware of AltGr-digits, which are used for instance on ! * Finnish keyboards. ! */ ! event->key.keyval = GDK_0 + (xevent->wParam - '0'); ! else ! ignore_WM_CHAR = FALSE; ! break; case VK_OEM_PLUS: /* On my Win98, the '+' key comes in * as VK_OEM_PLUS, etc */ case VK_OEM_COMMA: case VK_OEM_MINUS: case VK_OEM_PERIOD: case VK_OEM_2: case VK_OEM_4: case VK_OEM_5: case VK_OEM_6: ! if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0 ! || GetKeyState (VK_MENU) < 0)) /* Control- or Alt- plus, comma, minus or period won't * come in as WM_CHAR, but beware of AltGr-plus which is * backslash on Finnish keyboards --- 3971,3990 ---- case '7': case '8': case '9': ! case VK_OEM_PLUS: /* On my Win98, the '+' key comes in * as VK_OEM_PLUS, etc */ case VK_OEM_COMMA: case VK_OEM_MINUS: case VK_OEM_PERIOD: + case VK_OEM_1: case VK_OEM_2: + case VK_OEM_3: case VK_OEM_4: case VK_OEM_5: case VK_OEM_6: ! case VK_OEM_7: /* Control- or Alt- plus, comma, minus or period won't * come in as WM_CHAR, but beware of AltGr-plus which is * backslash on Finnish keyboards *************** *** 3833,3866 **** /* All these VK_OEM keycodes are the corresponding ASCII * char + 0x90 */ ! event->key.keyval = xevent->wParam - 0x90; ! else ! ignore_WM_CHAR = FALSE; ! break; ! case VK_OEM_1: ! if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0 ! || GetKeyState (VK_MENU) < 0)) ! /* ;: on US keyboard */ ! event->key.keyval = ';'; ! else ! ignore_WM_CHAR = FALSE; ! break; ! case VK_OEM_3: ! if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0 ! || GetKeyState (VK_MENU) < 0)) ! /* `~ on US keyboard */ ! event->key.keyval = '`'; ! else ! ignore_WM_CHAR = FALSE; ! break; ! case VK_OEM_7: ! if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0 ! || GetKeyState (VK_MENU) < 0)) ! /* '" on US keyboard */ ! event->key.keyval = '\''; else ignore_WM_CHAR = FALSE; break; default: if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP) event->key.keyval = xevent->wParam; --- 3992,4045 ---- /* All these VK_OEM keycodes are the corresponding ASCII * char + 0x90 */ ! ! /* When altgr key is not down but either control or alt (aka menu) key */ ! /* is down, then we convert the event here rather than waiting for the */ ! /* corresponding WM_CHAR event */ ! if (!is_AltGr_key && (GetKeyState(VK_MENU) < 0 || GetKeyState(VK_CONTROL) < 0)) { ! WORD cvt = 0; ! BYTE keystate[256]; ! static HKL kbd = NULL; ! int res; ! UINT scn; ! /*int i;*/ ! ! /* Get information about this user's keyboard layout */ ! kbd = GetKeyboardLayout(0); ! ! /* Get current state of the keyboard and then pretend that the */ ! /* control key is not down because otherwise ToAsciiEx() fails */ ! /* to return a key value for the event */ ! /* This is OK to do here because we already filtered out the */ ! /* AltGr (=ctrl+right-alt) case above, although I am not sure */ ! /* whether french right-alt and some of the other odd combos */ ! /* will all be handled right. */ ! GetKeyboardState(keystate); ! keystate[VK_LCONTROL] = 0; ! keystate[VK_RCONTROL] = 0; ! keystate[VK_CONTROL] = 0; ! /*for (i = 0; i <= 255; i++)*/ ! /*g_print("KEYSTATE %x: %x\n", i, keystate[i]);*/ ! ! /* Find the scan code for the key event and then get the key value */ ! scn = MapVirtualKey(xevent->wParam, 0); ! res = ToAsciiEx(xevent->wParam, scn, keystate, &cvt, 0, kbd); ! /*g_print("RESULT %i %i %i %i\n", kbd, scn, res, cvt);*/ ! if (res == 0) ! event->key.keyval = GDK_VoidSymbol; ! else if (res == 1) ! event->key.keyval = cvt & 0xff; ! else ! event->key.keyval = GDK_VoidSymbol; ! /*g_print("NUM/PUNCT DOWN '%c' -> '%c'\n", xevent->wParam, event->key.keyval);*/ ! } ! ! /* If no modifier is down or it's AltGr key, we process the */ ! /* WM_CHAR event instead */ else ignore_WM_CHAR = FALSE; break; + default: if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP) event->key.keyval = xevent->wParam; *************** *** 3923,3928 **** --- 4102,4110 ---- if (ignore_WM_CHAR) { ignore_WM_CHAR = FALSE; + // Don't let the def window proc see the WM_CHAR either + *ret_valp = TRUE; + *ret_val_flagp = TRUE; break; } *************** *** 3948,3954 **** GdkEvent *event2 = gdk_event_new (); build_keypress_event (GDK_WINDOW_WIN32DATA (window), event2, xevent); event2->key.window = window; - event2->key.send_event = FALSE; gdk_window_ref (window); gdk_event_queue_append (event2); GDK_NOTE (EVENTS, print_event (event2)); --- 4130,4135 ---- *************** *** 3977,3982 **** --- 4158,4171 ---- button = 1; goto buttondown0; case WM_MBUTTONDOWN: + // The mouse wheel can also be depressed as middle mouse button, but this + // often happens by accident during wheeling, so we turn off middle mouse + // button within one second of last wheel turn to avoid odd and annoying + // behaviors in most widgets + if (GetTickCount() < last_mouse_wheel_time + 1000) { + return_val = FALSE; + goto bypass_switch; + } button = 2; goto buttondown0; case WM_RBUTTONDOWN: *************** *** 4120,4132 **** if (window == curWnd && LOWORD (xevent->lParam) == curX && HIWORD (xevent->lParam) == curY) ! break; /* HB: only process mouse move messages if we own the active window. */ ! GetWindowThreadProcessId(GetActiveWindow(), &pidActWin); ! GetWindowThreadProcessId(xevent->hwnd, &pidThis); ! if (pidActWin != pidThis) ! break; if (window != curWnd) synthesize_crossing_events (window, xevent); --- 4309,4333 ---- if (window == curWnd && LOWORD (xevent->lParam) == curX && HIWORD (xevent->lParam) == curY) ! { ! GDK_NOTE (EVENTS, g_print ("...ignored because mouse hasn't really moved\n")); ! break; ! } /* HB: only process mouse move messages if we own the active window. */ ! /* Note need to accommodate null active window, which can happen */ ! /* at least as a result of debugger interactions */ ! { ! HWND active_window = GetActiveWindow(); ! if (active_window != NULL) ! GetWindowThreadProcessId(active_window, &pidActWin); ! GetWindowThreadProcessId(xevent->hwnd, &pidThis); ! if ((active_window == NULL) || (pidActWin != pidThis)) ! { ! GDK_NOTE (EVENTS, g_print ("...ignored because we don't own the active window\n")); ! break; ! } ! } if (window != curWnd) synthesize_crossing_events (window, xevent); *************** *** 4142,4148 **** --- 4343,4352 ---- if (!propagate (&window, xevent, p_grab_window, p_grab_owner_events, p_grab_mask, doesnt_want_button_motion)) + { + GDK_NOTE (EVENTS, g_print ("...ignored because no window want's it propagated\n")); break; + } event->motion.window = window; event->motion.time = xevent->time; *************** *** 4165,4170 **** --- 4369,4377 ---- event->motion.deviceid = GDK_CORE_POINTER; return_val = !GDK_DRAWABLE_DESTROYED (window); + + GDK_NOTE (EVENTS, g_print ("...converted to GDK_MOTION_NOTIFY; return_val = %d\n", + return_val)); break; case WM_NCMOUSEMOVE: *************** *** 4204,4227 **** break; #endif case WM_CAPTURECHANGED: GDK_NOTE (EVENTS, g_print ("WM_CAPTURECHANGED: %#x %#lx\n", (guint) xevent->hwnd, xevent->lParam)); if (p_grab_window != NULL) { ! /* We aren't calling gdk_pointer_ungrab() ourselves. */ if (xevent->lParam != 0) newwindow = gdk_window_lookup ((HWND) xevent->lParam); else newwindow = NULL; ! if (newwindow == NULL) ! synthesize_leave_app_events (xevent, GDK_CROSSING_UNGRAB); ! ! p_grab_window = NULL; } ! if (p_grab_cursor != NULL) { SetCursor (NULL); if (!DestroyCursor (p_grab_cursor)) --- 4411,4443 ---- break; #endif + #if 0 // Disabled because it doesn't work with OLE drag-n-drop + // Would fix menus not going away when windows within app + // change but since gtk menu code ignores crossing events, + // that code would also need to be fixed. case WM_CAPTURECHANGED: GDK_NOTE (EVENTS, g_print ("WM_CAPTURECHANGED: %#x %#lx\n", (guint) xevent->hwnd, xevent->lParam)); if (p_grab_window != NULL) { ! /* Check to see if message was emitted as a result of a gdk_pointer_grab() call. */ if (xevent->lParam != 0) newwindow = gdk_window_lookup ((HWND) xevent->lParam); else newwindow = NULL; ! /* Synthesize a crossing ungrab event if the grab window has changed. */ ! if (window != p_grab_window) ! { ! if (curWnd != NULL && newwindow == NULL) ! synthesize_leave_app_events (xevent, GDK_CROSSING_UNGRAB); ! if (p_grab_window) ! gdk_window_unref(p_grab_window); ! p_grab_window = NULL; ! } } ! if (p_grab_window == NULL && p_grab_cursor != NULL) { SetCursor (NULL); if (!DestroyCursor (p_grab_cursor)) *************** *** 4229,4239 **** --- 4445,4489 ---- p_grab_cursor = NULL; } break; + #endif // 0 + + #if 0 // This is correct, but doesn't do anything useful for us since + // no gtk widgets pay attention to crossing events. If gtk menu + // did, this would cause menus to go away when app switching. + case WM_ACTIVATEAPP: + GDK_NOTE (EVENTS, g_print ("WM_ACTIVATEAPP: %#x %ld\n", + (guint) xevent->hwnd, xevent->wParam)); + + /* If we are losing the focus, send a crossing ungrab event so that */ + /* popped up menus, etc go away when we switch to another app */ + if (!xevent->wParam && p_grab_window != NULL) + { + + if (curWnd != NULL) + synthesize_leave_app_events (xevent, GDK_CROSSING_UNGRAB); + if (p_grab_window) + gdk_window_unref(p_grab_window); + p_grab_window = NULL; + + if (p_grab_cursor != NULL) + { + SetCursor (NULL); + if (!DestroyCursor (p_grab_cursor)) + WIN32_API_FAILED ("DestroyCursor"); + p_grab_cursor = NULL; + } + + return_val = TRUE; + } + break; + #endif case WM_MOUSEWHEEL: GDK_NOTE (EVENTS, g_print ("WM_MOUSEWHEEL: %#x %d\n", (guint) xevent->hwnd, HIWORD (xevent->wParam))); + last_mouse_wheel_time = GetTickCount(); + event->scroll.type = GDK_SCROLL; /* WM_MOUSEWHEEL seems to be delivered to the focus window Work *************** *** 4253,4259 **** if (newwindow != window) { ! gdk_window_unref (window); window = newwindow; gdk_window_ref (window); } --- 4503,4510 ---- if (newwindow != window) { ! if (window) ! gdk_window_unref (window); window = newwindow; gdk_window_ref (window); } *************** *** 4327,4332 **** --- 4578,4593 ---- return_val = !GDK_DRAWABLE_DESTROYED (window); break; #endif + case WM_MOUSEACTIVATE: + GDK_NOTE (EVENTS, g_print ("WM_MOUSEACTIVATE: %#x\n", + xevent->hwnd)); + if ( GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_TEMP ) + { + *ret_val_flagp = TRUE; + *ret_valp = MA_NOACTIVATE; + return_val = FALSE; + } + break; case WM_SETFOCUS: case WM_KILLFOCUS: *************** *** 4335,4345 **** "SET" : "KILL"), (guint) xevent->hwnd)); ! if (xevent->message == WM_SETFOCUS) ! curFocusWnd = window; else ! curFocusWnd = NULL; ! if (!(GDK_WINDOW_WIN32DATA (window)->event_mask & GDK_FOCUS_CHANGE_MASK)) break; --- 4596,4614 ---- "SET" : "KILL"), (guint) xevent->hwnd)); ! if (xevent->message == WM_SETFOCUS) ! { ! if (curFocusWnd) ! gdk_window_unref(curFocusWnd); ! curFocusWnd = window; ! gdk_window_ref(curFocusWnd); ! } else ! { ! if (curFocusWnd) ! gdk_window_unref(curFocusWnd); ! curFocusWnd = NULL; ! } if (!(GDK_WINDOW_WIN32DATA (window)->event_mask & GDK_FOCUS_CHANGE_MASK)) break; *************** *** 4711,4717 **** } if (window) ! gdk_window_unref (window); return return_val; } --- 4980,4986 ---- } if (window) ! gdk_window_unref (window); return return_val; } *************** *** 4721,4726 **** --- 4990,4997 ---- { MSG msg; + gdk_win32_set_allow_expose_callback(TRUE); + while (!gdk_event_queue_find_first () && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { *************** *** 4737,4742 **** --- 5008,5015 ---- DispatchMessage (&msg); } + + gdk_win32_set_allow_expose_callback(FALSE); } static gboolean *************** *** 4795,4804 **** (*gdk_event_func) (event, gdk_event_data); gdk_event_free (event); ! } ! /* Release any allocated DC's */ ! gdk_win32_c