From 9825ae145e432f379627d1f71485c778da4c2cd1 Mon Sep 17 00:00:00 2001 From: sungmin ha Date: Sun, 26 Jul 2015 17:06:10 +0900 Subject: [PATCH] tablet: added maru tablet device added mouse operation Change-Id: I500cff93afccd60cbee2dbb49c9ea6616ee94dab Signed-off-by: sungmin ha --- tizen/src/emul_state.c | 6 +- tizen/src/emulator.c | 18 +++ tizen/src/hw/maru_device_ids.h | 2 + tizen/src/hw/virtio/Makefile.objs | 1 + tizen/src/hw/virtio/maru_virtio_pci.c | 55 +++++++ tizen/src/hw/virtio/maru_virtio_tablet.c | 264 +++++++++++++++++++++++++++++++ tizen/src/hw/virtio/maru_virtio_tablet.h | 65 ++++++++ tizen/src/skin/maruskin_operation.c | 19 ++- tizen/src/ui/displaybase.cpp | 173 ++++++++++++++++---- tizen/src/ui/displaybase.h | 39 ++++- tizen/src/ui/displayglwidget.cpp | 24 ++- tizen/src/ui/displayglwidget.h | 7 +- tizen/src/ui/displayswwidget.cpp | 25 ++- tizen/src/ui/displayswwidget.h | 5 +- tizen/src/ui/mainwindow.cpp | 4 +- 15 files changed, 667 insertions(+), 40 deletions(-) create mode 100644 tizen/src/hw/virtio/maru_virtio_tablet.c create mode 100644 tizen/src/hw/virtio/maru_virtio_tablet.h diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index 399cef5..7774da4 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -243,7 +243,11 @@ char* get_emul_host_ip(void) int get_max_touch_point(void) { - return ts->max_finger; + if (ts) { + return ts->max_finger; + } else { + return 1; + } } /* base port for emualtor vm */ diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index ce68a53..4909ab2 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -59,6 +59,7 @@ int thread_running = 1; /* Check if we need exit main */ DECLARE_DEBUG_CHANNEL(main); +#define INPUT_TOUCH_PARAMETER "virtio-touchscreen-pci" #define ARGS_LIMIT 128 #define LEN_MARU_KERNEL_CMDLINE 512 char maru_kernel_cmdline[LEN_MARU_KERNEL_CMDLINE]; @@ -158,6 +159,21 @@ static void print_system_info(void) print_system_info_os(); } +static void set_qemu_input_mode(void) +{ + int i; + for (i = 0; i < _qemu_argc; ++i) { + if (strstr(_qemu_argv[i], INPUT_TOUCH_PARAMETER) != NULL) { + /* touchscreen */ + set_emul_input_touch_enable(true); + } + } + + if (is_emul_input_touch_enable() != true) { + set_emul_input_mouse_enable(true); + } +} + static void print_options_info(void) { int i; @@ -339,6 +355,8 @@ static int emulator_main(int argc, char *argv[], char **envp) atexit(maru_atexit); emulator_add_exit_notifier(&emulator_exit); + set_qemu_input_mode(); + print_system_info(); print_options_info(); diff --git a/tizen/src/hw/maru_device_ids.h b/tizen/src/hw/maru_device_ids.h index 0942e39..35fa05f 100644 --- a/tizen/src/hw/maru_device_ids.h +++ b/tizen/src/hw/maru_device_ids.h @@ -53,6 +53,7 @@ #define PCI_DEVICE_ID_VIRTIO_ROTARY 0x1022 #define PCI_DEVICE_ID_VIRTIO_ESM 0x1024 #define PCI_DEVICE_ID_VIRTIO_HWKEY 0x1028 +#define PCI_DEVICE_ID_VIRTIO_TABLET 0x1029 #define PCI_DEVICE_ID_VIRTIO_EVDI 0x102C #define PCI_DEVICE_ID_VIRTIO_SENSOR 0x1034 #define PCI_DEVICE_ID_VIRTIO_POWER 0x1035 @@ -100,5 +101,6 @@ #define VIRTIO_ID_POWER 40 #define VIRTIO_ID_VMODEM 41 #define VIRTIO_ID_ROTARY 42 +#define VIRTIO_ID_TABLET 43 #endif /* MARU_DEVICE_IDS_H_ */ diff --git a/tizen/src/hw/virtio/Makefile.objs b/tizen/src/hw/virtio/Makefile.objs index 026af61..adf0677 100644 --- a/tizen/src/hw/virtio/Makefile.objs +++ b/tizen/src/hw/virtio/Makefile.objs @@ -10,3 +10,4 @@ obj-y += maru_virtio_power.o obj-y += maru_virtio_sensor.o obj-y += maru_virtio_vmodem.o obj-y += maru_virtio_rotary.o +obj-y += maru_virtio_tablet.o diff --git a/tizen/src/hw/virtio/maru_virtio_pci.c b/tizen/src/hw/virtio/maru_virtio_pci.c index 3271a86..61cfc21 100644 --- a/tizen/src/hw/virtio/maru_virtio_pci.c +++ b/tizen/src/hw/virtio/maru_virtio_pci.c @@ -41,6 +41,7 @@ #include "maru_virtio_nfc.h" #include "maru_virtio_vmodem.h" #include "maru_virtio_rotary.h" +#include "maru_virtio_tablet.h" typedef struct VirtIOTouchscreenPCI VirtIOTouchscreenPCI; typedef struct VirtIOEVDIPCI VirtIOEVDIPCI; @@ -53,6 +54,7 @@ typedef struct VirtIOPOWERPCI VirtIOPOWERPCI; typedef struct VirtIOJACKPCI VirtIOJACKPCI; typedef struct VirtIOVModemPCI VirtIOVModemPCI; typedef struct VirtIORotaryPCI VirtIORotaryPCI; +typedef struct VirtIOTabletPCI VirtIOTabletPCI; /* * virtio-touchscreen-pci: This extends VirtioPCIProxy. @@ -113,6 +115,17 @@ struct VirtIOHWKeyPCI { }; /* + * virtio-tablet-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_TABLET_PCI "virtio-tablet-pci" +#define VIRTIO_TABLET_PCI(obj) \ + OBJECT_CHECK(VirtIOTabletPCI, (obj), TYPE_VIRTIO_TABLET_PCI) +struct VirtIOTabletPCI { + VirtIOPCIProxy parent_obj; + VirtIOTablet vdev; +}; + +/* * virtio-sensor-pci: This extends VirtioPCIProxy. */ #define TYPE_VIRTIO_SENSOR_PCI "virtio-sensor-pci" @@ -358,6 +371,47 @@ static TypeInfo virtio_hwkey_pci_info = { .class_init = virtio_hwkey_pci_class_init, }; +/* virtio-tablet-pci */ + +static int virtio_tablet_pci_init(VirtIOPCIProxy *vpci_dev) +{ + VirtIOTabletPCI *dev = VIRTIO_TABLET_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); + if (qdev_init(vdev) < 0) { + return -1; + } + return 0; +} + +static void virtio_tablet_pci_class_init(ObjectClass *klass, void *data) +{ + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + k->init = virtio_tablet_pci_init; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_TABLET; + pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; + pcidev_k->class_id = PCI_CLASS_OTHERS; +} + +static void virtio_tablet_pci_instance_init(Object *obj) +{ + VirtIOTabletPCI *dev = VIRTIO_TABLET_PCI(obj); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_TABLET); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); +} + +static TypeInfo virtio_tablet_pci_info = { + .name = TYPE_VIRTIO_TABLET_PCI, + .parent = TYPE_VIRTIO_PCI, + .instance_size = sizeof(VirtIOTabletPCI), + .instance_init = virtio_tablet_pci_instance_init, + .class_init = virtio_tablet_pci_class_init, +}; + /* virtio-evdi-pci */ static Property virtio_evdi_pci_properties[] = { @@ -671,6 +725,7 @@ static void maru_virtio_pci_register_types(void) type_register_static(&virtio_evdi_pci_info); type_register_static(&virtio_esm_pci_info); type_register_static(&virtio_hwkey_pci_info); + type_register_static(&virtio_tablet_pci_info); type_register_static(&virtio_keyboard_pci_info); type_register_static(&virtio_touchscreen_pci_info); type_register_static(&virtio_sensor_pci_info); diff --git a/tizen/src/hw/virtio/maru_virtio_tablet.c b/tizen/src/hw/virtio/maru_virtio_tablet.c new file mode 100644 index 0000000..9c1427f --- /dev/null +++ b/tizen/src/hw/virtio/maru_virtio_tablet.c @@ -0,0 +1,264 @@ +/* + * Maru Virtio Tablet Device + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Sungmin Ha + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include "emul_state.h" +#include "maru_virtio_tablet.h" +#include "hw/maru_device_ids.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(qemu, tablet); + +#define DEVICE_NAME "virtio-tablet" +#define MAX_BUF_COUNT 256 +static int vqidx; +/* + * Tablet event queue + */ +typedef struct TabletEventEntry { + unsigned int index; + EmulTabletEvent tablet; + + QTAILQ_ENTRY(TabletEventEntry) node; +} TabletEventEntry; + +/* the maximum number of Tablet event that can be put into a queue */ +#define MAX_TABLET_EVENT_CNT 256 + +static TabletEventEntry _events_buf[MAX_TABLET_EVENT_CNT]; +static QTAILQ_HEAD(, TabletEventEntry) events_queue = + QTAILQ_HEAD_INITIALIZER(events_queue); + +static unsigned int event_ringbuf_cnt; /* _events_buf */ +static unsigned int event_queue_cnt; /* events_queue */ + +/* + * VirtQueueElement queue + */ +typedef struct ElementEntry { + unsigned int el_index; + unsigned int sg_index; + VirtQueueElement elem; + + QTAILQ_ENTRY(ElementEntry) node; +} ElementEntry; + +static QTAILQ_HEAD(, ElementEntry) elem_queue = + QTAILQ_HEAD_INITIALIZER(elem_queue); + +static unsigned int elem_ringbuf_cnt; /* _elem_buf */ +static unsigned int elem_queue_cnt; /* elem_queue */ + +VirtIOTablet *vtk; +VirtQueueElement elem_vtk; + +/* lock for between communication thread and IO thread */ +static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; + +void maru_tablet_event(int event_type, int x, int y, int btn, int btn_status) +{ + TabletEventEntry *entry = NULL; + + if (!vtk) { + INFO("Tablet device can not be used.\n"); + return; + } + + if (unlikely(event_queue_cnt >= MAX_TABLET_EVENT_CNT)) { + INFO("full tablet event queue, lose event\n", event_queue_cnt); + + qemu_bh_schedule(vtk->bh); + return; + } + + entry = &(_events_buf[event_ringbuf_cnt % MAX_TABLET_EVENT_CNT]); + + /* tablet event is copied into the queue */ + entry->tablet.x = x; + entry->tablet.y = y; + entry->tablet.btn = btn; + entry->tablet.btn_status = btn_status; + entry->tablet.event_type = event_type; + + pthread_mutex_lock(&event_mutex); + + event_ringbuf_cnt++; + + /* 1 ~ */ + entry->index = ++event_queue_cnt; + + QTAILQ_INSERT_TAIL(&events_queue, entry, node); + + pthread_mutex_unlock(&event_mutex); + + /* call maru_virtio_tablet_notify */ + qemu_bh_schedule(vtk->bh); + + TRACE("tablet event (%d) : x=%d, y=%d, btn=%d, btn_status=%d, event_type=%d\n", + entry->index, entry->tablet.x, entry->tablet.y, entry->tablet.btn, + entry->tablet.btn_status, entry->tablet.event_type); +} + +static void maru_virtio_tablet_handle(VirtIODevice *vdev, VirtQueue *vq) +{ + int virt_sg_index = 0; + + TRACE("maru_virtio_tablet_handle\n"); + + if (unlikely(virtio_queue_empty(vtk->vq))) { + TRACE("virtqueue is empty\n"); + return; + } + /* Get a queue buffer which is written by guest side. */ + do { + virt_sg_index = virtqueue_pop(vq, &elem_vtk); + } while (virt_sg_index < MAX_BUF_COUNT); +} + +void maru_virtio_tablet_notify(void) +{ + TabletEventEntry *event_entry = NULL; + + TRACE("maru_virtio_tablet_notify\n"); + + if (unlikely(!virtio_queue_ready(vtk->vq))) { + ERR("virtio queue is not ready\n"); + return; + } + + while (true) { + if (event_queue_cnt == 0) { + TRACE("no event\n"); + break; + } + + /* get tablet event from host queue */ + event_entry = QTAILQ_FIRST(&events_queue); + + /* copy event into virtio buffer */ + memcpy(elem_vtk.in_sg[vqidx++].iov_base, &(event_entry->tablet), + sizeof(EmulTabletEvent)); + if (vqidx == MAX_BUF_COUNT) { + vqidx = 0; + } + + virtqueue_push(vtk->vq, &elem_vtk, sizeof(EmulTabletEvent)); + virtio_notify(&vtk->vdev, vtk->vq); + + pthread_mutex_lock(&event_mutex); + + /* remove host event */ + QTAILQ_REMOVE(&events_queue, event_entry, node); + event_queue_cnt--; + + pthread_mutex_unlock(&event_mutex); + } +} + +static uint32_t virtio_tablet_get_features( + VirtIODevice *vdev, uint32_t request_features) +{ + return request_features; +} + +static void maru_tablet_bh(void *opaque) +{ + maru_virtio_tablet_notify(); +} + +static void virtio_tablet_device_realize(DeviceState *dev, Error **errp) +{ + INFO("initialize the tablet device\n"); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + vtk = VIRTIO_TABLET(dev); + + if (vdev == NULL) { + ERR("failed to initialize the tablet device\n"); + return; + } + + virtio_init(vdev, TYPE_VIRTIO_TABLET, VIRTIO_ID_TABLET, 0); + + vtk->vq = virtio_add_queue(vdev, MAX_BUF_COUNT, maru_virtio_tablet_handle); + + vtk->qdev = dev; + + /* reset the counters */ + pthread_mutex_lock(&event_mutex); + event_queue_cnt = event_ringbuf_cnt = 0; + pthread_mutex_unlock(&event_mutex); + + elem_queue_cnt = elem_ringbuf_cnt = 0; + + /* bottom-half */ + vtk->bh = qemu_bh_new(maru_tablet_bh, vtk); +} + +static void virtio_tablet_device_unrealize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + + INFO("exit the tablet device\n"); + + if (vtk->bh) { + qemu_bh_delete(vtk->bh); + } + + virtio_cleanup(vdev); + + pthread_mutex_destroy(&event_mutex); +} + +static void virtio_tablet_device_reset(VirtIODevice *vdev) +{ + INFO("reset tablet device\n"); + vqidx = 0; +} + +static void virtio_tablet_class_init(ObjectClass *klass, void *data) +{ + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + vdc->unrealize = virtio_tablet_device_unrealize; + vdc->realize = virtio_tablet_device_realize; + vdc->reset = virtio_tablet_device_reset; + vdc->get_features = virtio_tablet_get_features; +} + +static const TypeInfo virtio_tablet_info = { + .name = TYPE_VIRTIO_TABLET, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOTablet), + .class_init = virtio_tablet_class_init, +}; + +static void virtio_register_types(void) +{ + type_register_static(&virtio_tablet_info); +} + +type_init(virtio_register_types) diff --git a/tizen/src/hw/virtio/maru_virtio_tablet.h b/tizen/src/hw/virtio/maru_virtio_tablet.h new file mode 100644 index 0000000..2b35527 --- /dev/null +++ b/tizen/src/hw/virtio/maru_virtio_tablet.h @@ -0,0 +1,65 @@ +/* + * Maru Virtio Tablet Device + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Sungmin Ha + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef MARU_TABLET_H_ +#define MARU_TABLET_H_ + +#include "ui/console.h" +#include "hw/virtio/virtio.h" + +#define TYPE_VIRTIO_TABLET "virtio-tablet-device" +#define VIRTIO_TABLET(obj) \ + OBJECT_CHECK(VirtIOTablet, (obj), TYPE_VIRTIO_TABLET) + +typedef struct VirtIOTablet +{ + VirtIODevice vdev; + /* simply a queue into which buffers are posted + by the guest for consumption by the host */ + VirtQueue *vq; + + QEMUBH *bh; + DeviceState *qdev; +} VirtIOTablet; + +/* This structure must match the kernel definitions */ +typedef struct EmulTabletEvent { + uint8_t event_type; + uint32_t x; + uint32_t y; + uint32_t btn; + uint32_t btn_status; +} EmulTabletEvent; + +VirtIODevice *maru_virtio_tablet_init(DeviceState *dev); +void maru_virtio_tablet_exit(VirtIODevice *vdev); + +void maru_tablet_event(int event_type, int x, int y, int btn, int btn_status); +void maru_virtio_tablet_notify(void); + +#endif /* MARU_TABLET_H_ */ diff --git a/tizen/src/skin/maruskin_operation.c b/tizen/src/skin/maruskin_operation.c index 0fd2b3e..f89edea 100644 --- a/tizen/src/skin/maruskin_operation.c +++ b/tizen/src/skin/maruskin_operation.c @@ -53,6 +53,7 @@ #include "ecs/ecs.h" #include "hw/virtio/maru_virtio_evdi.h" #include "hw/virtio/maru_virtio_rotary.h" +#include "ui/input.h" #ifdef CONFIG_HAX #include "target-i386/hax-i386.h" @@ -175,7 +176,23 @@ void do_mouse_event(int button_type, int event_type, guest_x = x; guest_y = y; - virtio_touchscreen_event(x, y, z, event_type); + if (x != 0) { + qemu_input_queue_rel(NULL, INPUT_AXIS_X, x); + } + if (y != 0) { + qemu_input_queue_rel(NULL, INPUT_AXIS_Y, y); + } + qemu_input_event_sync(); + + break; + case PS2_DOWN: + qemu_input_queue_btn(NULL, INPUT_BUTTON_LEFT, 1); + qemu_input_event_sync(); + + break; + case PS2_UP: + qemu_input_queue_btn(NULL, INPUT_BUTTON_LEFT, 0); + qemu_input_event_sync(); break; default: diff --git a/tizen/src/ui/displaybase.cpp b/tizen/src/ui/displaybase.cpp index a8ba5fe..6225b8a 100644 --- a/tizen/src/ui/displaybase.cpp +++ b/tizen/src/ui/displaybase.cpp @@ -33,6 +33,7 @@ extern "C" { void req_set_sensor_accel_angle(int angle); +void maru_tablet_event(int event_type, int x, int y, int btn, int btn_status); } #define BLANK_GUIDE_IMAGE_PATH "../images/" @@ -42,8 +43,8 @@ uint32_t qt5_window_width = 0; uint32_t qt5_window_height = 0; int qt5_window_angle = 0; -DisplayBase::DisplayBase(DisplayType *displayForm, qreal scaleFactor, - QWidget *w) : widget(w) +DisplayBase::DisplayBase(DisplayType *displayForm, QSize resolution, qreal scaleFactor, + QWidget *w) : resolution(resolution), widget(w) { this->rect = displayForm->getRect(); this->maskImage = displayForm->getMask(); @@ -56,6 +57,14 @@ DisplayBase::DisplayBase(DisplayType *displayForm, qreal scaleFactor, this->gImg = new QImage(); this->gPxmImg = new QPixmap(); + isMouse = is_emul_input_mouse_enable(); + if (isMouse) { + prevX = 0; + prevY = 0; + lastMouseTime.tv_sec = 0; + mouseStatus = MOUSE_LEAVE; + } + loadGuideImg(); MainWindow *win = (MainWindow *)widget->parentWidget(); @@ -238,7 +247,11 @@ void DisplayBase::handleMousePress(QMouseEvent *event) if (event->button() == Qt::LeftButton) { isDragging = true; - tsHelper->mousePressed(event, getGuestPos(event->pos())); + if (isMouse) { + do_mouse_event(1, PS2_PRESS, 0, 0, 0, 0, 0); + } else { + tsHelper->mousePressed(event, getGuestPos(event->pos())); + } } } @@ -249,45 +262,147 @@ void DisplayBase::handleMouseRelease(QMouseEvent *event) isDragging = false; } - tsHelper->mouseReleased(event, getGuestPos(event->pos())); + if (isMouse) { + do_mouse_event(1, PS2_RELEASE, 0, 0, 0, 0, 0); + } else { + tsHelper->mouseReleased(event, getGuestPos(event->pos())); + } } } void DisplayBase::handleMouseMove(QMouseEvent *event) { - if (isDragging == true) { - int hostPosX = event->x(); - int hostPosY = event->y(); - - /* bounds checking */ - if (hostPosX < 0) { - hostPosX = 0; - isDragging = false; - } else if (hostPosX >= widget->width()) { - hostPosX = widget->width() - 1; - isDragging = false; + if (isMouse) { + int event_type = MOUSE_MOVE; + int clientX = event->x(); + int clientY = event->y(); + + if (clientX < 0 || clientX > widget->width() || + clientY < 0 || clientY > widget->height()) { + if (isDragging == true) { + isDragging = false; + qDebug("auto released..."); + do_mouse_event(1, PS2_RELEASE, 0, 0, 0, 0, 0); + return; + } else { + /* do nothing */ + } } - - if (hostPosY < 0) { - hostPosY = 0; - isDragging = false; - } else if (hostPosY >= widget->height()) { - hostPosY = widget->height() - 1; - isDragging = false; + sendMouseEvent(event_type, clientX, clientY); + } else { /* touch device */ + if (isDragging == true) { + int hostPosX = event->x(); + int hostPosY = event->y(); + + /* bounds checking */ + if (hostPosX < 0) { + hostPosX = 0; + isDragging = false; + } else if (hostPosX >= widget->width()) { + hostPosX = widget->width() - 1; + isDragging = false; + } + + if (hostPosY < 0) { + hostPosY = 0; + isDragging = false; + } else if (hostPosY >= widget->height()) { + hostPosY = widget->height() - 1; + isDragging = false; + } + + if (isDragging == false) { + QPoint clientPos(hostPosX, hostPosY); + qDebug() << "drag out of touch screen :" << clientPos; + + // TODO: modify event + tsHelper->mouseReleased(event, getGuestPos(clientPos)); + } else { + tsHelper->mouseMoved(event, getGuestPos(event->pos())); + } } + } +} - if (isDragging == false) { - QPoint clientPos(hostPosX, hostPosY); - qDebug() << "drag out of touch screen :" << clientPos; +void DisplayBase::handleMouseInit(QMouseEvent *event) +{ + do_mouse_event(1, MOUSE_MOVE, -widget->width()/scaleFactor, + -widget->height()/scaleFactor, + -widget->width()/scaleFactor, + -widget->height()/scaleFactor, 0); + prevX = 0; + prevY = 0; +} - // TODO: modify event - tsHelper->mouseReleased(event, getGuestPos(clientPos)); - } else { - tsHelper->mouseMoved(event, getGuestPos(event->pos())); +void DisplayBase::handleMouseEnter(QEvent *event) +{ + if (isMouse) { + if (mouseStatus == MOUSE_LEAVE) { + mouseStatus = MOUSE_ENTER; } } } +void DisplayBase::handleMouseLeave(QEvent *event) +{ + if (isMouse) { + mouseStatus = MOUSE_LEAVE; + } +} + +void DisplayBase::sendMouseEvent(int eventType, int clientX, int clientY) +{ + int xx = clientX / scaleFactor; + int yy = clientY / scaleFactor; + int absX = xx; + int absY = yy; + + /* TODO: x*cos(rad)-y*sin(rad) */ + switch(rotateAngle) { + case 90: /* Reverse Landscape */ + absX = yy; + absY = resolution.height() - xx; + break; + case 180: /* Reverse Portrait */ + absX = resolution.width() - xx; + absY = resolution.height() - yy; + break; + case 270: /* Landscape */ + absX = resolution.width() - yy; + absY = xx; + break; + case 0: + default: + break; + } + + /* Because the TV usb mouse pointer is moved to center after a couple of seconds. + * Also the mouse pointer can be entered before emulator skin is initialized. + */ + struct timeval tv; + gettimeofday(&tv, NULL); + if (tv.tv_sec - lastMouseTime.tv_sec > CURSOR_RESET_TIME || mouseStatus != MOUSE_ENTERED) { + maru_tablet_event(INPUT_MOVE, absX, absY, 0, 0); + prevX = absX; + prevY = absY; + mouseStatus = MOUSE_ENTERED; + } + gettimeofday(&lastMouseTime, NULL); + + prevX = (prevX > resolution.width()) ? resolution.width() : prevX; + prevX = (prevX < 0) ? 0 : prevX; + + prevY = (prevY > resolution.height()) ? resolution.height() : prevY; + prevY = (prevY < 0) ? 0 : prevY; + + int relX = absX - prevX; + int relY = absY - prevY; + + do_mouse_event(1, MOUSE_MOVE, clientX, clientY, relX, relY, 0); + prevX = absX; + prevY = absY; +} + DisplayBase::~DisplayBase() { qDebug("destroy display"); diff --git a/tizen/src/ui/displaybase.h b/tizen/src/ui/displaybase.h index fd5c0bc..127c892 100644 --- a/tizen/src/ui/displaybase.h +++ b/tizen/src/ui/displaybase.h @@ -35,6 +35,7 @@ #include #include #include +#include #include "layout/displaytype.h" #include "input/touchscreenhelper.h" @@ -43,6 +44,28 @@ extern "C" { void qt5_graphic_hw_invalidate(void); } +enum { + TOUCH_PRESS = 1, + TOUCH_RELEASE = 2, + PS2_MOVE = 6, + PS2_PRESS = 8, + PS2_RELEASE = 9, +}; + +enum { + MOUSE_LEAVE = 0, + MOUSE_ENTER = 1, + MOUSE_ENTERED = 2, +}; + +/* keep it consistent with emulator-kernel tablet definition */ +enum { + INPUT_MOVE = 1, + INPUT_BTN = 2, +}; + +#define CURSOR_RESET_TIME 6 /* TV spec (sec) */ + class DisplayBase { public: @@ -63,7 +86,7 @@ public: TouchScreenHelper *getTouchScreenHelper(); protected: - DisplayBase(DisplayType *displayForm, qreal scaleFactor, QWidget *w); + DisplayBase(DisplayType *displayForm, QSize resolution, qreal scaleFactor, QWidget *w); virtual ~DisplayBase(); void handlePaint(QPaintEvent *event); @@ -72,12 +95,26 @@ protected: void handleMousePress(QMouseEvent *event); void handleMouseRelease(QMouseEvent *event); void handleMouseMove(QMouseEvent *event); + void handleMouseInit(QMouseEvent *event); + + void handleMouseEnter(QEvent *event); + void handleMouseLeave(QEvent *event); int rotateAngle; qreal scaleFactor; bool isDragging; private: + void sendMouseEvent(int eventType, int clientX, int clientY); + + QSize resolution; + bool isMouse; + + int prevX; + int prevY; + int mouseStatus; + struct timeval lastMouseTime; + QLabel *gLabel; QPixmap *gPxmImg; QImage *gImg; diff --git a/tizen/src/ui/displayglwidget.cpp b/tizen/src/ui/displayglwidget.cpp index 8eccc9f..28b5f81 100644 --- a/tizen/src/ui/displayglwidget.cpp +++ b/tizen/src/ui/displayglwidget.cpp @@ -30,11 +30,21 @@ #include "displayglwidget.h" +extern "C" { +#include "emul_state.h" +}; + DisplayGLWidget::DisplayGLWidget(QWidget *parent, QGLContext *context, - DisplayType *displayForm, qreal scaleFactor) : - QGLWidget(context, parent), DisplayBase(displayForm, scaleFactor, this) + DisplayType *displayForm, QSize resolution, qreal scaleFactor) : + QGLWidget(context, parent), DisplayBase(displayForm, resolution, scaleFactor, this) { setAutoBufferSwap(false); + isMouse = is_emul_input_mouse_enable(); + /* mouse mode */ + if (isMouse) { + setCursor(Qt::BlankCursor); + setMouseTracking(true); + } } void DisplayGLWidget::initializeGL() @@ -74,6 +84,16 @@ void DisplayGLWidget::mouseReleaseEvent(QMouseEvent *event) handleMouseRelease(event); } +void DisplayGLWidget::enterEvent(QEvent *event) +{ + handleMouseEnter(event); +} + +void DisplayGLWidget::leaveEvent(QEvent *event) +{ + handleMouseLeave(event); +} + void DisplayGLWidget::mouseMoveEvent(QMouseEvent *event) { handleMouseMove(event); diff --git a/tizen/src/ui/displayglwidget.h b/tizen/src/ui/displayglwidget.h index bd2e6a0..f41e083 100644 --- a/tizen/src/ui/displayglwidget.h +++ b/tizen/src/ui/displayglwidget.h @@ -42,7 +42,7 @@ class DisplayGLWidget : public QGLWidget, public: DisplayGLWidget(QWidget *parent, QGLContext *context, - DisplayType *displayForm, qreal scaleFactor); + DisplayType *displayForm, QSize resolution, qreal scaleFactor); ~DisplayGLWidget(); protected: @@ -54,6 +54,11 @@ protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); + + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); +private: + bool isMouse; }; #endif // DISPLAYGLWIDGET_H diff --git a/tizen/src/ui/displayswwidget.cpp b/tizen/src/ui/displayswwidget.cpp index 67d2e14..7d1d278 100644 --- a/tizen/src/ui/displayswwidget.cpp +++ b/tizen/src/ui/displayswwidget.cpp @@ -31,9 +31,13 @@ #include "displayswwidget.h" #include "input/multitouchtracker.h" +extern "C" { +#include "emul_state.h" +}; + DisplaySWWidget::DisplaySWWidget(QWidget *parent, - DisplayType *displayForm, qreal scaleFactor) : - QLabel(parent), DisplayBase(displayForm, scaleFactor, this) + DisplayType *displayForm, QSize resolution, qreal scaleFactor) : + QLabel(parent), DisplayBase(displayForm, resolution, scaleFactor, this) { this->mtTracker = getTouchScreenHelper()->getMtTracker(); @@ -43,6 +47,13 @@ DisplaySWWidget::DisplaySWWidget(QWidget *parent, displayForm->getRect().height() * scaleFactor); initImage.fill(Qt::black); setPixmap(initImage); + + isMouse = is_emul_input_mouse_enable(); + /* mouse mode */ + if (isMouse) { + setCursor(Qt::BlankCursor); + setMouseTracking(true); + } } /* override */ @@ -93,6 +104,16 @@ void DisplaySWWidget::mouseMoveEvent(QMouseEvent *event) handleMouseMove(event); } +void DisplaySWWidget::enterEvent(QEvent *event) +{ + handleMouseEnter(event); +} + +void DisplaySWWidget::leaveEvent(QEvent *event) +{ + handleMouseLeave(event); +} + DisplaySWWidget::~DisplaySWWidget() { /* do nothing */ diff --git a/tizen/src/ui/displayswwidget.h b/tizen/src/ui/displayswwidget.h index f38d3ca..779c7e8 100644 --- a/tizen/src/ui/displayswwidget.h +++ b/tizen/src/ui/displayswwidget.h @@ -42,7 +42,7 @@ class DisplaySWWidget : public QLabel, public: DisplaySWWidget(QWidget *parent, - DisplayType *displayForm, qreal scaleFactor); + DisplayType *displayForm, QSize resolution, qreal scaleFactor); ~DisplaySWWidget(); protected: @@ -53,8 +53,11 @@ protected: void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); private: MultiTouchTracker *mtTracker; + bool isMouse; }; #endif // DISPLAYSWWIDGET_H diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp index da51172..dcf9599 100644 --- a/tizen/src/ui/mainwindow.cpp +++ b/tizen/src/ui/mainwindow.cpp @@ -129,7 +129,7 @@ DisplayBase *MainWindow::createDisplay(DisplayType *displayForm) QGLContext *context = new QGLContext(format); displayWidget = new DisplayGLWidget(this, context, - displayForm, getUIState()->getScaleFactor()); + displayForm, uiInfo->resolution, getUIState()->getScaleFactor()); context->setFormat(format); context->create(wrapperContext); @@ -153,7 +153,7 @@ DisplayBase *MainWindow::createDisplay(DisplayType *displayForm) swapperThread->start(); } else { /* off-screen rendering */ DisplaySWWidget *widget = new DisplaySWWidget(this, - displayForm, getUIState()->getScaleFactor()); + displayForm, uiInfo->resolution, getUIState()->getScaleFactor()); screenWidget = widget; displayWidget = widget; -- 2.7.4