Skip to content

Commit

Permalink
Use new show custom input method information to display option change
Browse files Browse the repository at this point in the history
Instead of using system notification, which we do not have a long,
descriptive string, use the input popup to display such information
instead.

This can be easily achieved, by dispatch "option" notification in main
thread to get the changed options. Since key event always happens in the
main thread, we can guarantee that there is only one RimeState handling
the key event. After that, try to aggregate based on the
RimeOptionAction so the 3+ state option will not display multiple
strings.

Fix #111
  • Loading branch information
wengxt committed Jun 9, 2024
1 parent 41dcb73 commit 5cfb554
Show file tree
Hide file tree
Showing 11 changed files with 462 additions and 186 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ include(ECMSetupVersion)
include(ECMUninstallTarget)

find_package(Gettext REQUIRED)
find_package(Fcitx5Core 5.1.10 REQUIRED)
find_package(Fcitx5Core 5.1.11 REQUIRED)
find_package(Fcitx5Module REQUIRED COMPONENTS Notifications)
find_package(PkgConfig REQUIRED)
find_package(Pthread REQUIRED)

if (NOT DEFINED RIME_TARGET)
pkg_check_modules(Rime REQUIRED IMPORTED_TARGET "rime>=1.0.0")
Expand Down
59 changes: 59 additions & 0 deletions cmake/FindPthread.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Try to find Pthread functionality
# Once done this will define
#
# PTHREAD_FOUND - system has Pthread
# PTHREAD_INCLUDE_DIR - Pthread include directory
# PTHREAD_LIBRARIES - Libraries needed to use Pthread
#
# TODO: This will enable translations only if Gettext functionality is
# present in libc. Must have more robust system for release, where Gettext
# functionality can also reside in standalone Gettext library, or the one
# embedded within kdelibs (cf. gettext.m4 from Gettext source).
#
# Copyright (c) 2006, Chusslove Illich, <caslav.ilic@gmx.net>
# Copyright (c) 2007, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2016, Xuetian Weng <wengxt@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

find_path(PTHREAD_INCLUDE_DIR NAMES pthread.h)

if(PTHREAD_INCLUDE_DIR)
include(CheckFunctionExists)
check_function_exists(pthread_create PTHREAD_LIBC_HAS_PTHREAD_CREATE)

if (PTHREAD_LIBC_HAS_PTHREAD_CREATE)
set(PTHREAD_LIBRARIES)
set(PTHREAD_LIB_FOUND TRUE)
else (PTHREAD_LIBC_HAS_PTHREAD_CREATE)
find_library(PTHREAD_LIBRARIES NAMES pthread libpthread )
if(PTHREAD_LIBRARIES)
set(PTHREAD_LIB_FOUND TRUE)
endif(PTHREAD_LIBRARIES)
endif (PTHREAD_LIBC_HAS_PTHREAD_CREATE)

endif(PTHREAD_INCLUDE_DIR)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Pthread
FOUND_VAR
PTHREAD_FOUND
REQUIRED_VARS
PTHREAD_INCLUDE_DIR PTHREAD_LIB_FOUND
)

if(PTHREAD_FOUND AND NOT TARGET Pthread::Pthread)
if (PTHREAD_LIBRARIES)
add_library(Pthread::Pthread UNKNOWN IMPORTED)
set_target_properties(Pthread::Pthread PROPERTIES
IMPORTED_LOCATION "${PTHREAD_LIBRARIES}")
else()
add_library(Pthread::Pthread INTERFACE IMPORTED )
endif()
set_target_properties(Pthread::Pthread PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${PTHREAD_INCLUDE_DIR}"
)
endif()

mark_as_advanced(PTHREAD_INCLUDE_DIR PTHREAD_LIBRARIES PTHREAD_LIBC_HAS_PTHREAD_CREATE PTHREAD_LIB_FOUND)
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ set(RIME_SOURCES
rimeengine.cpp
rimecandidate.cpp
rimesession.cpp
rimeaction.cpp
)

set(RIME_LINK_LIBRARIES
Fcitx5::Core
Fcitx5::Config
${RIME_TARGET}
Fcitx5::Module::Notifications
Pthread::Pthread
)

find_package(Fcitx5ModuleDBus QUIET)
Expand Down
143 changes: 143 additions & 0 deletions src/rimeaction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* SPDX-FileCopyrightText: 2024~2024 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "rimeaction.h"
#include "rimeengine.h"
#include <algorithm>
#include <cstddef>
#include <fcitx-utils/stringutils.h>
#include <fcitx/action.h>
#include <fcitx/userinterfacemanager.h>
#include <optional>
#include <rime_api.h>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

