diff --git a/src/add-ons/input_server/devices/virtualkeyboard/Jamfile b/src/add-ons/input_server/devices/virtualkeyboard/Jamfile index 0f545e763f..83c33f78f6 100644 --- a/src/add-ons/input_server/devices/virtualkeyboard/Jamfile +++ b/src/add-ons/input_server/devices/virtualkeyboard/Jamfile @@ -3,6 +3,8 @@ SubDir HAIKU_TOP src add-ons input_server devices virtualkeyboard ; UsePrivateHeaders input interface shared tracker ; UsePrivateSystemHeaders ; +SubDirC++Flags -DVIRTUAL_KEYBOARD_DEVICE ; + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences keymap ] ; AddResources virtualkeyboard : VirtualKeyboard.rdef ; diff --git a/src/add-ons/input_server/devices/virtualkeyboard/KeyboardLayoutView.cpp b/src/add-ons/input_server/devices/virtualkeyboard/KeyboardLayoutView.cpp deleted file mode 100644 index e4e3c1aec6..0000000000 --- a/src/add-ons/input_server/devices/virtualkeyboard/KeyboardLayoutView.cpp +++ /dev/null @@ -1,1170 +0,0 @@ -/* - * Copyright 2009-2010, Axel Dörfler, axeld@pinc-software.de. - * Distributed under the terms of the MIT License. - */ - - -#include "KeyboardLayoutView.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "Keymap.h" - - -static const rgb_color kBrightColor = {230, 230, 230, 255}; -static const rgb_color kDarkColor = {200, 200, 200, 255}; -static const rgb_color kSecondDeadKeyColor = {240, 240, 150, 255}; -static const rgb_color kDeadKeyColor = {152, 203, 255, 255}; -static const rgb_color kLitIndicatorColor = {116, 212, 83, 255}; - - -#undef TRACE - -//#define TRACE_KEYBOARD_DEVICE -#ifdef TRACE_KEYBOARD_DEVICE - -static int32 sFunctionDepth = -1; - -class FunctionTracer { -public: - FunctionTracer(const void* pointer, const char* className, - const char* functionName) - : - fFunctionName(), - fPrepend(), - fPointer(pointer) - { - sFunctionDepth++; - fPrepend.Append(' ', sFunctionDepth * 2); - fFunctionName << className << "::" << functionName << "()"; - - debug_printf("%p -> %s%s {\n", fPointer, fPrepend.String(), - fFunctionName.String()); - } - - ~FunctionTracer() - { - debug_printf("%p -> %s}\n", fPointer, fPrepend.String()); - sFunctionDepth--; - } - - static int32 Depth() { return sFunctionDepth; } - -private: - BString fFunctionName; - BString fPrepend; - const void* fPointer; -}; - -# define KD_CALLED(x...) \ - FunctionTracer _ft(this, "LayoutView", __FUNCTION__) -# define KID_CALLED(x...) \ - FunctionTracer _ft(this, "LayoutView", __FUNCTION__) -# define TRACE(x...) \ - do { BString _to; \ - _to.Append(' ', (FunctionTracer::Depth() + 1) * 2); \ - debug_printf("%p -> %s", this, _to.String()); \ - debug_printf(x); } while (0) -# define LOG_EVENT(text...) debug_printf(text) -# define LOG_ERR(text...) TRACE(text) -#else -# define TRACE(x...) do {} while (0) -# define KD_CALLED(x...) TRACE(x) -# define KID_CALLED(x...) TRACE(x) -# define LOG_ERR(text...) debug_printf(text) -# define LOG_EVENT(text...) TRACE(x) -#endif - - -KeyboardLayoutView::KeyboardLayoutView(const char* name, - BInputServerDevice* dev) - : - BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), - fOffscreenBitmap(NULL), - fKeymap(NULL), - fEditable(true), - fModifiers(0), - fDeadKey(0), - fButtons(0), - fDragKey(NULL), - fDropTarget(NULL), - fOldSize(0, 0), - fDevice(dev) -{ - fLayout = new KeyboardLayout; - memset(fKeyState, 0, sizeof(fKeyState)); - - SetEventMask(B_KEYBOARD_EVENTS); -} - - -KeyboardLayoutView::~KeyboardLayoutView() -{ - delete fOffscreenBitmap; -} - - -void -KeyboardLayoutView::SetKeyboardLayout(KeyboardLayout* layout) -{ - fLayout = layout; - _InitOffscreen(); - _LayoutKeyboard(); - Invalidate(); -} - - -void -KeyboardLayoutView::SetKeymap(Keymap* keymap) -{ - fKeymap = keymap; - Invalidate(); -} - - -void -KeyboardLayoutView::SetEditable(bool editable) -{ - fEditable = editable; -} - - -void -KeyboardLayoutView::SetTarget(BMessenger target) -{ - fTarget = target; -} - - -void -KeyboardLayoutView::SetBaseFont(const BFont& font) -{ - fBaseFont = font; - - font_height fontHeight; - fBaseFont.GetHeight(&fontHeight); - fBaseFontHeight = fontHeight.ascent + fontHeight.descent; - fBaseFontSize = fBaseFont.Size(); - - Invalidate(); -} - - -void -KeyboardLayoutView::AttachedToWindow() -{ - SetViewColor(B_TRANSPARENT_COLOR); - - SetBaseFont(*be_plain_font); - fSpecialFont = *be_fixed_font; - fModifiers = modifiers(); -} - - -void -KeyboardLayoutView::FrameResized(float width, float height) -{ - _InitOffscreen(); - _LayoutKeyboard(); -} - - -void -KeyboardLayoutView::WindowActivated(bool active) -{ - if (active) - Invalidate(); -} - - -BSize -KeyboardLayoutView::MinSize() -{ - return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(100, 50)); -} - - -void -KeyboardLayoutView::KeyDown(const char* bytes, int32 numBytes) -{ - _KeyChanged(Window()->CurrentMessage()); -} - - -void -KeyboardLayoutView::KeyUp(const char* bytes, int32 numBytes) -{ - _KeyChanged(Window()->CurrentMessage()); -} - - -void -KeyboardLayoutView::MouseDown(BPoint point) -{ - fClickPoint = point; - fDragKey = NULL; - fDropPoint.x = -1; - - Key* key = _KeyAt(point); - if (key == NULL) - return; - - int32 buttons = 0; - if (Looper() != NULL && Looper()->CurrentMessage() != NULL) - Looper()->CurrentMessage()->FindInt32("buttons", &buttons); - - if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0 - && (fButtons & B_TERTIARY_MOUSE_BUTTON) == 0) { - // toggle the "deadness" of dead keys via middle mouse button - if (fKeymap != NULL) { - bool isEnabled = false; - uint8 deadKey - = fKeymap->DeadKey(key->code, fModifiers, &isEnabled); - if (deadKey > 0) { - fKeymap->SetDeadKeyEnabled(key->code, fModifiers, !isEnabled); - _InvalidateKey(key); - } - } - } else { - if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) { - if (_KeyState(key->code)) { - uint32 modifier = fKeymap->Modifier(key->code); - if ((modifier & modifiers()) == 0) { - _SetKeyState(key->code, false); - fModifiers &= ~modifier; - Invalidate(); - } - } else { - _SetKeyState(key->code, true); - fModifiers |= fKeymap->Modifier(key->code); - Invalidate(); - } - - // TODO: if possible, we could handle the lock keys for real - } else { - _SetKeyState(key->code, true); - _InvalidateKey(key); - } - } - - fButtons = buttons; -} - - -void -KeyboardLayoutView::MouseUp(BPoint point) -{ - Key* key = _KeyAt(fClickPoint); - - int32 buttons = 0; - if (Looper() != NULL && Looper()->CurrentMessage() != NULL) - Looper()->CurrentMessage()->FindInt32("buttons", &buttons); - - if (key != NULL) { - if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0 - && (buttons & B_TERTIARY_MOUSE_BUTTON) == 0) { - _SetKeyState(key->code, false); - _InvalidateKey(key); - fButtons = buttons; - } else { - fButtons = buttons; - - // modifier keys are sticky when used with the mouse - if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) - return; - - _SetKeyState(key->code, false); - - if (_HandleDeadKey(key->code, fModifiers) && fDeadKey != 0) - return; - - _InvalidateKey(key); - - if (fDragKey == NULL && fKeymap != NULL) { - _SendKeyDown(key); - } - } - } - fDragKey = NULL; -} - - -void -KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit, - const BMessage* dragMessage) -{ -} - - -void -KeyboardLayoutView::Draw(BRect updateRect) -{ - if (fOldSize != BSize(Bounds().Width(), Bounds().Height())) { - _InitOffscreen(); - _LayoutKeyboard(); - } - - 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(view, updateRect, key, _FrameFor(key), - _IsKeyPressed(key->code)); - } - - // Draw LED indicators - - for (int32 i = 0; i < fLayout->CountIndicators(); i++) { - Indicator* indicator = fLayout->IndicatorAt(i); - - _DrawIndicator(view, updateRect, indicator, _FrameFor(indicator->frame), - (fModifiers & indicator->modifier) != 0); - } - - if (fOffscreenBitmap != NULL) { - view->Sync(); - view->UnlockLooper(); - - DrawBitmapAsync(fOffscreenBitmap, BPoint(0, 0)); - } -} - - -void -KeyboardLayoutView::MessageReceived(BMessage* message) -{ - if (message->WasDropped() && fEditable && fDropTarget != NULL - && fKeymap != NULL) { - int32 keyCode; - const char* data; - ssize_t size; - if (message->FindData("text/plain", B_MIME_DATA, - (const void**)&data, &size) == B_OK) { - // Automatically convert UTF-8 escaped strings (for example from - // CharacterMap) - int32 dataSize = 0; - uint8 buffer[16]; - if (size > 3 && data[0] == '\\' && data[1] == 'x') { - char tempBuffer[16]; - if (size > 15) - size = 15; - memcpy(tempBuffer, data, size); - tempBuffer[size] = '\0'; - data = tempBuffer; - - while (size > 3 && data[0] == '\\' && data[1] == 'x') { - buffer[dataSize++] = strtoul(&data[2], NULL, 16); - if ((buffer[dataSize - 1] & 0x80) == 0) - break; - - size -= 4; - data += 4; - } - data = (const char*)buffer; - } else if ((data[0] & 0xc0) != 0x80 && (data[0] & 0x80) != 0) { - // only accept the first character UTF-8 character - while (dataSize < size && (data[dataSize] & 0x80) != 0) { - dataSize++; - } - } else if ((data[0] & 0x80) == 0) { - // an ASCII character - dataSize = 1; - } else { - // no valid character - beep(); - return; - } - - int32 buttons; - if (!message->IsSourceRemote() - && message->FindInt32("buttons", &buttons) == B_OK - && (buttons & B_SECONDARY_MOUSE_BUTTON) != 0 - && message->FindInt32("key", &keyCode) == B_OK) { - // switch keys if the dropped object came from us - Key* key = _KeyForCode(keyCode); - if (key == NULL - || (key == fDropTarget && fDragModifiers == fModifiers)) - return; - - char* string; - int32 numBytes; - fKeymap->GetChars(fDropTarget->code, fModifiers, fDeadKey, - &string, &numBytes); - if (string != NULL) { - // switch keys - fKeymap->SetKey(fDropTarget->code, fModifiers, fDeadKey, - (const char*)data, dataSize); - fKeymap->SetKey(key->code, fDragModifiers, fDeadKey, - string, numBytes); - delete[] string; - } else if (fKeymap->IsModifierKey(fDropTarget->code)) { - // switch key with modifier - fKeymap->SetModifier(key->code, - fKeymap->Modifier(fDropTarget->code)); - fKeymap->SetKey(fDropTarget->code, fModifiers, fDeadKey, - (const char*)data, dataSize); - } - } else { - // Send the old key to the target, so it's not lost entirely - _SendKeyDown(fDropTarget); - - fKeymap->SetKey(fDropTarget->code, fModifiers, fDeadKey, - (const char*)data, dataSize); - } - } else if (!message->IsSourceRemote() - && message->FindInt32("key", &keyCode) == B_OK) { - // Switch an unmapped key - - Key* key = _KeyForCode(keyCode); - if (key != NULL && key == fDropTarget) - return; - - uint32 modifier = fKeymap->Modifier(keyCode); - - char* string; - int32 numBytes; - fKeymap->GetChars(fDropTarget->code, fModifiers, fDeadKey, - &string, &numBytes); - if (string != NULL) { - // switch key with modifier - fKeymap->SetModifier(fDropTarget->code, modifier); - fKeymap->SetKey(keyCode, fDragModifiers, fDeadKey, - string, numBytes); - delete[] string; - } else { - // switch modifier keys - fKeymap->SetModifier(keyCode, - fKeymap->Modifier(fDropTarget->code)); - fKeymap->SetModifier(fDropTarget->code, modifier); - } - - _InvalidateKey(fDragKey); - } - - _InvalidateKey(fDropTarget); - fDropTarget = NULL; - fDropPoint.x = -1; - return; - } - - switch (message->what) { - case B_UNMAPPED_KEY_DOWN: - case B_UNMAPPED_KEY_UP: - _KeyChanged(message); - break; - - case B_MODIFIERS_CHANGED: - { - int32 newModifiers; - if (message->FindInt32("modifiers", &newModifiers) == B_OK - && fModifiers != newModifiers) { - fModifiers = newModifiers; - _EvaluateDropTarget(fDropPoint); - if (Window()->IsActive()) - Invalidate(); - } - break; - } - - default: - BView::MessageReceived(message); - break; - } -} - - -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() -{ - float factorX = Bounds().Width() / fLayout->Bounds().Width(); - float factorY = Bounds().Height() / fLayout->Bounds().Height(); - - fFactor = min_c(factorX, factorY); - fOffset = BPoint((Bounds().Width() - fLayout->Bounds().Width() - * fFactor) / 2, - (Bounds().Height() - fLayout->Bounds().Height() * fFactor) / 2); - - if (fLayout->DefaultKeySize().width < 11) - fGap = 1; - else - fGap = 2; - - fOldSize.width = Bounds().Width(); - fOldSize.height = Bounds().Height(); -} - - -void -KeyboardLayoutView::_DrawKeyButton(BView* view, BRect& rect, BRect updateRect, - rgb_color base, rgb_color background, bool pressed) -{ - be_control_look->DrawButtonFrame(view, rect, updateRect, 4.0f, base, - background, pressed ? BControlLook::B_ACTIVATED : 0); - be_control_look->DrawButtonBackground(view, rect, updateRect, 4.0f, - base, pressed ? BControlLook::B_ACTIVATED : 0); -} - - -void -KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key, - BRect rect, bool pressed) -{ - rgb_color base = key->dark ? kDarkColor : kBrightColor; - rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); - key_kind keyKind = kNormalKey; - int32 deadKey = 0; - bool secondDeadKey = false; - bool isDeadKeyEnabled = true; - - char text[32]; - if (fKeymap != NULL) { - _GetKeyLabel(key, text, sizeof(text), keyKind); - deadKey = fKeymap->DeadKey(key->code, fModifiers, &isDeadKeyEnabled); - secondDeadKey = fKeymap->IsDeadSecondKey(key->code, fModifiers, - fDeadKey); - } else { - // Show the key code if there is no keymap - snprintf(text, sizeof(text), "%02" B_PRIx32, key->code); - } - - _SetFontSize(view, keyKind); - - if (secondDeadKey) - base = kSecondDeadKeyColor; - else if (deadKey > 0 && isDeadKeyEnabled) - base = kDeadKeyColor; - - if (key->shape == kRectangleKeyShape) { - _DrawKeyButton(view, rect, updateRect, base, background, pressed); - - rect.InsetBy(1, 1); - - _GetAbbreviatedKeyLabelIfNeeded(view, rect, key, text, sizeof(text)); - be_control_look->DrawLabel(view, text, rect, updateRect, - base, 0, BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE)); - } else if (key->shape == kEnterKeyShape) { - BRect topLeft = rect; - BRect topRight = rect; - BRect bottomLeft = rect; - BRect bottomRight = rect; - - // TODO: for some reason, this does not always equal the bottom of - // the other keys... - bottomLeft.top = floorf(rect.top - + fLayout->DefaultKeySize().height * fFactor - fGap - 1); - bottomLeft.right = floorf(rect.left - + (key->frame.Width() - key->second_row) * fFactor - fGap - 2); - - topLeft.bottom = bottomLeft.top; - topLeft.right = bottomLeft.right + 1; - // add one to make the borders meet - - topRight.bottom = topLeft.bottom; - topRight.left = topLeft.right; - - bottomRight.top = bottomLeft.top; - bottomRight.left = bottomLeft.right; - - // draw top left corner - be_control_look->DrawButtonFrame(view, topLeft, updateRect, - 4.0f, 0.0f, 4.0f, 0.0f, base, background, - pressed ? BControlLook::B_ACTIVATED : 0, - BControlLook::B_LEFT_BORDER | BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER); - be_control_look->DrawButtonBackground(view, topLeft, updateRect, - 4.0f, 0.0f, 4.0f, 0.0f, base, - pressed ? BControlLook::B_ACTIVATED : 0, - BControlLook::B_LEFT_BORDER | BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER); - - // draw top right corner - be_control_look->DrawButtonFrame(view, topRight, updateRect, - 0.0f, 4.0f, 0.0f, 0.0f, base, background, - pressed ? BControlLook::B_ACTIVATED : 0, - BControlLook::B_TOP_BORDER | BControlLook::B_RIGHT_BORDER); - be_control_look->DrawButtonBackground(view, topRight, updateRect, - 0.0f, 4.0f, 0.0f, 0.0f, base, - pressed ? BControlLook::B_ACTIVATED : 0, - BControlLook::B_TOP_BORDER | BControlLook::B_RIGHT_BORDER); - - // draw bottom right corner - be_control_look->DrawButtonFrame(view, bottomRight, updateRect, - 0.0f, 0.0f, 4.0f, 4.0f, base, background, - pressed ? BControlLook::B_ACTIVATED : 0, - BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER - | BControlLook::B_BOTTOM_BORDER); - be_control_look->DrawButtonBackground(view, bottomRight, updateRect, - 0.0f, 0.0f, 4.0f, 4.0f, base, - pressed ? BControlLook::B_ACTIVATED : 0, - BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER - | BControlLook::B_BOTTOM_BORDER); - - // clip out the bottom left corner - bottomLeft.right += 1; - bottomLeft.top -= 2; - BRegion region(rect); - region.Exclude(bottomLeft); - view->ConstrainClippingRegion(®ion); - - // Fill in the rect with the background color - SetHighColor(background); - FillRect(rect); - - // draw the button background - BRect bgRect = rect.InsetByCopy(2, 2); - be_control_look->DrawButtonBackground(view, bgRect, updateRect, - 4.0f, 4.0f, 0.0f, 4.0f, base, - pressed ? BControlLook::B_ACTIVATED : 0); - - rect.left = bottomLeft.right; - _GetAbbreviatedKeyLabelIfNeeded(view, rect, key, text, sizeof(text)); - - // draw the button label - be_control_look->DrawLabel(view, text, rect, updateRect, - base, 0, BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE)); - - // reset the clipping region - view->ConstrainClippingRegion(NULL); - } -} - - -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, - bool abbreviated) -{ - if (code == map.caps_key) - return abbreviated ? "CAPS" : "CAPS LOCK"; - if (code == map.scroll_key) - return "SCROLL"; - if (code == map.num_key) - return abbreviated ? "NUM" : "NUM LOCK"; - if (code == map.left_shift_key || code == map.right_shift_key) - return "SHIFT"; - if (code == map.left_command_key || code == map.right_command_key) - return abbreviated ? "CMD" : "COMMAND"; - if (code == map.left_control_key || code == map.right_control_key) - return abbreviated ? "CTRL" : "CONTROL"; - if (code == map.left_option_key || code == map.right_option_key) - return abbreviated ? "OPT" : "OPTION"; - if (code == map.menu_key) - return "MENU"; - if (code == B_PRINT_KEY) - return "PRINT"; - if (code == B_PAUSE_KEY) - return "PAUSE"; - - return NULL; -} - - -const char* -KeyboardLayoutView::_SpecialMappedKeySymbol(const char* bytes, size_t numBytes) -{ - if (numBytes != 1) - return NULL; - - if (bytes[0] == B_TAB) - return "\xe2\x86\xb9"; - if (bytes[0] == B_ENTER) - return "\xe2\x86\xb5"; - if (bytes[0] == B_BACKSPACE) - return "\xe2\x8c\xab"; - - if (bytes[0] == B_UP_ARROW) - return "\xe2\x86\x91"; - if (bytes[0] == B_LEFT_ARROW) - return "\xe2\x86\x90"; - if (bytes[0] == B_DOWN_ARROW) - return "\xe2\x86\x93"; - if (bytes[0] == B_RIGHT_ARROW) - return "\xe2\x86\x92"; - - return NULL; -} - - -const char* -KeyboardLayoutView::_SpecialMappedKeyLabel(const char* bytes, size_t numBytes, - bool abbreviated) -{ - if (numBytes != 1) - return NULL; - - if (bytes[0] == B_ESCAPE) - return "ESC"; - - if (bytes[0] == B_INSERT) - return "INS"; - if (bytes[0] == B_DELETE) - return "DEL"; - if (bytes[0] == B_HOME) - return "HOME"; - if (bytes[0] == B_END) - return "END"; - if (bytes[0] == B_PAGE_UP) - return abbreviated ? "PG \xe2\x86\x91" : "PAGE \xe2\x86\x91"; - if (bytes[0] == B_PAGE_DOWN) - return abbreviated ? "PG \xe2\x86\x93" : "PAGE \xe2\x86\x93"; - - return NULL; -} - - -bool -KeyboardLayoutView::_FunctionKeyLabel(uint32 code, char* text, size_t textSize) -{ - if (code >= B_F1_KEY && code <= B_F12_KEY) { - snprintf(text, textSize, "F%" B_PRId32, code + 1 - B_F1_KEY); - return true; - } - - return false; -} - - -void -KeyboardLayoutView::_GetAbbreviatedKeyLabelIfNeeded(BView* view, BRect rect, - const Key* key, char* text, size_t textSize) -{ - if (floorf(rect.Width()) > ceilf(view->StringWidth(text))) - return; - - // Check if we have a shorter version of this key - - const key_map& map = fKeymap->Map(); - - const char* special = _SpecialKeyLabel(map, key->code, true); - if (special != NULL) { - strlcpy(text, special, textSize); - return; - } - - char* bytes = NULL; - int32 numBytes; - fKeymap->GetChars(key->code, fModifiers, fDeadKey, &bytes, &numBytes); - if (bytes != NULL) { - special = _SpecialMappedKeyLabel(bytes, numBytes, true); - if (special != NULL) - strlcpy(text, special, textSize); - - delete[] bytes; - } -} - - -void -KeyboardLayoutView::_GetKeyLabel(const Key* key, char* text, size_t textSize, - key_kind& keyKind) -{ - const key_map& map = fKeymap->Map(); - keyKind = kNormalKey; - text[0] = '\0'; - - const char* special = _SpecialKeyLabel(map, key->code); - if (special != NULL) { - strlcpy(text, special, textSize); - keyKind = kSpecialKey; - return; - } - - if (_FunctionKeyLabel(key->code, text, textSize)) { - keyKind = kSpecialKey; - return; - } - - char* bytes = NULL; - int32 numBytes; - fKeymap->GetChars(key->code, fModifiers, fDeadKey, &bytes, &numBytes); - if (bytes != NULL) { - special = _SpecialMappedKeyLabel(bytes, numBytes); - if (special != NULL) { - strlcpy(text, special, textSize); - keyKind = kSpecialKey; - } else { - special = _SpecialMappedKeySymbol(bytes, numBytes); - if (special != NULL) { - strlcpy(text, special, textSize); - keyKind = kSymbolKey; - } else { - bool hasGlyphs; - fBaseFont.GetHasGlyphs(bytes, 1, &hasGlyphs); - if (hasGlyphs) - strlcpy(text, bytes, textSize); - } - } - - delete[] bytes; - } -} - - -bool -KeyboardLayoutView::_IsKeyPressed(uint32 code) -{ - if (fDropTarget != NULL && fDropTarget->code == code) - return true; - - return _KeyState(code); -} - - -bool -KeyboardLayoutView::_KeyState(uint32 code) const -{ - if (code >= 16 * 8) - return false; - - return (fKeyState[code / 8] & (1 << (7 - (code & 7)))) != 0; -} - - -void -KeyboardLayoutView::_SetKeyState(uint32 code, bool pressed) -{ - if (code >= 16 * 8) - return; - - if (pressed) - fKeyState[code / 8] |= (1 << (7 - (code & 7))); - else - fKeyState[code / 8] &= ~(1 << (7 - (code & 7))); -} - - -Key* -KeyboardLayoutView::_KeyForCode(uint32 code) -{ - // TODO: have a lookup array - - for (int32 i = 0; i < fLayout->CountKeys(); i++) { - Key* key = fLayout->KeyAt(i); - if (key->code == code) - return key; - } - - return NULL; -} - - -void -KeyboardLayoutView::_InvalidateKey(uint32 code) -{ - _InvalidateKey(_KeyForCode(code)); -} - - -void -KeyboardLayoutView::_InvalidateKey(const Key* key) -{ - if (key != NULL) - Invalidate(_FrameFor(key)); -} - - -/*! Updates the fDeadKey member, and invalidates the view if needed. - - \return true if the view has been invalidated. -*/ -bool -KeyboardLayoutView::_HandleDeadKey(uint32 key, int32 modifiers) -{ - if (fKeymap == NULL || fKeymap->IsModifierKey(key)) - return false; - - bool isEnabled = false; - int32 deadKey = fKeymap->DeadKey(key, modifiers, &isEnabled); - if (fDeadKey != deadKey) { - if (isEnabled) { - Invalidate(); - fDeadKey = deadKey; - return true; - } - } else if (fDeadKey != 0) { - Invalidate(); - fDeadKey = 0; - return true; - } - - return false; -} - - -void -KeyboardLayoutView::_KeyChanged(const BMessage* message) -{ - const uint8* state; - ssize_t size; - int32 key; - if (message->FindData("states", B_UINT8_TYPE, (const void**)&state, &size) - != B_OK - || message->FindInt32("key", &key) != B_OK) - return; - - // Update key state, and invalidate change keys - - bool checkSingle = true; - - if (message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) { - if (_HandleDeadKey(key, fModifiers)) - checkSingle = false; - - if (_KeyForCode(key) == NULL) - printf("no key for code %" B_PRId32 "\n", key); - } - - for (int32 i = 0; i < 16; i++) { - if (fKeyState[i] != state[i]) { - uint8 diff = fKeyState[i] ^ state[i]; - fKeyState[i] = state[i]; - - if (!checkSingle || !Window()->IsActive()) - continue; - - for (int32 j = 7; diff != 0; j--, diff >>= 1) { - if (diff & 1) { - _InvalidateKey(i * 8 + j); - } - } - } - } -} - - -Key* -KeyboardLayoutView::_KeyAt(BPoint point) -{ - // Find key candidate - - BPoint keyPoint = point; - keyPoint -= fOffset; - keyPoint.x /= fFactor; - keyPoint.y /= fFactor; - - for (int32 i = 0; i < fLayout->CountKeys(); i++) { - Key* key = fLayout->KeyAt(i); - if (key->frame.Contains(keyPoint)) { - BRect frame = _FrameFor(key); - if (frame.Contains(point)) - return key; - - return NULL; - } - } - - return NULL; -} - - -BRect -KeyboardLayoutView::_FrameFor(BRect keyFrame) -{ - BRect rect; - rect.left = ceilf(keyFrame.left * fFactor); - rect.top = ceilf(keyFrame.top * fFactor); - rect.right = floorf((keyFrame.Width()) * fFactor + rect.left - fGap - 1); - rect.bottom = floorf((keyFrame.Height()) * fFactor + rect.top - fGap - 1); - rect.OffsetBy(fOffset); - - return rect; -} - - -BRect -KeyboardLayoutView::_FrameFor(const Key* key) -{ - return _FrameFor(key->frame); -} - - -void -KeyboardLayoutView::_SetFontSize(BView* view, key_kind keyKind) -{ - BSize size = fLayout->DefaultKeySize(); - float fontSize = fBaseFontSize; - if (fBaseFontHeight >= size.height * fFactor * 0.5) { - fontSize *= (size.height * fFactor * 0.5) / fBaseFontHeight; - if (fontSize < 8) - fontSize = 8; - } - - switch (keyKind) { - case kNormalKey: - fBaseFont.SetSize(fontSize); - view->SetFont(&fBaseFont); - break; - case kSpecialKey: - fSpecialFont.SetSize(fontSize * 0.7); - view->SetFont(&fSpecialFont); - break; - case kSymbolKey: - fSpecialFont.SetSize(fontSize * 1.6); - view->SetFont(&fSpecialFont); - break; - - case kIndicator: - { - BFont font; - font.SetSize(fontSize * 0.8); - view->SetFont(&font); - break; - } - } -} - - -void -KeyboardLayoutView::_EvaluateDropTarget(BPoint point) -{ - fDropTarget = _KeyAt(point); - if (fDropTarget != NULL) { - if (fDropTarget == fDragKey && fModifiers == fDragModifiers) - fDropTarget = NULL; - else - _InvalidateKey(fDropTarget); - } -} - - -void -KeyboardLayoutView::_SendKeyDown(const Key* key) -{ - KID_CALLED(); - - BMessage* message = new BMessage(B_KEY_DOWN); - message->AddInt64("when", system_time()); - message->AddData("states", B_UINT8_TYPE, &fKeyState, - sizeof(fKeyState)); - message->AddInt32("key", key->code); - message->AddInt32("modifiers", fModifiers); - message->AddInt32("be:key_repeat", 1); - //message.AddPointer("keymap", fKeymap); - - char* string; - int32 numBytes; - fKeymap->GetChars(key->code, fModifiers, fDeadKey, &string, - &numBytes); - if (string != NULL) { - message->AddString("bytes", string); - delete[] string; - } - - fKeymap->GetChars(key->code, 0, 0, &string, &numBytes); - if (string != NULL) { - message->AddInt32("raw_char", string[0]); - message->AddInt8("byte", string[0]); - delete[] string; - } - - if (fDevice->EnqueueMessage(message) != B_OK) - delete message; - -} diff --git a/src/add-ons/input_server/devices/virtualkeyboard/KeyboardLayoutView.h b/src/add-ons/input_server/devices/virtualkeyboard/KeyboardLayoutView.h deleted file mode 100644 index 6805bfce5b..0000000000 --- a/src/add-ons/input_server/devices/virtualkeyboard/KeyboardLayoutView.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. - * Distributed under the terms of the MIT License. - */ -#ifndef KEYBOARD_LAYOUT_VIEW_H -#define KEYBOARD_LAYOUT_VIEW_H - - -#include -#include -#include - -#include "KeyboardLayout.h" - - -class Keymap; - - -class KeyboardLayoutView : public BView { -public: - KeyboardLayoutView(const char* name, - BInputServerDevice* dev); - ~KeyboardLayoutView(); - - void SetKeyboardLayout(KeyboardLayout* layout); - void SetKeymap(Keymap* keymap); - void SetTarget(BMessenger target); - - KeyboardLayout* GetKeyboardLayout() { return fLayout; } - - void SetBaseFont(const BFont& font); - - void SetEditable(bool editable); - -protected: - virtual void AttachedToWindow(); - virtual void FrameResized(float width, float height); - virtual BSize MinSize(); - - virtual void KeyDown(const char* bytes, int32 numBytes); - virtual void KeyUp(const char* bytes, int32 numBytes); - virtual void MouseDown(BPoint point); - virtual void MouseUp(BPoint point); - virtual void MouseMoved(BPoint point, uint32 transit, - const BMessage* dragMessage); - - virtual void Draw(BRect updateRect); - virtual void MessageReceived(BMessage* message); - virtual void WindowActivated(bool active); - -private: - enum key_kind { - kNormalKey, - kSpecialKey, - kSymbolKey, - 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, bool abbreviated = false); - const char* _SpecialMappedKeySymbol(const char* bytes, - size_t numBytes); - const char* _SpecialMappedKeyLabel(const char* bytes, - size_t numBytes, bool abbreviated = false); - bool _FunctionKeyLabel(uint32 code, char* text, - size_t textSize); - void _GetAbbreviatedKeyLabelIfNeeded(BView* view, - BRect rect, const Key* key, char* text, - size_t textSize); - void _GetKeyLabel(const Key* key, char* text, - size_t textSize, key_kind& keyKind); - bool _IsKeyPressed(uint32 code); - bool _KeyState(uint32 code) const; - void _SetKeyState(uint32 code, bool pressed); - Key* _KeyForCode(uint32 code); - void _InvalidateKey(uint32 code); - void _InvalidateKey(const Key* key); - bool _HandleDeadKey(uint32 key, int32 modifiers); - void _KeyChanged(const BMessage* message); - Key* _KeyAt(BPoint point); - BRect _FrameFor(BRect keyFrame); - BRect _FrameFor(const Key* key); - void _SetFontSize(BView* view, key_kind keyKind); - void _EvaluateDropTarget(BPoint point); - void _SendKeyDown(const Key* key); - - BBitmap* fOffscreenBitmap; - BView* fOffscreenView; - - KeyboardLayout* fLayout; - Keymap* fKeymap; - BMessenger fTarget; - bool fEditable; - - uint8 fKeyState[16]; - int32 fModifiers; - int32 fDeadKey; - int32 fButtons; - - BPoint fClickPoint; - Key* fDragKey; - int32 fDragModifiers; - Key* fDropTarget; - BPoint fDropPoint; - - BSize fOldSize; - BFont fBaseFont; - BFont fSpecialFont; - float fBaseFontHeight; - float fBaseFontSize; - BPoint fOffset; - float fFactor; - float fGap; - - BInputServerDevice* fDevice; -}; - - -#endif // KEYBOARD_LAYOUT_VIEW_H diff --git a/src/add-ons/input_server/devices/virtualkeyboard/VirtualKeyboardWindow.cpp b/src/add-ons/input_server/devices/virtualkeyboard/VirtualKeyboardWindow.cpp index 6086e393ea..596961172b 100644 --- a/src/add-ons/input_server/devices/virtualkeyboard/VirtualKeyboardWindow.cpp +++ b/src/add-ons/input_server/devices/virtualkeyboard/VirtualKeyboardWindow.cpp @@ -61,7 +61,6 @@ VirtualKeyboardWindow::VirtualKeyboardWindow(BInputServerDevice* dev) fKeyboardView = new KeyboardLayoutView("Keyboard",fDevice); fKeyboardView->GetKeyboardLayout()->SetDefault(); - fKeyboardView->SetEditable(false); fKeyboardView->SetKeymap(&fCurrentKeymap); AddChild(BGroupLayoutBuilder(B_VERTICAL) @@ -130,7 +129,7 @@ VirtualKeyboardWindow::_LoadMaps() if (directory.SetTo(path.Path()) == B_OK) { while (directory.GetNextRef(&ref) == B_OK) { - fMapListView->AddItem(new KeymapListItem(ref)); + fMapListView->AddItem(new KeymapListItem(ref)); } } fMapListView->SortItems(&compare_key_list_items); diff --git a/src/preferences/keymap/KeyboardLayoutView.cpp b/src/preferences/keymap/KeyboardLayoutView.cpp index c9890eaa79..8432dc396f 100644 --- a/src/preferences/keymap/KeyboardLayoutView.cpp +++ b/src/preferences/keymap/KeyboardLayoutView.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -80,17 +81,18 @@ is_mappable_to_modifier(uint32 keyCode) // #pragma mark - KeyboardLayoutView -KeyboardLayoutView::KeyboardLayoutView(const char* name) +KeyboardLayoutView::KeyboardLayoutView(const char* name, BInputServerDevice* dev) : BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), fKeymap(NULL), - fEditable(true), + fEditable(dev == NULL), fModifiers(0), fDeadKey(0), fButtons(0), fDragKey(NULL), fDropTarget(NULL), - fOldSize(0, 0) + fOldSize(0, 0), + fDevice(dev) { fLayout = new KeyboardLayout; memset(fKeyState, 0, sizeof(fKeyState)); @@ -210,7 +212,7 @@ KeyboardLayoutView::MouseDown(BPoint point) || ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0 && (modifiers() & B_CONTROL_KEY) != 0)) { // secondary mouse button, pop up a swap context menu - if (!is_mappable_to_modifier(key->code)) { + if (fEditable && !is_mappable_to_modifier(key->code)) { // ToDo: Pop up a list of alternative characters to map // the key to. Currently we only add an option to remove the // current key mapping. @@ -224,7 +226,7 @@ KeyboardLayoutView::MouseDown(BPoint point) alternativesPopUp->SetAsyncAutoDestruct(true); if (alternativesPopUp->SetTargetForItems(Window()) == B_OK) alternativesPopUp->Go(ConvertToScreen(point), true); - } else { + } else if (fEditable) { // pop up the modifier keys menu BPopUpMenu* modifiersPopUp = new BPopUpMenu("Modifiers pop up", true, true, B_ITEMS_IN_COLUMN); @@ -403,7 +405,7 @@ KeyboardLayoutView::MouseUp(BPoint point) _InvalidateKey(key); if (fDragKey == NULL) - _SendFakeKeyDown(key); + _SendKeyDown(key); } fDragKey = NULL; @@ -417,6 +419,10 @@ KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit, if (fKeymap == NULL) return; + // Ignore mouse-moved events if we are acting as a real input device. + if (fDevice != NULL) + return; + // prevent dragging for tertiary mouse button if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0) return; @@ -607,7 +613,7 @@ KeyboardLayoutView::MessageReceived(BMessage* message) } } else { // Send the old key to the target, so it's not lost entirely - _SendFakeKeyDown(fDropTarget); + _SendKeyDown(fDropTarget); fKeymap->SetKey(fDropTarget->code, fModifiers, fDeadKey, (const char*)data, dataSize); @@ -1290,7 +1296,7 @@ KeyboardLayoutView::_EvaluateDropTarget(BPoint point) void -KeyboardLayoutView::_SendFakeKeyDown(const Key* key) +KeyboardLayoutView::_SendKeyDown(const Key* key) { BMessage message(B_KEY_DOWN); message.AddInt64("when", system_time()); @@ -1298,7 +1304,10 @@ KeyboardLayoutView::_SendFakeKeyDown(const Key* key) sizeof(fKeyState)); message.AddInt32("key", key->code); message.AddInt32("modifiers", fModifiers); - message.AddPointer("keymap", fKeymap); + message.AddInt32("be:key_repeat", 1); + + if (fDevice == NULL) + message.AddPointer("keymap", fKeymap); char* string; int32 numBytes; @@ -1316,7 +1325,15 @@ KeyboardLayoutView::_SendFakeKeyDown(const Key* key) delete[] string; } - fTarget.SendMessage(&message); + if (fDevice == NULL) { + fTarget.SendMessage(&message); + } else { +#if defined(VIRTUAL_KEYBOARD_DEVICE) + BMessage* deviceMessage = new BMessage(message); + if (fDevice->EnqueueMessage(deviceMessage) != B_OK) + delete deviceMessage; +#endif + } } diff --git a/src/preferences/keymap/KeyboardLayoutView.h b/src/preferences/keymap/KeyboardLayoutView.h index 0d1d485732..a9b638112a 100644 --- a/src/preferences/keymap/KeyboardLayoutView.h +++ b/src/preferences/keymap/KeyboardLayoutView.h @@ -17,13 +17,15 @@ #include "KeyboardLayout.h" +class BInputServerDevice; class BMenuItem; class Keymap; class KeyboardLayoutView : public BView { public: - KeyboardLayoutView(const char* name); + KeyboardLayoutView(const char* name, + BInputServerDevice* dev = NULL); ~KeyboardLayoutView(); void SetKeyboardLayout(KeyboardLayout* layout); @@ -95,7 +97,7 @@ private: BRect _FrameFor(const Key* key); void _SetFontSize(BView* view, key_kind keyKind); void _EvaluateDropTarget(BPoint point); - void _SendFakeKeyDown(const Key* key); + void _SendKeyDown(const Key* key); BMenuItem* _CreateSwapModifiersMenuItem(uint32 modifier, uint32 displayModifier, uint32 oldCode, @@ -126,6 +128,8 @@ private: BPoint fOffset; float fFactor; float fGap; + + BInputServerDevice* fDevice; };