PsychError SCREENShowCursorHelper(void) { // If you change the useString then also change the corresponding synopsis string in ScreenSynopsis.c static char useString[] = "Screen('ShowCursorHelper', screenIndex [, cursorshapeid][, mouseIndex]);"; // 1 2 3 static char synopsisString[] = "This is a helper function called by ShowCursor. Do not call Screen(\'ShowCursorHelper\'), use " "ShowCursor instead.\n" "Show the mouse pointer. If optional 'cursorshapeid' is given, select a specific cursor shape as well.\n" "If optional 'mouseIndex' is given, setup cursor for given master mouseIndex device (Linux only).\n"; static char seeAlsoString[] = "HideCursorHelper"; int screenNumber, cursorid, mouseIdx; char *cursorName = NULL; #if PSYCH_SYSTEM == PSYCH_LINUX Cursor mycursor; #endif //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(3)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs PsychCopyInScreenNumberArg(1, TRUE, &screenNumber); mouseIdx = -1; PsychCopyInIntegerArg(3, FALSE, &mouseIdx); PsychShowCursor(screenNumber, mouseIdx); // Copy in optional cursor shape id argument: The default of -1 means to // not change cursor appearance. Any other positive value changes to an // OS dependent shape (== the mapping of numbers to shapes is OS dependent). cursorid = -1; if (!PsychCopyInIntegerArg(2, kPsychArgAnything, &cursorid)) { if (PsychAllocInCharArg(2, kPsychArgAnything, &cursorName)) cursorid = -2; } // Cursor change request? if (cursorid!=-1) { // Yes. #if PSYCH_SYSTEM == PSYCH_OSX // OS/X: PsychCocoaSetThemeCursor(cursorid); #endif #if PSYCH_SYSTEM == PSYCH_LINUX #ifdef PTB_USE_WAYLAND // GNU/Linux with Wayland backend: // Map X11 id's to Wayland equivalents: switch (cursorid) { case 26: // SandClock cursorName = "watch"; break; case 58: // Hand cursorName = "hand1"; break; case 34: // CrossHair cursorName = "crosshair"; break; case 1: // IBeam cursorName = "xterm"; break; case 0: // Arrow cursorName = "left_ptr"; break; case 2: // Arrow cursorName = "left_ptr"; break; case 5: // Arrow cursorName = "left_ptr"; break; case -2: // Special case: Use provided cursorName string, if any: if (cursorName) break; default: cursorName = "left_ptr"; } PsychOSDefineWaylandCursor(screenNumber, mouseIdx, cursorName); #else // GNU/Linux with X11 windowing system: // Map screenNumber to X11 display handle and screenid: CGDirectDisplayID dpy; PsychGetCGDisplayIDFromScreenNumber(&dpy, screenNumber); // Create cursor spec from passed cursorid: mycursor = XCreateFontCursor(dpy, (unsigned int) cursorid); if (mouseIdx < 0) { // Set cursor for our window: PsychOSDefineX11Cursor(screenNumber, -1, mycursor); } else { // XInput cursor: Master pointers only. int nDevices; XIDeviceInfo* indevs = PsychGetInputDevicesForScreen(screenNumber, &nDevices); // Sanity check: if (NULL == indevs) PsychErrorExitMsg(PsychError_user, "Sorry, your system does not support individual mouse pointers."); if (mouseIdx >= nDevices) PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. No such cursor pointer."); if (indevs[mouseIdx].use != XIMasterPointer) PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. No such master cursor pointer."); PsychOSDefineX11Cursor(screenNumber, indevs[mouseIdx].deviceid, mycursor); } XFlush(dpy); #endif // Done (hopefully). #endif #if PSYCH_SYSTEM == PSYCH_WINDOWS // Microsoft Windows: LPCTSTR lpCursorName; #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif // Map provided cursor id to a Windows system id for such a cursor: switch(cursorid) { case 0: // Standard arrow cursor: lpCursorName = IDC_ARROW; break; case 1: // haircross cursor: lpCursorName = IDC_CROSS; break; case 2: // hand cursor: lpCursorName = IDC_HAND; break; case 3: // Arrows in all 4 directions cursor: lpCursorName = IDC_SIZEALL; break; case 4: // north-south cursor: lpCursorName = IDC_SIZENS; break; case 5: // east-west cursor: lpCursorName = IDC_SIZEWE; break; case 6: // hourglass cursor: lpCursorName = IDC_WAIT; break; case 7: // No cursor: lpCursorName = IDC_NO; break; case 8: // IBeam/text cursor: lpCursorName = IDC_IBEAM; break; default: // Default for unknown id is the standard arrow cursor: lpCursorName = IDC_ARROW; } // Load and set a cursor, based on the selected lpCursorName cursor id string: SetCursor(LoadCursor(NULL, lpCursorName)); #endif // End of cursor shape setup. } return(PsychError_none); }
PsychError SCREENShowCursorHelper(void) { int screenNumber, cursorid, mouseIdx; #if PSYCH_SYSTEM == PSYCH_LINUX Cursor mycursor; #endif //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(3)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs PsychCopyInScreenNumberArg(1, TRUE, &screenNumber); mouseIdx = -1; PsychCopyInIntegerArg(3, FALSE, &mouseIdx); PsychShowCursor(screenNumber, mouseIdx); // Copy in optional cursor shape id argument: The default of -1 means to // not change cursor appearance. Any other positive value changes to an // OS dependent shape (== the mapping of numbers to shapes is OS dependent). cursorid = -1; PsychCopyInIntegerArg(2, FALSE, &cursorid); // Cursor change request? if (cursorid!=-1) { // Yes. #if PSYCH_SYSTEM == PSYCH_OSX // OS/X: PsychCocoaSetThemeCursor(cursorid); #endif #if PSYCH_SYSTEM == PSYCH_LINUX // GNU/Linux with X11 windowing system: // Map screenNumber to X11 display handle and screenid: CGDirectDisplayID dpy; PsychGetCGDisplayIDFromScreenNumber(&dpy, screenNumber); // Create cursor spec from passed cursorid: mycursor = XCreateFontCursor(dpy, (unsigned int) cursorid); if (mouseIdx < 0) { // Set cursor for our window: PsychOSDefineX11Cursor(screenNumber, -1, mycursor); } else { // XInput cursor: Master pointers only. int nDevices; XIDeviceInfo* indevs = PsychGetInputDevicesForScreen(screenNumber, &nDevices); // Sanity check: if (NULL == indevs) PsychErrorExitMsg(PsychError_user, "Sorry, your system does not support individual mouse pointers."); if (mouseIdx >= nDevices) PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. No such cursor pointer."); if (indevs[mouseIdx].use != XIMasterPointer) PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. No such master cursor pointer."); PsychOSDefineX11Cursor(screenNumber, indevs[mouseIdx].deviceid, mycursor); } XFlush(dpy); // Done (hopefully). #endif #if PSYCH_SYSTEM == PSYCH_WINDOWS // Microsoft Windows: LPCTSTR lpCursorName; #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif // Map provided cursor id to a Windows system id for such a cursor: switch(cursorid) { case 0: // Standard arrow cursor: lpCursorName = IDC_ARROW; break; case 1: // haircross cursor: lpCursorName = IDC_CROSS; break; case 2: // hand cursor: lpCursorName = IDC_HAND; break; case 3: // Arrows in all 4 directions cursor: lpCursorName = IDC_SIZEALL; break; case 4: // north-south cursor: lpCursorName = IDC_SIZENS; break; case 5: // east-west cursor: lpCursorName = IDC_SIZEWE; break; case 6: // hourglass cursor: lpCursorName = IDC_WAIT; break; case 7: // No cursor: lpCursorName = IDC_NO; break; default: // Default for unknown id is the standard arrow cursor: lpCursorName = IDC_ARROW; } // Load and set a cursor, based on the selected lpCursorName cursor id string: SetCursor(LoadCursor(NULL, lpCursorName)); #endif // End of cursor shape setup. } return(PsychError_none); }
// Implement closing of all onscreen- and offscreen windows, release of all captured displays, // releasing of all internal textures and memory buffers, stopping of internal helper threads, // etc.... // This routine is normally called by SCREENCloseAll, but can be also called by the exit-handler, // and diverse error-handlers for cleanup. void ScreenCloseAllWindows(void) { PsychWindowRecordType **windowRecordArray; int i, numWindows, numScreens; static unsigned int recursionLevel = 0; // Recursive self-call? if (recursionLevel > 0) { // Ohoh: We are recursively calling ourselves, probably due to some // error condition triggered during our execution. This is bad, we need // to break the infinite recursion. How? We output a recursion warning, // then return as no-op: printf("PTB-ERROR: Error during error handling! ScreenCloseAllWindows() called recursively! Trying to break out of this vicious cycle...\n"); printf("PTB-ERROR: Maybe it is a good idea to exit and restart Matlab/Octave.\n"); // Skip to the release screen routine and hope for the best: goto critical_abort; } recursionLevel++; // Cold-Reset the drawing target: PsychColdResetDrawingTarget(); // Reset the "userspaceGL" flag which tells PTB that userspace GL rendering was active // due to Screen('BeginOpenGL') command. PsychSetUserspaceGLFlag(FALSE); // Check for stale texture ressources: PsychRessourceCheckAndReminder(TRUE); // Shutdown Quicktime subsystems if active: PsychExitMovieWriting(); PsychExitMovies(); PsychExitVideoCapture(); // Close the windows: We do it reverse (descending) order so textures get closed // before the onscreen windows. In theory this shouldn't matter, but in practice, // more stress on the PsychCloseWindow() path. If we have bugs there, chances are // higher they get exposed this way, which long-term is a good thing(TM). PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray); for(i = numWindows - 1; i >= 0; i--) { if (PsychPrefStateGet_Verbosity()>5) { printf("PTB-DEBUG: In ScreenCloseAllWindows(): Destroying window %i\n", i); fflush(NULL); } PsychCloseWindow(windowRecordArray[i]); } PsychDestroyVolatileWindowRecordPointerList(windowRecordArray); critical_abort: // Release all captured displays, unhide the cursor on each of them: numScreens=PsychGetNumDisplays(); for(i=0;i<numScreens;i++){ if(PsychIsScreenCaptured(i)) { PsychRestoreScreenSettings(i); PsychReleaseScreen(i); } PsychShowCursor(i, -1); } recursionLevel--; return; }