From bc5a65610a0df72d44f409a2e921a35e6d362db8 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 28 Feb 2015 04:15:13 +0000 Subject: [PATCH] - fixed a minor bug in the UNIX/X11 cursor code, causing an X error and abort due to a stale cursor cache, when the application (which calls glutSetCursor), uses glutLeaveMainLoop to close the connection to the X server, and then re-initializes freeglut and starts over with a new connection. git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1749 7f0cb862-5218-0410-a997-914c9d46530a --- src/x11/fg_cursor_x11.c | 53 +++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/x11/fg_cursor_x11.c b/src/x11/fg_cursor_x11.c index 6d889f2..9d15900 100644 --- a/src/x11/fg_cursor_x11.c +++ b/src/x11/fg_cursor_x11.c @@ -61,6 +61,7 @@ struct tag_cursorCacheEntry { unsigned int cursorShape; /* an XC_foo value */ Cursor cachedCursor; /* None if the corresponding cursor has not been created yet */ + Display *dpy; /* display used to allocate this cursor */ }; /* @@ -68,26 +69,26 @@ struct tag_cursorCacheEntry { * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive. */ static cursorCacheEntry cursorCache[] = { - { XC_arrow, None }, /* GLUT_CURSOR_RIGHT_ARROW */ - { XC_top_left_arrow, None }, /* GLUT_CURSOR_LEFT_ARROW */ - { XC_hand1, None }, /* GLUT_CURSOR_INFO */ - { XC_pirate, None }, /* GLUT_CURSOR_DESTROY */ - { XC_question_arrow, None }, /* GLUT_CURSOR_HELP */ - { XC_exchange, None }, /* GLUT_CURSOR_CYCLE */ - { XC_spraycan, None }, /* GLUT_CURSOR_SPRAY */ - { XC_watch, None }, /* GLUT_CURSOR_WAIT */ - { XC_xterm, None }, /* GLUT_CURSOR_TEXT */ - { XC_crosshair, None }, /* GLUT_CURSOR_CROSSHAIR */ - { XC_sb_v_double_arrow, None }, /* GLUT_CURSOR_UP_DOWN */ - { XC_sb_h_double_arrow, None }, /* GLUT_CURSOR_LEFT_RIGHT */ - { XC_top_side, None }, /* GLUT_CURSOR_TOP_SIDE */ - { XC_bottom_side, None }, /* GLUT_CURSOR_BOTTOM_SIDE */ - { XC_left_side, None }, /* GLUT_CURSOR_LEFT_SIDE */ - { XC_right_side, None }, /* GLUT_CURSOR_RIGHT_SIDE */ - { XC_top_left_corner, None }, /* GLUT_CURSOR_TOP_LEFT_CORNER */ - { XC_top_right_corner, None }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */ - { XC_bottom_right_corner, None }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */ - { XC_bottom_left_corner, None } /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */ + { XC_arrow, None, 0 }, /* GLUT_CURSOR_RIGHT_ARROW */ + { XC_top_left_arrow, None, 0 }, /* GLUT_CURSOR_LEFT_ARROW */ + { XC_hand1, None, 0 }, /* GLUT_CURSOR_INFO */ + { XC_pirate, None, 0 }, /* GLUT_CURSOR_DESTROY */ + { XC_question_arrow, None, 0 }, /* GLUT_CURSOR_HELP */ + { XC_exchange, None, 0 }, /* GLUT_CURSOR_CYCLE */ + { XC_spraycan, None, 0 }, /* GLUT_CURSOR_SPRAY */ + { XC_watch, None, 0 }, /* GLUT_CURSOR_WAIT */ + { XC_xterm, None, 0 }, /* GLUT_CURSOR_TEXT */ + { XC_crosshair, None, 0 }, /* GLUT_CURSOR_CROSSHAIR */ + { XC_sb_v_double_arrow, None, 0 }, /* GLUT_CURSOR_UP_DOWN */ + { XC_sb_h_double_arrow, None, 0 }, /* GLUT_CURSOR_LEFT_RIGHT */ + { XC_top_side, None, 0 }, /* GLUT_CURSOR_TOP_SIDE */ + { XC_bottom_side, None, 0 }, /* GLUT_CURSOR_BOTTOM_SIDE */ + { XC_left_side, None, 0 }, /* GLUT_CURSOR_LEFT_SIDE */ + { XC_right_side, None, 0 }, /* GLUT_CURSOR_RIGHT_SIDE */ + { XC_top_left_corner, None, 0 }, /* GLUT_CURSOR_TOP_LEFT_CORNER */ + { XC_top_right_corner, None, 0 }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */ + { XC_bottom_right_corner, None, 0 }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */ + { XC_bottom_left_corner, None, 0 } /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */ }; void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) @@ -104,10 +105,18 @@ void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) if( ( cursorIDToUse >= 0 ) && ( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) { cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ]; - if( entry->cachedCursor == None ) { + + /* the second clause forces an invalidation of the cached cursor, if it was + * created through a different display connection. + * This can only happen, in the extremely rare case where the user program calls the + * freeglut extension glutLeaveMainLoop, and then re-initializes freeglut and + * starts over. + */ + if( entry->cachedCursor == None || entry->dpy != fgDisplay.pDisplay.Display ) { entry->cachedCursor = XCreateFontCursor( fgDisplay.pDisplay.Display, entry->cursorShape ); - } + entry->dpy = fgDisplay.pDisplay.Display; + } cursor = entry->cachedCursor; } else { switch( cursorIDToUse ) -- 1.7.10.4