From 16dc221d20428a0c064cfcf67c786d7d93c44d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 27 Mar 2009 19:31:12 +0000 Subject: [PATCH] * 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 --- src/preferences/keymap/KeyboardLayoutView.cpp | 162 +++++++++++++----- src/preferences/keymap/KeyboardLayoutView.h | 7 + 2 files changed, 122 insertions(+), 47 deletions(-) diff --git a/src/preferences/keymap/KeyboardLayoutView.cpp b/src/preferences/keymap/KeyboardLayoutView.cpp index d4d5fddd7c..bc5500558b 100644 --- a/src/preferences/keymap/KeyboardLayoutView.cpp +++ b/src/preferences/keymap/KeyboardLayoutView.cpp @@ -24,6 +24,7 @@ static const rgb_color kLitIndicatorColor = {116, 212, 83, 255}; KeyboardLayoutView::KeyboardLayoutView(const char* name) : BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), + fOffscreenBitmap(NULL), fKeymap(NULL), fModifiers(0), fDeadKey(0), @@ -39,6 +40,7 @@ KeyboardLayoutView::KeyboardLayoutView(const char* name) KeyboardLayoutView::~KeyboardLayoutView() { + delete fOffscreenBitmap; } @@ -83,15 +85,13 @@ KeyboardLayoutView::SetFont(const BFont& font) void KeyboardLayoutView::AttachedToWindow() { - if (Parent()) - SetViewColor(Parent()->ViewColor()); - else - SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetViewColor(B_TRANSPARENT_COLOR); SetFont(*be_plain_font); fSpecialFont = *be_fixed_font; fModifiers = modifiers(); + _InitOffscreen(); _LayoutKeyboard(); } @@ -99,6 +99,7 @@ KeyboardLayoutView::AttachedToWindow() void KeyboardLayoutView::FrameResized(float width, float height) { + _InitOffscreen(); _LayoutKeyboard(); } @@ -229,12 +230,28 @@ KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit, void 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 for (int32 i = 0; i < fLayout->CountKeys(); i++) { Key* key = fLayout->KeyAt(i); - _DrawKey(this, updateRect, key, _FrameFor(key), + _DrawKey(view, updateRect, key, _FrameFor(key), _IsKeyPressed(key->code)); } @@ -243,49 +260,15 @@ KeyboardLayoutView::Draw(BRect updateRect) for (int32 i = 0; i < fLayout->CountIndicators(); i++) { Indicator* indicator = fLayout->IndicatorAt(i); - BRect rect = _FrameFor(indicator->frame); - float rectTop = rect.top; - rect.top += 2 * rect.Height() / 3; + _DrawIndicator(view, updateRect, indicator, _FrameFor(indicator->frame), + (fModifiers & indicator->modifier) != 0); + } - 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); + if (fOffscreenBitmap != NULL) { + view->Sync(); + view->UnlockLooper(); - 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; - rect.right -= rect.Width() / 3; - - rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); - 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); + DrawBitmapAsync(fOffscreenBitmap, BPoint(0, 0)); } } @@ -346,11 +329,16 @@ KeyboardLayoutView::MessageReceived(BMessage* message) break; 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); Invalidate(); } break; + } default: 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 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* KeyboardLayoutView::_SpecialKeyLabel(const key_map& map, uint32 code) { diff --git a/src/preferences/keymap/KeyboardLayoutView.h b/src/preferences/keymap/KeyboardLayoutView.h index 9511b135ec..06d81d914f 100644 --- a/src/preferences/keymap/KeyboardLayoutView.h +++ b/src/preferences/keymap/KeyboardLayoutView.h @@ -50,12 +50,16 @@ private: kIndicator }; + void _InitOffscreen(); void _LayoutKeyboard(); void _DrawKeyButton(BView* view, BRect& rect, BRect updateRect, rgb_color base, rgb_color background, bool pressed); void _DrawKey(BView* view, BRect updateRect, 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* _SpecialMappedKeySymbol(const char* bytes, size_t numBytes); @@ -78,6 +82,9 @@ private: void _EvaluateDropTarget(BPoint point); void _SendFakeKeyDown(const Key* key); + BBitmap* fOffscreenBitmap; + BView* fOffscreenView; + KeyboardLayout* fLayout; Keymap* fKeymap; BMessenger fTarget;