kylin-virtual-keyboard/ 0000775 0001750 0001750 00000000000 15160532634 014115 5 ustar feng feng kylin-virtual-keyboard/src/ 0000775 0001750 0001750 00000000000 15160532634 014704 5 ustar feng feng kylin-virtual-keyboard/src/virtualkeyboardsettings/ 0000775 0001750 0001750 00000000000 15160532634 021674 5 ustar feng feng kylin-virtual-keyboard/src/virtualkeyboardsettings/virtualkeyboardsettings.h 0000664 0001750 0001750 00000004216 15160532634 027040 0 ustar feng feng /*
* Copyright 2023 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef _VIRTUALKEYBOARDSETTINGS_H_
#define _VIRTUALKEYBOARDSETTINGS_H_
#include
#include
#include
#include "log.h"
class VirtualKeyboardSettings : public QObject {
Q_OBJECT
public:
static VirtualKeyboardSettings &getInstance();
void updateFloatButtonAvailability(bool value);
bool isFloatButtonEnabled() const;
bool isAnimationEnabled() const;
bool isPreloadViewEnabled() const;
float calculateVirtualKeyboardScaleFactor() const;
const QString trayIconShow() const;
private:
VirtualKeyboardSettings();
~VirtualKeyboardSettings() override = default;
Q_DISABLE_COPY(VirtualKeyboardSettings)
void init();
void emitFloatButtonAvailabilityChanged();
void emitTrayIconShowChanged();
signals:
void requestFloatButtonEnabled();
void requestFloatButtonDisabled();
void scaleFactorChanged();
void animationAvailabilityChanged();
void neverShowTrayIcon();
void alwaysShowTrayIcon();
void showTrayIconWhenKeyboardisConnected();
private:
std::unique_ptr gsettings_;
const QString gsettingsId_ = "org.ukui.virtualkeyboard";
const QString floatButtonEnabledKey_ = "floatButtonEnabled";
const QString virtualKeyboardScaleFactorKey_ = "virtualKeyboardScaleFactor";
const QString animationEnabledKey_ = "animationEnabled";
const QString trayIconShowKey_ = "trayIconShowPolicy";
const QString preloadViewEnabledKey_ = "preloadViewEnabled";
};
#endif
kylin-virtual-keyboard/src/virtualkeyboardsettings/virtualkeyboardsettings.cpp 0000664 0001750 0001750 00000010161 15160532634 027367 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2023.All rights reserved.
*
* 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 3 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, see .
*/
#include "virtualkeyboardsettings.h"
#include
#include
VirtualKeyboardSettings::VirtualKeyboardSettings() { init(); }
void VirtualKeyboardSettings::init() {
if (!QGSettings::isSchemaInstalled(gsettingsId_.toUtf8())) {
KVKBD_WARN("WARNING : INCORRECT GSETTINGS ID :{}, IS NOT INSTALLED!",
gsettingsId_.toStdString());
return;
}
gsettings_.reset(new QGSettings(gsettingsId_.toUtf8()));
connect(gsettings_.get(), &QGSettings::changed, this,
[this](const QString &key) {
if (!gsettings_->keys().contains(key)) {
return;
}
if (key == floatButtonEnabledKey_) {
emitFloatButtonAvailabilityChanged();
} else if (key == virtualKeyboardScaleFactorKey_) {
emit scaleFactorChanged();
} else if (key == trayIconShowKey_) {
emitTrayIconShowChanged();
} else if (key == animationEnabledKey_) {
emit animationAvailabilityChanged();
}
});
}
void VirtualKeyboardSettings::emitFloatButtonAvailabilityChanged() {
const bool value = gsettings_->get(floatButtonEnabledKey_).toBool();
if (value) {
emit requestFloatButtonEnabled();
} else {
emit requestFloatButtonDisabled();
}
}
void VirtualKeyboardSettings::updateFloatButtonAvailability(const bool value) {
if (gsettings_ == nullptr) {
KVKBD_WARN("WARNING : Gsettings Objetc is NULL !");
return;
}
gsettings_->set(floatButtonEnabledKey_, QVariant(value));
}
bool VirtualKeyboardSettings::isFloatButtonEnabled() const {
if (gsettings_ == nullptr) {
KVKBD_WARN("WARNING : Gsettings Objetc is NULL !");
return false;
}
return gsettings_->get(floatButtonEnabledKey_).toBool();
}
bool VirtualKeyboardSettings::isAnimationEnabled() const {
if (gsettings_ == nullptr) {
KVKBD_WARN("WARNING : Gsettings Objetc is NULL !");
return false;
}
return gsettings_->get(animationEnabledKey_).toBool();
}
bool VirtualKeyboardSettings::isPreloadViewEnabled() const {
if (gsettings_ == nullptr) {
KVKBD_WARN("WARNING : Gsettings Objetc is NULL !");
return false;
}
return gsettings_->get(preloadViewEnabledKey_).toBool();
}
float VirtualKeyboardSettings::calculateVirtualKeyboardScaleFactor() const {
return static_cast(
gsettings_->get(virtualKeyboardScaleFactorKey_).toInt()) /
100;
}
const QString VirtualKeyboardSettings::trayIconShow() const {
if (gsettings_ == nullptr) {
KVKBD_WARN("WARNING : Gsettings Objetc is NULL !");
return "NeverShow";
}
return gsettings_->get(trayIconShowKey_).toString();
}
void VirtualKeyboardSettings::emitTrayIconShowChanged() {
const QString value = gsettings_->get(trayIconShowKey_).toString();
if (value == "NeverShow") {
emit neverShowTrayIcon();
} else if (value == "AlwaysShow") {
emit alwaysShowTrayIcon();
} else if (value == "ShowWhenKeyboardIsConnected") {
emit showTrayIconWhenKeyboardisConnected();
} else {
KVKBD_WARN("WARNING : Gsettings Set trayIconShow Error !");
}
}
VirtualKeyboardSettings &VirtualKeyboardSettings::getInstance() {
static VirtualKeyboardSettings virtualKeyboardSettings;
return virtualKeyboardSettings;
}
kylin-virtual-keyboard/src/ipc/ 0000775 0001750 0001750 00000000000 15160532550 015454 5 ustar feng feng kylin-virtual-keyboard/src/ipc/fcitxvirtualkeyboardserviceproxy.cpp 0000664 0001750 0001750 00000003052 15160532550 025110 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "fcitxvirtualkeyboardserviceproxy.h"
// static
const QString FcitxVirtualKeyboardServiceProxy::serviceName_ =
"org.fcitx.Fcitx5";
// static
const QString FcitxVirtualKeyboardServiceProxy::servicePath_ =
"/virtualkeyboard";
// static
const QString FcitxVirtualKeyboardServiceProxy::serviceInterface_ =
"org.fcitx.Fcitx.VirtualKeyboard1";
FcitxVirtualKeyboardServiceProxy::FcitxVirtualKeyboardServiceProxy() {
virtualKeyboardService.reset(
new QDBusInterface(serviceName_, servicePath_, serviceInterface_,
QDBusConnection::sessionBus()));
}
void FcitxVirtualKeyboardServiceProxy::showVirtualKeyboard() const {
virtualKeyboardService->call("ShowVirtualKeyboard");
}
void FcitxVirtualKeyboardServiceProxy::hideVirtualKeyboard() const {
virtualKeyboardService->call("HideVirtualKeyboard");
}
kylin-virtual-keyboard/src/ipc/requestmerger.h 0000664 0001750 0001750 00000004141 15160532550 020517 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef REQUESTMERGER_H
#define REQUESTMERGER_H
#include
#include
#include
#include
class RequestMerger : public QObject {
Q_OBJECT
public:
using ExecuteCallback = std::function;
using ShouldActivateCallback = std::function;
using ShouldDeactivateCallback = std::function;
public:
explicit RequestMerger(int period);
~RequestMerger() override;
void init(ExecuteCallback activationExecuteCallback,
ExecuteCallback deactivationExecuteCallback,
ShouldActivateCallback shouldAcitvateCallback,
ShouldDeactivateCallback shouldDeactivateCallback);
void activate();
void deactivate();
private slots:
void execute();
private:
class State;
class IdleState;
class ActivationState;
class DeactivationState;
private:
void enterIdleState();
void enterActivationState();
void enterDeactivationState();
void start();
void stop();
void updateCurrentState(std::shared_ptr newState);
private:
// 请求合并的最小周期是10ms
const int LEAST_PERIOD = 10;
int period_ = LEAST_PERIOD;
QTimer timer_;
std::shared_ptr currentState_ = nullptr;
std::shared_ptr idleState_ = nullptr;
std::shared_ptr activationState_ = nullptr;
std::shared_ptr deactivationState_ = nullptr;
};
#endif // REQUESTMERGER_H
kylin-virtual-keyboard/src/ipc/keyboardserviceproxy.h 0000664 0001750 0001750 00000002300 15160532550 022103 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef _KEYBOARDSERVICEPROXY_H_
#define _KEYBOARDSERVICEPROXY_H_
#include
#include
#include
#include
#include "log.h"
class KeyboardServiceProxy : public QDBusAbstractInterface {
Q_OBJECT
public:
explicit KeyboardServiceProxy(QObject *parent = nullptr);
~KeyboardServiceProxy() override = default;
Q_SIGNALS:
void kbdStatusChanged();
public Q_SLOTS:
QDBusPendingReply GetKbdCount();
};
#endif
kylin-virtual-keyboard/src/ipc/requestmerger.cpp 0000664 0001750 0001750 00000011566 15160532550 021063 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "requestmerger.h"
class RequestMerger::State {
public:
virtual void activate() const = 0;
virtual void deactivate() const = 0;
void execute() const {
requestMerger_.enterIdleState();
if (!executeCallback_) {
return;
}
executeCallback_();
}
protected:
State(RequestMerger &requestMerger, ExecuteCallback executeCallback)
: requestMerger_(requestMerger),
executeCallback_(std::move(executeCallback)) {}
virtual ~State() = default;
protected:
RequestMerger &requestMerger_;
private:
ExecuteCallback executeCallback_;
};
class RequestMerger::IdleState : public RequestMerger::State {
public:
IdleState(RequestMerger &requestMerger,
ShouldActivateCallback shouldActivateCallback,
ShouldDeactivateCallback shouldDeactivateCallback)
: State(requestMerger, ExecuteCallback()),
shouldActivateCallback_(std::move(shouldActivateCallback)),
shouldDeactivateCallback_(std::move(shouldDeactivateCallback)) {}
~IdleState() override = default;
void activate() const override {
if (!shouldActivate()) {
return;
}
requestMerger_.enterActivationState();
}
void deactivate() const override {
if (!shouldDeactivate()) {
return;
}
requestMerger_.enterDeactivationState();
}
private:
bool shouldActivate() const {
return shouldActivateCallback_ && shouldActivateCallback_();
}
bool shouldDeactivate() const {
return shouldDeactivateCallback_ && shouldDeactivateCallback_();
}
private:
ShouldActivateCallback shouldActivateCallback_;
ShouldDeactivateCallback shouldDeactivateCallback_;
};
class RequestMerger::ActivationState : public RequestMerger::State {
public:
ActivationState(RequestMerger &requestMerger,
ExecuteCallback executeCallback)
: State(requestMerger, std::move(executeCallback)) {}
~ActivationState() override = default;
void activate() const override {}
void deactivate() const override { requestMerger_.enterIdleState(); }
};
class RequestMerger::DeactivationState : public RequestMerger::State {
public:
DeactivationState(RequestMerger &requestMerger,
ExecuteCallback executeCallback)
: State(requestMerger, std::move(executeCallback)) {}
~DeactivationState() override = default;
void activate() const override { requestMerger_.enterIdleState(); }
void deactivate() const override {}
};
RequestMerger::RequestMerger(int period) {
period_ = std::max(LEAST_PERIOD, period);
timer_.setSingleShot(true);
QObject::connect(&timer_, &QTimer::timeout, this, &RequestMerger::execute);
}
RequestMerger::~RequestMerger() = default;
void RequestMerger::init(ExecuteCallback activationExecuteCallback,
ExecuteCallback deactivationExecuteCallback,
ShouldActivateCallback shouldAcitvateCallback,
ShouldDeactivateCallback shouldDeactivateCallback) {
idleState_ =
std::make_shared(*this, std::move(shouldAcitvateCallback),
std::move(shouldDeactivateCallback));
activationState_ = std::make_shared(
*this, std::move(activationExecuteCallback));
deactivationState_ = std::make_shared(
*this, std::move(deactivationExecuteCallback));
updateCurrentState(idleState_);
}
void RequestMerger::activate() { currentState_->activate(); }
void RequestMerger::deactivate() { currentState_->deactivate(); }
void RequestMerger::start() { timer_.start(period_); }
void RequestMerger::stop() { timer_.stop(); }
void RequestMerger::updateCurrentState(std::shared_ptr newState) {
currentState_ = newState;
}
void RequestMerger::enterIdleState() {
updateCurrentState(idleState_);
stop();
}
void RequestMerger::enterActivationState() {
updateCurrentState(activationState_);
start();
}
void RequestMerger::enterDeactivationState() {
updateCurrentState(deactivationState_);
start();
}
void RequestMerger::execute() { currentState_->execute(); }
kylin-virtual-keyboard/src/ipc/fcitxcontrollerserviceproxy.cpp 0000664 0001750 0001750 00000004314 15160532550 024066 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#include "fcitxcontrollerserviceproxy.h"
const QString g_fcitxControllerServiceName = "org.fcitx.Fcitx5";
const QString g_fcitxControllerServicePath = "/controller";
const char *g_fcitxControllerServiceInterface = "org.fcitx.Fcitx.Controller1";
FcitxControllerServiceProxy::FcitxControllerServiceProxy(QObject *parent)
: QDBusAbstractInterface(g_fcitxControllerServiceName,
g_fcitxControllerServicePath,
g_fcitxControllerServiceInterface,
QDBusConnection::sessionBus(), parent) {}
QDBusPendingReply FcitxControllerServiceProxy::CurrentInputMethod() {
QList argumentList;
return asyncCallWithArgumentList(QStringLiteral("CurrentInputMethod"),
argumentList);
}
QDBusPendingReply
FcitxControllerServiceProxy::FullInputMethodGroupInfo(
const QString &imGroupName) {
QList argumentList;
argumentList << QVariant::fromValue(imGroupName);
return asyncCallWithArgumentList(QStringLiteral("FullInputMethodGroupInfo"),
argumentList);
}
QDBusPendingReply<>
FcitxControllerServiceProxy::SetCurrentIM(const QString &imName) {
QList argumentList;
argumentList << QVariant::fromValue(imName);
return asyncCallWithArgumentList(QStringLiteral("SetCurrentIM"),
argumentList);
}
kylin-virtual-keyboard/src/ipc/dbusservice.cpp 0000664 0001750 0001750 00000006335 15160532550 020505 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "dbusservice.h"
#include "virtualkeyboard/virtualkeyboardmanager.h"
DBusService::DBusService(VirtualKeyboardManager *virtualKeyboardManager)
: virtualKeyboardManager_(virtualKeyboardManager),
virtualKeyboardVisibilityRequestMerger_(
VIRTUAL_KEYBOARD_VISIBILITY_PEROID) {
initRequestMerger();
startService();
}
DBusService::~DBusService() { stopService(); }
void DBusService::initRequestMerger() {
virtualKeyboardVisibilityRequestMerger_.init(
[this]() { virtualKeyboardManager_->showVirtualKeyboard(); },
[this]() { virtualKeyboardManager_->hideVirtualKeyboard(); },
[this]() {
return !virtualKeyboardManager_->isVirtualKeyboardVisible();
},
[this]() {
return virtualKeyboardManager_->isVirtualKeyboardVisible();
});
}
bool DBusService::startService() {
return QDBusConnection::sessionBus().registerService(serviceName_) &&
QDBusConnection::sessionBus().registerObject(
servicePath_, serviceInterface_, this,
QDBusConnection::ExportAllSlots);
}
bool DBusService::stopService() {
QDBusConnection::sessionBus().unregisterObject(servicePath_);
return QDBusConnection::sessionBus().unregisterService(serviceName_);
}
void DBusService::ShowVirtualKeyboard() {
virtualKeyboardVisibilityRequestMerger_.activate();
}
void DBusService::HideVirtualKeyboard() {
virtualKeyboardVisibilityRequestMerger_.deactivate();
}
bool DBusService::IsVirtualKeyboardVisible() {
return virtualKeyboardManager_->isVirtualKeyboardVisible();
}
void DBusService::UpdatePreeditCaret(int preeditCursor) {
virtualKeyboardManager_->updatePreeditCaret(preeditCursor);
}
void DBusService::UpdatePreeditArea(const QString &preeditText) {
virtualKeyboardManager_->updatePreeditArea(preeditText);
}
void DBusService::UpdateCandidateArea(const QStringList &candidateTextList,
bool hasPrev, bool hasNext, int pageIndex,
int globalCursorIndex /* = -1*/) {
virtualKeyboardManager_->updateCandidateArea(
candidateTextList, hasPrev, hasNext, pageIndex, globalCursorIndex);
}
void DBusService::NotifyIMActivated(const QString &uniqueName) {
virtualKeyboardManager_->notifyIMActivated(uniqueName);
}
void DBusService::NotifyIMDeactivated(const QString &uniqueName) {
virtualKeyboardManager_->notifyIMDeactivated(uniqueName);
}
void DBusService::NotifyIMListChanged() {
virtualKeyboardManager_->notifyIMListChanged();
}
kylin-virtual-keyboard/src/ipc/fcitxcontrollerserviceproxy.h 0000664 0001750 0001750 00000002701 15160532550 023531 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef FCITXCONTROLLERSERVICEPROXY_H
#define FCITXCONTROLLERSERVICEPROXY_H
#include
#include
#include
#include "fcitxqtdbustypes.h"
class FcitxControllerServiceProxy : public QDBusAbstractInterface {
Q_OBJECT
public:
explicit FcitxControllerServiceProxy(QObject *parent = nullptr);
~FcitxControllerServiceProxy() override = default;
public:
QDBusPendingReply CurrentInputMethod();
QDBusPendingReply
FullInputMethodGroupInfo(const QString &imGroupName);
QDBusPendingReply<> SetCurrentIM(const QString &imName);
};
#endif // FCITXCONTROLLERSERVICEPROXY_H
kylin-virtual-keyboard/src/ipc/fcitxvirtualkeyboardserviceproxy.h 0000664 0001750 0001750 00000002642 15160532550 024561 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef FCITXVIRTUALKEYBOARDSERVICEPROXY_H
#define FCITXVIRTUALKEYBOARDSERVICEPROXY_H
#include
#include
#include
#include "virtualkeyboardentry/fcitxvirtualkeyboardservice.h"
class FcitxVirtualKeyboardServiceProxy : public FcitxVirtualKeyboardService {
public:
FcitxVirtualKeyboardServiceProxy();
~FcitxVirtualKeyboardServiceProxy() override = default;
void showVirtualKeyboard() const override;
void hideVirtualKeyboard() const override;
private:
std::unique_ptr virtualKeyboardService = nullptr;
static const QString serviceName_;
static const QString servicePath_;
static const QString serviceInterface_;
};
#endif // FCITXVIRTUALKEYBOARDSERVICEPROXY_H
kylin-virtual-keyboard/src/ipc/fcitxqtdbustypes.cpp 0000664 0001750 0001750 00000005016 15160532550 021607 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#include "fcitxqtdbustypes.h"
#include
#define KVKBD_FCITX5_QT_DEFINE_DBUS_TYPE(TYPE) \
qRegisterMetaType(#TYPE); \
qDBusRegisterMetaType(); \
qRegisterMetaType(#TYPE "List"); \
qDBusRegisterMetaType();
void registerKvkbdFcitxQtDBusTypes() {
KVKBD_FCITX5_QT_DEFINE_DBUS_TYPE(FcitxQtFullInputMethodEntry);
}
QDBusArgument &operator<<(QDBusArgument &argument,
const FcitxQtFullInputMethodEntry &arg) {
argument.beginStructure();
argument << arg.uniqueName();
argument << arg.name();
argument << arg.nativeName();
argument << arg.icon();
argument << arg.label();
argument << arg.languageCode();
argument << arg.addon();
argument << arg.configurable();
argument << arg.layout();
argument << arg.properties();
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument,
FcitxQtFullInputMethodEntry &arg) {
QString uniqueName, name, nativeName, icon, label, languageCode, addon,
layout;
bool configurable;
QVariantMap properties;
argument.beginStructure();
argument >> uniqueName >> name >> nativeName >> icon >> label >>
languageCode >> addon >> configurable >> layout >> properties;
argument.endStructure();
arg.setUniqueName(uniqueName);
arg.setName(name);
arg.setNativeName(nativeName);
arg.setIcon(icon);
arg.setLabel(label);
arg.setLanguageCode(languageCode);
arg.setAddon(addon);
arg.setConfigurable(configurable);
arg.setLayout(layout);
arg.setProperties(properties);
return argument;
}
kylin-virtual-keyboard/src/ipc/keyboardserviceproxy.cpp 0000664 0001750 0001750 00000003312 15160532550 022442 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#include "keyboardserviceproxy.h"
const QString g_serviceName = "org.fcitx.Fcitx5.KeyboardStatus";
const QString g_servicePath = "/";
const char *g_serviceInterface = "org.fcitx.Fcitx5.KeyboardStatus";
const QString g_kbdCountMethodName = "getKeyboardNum";
const QString g_kbdStatusSignalName = "keyboardStatusChanged";
KeyboardServiceProxy::KeyboardServiceProxy(QObject *parent)
: QDBusAbstractInterface(g_serviceName, g_servicePath, g_serviceInterface,
QDBusConnection::systemBus(), parent) {
QDBusConnection::systemBus().connect(
g_serviceName, g_servicePath, g_serviceInterface, g_kbdStatusSignalName,
this, SIGNAL(kbdStatusChanged()));
}
QDBusPendingReply KeyboardServiceProxy::GetKbdCount() {
QList argumentList;
KVKBD_INFO("start get Keyboard count via dbus interface:{}, method:{}",
g_serviceInterface, g_kbdCountMethodName.toStdString());
return asyncCallWithArgumentList(g_kbdCountMethodName, argumentList);
}
kylin-virtual-keyboard/src/ipc/ukuimenuserviceproxy.h 0000664 0001750 0001750 00000002001 15160532550 022143 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef UKUIMENUSERVICEPROXY_H
#define UKUIMENUSERVICEPROXY_H
#include
class UkuiMenuServiceProxy : public QDBusAbstractInterface {
public:
explicit UkuiMenuServiceProxy(QObject *parent = nullptr);
~UkuiMenuServiceProxy() override = default;
void toggle();
};
#endif kylin-virtual-keyboard/src/ipc/dbusservice.h 0000664 0001750 0001750 00000004322 15160532550 020144 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef DBUSSERVICE_H
#define DBUSSERVICE_H
#include
#include
#include "requestmerger.h"
#include "virtualkeyboard/virtualkeyboardmanager.h"
class DBusService : public QObject {
Q_OBJECT
public:
explicit DBusService(VirtualKeyboardManager *virtualKeyboardManager);
~DBusService() override;
private:
void initRequestMerger();
bool startService();
bool stopService();
public slots:
void ShowVirtualKeyboard();
void HideVirtualKeyboard();
bool IsVirtualKeyboardVisible();
void UpdatePreeditCaret(int preeditCursor);
void UpdatePreeditArea(const QString &preeditText);
void UpdateCandidateArea(const QStringList &candidateTextList, bool hasPrev,
bool hasNext, int pageIndex,
int globalCursorIndex = -1);
void NotifyIMActivated(const QString &uniqueName);
void NotifyIMDeactivated(const QString &uniqueName);
void NotifyIMListChanged();
private:
VirtualKeyboardManager *virtualKeyboardManager_ = nullptr;
QString serviceName_ = "org.fcitx.Fcitx5.VirtualKeyboard";
QString servicePath_ = "/org/fcitx/virtualkeyboard/impanel";
QString serviceInterface_ = "org.fcitx.Fcitx5.VirtualKeyboard1";
// 在300ms之内的显示和隐藏虚拟键盘的请求将会被合并处理,
// 避免虚拟键盘不必要的显示和隐藏及其相应的闪烁效果
const int VIRTUAL_KEYBOARD_VISIBILITY_PEROID = 300;
RequestMerger virtualKeyboardVisibilityRequestMerger_;
};
#endif // DBUSSERVICE_H
kylin-virtual-keyboard/src/ipc/ukuimenuserviceproxy.cpp 0000664 0001750 0001750 00000002474 15160532550 022514 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#include "ukuimenuserviceproxy.h"
const QString g_ukuiMenuServiceName = "org.ukui.menu";
const QString g_ukuiMenuServicePath = "/org/ukui/menu";
const char *g_ukuiMenuServiceInterface = "org.ukui.menu";
UkuiMenuServiceProxy::UkuiMenuServiceProxy(QObject *parent)
: QDBusAbstractInterface(g_ukuiMenuServiceName, g_ukuiMenuServicePath,
g_ukuiMenuServiceInterface,
QDBusConnection::sessionBus(), parent) {}
void UkuiMenuServiceProxy::toggle() {
QList argumentList;
argumentList << "";
asyncCallWithArgumentList("active", argumentList);
} kylin-virtual-keyboard/src/ipc/fcitxqtdbustypes.h 0000664 0001750 0001750 00000010362 15160532550 021254 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef FCITXQTDBUSTYPES_H
#define FCITXQTDBUSTYPES_H
#include
#include
#include
#include
void registerKvkbdFcitxQtDBusTypes();
#define KVKBD_FCITX5_QT_BEGIN_DECLARE_DBUS_TYPE(TYPE) \
class TYPE { \
Q_GADGET
#define KVKBD_FCITX5_QT_DECLARE_PROPERTY(TYPE, GETTER, SETTER) \
Q_PROPERTY(TYPE GETTER READ GETTER WRITE SETTER)
#define KVKBD_FCITX5_QT_DECLARE_FIELD(TYPE, GETTER, SETTER) \
public: \
std::conditional_t::value, const TYPE &, TYPE> \
GETTER() const { \
return GETTER##_; \
} \
void SETTER( \
std::conditional_t::value, const TYPE &, TYPE> \
value) { \
GETTER##_ = value; \
} \
\
private: \
TYPE GETTER##_ = TYPE();
#define KVKBD_FCITX5_QT_END_DECLARE_DBUS_TYPE(TYPE) \
} \
; \
typedef QList TYPE##List; \
QDBusArgument &operator<<(QDBusArgument &argument, const TYPE &value); \
const QDBusArgument &operator>>(const QDBusArgument &argument, TYPE &value);
KVKBD_FCITX5_QT_BEGIN_DECLARE_DBUS_TYPE(FcitxQtFullInputMethodEntry);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, uniqueName, setUniqueName);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, name, setName);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, nativeName, setNativeName);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, icon, setIcon);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, label, setLabel);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, languageCode, setLanguageCode);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, addon, setAddon);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(bool, configurable, setConfigurable);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QString, layout, setLayout);
KVKBD_FCITX5_QT_DECLARE_PROPERTY(QVariantMap, properties, setProperties);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, uniqueName, setUniqueName);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, name, setName);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, nativeName, setNativeName);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, icon, setIcon);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, label, setLabel);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, languageCode, setLanguageCode);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, addon, setAddon);
KVKBD_FCITX5_QT_DECLARE_FIELD(bool, configurable, setConfigurable);
KVKBD_FCITX5_QT_DECLARE_FIELD(QString, layout, setLayout);
KVKBD_FCITX5_QT_DECLARE_FIELD(QVariantMap, properties, setProperties);
KVKBD_FCITX5_QT_END_DECLARE_DBUS_TYPE(FcitxQtFullInputMethodEntry);
Q_DECLARE_METATYPE(FcitxQtFullInputMethodEntry)
Q_DECLARE_METATYPE(FcitxQtFullInputMethodEntryList)
#endif // FCITXQTDBUSTYPES_H
kylin-virtual-keyboard/src/CMakeLists.txt 0000664 0001750 0001750 00000006741 15160532634 017454 0 ustar feng feng include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/third-party)
set(HEADERS
animation/animationfactory.h
animation/animator.h
animation/disabledanimator.h
animation/enabledanimator.h
animation/expansionanimationfactory.h
animation/floatanimationfactory.h
appinputareamanager.h
geometrymanager/expansiongeometrymanager.h
geometrymanager/floatgeometrymanager.h
geometrymanager/geometrymanager.h
ipc/dbusservice.h
ipc/fcitxvirtualkeyboardserviceproxy.h
ipc/requestmerger.h
ipc/keyboardserviceproxy.h
ipc/ukuimenuserviceproxy.h
ipc/fcitxqtdbustypes.h
ipc/fcitxcontrollerserviceproxy.h
localsettings/localsettings.h
localsettings/viewlocalsettings.h
screenmanager.h
virtualkeyboard/placementmodemanager.h
virtualkeyboard/virtualkeyboardmanager.h
virtualkeyboard/virtualkeyboardmodel.h
virtualkeyboard/virtualkeyboardstrategy.h
virtualkeyboard/virtualkeyboardview.h
virtualkeyboardentry/fcitxvirtualkeyboardservice.h
virtualkeyboardentry/floatbutton.h
virtualkeyboardentry/floatbuttonmanager.h
virtualkeyboardentry/floatbuttonstrategy.h
virtualkeyboardentry/virtualkeyboardentrymanager.h
virtualkeyboardentry/virtualkeyboardtrayicon.h
virtualkeyboardentry/trayiconstrategy.h
virtualkeyboardsettings/virtualkeyboardsettings.h
log.h
messagehandler.h
commandlinehandler.h
errorhandler.h
)
set(SOURCES
animation/animationfactory.cpp
animation/disabledanimator.cpp
animation/enabledanimator.cpp
animation/expansionanimationfactory.cpp
animation/floatanimationfactory.cpp
appinputareamanager.cpp
geometrymanager/expansiongeometrymanager.cpp
geometrymanager/floatgeometrymanager.cpp
geometrymanager/geometrymanager.cpp
ipc/dbusservice.cpp
ipc/fcitxvirtualkeyboardserviceproxy.cpp
ipc/requestmerger.cpp
ipc/keyboardserviceproxy.cpp
ipc/ukuimenuserviceproxy.cpp
ipc/fcitxqtdbustypes.cpp
ipc/fcitxcontrollerserviceproxy.cpp
localsettings/viewlocalsettings.cpp
main.cpp
screenmanager.cpp
virtualkeyboard/placementmodemanager.cpp
virtualkeyboard/virtualkeyboardmanager.cpp
virtualkeyboard/virtualkeyboardmodel.cpp
virtualkeyboard/virtualkeyboardview.cpp
virtualkeyboard/virtualkeyboardviewstate.cpp
virtualkeyboardentry/floatbutton.cpp
virtualkeyboardentry/floatbuttonmanager.cpp
virtualkeyboardentry/virtualkeyboardentrymanager.cpp
virtualkeyboardentry/virtualkeyboardtrayicon.cpp
virtualkeyboardsettings/virtualkeyboardsettings.cpp
log.cpp
messagehandler.cpp
commandlinehandler.cpp
errorhandler.cpp
)
add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES} ${RESOURCES} ${TRANSLATIONS})
target_link_libraries(${PROJECT_NAME}
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Concurrent
Qt${QT_VERSION_MAJOR}::DBus
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::QuickControls2
KF${QT_VERSION_MAJOR}::WindowSystem
Fcitx5::Core
${GSettings_QT_LIBRARIES}
qtsingleapplication
spdlog::spdlog
)
if (QT_VERSION_MAJOR EQUAL 6)
target_link_libraries(${PROJECT_NAME} Qt${QT_VERSION_MAJOR}::Core5Compat)
endif()
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
kylin-virtual-keyboard/src/main.cpp 0000664 0001750 0001750 00000005355 15160532634 016344 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include
#include
#include
#include
#include "commandlinehandler.h"
#include "errorhandler.h"
#include "ipc/dbusservice.h"
#include "ipc/fcitxvirtualkeyboardserviceproxy.h"
#include "log.h"
#include "messagehandler.h"
#include "qtsingleapplication/src/QtSingleApplication"
#include "virtualkeyboard/virtualkeyboardmanager.h"
#include "virtualkeyboardentry/virtualkeyboardentrymanager.h"
const QString APP_ID = "kylin-virtual-keyboard";
const QString APP_VERSION = "4.20.1.0";
int main(int argc, char *argv[]) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QtSingleApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QtSingleApplication app(APP_ID, argc, argv);
QtSingleApplication::setApplicationName(APP_ID);
QtSingleApplication::setApplicationVersion(APP_VERSION);
// 命令行处理器
CommandLineHandler commandHandler;
commandHandler.process(app);
// 检查是否应该继续执行(单实例和命令行参数检查)
if (!commandHandler.shouldContinueExecution(app)) {
return 0;
}
// 异常处理器,堆栈信息记录到:~/.log/kylin-virtual-keyboard-error.log
ErrorHandler::init();
SpdlogProxy::getInstance();
KVKBD_INFO("{},---START---", APP_ID.toStdString());
// 消息处理器,绑定接收二次运行时程序发送的消息
MessageHandler messageHandler;
commandHandler.bindMessageHandler(app, messageHandler);
QTranslator translator;
if (translator.load(QLocale::system(), "translation", "_",
":/translations")) {
app.installTranslator(&translator);
}
FcitxVirtualKeyboardServiceProxy virtualKeyboardService;
VirtualKeyboardManager virtualKeyboardManager([&virtualKeyboardService]() {
virtualKeyboardService.hideVirtualKeyboard();
});
VirtualKeyboardEntryManager entryManager(virtualKeyboardManager,
virtualKeyboardService);
DBusService dbusService(&virtualKeyboardManager);
return app.exec();
}
kylin-virtual-keyboard/src/commandlinehandler.h 0000664 0001750 0001750 00000002604 15160532550 020700 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef COMMANDLINEHANDLER_H
#define COMMANDLINEHANDLER_H
#include
#include
#include
#include "qtsingleapplication/src/QtSingleApplication"
class MessageHandler;
class CommandLineHandler : public QCommandLineParser {
public:
CommandLineHandler();
// 检查是否应该继续执行主程序(处理单例检查和启动命令)
bool shouldContinueExecution(QtSingleApplication &app) const;
// 绑定消息接收处理
void bindMessageHandler(QtSingleApplication &app,
MessageHandler &messageHandler);
private:
QCommandLineOption m_loglevelOption;
};
#endif // COMMANDLINEHANDLER_H
kylin-virtual-keyboard/src/appinputareamanager.h 0000664 0001750 0001750 00000002736 15160532634 021111 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef APPINPUTAREAMANAGER_H
#define APPINPUTAREAMANAGER_H
#include
#include
#include
#include
class AppInputAreaManager : public QObject {
Q_OBJECT
public:
explicit AppInputAreaManager(QObject *parent = nullptr);
~AppInputAreaManager() = default;
// TODO(linyuxuan): 使用kdk重新实现该函数
void raiseInputArea(const QRect &virtualKeyboardRect);
void fallInputArea();
private:
void connectSignal();
private:
QRect virtualKeyboardRect_;
QWidget dummyWidget_;
QTimer oneshotTimer_;
// 经过指定时间之后顶起应用程序,避免桌面在虚拟键盘显示之前可见
// 根据使用经验,选定200毫秒作为经验值
static const int SHOW_DELAY_TIME = 200;
};
#endif // APPINPUTAREAMANAGER_H
kylin-virtual-keyboard/src/errorhandler.h 0000664 0001750 0001750 00000003233 15160532550 017542 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef ERRORHANDLER_H
#define ERRORHANDLER_H
#include
#ifndef SIGUNUSED
#define SIGUNUSED 29
#endif
class ErrorHandler {
public:
ErrorHandler() = delete;
~ErrorHandler() = delete;
ErrorHandler(const ErrorHandler &) = delete;
ErrorHandler &operator=(const ErrorHandler &) = delete;
static void init();
static void setCrashLogPath(const QString &path);
private:
static void createLogFile();
static void registerSignalHandler();
static void signalHandler(int sig);
static void writeString(int fd, const char *str);
static void writeBuffer(int fd, const char *buffer, int len);
static void writeUInt64(int fd, unsigned long long number);
static ssize_t writeAll(int fd, const void *buf, size_t count);
static const char *getSignalName(int sig);
static void generateBacktrace(int fd);
private:
static QString m_crashLogPath;
static bool m_logDirWritable;
};
#endif // ERRORHANDLER_H
kylin-virtual-keyboard/src/appinputareamanager.cpp 0000664 0001750 0001750 00000005712 15160532634 021441 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "appinputareamanager.h"
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include
#include
#include
#else
#include
#endif
AppInputAreaManager::AppInputAreaManager(QObject *parent)
: QObject(parent), dummyWidget_(nullptr), oneshotTimer_(nullptr) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
KX11Extras::setType(dummyWidget_.winId(), NET::Dock);
#else
KWindowSystem::setType(dummyWidget_.winId(), NET::Dock);
#endif
dummyWidget_.setWindowFlags(Qt::FramelessWindowHint);
dummyWidget_.setAttribute(Qt::WA_TranslucentBackground);
oneshotTimer_.setSingleShot(true);
connectSignal();
}
void AppInputAreaManager::connectSignal() {
QObject::connect(&oneshotTimer_, &QTimer::timeout, this, [this]() {
dummyWidget_.setGeometry(virtualKeyboardRect_);
dummyWidget_.show();
// 使用KWin接口调整工作区域,仅在X11下有效
// 该接口对全屏应用无效
// 该接口需在winId对象显示前后调用,否则可能不生效
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
KX11Extras::setExtendedStrut(dummyWidget_.winId(), 0, 0, 0, 0, 0, 0, 0,
0, 0, virtualKeyboardRect_.height(),
virtualKeyboardRect_.x(),
virtualKeyboardRect_.width() - 1);
#else
KWindowSystem::setExtendedStrut(dummyWidget_.winId(), 0, 0, 0, 0, 0, 0,
0, 0, 0, virtualKeyboardRect_.height(),
virtualKeyboardRect_.x(),
virtualKeyboardRect_.width() - 1);
#endif
});
}
void AppInputAreaManager::raiseInputArea(const QRect &virtualKeyboardRect) {
virtualKeyboardRect_ = virtualKeyboardRect;
oneshotTimer_.start(SHOW_DELAY_TIME);
}
void AppInputAreaManager::fallInputArea() {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
KX11Extras::setExtendedStrut(dummyWidget_.winId(), 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0);
#else
KWindowSystem::setExtendedStrut(dummyWidget_.winId(), 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0);
#endif
dummyWidget_.hide();
oneshotTimer_.stop();
}
kylin-virtual-keyboard/src/commandlinehandler.cpp 0000664 0001750 0001750 00000004042 15160532550 021231 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "commandlinehandler.h"
#include
#include "log.h"
#include "messagehandler.h"
CommandLineHandler::CommandLineHandler()
: m_loglevelOption(QStringList() << "loglevel",
"Set the log level \n"
"(available: debug, info, warn, error).\n"
"e.g. --loglevel=debug",
"loglevel") {
addHelpOption();
addVersionOption();
addOption(m_loglevelOption);
}
bool CommandLineHandler::shouldContinueExecution(
QtSingleApplication &app) const {
// 单实例判断
if (!app.isRunning()) {
return true;
}
if (isSet(m_loglevelOption)) {
QString level = value(m_loglevelOption);
QString command = QString("loglevel %1").arg(level);
app.sendMessage(command);
}
std::cout << "kylin-virtual-keyboard is already running!" << std::endl;
return false;
}
void CommandLineHandler::bindMessageHandler(QtSingleApplication &app,
MessageHandler &messageHandler) {
QObject::connect(
&app, &QtSingleApplication::messageReceived,
[&](const QString &message) {
messageHandler.processMessage(message, [&](const QString &result) {
KVKBD_INFO("Command result: {}", result.toStdString());
});
});
}
kylin-virtual-keyboard/src/messagehandler.h 0000664 0001750 0001750 00000002721 15160532550 020036 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef MESSAGEHANDLER_H
#define MESSAGEHANDLER_H
#include
#include
#include
#include
#include
#include "log.h"
class MessageHandler : public QObject {
public:
using ResultCallback = std::function;
explicit MessageHandler(QObject *parent = nullptr);
void registerCommand(const QString &command,
std::function handler);
void processMessage(const QString &rawMessage,
ResultCallback callback = nullptr);
private:
QString handleLogLevel(const QStringList &args) const;
private:
QMap> commandHandlers;
};
#endif // MESSAGEHANDLER_H
kylin-virtual-keyboard/src/log.h 0000664 0001750 0001750 00000011173 15160532550 015636 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef LOG_H
#define LOG_H
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
#include
#include
#include
#include
#include
#include
#include
#define KVKBD_TRACE(...) \
do { \
if (!SpdlogProxy::isCleaned() && \
spdlog::default_logger_raw() != nullptr) { \
SPDLOG_LOGGER_TRACE(spdlog::default_logger_raw(), __VA_ARGS__); \
} \
} while (0)
#define KVKBD_DEBUG(...) \
do { \
if (!SpdlogProxy::isCleaned() && \
spdlog::default_logger_raw() != nullptr) { \
SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__); \
} \
} while (0)
#define KVKBD_INFO(...) \
do { \
if (!SpdlogProxy::isCleaned() && \
spdlog::default_logger_raw() != nullptr) { \
SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__); \
} \
} while (0)
#define KVKBD_WARN(...) \
do { \
if (!SpdlogProxy::isCleaned() && \
spdlog::default_logger_raw() != nullptr) { \
SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__); \
} \
} while (0)
#define KVKBD_ERROR(...) \
do { \
if (!SpdlogProxy::isCleaned() && \
spdlog::default_logger_raw() != nullptr) { \
SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__); \
} \
} while (0)
class SpdlogProxy {
public:
static SpdlogProxy &getInstance() {
static SpdlogProxy instance;
return instance;
}
SpdlogProxy(const SpdlogProxy &) = delete;
SpdlogProxy &operator=(const SpdlogProxy &) = delete;
class LogOption {
public:
long long fileSize = 1024 * 1024 * 10;
int fileCounts = 1;
bool rotateEnable = false;
};
static bool isCleaned();
static void messageHandler(QtMsgType type,
const QMessageLogContext &context,
const QString &msg);
Q_INVOKABLE static void debug(const QString &msg);
Q_INVOKABLE static void info(const QString &msg);
Q_INVOKABLE static void warn(const QString &msg);
Q_INVOKABLE static void error(const QString &msg);
private:
SpdlogProxy() { init(SpdlogProxy::LogOption()); }
~SpdlogProxy() { cleanUp(); }
static void init(const LogOption &option);
static void cleanUp();
static QString getGsettingsLogLevel();
static spdlog::level::level_enum transToSpdLogLevel(const QString &level);
static QString getWritableLogFilePath();
private:
static std::shared_ptr m_logger;
static std::atomic m_cleaned;
};
#endif // SPDLOGPROXY_H
kylin-virtual-keyboard/src/localsettings/ 0000775 0001750 0001750 00000000000 15160532550 017554 5 ustar feng feng kylin-virtual-keyboard/src/localsettings/localsettings.h 0000664 0001750 0001750 00000002234 15160532550 022601 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef LOCALSETTINGS_H
#define LOCALSETTINGS_H
#include
class LocalSettings {
public:
virtual ~LocalSettings() = default;
virtual QVariant getValue(const QString &group, const QString &key,
const QVariant &defaultValue = QVariant()) = 0;
virtual void setValue(const QString &group, const QString &key,
const QVariant &value) = 0;
protected:
LocalSettings() = default;
};
#endif // LOCALSETTINGS_H
kylin-virtual-keyboard/src/localsettings/viewlocalsettings.h 0000664 0001750 0001750 00000003312 15160532550 023472 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef VIEWLOCALSETTINGS_H
#define VIEWLOCALSETTINGS_H
#include
#include
#include "localsettings.h"
#include "log.h"
class ViewLocalSettings : public LocalSettings {
public:
using SettingMap = QMap;
using GroupSettingMap = QMap;
public:
ViewLocalSettings(const QString &organization, const QString &application);
~ViewLocalSettings() override;
QVariant getValue(const QString &group, const QString &key);
QVariant getValue(const QString &group, const QString &key,
const QVariant &defaultValue) override;
void setValue(const QString &group, const QString &key,
const QVariant &value) override;
void remove(const QString &key);
bool contains(const QString &key) const;
private:
void saveSettingsAsync();
private:
const QString organization_;
const QString application_;
GroupSettingMap groupSettingMap_;
QFutureWatcher futureWatcher_;
};
#endif // VIEWLOCALSETTINGS_H
kylin-virtual-keyboard/src/localsettings/viewlocalsettings.cpp 0000664 0001750 0001750 00000007422 15160532550 024033 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "viewlocalsettings.h"
#include
#include
namespace {
void updateSettings(QSettings &settings,
const ViewLocalSettings::SettingMap &settingMap) {
for (auto settingIter = settingMap.constBegin();
settingIter != settingMap.constEnd(); settingIter++) {
settings.setValue(settingIter.key(), settingIter.value());
}
}
void saveSettings(const QString &organization, const QString &application,
const ViewLocalSettings::GroupSettingMap &groupSettingMap) {
QSettings settings(organization, application);
for (auto groupIter = groupSettingMap.constBegin();
groupIter != groupSettingMap.constEnd(); groupIter++) {
settings.beginGroup(groupIter.key());
updateSettings(settings, groupIter.value());
settings.endGroup();
}
settings.sync();
}
} // namespace
ViewLocalSettings::ViewLocalSettings(const QString &organization,
const QString &application)
: organization_(organization), application_(application) {
QObject::connect(&futureWatcher_, &QFutureWatcher::finished,
[this]() {
if (groupSettingMap_.isEmpty()) {
return;
}
saveSettingsAsync();
});
KVKBD_DEBUG("organization_:{},application_:{}", organization_.toStdString(),
application_.toStdString());
}
ViewLocalSettings::~ViewLocalSettings() = default;
QVariant ViewLocalSettings::getValue(const QString &group, const QString &key) {
QSettings settings(organization_, application_);
settings.beginGroup(group);
auto value = settings.value(key);
settings.endGroup();
return value;
}
QVariant
ViewLocalSettings::getValue(const QString &group, const QString &key,
const QVariant &defaultValue /*= QVariant()*/) {
QSettings settings(organization_, application_);
settings.beginGroup(group);
auto value = settings.value(key, defaultValue);
settings.endGroup();
return value;
}
void ViewLocalSettings::setValue(const QString &group, const QString &key,
const QVariant &value) {
auto &settingMap = groupSettingMap_[group];
settingMap.insert(key, value);
if (futureWatcher_.isFinished()) {
saveSettingsAsync();
}
}
void ViewLocalSettings::saveSettingsAsync() {
auto oneshotGroupSettingMap(std::move(groupSettingMap_));
auto organization = organization_;
auto application = application_;
futureWatcher_.setFuture(
QtConcurrent::run([oneshotGroupSettingMap, organization, application]() {
saveSettings(organization, application, oneshotGroupSettingMap);
}));
}
void ViewLocalSettings::remove(const QString &key) {
QSettings settings(organization_, application_);
settings.remove(key);
}
bool ViewLocalSettings::contains(const QString &key) const {
QSettings settings(organization_, application_);
return settings.contains(key);
}
kylin-virtual-keyboard/src/virtualkeyboardentry/ 0000775 0001750 0001750 00000000000 15160532634 021175 5 ustar feng feng kylin-virtual-keyboard/src/virtualkeyboardentry/floatbutton.cpp 0000664 0001750 0001750 00000010476 15160532634 024252 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "virtualkeyboardentry/floatbutton.h"
#include
#include
#include
FloatButton::FloatButton(MouseClickedCallback mouseClickedCallback)
: mouseClickedCallback_(std::move(mouseClickedCallback)) {
// 主题框架默认禁用了move消息,因此,QPushButton需要禁用主题框架
setProperty("useStyleWindowManager", QVariant(false));
initStyle();
}
void FloatButton::move(int x, int y) { QPushButton::move(x, y); }
void FloatButton::resize(int width, int height) {
setFixedSize(width, height);
setIconSize(size());
QPushButton::resize(width, height);
}
void FloatButton::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
startX_ = event->pos().x();
startY_ = event->pos().y();
startClickTimer();
}
QPushButton::mousePressEvent(event);
}
bool FloatButton::shouldPerformMouseClick() const {
return !isFloatButtonMoved() && clickTimer_->isActive();
}
void FloatButton::processMouseReleaseEvent() {
emit mouseReleased();
manhattonLength = 0;
startX_ = -1;
startY_ = -1;
}
void FloatButton::processMouseClickEvent() {
if (!mouseClickedCallback_) {
return;
}
mouseClickedCallback_();
}
void FloatButton::mouseReleaseEvent(QMouseEvent *event) {
QPushButton::mouseReleaseEvent(event);
if (event->button() != Qt::LeftButton) {
return;
}
bool couldPerformMouseClick = shouldPerformMouseClick();
stopClickTimer();
if (couldPerformMouseClick) {
processMouseClickEvent();
return;
}
if (isFloatButtonMoved()) {
processMouseReleaseEvent();
}
}
void FloatButton::updateManhattonLength(QMouseEvent *event) {
int offsetX = event->pos().x() - startX_;
int offsetY = event->pos().y() - startY_;
manhattonLength += std::abs(offsetX) + std::abs(offsetY);
}
bool FloatButton::isFloatButtonMoved() const {
return manhattonLength > manhattonLengthThreshold;
}
void FloatButton::processMouseMoveEvent(QMouseEvent *event) {
if (!isFloatButtonMoved()) {
updateManhattonLength(event);
} else {
emit mouseMoved(event->pos().x() - startX_, event->pos().y() - startY_);
}
}
void FloatButton::mouseMoveEvent(QMouseEvent *event) {
if (event->buttons() & Qt::LeftButton) {
processMouseMoveEvent(event);
}
QPushButton::mouseMoveEvent(event);
}
void FloatButton::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(QBrush(Qt::white));
painter.setPen(Qt::transparent);
QRect rect = this->rect();
rect.setWidth(rect.width());
rect.setHeight(rect.height());
painter.drawEllipse(rect);
QPushButton::paintEvent(event);
}
void FloatButton::initStyle() {
setWindowTitle("kylin-virtual-keyboard-float-button");
setAttribute(Qt::WA_TranslucentBackground);
setStyleSheet("QPushButton{border-image: "
"url(:/floatbutton/img/floatbuttondefault.svg);}"
"QPushButton:hover{border-image: "
"url(:/floatbutton/img/floatbuttonhovered.svg);}"
"QPushButton:pressed{border-image: "
"url(:/floatbutton/img/floatbuttonpressed.svg);}");
setAttribute(Qt::WA_AlwaysShowToolTips, true);
setToolTip(tr("Click to show virtual keyboard"));
}
void FloatButton::startClickTimer() {
clickTimer_.reset(new QTimer());
clickTimer_->setSingleShot(true);
clickTimer_->start(clickTimeThreshold_);
}
void FloatButton::stopClickTimer() {
if (clickTimer_ == nullptr) {
clickTimer_.reset();
}
}
kylin-virtual-keyboard/src/virtualkeyboardentry/virtualkeyboardtrayicon.h 0000664 0001750 0001750 00000003671 15160532550 026332 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef VIRTUALKEYBOARDTRAYICON_H
#define VIRTUALKEYBOARDTRAYICON_H
#include
#include
#include
#include
#include "virtualkeyboard/virtualkeyboardmanager.h"
#include "virtualkeyboardentry/fcitxvirtualkeyboardservice.h"
/**
* Used to manage the entrance section of the Kylin Virtual Keyboard tray icon.
* 1. click to show/hide kylin virtual keyboard.
* 2. register tray icon.
*/
class VirtualKeyboardTrayIcon : public QObject {
Q_OBJECT
public:
VirtualKeyboardTrayIcon(
VirtualKeyboardManager &virtualKeyboardManager,
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService);
~VirtualKeyboardTrayIcon() override = default;
void setContextMenu(QMenu *contextMenu);
void hideContextMenu();
void initTrayIcon();
void destroyTrayIcon();
bool isInit() const;
void changeTrayIconVisibility(bool enable = false);
private:
void toggleVirtualKeyboard();
private slots:
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
private:
std::unique_ptr trayIcon_ = nullptr;
VirtualKeyboardManager &virtualKeyboardManager_;
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService_;
};
#endif // VIRTUALKEYBOARDTRAYICON_H
kylin-virtual-keyboard/src/virtualkeyboardentry/virtualkeyboardentrymanager.h 0000664 0001750 0001750 00000006253 15160532634 027200 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef VIRTUALKEYBOARDENTRYMANAGER_H
#define VIRTUALKEYBOARDENTRYMANAGER_H
#include
#include
#include
#include
#include "ipc/fcitxvirtualkeyboardserviceproxy.h"
#include "ipc/keyboardserviceproxy.h"
#include "localsettings/viewlocalsettings.h"
#include "trayiconstrategy.h"
#include "virtualkeyboard/virtualkeyboardmanager.h"
#include "virtualkeyboardentry/floatbuttonmanager.h"
#include "virtualkeyboardentry/virtualkeyboardtrayicon.h"
/**
* Used to manage the entrance section of the Kylin Virtual Keyboard.
* 1. the entry of tray icon.
* 2. the entry of float button.
*/
class VirtualKeyboardEntryManager : public QObject {
Q_OBJECT
public:
VirtualKeyboardEntryManager(
VirtualKeyboardManager &virtualKeyboardManager,
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService);
~VirtualKeyboardEntryManager() override;
private:
using ActionTriggeredCallback = std::function;
private:
void connectSignals();
void moveValueFromLocalSettings();
void initFloatButtonContextMenuAndAction();
void updateFloatButtonContextMenuAction(const QString &icon,
const QString &text,
ActionTriggeredCallback callback);
void initTrayIconStrategy();
void toggleVirtualKeyboard();
void updateStrategy(std::shared_ptr newStrategy);
void updateTrayExistence();
void updateTrayVisibility();
int getKeyboardCount(const bool &sync);
private:
VirtualKeyboardManager &virtualKeyboardManager_;
ViewLocalSettings floatButtonSettings_{"kylinsoft", "kylin float button"};
std::unique_ptr floatButtonManager_ = nullptr;
std::unique_ptr trayIconEntry_ = nullptr;
std::unique_ptr floatButtonContextMenu_ = nullptr;
std::unique_ptr floatButtonContextMenuAction_ = nullptr;
ActionTriggeredCallback actionTriggeredCallback_;
// 三种策略实现托盘图标可用性和可见性
std::shared_ptr alwaysShowStrategy_ = nullptr;
std::shared_ptr neverShowStrategy_ = nullptr;
std::shared_ptr keyboardStatusStrategy_ = nullptr;
// 当前策略
std::shared_ptr currenTrayIconStrategy_ = nullptr;
// 键盘服务代理
std::unique_ptr keyboardServiceProxy_ = nullptr;
};
#endif // VIRTUALKEYBOARDENTRYMANAGER_H
kylin-virtual-keyboard/src/virtualkeyboardentry/virtualkeyboardtrayicon.cpp 0000664 0001750 0001750 00000005372 15160532634 026670 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "virtualkeyboardentry/virtualkeyboardtrayicon.h"
#include
VirtualKeyboardTrayIcon::VirtualKeyboardTrayIcon(
VirtualKeyboardManager &virtualKeyboardManager,
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService)
: virtualKeyboardManager_(virtualKeyboardManager),
fcitxVirtualKeyboardService_(fcitxVirtualKeyboardService) {}
void VirtualKeyboardTrayIcon::setContextMenu(QMenu *contextMenu) {
if (trayIcon_ == nullptr) {
KVKBD_WARN("trayIcon_ is null!");
return;
}
trayIcon_->setContextMenu(contextMenu);
}
void VirtualKeyboardTrayIcon::hideContextMenu() {
if (trayIcon_ == nullptr) {
KVKBD_WARN("trayIcon_ is null!");
return;
}
trayIcon_->contextMenu()->hide();
}
void VirtualKeyboardTrayIcon::toggleVirtualKeyboard() {
if (virtualKeyboardManager_.isVirtualKeyboardVisible()) {
fcitxVirtualKeyboardService_.hideVirtualKeyboard();
} else {
fcitxVirtualKeyboardService_.showVirtualKeyboard();
}
}
void VirtualKeyboardTrayIcon::onTrayIconActivated(
QSystemTrayIcon::ActivationReason reason) {
switch (reason) {
case QSystemTrayIcon::Trigger: {
toggleVirtualKeyboard();
break;
};
default:
break;
}
}
void VirtualKeyboardTrayIcon::initTrayIcon() {
trayIcon_.reset(new QSystemTrayIcon(this));
trayIcon_->setIcon(QIcon::fromTheme("ukui-virtual-keyboard-symbolic"));
trayIcon_->setToolTip(tr("kylin-virtual-keyboard"));
connect(trayIcon_.get(),
SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this,
SLOT(onTrayIconActivated(QSystemTrayIcon::ActivationReason)));
trayIcon_->setVisible(true);
}
void VirtualKeyboardTrayIcon::destroyTrayIcon() {
if (trayIcon_ == nullptr) {
return;
}
trayIcon_.reset();
}
bool VirtualKeyboardTrayIcon::isInit() const { return trayIcon_ != nullptr; }
void VirtualKeyboardTrayIcon::changeTrayIconVisibility(bool enable) {
if (trayIcon_ == nullptr) {
return;
}
trayIcon_->setVisible(enable);
}
kylin-virtual-keyboard/src/virtualkeyboardentry/floatbuttonstrategy.h 0000664 0001750 0001750 00000003612 15160532634 025474 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef FLOATBUTTONSTRATEGY_H
#define FLOATBUTTONSTRATEGY_H
#include "geometrymanager/floatgeometrymanager.h"
#include "screenmanager.h"
class FloatButtonStrategy : public FloatGeometryManager::Strategy {
public:
FloatButtonStrategy() = default;
~FloatButtonStrategy() override = default;
int getDefaultRightMargin() const override {
return getUnitWidth() * defaultRightMarginRatio_;
}
int getDefaultBottomMargin() const override {
return getUnitHeight() * defaultBottomMarginRatio_;
}
private:
int getUnitWidth() const override {
const auto viewPortSize = ScreenManager::getPrimaryScreenSize();
return std::max(viewPortSize.width(), viewPortSize.height());
}
int getUnitHeight() const override {
const auto viewPortSize = ScreenManager::getPrimaryScreenSize();
return std::max(viewPortSize.width(), viewPortSize.height());
}
float getViewWidthRatio() const override { return 56.0 / 1620.0; }
float getViewHeightRatio() const override { return 56.0 / 1620.0; }
private:
static constexpr float defaultBottomMarginRatio_ = 0.03f;
static constexpr float defaultRightMarginRatio_ = 0.02f;
};
#endif // FLOATBUTTONSTRATEGY_H
kylin-virtual-keyboard/src/virtualkeyboardentry/floatbuttonmanager.h 0000664 0001750 0001750 00000004714 15160532634 025250 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef FLOATBUTTONMANAGER_H
#define FLOATBUTTONMANAGER_H
#include
#include
#include
#include
#include "localsettings/localsettings.h"
#include "virtualkeyboard/virtualkeyboardmanager.h"
#include "virtualkeyboardentry/fcitxvirtualkeyboardservice.h"
#include "virtualkeyboardentry/floatbutton.h"
/**
* Used to manage the entrance section of the Kylin Virtual Keyboard float
* button.
*
* 1. click to show/hide kylin virtual keyboard.
* 2. show float button.
*/
class FloatButtonManager : public QObject {
Q_OBJECT
public:
FloatButtonManager(
const VirtualKeyboardManager &virtualKeyboardManager,
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService,
LocalSettings &floatButtonSettings);
~FloatButtonManager() override = default;
void updateFloatButtonEnabled(bool enabled);
void enableFloatButton();
void disableFloatButton();
signals:
void floatButtonEnabled();
void floatButtonDisabled();
private slots:
void initFloatButton();
void destroyFloatButton();
void onScreenResolutionChanged();
private:
void initGeometryManager();
void initInternalSignalConnections();
void initScreenSignalConnections();
void createFloatButton();
void connectFloatButtonSignals();
void showFloatButton();
void hideFloatButton();
void setFloatButtonEnabled(bool enabled);
private:
bool floatButtonEnabled_ = false;
const VirtualKeyboardManager &virtualKeyboardManager_;
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService_;
LocalSettings &floatButtonSettings_;
std::unique_ptr floatButton_ = nullptr;
std::unique_ptr geometryManager_ = nullptr;
};
#endif // FLOATBUTTONMANAGER_H
kylin-virtual-keyboard/src/virtualkeyboardentry/floatbuttonmanager.cpp 0000664 0001750 0001750 00000011444 15160532634 025601 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "virtualkeyboardentry/floatbuttonmanager.h"
#include
#include
#include
#include
#include
#include
#include "geometrymanager/floatgeometrymanager.h"
#include "geometrymanager/geometrymanager.h"
#include "virtualkeyboardentry/floatbuttonstrategy.h"
FloatButtonManager::FloatButtonManager(
const VirtualKeyboardManager &virtualKeyboardManager,
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService,
LocalSettings &floatButtonSettings)
: virtualKeyboardManager_(virtualKeyboardManager),
fcitxVirtualKeyboardService_(fcitxVirtualKeyboardService),
floatButtonSettings_(floatButtonSettings) {
initGeometryManager();
initInternalSignalConnections();
initScreenSignalConnections();
}
void FloatButtonManager::enableFloatButton() { setFloatButtonEnabled(true); }
void FloatButtonManager::disableFloatButton() { setFloatButtonEnabled(false); }
void FloatButtonManager::initGeometryManager() {
geometryManager_.reset(new FloatGeometryManager(
std::unique_ptr(
new FloatButtonStrategy()),
floatButtonSettings_));
}
void FloatButtonManager::initScreenSignalConnections() {
connect(QGuiApplication::primaryScreen(), &QScreen::geometryChanged, this,
&FloatButtonManager::onScreenResolutionChanged);
}
void FloatButtonManager::initInternalSignalConnections() {
connect(this, &FloatButtonManager::floatButtonEnabled, this,
&FloatButtonManager::initFloatButton);
connect(this, &FloatButtonManager::floatButtonDisabled, this,
&FloatButtonManager::destroyFloatButton);
}
void FloatButtonManager::initFloatButton() {
fcitxVirtualKeyboardService_.hideVirtualKeyboard();
createFloatButton();
connectFloatButtonSignals();
geometryManager_->updateGeometry();
}
void FloatButtonManager::destroyFloatButton() {
if (floatButton_ == nullptr) {
return;
}
// 销毁之前必须隐藏,否则会导致虚拟键盘进程
// 直接退出
floatButton_->hide();
floatButton_.reset();
}
void FloatButtonManager::onScreenResolutionChanged() {
if (!floatButtonEnabled_) {
return;
}
geometryManager_->updateGeometry();
}
void FloatButtonManager::showFloatButton() {
if (!floatButtonEnabled_) {
return;
}
floatButton_->show();
}
void FloatButtonManager::hideFloatButton() {
if (!floatButtonEnabled_) {
return;
}
floatButton_->hide();
}
void FloatButtonManager::createFloatButton() {
floatButton_.reset(new FloatButton(
[this]() { fcitxVirtualKeyboardService_.showVirtualKeyboard(); }));
floatButton_->setWindowFlags(Qt::FramelessWindowHint |
Qt::BypassWindowManagerHint | Qt::Tool);
floatButton_->show();
}
void FloatButtonManager::connectFloatButtonSignals() {
connect(floatButton_.get(), &FloatButton::mouseMoved,
geometryManager_.get(), &FloatGeometryManager::moveBy);
connect(floatButton_.get(), &FloatButton::mouseReleased,
geometryManager_.get(), &FloatGeometryManager::endDrag);
connect(geometryManager_.get(), &FloatGeometryManager::viewMoved,
floatButton_.get(), &FloatButton::move);
connect(geometryManager_.get(), &FloatGeometryManager::viewResized,
floatButton_.get(), &FloatButton::resize);
connect(&virtualKeyboardManager_,
&VirtualKeyboardManager::virtualKeyboardVisibiltyChanged,
floatButton_.get(), [this](bool visible) {
if (visible) {
hideFloatButton();
} else {
showFloatButton();
}
});
}
void FloatButtonManager::updateFloatButtonEnabled(bool enabled) {
floatButtonEnabled_ = enabled;
if (floatButtonEnabled_) {
emit floatButtonEnabled();
} else {
emit floatButtonDisabled();
}
}
void FloatButtonManager::setFloatButtonEnabled(bool enabled) {
if (floatButtonEnabled_ == enabled) {
return;
}
updateFloatButtonEnabled(enabled);
}
kylin-virtual-keyboard/src/virtualkeyboardentry/fcitxvirtualkeyboardservice.h 0000664 0001750 0001750 00000002047 15160532550 027174 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef FCITXVIRTUALKEYBOARDSERVICE_H
#define FCITXVIRTUALKEYBOARDSERVICE_H
class FcitxVirtualKeyboardService {
public:
virtual ~FcitxVirtualKeyboardService() {}
virtual void showVirtualKeyboard() const = 0;
virtual void hideVirtualKeyboard() const = 0;
protected:
FcitxVirtualKeyboardService() = default;
};
#endif // FCITXVIRTUALKEYBOARDSERVICE_H
kylin-virtual-keyboard/src/virtualkeyboardentry/floatbutton.h 0000664 0001750 0001750 00000004351 15160532634 023712 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef FLOATBUTTON_H
#define FLOATBUTTON_H
#include
#include
#include
#include
#include
#include
#include
/**
* Used to manage the entrance section of the Kylin Virtual Keyboard float
* button.
*
* 1. show float button.
*/
class FloatButton : public QPushButton {
Q_OBJECT
public:
using MouseClickedCallback = std::function;
public:
explicit FloatButton(MouseClickedCallback mouseClickedCallback);
~FloatButton() override = default;
signals:
void mouseMoved(int x, int y);
void mouseReleased();
public slots:
void move(int x, int y);
void resize(int width, int height);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
bool shouldPerformMouseClick() const;
void processMouseReleaseEvent();
void processMouseClickEvent();
void processMouseMoveEvent(QMouseEvent *event);
void updateManhattonLength(QMouseEvent *event);
bool isFloatButtonMoved() const;
void initStyle();
void startClickTimer();
void stopClickTimer();
private:
int startX_ = -1;
int startY_ = -1;
int manhattonLength = 0;
constexpr static int manhattonLengthThreshold = 10;
MouseClickedCallback mouseClickedCallback_;
std::unique_ptr clickTimer_ = nullptr;
const int clickTimeThreshold_ = 600;
};
#endif // FLOATBUTTON_H
kylin-virtual-keyboard/src/virtualkeyboardentry/trayiconstrategy.h 0000664 0001750 0001750 00000004127 15160532550 024762 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#ifndef _TRAYICONSTRATEGY_H_
#define _TRAYICONSTRATEGY_H_
class TrayIconStrategy {
public:
virtual ~TrayIconStrategy() = default;
// 控制托盘图标的可用性(是否创建)
virtual bool shouldCreateTray() const = 0;
// 控制托盘图标的可见性(是否显示)
virtual bool shouldShowTray(int keyboardCount) const = 0;
// 是否需要监听键盘状态
virtual bool needsKeyboardMonitor() const = 0;
};
// 具体策略:始终显示
class AlwaysShowStrategy : public TrayIconStrategy {
public:
bool shouldCreateTray() const override { return true; }
bool shouldShowTray(int /*keyboardCount*/) const override { return true; }
bool needsKeyboardMonitor() const override { return false; }
};
// 具体策略:始终不显示(不创建)
class NeverShowStrategy : public TrayIconStrategy {
public:
bool shouldCreateTray() const override { return false; }
bool shouldShowTray(int /*keyboardCount*/) const override { return false; }
bool needsKeyboardMonitor() const override { return false; }
};
// 具体策略:根据键盘状态来显示
class KeyboardStatusStrategy : public TrayIconStrategy {
public:
bool shouldCreateTray() const override { return true; }
bool shouldShowTray(int keyboardCount) const override {
return keyboardCount == 0;
}
bool needsKeyboardMonitor() const override { return true; }
};
#endif kylin-virtual-keyboard/src/virtualkeyboardentry/virtualkeyboardentrymanager.cpp 0000664 0001750 0001750 00000022062 15160532634 027527 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "virtualkeyboardentry/virtualkeyboardentrymanager.h"
#include
#include
#include "geometrymanager/geometrymanager.h"
#include "virtualkeyboardentry/floatbuttonstrategy.h"
#include "virtualkeyboardsettings/virtualkeyboardsettings.h"
static const QString floatButtonGroup = "floatButton";
static const QString floatButtonEnabledKey = "floatButtonEnabled";
VirtualKeyboardEntryManager::VirtualKeyboardEntryManager(
VirtualKeyboardManager &virtualKeyboardManager,
const FcitxVirtualKeyboardService &fcitxVirtualKeyboardService)
: virtualKeyboardManager_(virtualKeyboardManager),
floatButtonManager_(new FloatButtonManager(virtualKeyboardManager,
fcitxVirtualKeyboardService,
floatButtonSettings_)),
trayIconEntry_(new VirtualKeyboardTrayIcon(virtualKeyboardManager_,
fcitxVirtualKeyboardService)),
keyboardServiceProxy_(new KeyboardServiceProxy()) {
initTrayIconStrategy();
moveValueFromLocalSettings();
initFloatButtonContextMenuAndAction();
connectSignals();
floatButtonManager_->updateFloatButtonEnabled(
VirtualKeyboardSettings::getInstance().isFloatButtonEnabled());
}
VirtualKeyboardEntryManager::~VirtualKeyboardEntryManager() = default;
void VirtualKeyboardEntryManager::initTrayIconStrategy() {
alwaysShowStrategy_ = std::make_shared();
neverShowStrategy_ = std::make_shared();
keyboardStatusStrategy_ = std::make_shared();
auto showPolicy = VirtualKeyboardSettings::getInstance().trayIconShow();
KVKBD_INFO("trayIcon showPolicy:{}", showPolicy.toStdString());
if (showPolicy == "NeverShow") {
updateStrategy(neverShowStrategy_);
} else if (showPolicy == "AlwaysShow") {
updateStrategy(alwaysShowStrategy_);
} else if (showPolicy == "ShowWhenKeyboardIsConnected") {
updateStrategy(keyboardStatusStrategy_);
}
}
void VirtualKeyboardEntryManager::initFloatButtonContextMenuAndAction() {
floatButtonContextMenu_.reset(new QMenu());
floatButtonContextMenuAction_.reset(new QAction());
floatButtonContextMenu_->addAction(floatButtonContextMenuAction_.get());
trayIconEntry_->setContextMenu(floatButtonContextMenu_.get());
connect(floatButtonContextMenu_.get(), &QMenu::aboutToShow, this,
[this]() { virtualKeyboardManager_.hide(); });
connect(floatButtonContextMenuAction_.get(), &QAction::triggered, this,
[this](bool) {
if (!actionTriggeredCallback_) {
return;
}
actionTriggeredCallback_();
});
}
void VirtualKeyboardEntryManager::connectSignals() {
connect(floatButtonManager_.get(), &FloatButtonManager::floatButtonEnabled,
this, [this]() {
updateFloatButtonContextMenuAction(
":/floatbutton/img/disablefloatbutton.svg",
tr("Disable the float button"), []() {
VirtualKeyboardSettings::getInstance()
.updateFloatButtonAvailability(false);
});
});
connect(floatButtonManager_.get(), &FloatButtonManager::floatButtonDisabled,
this, [this]() {
updateFloatButtonContextMenuAction(
":/floatbutton/img/enablefloatbutton.svg",
tr("Enable the float button"), []() {
VirtualKeyboardSettings::getInstance()
.updateFloatButtonAvailability(true);
});
});
connect(&virtualKeyboardManager_,
&VirtualKeyboardManager::virtualKeyboardVisibiltyChanged, this,
[this](bool visible) {
if (!visible) {
return;
}
trayIconEntry_->hideContextMenu();
});
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::requestFloatButtonEnabled, this,
[this]() {
virtualKeyboardManager_.hideVirtualKeyboard();
floatButtonManager_->enableFloatButton();
});
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::requestFloatButtonDisabled, this,
[this]() { floatButtonManager_->disableFloatButton(); });
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::neverShowTrayIcon, this,
[this]() { updateStrategy(neverShowStrategy_); });
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::alwaysShowTrayIcon, this,
[this]() { updateStrategy(alwaysShowStrategy_); });
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::showTrayIconWhenKeyboardisConnected, this,
[this]() { updateStrategy(keyboardStatusStrategy_); });
connect(keyboardServiceProxy_.get(),
&KeyboardServiceProxy::kbdStatusChanged, this,
[this]() { updateTrayVisibility(); });
}
void VirtualKeyboardEntryManager::updateFloatButtonContextMenuAction(
const QString &icon, const QString &text,
ActionTriggeredCallback callback) {
floatButtonContextMenuAction_->setIcon(QIcon(icon));
floatButtonContextMenuAction_->setText(text);
actionTriggeredCallback_ = std::move(callback);
}
void VirtualKeyboardEntryManager::moveValueFromLocalSettings() {
if (!floatButtonSettings_.contains(floatButtonEnabledKey)) {
return;
}
const bool value =
floatButtonSettings_.getValue(floatButtonGroup, floatButtonEnabledKey)
.value();
floatButtonSettings_.remove(floatButtonEnabledKey);
VirtualKeyboardSettings::getInstance().updateFloatButtonAvailability(value);
}
void VirtualKeyboardEntryManager::updateStrategy(
std::shared_ptr newStrategy) {
// 更新当前策略
currenTrayIconStrategy_ = newStrategy;
// 更新托盘图标可用性
updateTrayExistence();
// 更新图标可见性
updateTrayVisibility();
}
void VirtualKeyboardEntryManager::updateTrayExistence() {
if (trayIconEntry_ == nullptr) {
KVKBD_WARN("trayIconEntry_ is null!");
return;
}
const bool shouldCreate = currenTrayIconStrategy_->shouldCreateTray();
if (shouldCreate && !trayIconEntry_->isInit()) {
trayIconEntry_->initTrayIcon();
if (floatButtonContextMenu_) {
trayIconEntry_->setContextMenu(floatButtonContextMenu_.get());
}
} else if (!shouldCreate && trayIconEntry_->isInit()) {
trayIconEntry_->destroyTrayIcon();
}
}
void VirtualKeyboardEntryManager::updateTrayVisibility() {
const auto needMonitor = currenTrayIconStrategy_->needsKeyboardMonitor();
int kbdCount = 0;
if (needMonitor) {
kbdCount = getKeyboardCount(true);
}
const auto shouldShow = currenTrayIconStrategy_->shouldShowTray(kbdCount);
KVKBD_INFO("need monitor keyboard:{}, should show trayIcon:{}", needMonitor,
shouldShow);
trayIconEntry_->changeTrayIconVisibility(shouldShow);
}
int VirtualKeyboardEntryManager::getKeyboardCount(const bool &sync) {
if (!keyboardServiceProxy_) {
KVKBD_WARN("keyboardServiceProxy_ is null!");
return 0;
}
int currentKbdCount = 0;
auto kbdNumcall = keyboardServiceProxy_->GetKbdCount();
auto kbdNumcallwatcher = new QDBusPendingCallWatcher(kbdNumcall, this);
QObject::connect(kbdNumcallwatcher, &QDBusPendingCallWatcher::finished,
this, [&](QDBusPendingCallWatcher *watcher) {
watcher->deleteLater();
QDBusPendingReply reply = *watcher;
if (!reply.isError()) {
if (currentKbdCount != reply) {
currentKbdCount = reply;
}
} else {
KVKBD_WARN("getKeyboardCount(),reply error:{}",
reply.error().message().toStdString());
}
});
if (sync) {
kbdNumcallwatcher->waitForFinished();
}
KVKBD_INFO("currentKbdCount:{}", currentKbdCount);
return currentKbdCount;
}
kylin-virtual-keyboard/src/geometrymanager/ 0000775 0001750 0001750 00000000000 15160532634 020072 5 ustar feng feng kylin-virtual-keyboard/src/geometrymanager/expansiongeometrymanager.cpp 0000664 0001750 0001750 00000003102 15160532634 025705 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "expansiongeometrymanager.h"
#include "screenmanager.h"
ExpansionGeometryManager::ExpansionGeometryManager(Scaler &&scaler)
: GeometryManager(std::move(scaler)) {}
int ExpansionGeometryManager::calculateViewWidth() const {
return ScreenManager::getPrimaryScreenSize().width();
}
int ExpansionGeometryManager::calculateViewHeight() const {
QSize viewPortSize = ScreenManager::getPrimaryScreenSize();
return std::max(viewPortSize.width(), viewPortSize.height()) *
viewHeightRatio_;
}
QPoint ExpansionGeometryManager::calculateViewPosition() const {
QRect viewPortRec = ScreenManager::getPrimaryScreenGeometry();
return QPoint(viewPortRec.left(), viewPortRec.y() + viewPortRec.height() - calculateScaledViewHeight());
}
QRect ExpansionGeometryManager::getScreenGeometry() const {
return ScreenManager::getPrimaryScreenGeometry();
}
kylin-virtual-keyboard/src/geometrymanager/geometrymanager.h 0000664 0001750 0001750 00000004550 15160532634 023435 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef GEOMETRYMANAGER_H
#define GEOMETRYMANAGER_H
#include
#include
#include
#include
#include "log.h"
class Scaler {
public:
using ScaleFactorCallback = std::function;
public:
Scaler() = default;
Scaler(ScaleFactorCallback widthScaleFactorCallback,
ScaleFactorCallback heightScaleFactorCallback,
ScaleFactorCallback contentScaleFactorCallback);
~Scaler() = default;
float getWidthScaleFactor() const;
float getHeightScaleFactor() const;
float getContentScaleFactor() const;
private:
static float getScaleFactor(ScaleFactorCallback callback);
private:
ScaleFactorCallback widthScaleFactorCallback_ = nullptr;
ScaleFactorCallback heightScaleFactorCallback_ = nullptr;
ScaleFactorCallback contentScaleFactorCallback_ = nullptr;
};
class VirtualKeyboardManager;
class GeometryManager : public QObject {
Q_OBJECT
public:
~GeometryManager() override = default;
QRect geometry() const;
QRect screenGeometry() const;
int getViewContentWidth() const;
int getViewContentHeight() const;
public slots:
void updateGeometry();
signals:
void viewMoved(int x, int y);
void viewResized(int width, int height);
protected:
explicit GeometryManager(Scaler &&scaler);
QSize calculateViewSize() const;
int calculateScaledViewWidth() const;
int calculateScaledViewHeight() const;
private:
virtual int calculateViewWidth() const = 0;
virtual int calculateViewHeight() const = 0;
virtual QPoint calculateViewPosition() const = 0;
virtual QRect getScreenGeometry() const = 0;
private:
Scaler scaler_;
};
#endif // GEOMETRYMANAGER_H
kylin-virtual-keyboard/src/geometrymanager/expansiongeometrymanager.h 0000664 0001750 0001750 00000002401 15160532550 025350 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef EXPANSIONGEOMETRYMANAGER_H
#define EXPANSIONGEOMETRYMANAGER_H
#include "geometrymanager.h"
class ExpansionGeometryManager : public GeometryManager {
public:
explicit ExpansionGeometryManager(Scaler &&scaler);
~ExpansionGeometryManager() override = default;
private:
int calculateViewWidth() const override;
int calculateViewHeight() const override;
QPoint calculateViewPosition() const override;
QRect getScreenGeometry() const override;
private:
constexpr static float viewHeightRatio_ = 512.0 / 1620.0;
};
#endif // EXPANSIONGEOMETRYMANAGER_H
kylin-virtual-keyboard/src/geometrymanager/geometrymanager.cpp 0000664 0001750 0001750 00000005326 15160532634 023772 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "geometrymanager.h"
#include "screenmanager.h"
Scaler::Scaler(ScaleFactorCallback widthScaleFactorCallback,
ScaleFactorCallback heightScaleFactorCallback,
ScaleFactorCallback contentScaleFactorCallback)
: widthScaleFactorCallback_(std::move(widthScaleFactorCallback)),
heightScaleFactorCallback_(std::move(heightScaleFactorCallback)),
contentScaleFactorCallback_(std::move(contentScaleFactorCallback)) {}
float Scaler::getScaleFactor(ScaleFactorCallback callback) {
if (callback == nullptr) {
return 1.0f;
}
return callback();
}
float Scaler::getWidthScaleFactor() const {
return getScaleFactor(widthScaleFactorCallback_);
}
float Scaler::getHeightScaleFactor() const {
return getScaleFactor(heightScaleFactorCallback_);
}
float Scaler::getContentScaleFactor() const {
return getScaleFactor(contentScaleFactorCallback_);
}
GeometryManager::GeometryManager(Scaler &&scaler)
: QObject(), scaler_(std::move(scaler)) {}
QSize GeometryManager::calculateViewSize() const {
return QSize(calculateScaledViewWidth(), calculateScaledViewHeight());
}
QRect GeometryManager::geometry() const {
return QRect(calculateViewPosition(), calculateViewSize());
}
QRect GeometryManager::screenGeometry() const { return getScreenGeometry(); }
void GeometryManager::updateGeometry() {
QPoint position = calculateViewPosition();
emit viewMoved(position.x(), position.y());
QSize size = calculateViewSize();
emit viewResized(size.width(), size.height());
}
int GeometryManager::calculateScaledViewWidth() const {
return calculateViewWidth() * scaler_.getWidthScaleFactor();
}
int GeometryManager::calculateScaledViewHeight() const {
return calculateViewHeight() * scaler_.getHeightScaleFactor();
}
int GeometryManager::getViewContentWidth() const {
return calculateViewWidth() * scaler_.getContentScaleFactor();
}
int GeometryManager::getViewContentHeight() const {
return calculateViewHeight() * scaler_.getContentScaleFactor();
}
kylin-virtual-keyboard/src/geometrymanager/floatgeometrymanager.h 0000664 0001750 0001750 00000010047 15160532634 024461 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef FLOATGEOMETRYMANAGER_H
#define FLOATGEOMETRYMANAGER_H
#include
#include
#include "geometrymanager.h"
#include "localsettings/localsettings.h"
class FloatGeometryManager : public GeometryManager {
Q_OBJECT
public:
class Strategy;
public:
FloatGeometryManager(std::unique_ptr strategy,
LocalSettings &viewSettings);
FloatGeometryManager(std::unique_ptr strategy,
LocalSettings &viewSettings, Scaler &&scaler);
~FloatGeometryManager() override;
public slots:
void moveBy(int offsetX, int offsetY);
void endDrag();
private:
QPoint calculateViewPosition() const override;
int calculateViewWidth() const override;
int calculateViewHeight() const override;
QRect getScreenGeometry() const override;
int calculateNormalizedX(int positionX) const;
int calculateNormalizedY(int positionY) const;
QRect calculateProbableScreenGeometry() const;
QPoint calculateNormalizedPosition(const QPoint &position) const;
QPoint calculatePositionFromRatio(float leftMarginRatio,
float topMarginRatio) const;
QPoint calculateCurrentPosition() const;
QPoint calculateNormalizedPositionFromRatio(float leftMarginRatio,
float topMarginRatio) const;
QSize calculateMarginSize() const;
QMap getMarginRatioMap() const;
QMap getLastPositionMap() const;
QMap getDefaultMarginRatioMap() const;
QMap getDefaultLastPositionMap() const;
float calculateLeftMarginRatio(float leftMargin) const;
float calculateTopMarginRatio(float topMargin) const;
void updateMarginRatio(const QPoint &targetPosition);
void updateCurrentPostion(const QPoint &position);
void saveMarginRatioMap();
void saveLastPostionMap();
void loadMarginRatioMap();
void loadLastPostionMap();
void resetParameters();
void moveView(const QPoint &targetPoint);
QRect adjustToScreenEdges(const QRect &windowRect) const;
private:
float leftMarginRatio_ = 0.0f;
float topMarginRatio_ = 0.0f;
std::unique_ptr strategy_;
LocalSettings &viewSettings_;
static const QString floatGeometryGroup;
static const QString marginRatioMapKey;
static const QString leftMarginRatioKey;
static const QString topMarginRatioKey;
static const QString lastPositionMapKey;
static const QString lastPositionXKey;
static const QString lastPositionYKey;
static const int defaultCoordinate;
QPoint currentPosition_;
};
class FloatGeometryManager::Strategy {
public:
virtual ~Strategy() = default;
int getViewWidth(const QRect &screenGeo) const {
return screenGeo.width() * getViewWidthRatio();
}
int getViewHeight(const QRect &screenGeo) const {
auto height = std::max(screenGeo.width(), screenGeo.height());
return height * getViewHeightRatio();
}
virtual int getDefaultRightMargin() const = 0;
virtual int getDefaultBottomMargin() const = 0;
protected:
Strategy() = default;
private:
virtual int getUnitWidth() const = 0;
virtual float getViewWidthRatio() const = 0;
virtual int getUnitHeight() const = 0;
virtual float getViewHeightRatio() const = 0;
};
#endif // FLOATGEOMETRYMANAGER_H
kylin-virtual-keyboard/src/geometrymanager/floatgeometrymanager.cpp 0000664 0001750 0001750 00000027116 15160532634 025021 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "floatgeometrymanager.h"
#include
#include "localsettings/localsettings.h"
#include "screenmanager.h"
// static
const QString FloatGeometryManager::floatGeometryGroup = "floatGeometry";
// static
const QString FloatGeometryManager::marginRatioMapKey = "marginRatioMap";
// static
const QString FloatGeometryManager::leftMarginRatioKey = "leftMarginRatio";
// static
const QString FloatGeometryManager::topMarginRatioKey = "topMarginRatio";
const QString FloatGeometryManager::lastPositionMapKey = "lastPositionMap";
const QString FloatGeometryManager::lastPositionXKey = "lastPositionX";
const QString FloatGeometryManager::lastPositionYKey = "lastPositionY";
const int FloatGeometryManager::defaultCoordinate = -99999999;
FloatGeometryManager::FloatGeometryManager(std::unique_ptr strategy,
LocalSettings &viewSettings)
: FloatGeometryManager(std::move(strategy), viewSettings, Scaler()) {}
FloatGeometryManager::FloatGeometryManager(std::unique_ptr strategy,
LocalSettings &viewSettings,
Scaler &&scaler)
: GeometryManager(std::move(scaler)), strategy_(std::move(strategy)),
viewSettings_(viewSettings) {
loadLastPostionMap();
loadMarginRatioMap();
ScreenManager::screenRemoved([this]() {
KVKBD_WARN("--- [screen removed] ---");
const auto *screenAt = QGuiApplication::screenAt(currentPosition_);
if (!screenAt) {
KVKBD_WARN("screen removed, will reset view to primary screen!");
resetParameters();
}
});
}
FloatGeometryManager::~FloatGeometryManager() {
}
void FloatGeometryManager::moveBy(int offsetX, int offsetY) {
const QPoint offset(offsetX, offsetY);
const auto currentPosition = calculateCurrentPosition();
updateCurrentPostion(currentPosition);
moveView(QPoint(currentPosition + offset));
}
void FloatGeometryManager::endDrag() {
const QPoint currentPosition = calculateCurrentPosition();
const auto viewRect = QRect(currentPosition, calculateViewSize());
const auto adjustedPosition = adjustToScreenEdges(viewRect).topLeft();
if (adjustedPosition != currentPosition) {
updateCurrentPostion(adjustedPosition);
moveView(adjustedPosition);
}
saveMarginRatioMap();
saveLastPostionMap();
updateGeometry();
}
int FloatGeometryManager::calculateViewWidth() const {
return strategy_->getViewWidth(getScreenGeometry());
}
int FloatGeometryManager::calculateViewHeight() const {
return strategy_->getViewHeight(getScreenGeometry());
}
QRect FloatGeometryManager::getScreenGeometry() const {
return calculateProbableScreenGeometry();
}
QRect FloatGeometryManager::calculateProbableScreenGeometry() const {
const auto *screenAt = QGuiApplication::screenAt(currentPosition_);
if (screenAt) {
KVKBD_DEBUG("using screenAt:{}", screenAt->name().toStdString());
return screenAt->geometry();
} else {
KVKBD_DEBUG("using primary screen");
return ScreenManager::getPrimaryScreenGeometry();
}
}
QPoint FloatGeometryManager::calculateNormalizedPosition(
const QPoint &position) const {
const auto viewRect = QRect(position, calculateViewSize());
const auto adjustedPosition = adjustToScreenEdges(viewRect).topLeft();
return adjustedPosition;
}
QPoint FloatGeometryManager::calculateCurrentPosition() const {
const auto currentPosition =
calculatePositionFromRatio(leftMarginRatio_, topMarginRatio_);
return currentPosition;
}
QPoint
FloatGeometryManager::calculatePositionFromRatio(float leftMarginRatio,
float topMarginRatio) const {
const QSize marginSize = calculateMarginSize();
return QPoint(marginSize.width() * leftMarginRatio,
marginSize.height() * topMarginRatio);
}
QPoint FloatGeometryManager::calculateNormalizedPositionFromRatio(
float leftMarginRatio, float topMarginRatio) const {
return calculateNormalizedPosition(
calculatePositionFromRatio(leftMarginRatio, topMarginRatio));
}
QPoint FloatGeometryManager::calculateViewPosition() const {
return calculateNormalizedPosition(calculateCurrentPosition());
}
QSize FloatGeometryManager::calculateMarginSize() const {
const auto viewPortRect = calculateProbableScreenGeometry();
const auto viewSize = calculateViewSize();
const int horizontalMargin =
viewPortRect.left() + viewPortRect.width() - viewSize.width();
const int verticalMargin =
viewPortRect.top() + viewPortRect.height() - viewSize.height();
return QSize(horizontalMargin, verticalMargin);
}
QMap FloatGeometryManager::getMarginRatioMap() const {
QMap marginRatioMap = {
{leftMarginRatioKey, leftMarginRatio_},
{topMarginRatioKey, topMarginRatio_}};
return marginRatioMap;
}
QMap FloatGeometryManager::getLastPositionMap() const {
QMap lastPositionMap = {
{lastPositionXKey, currentPosition_.x()},
{lastPositionYKey, currentPosition_.y()}};
return lastPositionMap;
}
float FloatGeometryManager::calculateLeftMarginRatio(float leftMargin) const {
return leftMargin / calculateMarginSize().width();
}
float FloatGeometryManager::calculateTopMarginRatio(float topMargin) const {
return topMargin / calculateMarginSize().height();
}
void FloatGeometryManager::updateMarginRatio(const QPoint &targetPosition) {
leftMarginRatio_ = calculateLeftMarginRatio(targetPosition.x());
topMarginRatio_ = calculateTopMarginRatio(targetPosition.y());
KVKBD_DEBUG("leftMarginRatio_:{}, topMarginRatio_:{}", leftMarginRatio_,
topMarginRatio_);
}
void FloatGeometryManager::updateCurrentPostion(const QPoint &position) {
currentPosition_ = position;
}
void FloatGeometryManager::saveMarginRatioMap() {
viewSettings_.setValue(floatGeometryGroup, marginRatioMapKey,
getMarginRatioMap());
}
void FloatGeometryManager::saveLastPostionMap() {
viewSettings_.setValue(floatGeometryGroup, lastPositionMapKey,
getLastPositionMap());
}
QMap FloatGeometryManager::getDefaultMarginRatioMap() const {
const QRect viewPortGeo = ScreenManager::getPrimaryScreenGeometry();
const auto viewSize = calculateViewSize();
const int leftMargin =
viewPortGeo.left() + viewPortGeo.width() -
(viewSize.width() + strategy_->getDefaultRightMargin());
const int topMargin =
viewPortGeo.top() + viewPortGeo.height() -
(viewSize.height() + strategy_->getDefaultBottomMargin());
const float defaultLeftMarginRatio = calculateLeftMarginRatio(leftMargin);
const float defaultTopMarginRatio = calculateTopMarginRatio(topMargin);
QMap viewDefaultMarginRatioMap = {
{leftMarginRatioKey, defaultLeftMarginRatio},
{topMarginRatioKey, defaultTopMarginRatio}};
return viewDefaultMarginRatioMap;
}
QMap
FloatGeometryManager::getDefaultLastPositionMap() const {
QMap viewDefaultLastPositionMap = {
{lastPositionXKey, defaultCoordinate},
{lastPositionYKey, defaultCoordinate}};
return viewDefaultLastPositionMap;
}
void FloatGeometryManager::loadMarginRatioMap() {
const auto marginRatioMap =
viewSettings_
.getValue(floatGeometryGroup, marginRatioMapKey,
getDefaultMarginRatioMap())
.toMap();
const float leftMarginRatio = marginRatioMap[leftMarginRatioKey].toFloat();
const float topMarginRatio = marginRatioMap[topMarginRatioKey].toFloat();
KVKBD_DEBUG("leftMarginRatio_:{}, topMarginRatio_:{}", leftMarginRatio_,
topMarginRatio_);
updateMarginRatio(
calculateNormalizedPositionFromRatio(leftMarginRatio, topMarginRatio));
}
void FloatGeometryManager::loadLastPostionMap() {
KVKBD_DEBUG("floatGeometryGroup:{}", floatGeometryGroup.toStdString());
const auto lastPositionMap =
viewSettings_
.getValue(floatGeometryGroup, lastPositionMapKey,
getDefaultLastPositionMap())
.toMap();
const auto lastPostionX = lastPositionMap[lastPositionXKey].toInt();
const auto lastPostionY = lastPositionMap[lastPositionYKey].toInt();
updateCurrentPostion(QPoint(lastPostionX, lastPostionY));
}
void FloatGeometryManager::resetParameters() {
const auto lastPositionMap = getDefaultLastPositionMap();
const auto lastPostionX = lastPositionMap[lastPositionXKey].toInt();
const auto lastPostionY = lastPositionMap[lastPositionYKey].toInt();
auto defaultPosition = QPoint(lastPostionX, lastPostionY);
updateCurrentPostion(defaultPosition);
saveLastPostionMap();
const auto marginRatioMap = getDefaultMarginRatioMap();
const float leftMarginRatio = marginRatioMap[leftMarginRatioKey].toFloat();
const float topMarginRatio = marginRatioMap[topMarginRatioKey].toFloat();
leftMarginRatio_ = leftMarginRatio;
topMarginRatio_ = topMarginRatio;
saveMarginRatioMap();
KVKBD_WARN("leftMarginRatio_:{}, topMarginRatio_:{}", leftMarginRatio,
topMarginRatio);
}
void FloatGeometryManager::moveView(const QPoint &targetPoint) {
updateMarginRatio(targetPoint);
const QPoint currentPosition = calculateCurrentPosition();
emit viewMoved(currentPosition.x(), currentPosition.y());
}
QRect FloatGeometryManager::adjustToScreenEdges(const QRect &windowRect) const {
QScreen *targetScreen = QGuiApplication::screenAt(windowRect.center());
if (!targetScreen) {
for (QScreen *screen : QGuiApplication::screens()) {
if (screen->geometry().intersects(windowRect)) {
targetScreen = screen;
break;
}
}
}
if (!targetScreen) {
QPoint windowCenter = windowRect.center();
qreal minDistance = std::numeric_limits::max();
for (QScreen *screen : QGuiApplication::screens()) {
QRect screenGeo = screen->geometry();
QPoint screenCenter = screenGeo.center();
qreal distance = QLineF(windowCenter, screenCenter).length();
if (distance < minDistance) {
minDistance = distance;
targetScreen = screen;
}
}
}
if (!targetScreen) {
targetScreen = QGuiApplication::primaryScreen();
}
QRect screenGeo = targetScreen->geometry();
QRect adjusted = windowRect;
if (adjusted.left() < screenGeo.left())
adjusted.moveLeft(screenGeo.left());
if (adjusted.right() > screenGeo.right())
adjusted.moveRight(screenGeo.right());
if (adjusted.top() < screenGeo.top())
adjusted.moveTop(screenGeo.top());
if (adjusted.bottom() > screenGeo.bottom())
adjusted.moveBottom(screenGeo.bottom());
return adjusted;
}
kylin-virtual-keyboard/src/log.cpp 0000664 0001750 0001750 00000015706 15160532550 016177 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#include "log.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const QString APP_LOG_NAME = "kylin-virtual-keyboard.log";
const QString LOGGER_NAME = "kvkbd_log";
const QString GSETTINGS_ID = "org.ukui.virtualkeyboard";
const QString LOG_LEVEL_KEY = "logLevel";
std::shared_ptr SpdlogProxy::m_logger = nullptr;
std::atomic SpdlogProxy::m_cleaned{false};
void SpdlogProxy::init(const LogOption &option) {
QString logFileName = getWritableLogFilePath();
const auto logLevelString = getGsettingsLogLevel();
spdlog::level::level_enum level = transToSpdLogLevel(logLevelString);
std::vector sinks;
// 添加控制台 sink,捕获控制台输出,主要对qml
spdlog::sink_ptr console_sink =
std::make_shared();
sinks.push_back(console_sink);
// 添加文件 sink,使用try-catch处理文件创建失败的情况
try {
spdlog::sink_ptr file_sink =
std::make_shared(
logFileName.toStdString(), option.fileSize, option.fileCounts,
option.rotateEnable);
sinks.push_back(file_sink);
} catch (const spdlog::spdlog_ex &e) {
// 文件创建失败,只使用控制台输出
qWarning() << "Failed to create log file:" << logFileName
<< "Error:" << e.what()
<< "Falling back to console output only.";
}
m_logger = std::make_shared(LOGGER_NAME.toStdString(),
sinks.begin(), sinks.end());
m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%s:%!:%#] %v");
m_logger->set_level(level);
m_logger->flush_on(level);
// 注册 Qt 消息处理器
qInstallMessageHandler(messageHandler);
spdlog::register_logger(m_logger);
spdlog::set_default_logger(m_logger);
KVKBD_INFO("log file:{}", logFileName.toStdString());
}
void SpdlogProxy::cleanUp() {
static std::once_flag cleanup_flag;
std::call_once(cleanup_flag, []() {
m_cleaned.store(true);
qInstallMessageHandler(nullptr);
try {
if (m_logger) {
m_logger->flush();
}
if (spdlog::get(LOGGER_NAME.toStdString())) {
spdlog::drop(LOGGER_NAME.toStdString());
}
if (m_logger) {
m_logger.reset();
}
} catch (const std::exception &e) {
std::cerr << "Error during log cleanup: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unknown error during log cleanup" << std::endl;
}
});
}
bool SpdlogProxy::isCleaned() { return m_cleaned.load(); }
void SpdlogProxy::messageHandler(QtMsgType type,
const QMessageLogContext &context,
const QString &msg) {
if (m_cleaned.load() || m_logger == nullptr)
return;
spdlog::level::level_enum level;
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
int line = context.line;
switch (type) {
case QtDebugMsg:
level = spdlog::level::debug;
break;
case QtInfoMsg:
level = spdlog::level::info;
break;
case QtWarningMsg:
level = spdlog::level::warn;
break;
case QtCriticalMsg:
level = spdlog::level::err;
break;
case QtFatalMsg:
level = spdlog::level::critical;
break;
default:
level = spdlog::level::info;
break;
}
// 记录到 spdlog(包含文件名、行号、函数名)
spdlog::log(spdlog::source_loc{file, line, function}, level, "{}",
msg.toStdString());
}
void SpdlogProxy::debug(const QString &msg) {
if (m_cleaned.load() || m_logger == nullptr)
return;
m_logger->debug("[log-proxy] {}", msg.toStdString());
}
void SpdlogProxy::info(const QString &msg) {
if (m_cleaned.load() || m_logger == nullptr)
return;
m_logger->info("[log-proxy] {}", msg.toStdString());
}
void SpdlogProxy::warn(const QString &msg) {
if (m_cleaned.load() || m_logger == nullptr)
return;
m_logger->warn("[log-proxy] {}", msg.toStdString());
}
void SpdlogProxy::error(const QString &msg) {
if (m_cleaned.load() || m_logger == nullptr)
return;
m_logger->error("[log-proxy] {}", msg.toStdString());
}
QString SpdlogProxy::getGsettingsLogLevel() {
QString result = "info";
if (!QGSettings::isSchemaInstalled(GSETTINGS_ID.toUtf8())) {
return result;
}
QGSettings gsettings = QGSettings(GSETTINGS_ID.toUtf8());
if (gsettings.keys().contains(LOG_LEVEL_KEY)) {
QVariant value = gsettings.get(LOG_LEVEL_KEY);
if (value.isValid()) {
result = value.toString();
}
}
return result;
}
spdlog::level::level_enum
SpdlogProxy::transToSpdLogLevel(const QString &level) {
if (level == "debug") {
return spdlog::level::debug;
} else if (level == "info") {
return spdlog::level::info;
} else if (level == "warn") {
return spdlog::level::warn;
} else if (level == "error") {
return spdlog::level::err;
} else {
return spdlog::level::info;
}
}
QString SpdlogProxy::getWritableLogFilePath() {
QString homeDir =
QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QStringList logPaths;
QString primaryLogPath = homeDir + "/.log/";
QString fallbackLogPath =
QStandardPaths::writableLocation(QStandardPaths::TempLocation) +
"/kylin-virtual-keyboard/";
logPaths << primaryLogPath << fallbackLogPath;
QString logFileName;
for (const QString &logPath : logPaths) {
QDir logDir(logPath);
if (!logDir.exists()) {
logDir.mkpath(".");
}
if (!QFileInfo(logPath).isWritable()) {
continue;
}
logFileName = logPath + APP_LOG_NAME;
break;
}
return logFileName;
}
kylin-virtual-keyboard/src/errorhandler.cpp 0000664 0001750 0001750 00000011351 15160532550 020075 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2025.All rights reserved.
*
* 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 3 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, see .
*/
#include "errorhandler.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MINIMAL_BUFFER_SIZE 256
#define BACKTRACE_SIZE 32
QString ErrorHandler::m_crashLogPath;
bool ErrorHandler::m_logDirWritable = false;
const QString fileName = "kylin-virtual-keyboard-error.log";
void ErrorHandler::init() {
createLogFile();
registerSignalHandler();
void *array[BACKTRACE_SIZE] = {
nullptr,
};
(void)backtrace(array, BACKTRACE_SIZE);
}
void ErrorHandler::createLogFile() {
QString homeDir =
QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QStringList logPaths;
QString primaryLogPath = homeDir + "/.log/";
QString fallbackLogPath =
QStandardPaths::writableLocation(QStandardPaths::TempLocation) +
"/kylin-virtual-keyboard/";
logPaths << primaryLogPath << fallbackLogPath;
for (const QString &logPath : logPaths) {
QDir logDir(logPath);
if (!logDir.exists()) {
logDir.mkpath(".");
}
if (!QFileInfo(logPath).isWritable()) {
continue;
}
m_crashLogPath = logPath + fileName;
m_logDirWritable = true;
break;
}
}
void ErrorHandler::registerSignalHandler() {
// 注册信号处理器
// 只关心以下信号
signal(SIGSEGV, signalHandler);
signal(SIGABRT, signalHandler);
signal(SIGFPE, signalHandler);
signal(SIGILL, signalHandler);
}
void ErrorHandler::signalHandler(int sig) {
if (m_crashLogPath.isEmpty()) {
return;
}
if (m_logDirWritable == false) {
return;
}
int fd = open(m_crashLogPath.toLocal8Bit().constData(),
O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
return;
}
writeString(fd, "=========================\n");
writeString(fd, "Kylin Virtual Keyboard -- Get Signal No.: ");
writeUInt64(fd, sig);
writeString(fd, " (");
writeString(fd, getSignalName(sig));
writeString(fd, ")\n");
time_t t = time(nullptr);
writeString(fd, "Date: ");
writeUInt64(fd, t);
writeString(fd, " (try \"date -d @");
writeUInt64(fd, t);
writeString(fd, "\" if you are using GNU date)\n");
writeString(fd, "ProcessID: ");
writeUInt64(fd, getpid());
writeString(fd, "\n");
generateBacktrace(fd);
close(fd);
signal(sig, SIG_DFL);
raise(sig);
}
void ErrorHandler::writeUInt64(int fd, unsigned long long number) {
char buffer[MINIMAL_BUFFER_SIZE]{0};
int len = snprintf(buffer, sizeof(buffer), "%llu", number);
if (len > 0 && len < (int)sizeof(buffer)) {
writeBuffer(fd, buffer, len);
}
}
ssize_t ErrorHandler::writeAll(int fd, const void *buf, size_t count) {
const char *p = (const char *)buf;
while (count > 0) {
ssize_t written = write(fd, p, count);
if (written == -1) {
if (errno == EINTR)
continue;
return -1;
}
p += written;
count -= written;
}
return 0;
}
const char *ErrorHandler::getSignalName(int sig) {
switch (sig) {
case SIGSEGV:
return "SIGSEGV";
case SIGFPE:
return "SIGFPE";
case SIGILL:
return "SIGILL";
case SIGABRT:
return "SIGABRT";
default:
return "OTHER";
}
}
void ErrorHandler::generateBacktrace(int fd) {
void *array[BACKTRACE_SIZE]{
nullptr,
};
int size = backtrace(array, BACKTRACE_SIZE);
writeString(fd, "\nBacktrace:\n");
writeString(fd, "Backtrace size: ");
writeUInt64(fd, size);
writeString(fd, "\n");
writeString(fd, "\nBacktrace addresses:\n");
backtrace_symbols_fd(array, size, fd);
}
void ErrorHandler::writeString(int fd, const char *str) {
writeAll(fd, str, strlen(str));
}
void ErrorHandler::writeBuffer(int fd, const char *buffer, int len) {
writeAll(fd, buffer, len);
} kylin-virtual-keyboard/src/virtualkeyboard/ 0000775 0001750 0001750 00000000000 15160532634 020113 5 ustar feng feng kylin-virtual-keyboard/src/virtualkeyboard/virtualkeyboardmanager.cpp 0000664 0001750 0001750 00000021320 15160532634 025357 0 ustar feng feng /*
* Copyright (c) KylinSoft Co., Ltd. 2022.All rights reserved.
*
* 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 3 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, see .
*/
#include "virtualkeyboardmanager.h"
#include
#include
#include "animation/disabledanimator.h"
#include "animation/enabledanimator.h"
#include "animation/expansionanimationfactory.h"
#include "animation/floatanimationfactory.h"
#include "virtualkeyboardsettings/virtualkeyboardsettings.h"
#include "virtualkeyboardstrategy.h"
VirtualKeyboardManager::VirtualKeyboardManager(
HideVirtualKeyboardCallback hideVirtualKeyboardCallback)
: hideVirtualKeyboardCallback_(std::move(hideVirtualKeyboardCallback)) {
initVirtualKeyboardModel();
initAppInputAreaManager();
initVirtualKeyboardView();
initScreenSignalConnections();
}
VirtualKeyboardManager::~VirtualKeyboardManager() {
hideVirtualKeyboard();
appInputAreaManager_.reset();
view_.reset();
model_.reset();
}
void VirtualKeyboardManager::showVirtualKeyboard() {
if (isVirtualKeyboardVisible()) {
return;
}
view_->show();
visibiltyChanged();
}
void VirtualKeyboardManager::hideVirtualKeyboard() {
if (!isVirtualKeyboardVisible()) {
return;
}
appInputAreaManager_->fallInputArea();
view_->hide();
visibiltyChanged();
}
void VirtualKeyboardManager::hide() {
if (!hideVirtualKeyboardCallback_) {
return;
}
hideVirtualKeyboardCallback_();
}
void VirtualKeyboardManager::flipPlacementMode() { view_->flip(); }
void VirtualKeyboardManager::moveBy(int offsetX, int offsetY) {
view_->moveBy(offsetX, offsetY);
}
void VirtualKeyboardManager::endDrag() { view_->endDrag(); }
void VirtualKeyboardManager::visibiltyChanged() {
emit virtualKeyboardVisibiltyChanged(isVirtualKeyboardVisible());
}
bool VirtualKeyboardManager::isVirtualKeyboardVisible() const {
return view_->isVisible();
}
void VirtualKeyboardManager::updatePreeditCaret(int index) {
model_->setPreeditCaret(index);
}
void VirtualKeyboardManager::updatePreeditArea(const QString &preeditText) {
model_->setPreeditText(preeditText);
}
void VirtualKeyboardManager::updateCandidateArea(
const QStringList &candidateTextList, bool hasPrev, bool hasNext,
int pageIndex, int globalCursorIndex) {
model_->updateCandidateArea(QVariant(candidateTextList), hasPrev, hasNext,
pageIndex, globalCursorIndex);
}
void VirtualKeyboardManager::notifyIMActivated(const QString &uniqueName) {
model_->setUniqueName(uniqueName);
}
void VirtualKeyboardManager::notifyIMDeactivated(
const QString & /*uniqueName*/) {
emit model_->imDeactivated();
}
void VirtualKeyboardManager::notifyIMListChanged() {
model_->syncCurrentIMList();
}
void VirtualKeyboardManager::processResolutionChangedEvent() {
if (isVirtualKeyboardVisible()) {
view_->updateGeometry();
raiseInputAreaIfNecessary();
}
}
void VirtualKeyboardManager::initAppInputAreaManager() {
appInputAreaManager_.reset(new AppInputAreaManager(this));
}
std::unique_ptr
VirtualKeyboardManager::createPlacementModeManager() {
return std::unique_ptr(
new PlacementModeManager(viewSettings_));
}
Scaler VirtualKeyboardManager::createFloatModeScaler() {
return Scaler(
[]() {
return VirtualKeyboardSettings::getInstance()
.calculateVirtualKeyboardScaleFactor();
},
[]() {
return VirtualKeyboardSettings::getInstance()
.calculateVirtualKeyboardScaleFactor();
},
[]() {
return VirtualKeyboardSettings::getInstance()
.calculateVirtualKeyboardScaleFactor();
});
}
Scaler VirtualKeyboardManager::createExpansionModeScaler() {
return Scaler([]() { return 1.0f; },
[]() {
return VirtualKeyboardSettings::getInstance()
.calculateVirtualKeyboardScaleFactor();
},
[]() {
return VirtualKeyboardSettings::getInstance()
.calculateVirtualKeyboardScaleFactor();
});
}
std::unique_ptr
VirtualKeyboardManager::createExpansionGeometryManager() {
return std::unique_ptr(
new ExpansionGeometryManager(createExpansionModeScaler()));
}
std::unique_ptr
VirtualKeyboardManager::createFloatGeometryManger() {
return std::unique_ptr(new FloatGeometryManager(
std::unique_ptr(
new VirtualKeyboardStrategy()),
viewSettings_, createFloatModeScaler()));
}
void VirtualKeyboardManager::initVirtualKeyboardModel() {
model_.reset(new VirtualKeyboardModel(this));
connect(model_.get(), SIGNAL(backendConnectionDisconnected()), this,
SLOT(hideVirtualKeyboard()));
}
void VirtualKeyboardManager::initVirtualKeyboardView() {
view_.reset(new VirtualKeyboardView(
*this, *model_, createPlacementModeManager(),
createExpansionGeometryManager(), createFloatGeometryManger()));
view_->setAnimator(createAnimator());
connectVirtualKeyboardModelSignals();
connectVirtualKeyboardViewSignals();
connectVirtualKeyboardSettingsSignals();
}
void VirtualKeyboardManager::connectVirtualKeyboardModelSignals() {
connect(model_.get(), SIGNAL(updateCandidateArea(const QVariant &, int)),
view_.get(), SIGNAL(updateCandidateArea(const QVariant &, int)));
connect(model_.get(), SIGNAL(imDeactivated()), view_.get(),
SIGNAL(imDeactivated()));
}
void VirtualKeyboardManager::connectVirtualKeyboardViewSignals() {
connect(
view_.get(), &VirtualKeyboardView::raiseAppRequested, this,
[this]() { appInputAreaManager_->raiseInputArea(view_->geometry()); });
connect(view_.get(), &VirtualKeyboardView::fallAppRequested, this,
[this]() { appInputAreaManager_->fallInputArea(); });
}
void VirtualKeyboardManager::connectVirtualKeyboardSettingsSignals() {
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::scaleFactorChanged, view_.get(),
[this]() {
view_->updateGeometry();
raiseInputAreaIfNecessary();
});
connect(&VirtualKeyboardSettings::getInstance(),
&VirtualKeyboardSettings::animationAvailabilityChanged, this,
[this]() { view_->setAnimator(createAnimator()); });
}
void VirtualKeyboardManager::initScreenSignalConnections() {
connect(QGuiApplication::primaryScreen(),
SIGNAL(geometryChanged(const QRect &)), this,
SLOT(processResolutionChangedEvent()));
}
void VirtualKeyboardManager::raiseInputAreaIfNecessary() {
if (!view_->isVisible()) {
return;
}
if (view_->isFloatMode()) {
return;
}
appInputAreaManager_->raiseInputArea(view_->geometry());
}
std::unique_ptr
VirtualKeyboardManager::createAnimationFactory() {
if (view_->isFloatMode()) {
return std::unique_ptr(new FloatAnimationFactory());
} else {
return std::unique_ptr(
new ExpansionAnimationFactory());
}
}
std::unique_ptr VirtualKeyboardManager::createEnabledAnimator() {
auto animator = std::unique_ptr(new EnabledAnimator(
[this]() { return view_->isFloatMode(); }, createAnimationFactory()));
EnabledAnimator *enabledAnimator = animator.get();
connect(view_.get(), &VirtualKeyboardView::isFloatModeChanged,
enabledAnimator, [this, enabledAnimator]() {
enabledAnimator->setAnimationFactory(createAnimationFactory());
});
return animator;
}
std::unique_ptr VirtualKeyboardManager::createDisabledAnimator() {
return std::unique_ptr(new DisabledAnimator());
}
std::unique_ptr VirtualKeyboardManager::createAnimator() {
if (VirtualKeyboardSettings::getInstance().isAnimationEnabled()) {
return createEnabledAnimator();
} else {
return createDisabledAnimator();
}
}
kylin-virtual-keyboard/src/virtualkeyboard/virtualkeyboardmanager.h 0000664 0001750 0001750 00000006720 15160532634 025033 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef VIRTUALKEYBOARDMANAGER_H
#define VIRTUALKEYBOARDMANAGER_H
#include
#include
#include
#include "animation/animationfactory.h"
#include "appinputareamanager.h"
#include "geometrymanager/expansiongeometrymanager.h"
#include "geometrymanager/floatgeometrymanager.h"
#include "localsettings/viewlocalsettings.h"
#include "placementmodemanager.h"
#include "virtualkeyboardmodel.h"
#include "virtualkeyboardview.h"
class VirtualKeyboardManager : public QObject {
Q_OBJECT
public:
using HideVirtualKeyboardCallback = std::function;
public:
explicit VirtualKeyboardManager(
HideVirtualKeyboardCallback hideVirtualKeyboardCallback);
~VirtualKeyboardManager();
void showVirtualKeyboard();
Q_INVOKABLE void hide();
Q_INVOKABLE void flipPlacementMode();
Q_INVOKABLE void moveBy(int offsetX, int offsetY);
Q_INVOKABLE void endDrag();
void visibiltyChanged();
bool isVirtualKeyboardVisible() const;
void updatePreeditCaret(int index);
void updatePreeditArea(const QString &preeditText);
void updateCandidateArea(const QStringList &candidateTextList, bool hasPrev,
bool hasNext, int pageIndex,
int globalCursorIndex);
void notifyIMActivated(const QString &uniqueName);
void notifyIMDeactivated(const QString &uniqueName);
void notifyIMListChanged();
signals:
void virtualKeyboardVisibiltyChanged(bool isShow);
public slots:
void processResolutionChangedEvent();
void hideVirtualKeyboard();
private:
void initAppInputAreaManager();
std::unique_ptr createPlacementModeManager();
static Scaler createExpansionModeScaler();
static Scaler createFloatModeScaler();
static std::unique_ptr
createExpansionGeometryManager();
std::unique_ptr createFloatGeometryManger();
void initVirtualKeyboardModel();
void initScreenSignalConnections();
void initVirtualKeyboardView();
void connectVirtualKeyboardModelSignals();
void connectVirtualKeyboardViewSignals();
void connectVirtualKeyboardSettingsSignals();
void raiseInputAreaIfNecessary();
std::unique_ptr createAnimationFactory();
std::unique_ptr createEnabledAnimator();
std::unique_ptr createDisabledAnimator();
std::unique_ptr createAnimator();
std::unique_ptr appInputAreaManager_ = nullptr;
std::unique_ptr model_ = nullptr;
std::unique_ptr view_ = nullptr;
HideVirtualKeyboardCallback hideVirtualKeyboardCallback_;
ViewLocalSettings viewSettings_{"kylinsoft", "kylin virtual keyboard"};
};
#endif // VIRTUALKEYBOARDMANAGER_H
kylin-virtual-keyboard/src/virtualkeyboard/virtualkeyboardview.h 0000664 0001750 0001750 00000007777 15160532634 024410 0 ustar feng feng /*
* Copyright 2022 KylinSoft Co., Ltd.
*
* 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 3 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, see .
*/
#ifndef VIRTUALKEYBOARDVIEW_H
#define VIRTUALKEYBOARDVIEW_H
#include
#include
#include
#include
#include "animation/animator.h"
#include "geometrymanager/expansiongeometrymanager.h"
#include "geometrymanager/floatgeometrymanager.h"
#include "geometrymanager/geometrymanager.h"
#include "virtualkeyboard/placementmodemanager.h"
class VirtualKeyboardView : public QObject {
Q_OBJECT
public:
VirtualKeyboardView(
QObject &manager, QObject &model,
std::unique_ptr placementModeManager,
std::unique_ptr expansionGeometryManager,
std::unique_ptr floatGeometryManager);
~VirtualKeyboardView() override;
void initView();
Q_PROPERTY(bool isFloatMode READ isFloatMode NOTIFY isFloatModeChanged);
Q_PROPERTY(
int contentHeight READ getContentHeight NOTIFY contentHeightChanged);
Q_PROPERTY(
int contentWidth READ getContentWidth NOTIFY contentWidthChanged);
void moveBy(int offsetX, int offsetY);
void endDrag();
QRect geometry() const;
QRect screenGeometry() const;
void updateGeometry();
void emitContentGeometrySignals();
bool isVisible() const;
void show();
void hide();
void flip();
QWindow *view() { return view_.get(); }
bool isFloatMode() const { return placementModeManager_->isFloatMode(); }
void updateExpansionFlippingStartGeometry();
void setAnimator(std::shared_ptr animator);
signals:
void isFloatModeChanged();
void contentHeightChanged();
void contentWidthChanged();
void updateCandidateArea(const QVariant &candidateTextList,
int globalCursorIndex);
void imDeactivated();
void raiseAppRequested();
void fallAppRequested();
public slots:
void move(int x, int y);
void resize();
private:
class State;
class VisibleState;
class HidingState;
class ShowingState;
class InvisibleState;
class FlippingState;
private:
void initState();
QRect calculateInitialGeometry();
static int getScreenHeight();
int getScreenRelativeHeight();
void connectSignals();
void destroyView();
int getContentHeight();
int getContentWidth();
void setViewOpacity();
void updateCurrentState(std::shared_ptr newState);
void enterVisibleState();
void enterHidingState();
void enterShowingState();
void enterInvisibleState();
void enterFlippingState();
GeometryManager &getCurrentGeometryManager() const;
private:
QObject &manager_;
QObject &model_;
std::unique_ptr view_ = nullptr;
std::unique_ptr