| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the plugins of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qdirectfbinput.h" |
| #include "qdirectfbconvenience.h" |
| |
| #include <QThread> |
| #include <QDebug> |
| #include <qpa/qwindowsysteminterface.h> |
| #include <QMouseEvent> |
| #include <QEvent> |
| |
| #include <directfb.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| QDirectFbInput::QDirectFbInput(IDirectFB *dfb, IDirectFBDisplayLayer *dfbLayer) |
| : m_dfbInterface(dfb) |
| , m_dfbDisplayLayer(dfbLayer) |
| , m_shouldStop(false) |
| { |
| DFBResult ok = m_dfbInterface->CreateEventBuffer(m_dfbInterface, m_eventBuffer.outPtr()); |
| if (ok != DFB_OK) |
| DirectFBError("Failed to initialise eventbuffer", ok); |
| } |
| |
| void QDirectFbInput::run() |
| { |
| while (!m_shouldStop) { |
| if (m_eventBuffer->WaitForEvent(m_eventBuffer.data()) == DFB_OK) |
| handleEvents(); |
| } |
| } |
| |
| void QDirectFbInput::stopInputEventLoop() |
| { |
| m_shouldStop = true; |
| m_eventBuffer->WakeUp(m_eventBuffer.data()); |
| } |
| |
| void QDirectFbInput::addWindow(IDirectFBWindow *window, QWindow *platformWindow) |
| { |
| DFBResult res; |
| DFBWindowID id; |
| |
| res = window->GetID(window, &id); |
| if (res != DFB_OK) { |
| DirectFBError("QDirectFbInput::addWindow", res); |
| return; |
| } |
| |
| m_tlwMap.insert(id, platformWindow); |
| window->AttachEventBuffer(window, m_eventBuffer.data()); |
| } |
| |
| void QDirectFbInput::removeWindow(IDirectFBWindow *window) |
| { |
| DFBResult res; |
| DFBWindowID id; |
| |
| res = window->GetID(window, &id); |
| if (res != DFB_OK) { |
| DirectFBError("QDirectFbInput::removeWindow", res); |
| return; |
| } |
| |
| window->DetachEventBuffer(window, m_eventBuffer.data()); |
| m_tlwMap.remove(id); |
| } |
| |
| void QDirectFbInput::handleEvents() |
| { |
| DFBResult hasEvent = m_eventBuffer->HasEvent(m_eventBuffer.data()); |
| while(hasEvent == DFB_OK){ |
| DFBEvent event; |
| DFBResult ok = m_eventBuffer->GetEvent(m_eventBuffer.data(), &event); |
| if (ok != DFB_OK) |
| DirectFBError("Failed to get event",ok); |
| if (event.clazz == DFEC_WINDOW) { |
| switch (event.window.type) { |
| case DWET_BUTTONDOWN: |
| case DWET_BUTTONUP: |
| case DWET_MOTION: |
| handleMouseEvents(event); |
| break; |
| case DWET_WHEEL: |
| handleWheelEvent(event); |
| break; |
| case DWET_KEYDOWN: |
| case DWET_KEYUP: |
| handleKeyEvents(event); |
| break; |
| case DWET_ENTER: |
| case DWET_LEAVE: |
| handleEnterLeaveEvents(event); |
| break; |
| case DWET_GOTFOCUS: |
| handleGotFocusEvent(event); |
| break; |
| case DWET_CLOSE: |
| handleCloseEvent(event); |
| break; |
| case DWET_POSITION_SIZE: |
| handleGeometryEvent(event); |
| break; |
| default: |
| break; |
| } |
| |
| } |
| |
| hasEvent = m_eventBuffer->HasEvent(m_eventBuffer.data()); |
| } |
| } |
| |
| void QDirectFbInput::handleMouseEvents(const DFBEvent &event) |
| { |
| QPoint p(event.window.x, event.window.y); |
| QPoint globalPos(event.window.cx, event.window.cy); |
| Qt::MouseButtons buttons = QDirectFbConvenience::mouseButtons(event.window.buttons); |
| |
| QDirectFBPointer<IDirectFBDisplayLayer> layer(QDirectFbConvenience::dfbDisplayLayer()); |
| QDirectFBPointer<IDirectFBWindow> window; |
| layer->GetWindow(layer.data(), event.window.window_id, window.outPtr()); |
| |
| long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); |
| |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| QWindowSystemInterface::handleMouseEvent(tlw, timestamp, p, globalPos, buttons); |
| } |
| |
| void QDirectFbInput::handleWheelEvent(const DFBEvent &event) |
| { |
| QPoint p(event.window.x, event.window.y); |
| QPoint globalPos(event.window.cx, event.window.cy); |
| long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| QWindowSystemInterface::handleWheelEvent(tlw, timestamp, p, globalPos, |
| event.window.step*120, |
| Qt::Vertical); |
| } |
| |
| void QDirectFbInput::handleKeyEvents(const DFBEvent &event) |
| { |
| QEvent::Type type = QDirectFbConvenience::eventType(event.window.type); |
| Qt::Key key = QDirectFbConvenience::keyMap()->value(event.window.key_symbol); |
| Qt::KeyboardModifiers modifiers = QDirectFbConvenience::keyboardModifiers(event.window.modifiers); |
| |
| long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); |
| |
| QChar character; |
| if (DFB_KEY_TYPE(event.window.key_symbol) == DIKT_UNICODE) |
| character = QChar(event.window.key_symbol); |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| QWindowSystemInterface::handleKeyEvent(tlw, timestamp, type, key, modifiers, character); |
| } |
| |
| void QDirectFbInput::handleEnterLeaveEvents(const DFBEvent &event) |
| { |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| switch (event.window.type) { |
| case DWET_ENTER: |
| QWindowSystemInterface::handleEnterEvent(tlw); |
| break; |
| case DWET_LEAVE: |
| QWindowSystemInterface::handleLeaveEvent(tlw); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void QDirectFbInput::handleGotFocusEvent(const DFBEvent &event) |
| { |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| QWindowSystemInterface::handleWindowActivated(tlw); |
| } |
| |
| void QDirectFbInput::handleCloseEvent(const DFBEvent &event) |
| { |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| QWindowSystemInterface::handleCloseEvent(tlw); |
| } |
| |
| void QDirectFbInput::handleGeometryEvent(const DFBEvent &event) |
| { |
| QWindow *tlw = m_tlwMap.value(event.window.window_id); |
| QRect rect(event.window.x, event.window.y, event.window.w, event.window.h); |
| QWindowSystemInterface::handleGeometryChange(tlw, rect); |
| } |
| |
| QT_END_NAMESPACE |