Exemplo n.º 1
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;
	}
}
Exemplo n.º 2
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);
    }
}