21 |
|
/* |
22 |
|
* TODO |
23 |
|
* - check for supported modes ??? |
24 |
– |
* - window mode "hardware" cursor hotspot |
24 |
|
*/ |
25 |
|
|
26 |
|
#include <stdio.h> |
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 |
|
|
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; |
213 |
|
|
214 |
|
static int16 set_gamma(VidLocals *csSave, uint32 gamma) |
215 |
|
{ |
202 |
– |
return paramErr; |
203 |
– |
|
216 |
|
if (gamma == 0) { // Build linear ramp, 256 entries |
217 |
|
|
218 |
|
// Allocate new table, if necessary |
428 |
|
|
429 |
|
case cscSetHardwareCursor: { |
430 |
|
// D(bug("SetHardwareCursor\n")); |
431 |
+ |
|
432 |
+ |
if (!csSave->cursorHardware) |
433 |
+ |
return controlErr; |
434 |
+ |
|
435 |
|
csSave->cursorSet = false; |
436 |
|
bool changed = false; |
437 |
|
|
422 |
– |
// Get cursor data even on a screen, to set the right cursor image when switching back to a window |
438 |
|
// Image |
439 |
|
uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage |
440 |
|
uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap); |
441 |
|
if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0) |
442 |
|
return controlErr; |
443 |
|
uint32 pixmap = ReadMacInt32(pmhandle); |
444 |
< |
if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) { |
445 |
< |
memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32); |
446 |
< |
changed = true; |
447 |
< |
} |
444 |
> |
|
445 |
> |
// XXX: only certain image formats are handled properly at the moment |
446 |
> |
uint16 rowBytes = ReadMacInt16(pixmap + 4) & 0x7FFF; |
447 |
> |
if (rowBytes != 2) |
448 |
> |
return controlErr; |
449 |
|
|
450 |
|
// Mask |
451 |
|
uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask); |
452 |
|
if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0) |
453 |
|
return controlErr; |
454 |
|
uint32 bitmap = ReadMacInt32(bmhandle); |
455 |
+ |
|
456 |
+ |
// Get cursor data even on a screen, to set the right cursor image when switching back to a window. |
457 |
+ |
// Hotspot is stale, but will be fixed by the next call to DrawHardwareCursor, which is likely to |
458 |
+ |
// occur immediately hereafter. |
459 |
+ |
|
460 |
+ |
if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) { |
461 |
+ |
memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32); |
462 |
+ |
changed = true; |
463 |
+ |
} |
464 |
|
if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) { |
465 |
|
memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32); |
466 |
|
changed = true; |
467 |
|
} |
468 |
|
|
444 |
– |
// Hotspot (!! this doesn't work) |
445 |
– |
MacCursor[2] = ReadMacInt8(0x885); |
446 |
– |
MacCursor[3] = ReadMacInt8(0x887); |
447 |
– |
|
469 |
|
// Set new cursor image |
470 |
|
if (!video_can_change_cursor()) |
471 |
|
return controlErr; |
473 |
|
video_set_cursor(); |
474 |
|
|
475 |
|
csSave->cursorSet = true; |
476 |
+ |
csSave->cursorHotFlag = true; |
477 |
|
return noErr; |
478 |
|
} |
479 |
|
|
480 |
< |
case cscDrawHardwareCursor: |
480 |
> |
case cscDrawHardwareCursor: { |
481 |
|
// D(bug("DrawHardwareCursor\n")); |
482 |
+ |
|
483 |
+ |
if (!csSave->cursorHardware) |
484 |
+ |
return controlErr; |
485 |
+ |
|
486 |
+ |
int32 oldX = csSave->cursorX; |
487 |
+ |
int32 oldY = csSave->cursorY; |
488 |
+ |
uint32 oldVisible = csSave->cursorVisible; |
489 |
+ |
|
490 |
|
csSave->cursorX = ReadMacInt32(param + csCursorX); |
491 |
|
csSave->cursorY = ReadMacInt32(param + csCursorY); |
492 |
|
csSave->cursorVisible = ReadMacInt32(param + csCursorVisible); |
493 |
+ |
bool changed = (csSave->cursorVisible != oldVisible); |
494 |
+ |
|
495 |
+ |
// If this is the first DrawHardwareCursor call since the cursor was last set (via SetHardwareCursor), |
496 |
+ |
// attempt to set an appropriate cursor hotspot. SetHardwareCursor itself does not know what the |
497 |
+ |
// hotspot should be; it knows only the cursor image and mask. The hotspot is known only to the caller, |
498 |
+ |
// and we have to try to infer it here. The usual sequence of calls when changing the cursor is: |
499 |
+ |
// |
500 |
+ |
// DrawHardwareCursor with (oldX, oldY, invisible) |
501 |
+ |
// SetHardwareCursor with (cursor) |
502 |
+ |
// DrawHardwareCursor with (newX, newY, visible) |
503 |
+ |
// |
504 |
+ |
// The key thing to note is that the sequence is intended not to change the current screen pixel location |
505 |
+ |
// indicated by the hotspot. Thus, the difference between (newX, newY) and (oldX, oldY) reflects precisely |
506 |
+ |
// the difference between the old cursor hotspot and the new one. For example, if you change from a |
507 |
+ |
// cursor whose hotspot is (1, 1) to one whose hotspot is (7, 4), then you must adjust the cursor position |
508 |
+ |
// by (-6, -3) in order for the same screen pixel to remain under the new hotspot. |
509 |
+ |
// |
510 |
+ |
// Alas, on rare occasions this heuristic can fail, and if you did nothing else you could even get stuck |
511 |
+ |
// with the wrong hotspot from then on. To address that possibility, we force the hotspot to (1, 1) |
512 |
+ |
// whenever the cursor being drawn is the standard arrow. Thus, while it is very unlikely that you will |
513 |
+ |
// ever have the wrong hotspot, if you do, it is easy to recover. |
514 |
+ |
|
515 |
+ |
if (csSave->cursorHotFlag) { |
516 |
+ |
csSave->cursorHotFlag = false; |
517 |
+ |
D(bug("old hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY)); |
518 |
+ |
|
519 |
+ |
static uint8 arrow[] = { |
520 |
+ |
0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, |
521 |
+ |
0x7F, 0x80, 0x7C, 0x00, 0x6C, 0x00, 0x46, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, |
522 |
+ |
}; |
523 |
+ |
if (memcmp(MacCursor + 4, arrow, 32) == 0) { |
524 |
+ |
csSave->cursorHotX = 1; |
525 |
+ |
csSave->cursorHotY = 1; |
526 |
+ |
} else if (csSave->cursorX != oldX || csSave->cursorY != oldY) { |
527 |
+ |
int32 hotX = csSave->cursorHotX + (oldX - csSave->cursorX); |
528 |
+ |
int32 hotY = csSave->cursorHotY + (oldY - csSave->cursorY); |
529 |
+ |
|
530 |
+ |
if (0 <= hotX && hotX <= 15 && 0 <= hotY && hotY <= 15) { |
531 |
+ |
csSave->cursorHotX = hotX; |
532 |
+ |
csSave->cursorHotY = hotY; |
533 |
+ |
} |
534 |
+ |
} |
535 |
+ |
if (MacCursor[2] != csSave->cursorHotX || MacCursor[3] != csSave->cursorHotY) { |
536 |
+ |
MacCursor[2] = csSave->cursorHotX; |
537 |
+ |
MacCursor[3] = csSave->cursorHotY; |
538 |
+ |
changed = true; |
539 |
+ |
} |
540 |
+ |
D(bug("new hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY)); |
541 |
+ |
} |
542 |
+ |
|
543 |
+ |
if (changed && video_can_change_cursor()) |
544 |
+ |
video_set_cursor(); |
545 |
+ |
|
546 |
|
return noErr; |
547 |
+ |
} |
548 |
|
|
549 |
|
case 43: { // Driver Gestalt |
550 |
|
uint32 sel = ReadMacInt32(pb + csParam); |
697 |
|
case cscGetGamma: // GetGamma |
698 |
|
D(bug("GetGamma\n")); |
699 |
|
WriteMacInt32(param, (uint32)csSave->gammaTable); |
700 |
< |
return statusErr; |
700 |
> |
return noErr; |
701 |
|
|
702 |
|
case cscGetDefaultMode: // GetDefaultMode |
703 |
|
D(bug("GetDefaultMode\n")); |
943 |
|
|
944 |
|
case cscSupportsHardwareCursor: |
945 |
|
D(bug("SupportsHardwareCursor\n")); |
946 |
< |
WriteMacInt32(param, 1); |
946 |
> |
WriteMacInt32(param, csSave->cursorHardware); |
947 |
|
return noErr; |
948 |
|
|
949 |
|
case cscGetHardwareCursorDrawState: |
950 |
|
D(bug("GetHardwareCursorDrawState\n")); |
951 |
+ |
|
952 |
+ |
if (!csSave->cursorHardware) |
953 |
+ |
return statusErr; |
954 |
+ |
|
955 |
|
WriteMacInt32(param + csCursorX, csSave->cursorX); |
956 |
|
WriteMacInt32(param + csCursorY, csSave->cursorY); |
957 |
|
WriteMacInt32(param + csCursorVisible, csSave->cursorVisible); |