//------------------------------------------------------------------------------ // 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 // 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), fDrawData(), 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 */ void CursorHandler::MoveTo(BPoint pt) { 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) { 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); } } //! 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 if (fHideLevel == 0) return; fIsObscured = false; fHideLevel--; if (fHideLevel > 0) return; fOldPosition = fPosition; if (!fCursor) return; fValidSaveData = true; if (!fSavedData) fSavedData = new UtilityBitmap(fCursor->Bounds(), (color_space)fDriver->DisplayMode()->space, 0); fDriver->CopyToBitmap(fSavedData, fPosition); // Draw the data to the buffer fDrawData.draw_mode = B_OP_ALPHA; fDriver->CopyBitmap(fCursor, fCursor->Bounds(), fPosition, &fDrawData); fDrawData.draw_mode = B_OP_COPY; 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); fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); 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; } fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); fDriver->Invalidate(fPosition); } void CursorHandler::DriverHide(void) { if(fDriverHidden) return; fDriverHidden=true; if(!fCursor) return; if(!fSavedData) fSavedData=new UtilityBitmap(fCursor); fDriver->CopyBitmap(fSavedData,fSavedData->Bounds(),fOldPosition,&fDrawData); fDriver->Invalidate(fPosition); } void CursorHandler::DriverShow(void) { if(!fDriverHidden) return; fDriverHidden=false; fOldPosition=fPosition; if(!fCursor) return; fValidSaveData=true; if(!fSavedData) fSavedData=new UtilityBitmap(fCursor->Bounds(),(color_space)fDriver->DisplayMode()->space,0); fDriver->CopyToBitmap(fSavedData,fPosition); // Draw the data to the buffer fDrawData.draw_mode=B_OP_ALPHA; fDriver->CopyBitmap(fCursor,fCursor->Bounds(),fPosition,&fDrawData); fDrawData.draw_mode=B_OP_COPY; fDriver->Invalidate(fPosition); }