implemented cursor support in the DisplayDriverPainter

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12107 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-03-28 18:03:45 +00:00
parent 31f3fbc45c
commit e33b90ea35
9 changed files with 537 additions and 327 deletions

View File

@ -38,8 +38,7 @@
\brief Sets up internal variables needed by all DisplayDriver subclasses
*/
DisplayDriver::DisplayDriver()
: fCursorHandler(this),
fDPMSState(B_DPMS_ON),
: fDPMSState(B_DPMS_ON),
fDPMSCaps(B_DPMS_ON)
{
fDisplayMode.virtual_width = 640;
@ -68,7 +67,7 @@ DisplayDriver::~DisplayDriver()
bool
DisplayDriver::Initialize()
{
fCursorHandler.SetCursor(new ServerCursor(default_cursor_data));
SetCursor(new ServerCursor(default_cursor_data));
return true;
}
@ -83,127 +82,6 @@ DisplayDriver::Shutdown()
{
}
/*!
\brief Hides the cursor.
Hide calls are not nestable, unlike that of the BApplication class. Subclasses should
call _SetCursorHidden(true) somewhere within this function to ensure that data is
maintained accurately. Subclasses must include a call to DisplayDriver::HideCursor
for proper state tracking.
*/
void
DisplayDriver::HideCursor()
{
Lock();
fCursorHandler.Hide();
Unlock();
}
/*!
\brief Returns whether the cursor is visible or not.
\return true if hidden or obscured, false if not.
*/
bool
DisplayDriver::IsCursorHidden()
{
Lock();
bool value = fCursorHandler.IsHidden();
Unlock();
return value;
}
/*!
\brief Moves the cursor to the given point.
The coordinates passed to MoveCursorTo are guaranteed to be within the frame buffer's
range, but the cursor data itself will need to be clipped. A check to see if the
cursor is obscured should be made and if so, a call to _SetCursorObscured(false)
should be made the cursor in addition to displaying at the passed coordinates.
*/
void
DisplayDriver::MoveCursorTo(const float &x, const float &y)
{
Lock();
fCursorHandler.MoveTo(BPoint(x, y));
Unlock();
}
/*!
\brief Shows the cursor.
Show calls are not nestable, unlike that of the BApplication class. Subclasses should
call _SetCursorHidden(false) somewhere within this function to ensure that data is
maintained accurately. Subclasses must call DisplayDriver::ShowCursor at some point
to ensure proper state tracking.
*/
void
DisplayDriver::ShowCursor()
{
Lock();
fCursorHandler.Show();
Unlock();
}
/*!
\brief Obscures the cursor.
Obscure calls are not nestable. Subclasses should call DisplayDriver::ObscureCursor
somewhere within this function to ensure that data is maintained accurately. A check
will be made by the system before the next MoveCursorTo call to show the cursor if
it is obscured.
*/
void
DisplayDriver::ObscureCursor()
{
Lock();
fCursorHandler.Obscure();
Unlock();
}
/*!
\brief Changes the cursor.
\param cursor The new cursor. Guaranteed to be non-NULL.
The driver does not take ownership of the given cursor. Subclasses should make
a copy of the cursor passed to it. The default version of this function hides the
cursory, replaces it, and shows the cursor if previously visible.
*/
void
DisplayDriver::SetCursor(ServerCursor *cursor)
{
Lock();
fCursorHandler.SetCursor(cursor);
Unlock();
}
//! Returns the cursor's current position
BPoint
DisplayDriver::GetCursorPosition()
{
Lock();
BPoint pos = fCursorHandler.GetPosition();
Unlock();
return pos;
}
/*!
\brief Returns whether or not the cursor is currently obscured
\return True if obscured, false if not.
*/
bool
DisplayDriver::IsCursorObscured(bool state)
{
Lock();
bool obscured = fCursorHandler.IsObscured();
Unlock();
return obscured;
}
// Protected Internal Functions
/*
\brief Sets the screen mode to specified resolution and color depth.

View File

@ -51,7 +51,8 @@ static Blitter blitter;
*/
DisplayDriverImpl::DisplayDriverImpl()
: DisplayDriver(),
fLocker("DisplayDriver lock")
fLocker("DisplayDriver lock"),
fCursorHandler(this)
{
}
@ -2272,6 +2273,127 @@ void DisplayDriverImpl::GetTruncatedStrings(const char **instrings,const int32 &
// TODO: Implement DisplayDriverImpl::GetTruncatedStrings
}
/*!
\brief Hides the cursor.
Hide calls are not nestable, unlike that of the BApplication class. Subclasses should
call _SetCursorHidden(true) somewhere within this function to ensure that data is
maintained accurately. Subclasses must include a call to DisplayDriver::HideCursor
for proper state tracking.
*/
void
DisplayDriverImpl::HideCursor()
{
Lock();
fCursorHandler.Hide();
Unlock();
}
/*!
\brief Returns whether the cursor is visible or not.
\return true if hidden or obscured, false if not.
*/
bool
DisplayDriverImpl::IsCursorHidden()
{
Lock();
bool value = fCursorHandler.IsHidden();
Unlock();
return value;
}
/*!
\brief Moves the cursor to the given point.
The coordinates passed to MoveCursorTo are guaranteed to be within the frame buffer's
range, but the cursor data itself will need to be clipped. A check to see if the
cursor is obscured should be made and if so, a call to _SetCursorObscured(false)
should be made the cursor in addition to displaying at the passed coordinates.
*/
void
DisplayDriverImpl::MoveCursorTo(const float &x, const float &y)
{
Lock();
fCursorHandler.MoveTo(BPoint(x, y));
Unlock();
}
/*!
\brief Shows the cursor.
Show calls are not nestable, unlike that of the BApplication class. Subclasses should
call _SetCursorHidden(false) somewhere within this function to ensure that data is
maintained accurately. Subclasses must call DisplayDriver::ShowCursor at some point
to ensure proper state tracking.
*/
void
DisplayDriverImpl::ShowCursor()
{
Lock();
fCursorHandler.Show();
Unlock();
}
/*!
\brief Obscures the cursor.
Obscure calls are not nestable. Subclasses should call DisplayDriver::ObscureCursor
somewhere within this function to ensure that data is maintained accurately. A check
will be made by the system before the next MoveCursorTo call to show the cursor if
it is obscured.
*/
void
DisplayDriverImpl::ObscureCursor()
{
Lock();
fCursorHandler.Obscure();
Unlock();
}
/*!
\brief Changes the cursor.
\param cursor The new cursor. Guaranteed to be non-NULL.
The driver does not take ownership of the given cursor. Subclasses should make
a copy of the cursor passed to it. The default version of this function hides the
cursory, replaces it, and shows the cursor if previously visible.
*/
void
DisplayDriverImpl::SetCursor(ServerCursor *cursor)
{
Lock();
fCursorHandler.SetCursor(cursor);
Unlock();
}
//! Returns the cursor's current position
BPoint
DisplayDriverImpl::GetCursorPosition()
{
Lock();
BPoint pos = fCursorHandler.GetPosition();
Unlock();
return pos;
}
/*!
\brief Returns whether or not the cursor is currently obscured
\return True if obscured, false if not.
*/
bool
DisplayDriverImpl::IsCursorObscured(bool state)
{
Lock();
bool obscured = fCursorHandler.IsObscured();
Unlock();
return obscured;
}
/*!
\brief Locks the driver
\param timeout Optional timeout specifier

View File

@ -128,7 +128,7 @@ DisplayDriverPainter::CopyRegionList(BList* list, BList* pList,
if (!clipReg || !Lock())
return;
// This is the same implementation as in DisplayDriverImpl for now
// This is the same implementation as in DisplayDriverPainter for now
// since we're not using painter.... this won't do much good, will it?
// fPainter->ConstrainClipping(*clipReg);
@ -755,6 +755,65 @@ DisplayDriverPainter::GetTruncatedStrings(const char **instrings,
printf("DisplayDriverPainter::GetTruncatedStrings()\n");
}
// HideCursor
void
DisplayDriverPainter::HideCursor()
{
fGraphicsCard->SetCursorVisible(false);
}
// IsCursorHidden
bool
DisplayDriverPainter::IsCursorHidden()
{
return !fGraphicsCard->IsCursorVisible();
}
// MoveCursorTo
void
DisplayDriverPainter::MoveCursorTo(const float &x, const float &y)
{
fGraphicsCard->MoveCursorTo(x, y);
}
// ShowCursor
void
DisplayDriverPainter::ShowCursor()
{
fGraphicsCard->SetCursorVisible(true);
}
// ObscureCursor
void
DisplayDriverPainter::ObscureCursor()
{
// TODO: I don't think this has anything to do with the DisplayDriver
// implement elsewhere!!
}
// SetCursor
void
DisplayDriverPainter::SetCursor(ServerCursor *cursor)
{
fGraphicsCard->SetCursor(cursor);
}
// GetCursorPosition
BPoint
DisplayDriverPainter::GetCursorPosition()
{
return fGraphicsCard->GetCursorPosition();
}
// IsCursorObscured
bool
DisplayDriverPainter::IsCursorObscured(bool state)
{
// TODO: I don't think this has anything to do with the DisplayDriver
// implement elsewhere!!
return false;
}
// Lock
bool
DisplayDriverPainter::Lock(bigtime_t timeout)

View File

@ -217,10 +217,8 @@ class DisplayDriverPainter : public DisplayDriver {
const float &maxwidth,
char **outstrings);
virtual bool Lock(bigtime_t timeout = B_INFINITE_TIMEOUT);
virtual void Unlock();
/* virtual void HideCursor();
// cursor handling
virtual void HideCursor();
virtual bool IsCursorHidden();
virtual void MoveCursorTo( const float &x,
const float &y);
@ -228,9 +226,12 @@ class DisplayDriverPainter : public DisplayDriver {
virtual void ObscureCursor();
virtual void SetCursor(ServerCursor *cursor);
BPoint GetCursorPosition();
virtual bool IsCursorObscured(bool state);*/
virtual bool IsCursorObscured(bool state);
virtual bool Lock(bigtime_t timeout = B_INFINITE_TIMEOUT);
virtual void Unlock();
// display mode access
virtual void SetMode(const display_mode &mode);

View File

@ -1,14 +1,106 @@
// HWInterface.cpp
#include "ServerCursor.h"
#include "HWInterface.h"
// constructor
HWInterface::HWInterface()
: BLocker("hw interface lock")
: BLocker("hw interface lock"),
fCursor(NULL),
fCursorVisible(true),
fCursorLocation(0.5, 0.5)
{
}
// destructor
HWInterface::~HWInterface()
{
delete fCursor;
}
// SetCursor
void
HWInterface::SetCursor(ServerCursor* cursor)
{
if (Lock()) {
if (fCursor != cursor) {
BRect oldFrame = _CursorFrame();
delete fCursor;
fCursor = cursor;
Invalidate(oldFrame);
Invalidate(_CursorFrame());
}
Unlock();
}
}
// SetCursorVisible
void
HWInterface::SetCursorVisible(bool visible)
{
if (Lock()) {
if (fCursorVisible != visible) {
fCursorVisible = visible;
Invalidate(_CursorFrame());
}
Unlock();
}
}
// IsCursorVisible
bool
HWInterface::IsCursorVisible()
{
bool visible = true;
if (Lock()) {
visible = fCursorVisible;
Unlock();
}
return visible;
}
// MoveCursorTo
void
HWInterface::MoveCursorTo(const float& x, const float& y)
{
if (Lock()) {
BPoint p(x, y);
if (p != fCursorLocation) {
BRect oldFrame = _CursorFrame();
fCursorLocation = p;
Invalidate(oldFrame);
Invalidate(_CursorFrame());
}
Unlock();
}
}
// GetCursorPosition
BPoint
HWInterface::GetCursorPosition()
{
BPoint location;
if (Lock()) {
location = fCursorLocation;
Unlock();
}
return location;
}
// _CursorFrame
//
// PRE: the object must be locked
BRect
HWInterface::_CursorFrame() const
{
BRect frame(0.0, 0.0, -1.0, -1.0);
if (fCursor && fCursorVisible) {
frame = fCursor->Bounds();
frame.OffsetTo(fCursorLocation - fCursor->GetHotSpot());
}
return frame;
}

View File

@ -13,9 +13,10 @@
#include <GraphicsCard.h>
#include <Locker.h>
#include <OS.h>
#include <Rect.h>
class RenderingBuffer;
class BRect;
class ServerCursor;
class HWInterface : public BLocker {
public:
@ -25,10 +26,10 @@ class HWInterface : public BLocker {
virtual status_t Initialize() = 0;
virtual status_t Shutdown() = 0;
// screen mode stuff
virtual status_t SetMode(const display_mode &mode) = 0;
// virtual void GetMode(display_mode *mode) = 0;
virtual status_t GetDeviceInfo(accelerant_device_info *info) = 0;
virtual status_t GetModeList(display_mode **mode_list,
uint32 *count) = 0;
@ -46,6 +47,14 @@ class HWInterface : public BLocker {
virtual uint32 DPMSMode() const = 0;
virtual uint32 DPMSCapabilities() const = 0;
// cursor handling
virtual void SetCursor(ServerCursor* cursor);
virtual void SetCursorVisible(bool visible);
virtual bool IsCursorVisible();
virtual void MoveCursorTo(const float& x,
const float& y);
BPoint GetCursorPosition();
// frame buffer access
virtual RenderingBuffer* FrontBuffer() const = 0;
virtual RenderingBuffer* BackBuffer() const = 0;
@ -54,6 +63,13 @@ class HWInterface : public BLocker {
virtual status_t Invalidate(const BRect& frame) = 0;
// while as CopyBackToFront() actually performs the operation
virtual status_t CopyBackToFront(const BRect& frame) = 0;
protected:
BRect _CursorFrame() const;
ServerCursor* fCursor;
bool fCursorVisible;
BPoint fCursorLocation;
};
#endif // HW_INTERFACE_H

View File

@ -150,7 +150,7 @@ Painter::SetDrawData(const DrawData* data)
SetLowColor(data->lowcolor.GetColor32());
SetScale(data->scale);
SetPenSize(data->pensize);
// SetOrigin();
// fOrigin = data->coordOrigin;
SetDrawingMode(data->draw_mode);
SetBlendingMode(data->alphaSrcMode, data->alphaFncMode);
SetPenLocation(data->penlocation);

View File

@ -29,6 +29,7 @@
#include "BitmapBuffer.h"
#include "PortLink.h"
#include "ServerConfig.h"
#include "ServerCursor.h"
#include "ServerProtocol.h"
#include "UpdateQueue.h"
@ -112,12 +113,6 @@ class CardView : public BView {
private:
BPortLink* fServerLink;
const BBitmap* fBitmap;
/* int hide_cursor;
BBitmap *cursor;
BRect cursorframe, oldcursorframe;
bool obscure_cursor;*/
};
class CardWindow : public BWindow {
@ -157,31 +152,11 @@ CardView::CardView(BRect bounds)
return;
}
fServerLink = new BPortLink(serverInputPort);
// Create a cursor which isn't just a box
/* cursor=new BBitmap(BRect(0,0,20,20),B_RGBA32,true);
BView *v=new BView(cursor->Bounds(),"v", B_FOLLOW_NONE, B_WILL_DRAW);
hide_cursor=0;
cursor->Lock();
cursor->AddChild(v);
v->SetHighColor(255,255,255,0);
v->FillRect(cursor->Bounds());
v->SetHighColor(255,0,0,255);
v->FillTriangle(cursor->Bounds().LeftTop(),cursor->Bounds().RightTop(),cursor->Bounds().LeftBottom());
cursor->RemoveChild(v);
cursor->Unlock();
cursorframe=cursor->Bounds();
oldcursorframe=cursor->Bounds();*/
}
CardView::~CardView()
{
delete fServerLink;
/* delete cursor;*/
}
// AttachedToWindow
@ -197,16 +172,6 @@ CardView::Draw(BRect updateRect)
if (fBitmap) {
DrawBitmapAsync(fBitmap, updateRect, updateRect);
}
/* if (viewbmp) {
DrawBitmapAsync(viewbmp,oldcursorframe,oldcursorframe);
DrawBitmapAsync(viewbmp,rect,rect);
if (hide_cursor == 0 && obscure_cursor == false) {
SetDrawingMode(B_OP_ALPHA);
DrawBitmapAsync(cursor,cursor->Bounds(), cursorframe);
SetDrawingMode(B_OP_COPY);
}
}*/
}
// These functions emulate the Input Server by sending the *exact* same kind of messages
@ -228,12 +193,11 @@ CardView::MouseMoved(BPoint pt, uint32 transit, const BMessage* dragMessage)
{
if (!Bounds().Contains(pt))
return;
// TODO: no cursor support yet
// A bug in R5 prevents this call from having an effect if
// called elsewhere, and calling it here works, if we're lucky :-)
// BCursor cursor(kEmptyCursor);
// SetViewCursor(&cursor, true);
BCursor cursor(kEmptyCursor);
SetViewCursor(&cursor, true);
#ifdef ENABLE_INPUT_SERVER_EMULATION
send_mouse_moved(fServerLink, pt, Window()->CurrentMessage());
@ -420,9 +384,6 @@ ViewHWInterface::SetMode(const display_mode &mode)
printf("ViewHWInterface::SetMode(%s)\n", string_for_color_space((color_space)fDisplayMode.space));
// left over code
// hide_cursor=0;
BRect frame(0.0, 0.0,
fDisplayMode.virtual_width - 1,
fDisplayMode.virtual_height - 1);
@ -494,9 +455,6 @@ printf("ViewHWInterface::SetMode(%s)\n", string_for_color_space((color_space)fDi
status_t
ViewHWInterface::GetDeviceInfo(accelerant_device_info *info)
{
// if(!info || !is_initialized)
// return B_ERROR;
// We really don't have to provide anything here because this is strictly
// a software-only driver, but we'll have some fun, anyway.
@ -514,11 +472,6 @@ ViewHWInterface::GetDeviceInfo(accelerant_device_info *info)
status_t
ViewHWInterface::GetModeList(display_mode **modes, uint32 *count)
{
// if(!count || !is_initialized)
// return B_ERROR;
// screenwin->Lock();
// DEPRECATED:
// NOTE: Originally, I was going to figure out good timing values to be
// returned in each of the modes supported, but I won't bother, being this
@ -576,7 +529,6 @@ ViewHWInterface::GetModeList(display_mode **modes, uint32 *count)
modes[i]->v_display_start=0;
modes[i]->flags=B_PARALLEL_ACCESS;
}
// screenwin->Unlock();
return B_OK;
}
@ -675,16 +627,14 @@ ViewHWInterface::CopyBackToFront(const BRect& frame)
// && area.Intersects(fBackBuffer->Bitmap()->Bounds())) {
const BBitmap* from = fBackBuffer->Bitmap();
const BBitmap* into = fFrontBuffer->Bitmap();
// const BBitmap* into = fFrontBuffer->Bitmap();
// make sure we don't copy out of bounds
area = from->Bounds() & area;
// area = into->Bounds() & area;
uint32 srcBPR = from->BytesPerRow();
uint32 dstBPR = into->BytesPerRow();
uint8* dst = (uint8*)into->Bits();
uint8* src = (uint8*)from->Bits();
uint32 srcBPR = fBackBuffer->BytesPerRow();
uint8* src = (uint8*)fBackBuffer->Bits();
// convert to integer coordinates
int32 x = (int32)floorf(area.left);
@ -695,8 +645,100 @@ ViewHWInterface::CopyBackToFront(const BRect& frame)
// offset to left top pixel in source buffer (always B_RGBA32)
src += y * srcBPR + x * 4;
_CopyToFront(src, srcBPR, x, y, right, bottom);
_DrawCursor(area);
// update the region on screen
fWindow->Invalidate(area);
}
return B_OK;
}
// _DrawCursor
void
ViewHWInterface::_DrawCursor(BRect area) const
{
BRect cf = _CursorFrame();
if (cf.IsValid() && area.Intersects(cf)) {
// clip to common area
area = area & cf;
int32 left = (int32)floorf(area.left);
int32 top = (int32)floorf(area.top);
int32 right = (int32)ceilf(area.right);
int32 bottom = (int32)ceilf(area.bottom);
int32 width = right - left + 1;
int32 height = bottom - top + 1;
// make a bitmap from the backbuffer
// that has the cursor blended on top of it
// blending buffer
uint8* buffer = new uint8[width * height * 4];
// offset into back buffer
uint8* src = (uint8*)fBackBuffer->Bits();
uint32 srcBPR = fBackBuffer->BytesPerRow();
src += top * srcBPR + left * 4;
// offset into cursor bitmap
uint8* crs = (uint8*)fCursor->Bits();
uint32 crsBPR = fCursor->BytesPerRow();
// since area is clipped to cf,
// the diff between top and cf.top is always positive,
// same for diff between left and cf.left
crs += (top - (int32)floorf(cf.top)) * crsBPR
+ (left - (int32)floorf(cf.left)) * 4;
uint8* dst = buffer;
// blending
for (int32 y = top; y <= bottom; y++) {
uint8* s = src;
uint8* c = crs;
uint8* d = dst;
for (int32 x = left; x <= right; x++) {
// assume backbuffer alpha = 255
// TODO: it appears alpha in cursor us upside down
uint8 a = 255 - c[3];
d[0] = (((s[0] - c[0]) * a) + (c[0] << 8)) >> 8;
d[1] = (((s[1] - c[1]) * a) + (c[1] << 8)) >> 8;
d[2] = (((s[2] - c[2]) * a) + (c[2] << 8)) >> 8;
d[3] = 255;
s += 4;
c += 4;
d += 4;
}
crs += crsBPR;
src += srcBPR;
dst += width * 4;
}
// copy result to front buffer
_CopyToFront(buffer, width * 4, left, top, right, bottom);
delete[] buffer;
}
}
// _CopyToFront
//
// * source is assumed to be already at the right offset
// * source is assumed to be in B_RGBA32 format
// * location in front buffer is calculated
// * conversion from B_RGBA32 to format of front buffer is taken care of
void
ViewHWInterface::_CopyToFront(uint8* src, uint32 srcBPR,
int32 x, int32 y,
int32 right, int32 bottom) const
{
uint8* dst = (uint8*)fFrontBuffer->Bits();
uint32 dstBPR = fFrontBuffer->BytesPerRow();
// transfer, handle colorspace conversion
switch (into->ColorSpace()) {
switch (fFrontBuffer->ColorSpace()) {
case B_RGB32:
case B_RGBA32: {
int32 bytes = (right - x + 1) * 4;
@ -831,11 +873,6 @@ ViewHWInterface::CopyBackToFront(const BRect& frame)
break;
}
// update the region on screen
fWindow->Invalidate(area);
}
return B_OK;
}

View File

@ -57,6 +57,11 @@ class ViewHWInterface : public HWInterface {
virtual status_t CopyBackToFront(const BRect& area);
private:
void _DrawCursor(BRect area) const;
void _CopyToFront(uint8* src, uint32 srcBPR,
int32 x, int32 y,
int32 right, int32 bottom) const;
BitmapBuffer* fBackBuffer;
BitmapBuffer* fFrontBuffer;