Fix for bug 78363 "Beachball in Mac `spinning' cursor should actually spin".

r=pinkerton@netscape.com sr=sfraser@netscape.com
This commit is contained in:
lordpixel%mac.com 2003-05-26 17:41:19 +00:00
parent 8dc2f15ba0
commit 6fd343ec43
2 changed files with 145 additions and 111 deletions

View File

@ -84,6 +84,10 @@ nsIWidget * gRollupWidget = nsnull;
static NMRec gNMRec;
static Boolean gNotificationInstalled = false;
//used to animate the Arrow + Beachball cursor
static CursorSpinner *gCursorSpinner = nsnull;
static const int kSpinCursorFirstFrame = 200;
// Routines for iterating over the rects of a region. Carbon and pre-Carbon
// do this differently so provide a way to do both.
#if TARGET_CARBON
@ -105,13 +109,14 @@ static void blinkRect(const Rect* r, PRBool isPaint);
static void blinkRgn(RgnHandle rgn, PRBool isPaint);
#endif
#if defined(INVALIDATE_DEBUGGING) || defined(PAINT_DEBUGGING) || defined (PINK_PROFILING)
static Boolean KeyDown(const UInt8 theKey)
{
KeyMap map;
GetKeys(map);
return ((*((UInt8 *)map + (theKey >> 3)) >> (theKey & 7)) & 1) != 0;
}
#endif
#if defined(INVALIDATE_DEBUGGING) || defined(PAINT_DEBUGGING)
@ -698,129 +703,142 @@ NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
{
nsBaseWidget::SetCursor(aCursor);
// allow the cursor to be set internally if we're in the bg, but
// don't actually set it.
// allow the cursor to be set internally if we're in the bg, but
// don't actually set it.
if ( !nsToolkit::IsAppInForeground() )
{
return NS_OK;
}
if ( gCursorSpinner == nsnull)
{
gCursorSpinner = new CursorSpinner();
}
// mac specific cursor manipulation
if (nsToolkit::HasAppearanceManager())
{
short cursor = -1;
switch (aCursor)
{
case eCursor_standard: cursor = kThemeArrowCursor; break;
case eCursor_wait: cursor = kThemeWatchCursor; break;
case eCursor_select: cursor = kThemeIBeamCursor; break;
case eCursor_hyperlink: cursor = kThemePointingHandCursor; break;
case eCursor_sizeWE: cursor = kThemeResizeLeftRightCursor; break;
case eCursor_sizeNS: cursor = 129; break;
case eCursor_sizeNW: cursor = 130; break;
case eCursor_sizeSE: cursor = 131; break;
case eCursor_sizeNE: cursor = 132; break;
case eCursor_sizeSW: cursor = 133; break;
case eCursor_arrow_north: cursor = 134; break;
case eCursor_arrow_north_plus:cursor = 135; break;
case eCursor_arrow_south: cursor = 136; break;
case eCursor_arrow_south_plus:cursor = 137; break;
case eCursor_arrow_west: cursor = 138; break;
case eCursor_arrow_west_plus: cursor = 139; break;
case eCursor_arrow_east: cursor = 140; break;
case eCursor_arrow_east_plus: cursor = 141; break;
case eCursor_crosshair: cursor = kThemeCrossCursor; break;
case eCursor_move: cursor = kThemeOpenHandCursor; break;
case eCursor_help: cursor = 143; break;
case eCursor_copy: cursor = 144; break; // CSS3
case eCursor_alias: cursor = 145; break;
case eCursor_context_menu: cursor = 146; break;
case eCursor_cell: cursor = kThemePlusCursor; break;
case eCursor_grab: cursor = kThemeOpenHandCursor; break;
case eCursor_grabbing: cursor = kThemeClosedHandCursor; break;
case eCursor_spinning: cursor = 149; break; // better than kThemeSpinningCursor
case eCursor_count_up: cursor = kThemeCountingUpHandCursor; break;
case eCursor_count_down: cursor = kThemeCountingDownHandCursor; break;
case eCursor_count_up_down: cursor = kThemeCountingUpAndDownHandCursor; break;
case eCursor_zoom_in: cursor = 150; break;
case eCursor_zoom_out: cursor = 151; break;
short cursor = -1;
switch (aCursor)
{
case eCursor_standard: cursor = kThemeArrowCursor; break;
case eCursor_wait: cursor = kThemeWatchCursor; break;
case eCursor_select: cursor = kThemeIBeamCursor; break;
case eCursor_hyperlink: cursor = kThemePointingHandCursor; break;
case eCursor_sizeWE: cursor = kThemeResizeLeftRightCursor; break;
case eCursor_sizeNS: cursor = 129; break;
case eCursor_sizeNW: cursor = 130; break;
case eCursor_sizeSE: cursor = 131; break;
case eCursor_sizeNE: cursor = 132; break;
case eCursor_sizeSW: cursor = 133; break;
case eCursor_arrow_north: cursor = 134; break;
case eCursor_arrow_north_plus: cursor = 135; break;
case eCursor_arrow_south: cursor = 136; break;
case eCursor_arrow_south_plus: cursor = 137; break;
case eCursor_arrow_west: cursor = 138; break;
case eCursor_arrow_west_plus: cursor = 139; break;
case eCursor_arrow_east: cursor = 140; break;
case eCursor_arrow_east_plus: cursor = 141; break;
case eCursor_crosshair: cursor = kThemeCrossCursor; break;
case eCursor_move: cursor = kThemeOpenHandCursor; break;
case eCursor_help: cursor = 143; break;
case eCursor_copy: cursor = 144; break; // CSS3
case eCursor_alias: cursor = 145; break;
case eCursor_context_menu: cursor = 146; break;
case eCursor_cell: cursor = kThemePlusCursor; break;
case eCursor_grab: cursor = kThemeOpenHandCursor; break;
case eCursor_grabbing: cursor = kThemeClosedHandCursor; break;
case eCursor_spinning: cursor = kSpinCursorFirstFrame; break; // better than kThemeSpinningCursor
case eCursor_count_up: cursor = kThemeCountingUpHandCursor; break;
case eCursor_count_down: cursor = kThemeCountingDownHandCursor; break;
case eCursor_count_up_down: cursor = kThemeCountingUpAndDownHandCursor; break;
case eCursor_zoom_in: cursor = 149; break;
case eCursor_zoom_out: cursor = 150; break;
}
}
if (cursor >= 0)
{
if (cursor >= 128)
{
nsMacResources::OpenLocalResourceFile();
CursHandle cursHandle = ::GetCursor(cursor);
NS_ASSERTION ( cursHandle, "Can't load cursor, is the resource file installed correctly?" );
if ( cursHandle )
::SetCursor(*cursHandle);
nsMacResources::CloseLocalResourceFile();
}
else
::SetThemeCursor(cursor);
}
if (aCursor == eCursor_spinning)
{
gCursorSpinner->StartSpinCursor();
}
else
{
short cursor = -1;
switch (aCursor)
{
case eCursor_standard: ::InitCursor(); break;
case eCursor_wait: cursor = watchCursor; break;
case eCursor_select: cursor = iBeamCursor; break;
case eCursor_hyperlink: cursor = plusCursor; break;
case eCursor_sizeWE: cursor = 128; break;
case eCursor_sizeNS: cursor = 129; break;
case eCursor_sizeNW: cursor = 130; break;
case eCursor_sizeSE: cursor = 131; break;
case eCursor_sizeNE: cursor = 132; break;
case eCursor_sizeSW: cursor = 133; break;
case eCursor_arrow_north: cursor = 134; break;
case eCursor_arrow_north_plus:cursor = 135; break;
case eCursor_arrow_south: cursor = 136; break;
case eCursor_arrow_south_plus:cursor = 137; break;
case eCursor_arrow_west: cursor = 138; break;
case eCursor_arrow_west_plus: cursor = 139; break;
case eCursor_arrow_east: cursor = 140; break;
case eCursor_arrow_east_plus: cursor = 141; break;
case eCursor_crosshair: cursor = crossCursor; break;
case eCursor_move: cursor = 142; break;
case eCursor_help: cursor = 143; break;
case eCursor_copy: cursor = 144; break; // CSS3
case eCursor_alias: cursor = 145; break;
case eCursor_context_menu: cursor = 146; break;
case eCursor_cell: cursor = plusCursor; break;
case eCursor_grab: cursor = 147; break;
case eCursor_grabbing: cursor = 148; break;
case eCursor_spinning: cursor = 149; break;
case eCursor_count_up: cursor = watchCursor; break;
case eCursor_count_down: cursor = watchCursor; break;
case eCursor_count_up_down: cursor = watchCursor; break;
case eCursor_zoom_in: cursor = 150; break;
case eCursor_zoom_out: cursor = 151; break;
}
if (cursor > 0)
{
if (cursor >= 128) {
nsMacResources::OpenLocalResourceFile();
CursHandle cursHandle = ::GetCursor(cursor);
NS_ASSERTION ( cursHandle, "Can't load cursor, is the resource file installed correctly?" );
if ( cursHandle )
::SetCursor(*cursHandle);
nsMacResources::CloseLocalResourceFile();
}
else {
CursHandle cursHandle = ::GetCursor(cursor);
NS_ASSERTION ( cursHandle, "Can't load cursor, is the resource file installed correctly?" );
if ( cursHandle )
::SetCursor(*cursHandle);
}
}
gCursorSpinner->StopSpinCursor();
nsWindow::SetCursorResource(cursor);
}
return NS_OK;
} // nsWindow::SetCursor
void nsWindow::SetCursorResource(short aCursorResourceNum)
{
if (aCursorResourceNum >= 0)
{
if (aCursorResourceNum >= 128)
{
nsMacResources::OpenLocalResourceFile();
CursHandle cursHandle = ::GetCursor(aCursorResourceNum);
NS_ASSERTION (cursHandle, "Can't load cursor, is the resource file installed correctly?");
if (cursHandle)
{
::SetCursor(*cursHandle);
}
nsMacResources::CloseLocalResourceFile();
}
else
{
::SetThemeCursor(aCursorResourceNum);
}
}
}
CursorSpinner::CursorSpinner() :
mSpinCursorFrame(0), mTimerUPP(nsnull), mTimerRef(nsnull)
{
mTimerUPP = NewEventLoopTimerUPP(SpinCursor);
}
CursorSpinner::~CursorSpinner()
{
if (mTimerRef) ::RemoveEventLoopTimer(mTimerRef);
if (mTimerUPP) ::DisposeEventLoopTimerUPP(mTimerUPP);
}
short CursorSpinner::GetNextCursorFrame()
{
int result = kSpinCursorFirstFrame + mSpinCursorFrame;
mSpinCursorFrame = (mSpinCursorFrame + 1) % 4;
return (short) result;
}
void CursorSpinner::StartSpinCursor()
{
OSStatus result = noErr;
if (mTimerRef == nsnull)
{
result = ::InstallEventLoopTimer(::GetMainEventLoop(), 0, 0.25 * kEventDurationSecond,
mTimerUPP, this, &mTimerRef);
if (result != noErr)
{
mTimerRef = nsnull;
nsWindow::SetCursorResource(kSpinCursorFirstFrame);
}
}
}
void CursorSpinner::StopSpinCursor()
{
if (mTimerRef)
{
::RemoveEventLoopTimer(mTimerRef);
mTimerRef = nsnull;
}
}
pascal void CursorSpinner::SpinCursor(EventLoopTimerRef inTimer, void *inUserData)
{
CursorSpinner* cs = reinterpret_cast<CursorSpinner*>(inUserData);
nsWindow::SetCursorResource(cs->GetNextCursorFrame());
}
#pragma mark -
//-------------------------------------------------------------------------
//

View File

@ -74,6 +74,21 @@ typedef struct TRectArray
} TRectArray;
class CursorSpinner {
public:
CursorSpinner();
~CursorSpinner();
void StartSpinCursor();
void StopSpinCursor();
private:
short mSpinCursorFrame;
EventLoopTimerUPP mTimerUPP;
EventLoopTimerRef mTimerRef;
short GetNextCursorFrame();
static pascal void SpinCursor(EventLoopTimerRef inTimer, void *inUserData);
};
//-------------------------------------------------------------------------
//
@ -180,7 +195,8 @@ public:
NS_IMETHOD SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight);
NS_IMETHOD SetCursor(nsCursor aCursor);
static void SetCursorResource(short aCursorResourceNum);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD SetTitle(const nsString& title);