2004-09-21 02:50:02 +04:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Copyright (c) 2001-2002, Haiku, Inc.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
//
|
|
|
|
// File Name: CursorHandler.cpp
|
|
|
|
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
|
|
|
// Description: class for handling cursor display for DisplayDriver
|
|
|
|
//
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "CursorHandler.h"
|
|
|
|
#include "DisplayDriver.h"
|
|
|
|
#include "RectUtils.h"
|
|
|
|
|
|
|
|
CursorHandler::CursorHandler(DisplayDriver *driver)
|
|
|
|
: fDriver(driver),
|
|
|
|
fOldPosition(0,0,0,0),
|
|
|
|
fPosition(0,0,0,0),
|
|
|
|
fCursorPos(0,0),
|
|
|
|
fSavedData(NULL),
|
|
|
|
fCursor(NULL),
|
|
|
|
fHideLevel(0),
|
2005-03-25 20:29:20 +03:00
|
|
|
fDrawData(),
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriverHidden(false),
|
|
|
|
fIsObscured(false),
|
|
|
|
fValidSaveData(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Frees any memory used for saving screen data
|
|
|
|
CursorHandler::~CursorHandler(void)
|
|
|
|
{
|
|
|
|
delete fSavedData;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Tests to see if the passed rectangle intersects the cursor's current position
|
|
|
|
\param r The rectangle to test against
|
|
|
|
\return true if r intersects the cursor's current screen footprint
|
|
|
|
*/
|
|
|
|
bool CursorHandler::IntersectsCursor(const BRect &r)
|
|
|
|
{
|
|
|
|
return TestRectIntersection(r, fPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CursorHandler::SetCursor(ServerCursor *cursor)
|
|
|
|
{
|
|
|
|
// we may start empty, but we will never need to stay that way
|
|
|
|
if(!cursor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Hide();
|
|
|
|
|
|
|
|
if(fSavedData && cursor->Bounds()!=fSavedData->Bounds())
|
|
|
|
{
|
|
|
|
delete fSavedData;
|
|
|
|
fSavedData=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!fSavedData)
|
|
|
|
fSavedData=new UtilityBitmap(cursor);
|
|
|
|
|
|
|
|
fCursor=cursor;
|
|
|
|
|
|
|
|
// We change the position rectangles to reflect the new cursor, compensating for the
|
|
|
|
// new cursor's hotspot.
|
|
|
|
fPosition=cursor->Bounds().OffsetToCopy(fCursorPos.x-fCursor->GetHotSpot().x,
|
|
|
|
fCursorPos.y-fCursor->GetHotSpot().y);
|
|
|
|
fOldPosition=fPosition;
|
|
|
|
|
|
|
|
Show();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Moves the cursor to the specified place on screen
|
|
|
|
\param pt The new cursor location
|
|
|
|
|
|
|
|
This function fails if asked to move the cursor outside the screen boundaries
|
|
|
|
*/
|
2005-03-25 20:29:20 +03:00
|
|
|
void CursorHandler::MoveTo(BPoint pt)
|
2004-09-21 02:50:02 +04:00
|
|
|
{
|
2005-03-25 20:29:20 +03:00
|
|
|
pt.x = max_c(pt.x, 0.0);
|
|
|
|
pt.y = max_c(pt.y, 0.0);
|
|
|
|
pt.x = min_c(pt.x, fDriver->DisplayMode()->virtual_width - 1);
|
|
|
|
pt.y = min_c(pt.y, fDriver->DisplayMode()->virtual_height - 1);
|
|
|
|
|
|
|
|
if (fCursorPos != pt) {
|
2004-09-21 02:50:02 +04:00
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fCursorPos=pt;
|
|
|
|
|
|
|
|
if (!fSavedData)
|
|
|
|
debugger("NULL savedata\n");
|
|
|
|
|
|
|
|
fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData);
|
|
|
|
fPosition.OffsetTo(fCursorPos.x-fCursor->GetHotSpot().x,
|
|
|
|
fCursorPos.y-fCursor->GetHotSpot().y);
|
|
|
|
fDriver->CopyToBitmap(fSavedData,fPosition);
|
|
|
|
|
|
|
|
fDrawData.draw_mode=B_OP_ALPHA;
|
|
|
|
fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&fDrawData);
|
|
|
|
fDrawData.draw_mode=B_OP_COPY;
|
|
|
|
|
|
|
|
fDriver->Invalidate(fOldPosition);
|
|
|
|
fOldPosition=fPosition;
|
|
|
|
|
|
|
|
fDriver->Invalidate(fPosition);
|
|
|
|
}
|
2004-09-21 02:50:02 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Shows the cursor. Unlike BView, calls are not cumulative
|
|
|
|
void CursorHandler::Show(void)
|
|
|
|
{
|
|
|
|
// This call is pretty simple -- save the area underneath the cursor and draw the thing
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
if (fHideLevel == 0)
|
2004-09-21 02:50:02 +04:00
|
|
|
return;
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fIsObscured = false;
|
2004-09-21 02:50:02 +04:00
|
|
|
fHideLevel--;
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
if (fHideLevel > 0)
|
2004-09-21 02:50:02 +04:00
|
|
|
return;
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fOldPosition = fPosition;
|
2004-09-21 02:50:02 +04:00
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
if (!fCursor)
|
2004-09-21 02:50:02 +04:00
|
|
|
return;
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fValidSaveData = true;
|
2004-09-21 02:50:02 +04:00
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
if (!fSavedData)
|
|
|
|
fSavedData = new UtilityBitmap(fCursor->Bounds(),
|
|
|
|
(color_space)fDriver->DisplayMode()->space, 0);
|
2004-09-21 02:50:02 +04:00
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fDriver->CopyToBitmap(fSavedData, fPosition);
|
2004-09-21 02:50:02 +04:00
|
|
|
|
|
|
|
// Draw the data to the buffer
|
2005-03-25 20:29:20 +03:00
|
|
|
fDrawData.draw_mode = B_OP_ALPHA;
|
|
|
|
fDriver->CopyBitmap(fCursor, fCursor->Bounds(), fPosition, &fDrawData);
|
|
|
|
fDrawData.draw_mode = B_OP_COPY;
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriver->Invalidate(fPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Hides the cursor. Unlike BView, calls are not cumulative
|
|
|
|
void CursorHandler::Hide(void)
|
|
|
|
{
|
|
|
|
fHideLevel++;
|
|
|
|
|
|
|
|
// TODO: find out what the behavior is if a Hide is called on an obscured cursor
|
|
|
|
|
|
|
|
// For now, we will change the state from obscured to hidden and leave it at that
|
|
|
|
if(fIsObscured)
|
|
|
|
{
|
|
|
|
fIsObscured=false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fHideLevel>1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(!fCursor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(!fSavedData)
|
|
|
|
fSavedData=new UtilityBitmap(fCursor);
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData);
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriver->Invalidate(fPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Hides the cursor until the next MoveTo call. Unlike BView, calls are not cumulative
|
|
|
|
void CursorHandler::Obscure(void)
|
|
|
|
{
|
|
|
|
if(IsObscured())
|
|
|
|
return;
|
|
|
|
|
|
|
|
fIsObscured=true;
|
|
|
|
|
|
|
|
// TODO: find out what the behavior is if an Obscure is called on a hidden cursor
|
|
|
|
|
|
|
|
// For now, we will change the state from obscured to hidden and leave it at that
|
|
|
|
if(fHideLevel>0)
|
|
|
|
{
|
|
|
|
fHideLevel=0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData);
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriver->Invalidate(fPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CursorHandler::DriverHide(void)
|
|
|
|
{
|
|
|
|
if(fDriverHidden)
|
|
|
|
return;
|
2004-09-22 03:10:23 +04:00
|
|
|
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriverHidden=true;
|
|
|
|
|
|
|
|
if(!fCursor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(!fSavedData)
|
|
|
|
fSavedData=new UtilityBitmap(fCursor);
|
|
|
|
|
2005-03-25 20:29:20 +03:00
|
|
|
fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData);
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriver->Invalidate(fPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CursorHandler::DriverShow(void)
|
|
|
|
{
|
|
|
|
if(!fDriverHidden)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fDriverHidden=false;
|
|
|
|
|
|
|
|
fOldPosition=fPosition;
|
|
|
|
|
|
|
|
if(!fCursor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fValidSaveData=true;
|
|
|
|
|
|
|
|
if(!fSavedData)
|
2005-03-25 20:29:20 +03:00
|
|
|
fSavedData=new UtilityBitmap(fCursor->Bounds(),(color_space)fDriver->DisplayMode()->space,0);
|
2004-09-21 02:50:02 +04:00
|
|
|
|
|
|
|
fDriver->CopyToBitmap(fSavedData,fPosition);
|
|
|
|
|
|
|
|
// Draw the data to the buffer
|
2005-03-25 20:29:20 +03:00
|
|
|
fDrawData.draw_mode=B_OP_ALPHA;
|
|
|
|
fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&fDrawData);
|
|
|
|
fDrawData.draw_mode=B_OP_COPY;
|
2004-09-21 02:50:02 +04:00
|
|
|
fDriver->Invalidate(fPosition);
|
|
|
|
}
|