예제 #1
0
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;
}
예제 #2
0
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) {
                // Send fake key down message to target
                _SendFakeKeyDown(key);
            }
        }
    }
    fDragKey = NULL;
}
예제 #3
0
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);
				}
			}
		}
	}
예제 #4
0
void
KeyboardLayoutView::_InvalidateKey(uint32 code)
{
	_InvalidateKey(_KeyForCode(code));
}
예제 #5
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;
	}
}
예제 #6
0
void
KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit,
                               const BMessage* dragMessage)
{
    if (fKeymap == NULL)
        return;

    // prevent dragging for tertiary mouse button
    if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0)
        return;

    if (dragMessage != NULL) {
        if (fEditable) {
            _InvalidateKey(fDropTarget);
            fDropPoint = point;

            _EvaluateDropTarget(point);
        }

        return;
    }

    int32 buttons;
    if (Window()->CurrentMessage() == NULL
            || Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK
            || buttons == 0)
        return;

    if (fDragKey == NULL && (fabs(point.x - fClickPoint.x) > 4
                             || fabs(point.y - fClickPoint.y) > 4)) {
        // start dragging
        Key* key = _KeyAt(fClickPoint);
        if (key == NULL)
            return;

        BRect frame = _FrameFor(key);
        BPoint offset = fClickPoint - frame.LeftTop();
        frame.OffsetTo(B_ORIGIN);

        BRect rect = frame;
        rect.right--;
        rect.bottom--;
        BBitmap* bitmap = new BBitmap(rect, B_RGBA32, true);
        bitmap->Lock();

        BView* view = new BView(rect, "drag", B_FOLLOW_NONE, 0);
        bitmap->AddChild(view);

        view->SetHighColor(0, 0, 0, 0);
        view->FillRect(view->Bounds());
        view->SetDrawingMode(B_OP_ALPHA);
        view->SetHighColor(0, 0, 0, 128);
        // set the level of transparency by value
        view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
        _DrawKey(view, frame, key, frame, false);

        view->Sync();
        bitmap->Unlock();

        BMessage drag(B_MIME_DATA);
        drag.AddInt32("key", key->code);

        char* string;
        int32 numBytes;
        fKeymap->GetChars(key->code, fModifiers, fDeadKey, &string,
                          &numBytes);
        if (string != NULL) {
            drag.AddData("text/plain", B_MIME_DATA, string, numBytes);
            delete[] string;
        }

        DragMessage(&drag, bitmap, B_OP_ALPHA, offset);
        fDragKey = key;
        fDragModifiers = fModifiers;

        fKeyState[key->code / 8] &= ~(1 << (7 - (key->code & 7)));
        _InvalidateKey(key);
    }
}