* Now uses an offscreen bitmap for flicker free drawing.

* Only trigger a redraw on B_MODIFIER_CHANGED if something actually changed.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29747 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-03-27 19:31:12 +00:00
parent c8722a1e82
commit 16dc221d20
2 changed files with 122 additions and 47 deletions
+114 -46
View File
@@ -24,6 +24,7 @@ static const rgb_color kLitIndicatorColor = {116, 212, 83, 255};
KeyboardLayoutView::KeyboardLayoutView(const char* name) KeyboardLayoutView::KeyboardLayoutView(const char* name)
: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), : BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
fOffscreenBitmap(NULL),
fKeymap(NULL), fKeymap(NULL),
fModifiers(0), fModifiers(0),
fDeadKey(0), fDeadKey(0),
@@ -39,6 +40,7 @@ KeyboardLayoutView::KeyboardLayoutView(const char* name)
KeyboardLayoutView::~KeyboardLayoutView() KeyboardLayoutView::~KeyboardLayoutView()
{ {
delete fOffscreenBitmap;
} }
@@ -83,15 +85,13 @@ KeyboardLayoutView::SetFont(const BFont& font)
void void
KeyboardLayoutView::AttachedToWindow() KeyboardLayoutView::AttachedToWindow()
{ {
if (Parent()) SetViewColor(B_TRANSPARENT_COLOR);
SetViewColor(Parent()->ViewColor());
else
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetFont(*be_plain_font); SetFont(*be_plain_font);
fSpecialFont = *be_fixed_font; fSpecialFont = *be_fixed_font;
fModifiers = modifiers(); fModifiers = modifiers();
_InitOffscreen();
_LayoutKeyboard(); _LayoutKeyboard();
} }
@@ -99,6 +99,7 @@ KeyboardLayoutView::AttachedToWindow()
void void
KeyboardLayoutView::FrameResized(float width, float height) KeyboardLayoutView::FrameResized(float width, float height)
{ {
_InitOffscreen();
_LayoutKeyboard(); _LayoutKeyboard();
} }
@@ -229,12 +230,28 @@ KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit,
void void
KeyboardLayoutView::Draw(BRect updateRect) KeyboardLayoutView::Draw(BRect updateRect)
{ {
BView* view;
if (fOffscreenBitmap != NULL) {
view = fOffscreenView;
view->LockLooper();
} else
view = this;
// Draw background
if (Parent())
view->SetLowColor(Parent()->ViewColor());
else
view->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
view->FillRect(updateRect, B_SOLID_LOW);
// Draw keys // Draw keys
for (int32 i = 0; i < fLayout->CountKeys(); i++) { for (int32 i = 0; i < fLayout->CountKeys(); i++) {
Key* key = fLayout->KeyAt(i); Key* key = fLayout->KeyAt(i);
_DrawKey(this, updateRect, key, _FrameFor(key), _DrawKey(view, updateRect, key, _FrameFor(key),
_IsKeyPressed(key->code)); _IsKeyPressed(key->code));
} }
@@ -243,49 +260,15 @@ KeyboardLayoutView::Draw(BRect updateRect)
for (int32 i = 0; i < fLayout->CountIndicators(); i++) { for (int32 i = 0; i < fLayout->CountIndicators(); i++) {
Indicator* indicator = fLayout->IndicatorAt(i); Indicator* indicator = fLayout->IndicatorAt(i);
BRect rect = _FrameFor(indicator->frame); _DrawIndicator(view, updateRect, indicator, _FrameFor(indicator->frame),
float rectTop = rect.top; (fModifiers & indicator->modifier) != 0);
rect.top += 2 * rect.Height() / 3;
const char* label = NULL;
if (indicator->modifier == B_CAPS_LOCK)
label = "caps";
else if (indicator->modifier == B_NUM_LOCK)
label = "num";
else if (indicator->modifier == B_SCROLL_LOCK)
label = "scroll";
if (label != NULL) {
_SetFontSize(this, kIndicator);
font_height fontHeight;
GetFontHeight(&fontHeight);
if (ceilf(rect.top - fontHeight.ascent + fontHeight.descent - 2)
>= rectTop) {
SetHighColor(0, 0, 0);
SetLowColor(ViewColor());
BString text(label);
TruncateString(&text, B_TRUNCATE_END, rect.Width());
DrawString(text.String(), BPoint(ceilf(rect.left + (rect.Width()
- StringWidth(text.String())) / 2),
ceilf(rect.top - fontHeight.descent - 2)));
}
} }
rect.left += rect.Width() / 4; if (fOffscreenBitmap != NULL) {
rect.right -= rect.Width() / 3; view->Sync();
view->UnlockLooper();
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); DrawBitmapAsync(fOffscreenBitmap, BPoint(0, 0));
rgb_color base;
if ((fModifiers & indicator->modifier) != 0)
base = kLitIndicatorColor;
else
base = kDarkColor;
be_control_look->DrawButtonFrame(this, rect, updateRect, base,
background, BControlLook::B_DISABLED);
be_control_look->DrawButtonBackground(this, rect, updateRect,
base, BControlLook::B_DISABLED);
} }
} }
@@ -346,11 +329,16 @@ KeyboardLayoutView::MessageReceived(BMessage* message)
break; break;
case B_MODIFIERS_CHANGED: case B_MODIFIERS_CHANGED:
if (message->FindInt32("modifiers", &fModifiers) == B_OK) { {
int32 newModifiers;
if (message->FindInt32("modifiers", &newModifiers) == B_OK
&& fModifiers != newModifiers) {
fModifiers = newModifiers;
_EvaluateDropTarget(fDropPoint); _EvaluateDropTarget(fDropPoint);
Invalidate(); Invalidate();
} }
break; break;
}
default: default:
BView::MessageReceived(message); BView::MessageReceived(message);
@@ -359,6 +347,40 @@ KeyboardLayoutView::MessageReceived(BMessage* message)
} }
void
KeyboardLayoutView::_InitOffscreen()
{
delete fOffscreenBitmap;
fOffscreenView = NULL;
fOffscreenBitmap = new(std::nothrow) BBitmap(Bounds(),
B_BITMAP_ACCEPTS_VIEWS, B_RGB32);
if (fOffscreenBitmap != NULL && fOffscreenBitmap->IsValid()) {
fOffscreenBitmap->Lock();
fOffscreenView = new(std::nothrow) BView(Bounds(), "offscreen view",
0, 0);
if (fOffscreenView != NULL) {
if (Parent() != NULL) {
fOffscreenView->SetViewColor(Parent()->ViewColor());
} else {
fOffscreenView->SetViewColor(
ui_color(B_PANEL_BACKGROUND_COLOR));
}
fOffscreenView->SetLowColor(fOffscreenView->ViewColor());
fOffscreenBitmap->AddChild(fOffscreenView);
}
fOffscreenBitmap->Unlock();
}
if (fOffscreenView == NULL) {
// something went wrong
delete fOffscreenBitmap;
fOffscreenBitmap = NULL;
}
}
void void
KeyboardLayoutView::_LayoutKeyboard() KeyboardLayoutView::_LayoutKeyboard()
{ {
@@ -467,6 +489,52 @@ KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key,
} }
void
KeyboardLayoutView::_DrawIndicator(BView* view, BRect updateRect,
const Indicator* indicator, BRect rect, bool lit)
{
float rectTop = rect.top;
rect.top += 2 * rect.Height() / 3;
const char* label = NULL;
if (indicator->modifier == B_CAPS_LOCK)
label = "caps";
else if (indicator->modifier == B_NUM_LOCK)
label = "num";
else if (indicator->modifier == B_SCROLL_LOCK)
label = "scroll";
if (label != NULL) {
_SetFontSize(view, kIndicator);
font_height fontHeight;
GetFontHeight(&fontHeight);
if (ceilf(rect.top - fontHeight.ascent + fontHeight.descent - 2)
>= rectTop) {
view->SetHighColor(0, 0, 0);
view->SetLowColor(ViewColor());
BString text(label);
view->TruncateString(&text, B_TRUNCATE_END, rect.Width());
view->DrawString(text.String(),
BPoint(ceilf(rect.left + (rect.Width()
- StringWidth(text.String())) / 2),
ceilf(rect.top - fontHeight.descent - 2)));
}
}
rect.left += rect.Width() / 4;
rect.right -= rect.Width() / 3;
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color base = lit ? kLitIndicatorColor : kDarkColor;
be_control_look->DrawButtonFrame(view, rect, updateRect, base,
background, BControlLook::B_DISABLED);
be_control_look->DrawButtonBackground(view, rect, updateRect,
base, BControlLook::B_DISABLED);
}
const char* const char*
KeyboardLayoutView::_SpecialKeyLabel(const key_map& map, uint32 code) KeyboardLayoutView::_SpecialKeyLabel(const key_map& map, uint32 code)
{ {
@@ -50,12 +50,16 @@ private:
kIndicator kIndicator
}; };
void _InitOffscreen();
void _LayoutKeyboard(); void _LayoutKeyboard();
void _DrawKeyButton(BView* view, BRect& rect, void _DrawKeyButton(BView* view, BRect& rect,
BRect updateRect, rgb_color base, BRect updateRect, rgb_color base,
rgb_color background, bool pressed); rgb_color background, bool pressed);
void _DrawKey(BView* view, BRect updateRect, void _DrawKey(BView* view, BRect updateRect,
const Key* key, BRect frame, bool pressed); const Key* key, BRect frame, bool pressed);
void _DrawIndicator(BView* view, BRect updateRect,
const Indicator* indicator, BRect rect,
bool lit);
const char* _SpecialKeyLabel(const key_map& map, uint32 code); const char* _SpecialKeyLabel(const key_map& map, uint32 code);
const char* _SpecialMappedKeySymbol(const char* bytes, const char* _SpecialMappedKeySymbol(const char* bytes,
size_t numBytes); size_t numBytes);
@@ -78,6 +82,9 @@ private:
void _EvaluateDropTarget(BPoint point); void _EvaluateDropTarget(BPoint point);
void _SendFakeKeyDown(const Key* key); void _SendFakeKeyDown(const Key* key);
BBitmap* fOffscreenBitmap;
BView* fOffscreenView;
KeyboardLayout* fLayout; KeyboardLayout* fLayout;
Keymap* fKeymap; Keymap* fKeymap;
BMessenger fTarget; BMessenger fTarget;