Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/frontend/waylandim/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@ add_fcitx5_addon(waylandim
plasmaappmonitor.cpp
virtualinputcontext.cpp
wlrappmonitor.cpp
cosmicappmonitor.cpp
appmonitor.cpp
${WAYLAND_IM_PROTOCOL_SRCS}
)
target_include_directories(waylandim PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(waylandim Fcitx5::Core Wayland::Client XKBCommon::XKBCommon Fcitx5::Wayland::PlasmaWindowManagement Fcitx5::Wayland::WLRForeignToplevelManagement Fcitx5::Module::Wayland Fcitx5::Wayland::Core Fcitx5::Wayland::InputMethod Fcitx5::Wayland::InputMethodV2)
target_link_libraries(waylandim
Fcitx5::Core Wayland::Client XKBCommon::XKBCommon
Fcitx5::Wayland::PlasmaWindowManagement
Fcitx5::Wayland::WLRForeignToplevelManagement
Fcitx5::Module::Wayland
Fcitx5::Wayland::Core
Fcitx5::Wayland::InputMethod
Fcitx5::Wayland::InputMethodV2
Fcitx5::Wayland::ExtForeignToplevelList
Fcitx5::Wayland::CosmicToplevelInfo)
install(TARGETS waylandim DESTINATION "${FCITX_INSTALL_ADDONDIR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/waylandim.conf.in.in ${CMAKE_CURRENT_BINARY_DIR}/waylandim.conf.in @ONLY)
fcitx5_translate_desktop_file(${CMAKE_CURRENT_BINARY_DIR}/waylandim.conf.in waylandim.conf)
Expand Down
152 changes: 152 additions & 0 deletions src/frontend/waylandim/cosmicappmonitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* SPDX-FileCopyrightText: 2022~2022 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
*/
#include "cosmicappmonitor.h"
#include <cstddef>
#include <cstdint>
#include <list>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <wayland-client-core.h>
#include <wayland-util.h>
#include "fcitx-utils/signals.h"
#include "display.h"
#include "ext_foreign_toplevel_handle_v1.h"
#include "ext_foreign_toplevel_list_v1.h"
#include "zcosmic_toplevel_handle_v1.h"
#include "zcosmic_toplevel_info_v1.h"

namespace fcitx {
class CosmicWindow {
public:
CosmicWindow(CosmicAppMonitor *parent,
wayland::ExtForeignToplevelHandleV1 *window)
: parent_(parent), window_(window),
key_(std::to_string(wl_proxy_get_id(reinterpret_cast<wl_proxy *>(
static_cast<ext_foreign_toplevel_handle_v1 *>(*window))))) {
if (parent->info()) {
setup(parent->info());
}
}

const auto &appId() const { return appId_; }
bool active() const { return active_; }
const auto &key() { return key_; }

void setup(wayland::ZcosmicToplevelInfoV1 *info) {
if (setup_) {
return;
}
cosmicWindow_.reset(info->getCosmicToplevel(window_.get()));
conns_.emplace_back(
cosmicWindow_->state().connect([this](wl_array *array) {
pendingActive_ = false;
size_t size = array->size / sizeof(uint32_t);
for (size_t i = 0; i < size; ++i) {
auto entry = static_cast<uint32_t *>(array->data)[i];
if (entry == ZCOSMIC_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED) {
pendingActive_ = true;
}
}
}));
conns_.emplace_back(window_->done().connect([this]() {
if (active_ != pendingActive_) {
active_ = pendingActive_;
parent_->refresh();
}
}));
conns_.emplace_back(window_->appId().connect([this](const char *appId) {
if (appId_ != appId) {
appId_ = appId;
parent_->refresh();
}
}));
setup_ = true;
}

private:
bool setup_ = false;
CosmicAppMonitor *parent_;
bool pendingActive_ = false;
bool active_ = false;
std::string appId_;
std::unique_ptr<wayland::ExtForeignToplevelHandleV1> window_;
std::unique_ptr<wayland::ZcosmicToplevelHandleV1> cosmicWindow_;
std::string key_;
std::list<ScopedConnection> conns_;
};

CosmicAppMonitor::CosmicAppMonitor(wayland::Display *display) {
display->requestGlobals<wayland::ExtForeignToplevelListV1>();
display->requestGlobalsWithMinimalVersion<wayland::ZcosmicToplevelInfoV1>(
2);

globalConn_ = display->globalCreated().connect(
[this](const std::string &name, const std::shared_ptr<void> &global) {
if (name == wayland::ExtForeignToplevelListV1::interface) {
setExtForeignToplevelList(
static_cast<wayland::ExtForeignToplevelListV1 *>(
global.get()));
} else if (name == wayland::ZcosmicToplevelInfoV1::interface) {
setCosmicToplevelInfo(
static_cast<wayland::ZcosmicToplevelInfoV1 *>(
global.get()));
}
});

if (auto list = display->getGlobal<wayland::ExtForeignToplevelListV1>()) {
setExtForeignToplevelList(list.get());
}
if (auto info = display->getGlobal<wayland::ZcosmicToplevelInfoV1>()) {
setCosmicToplevelInfo(info.get());
}
}

CosmicAppMonitor::~CosmicAppMonitor() = default;

bool CosmicAppMonitor::isAvailable() const {
return toplevelConn_.connected() && info_;
}

void CosmicAppMonitor::setExtForeignToplevelList(
wayland::ExtForeignToplevelListV1 *list) {
toplevelConn_ = list->toplevel().connect(
[this](wayland::ExtForeignToplevelHandleV1 *handle) {
windows_[handle] = std::make_unique<CosmicWindow>(this, handle);
handle->closed().connect([this, handle]() { remove(handle); });
});
}

void CosmicAppMonitor::setCosmicToplevelInfo(
wayland::ZcosmicToplevelInfoV1 *info) {
info_ = info;
for (auto &[_, window] : windows_) {
window->setup(info_);
}
}

void CosmicAppMonitor::remove(wayland::ExtForeignToplevelHandleV1 *handle) {
windows_.erase(handle);
refresh();
}

void CosmicAppMonitor::refresh() {
std::unordered_map<std::string, std::string> state;
std::optional<std::string> focus;
for (const auto &[_, wlrWindow] : windows_) {
if (!wlrWindow->appId().empty()) {
auto iter = state.emplace(wlrWindow->key(), wlrWindow->appId());
if (wlrWindow->active() && !focus && iter.second) {
focus = iter.first->first;
}
}
}
appUpdated(state, focus);
}

} // namespace fcitx
54 changes: 54 additions & 0 deletions src/frontend/waylandim/cosmicappmonitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* SPDX-FileCopyrightText: 2022~2022 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
*/
#ifndef _FCITX5_FRONTEND_WAYLANDIM_COSMICAPPMONITOR_H_
#define _FCITX5_FRONTEND_WAYLANDIM_COSMICAPPMONITOR_H_

#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include "fcitx-utils/signals.h"
#include "fcitx-wayland/core/display.h"
#include "appmonitor.h"
#include "zcosmic_toplevel_info_v1.h"

namespace fcitx {
namespace wayland {
class ExtForeignToplevelListV1;
class ExtForeignToplevelHandleV1;
} // namespace wayland
class CosmicWindow;

class CosmicAppMonitor : public AppMonitor {
public:
CosmicAppMonitor(wayland::Display *display);
~CosmicAppMonitor() override;

bool isAvailable() const override;

void setExtForeignToplevelList(wayland::ExtForeignToplevelListV1 *list);
void setCosmicToplevelInfo(wayland::ZcosmicToplevelInfoV1 *info);

void remove(wayland::ExtForeignToplevelHandleV1 *handle);
void refresh();

auto *info() const { return info_; }

private:
void setup();
ScopedConnection globalConn_;
ScopedConnection toplevelConn_;
std::unordered_map<wayland::ExtForeignToplevelHandleV1 *,
std::unique_ptr<CosmicWindow>>
windows_;
std::unordered_map<std::string, uint32_t> appState_;
wayland::ZcosmicToplevelInfoV1 *info_ = nullptr;
};

} // namespace fcitx

#endif // _FCITX5_FRONTEND_WAYLANDIM_COSMICAPPMONITOR_H_
19 changes: 12 additions & 7 deletions src/frontend/waylandim/waylandim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "waylandim.h"
#include <memory>
#include <string>
#include <utility>
#include "fcitx-utils/log.h"
#include "fcitx-utils/misc_p.h"
#include "fcitx/addonfactory.h"
Expand All @@ -17,6 +16,7 @@
#include "fcitx/instance.h"
#include "fcitx/misc_p.h"
#include "appmonitor.h"
#include "cosmicappmonitor.h"
#include "display.h"
#include "plasmaappmonitor.h"
#include "virtualinputcontext.h"
Expand Down Expand Up @@ -100,16 +100,21 @@ AggregatedAppMonitor *WaylandIMModule::appMonitor(const std::string &display) {
auto *display = static_cast<wayland::Display *>(
wl_display_get_user_data(displayIter->second));

auto plasmaMonitor = std::make_unique<PlasmaAppMonitor>(display);
auto wlrMonitor = std::make_unique<WlrAppMonitor>(display);
appMonitorPtr = std::make_unique<AggregatedAppMonitor>();
if (getDesktopType() == DesktopType::KDE5 ||
getDesktopType() == DesktopType::KDE6) {
appMonitorPtr->addSubMonitor(std::move(plasmaMonitor));
appMonitorPtr->addSubMonitor(std::move(wlrMonitor));
appMonitorPtr->addSubMonitor(
std::make_unique<PlasmaAppMonitor>(display));
appMonitorPtr->addSubMonitor(
std::make_unique<WlrAppMonitor>(display));
} else if (getDesktopType() == DesktopType::Cosmic) {
appMonitorPtr->addSubMonitor(
std::make_unique<CosmicAppMonitor>(display));
} else {
appMonitorPtr->addSubMonitor(std::move(wlrMonitor));
appMonitorPtr->addSubMonitor(std::move(plasmaMonitor));
appMonitorPtr->addSubMonitor(
std::make_unique<WlrAppMonitor>(display));
appMonitorPtr->addSubMonitor(
std::make_unique<PlasmaAppMonitor>(display));
}
}
return appMonitorPtr.get();
Expand Down
16 changes: 10 additions & 6 deletions src/frontend/waylandim/wlrappmonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ class WlrWindow {
}
}
}));
conns_.emplace_back(window->done().connect([this]() {
active_ = pendingActive_;
parent_->refresh();
conns_.emplace_back(window_->done().connect([this]() {
if (active_ != pendingActive_) {
active_ = pendingActive_;
parent_->refresh();
}
}));
conns_.emplace_back(window->appId().connect([this](const char *appId) {
appId_ = appId;
parent_->refresh();
conns_.emplace_back(window_->appId().connect([this](const char *appId) {
if (appId_ != appId) {
appId_ = appId;
parent_->refresh();
}
}));
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib/fcitx-wayland/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ add_subdirectory(viewporter)
add_subdirectory(tablet-v2)
add_subdirectory(cursor-shape)
#add_subdirectory(input-method-v3)
add_subdirectory(ext-foreign-toplevel-list)
add_subdirectory(cosmic-toplevel-info-unstable-v1)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
ecm_add_wayland_client_protocol(COSMIC_TOPLEVEL_INFO_PROTOCOL_SRCS
PROTOCOL ${CMAKE_CURRENT_SOURCE_DIR}/cosmic-toplevel-info-unstable-v1.xml
BASENAME cosmic-toplevel-info-unstable-v1)

# This two are irrelevant, but pulled in as dependency.
ecm_add_wayland_client_protocol(COSMIC_TOPLEVEL_INFO_PROTOCOL_SRCS
PROTOCOL ${WAYLAND_PROTOCOLS_PKGDATADIR}/staging/ext-workspace/ext-workspace-v1.xml
BASENAME ext-workspace-v1)

ecm_add_wayland_client_protocol(COSMIC_TOPLEVEL_INFO_PROTOCOL_SRCS
PROTOCOL ${CMAKE_CURRENT_SOURCE_DIR}/cosmic-workspace-unstable-v1.xml
BASENAME cosmic-workspace-unstable-v1)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

set(FCITX_WAYLAND_COSMIC_TOPLEVEL_INFO_PROTOCOL_SOURCES
zcosmic_toplevel_info_v1.cpp
zcosmic_toplevel_handle_v1.cpp
)

add_library(Fcitx5WaylandCosmicToplevelInfo STATIC ${FCITX_WAYLAND_COSMIC_TOPLEVEL_INFO_PROTOCOL_SOURCES} ${COSMIC_TOPLEVEL_INFO_PROTOCOL_SRCS})
set_target_properties(Fcitx5WaylandCosmicToplevelInfo PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
target_include_directories(Fcitx5WaylandCosmicToplevelInfo PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/..;${CMAKE_CURRENT_BINARY_DIR}>")
target_link_libraries(Fcitx5WaylandCosmicToplevelInfo
Wayland::Client Fcitx5::Utils Fcitx5::Wayland::Core
Fcitx5::Wayland::ExtForeignToplevelList)

add_library(Fcitx5::Wayland::CosmicToplevelInfo ALIAS Fcitx5WaylandCosmicToplevelInfo)

Loading
Loading