namespace fcitx {

ToggleAction::ToggleAction(RimeEngine *engine, std::string_view schema,
std::string_view option, std::string disabledText,
std::string enabledText)
: engine_(engine), option_(option), disabledText_(std::move(disabledText)),
enabledText_(std::move(enabledText)) {
engine_->instance()->userInterfaceManager().registerAction(
stringutils::concat("fcitx-rime-", schema, "-", option), this);
}

void ToggleAction::activate(InputContext *ic) {
auto *state = engine_->state(ic);
auto *api = engine_->api();
if (!state) {
return;
}
// Do not send notification since user is explicitly select it.
engine_->blockNotificationFor(30000);
auto session = state->session();
Bool oldValue = api->get_option(session, option_.c_str());
api->set_option(session, option_.c_str(), !oldValue);
}

std::string ToggleAction::shortText(InputContext *ic) const {
auto *state = engine_->state(ic);
auto *api = engine_->api();
if (!state) {
return "";
}
auto session = state->session();
if (api->get_option(session, option_.c_str())) {
return stringutils::concat(enabledText_, "", disabledText_);
}
return stringutils::concat(disabledText_, "", enabledText_);
}

std::optional<std::string> ToggleAction::snapshotOption(InputContext *ic) {
auto *state = engine_->state(ic);
auto *api = engine_->api();
if (!state) {
return std::nullopt;
}
auto session = state->session(false);
if (!session) {
return std::nullopt;
}
if (!api->get_option(session, option_.c_str())) {
return stringutils::concat("!", option_);
}
return option_;
}

bool ToggleAction::checkOptionName(std::string_view name) const {
return name == option_;
}

SelectAction::SelectAction(RimeEngine *engine, std::string_view schema,
std::vector<std::string> options,
std::vector<std::string> texts)
: engine_(engine), options_(options), texts_(std::move(texts)) {
for (size_t i = 0; i < options.size(); ++i) {
actions_.emplace_back();
actions_.back().setShortText(texts_[i]);
actions_.back().connect<SimpleAction::Activated>(
[this, i](InputContext *ic) {
auto *state = engine_->state(ic);
auto *api = engine_->api();
if (!state) {
return;
}
auto session = state->session();
for (size_t j = 0; j < options_.size(); ++j) {
api->set_option(session, options_[j].c_str(), i == j);
}
});
engine_->instance()->userInterfaceManager().registerAction(
stringutils::concat("fcitx-rime-", schema, "-", options_[i]),
&actions_.back());
menu_.addAction(&actions_.back());
}
setMenu(&menu_);
engine_->instance()->userInterfaceManager().registerAction(
stringutils::concat("fcitx-rime-", schema, "-select-", options[0]),
this);
}

std::string SelectAction::shortText(InputContext *ic) const {
auto *state = engine_->state(ic);
auto *api = engine_->api();
if (!state) {
return "";
}
auto session = state->session();
for (size_t i = 0; i < options_.size(); ++i) {
if (api->get_option(session, options_[i].c_str())) {
return texts_[i];
}
}
return "";
}

std::optional<std::string> SelectAction::snapshotOption(InputContext *ic) {
auto *state = engine_->state(ic);
auto *api = engine_->api();
if (!state) {
return std::nullopt;
}
auto session = state->session(false);
if (!session) {
return std::nullopt;
}
for (auto &option : options_) {
if (api->get_option(session, option.c_str())) {
return option;
}
}
return std::nullopt;
}

bool SelectAction::checkOptionName(std::string_view name) const {
return std::find(options_.begin(), options_.end(), name) != options_.end();
}
} // namespace fcitx
82 changes: 82 additions & 0 deletions src/rimeaction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2017~2017 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef _FCITX_RIMEACTION_H_
#define _FCITX_RIMEACTION_H_

#include <cstddef>
#include <fcitx/action.h>
#include <fcitx/menu.h>
#include <list>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

namespace fcitx {

class RimeEngine;

class RimeOptionAction : public Action {
public:
// This is used to save the option when we need to release the session.
virtual std::optional<std::string> snapshotOption(InputContext *ic) = 0;
// Check whether a option name belongs to the action.
virtual bool checkOptionName(std::string_view name) const = 0;
};

class ToggleAction : public RimeOptionAction {
public:
ToggleAction(RimeEngine *engine, std::string_view schema,
std::string_view option, std::string disabledText,
std::string enabledText);

void activate(InputContext *ic) override;

std::string shortText(InputContext *ic) const override;

std::string icon(InputContext * /*unused*/) const override { return ""; }

std::optional<std::string> snapshotOption(InputContext *ic) override;

const std::string &option() const { return option_; }

bool checkOptionName(std::string_view name) const override;

private:
RimeEngine *engine_;
std::string option_;
std::string disabledText_;
std::string enabledText_;
};

class SelectAction : public RimeOptionAction {
public:
SelectAction(RimeEngine *engine, std::string_view schema,
std::vector<std::string> options,
std::vector<std::string> texts);

std::string shortText(InputContext *ic) const override;

std::string icon(InputContext * /*unused*/) const override { return ""; }

std::optional<std::string> snapshotOption(InputContext *ic) override;

const std::vector<std::string> &options() const { return options_; }

bool checkOptionName(std::string_view name) const override;

private:
RimeEngine *engine_;
std::vector<std::string> options_;
std::vector<std::string> texts_;
std::list<SimpleAction> actions_;
Menu menu_;
};

} // namespace fcitx

#endif // _FCITX_RIMEENGINE_H_
4 changes: 2 additions & 2 deletions src/rimecandidate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const CandidateWord &RimeCandidateList::candidateFromAll(int idx) const {

int RimeCandidateList::totalSize() const { return -1; }

bool RimeCandidateList::hasAction(const CandidateWord &candidate) const {
bool RimeCandidateList::hasAction(const CandidateWord & /*candidate*/) const {
#ifndef FCITX_RIME_NO_DELETE_CANDIDATE
// We can always reset rime candidate's frequency.
return true;
Expand All @@ -162,7 +162,7 @@ bool RimeCandidateList::hasAction(const CandidateWord &candidate) const {
}

std::vector<CandidateAction>
RimeCandidateList::candidateActions(const CandidateWord &candidate) const {
RimeCandidateList::candidateActions(const CandidateWord & /*candidate*/) const {
std::vector<CandidateAction> actions;
#ifndef FCITX_RIME_NO_DELETE_CANDIDATE
CandidateAction action;
Expand Down
Loading

0 comments on commit 5cfb554

Please sign in to comment.