ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
(Generate patch)

Comparing SheepShaver/src/video.cpp (file contents):
Revision 1.15 by gbeauche, 2008-01-01T09:47:38Z vs.
Revision 1.16 by asvitkine, 2008-06-25T02:52:22Z

# Line 21 | Line 21
21   /*
22   * TODO
23   * - check for supported modes ???
24 * - window mode "hardware" cursor hotspot
24   */
25  
26   #include <stdio.h>
# Line 143 | Line 142 | bool VideoSnapshot(int xsize, int ysize,
142  
143  
144   /*
145 + *  Determine whether we should use the hardware or software cursor, and return true for the former, false for the latter.
146 + *  Currently we use the hardware cursor if we can, but perhaps this can be made a preference someday.
147 + */
148 +
149 + static bool UseHardwareCursor(void)
150 + {
151 +        return video_can_change_cursor();
152 + }
153 +
154 +
155 + /*
156   *  Video driver open routine
157   */
158  
# Line 157 | Line 167 | static int16 VideoOpen(uint32 pb, VidLoc
167          csSave->savePage = 0;
168          csSave->saveVidParms = 0;                       // Add the right table
169          csSave->luminanceMapping = false;
170 +        csSave->cursorHardware = UseHardwareCursor();
171          csSave->cursorX = 0;
172          csSave->cursorY = 0;
173          csSave->cursorVisible = 0;
174          csSave->cursorSet = 0;
175 +        csSave->cursorHotFlag = false;
176 +        csSave->cursorHotX = 0;
177 +        csSave->cursorHotY = 0;
178  
179          // Find and set default gamma table
180          csSave->gammaTable = 0;
# Line 416 | Line 430 | static int16 VideoControl(uint32 pb, Vid
430  
431                  case cscSetHardwareCursor: {
432   //                      D(bug("SetHardwareCursor\n"));
433 +
434 +                        if (!csSave->cursorHardware)
435 +                                return controlErr;
436 +
437                          csSave->cursorSet = false;
438                          bool changed = false;
439  
422                        // Get cursor data even on a screen, to set the right cursor image when switching back to a window
440                          // Image
441                          uint32 cursor = ReadMacInt32(param);    // Pointer to CursorImage
442                          uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap);
443                          if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0)
444                                  return controlErr;
445                          uint32 pixmap = ReadMacInt32(pmhandle);
446 <                        if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) {
447 <                                memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32);
448 <                                changed = true;
449 <                        }
446 >
447 >                        // XXX: only certain image formats are handled properly at the moment
448 >                        uint16 rowBytes = ReadMacInt16(pixmap + 4) & 0x7FFF;
449 >                        if (rowBytes != 2)
450 >                                return controlErr;
451  
452                          // Mask
453                          uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask);
454                          if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0)
455                                  return controlErr;
456                          uint32 bitmap = ReadMacInt32(bmhandle);
457 +
458 +                        // Get cursor data even on a screen, to set the right cursor image when switching back to a window.
459 +                        // Hotspot is stale, but will be fixed by the next call to DrawHardwareCursor, which is likely to
460 +                        // occur immediately hereafter.
461 +
462 +                        if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) {
463 +                                memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32);
464 +                                changed = true;
465 +                        }
466                          if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) {
467                                  memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32);
468                                  changed = true;
469                          }
470  
444                        // Hotspot (!! this doesn't work)
445                        MacCursor[2] = ReadMacInt8(0x885);
446                        MacCursor[3] = ReadMacInt8(0x887);
447
471                          // Set new cursor image
472                          if (!video_can_change_cursor())
473                                  return controlErr;
# Line 452 | Line 475 | static int16 VideoControl(uint32 pb, Vid
475                                  video_set_cursor();
476  
477                          csSave->cursorSet = true;
478 +                        csSave->cursorHotFlag = true;
479                          return noErr;
480                  }
481  
482 <                case cscDrawHardwareCursor:
482 >                case cscDrawHardwareCursor: {
483   //                      D(bug("DrawHardwareCursor\n"));
484 +
485 +                        if (!csSave->cursorHardware)
486 +                                return controlErr;
487 +
488 +                        int32 oldX = csSave->cursorX;
489 +                        int32 oldY = csSave->cursorY;
490 +                        uint32 oldVisible = csSave->cursorVisible;
491 +
492                          csSave->cursorX = ReadMacInt32(param + csCursorX);
493                          csSave->cursorY = ReadMacInt32(param + csCursorY);
494                          csSave->cursorVisible = ReadMacInt32(param + csCursorVisible);
495 +                        bool changed = (csSave->cursorVisible != oldVisible);
496 +
497 +                        // If this is the first DrawHardwareCursor call since the cursor was last set (via SetHardwareCursor),
498 +                        // attempt to set an appropriate cursor hotspot.  SetHardwareCursor itself does not know what the
499 +                        // hotspot should be; it knows only the cursor image and mask.  The hotspot is known only to the caller,
500 +                        // and we have to try to infer it here.  The usual sequence of calls when changing the cursor is:
501 +                        //
502 +                        //      DrawHardwareCursor with (oldX, oldY, invisible)
503 +                        //      SetHardwareCursor with (cursor)
504 +                        //      DrawHardwareCursor with (newX, newY, visible)
505 +                        //
506 +                        // The key thing to note is that the sequence is intended not to change the current screen pixel location
507 +                        // indicated by the hotspot.  Thus, the difference between (newX, newY) and (oldX, oldY) reflects precisely
508 +                        // the difference between the old cursor hotspot and the new one.  For example, if you change from a
509 +                        // cursor whose hotspot is (1, 1) to one whose hotspot is (7, 4), then you must adjust the cursor position
510 +                        // by (-6, -3) in order for the same screen pixel to remain under the new hotspot.
511 +                        //
512 +                        // Alas, on rare occasions this heuristic can fail, and if you did nothing else you could even get stuck
513 +                        // with the wrong hotspot from then on.  To address that possibility, we force the hotspot to (1, 1)
514 +                        // whenever the cursor being drawn is the standard arrow.  Thus, while it is very unlikely that you will
515 +                        // ever have the wrong hotspot, if you do, it is easy to recover.
516 +
517 +                        if (csSave->cursorHotFlag) {
518 +                                csSave->cursorHotFlag = false;
519 +                                D(bug("old hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY));
520 +
521 +                                static uint8 arrow[] = {
522 +                                        0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00,
523 +                                        0x7F, 0x80, 0x7C, 0x00, 0x6C, 0x00, 0x46, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
524 +                                };
525 +                                if (memcmp(MacCursor + 4, arrow, 32) == 0) {
526 +                                        csSave->cursorHotX = 1;
527 +                                        csSave->cursorHotY = 1;
528 +                                } else if (csSave->cursorX != oldX || csSave->cursorY != oldY) {
529 +                                        int32 hotX = csSave->cursorHotX + (oldX - csSave->cursorX);
530 +                                        int32 hotY = csSave->cursorHotY + (oldY - csSave->cursorY);
531 +
532 +                                        if (0 <= hotX && hotX <= 15 && 0 <= hotY && hotY <= 15) {
533 +                                                csSave->cursorHotX = hotX;
534 +                                                csSave->cursorHotY = hotY;
535 +                                        }
536 +                                }
537 +                                if (MacCursor[2] != csSave->cursorHotX || MacCursor[3] != csSave->cursorHotY) {
538 +                                        MacCursor[2] = csSave->cursorHotX;
539 +                                        MacCursor[3] = csSave->cursorHotY;
540 +                                        changed = true;
541 +                                }
542 +                                D(bug("new hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY));
543 +                        }
544 +
545 +                        if (changed && video_can_change_cursor())
546 +                                video_set_cursor();
547 +
548                          return noErr;
549 +                }
550  
551                  case 43: {      // Driver Gestalt
552                          uint32 sel = ReadMacInt32(pb + csParam);
# Line 859 | Line 945 | static int16 VideoStatus(uint32 pb, VidL
945  
946                  case cscSupportsHardwareCursor:
947                          D(bug("SupportsHardwareCursor\n"));
948 <                        WriteMacInt32(param, 1);
948 >                        WriteMacInt32(param, csSave->cursorHardware);
949                          return noErr;
950  
951                  case cscGetHardwareCursorDrawState:
952                          D(bug("GetHardwareCursorDrawState\n"));
953 +
954 +                        if (!csSave->cursorHardware)
955 +                                return statusErr;
956 +
957                          WriteMacInt32(param + csCursorX, csSave->cursorX);
958                          WriteMacInt32(param + csCursorY, csSave->cursorY);
959                          WriteMacInt32(param + csCursorVisible, csSave->cursorVisible);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines