2018-02-06 14:55:35 +01:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "QskInputContext.h"
|
2018-06-04 10:00:52 +02:00
|
|
|
#include "QskInputEngine.h"
|
|
|
|
#include "QskInputPanel.h"
|
2018-04-23 14:37:17 +02:00
|
|
|
|
2018-05-01 12:41:20 +02:00
|
|
|
#include "QskLinearBox.h"
|
|
|
|
#include "QskDialog.h"
|
|
|
|
#include "QskPopup.h"
|
|
|
|
#include "QskWindow.h"
|
|
|
|
#include "QskEvent.h"
|
|
|
|
#include "QskQuick.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-04-01 12:47:44 +02:00
|
|
|
#include <QPointer>
|
2018-04-20 08:52:26 +02:00
|
|
|
#include <QGuiApplication>
|
|
|
|
|
2018-04-27 13:48:51 +02:00
|
|
|
QSK_QT_PRIVATE_BEGIN
|
|
|
|
#include <private/qguiapplication_p.h>
|
|
|
|
QSK_QT_PRIVATE_END
|
|
|
|
|
|
|
|
#include <qpa/qplatformintegration.h>
|
2018-05-09 15:45:43 +02:00
|
|
|
#include <qpa/qplatforminputcontext.h>
|
2018-04-27 13:48:51 +02:00
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
class InputEngine final : public QskInputEngine
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void attachToPanel( QQuickItem* item ) override
|
|
|
|
{
|
|
|
|
if ( m_panel )
|
|
|
|
m_panel->attachInputItem( item );
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual QskControl* createPanel() override
|
|
|
|
{
|
|
|
|
m_panel = new QskInputPanel();
|
|
|
|
|
|
|
|
connect( m_panel, &QskInputPanel::keySelected,
|
|
|
|
this, &QskInputEngine::commitKey, Qt::UniqueConnection );
|
|
|
|
|
|
|
|
connect( m_panel, &QskInputPanel::predictiveTextSelected,
|
|
|
|
this, &QskInputEngine::commitPredictiveText, Qt::UniqueConnection );
|
|
|
|
|
|
|
|
return m_panel;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual QQuickItem* inputProxy() const override
|
|
|
|
{
|
|
|
|
if ( m_panel )
|
|
|
|
{
|
|
|
|
if ( m_panel->panelHints() & QskInputPanel::InputProxy )
|
|
|
|
return m_panel->inputProxy();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
virtual void setPredictionEnabled( bool on ) override
|
|
|
|
{
|
|
|
|
if ( m_panel )
|
|
|
|
m_panel->setPanelHint( QskInputPanel::Prediction, on );
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void showPrediction( const QStringList& prediction ) override
|
|
|
|
{
|
|
|
|
if ( m_panel )
|
|
|
|
m_panel->setPrediction( prediction );
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
QPointer< QskInputPanel > m_panel;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
static QPointer< QskInputContext > qskInputContext = nullptr;
|
2018-04-27 13:48:51 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
static void qskSendToPlatformContext( QEvent::Type type )
|
2018-04-27 13:48:51 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
const auto platformInputContext =
|
|
|
|
QGuiApplicationPrivate::platformIntegration()->inputContext();
|
2018-04-27 13:48:51 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
if ( platformInputContext )
|
|
|
|
{
|
|
|
|
QEvent event( type );
|
|
|
|
QCoreApplication::sendEvent( platformInputContext, &event );
|
|
|
|
}
|
2018-04-27 13:48:51 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
static void qskInputContextHook()
|
2018-04-27 13:48:51 +02:00
|
|
|
{
|
2018-06-04 10:00:52 +02:00
|
|
|
qAddPostRoutine( [] { delete qskInputContext; } );
|
2018-04-27 13:48:51 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
Q_COREAPP_STARTUP_FUNCTION( qskInputContextHook )
|
2018-04-27 13:48:51 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
void QskInputContext::setInstance( QskInputContext* inputContext )
|
|
|
|
{
|
|
|
|
if ( inputContext != qskInputContext )
|
|
|
|
{
|
|
|
|
const auto oldContext = qskInputContext;
|
|
|
|
qskInputContext = inputContext;
|
2018-04-27 13:48:51 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
if ( oldContext && oldContext->parent() == nullptr )
|
|
|
|
delete oldContext;
|
2018-04-27 13:48:51 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
qskSendToPlatformContext( QEvent::PlatformPanel );
|
|
|
|
}
|
2018-04-27 13:48:51 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
QskInputContext* QskInputContext::instance()
|
2018-04-27 13:48:51 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
return qskInputContext;
|
2018-04-27 13:48:51 +02:00
|
|
|
}
|
|
|
|
|
2018-04-01 12:47:44 +02:00
|
|
|
class QskInputContext::PrivateData
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-01 12:47:44 +02:00
|
|
|
public:
|
2018-04-11 17:33:43 +02:00
|
|
|
// item receiving the input
|
2018-04-01 12:47:44 +02:00
|
|
|
QPointer< QQuickItem > inputItem;
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
// popup or window embedding the panel
|
2018-04-12 12:03:51 +02:00
|
|
|
QskPopup* inputPopup = nullptr;
|
|
|
|
QskWindow* inputWindow = nullptr;
|
2018-04-04 20:19:47 +02:00
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
QPointer< QskInputEngine > inputEngine;
|
2018-04-01 12:47:44 +02:00
|
|
|
};
|
|
|
|
|
2018-04-04 15:19:51 +02:00
|
|
|
QskInputContext::QskInputContext():
|
2018-04-01 12:47:44 +02:00
|
|
|
m_data( new PrivateData() )
|
|
|
|
{
|
2018-04-03 20:15:20 +02:00
|
|
|
setObjectName( "InputContext" );
|
2018-06-04 10:00:52 +02:00
|
|
|
setEngine( new InputEngine() );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskInputContext::~QskInputContext()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
void QskInputContext::setEngine( QskInputEngine* engine )
|
|
|
|
{
|
|
|
|
if ( m_data->inputEngine == engine )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( m_data->inputEngine && m_data->inputEngine->parent() == this )
|
|
|
|
{
|
|
|
|
m_data->inputEngine->disconnect( this );
|
|
|
|
|
|
|
|
if ( m_data->inputEngine->parent() == this )
|
|
|
|
delete m_data->inputEngine;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_data->inputEngine = engine;
|
|
|
|
|
|
|
|
if ( engine )
|
|
|
|
{
|
|
|
|
if ( engine->parent() == nullptr )
|
|
|
|
engine->setParent( this );
|
|
|
|
|
|
|
|
connect( engine, &QskInputEngine::activeChanged,
|
|
|
|
this, &QskInputContext::activeChanged );
|
|
|
|
|
|
|
|
connect( engine, &QskInputEngine::localeChanged,
|
|
|
|
this, [] { qskSendToPlatformContext( QEvent::LocaleChange ); } );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QskInputEngine* QskInputContext::engine() const
|
|
|
|
{
|
|
|
|
return m_data->inputEngine;
|
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
QQuickItem* QskInputContext::inputItem() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
return m_data->inputItem;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-06-01 12:00:31 +02:00
|
|
|
QskControl* QskInputContext::inputPanel() const
|
2018-04-04 12:05:01 +02:00
|
|
|
{
|
2018-06-04 10:00:52 +02:00
|
|
|
if ( m_data->inputEngine == nullptr )
|
|
|
|
return nullptr;
|
2018-05-09 15:45:43 +02:00
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
auto panel = m_data->inputEngine->panel( true );
|
2018-05-09 15:45:43 +02:00
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
if ( panel && panel->parent() != this )
|
|
|
|
panel->setParent( const_cast< QskInputContext* >( this ) );
|
2018-05-09 15:45:43 +02:00
|
|
|
|
2018-06-01 12:00:31 +02:00
|
|
|
return panel;
|
2018-04-05 14:18:15 +02:00
|
|
|
}
|
|
|
|
|
2018-04-26 14:42:33 +02:00
|
|
|
void QskInputContext::update( Qt::InputMethodQueries queries )
|
|
|
|
{
|
|
|
|
if ( queries & Qt::ImEnabled )
|
|
|
|
{
|
|
|
|
QInputMethodQueryEvent event( Qt::ImEnabled );
|
|
|
|
QCoreApplication::sendEvent( m_data->inputItem, &event );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-04-26 14:42:33 +02:00
|
|
|
if ( !event.value( Qt::ImEnabled ).toBool() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
hidePanel();
|
2018-04-26 14:42:33 +02:00
|
|
|
return;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
if ( m_data->inputEngine )
|
|
|
|
m_data->inputEngine->updateInputPanel( queries );
|
2018-04-04 15:19:51 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
QRectF QskInputContext::panelRect() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
if ( m_data->inputPopup )
|
|
|
|
return m_data->inputPopup->geometry();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
return QRectF();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-06-01 12:00:31 +02:00
|
|
|
QskPopup* QskInputContext::createEmbeddingPopup( QskControl* panel )
|
2018-04-30 10:03:51 +02:00
|
|
|
{
|
|
|
|
auto popup = new QskPopup();
|
|
|
|
|
|
|
|
popup->setAutoLayoutChildren( true );
|
|
|
|
popup->setTransparentForPositioner( false );
|
|
|
|
popup->setModal( true );
|
|
|
|
|
|
|
|
auto box = new QskLinearBox( popup );
|
|
|
|
box->addItem( panel );
|
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
Qt::Alignment alignment = Qt::AlignVCenter;
|
|
|
|
if ( m_data->inputEngine )
|
|
|
|
alignment = m_data->inputEngine->panelAlignment() & Qt::AlignVertical_Mask;
|
2018-04-30 10:03:51 +02:00
|
|
|
|
2018-06-01 12:00:31 +02:00
|
|
|
popup->setOverlay( alignment == Qt::AlignVCenter );
|
2018-04-30 10:03:51 +02:00
|
|
|
|
2018-06-01 12:00:31 +02:00
|
|
|
switch( alignment )
|
|
|
|
{
|
|
|
|
case Qt::AlignTop:
|
|
|
|
{
|
|
|
|
box->setExtraSpacingAt( Qt::BottomEdge | Qt::LeftEdge | Qt::RightEdge );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Qt::AlignVCenter:
|
|
|
|
{
|
|
|
|
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Qt::AlignBottom:
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
|
|
|
}
|
|
|
|
}
|
2018-04-30 10:03:51 +02:00
|
|
|
|
|
|
|
return popup;
|
|
|
|
}
|
|
|
|
|
2018-06-01 12:00:31 +02:00
|
|
|
QskWindow* QskInputContext::createEmbeddingWindow( QskControl* panel )
|
2018-04-30 10:03:51 +02:00
|
|
|
{
|
|
|
|
auto window = new QskWindow();
|
|
|
|
|
|
|
|
window->setFlags( window->flags() & Qt::Dialog );
|
|
|
|
//window->setModality( Qt::ApplicationModal );
|
|
|
|
window->setAutoLayoutChildren( true );
|
|
|
|
#if 0
|
|
|
|
window->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
panel->setParentItem( window->contentItem() );
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
void QskInputContext::showPanel()
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
auto focusItem = qobject_cast< QQuickItem* >( qGuiApp->focusObject() );
|
|
|
|
if ( focusItem == nullptr )
|
|
|
|
return;
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
auto panel = inputPanel();
|
|
|
|
if ( panel == nullptr )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( ( focusItem == panel )
|
|
|
|
|| qskIsAncestorOf( panel, focusItem ) )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
// ignore: usually the input proxy of the panel
|
|
|
|
return;
|
|
|
|
}
|
2018-04-18 19:41:46 +02:00
|
|
|
|
2018-04-27 13:48:51 +02:00
|
|
|
m_data->inputItem = focusItem;
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-27 13:48:51 +02:00
|
|
|
if ( QskDialog::instance()->policy() == QskDialog::TopLevelWindow )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
// The input panel is embedded in a top level window
|
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
delete m_data->inputPopup;
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( m_data->inputWindow == nullptr )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
auto window = createEmbeddingWindow( panel );
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( window )
|
|
|
|
{
|
|
|
|
QSize size = window->effectivePreferredSize();
|
|
|
|
if ( size.isEmpty() )
|
|
|
|
{
|
|
|
|
// no idea, may be something based on the screen size
|
|
|
|
size = QSize( 800, 240 );
|
|
|
|
}
|
2018-04-18 19:41:46 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
window->resize( size );
|
|
|
|
window->show();
|
2018-04-18 19:41:46 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
window->setDeleteOnClose( true );
|
|
|
|
window->installEventFilter( this );
|
|
|
|
}
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
m_data->inputWindow = window;
|
|
|
|
}
|
2018-04-11 17:33:43 +02:00
|
|
|
}
|
|
|
|
else
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
// The input panel is embedded in a popup
|
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
delete m_data->inputWindow;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( m_data->inputPopup == nullptr )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
auto popup = createEmbeddingPopup( panel );
|
2018-04-18 19:41:46 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( popup )
|
|
|
|
{
|
|
|
|
popup->setParentItem( m_data->inputItem->window()->contentItem() );
|
|
|
|
if ( popup->parent() == nullptr )
|
|
|
|
popup->setParent( this );
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
popup->setVisible( true );
|
|
|
|
popup->installEventFilter( this );
|
|
|
|
}
|
2018-06-01 12:00:31 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
m_data->inputPopup = popup;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2018-04-05 14:18:15 +02:00
|
|
|
}
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
if ( m_data->inputEngine )
|
|
|
|
m_data->inputEngine->attachInputItem( m_data->inputItem );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
void QskInputContext::hidePanel()
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
if ( m_data->inputPopup )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-17 21:28:15 +02:00
|
|
|
#if 1
|
2018-04-27 13:48:51 +02:00
|
|
|
if ( auto focusItem = m_data->inputPopup->scopedFocusItem() )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Qt bug: QQuickItem::hasFocus() is not cleared
|
|
|
|
when the corresponding focusScope gets deleted.
|
|
|
|
Usually no problem, but here the focusItem is no
|
|
|
|
child and will be reused with a different parent
|
|
|
|
later.
|
|
|
|
*/
|
|
|
|
focusItem->setFocus( false );
|
|
|
|
}
|
2018-04-17 21:28:15 +02:00
|
|
|
#endif
|
2018-04-30 10:03:51 +02:00
|
|
|
}
|
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
if ( m_data->inputEngine )
|
|
|
|
{
|
|
|
|
if ( auto panel = m_data->inputEngine->panel( false ) )
|
|
|
|
panel->setParentItem( nullptr );
|
2018-06-01 12:00:31 +02:00
|
|
|
|
2018-06-04 10:00:52 +02:00
|
|
|
m_data->inputEngine->attachInputItem( nullptr );
|
|
|
|
}
|
2018-04-17 21:28:15 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( m_data->inputPopup )
|
2018-04-27 13:48:51 +02:00
|
|
|
m_data->inputPopup->deleteLater();
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-27 13:48:51 +02:00
|
|
|
if ( m_data->inputWindow )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
QskWindow* window = m_data->inputWindow;
|
|
|
|
m_data->inputWindow = nullptr;
|
|
|
|
|
2018-04-11 17:33:43 +02:00
|
|
|
window->removeEventFilter( this );
|
|
|
|
window->close(); // deleteOnClose is set
|
2018-04-05 14:18:15 +02:00
|
|
|
}
|
2018-04-11 08:58:14 +02:00
|
|
|
|
2018-04-27 13:48:51 +02:00
|
|
|
m_data->inputItem = nullptr;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
void QskInputContext::setActive( bool on )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
if ( on )
|
|
|
|
showPanel();
|
|
|
|
else
|
|
|
|
hidePanel();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QskInputContext::isActive() const
|
|
|
|
{
|
|
|
|
if ( auto panel = inputPanel() )
|
|
|
|
{
|
|
|
|
return panel && panel->isVisible()
|
|
|
|
&& panel->window() && panel->window()->isVisible();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QLocale QskInputContext::locale() const
|
|
|
|
{
|
2018-06-04 10:00:52 +02:00
|
|
|
if ( auto panel = inputPanel() )
|
|
|
|
return panel->locale();
|
2018-04-26 14:42:33 +02:00
|
|
|
|
|
|
|
return QLocale();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskInputContext::setFocusObject( QObject* focusObject )
|
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
if ( m_data->inputItem == nullptr || m_data->inputItem == focusObject )
|
|
|
|
{
|
|
|
|
// we don't care
|
|
|
|
return;
|
|
|
|
}
|
2018-03-14 17:30:39 +01:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
const auto w = m_data->inputItem->window();
|
|
|
|
if ( w == nullptr )
|
|
|
|
return;
|
2018-04-11 17:33:43 +02:00
|
|
|
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( m_data->inputWindow )
|
2018-04-27 13:48:51 +02:00
|
|
|
{
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( focusObject == nullptr )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( m_data->inputItem->hasFocus() )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-30 10:03:51 +02:00
|
|
|
/*
|
2018-05-09 15:45:43 +02:00
|
|
|
As long as the focus is nowhere and
|
2018-04-30 10:03:51 +02:00
|
|
|
the local focus stay on the input item
|
|
|
|
we don't care
|
|
|
|
*/
|
|
|
|
|
|
|
|
return;
|
2018-04-11 17:33:43 +02:00
|
|
|
}
|
2018-04-27 13:48:51 +02:00
|
|
|
}
|
2018-04-30 10:03:51 +02:00
|
|
|
else
|
2018-04-27 13:48:51 +02:00
|
|
|
{
|
2018-04-30 10:03:51 +02:00
|
|
|
const auto focusItem = qobject_cast< QQuickItem* >( focusObject );
|
|
|
|
if ( focusItem && focusItem->window() == m_data->inputWindow )
|
|
|
|
return;
|
2018-04-11 17:33:43 +02:00
|
|
|
}
|
2018-04-27 13:48:51 +02:00
|
|
|
}
|
2018-04-30 10:03:51 +02:00
|
|
|
else if ( m_data->inputPopup )
|
2018-04-27 13:48:51 +02:00
|
|
|
{
|
2018-04-30 10:03:51 +02:00
|
|
|
if ( w->contentItem()->scopedFocusItem() == m_data->inputPopup )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
As long as the focus stays inside the inputPopup
|
|
|
|
we don't care
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
2018-04-05 14:18:15 +02:00
|
|
|
}
|
2018-04-30 10:03:51 +02:00
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
hidePanel();
|
2018-04-30 10:03:51 +02:00
|
|
|
m_data->inputItem = nullptr;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 17:01:30 +02:00
|
|
|
QskTextPredictor* QskInputContext::textPredictor( const QLocale& ) const
|
2018-04-20 08:52:26 +02:00
|
|
|
{
|
2018-05-09 17:01:30 +02:00
|
|
|
return nullptr;
|
2018-04-20 08:52:26 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
void QskInputContext::processClickAt( int cursorPosition )
|
2018-04-20 08:52:26 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
Q_UNUSED( cursorPosition );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:45:43 +02:00
|
|
|
void QskInputContext::commitPrediction( bool )
|
2018-04-04 12:05:01 +02:00
|
|
|
{
|
2018-04-27 13:48:51 +02:00
|
|
|
/*
|
2018-05-09 15:45:43 +02:00
|
|
|
called, when the input item loses the focus.
|
2018-04-27 13:48:51 +02:00
|
|
|
As it it should be possible to navigate inside of the
|
2018-05-09 15:45:43 +02:00
|
|
|
inputPanel what should we do here ?
|
2018-04-27 13:48:51 +02:00
|
|
|
*/
|
2018-04-04 12:05:01 +02:00
|
|
|
}
|
|
|
|
|
2018-04-11 08:58:14 +02:00
|
|
|
bool QskInputContext::eventFilter( QObject* object, QEvent* event )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-12 12:03:51 +02:00
|
|
|
if ( object == m_data->inputWindow )
|
2018-04-11 08:58:14 +02:00
|
|
|
{
|
2018-04-12 12:03:51 +02:00
|
|
|
switch( event->type() )
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-04-12 12:03:51 +02:00
|
|
|
case QEvent::Move:
|
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
Q_EMIT panelRectChanged();
|
2018-04-12 12:03:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::Resize:
|
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
if ( auto panel = inputPanel() )
|
|
|
|
panel->setSize( m_data->inputWindow->size() );
|
2018-04-12 12:03:51 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::DeferredDelete:
|
|
|
|
{
|
|
|
|
m_data->inputWindow = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
2018-04-11 17:33:43 +02:00
|
|
|
}
|
2018-04-12 12:03:51 +02:00
|
|
|
}
|
2018-04-20 08:52:26 +02:00
|
|
|
else if ( object == m_data->inputPopup )
|
2018-04-12 12:03:51 +02:00
|
|
|
{
|
2018-04-12 13:32:28 +02:00
|
|
|
switch( static_cast< int >( event->type() ) )
|
2018-04-11 08:58:14 +02:00
|
|
|
{
|
2018-04-12 12:03:51 +02:00
|
|
|
case QskEvent::GeometryChange:
|
2018-04-11 17:33:43 +02:00
|
|
|
{
|
2018-05-09 15:45:43 +02:00
|
|
|
Q_EMIT panelRectChanged();
|
2018-04-12 12:03:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case QEvent::DeferredDelete:
|
|
|
|
{
|
2018-04-20 08:52:26 +02:00
|
|
|
m_data->inputPopup = nullptr;
|
2018-04-12 12:03:51 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-04-11 08:58:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Inherited::eventFilter( object, event );
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
#include "moc_QskInputContext.cpp"
|