From 03d8a51c56f08eb559d8bfc4b4f5d917d7f373dc Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Tue, 15 Apr 2025 12:27:55 +0600 Subject: [PATCH 01/31] Detect Gnome and the presence of the app indicator extention to conditionally show the Hide to Tray menu item --- src/frontend/CMakeLists.txt | 3 +- src/frontend/PlatformConfig.cpp | 130 ++++++++++++++++++++++++++++++++ src/frontend/PlatformConfig.h | 41 ++++++++++ src/frontend/TopBar.cpp | 6 +- src/frontend/main.cpp | 4 + 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 src/frontend/PlatformConfig.cpp create mode 100644 src/frontend/PlatformConfig.h diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 7a1d6042..bbbd6799 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -17,7 +17,8 @@ set(SRC_MAIN main.cpp LayoutConverter.cpp LayoutConverter.h SingleInstance.cpp - AvroPhonetic.cpp) + AvroPhonetic.cpp + PlatformConfig.cpp) set(LINK_LIBS libShared Qt5::Widgets Qt5::Network ${ZSTD_LIBRARIES}) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp new file mode 100644 index 00000000..4c7d0fef --- /dev/null +++ b/src/frontend/PlatformConfig.cpp @@ -0,0 +1,130 @@ +/* + * OpenBangla Keyboard + * Copyright (C) 2025 Muhammad Mominul Huque + * + * 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 "PlatformConfig.h" + +DesktopEnvironment detectDesktopEnvironment() { + const QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + // Detect Windows/macOS first + #ifdef Q_OS_WIN + return DesktopEnvironment::Windows; + #endif + + #ifdef Q_OS_MACOS + return DesktopEnvironment::macOS; + #endif + + // Linux/UNIX detection + QStringList desktopEnvs { + env.value("XDG_CURRENT_DESKTOP"), + env.value("DESKTOP_SESSION"), + env.value("GDMSESSION"), + env.value("XDG_SESSION_DESKTOP") + }; + + const QString de = desktopEnvs.join(';').toLower(); + + if (de.contains("gnome")) return DesktopEnvironment::GNOME; + if (de.contains("kde")) return DesktopEnvironment::KDE; + if (de.contains("xfce")) return DesktopEnvironment::XFCE; + if (de.contains("lxde")) return DesktopEnvironment::LXDE; + if (de.contains("lxqt")) return DesktopEnvironment::LXQt; + if (de.contains("mate")) return DesktopEnvironment::MATE; + if (de.contains("cinnamon")) return DesktopEnvironment::Cinnamon; + if (de.contains("budgie")) return DesktopEnvironment::Budgie; + if (de.contains("unity")) return DesktopEnvironment::Unity; + if (de.contains("pantheon")) return DesktopEnvironment::Pantheon; + if (de.contains("deepin")) return DesktopEnvironment::Deepin; + + // Fallback session type detection + if (!env.value("WAYLAND_DISPLAY").isEmpty()) + return DesktopEnvironment::Wayland; + if (env.value("XDG_SESSION_TYPE").contains("x11")) + return DesktopEnvironment::X11; + + return DesktopEnvironment::Unknown; +} + +QString desktopEnvironmentToString(DesktopEnvironment de) { + switch(de) { + case DesktopEnvironment::Windows: return "Windows"; + case DesktopEnvironment::macOS: return "macOS"; + case DesktopEnvironment::GNOME: return "GNOME"; + case DesktopEnvironment::KDE: return "KDE"; + case DesktopEnvironment::XFCE: return "XFCE"; + case DesktopEnvironment::LXDE: return "LXDE"; + case DesktopEnvironment::LXQt: return "LXQt"; + case DesktopEnvironment::MATE: return "MATE"; + case DesktopEnvironment::Cinnamon: return "Cinnamon"; + case DesktopEnvironment::Budgie: return "Budgie"; + case DesktopEnvironment::Unity: return "Unity"; + case DesktopEnvironment::Pantheon: return "Pantheon"; + case DesktopEnvironment::Deepin: return "Deepin"; + case DesktopEnvironment::Wayland: return "Wayland"; + case DesktopEnvironment::X11: return "X11"; + default: return "Unknown"; + } +} + +bool isAppIndicatorEnabled() { + QProcess process; + process.setProgram("gnome-extensions"); + process.setArguments(QStringList() << "list" << "--enabled"); + + process.start(); + if (!process.waitForFinished()) { + qWarning() << "Failed to execute gnome-extensions command"; + return false; + } + + if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { + qWarning() << "Command execution failed"; + return false; + } + + const QString output = QString::fromUtf8(process.readAllStandardOutput()); + const QString targetUUID = "appindicatorsupport@rgcjonas.gmail.com"; + + // Check each line for exact match + const QStringList extensions = output.split('\n', Qt::SkipEmptyParts); + for (const QString &ext : extensions) { + if (ext.trimmed() == targetUUID) { + return true; + } + } + + return false; +} + +bool shouldShowTrayIcon() { + DesktopEnvironment de = detectDesktopEnvironment(); + if (de == DesktopEnvironment::GNOME) { + return isAppIndicatorEnabled(); + } else if(de == DesktopEnvironment::Pantheon) { + // Pantheon (Elementary OS) does not support AppIndicator + return false; + } + + return true; +} diff --git a/src/frontend/PlatformConfig.h b/src/frontend/PlatformConfig.h new file mode 100644 index 00000000..44d51755 --- /dev/null +++ b/src/frontend/PlatformConfig.h @@ -0,0 +1,41 @@ +/* + * OpenBangla Keyboard + * Copyright (C) 2025 Muhammad Mominul Huque + * + * 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 . + */ + + enum class DesktopEnvironment { + Unknown, + Windows, + macOS, + GNOME, + KDE, + XFCE, + LXDE, + LXQt, + MATE, + Cinnamon, + Budgie, + Unity, + Pantheon, + Deepin, + Wayland, + X11 +}; + +DesktopEnvironment detectDesktopEnvironment(); +QString desktopEnvironmentToString(DesktopEnvironment de); +bool isAppIndicatorEnabled(); +bool shouldShowTrayIcon(); diff --git a/src/frontend/TopBar.cpp b/src/frontend/TopBar.cpp index 3515d10e..99184485 100644 --- a/src/frontend/TopBar.cpp +++ b/src/frontend/TopBar.cpp @@ -33,6 +33,7 @@ #include "SettingsDialog.h" #include "LayoutConverter.h" #include "AutoCorrectDialog.h" +#include "PlatformConfig.h" #include "ui_TopBar.h" @@ -149,7 +150,10 @@ void TopBar::SetupPopupMenus() { connect(iconMenuAbout, SIGNAL(triggered()), this, SLOT(iconMenuAbout_clicked())); iconMenu = new QMenu(this); - iconMenu->addAction(iconMenuHide); + // Gnome Shell and Pantheon doesn't support tray icon natively. + if(shouldShowTrayIcon()) { + iconMenu->addAction(iconMenuHide); + } iconMenu->addAction(iconMenuLayout); iconMenu->addAction(iconMenuAbout); } diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index 7ed46d30..30e3f275 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -23,6 +23,8 @@ #include "TopBar.h" #include "SingleInstance.h" #include "Settings.h" +#include "PlatformConfig.h" +#include "Log.h" int main(int argc, char *argv[]) { if(qgetenv("XDG_SESSION_TYPE") == "wayland") { @@ -49,6 +51,8 @@ int main(int argc, char *argv[]) { parser.addOption(startInTray); parser.process(app); + LOG_DEBUG("Detected Desktop Environment: %s\n", desktopEnvironmentToString(detectDesktopEnvironment()).toStdString().c_str()); + // Prevent many instances of the app to be launched QString name = "com.openbangla.keyboard"; SingleInstance instance; From e440ccefb1f48516b92aa1d4f3add5ef4f2ddfb8 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Tue, 15 Apr 2025 23:30:16 +0600 Subject: [PATCH 02/31] Implement Gnome Input sources configuration --- src/frontend/PlatformConfig.cpp | 84 +++++++++++++++++++++++++++++++++ src/frontend/PlatformConfig.h | 2 + src/frontend/main.cpp | 2 + 3 files changed, 88 insertions(+) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 4c7d0fef..9571544a 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -20,8 +20,10 @@ #include #include #include +#include #include "PlatformConfig.h" +#include "Log.h" DesktopEnvironment detectDesktopEnvironment() { const QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); @@ -128,3 +130,85 @@ bool shouldShowTrayIcon() { return true; } + +QString getGnomeInputSources() { + QString key = "/org/gnome/desktop/input-sources/sources"; + + QProcess process; + process.start("dconf", {"read", key}); + process.waitForFinished(); + + if (process.exitCode() == 0) { + QString output = process.readAllStandardOutput().trimmed(); + return output; + } else { + LOG_ERROR("getGnomeInputSources Error: %s\n", process.readAllStandardError().toStdString().c_str()); + return ""; + } +} + +void setGnomeInputSources(QString value) { + QString key = "/org/gnome/desktop/input-sources/sources"; + + // Execute: dconf write "" + QProcess process; + process.start("dconf", {"write", key, value}); + process.waitForFinished(); + + if (process.exitCode() == 0) { + LOG_DEBUG("Successfully updated DConf settings!\n"); + } else { + LOG_ERROR("Error updating DConf settings: %s\n", process.readAllStandardError().toStdString().c_str()); + } +} + +void setupGnomeIME() { + QString sources = getGnomeInputSources(); + QStringList sourcesList; + + // It comes in an array of tuples like this: + // [('xkb', 'us'), ('ibus', 'OpenBangla')] + // So we need to do some preprocessing. + auto string = sources.replace("[", "").replace("]", ""); + auto index = string.indexOf("),"); + + while(index != -1) { + auto sub = string.mid(0, index + 1).trimmed(); + sourcesList.append(sub); + string.remove(0, index + 2); + index = string.indexOf("),"); + } + + if(!string.isEmpty()) { + sourcesList.append(string.trimmed()); + } + + for (const auto &source : sourcesList) { + LOG_DEBUG("Source: %s\n", source.toStdString().c_str()); + } + + // Check if OpenBangla exists in the sources + bool found = sourcesList.contains("('ibus', 'OpenBangla')"); + + if (found) { + LOG_DEBUG("OpenBangla found in sources\n"); + } else { + LOG_DEBUG("OpenBangla not found in sources\n"); + // Add OpenBangla to the sources + sourcesList.append("('ibus', 'OpenBangla')"); + auto sourcesString = QString("[%1]").arg(sourcesList.join(", ")); + setGnomeInputSources(sourcesString); + LOG_DEBUG("Added OpenBangla to sources\n"); + } +} + + +void setupInputSources() { + auto de = detectDesktopEnvironment(); + + if(de == DesktopEnvironment::GNOME) { + setupGnomeIME(); + } else { + LOG_DEBUG("Desktop Environment not supported for input source setup\n"); + } +} diff --git a/src/frontend/PlatformConfig.h b/src/frontend/PlatformConfig.h index 44d51755..396bb575 100644 --- a/src/frontend/PlatformConfig.h +++ b/src/frontend/PlatformConfig.h @@ -39,3 +39,5 @@ DesktopEnvironment detectDesktopEnvironment(); QString desktopEnvironmentToString(DesktopEnvironment de); bool isAppIndicatorEnabled(); bool shouldShowTrayIcon(); + +void setupInputSources(); diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index 30e3f275..e6eea7fa 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -53,6 +53,8 @@ int main(int argc, char *argv[]) { LOG_DEBUG("Detected Desktop Environment: %s\n", desktopEnvironmentToString(detectDesktopEnvironment()).toStdString().c_str()); + setupInputSources(); + // Prevent many instances of the app to be launched QString name = "com.openbangla.keyboard"; SingleInstance instance; From e3cb013ca57788613dfde877de25462bff6b7f2d Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Wed, 16 Apr 2025 08:47:09 +0600 Subject: [PATCH 03/31] Package the ibus and fcitx backends together pkg+ --- .github/workflows/deploy.yml | 10 ++-------- CMakeLists.txt | 18 +++++++++++++++--- tools/build.sh | 23 +++++------------------ 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 76b49c5c..28e6b704 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,23 +11,17 @@ jobs: strategy: matrix: # container: [ "ubuntu:18.04", "ubuntu:20.04", "ubuntu:22.04", "ubuntu:23.04", "debian:11", "fedora:37", "fedora:38", "archlinux:latest" ] - container: [ "ubuntu:20.04", "ubuntu:22.04", "ubuntu:24.04", "debian:11", "debian:12", "fedora:40", "fedora:41", "opensuse/tumbleweed" ] + container: [ "ubuntu:22.04", "ubuntu:24.04", "debian:11", "debian:12", "fedora:40", "fedora:41", "opensuse/tumbleweed" ] # this list should be updated from time to time by consulting these pages: # https://releases.ubuntu.com/ # https://wiki.debian.org/DebianReleases#Production_Releases # https://fedoraproject.org/wiki/Releases # https://en.wikipedia.org/wiki/OpenSUSE#Version_history - ime: [ "ibus", "fcitx" ] - # Some distributions doesn't have the required version of fcitx library, so we exclude them. - exclude: - - container: "ubuntu:20.04" - ime: "fcitx" runs-on: "ubuntu-latest" container: image: ${{ matrix.container }} env: DIST: ${{ matrix.container }} - IME: ${{ matrix.ime }} DEBIAN_FRONTEND: noninteractive steps: - name: install-git @@ -64,7 +58,7 @@ jobs: - name: upload-artifacts uses: actions/upload-artifact@v4 with: - name: pkg-${{ steps.sanitizer.outputs.sanitized_container }}-${{ matrix.ime }} + name: pkg-${{ steps.sanitizer.outputs.sanitized_container }} path: artifact release: diff --git a/CMakeLists.txt b/CMakeLists.txt index 18ed6e17..cdaa53be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,9 +66,10 @@ if(OS_LINUX) option(ENABLE_IBUS "Enable IBus support" OFF) option(ENABLE_FCITX "Enable Fcitx support" OFF) + option(ENABLE_BOTH "Enable both IBus and Fcitx support" OFF) - if((NOT ENABLE_IBUS) AND (NOT ENABLE_FCITX)) - message(FATAL_ERROR "Please set atleast ENABLE_IBUS or ENABLE_FCITX to be ON to build a backend") + if((NOT ENABLE_IBUS) AND (NOT ENABLE_FCITX) AND (NOT ENABLE_BOTH)) + message(FATAL_ERROR "Please set atleast ENABLE_IBUS or ENABLE_FCITX or ENABLE_BOTH to be ON to build a backend") endif() ## Find iBus ## @@ -81,6 +82,11 @@ if(OS_LINUX) find_package(Fcitx5Core 5.0.5 REQUIRED) endif() + if(ENABLE_BOTH) + pkg_check_modules(IBUS REQUIRED ibus-1.0) + find_package(Fcitx5Core 5.0.5 REQUIRED) + endif() + ## Find zstd ## pkg_check_modules(ZSTD REQUIRED libzstd) endif() @@ -132,12 +138,18 @@ if(ENABLE_IBUS) set(CPACK_DEBIAN_PACKAGE_DEPENDS "ibus (>= 1.5.1)") set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, ibus >= 1.5.1, ibus-libs >= 1.5.1, libzstd >= 1.3.3") list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component") -else() +elseif(ENABLE_FCITX) ## FCITX set(CPACK_PACKAGE_NAME "fcitx-openbangla") set(CPACK_DEBIAN_PACKAGE_DEPENDS "fcitx5 (>= 5.0.5)") set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, libzstd >= 1.3.3, fcitx5 >= 5.0.5") list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") +elseif(ENABLE_BOTH) + set(CPACK_PACKAGE_NAME "openbangla_keyboard") + # set(CPACK_DEBIAN_PACKAGE_DEPENDS "ibus (>= 1.5.1)") + # set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, libzstd >= 1.3.3") + list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component" "/usr/lib64/fcitx5" + "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") endif() set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${PROJECT_VERSION}-$ENV{DIST}") diff --git a/tools/build.sh b/tools/build.sh index 9fb12c6e..4ffb2010 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -1,19 +1,14 @@ #! /bin/bash RELEASE_VERSION=$(cat version.txt | head -n1) # follow cmake PACKAGE_FILE_NAME directive in main repo -RELEASE_STUB="${IME}-openbangla_${RELEASE_VERSION}-" +RELEASE_STUB="openbangla_keyboard_${RELEASE_VERSION}-" makeDeb () { RELEASE_FILENAME="${RELEASE_STUB}${DIST}.deb" - apt-get -y install build-essential pkg-config libibus-1.0-dev cmake libzstd-dev ninja-build curl qtbase5-dev qtbase5-dev-tools file + apt-get -y install build-essential pkg-config libibus-1.0-dev libfcitx5core-dev cmake libzstd-dev ninja-build curl qtbase5-dev qtbase5-dev-tools file curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain stable - if [[ "${IME}" == "ibus" ]]; then - cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_IBUS=ON -DCPACK_GENERATOR=DEB - else - apt-get -y install libfcitx5core-dev - cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_FCITX=ON -DCPACK_GENERATOR=DEB - fi + cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_BOTH=ON -DCPACK_GENERATOR=DEB ninja package -C /build RELEASE_FILE="/build/${RELEASE_FILENAME}" @@ -24,11 +19,7 @@ makeRpmFedora () { dnf install -y --allowerasing @buildsys-build cmake ibus-devel fcitx5-devel libzstd-devel qt5-qtdeclarative-devel ninja-build curl curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain stable - if [[ "${IME}" == "ibus" ]]; then - cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_IBUS=ON -DCPACK_GENERATOR=RPM - else - cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_FCITX=ON -DCPACK_GENERATOR=RPM - fi + cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_BOTH=ON -DCPACK_GENERATOR=RPM ninja package -C /build RELEASE_FILE="/build/${RELEASE_FILENAME}" @@ -42,11 +33,7 @@ makeRpmOpenSuse () { zypper install -y libQt5Core-devel libQt5Widgets-devel libQt5Network-devel libzstd-devel cmake ninja ibus-devel fcitx5-devel gcc curl rpm-build curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --default-toolchain stable - if [[ "${IME}" == "ibus" ]]; then - cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_IBUS=ON -DCPACK_GENERATOR=RPM - else - cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_FCITX=ON -DCPACK_GENERATOR=RPM - fi + cmake -H"$GITHUB_WORKSPACE" -B/build -GNinja -DCMAKE_INSTALL_PREFIX="/usr" -DENABLE_BOTH=ON -DCPACK_GENERATOR=RPM ninja package -C /build RELEASE_FILE="/build/${RELEASE_FILENAME}" From 4b690ef0590d6c23549546fc437bc8066423f0f6 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 19 Apr 2025 18:24:53 +0600 Subject: [PATCH 04/31] Support Ubuntu flavoured appindicator extension Add `mru-sources` too for Gnome configuration --- src/frontend/PlatformConfig.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 9571544a..b7627355 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -107,11 +107,13 @@ bool isAppIndicatorEnabled() { const QString output = QString::fromUtf8(process.readAllStandardOutput()); const QString targetUUID = "appindicatorsupport@rgcjonas.gmail.com"; + const QString targetUUID2 = "ubuntu-appindicators@ubuntu.com"; // Check each line for exact match const QStringList extensions = output.split('\n', Qt::SkipEmptyParts); for (const QString &ext : extensions) { - if (ext.trimmed() == targetUUID) { + auto trimmedExt = ext.trimmed(); + if (trimmedExt == targetUUID || trimmedExt == targetUUID2) { return true; } } @@ -147,9 +149,7 @@ QString getGnomeInputSources() { } } -void setGnomeInputSources(QString value) { - QString key = "/org/gnome/desktop/input-sources/sources"; - +void writeDConfSetting(QString key, QString value) { // Execute: dconf write "" QProcess process; process.start("dconf", {"write", key, value}); @@ -187,6 +187,8 @@ void setupGnomeIME() { LOG_DEBUG("Source: %s\n", source.toStdString().c_str()); } + QString firstSource = sourcesList.first(); + // Check if OpenBangla exists in the sources bool found = sourcesList.contains("('ibus', 'OpenBangla')"); @@ -197,7 +199,8 @@ void setupGnomeIME() { // Add OpenBangla to the sources sourcesList.append("('ibus', 'OpenBangla')"); auto sourcesString = QString("[%1]").arg(sourcesList.join(", ")); - setGnomeInputSources(sourcesString); + writeDConfSetting("/org/gnome/desktop/input-sources/sources", sourcesString); + writeDConfSetting("/org/gnome/desktop/input-sources/mru-sources", QString("[%1]").arg(firstSource)); LOG_DEBUG("Added OpenBangla to sources\n"); } } From 010f8cb76e40de72d4d5892ca3db32320fb58ead Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 19 Apr 2025 18:25:50 +0600 Subject: [PATCH 05/31] Change package name --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a34d33f6..ead446c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ elseif(ENABLE_FCITX) set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, libzstd >= 1.3.3, fcitx5 >= 5.0.5") list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") elseif(ENABLE_BOTH) - set(CPACK_PACKAGE_NAME "openbangla_keyboard") + set(CPACK_PACKAGE_NAME "openbangla-keyboard") # set(CPACK_DEBIAN_PACKAGE_DEPENDS "ibus (>= 1.5.1)") # set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, libzstd >= 1.3.3") list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component" "/usr/lib64/fcitx5" From 54cb627ad06e3431a0e13a2ae17fde77c66c875e Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 19 Apr 2025 18:51:25 +0600 Subject: [PATCH 06/31] Fix pkg name in build script --- tools/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build.sh b/tools/build.sh index 4ffb2010..aff20702 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -1,7 +1,7 @@ #! /bin/bash RELEASE_VERSION=$(cat version.txt | head -n1) # follow cmake PACKAGE_FILE_NAME directive in main repo -RELEASE_STUB="openbangla_keyboard_${RELEASE_VERSION}-" +RELEASE_STUB="openbangla-keyboard_${RELEASE_VERSION}-" makeDeb () { RELEASE_FILENAME="${RELEASE_STUB}${DIST}.deb" From 4727f8decf3434dc9eaef57715bc47ca901ece41 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 19 Apr 2025 19:05:31 +0600 Subject: [PATCH 07/31] Forgot to add both subdirectories for ENABLE_BOTH --- src/engine/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index ccfe1288..4b91db19 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -12,6 +12,11 @@ if (OS_LINUX) add_subdirectory(fcitx) endif() + if(ENABLE_BOTH) + add_subdirectory(ibus) + add_subdirectory(fcitx) + endif() + ## Include subdirectories add_subdirectory(riti) endif (OS_LINUX) From c44c64b1781137eb7b3a9f8f6ca10d8e75b07f57 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Wed, 4 Feb 2026 21:22:08 +0600 Subject: [PATCH 08/31] macOS platform specific Swift code integration support --- .vscode/c_cpp_properties.json | 1 + CMakeLists.txt | 19 +++--- cmake/AddSwift.cmake | 78 ++++++++++++++++++++++++ cmake/InitializeSwift.cmake | 89 ++++++++++++++++++++++++++++ src/frontend/CMakeLists.txt | 13 ++-- src/frontend/PlatformConfig.cpp | 8 +++ src/frontend/macOS/CMakeLists.txt | 9 +++ src/frontend/macOS/InputSource.swift | 6 ++ 8 files changed, 208 insertions(+), 15 deletions(-) create mode 100644 cmake/AddSwift.cmake create mode 100644 cmake/InitializeSwift.cmake create mode 100644 src/frontend/macOS/CMakeLists.txt create mode 100644 src/frontend/macOS/InputSource.swift diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index beac2882..2cea3c9f 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -8,6 +8,7 @@ "${workspaceRoot}" ], "defines": [], + "compileCommands": "build/compile_commands.json", "intelliSenseMode": "clang-x64", "browse": { "path": [ diff --git a/CMakeLists.txt b/CMakeLists.txt index b9a09d3b..0c7f8b11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.26...3.29) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") file(STRINGS "${CMAKE_SOURCE_DIR}/version.txt" VERSION_STRING LIMIT_COUNT 1 REGEX "^.+") @@ -17,7 +17,18 @@ if(NOT WIN32 AND NOT APPLE) include(CMakeCargo) endif() +if(APPLE) + enable_language(Swift) + + # Set up swiftrt.o and runtime library search paths + include(InitializeSwift) + # cmake/modules/AddSwift.cmake provides the function for creating the Swift to + # C++ bridging header + include(AddSwift) +endif() + find_package(Qt5 COMPONENTS Widgets Network REQUIRED) +find_package(zstd CONFIG REQUIRED) message(STATUS "Qt5 framework version: ${Qt5Core_VERSION}") @@ -86,14 +97,10 @@ if(OS_LINUX) pkg_check_modules(IBUS REQUIRED ibus-1.0) find_package(Fcitx5Core 5.0.5 REQUIRED) endif() - - ## Find zstd ## - pkg_check_modules(ZSTD REQUIRED libzstd) endif() # For Windows if(WIN32) - find_package(zstd CONFIG REQUIRED) set(PROJECT_DATADIR "$ENV{LOCALAPPDATA}\\OpenBangla" CACHE PATH "Path to Data Directory") set(BIN_DIR "${PROJECT_DATADIR}/bin") add_definitions(-DPROJECT_DATADIR="${PROJECT_DATADIR}") @@ -102,8 +109,6 @@ endif() # For Apple if(APPLE) - find_package(zstd CONFIG REQUIRED) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) set(CMAKE_INSTALL_PREFIX "/") endif() diff --git a/cmake/AddSwift.cmake b/cmake/AddSwift.cmake new file mode 100644 index 00000000..099273fd --- /dev/null +++ b/cmake/AddSwift.cmake @@ -0,0 +1,78 @@ +# This source file is part of the Swift open source project +# +# Copyright (c) 2023 Apple Inc. and the Swift project authors. +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See https://swift.org/LICENSE.txt for license information + + +# Generate the bridging header from Swift to C++ +# +# target: the name of the target to generate headers for. +# This target must build swift source files. +# header: the name of the header file to generate. +# +# NOTE: This logic will eventually be unstreamed into CMake. +function(_swift_generate_cxx_header target header) + if(NOT TARGET ${target}) + message(FATAL_ERROR "Target ${target} not defined.") + endif() + + if(NOT DEFINED CMAKE_Swift_COMPILER) + message(WARNING "Swift not enabled in project. Cannot generate headers for Swift files.") + return() + endif() + + cmake_parse_arguments(ARG "" "" "SEARCH_PATHS;MODULE_NAME" ${ARGN}) + + if(NOT ARG_MODULE_NAME) + set(target_module_name $) + set(ARG_MODULE_NAME $,${target_module_name},${target}>) + endif() + + if(ARG_SEARCH_PATHS) + list(TRANSFORM ARG_SEARCH_PATHS PREPEND "-I") + endif() + + if(APPLE AND CMAKE_OSX_SYSROOT) + set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}") + elseif(WIN32) + set(SDK_FLAGS "-sdk" "$ENV{SDKROOT}") + elseif(CMAKE_SYSROOT) + set(SDK_FLAGS "-sdk" "${CMAKE_SYSROOT}") + endif() + + cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR include + OUTPUT_VARIABLE base_path) + + cmake_path(APPEND base_path ${header} + OUTPUT_VARIABLE header_path) + + cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR "${ARG_MODULE_NAME}.emit-module.d" OUTPUT_VARIABLE depfile_path) + + set(_AllSources $,${CMAKE_CURRENT_SOURCE_DIR}>) + set(_SwiftSources $) + add_custom_command(OUTPUT ${header_path} + DEPENDS ${_SwiftSources} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND + ${CMAKE_Swift_COMPILER} -typecheck + ${ARG_SEARCH_PATHS} + ${_SwiftSources} + ${SDK_FLAGS} + -module-name "${ARG_MODULE_NAME}" + -cxx-interoperability-mode=default + -emit-clang-header-path ${header_path} + -emit-dependencies + DEPFILE "${depfile_path}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT + "Generating '${header_path}'" + COMMAND_EXPAND_LISTS) + + # Added to public interface for dependees to find. + target_include_directories(${target} PUBLIC ${base_path}) + # Added to the target to ensure target rebuilds if header changes and is used + # by sources in the target. + target_sources(${target} PRIVATE ${header_path}) +endfunction() diff --git a/cmake/InitializeSwift.cmake b/cmake/InitializeSwift.cmake new file mode 100644 index 00000000..c4fa2ea2 --- /dev/null +++ b/cmake/InitializeSwift.cmake @@ -0,0 +1,89 @@ +# This source file is part of the Swift open source project +# +# Copyright (c) 2023 Apple Inc. and the Swift project authors. +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See https://swift.org/LICENSE.txt for license information + +# Compute the name of the architecture directory on Windows from the CMake +# system processor name. +function(_swift_windows_arch_name output_variable_name target_arch) + if(NOT WIN32) + return() + endif() + + if("${target_arch}" STREQUAL "AMD64") + set("${output_variable_name}" "x86_64" PARENT_SCOPE) + elseif("${target_arch}" STREQUAL "ARM64") + set("${output_variable_name}" "aarch64" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown windows architecture: ${target_arch}") + endif() +endfunction() + +# Compute flags and search paths +# NOTE: This logic will eventually move to CMake +function(_setup_swift_paths) + # If we haven't set the swift library search paths, do that now + if(NOT SWIFT_LIBRARY_SEARCH_PATHS) + if(CMAKE_OSX_SYSROOT) + set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}") + endif() + + # Note: This does not handle cross-compiling correctly. + # To handle it correctly, we would need to pass the target triple and + # flags to this compiler invocation. + execute_process( + COMMAND ${CMAKE_Swift_COMPILER} ${SDK_FLAGS} -print-target-info + OUTPUT_VARIABLE SWIFT_TARGET_INFO + ) + + # extract search paths from swift driver response + string(JSON SWIFT_TARGET_PATHS GET ${SWIFT_TARGET_INFO} "paths") + + string(JSON SWIFT_TARGET_LIBRARY_PATHS GET ${SWIFT_TARGET_PATHS} "runtimeLibraryPaths") + string(JSON SWIFT_TARGET_LIBRARY_PATHS_LENGTH LENGTH ${SWIFT_TARGET_LIBRARY_PATHS}) + math(EXPR SWIFT_TARGET_LIBRARY_PATHS_LENGTH "${SWIFT_TARGET_LIBRARY_PATHS_LENGTH} - 1 ") + + string(JSON SWIFT_TARGET_LIBRARY_IMPORT_PATHS GET ${SWIFT_TARGET_PATHS} "runtimeLibraryImportPaths") + string(JSON SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH LENGTH ${SWIFT_TARGET_LIBRARY_IMPORT_PATHS}) + math(EXPR SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH "${SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH} - 1 ") + + string(JSON SWIFT_SDK_IMPORT_PATH ERROR_VARIABLE errno GET ${SWIFT_TARGET_PATHS} "sdkPath") + + foreach(JSON_ARG_IDX RANGE ${SWIFT_TARGET_LIBRARY_PATHS_LENGTH}) + string(JSON SWIFT_LIB GET ${SWIFT_TARGET_LIBRARY_PATHS} ${JSON_ARG_IDX}) + list(APPEND SWIFT_SEARCH_PATHS ${SWIFT_LIB}) + endforeach() + + foreach(JSON_ARG_IDX RANGE ${SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH}) + string(JSON SWIFT_LIB GET ${SWIFT_TARGET_LIBRARY_IMPORT_PATHS} ${JSON_ARG_IDX}) + list(APPEND SWIFT_SEARCH_PATHS ${SWIFT_LIB}) + endforeach() + + if(SWIFT_SDK_IMPORT_PATH) + list(APPEND SWIFT_SEARCH_PATHS ${SWIFT_SDK_IMPORT_PATH}) + endif() + + # Save the swift library search paths + set(SWIFT_LIBRARY_SEARCH_PATHS ${SWIFT_SEARCH_PATHS} CACHE FILEPATH "Swift driver search paths") + endif() + + link_directories(${SWIFT_LIBRARY_SEARCH_PATHS}) + + if(WIN32) + _swift_windows_arch_name(SWIFT_WIN_ARCH_DIR "${CMAKE_SYSTEM_PROCESSOR}") + set(SWIFT_SWIFTRT_FILE "$ENV{SDKROOT}/usr/lib/swift/windows/${SWIFT_WIN_ARCH_DIR}/swiftrt.obj") + add_link_options("$<$:${SWIFT_SWIFTRT_FILE}>") + elseif(NOT APPLE) + find_file(SWIFT_SWIFTRT_FILE + swiftrt.o + PATHS ${SWIFT_LIBRARY_SEARCH_PATHS} + NO_CACHE + REQUIRED + NO_DEFAULT_PATH) + add_link_options("$<$:${SWIFT_SWIFTRT_FILE}>") + endif() +endfunction() + +_setup_swift_paths() diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 39864542..73063f97 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -1,4 +1,4 @@ -include_directories(../shared 3rdParty) +include_directories(../shared 3rdParty macOS) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) @@ -21,19 +21,16 @@ set(SRC_MAIN main.cpp AvroPhonetic.cpp PlatformConfig.cpp) -set(LINK_LIBS libShared Qt5::Widgets Qt5::Network) - -if(OS_LINUX) - list(APPEND LINK_LIBS ${ZSTD_LIBRARIES}) -endif(OS_LINUX) +set(LINK_LIBS libShared Qt5::Widgets Qt5::Network zstd::libzstd) if(WIN32) - list(APPEND LINK_LIBS zstd::libzstd) set(CMAKE_WIN32_EXECUTABLE ON) endif(WIN32) if(APPLE) - list(APPEND LINK_LIBS zstd::libzstd) + add_subdirectory(macOS) + + list(APPEND LINK_LIBS macOS) list(APPEND LINK_LIBS "-framework Foundation") endif(APPLE) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index b7627355..46cee821 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -25,6 +25,10 @@ #include "PlatformConfig.h" #include "Log.h" +#ifdef Q_OS_MACOS +#include "macOS.h" +#endif + DesktopEnvironment detectDesktopEnvironment() { const QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); @@ -211,6 +215,10 @@ void setupInputSources() { if(de == DesktopEnvironment::GNOME) { setupGnomeIME(); + } else if(de == DesktopEnvironment::macOS) { + #ifdef Q_OS_MACOS + macOS::sayHello(); + #endif } else { LOG_DEBUG("Desktop Environment not supported for input source setup\n"); } diff --git a/src/frontend/macOS/CMakeLists.txt b/src/frontend/macOS/CMakeLists.txt new file mode 100644 index 00000000..fe643028 --- /dev/null +++ b/src/frontend/macOS/CMakeLists.txt @@ -0,0 +1,9 @@ + +add_library(macOS STATIC InputSource.swift) +set_target_properties(macOS PROPERTIES Swift_MODULE_NAME "macOS") +target_compile_options(macOS PUBLIC + "$<$:-cxx-interoperability-mode=default>") + +_swift_generate_cxx_header(macOS + macOS.h + SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/src/frontend/macOS/InputSource.swift b/src/frontend/macOS/InputSource.swift new file mode 100644 index 00000000..8c4e1efc --- /dev/null +++ b/src/frontend/macOS/InputSource.swift @@ -0,0 +1,6 @@ + +import Foundation + +public func sayHello() { + print("Hello from InputSource.swift!") +} From efa4389f25ec8e41928c71a4edb0642be3b4c4a9 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Fri, 6 Feb 2026 23:06:24 +0600 Subject: [PATCH 09/31] Initial auto-config on macOS --- CMakeLists.txt | 6 ++++ data/productbuild/postinstall | 10 ++++++ src/frontend/PlatformConfig.cpp | 3 +- src/frontend/macOS/InputSource.swift | 52 ++++++++++++++++++++++++++-- src/frontend/main.cpp | 17 +++++++++ 5 files changed, 85 insertions(+), 3 deletions(-) create mode 100755 data/productbuild/postinstall diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c7f8b11..f5cd5b04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ endif() if(APPLE) enable_language(Swift) + if("${CMAKE_Swift_COMPILER_VERSION}" VERSION_LESS 5.9) + message(FATAL_ERROR "Bidirectional C++ Interop requires Swift 5.9 or greater. Have ${CMAKE_Swift_COMPILER_VERSION}") + endif() + # Set up swiftrt.o and runtime library search paths include(InitializeSwift) # cmake/modules/AddSwift.cmake provides the function for creating the Swift to @@ -192,7 +196,9 @@ elseif(APPLE) set(CPACK_COMPONENTS_ALL IME GUI) set(CPACK_COMPONENT_IME_REQUIRED TRUE) set(CPACK_COMPONENT_GUI_REQUIRED TRUE) + set(CPACK_COMPONENT_GUI_DEPENDS IME) set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "FALSE") + set(CPACK_POSTFLIGHT_GUI_SCRIPT "${CMAKE_SOURCE_DIR}/data/productbuild/postinstall") set(CPACK_PRODUCTBUILD_RESOURCES_DIR "${CMAKE_SOURCE_DIR}/data/productbuild") set(CPACK_PRODUCTBUILD_BACKGROUND "installer.png") set(CPACK_PRODUCTBUILD_BACKGROUND_ALIGNMENT "left") diff --git a/data/productbuild/postinstall b/data/productbuild/postinstall new file mode 100755 index 00000000..abea68ee --- /dev/null +++ b/data/productbuild/postinstall @@ -0,0 +1,10 @@ +#!/bin/bash + +# Launch IME to register +open /Library/Input\ Methods/OpenBangla.app +sleep 1 + +# Run helper to enable it +/Applications/OpenBangla\ Keyboard.app/Contents/MacOS/OpenBangla\ Keyboard --help + +exit 0 \ No newline at end of file diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 46cee821..f29c7fec 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -217,7 +217,8 @@ void setupInputSources() { setupGnomeIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS - macOS::sayHello(); + bool enabled = macOS::getInputSourceEnabled(); + LOG_DEBUG("OpenBangla Input Source Enabled: %s\n", enabled ? "true" : "false"); #endif } else { LOG_DEBUG("Desktop Environment not supported for input source setup\n"); diff --git a/src/frontend/macOS/InputSource.swift b/src/frontend/macOS/InputSource.swift index 8c4e1efc..1de8d5ed 100644 --- a/src/frontend/macOS/InputSource.swift +++ b/src/frontend/macOS/InputSource.swift @@ -1,6 +1,54 @@ +import Carbon import Foundation -public func sayHello() { - print("Hello from InputSource.swift!") +let bundleID = "org.openbangla.inputmethod.keyboard" + +func getInputSource() -> TISInputSource? { + // Create properties to find your specific input source + let properties: [CFString: Any] = [ + kTISPropertyBundleID: bundleID + ] + + guard let sourceList = TISCreateInputSourceList(properties as CFDictionary, false)?.takeRetainedValue() as? [TISInputSource], + let inputSource = sourceList.first else { + NSLog("Error: Could not find OpenBangla input source") + return nil + } + + return inputSource +} + +public func getInputSourceEnabled() -> Bool { + guard let inputSource = getInputSource() else { + return false + } + + let isEnabled = TISGetInputSourceProperty(inputSource, kTISPropertyInputSourceIsEnabled) + + if let enabled = isEnabled, Unmanaged.fromOpaque(enabled).takeUnretainedValue() == kCFBooleanTrue { + return true + } + + return false +} + +public func setupOpenBanglaInputSource() { + guard let inputSource = getInputSource() else { + return + } + + let enableStatus = TISEnableInputSource(inputSource) + if enableStatus != noErr { + NSLog("Error: Failed to enable input source: \(enableStatus)") + return + } + + // let selectStatus = TISSelectInputSource(inputSource) + // if selectStatus != noErr { + // print("Failed to select input source: \(selectStatus)") + // return + // } + + NSLog("OpenBangla IME enabled!") } diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index cdd26902..2ab750ed 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -27,6 +27,10 @@ #include "Log.h" #include "FileSystem.h" +#ifdef Q_OS_MACOS + #include "macOS.h" +#endif + int main(int argc, char *argv[]) { QApplication app(argc, argv); gUserFolders = new UserFolders(); @@ -43,8 +47,21 @@ int main(int argc, char *argv[]) { QCommandLineOption startInTray("tray","Start in tray"); parser.addOption(darkIcon); parser.addOption(startInTray); + + #ifdef Q_OS_MACOS + QCommandLineOption setTIS("setup-macos","Setup macOS input source"); + parser.addOption(setTIS); + #endif + parser.process(app); + #ifdef Q_OS_MACOS + if(parser.isSet(setTIS)) { + macOS::setupOpenBanglaInputSource(); + return 0; + } + #endif + LOG_DEBUG("Detected Desktop Environment: %s\n", desktopEnvironmentToString(detectDesktopEnvironment()).toStdString().c_str()); setupInputSources(); From e829d869c1554ec724ed48c1a182c35b4cc7ae4f Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 7 Feb 2026 00:31:40 +0600 Subject: [PATCH 10/31] Fix code signature invalidation during packaging --- CMakeLists.txt | 14 +++++++++++++- cmake/CPack.distribution.dist.in | 24 ++++++++++++++++++++++++ src/frontend/CMakeLists.txt | 8 ++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 cmake/CPack.distribution.dist.in diff --git a/CMakeLists.txt b/CMakeLists.txt index f5cd5b04..b844e38a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,14 @@ endif() if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) set(CMAKE_INSTALL_PREFIX "/") + + # Determine host architectures for the .pkg installer distribution. + # Without hostArchitectures, macOS assumes x86_64 and prompts for Rosetta. + if(CMAKE_OSX_ARCHITECTURES) + string(REPLACE ";" "," CPACK_HOST_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") + else() + set(CPACK_HOST_ARCHITECTURES "${CMAKE_SYSTEM_PROCESSOR}") + endif() endif() add_subdirectory(src/engine) @@ -148,7 +156,11 @@ endif() set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") -set(CPACK_STRIP_FILES TRUE) +if(NOT APPLE) + # Stripping on macOS invalidates ad-hoc code signatures, causing + # installed apps to be killed by the system. + set(CPACK_STRIP_FILES TRUE) +endif() set(CPACK_PRODUCTBUILD_IDENTITY_NAME "" CACHE STRING "Code signing identity for productbuild") set(CPACK_PRODUCTBUILD_KEYCHAIN_PATH "" CACHE STRING "Keychain path for code signing") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://openbangla.org/") diff --git a/cmake/CPack.distribution.dist.in b/cmake/CPack.distribution.dist.in new file mode 100644 index 00000000..c14d89ef --- /dev/null +++ b/cmake/CPack.distribution.dist.in @@ -0,0 +1,24 @@ + + + @CPACK_PACKAGE_NAME@ + + + + + + + + + + + + + + file:./Contents/Packages/@CPACK_PACKAGE_FILE_NAME@-GUI.pkg + + + + file:./Contents/Packages/@CPACK_PACKAGE_FILE_NAME@-IME.pkg + + + diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 73063f97..66b638bb 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -119,8 +119,12 @@ if(OS_LINUX) endif() if(APPLE) - install(TARGETS openbangla-gui - BUNDLE DESTINATION "Applications" + # Install the bundle as a directory rather than a target to prevent + # install_name_tool from modifying the binary and invalidating the + # code signature applied after macdeployqt. + install(DIRECTORY "$" + DESTINATION "Applications" + USE_SOURCE_PERMISSIONS COMPONENT GUI ) endif() From f964fe48d97c14ef06b776b220a9b3bc408518b8 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 17:09:49 +0600 Subject: [PATCH 11/31] Conditional dependencies for deb and rpm packages pkg+ --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b844e38a..73bceaea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,8 +194,11 @@ elseif(ENABLE_FCITX) list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") elseif(ENABLE_BOTH) set(CPACK_PACKAGE_NAME "openbangla-keyboard") - # set(CPACK_DEBIAN_PACKAGE_DEPENDS "ibus (>= 1.5.1)") - # set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, libzstd >= 1.3.3") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "fcitx5 (>= 5.0.5) | ibus (>= 1.5.1)") + set(CPACK_RPM_PACKAGE_REQUIRES + "(ibus >= 1.5.1 if gnome-shell else fcitx5 >= 5.0.5); (gnome-shell-extension-appindicator if gnome-shell)" + "qt5-qtbase >= 5.15.0, libzstd >= 1.3.3" + ) list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component" "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") elseif(APPLE) From 872a8b590b5127d57eab96f0632688761b74b3ed Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 17:26:37 +0600 Subject: [PATCH 12/31] fix build pkg+ --- .github/workflows/ci.yml | 6 +++--- CMakeLists.txt | 2 +- src/frontend/CMakeLists.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e0a4b12..e6e0c362 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_IBUS=ON -DENABLE_FCITX=ON + cmake .. -DENABLE_BOTH=ON make build-macos: @@ -44,7 +44,7 @@ jobs: submodules: recursive - name: install-deps - run: brew install cmake qt@5 zstd + run: brew install cmake qt@5 zstd ninja - name: setup-qt run: echo "$(brew --prefix qt@5)/bin" >> $GITHUB_PATH @@ -53,6 +53,6 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5);$(brew --prefix zstd)" + cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5);$(brew --prefix zstd)" -GNinja make diff --git a/CMakeLists.txt b/CMakeLists.txt index 73bceaea..1bed3aee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(APPLE) endif() find_package(Qt5 COMPONENTS Widgets Network REQUIRED) -find_package(zstd CONFIG REQUIRED) +find_package(Zstd REQUIRED) message(STATUS "Qt5 framework version: ${Qt5Core_VERSION}") diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 66b638bb..cea9759e 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -21,7 +21,7 @@ set(SRC_MAIN main.cpp AvroPhonetic.cpp PlatformConfig.cpp) -set(LINK_LIBS libShared Qt5::Widgets Qt5::Network zstd::libzstd) +set(LINK_LIBS libShared Qt5::Widgets Qt5::Network zstd::libzstd_shared) if(WIN32) set(CMAKE_WIN32_EXECUTABLE ON) From 4b6fc0ec337b0cf1662e03039f540aa15e803cfd Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 17:37:02 +0600 Subject: [PATCH 13/31] Fix build --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 8 +++++++- src/frontend/CMakeLists.txt | 9 ++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6e0c362..3bc99945 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,5 +54,5 @@ jobs: mkdir build cd build cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5);$(brew --prefix zstd)" -GNinja - make + ninja diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bed3aee..d36c429c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,6 @@ if(APPLE) endif() find_package(Qt5 COMPONENTS Widgets Network REQUIRED) -find_package(Zstd REQUIRED) message(STATUS "Qt5 framework version: ${Qt5Core_VERSION}") @@ -86,6 +85,9 @@ if(OS_LINUX) if((NOT ENABLE_IBUS) AND (NOT ENABLE_FCITX) AND (NOT ENABLE_BOTH)) message(FATAL_ERROR "Please set atleast ENABLE_IBUS or ENABLE_FCITX or ENABLE_BOTH to be ON to build a backend") endif() + + ## Find zstd ## + pkg_check_modules(ZSTD REQUIRED libzstd) ## Find iBus ## if(ENABLE_IBUS) @@ -105,6 +107,8 @@ endif() # For Windows if(WIN32) + find_package(zstd CONFIG REQUIRED) + set(PROJECT_DATADIR "$ENV{LOCALAPPDATA}\\OpenBangla" CACHE PATH "Path to Data Directory") set(BIN_DIR "${PROJECT_DATADIR}/bin") add_definitions(-DPROJECT_DATADIR="${PROJECT_DATADIR}") @@ -113,6 +117,8 @@ endif() # For Apple if(APPLE) + find_package(zstd CONFIG REQUIRED) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) set(CMAKE_INSTALL_PREFIX "/") diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index cea9759e..3a01b6a4 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -21,10 +21,16 @@ set(SRC_MAIN main.cpp AvroPhonetic.cpp PlatformConfig.cpp) -set(LINK_LIBS libShared Qt5::Widgets Qt5::Network zstd::libzstd_shared) +set(LINK_LIBS libShared Qt5::Widgets Qt5::Network) + +if(OS_LINUX) + list(APPEND LINK_LIBS ${ZSTD_LIBRARIES}) +endif(OS_LINUX) if(WIN32) set(CMAKE_WIN32_EXECUTABLE ON) + + list(APPEND LINK_LIBS zstd::libzstd) endif(WIN32) if(APPLE) @@ -32,6 +38,7 @@ if(APPLE) list(APPEND LINK_LIBS macOS) list(APPEND LINK_LIBS "-framework Foundation") + list(APPEND LINK_LIBS zstd::libzstd) endif(APPLE) if(APPLE) From d4ee4ad3197323ac455ffe5379251d929b013c80 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 17:43:29 +0600 Subject: [PATCH 14/31] test pkg build pkg+ --- src/frontend/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 3a01b6a4..f2686485 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -36,9 +36,7 @@ endif(WIN32) if(APPLE) add_subdirectory(macOS) - list(APPEND LINK_LIBS macOS) - list(APPEND LINK_LIBS "-framework Foundation") - list(APPEND LINK_LIBS zstd::libzstd) + list(APPEND LINK_LIBS macOS "-framework Foundation" zstd::libzstd) endif(APPLE) if(APPLE) From af9d2c47543e8719a10c233e69700a7184ee165c Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 19:19:16 +0600 Subject: [PATCH 15/31] pkg+ --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d36c429c..05c3993f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.26...3.29) +cmake_minimum_required(VERSION 3.25...3.29) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") file(STRINGS "${CMAKE_SOURCE_DIR}/version.txt" VERSION_STRING LIMIT_COUNT 1 REGEX "^.+") From 040008ed18c4a0bb34adbbb704b3c95d3340ce9d Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 19:31:38 +0600 Subject: [PATCH 16/31] pkg+ --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05c3993f..26f4848e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.25...3.29) +cmake_minimum_required(VERSION 3.18...3.29) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") file(STRINGS "${CMAKE_SOURCE_DIR}/version.txt" VERSION_STRING LIMIT_COUNT 1 REGEX "^.+") From 633f887c1fc061d54d41f125ae688cffa677cd61 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 19:39:08 +0600 Subject: [PATCH 17/31] pkg+ --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 26f4848e..28954136 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,8 +202,7 @@ elseif(ENABLE_BOTH) set(CPACK_PACKAGE_NAME "openbangla-keyboard") set(CPACK_DEBIAN_PACKAGE_DEPENDS "fcitx5 (>= 5.0.5) | ibus (>= 1.5.1)") set(CPACK_RPM_PACKAGE_REQUIRES - "(ibus >= 1.5.1 if gnome-shell else fcitx5 >= 5.0.5); (gnome-shell-extension-appindicator if gnome-shell)" - "qt5-qtbase >= 5.15.0, libzstd >= 1.3.3" + "(ibus >= 1.5.1 if gnome-shell else fcitx5 >= 5.0.5), (gnome-shell-extension-appindicator if gnome-shell), qt5-qtbase >= 5.15.0, libzstd >= 1.3.3" ) list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component" "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") From df94cc8b1613c2637c38b1ceb1fb5d4241ccc0c6 Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 20:35:24 +0600 Subject: [PATCH 18/31] pkg+ --- tools/build.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/build.sh b/tools/build.sh index aff20702..8b238284 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -26,8 +26,6 @@ makeRpmFedora () { } makeRpmOpenSuse () { - # Replace '/' with '-' - export DIST=$(echo "$DIST" | tr '/' '-') RELEASE_FILENAME="${RELEASE_STUB}${DIST}.rpm" zypper install -y libQt5Core-devel libQt5Widgets-devel libQt5Network-devel libzstd-devel cmake ninja ibus-devel fcitx5-devel gcc curl rpm-build From 7a6ea32753e29ac97379b8ed0d56dda6637fb17d Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 20:44:58 +0600 Subject: [PATCH 19/31] pkg+ --- CMakeLists.txt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28954136..9cf4aa42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,20 +153,21 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenBangla Team " set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/data/Readme.txt") set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/data/Readme.txt") if(APPLE) + set(CPACK_PACKAGE_NAME "OpenBangla Keyboard") # macOS productbuild requires license files with .txt, .rtf, .rtfd, or .html extension configure_file("${CMAKE_SOURCE_DIR}/LICENSE" "${CMAKE_BINARY_DIR}/LICENSE.txt" COPYONLY) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/LICENSE.txt") else() + set(CPACK_PACKAGE_NAME "openbangla-keyboard") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") -endif() -set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") -set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") -if(NOT APPLE) + # Stripping on macOS invalidates ad-hoc code signatures, causing # installed apps to be killed by the system. set(CPACK_STRIP_FILES TRUE) endif() +set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") set(CPACK_PRODUCTBUILD_IDENTITY_NAME "" CACHE STRING "Code signing identity for productbuild") set(CPACK_PRODUCTBUILD_KEYCHAIN_PATH "" CACHE STRING "Keychain path for code signing") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://openbangla.org/") @@ -188,18 +189,17 @@ set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${PROJECT_VERSION}-$ENV{DIST} # Configure CPack on the basis of which backend we are building for. if(ENABLE_IBUS) ## IBUS - set(CPACK_PACKAGE_NAME "ibus-openbangla") + # set(CPACK_PACKAGE_NAME "ibus-openbangla") set(CPACK_DEBIAN_PACKAGE_DEPENDS "ibus (>= 1.5.1)") set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, ibus >= 1.5.1, ibus-libs >= 1.5.1, libzstd >= 1.3.3") list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component") elseif(ENABLE_FCITX) ## FCITX - set(CPACK_PACKAGE_NAME "fcitx-openbangla") + # set(CPACK_PACKAGE_NAME "fcitx-openbangla") set(CPACK_DEBIAN_PACKAGE_DEPENDS "fcitx5 (>= 5.0.5)") set(CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9.0, libzstd >= 1.3.3, fcitx5 >= 5.0.5") list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") elseif(ENABLE_BOTH) - set(CPACK_PACKAGE_NAME "openbangla-keyboard") set(CPACK_DEBIAN_PACKAGE_DEPENDS "fcitx5 (>= 5.0.5) | ibus (>= 1.5.1)") set(CPACK_RPM_PACKAGE_REQUIRES "(ibus >= 1.5.1 if gnome-shell else fcitx5 >= 5.0.5), (gnome-shell-extension-appindicator if gnome-shell), qt5-qtbase >= 5.15.0, libzstd >= 1.3.3" @@ -207,7 +207,6 @@ elseif(ENABLE_BOTH) list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/ibus" "/usr/share/ibus/component" "/usr/lib64/fcitx5" "/usr/share/fcitx5" "/usr/share/fcitx5/inputmethod" "/usr/share/fcitx5/addon") elseif(APPLE) - set(CPACK_PACKAGE_NAME "OpenBangla Keyboard") set(CPACK_PACKAGE_VENDOR "OpenBangla") set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") set(CPACK_PACKAGE_FILE_NAME "OpenBangla-Keyboard-${PROJECT_VERSION}") From ce8b378d1793b319732d61190e6ed09827d2c12c Mon Sep 17 00:00:00 2001 From: Muhammad Mominul Huque Date: Sat, 14 Feb 2026 21:02:07 +0600 Subject: [PATCH 20/31] pkg+ --- tools/build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/build.sh b/tools/build.sh index 8b238284..aff20702 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -26,6 +26,8 @@ makeRpmFedora () { } makeRpmOpenSuse () { + # Replace '/' with '-' + export DIST=$(echo "$DIST" | tr '/' '-') RELEASE_FILENAME="${RELEASE_STUB}${DIST}.rpm" zypper install -y libQt5Core-devel libQt5Widgets-devel libQt5Network-devel libzstd-devel cmake ninja ibus-devel fcitx5-devel gcc curl rpm-build From c6a16c802dc608d27a45476df5433d464d278d80 Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 7 Mar 2026 01:07:45 +0600 Subject: [PATCH 21/31] Implement auto-config for KDE Fcitx --- src/frontend/PlatformConfig.cpp | 209 ++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index f29c7fec..86b1bcd4 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -21,6 +21,10 @@ #include #include #include +#include +#include +#include +#include #include "PlatformConfig.h" #include "Log.h" @@ -210,11 +214,216 @@ void setupGnomeIME() { } +QString findFcitx5WaylandLauncher() { + QStringList candidates = { + "/usr/share/applications/fcitx5-wayland-launcher.desktop", + "/usr/local/share/applications/fcitx5-wayland-launcher.desktop", + }; + + // Also check XDG data dirs + QString xdgDataDirs = QProcessEnvironment::systemEnvironment().value("XDG_DATA_DIRS", "/usr/share:/usr/local/share"); + for (const auto &dir : xdgDataDirs.split(':')) { + QString path = dir + "/applications/fcitx5-wayland-launcher.desktop"; + if (!candidates.contains(path)) { + candidates.append(path); + } + } + + for (const auto &path : candidates) { + if (QFile::exists(path)) { + return path; + } + } + + return ""; +} + +void setupKdeVirtualKeyboard() { + QString launcherPath = findFcitx5WaylandLauncher(); + if (launcherPath.isEmpty()) { + LOG_DEBUG("Fcitx5 Wayland launcher desktop file not found\n"); + return; + } + + // Read current virtual keyboard setting + QProcess readProcess; + readProcess.start("kreadconfig6", {"--file", "kwinrc", "--group", "Wayland", "--key", "InputMethod"}); + readProcess.waitForFinished(); + + QString currentValue = readProcess.readAllStandardOutput().trimmed(); + + if (currentValue == launcherPath) { + LOG_DEBUG("KDE virtual keyboard already set to Fcitx5\n"); + return; + } + + // Set Fcitx5 as the virtual keyboard + QProcess writeProcess; + writeProcess.start("kwriteconfig6", {"--file", "kwinrc", "--group", "Wayland", "--key", "InputMethod", launcherPath}); + writeProcess.waitForFinished(); + + if (writeProcess.exitCode() == 0) { + LOG_DEBUG("Set KDE virtual keyboard to Fcitx5: %s\n", launcherPath.toStdString().c_str()); + } else { + LOG_ERROR("Failed to set KDE virtual keyboard: %s\n", writeProcess.readAllStandardError().toStdString().c_str()); + } +} + +bool addOpenBanglaToFcitx5ViaDBus() { + // Get current input method group info + QProcess getProcess; + getProcess.start("gdbus", {"call", "--session", + "--dest", "org.fcitx.Fcitx5", + "--object-path", "/controller", + "--method", "org.fcitx.Fcitx.Controller1.InputMethodGroupInfo", + "Default"}); + getProcess.waitForFinished(); + + if (getProcess.exitCode() != 0) { + return false; + } + + // Output format: ('us', [('keyboard-us', ''), ('openbangla', '')]) + QString output = getProcess.readAllStandardOutput().trimmed(); + + if (output.contains("'openbangla'")) { + LOG_DEBUG("OpenBangla already in Fcitx5 input method group\n"); + return true; + } + + // Parse the default layout from the output + // Format: ('layout', [...]) + QString defaultLayout = "us"; + int firstQuote = output.indexOf('\''); + int secondQuote = output.indexOf('\'', firstQuote + 1); + if (firstQuote >= 0 && secondQuote > firstQuote) { + defaultLayout = output.mid(firstQuote + 1, secondQuote - firstQuote - 1); + } + + // Parse the existing input methods array + // We need to reconstruct the array with openbangla added + int arrayStart = output.indexOf('['); + int arrayEnd = output.lastIndexOf(']'); + QString existingArray; + if (arrayStart >= 0 && arrayEnd > arrayStart) { + existingArray = output.mid(arrayStart, arrayEnd - arrayStart + 1); + } + + // Build new array: insert openbangla before the closing bracket + QString newArray; + if (existingArray.isEmpty() || existingArray == "[]") { + newArray = "[('keyboard-us', ''), ('openbangla', '')]"; + } else { + // Remove trailing ] and add openbangla + newArray = existingArray.left(existingArray.length() - 1) + ", ('openbangla', '')]"; + } + + QProcess setProcess; + setProcess.start("gdbus", {"call", "--session", + "--dest", "org.fcitx.Fcitx5", + "--object-path", "/controller", + "--method", "org.fcitx.Fcitx.Controller1.SetInputMethodGroupInfo", + "Default", defaultLayout, newArray}); + setProcess.waitForFinished(); + + if (setProcess.exitCode() == 0) { + LOG_DEBUG("Added OpenBangla to Fcitx5 input method group via DBus\n"); + return true; + } + + LOG_ERROR("Failed to add OpenBangla via DBus: %s\n", setProcess.readAllStandardError().toStdString().c_str()); + return false; +} + +void addOpenBanglaToFcitx5Profile() { + QString profilePath = QDir::homePath() + "/.config/fcitx5/profile"; + + // Ensure the directory exists + QDir().mkpath(QDir::homePath() + "/.config/fcitx5"); + + if (QFile::exists(profilePath)) { + // Read existing profile and check if openbangla is already present + QSettings profile(profilePath, QSettings::IniFormat); + + // Scan existing groups for openbangla + int itemCount = 0; + bool found = false; + + for (const auto &group : profile.childGroups()) { + if (group.startsWith("Groups/0/Items/")) { + itemCount++; + profile.beginGroup(group); + if (profile.value("Name").toString() == "openbangla") { + found = true; + } + profile.endGroup(); + } + } + + if (found) { + LOG_DEBUG("OpenBangla already in Fcitx5 profile\n"); + return; + } + + // Add openbangla as the next item + QString newGroup = QString("Groups/0/Items/%1").arg(itemCount); + profile.beginGroup(newGroup); + profile.setValue("Name", "openbangla"); + profile.setValue("Layout", ""); + profile.endGroup(); + profile.sync(); + + LOG_DEBUG("Added OpenBangla to existing Fcitx5 profile\n"); + } else { + // Create a new profile with keyboard-us and openbangla + QSettings profile(profilePath, QSettings::IniFormat); + + profile.beginGroup("Groups/0"); + profile.setValue("Name", "Default"); + profile.setValue("Default Layout", "us"); + profile.setValue("DefaultIM", "openbangla"); + profile.endGroup(); + + profile.beginGroup("Groups/0/Items/0"); + profile.setValue("Name", "keyboard-us"); + profile.setValue("Layout", ""); + profile.endGroup(); + + profile.beginGroup("Groups/0/Items/1"); + profile.setValue("Name", "openbangla"); + profile.setValue("Layout", ""); + profile.endGroup(); + + profile.beginGroup("GroupOrder"); + profile.setValue("0", "Default"); + profile.endGroup(); + + profile.sync(); + + LOG_DEBUG("Created new Fcitx5 profile with OpenBangla\n"); + } +} + +void setupFcitx5InputMethod() { + // Try DBus first (works when Fcitx5 is already running) + if (!addOpenBanglaToFcitx5ViaDBus()) { + LOG_DEBUG("Fcitx5 DBus not available, writing profile directly\n"); + addOpenBanglaToFcitx5Profile(); + } +} + +void setupKdeIME() { + setupKdeVirtualKeyboard(); + setupFcitx5InputMethod(); +} + void setupInputSources() { auto de = detectDesktopEnvironment(); if(de == DesktopEnvironment::GNOME) { setupGnomeIME(); + } else if(de == DesktopEnvironment::KDE) { + setupKdeIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS bool enabled = macOS::getInputSourceEnabled(); From 87a60cede8cbcd1330e2bb16c5b87dd0c0bc3651 Mon Sep 17 00:00:00 2001 From: Mominul Date: Sun, 8 Mar 2026 13:09:46 +0600 Subject: [PATCH 22/31] Implement fcitx5 autoconfig for Deepin OS --- src/frontend/PlatformConfig.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 86b1bcd4..07d78251 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -424,6 +424,8 @@ void setupInputSources() { setupGnomeIME(); } else if(de == DesktopEnvironment::KDE) { setupKdeIME(); + } else if(de == DesktopEnvironment::Deepin) { + setupFcitx5InputMethod(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS bool enabled = macOS::getInputSourceEnabled(); From a0e753254931529511a3cd0b0b7035468fdec279 Mon Sep 17 00:00:00 2001 From: Mominul Date: Mon, 23 Mar 2026 20:16:13 +0600 Subject: [PATCH 23/31] Fix autoconfig on mac --- src/frontend/macOS/InputSource.swift | 87 +++++++++++++++++----------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/src/frontend/macOS/InputSource.swift b/src/frontend/macOS/InputSource.swift index 1de8d5ed..da92bf40 100644 --- a/src/frontend/macOS/InputSource.swift +++ b/src/frontend/macOS/InputSource.swift @@ -1,54 +1,71 @@ - import Carbon import Foundation -let bundleID = "org.openbangla.inputmethod.keyboard" +private let bundleID = "org.openbangla.inputmethod.keyboard" +private let imeName = "OpenBangla" + +// MARK: - IME location -func getInputSource() -> TISInputSource? { - // Create properties to find your specific input source - let properties: [CFString: Any] = [ - kTISPropertyBundleID: bundleID +/// Returns the URL of the installed IME bundle, checking system-wide and +/// per-user Input Methods directories in that order. +private func locateIME() -> URL? { + let candidates = [ + URL(fileURLWithPath: "/Library/Input Methods/\(imeName).app"), + FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent("Library/Input Methods/\(imeName).app"), ] - - guard let sourceList = TISCreateInputSourceList(properties as CFDictionary, false)?.takeRetainedValue() as? [TISInputSource], - let inputSource = sourceList.first else { - NSLog("Error: Could not find OpenBangla input source") - return nil - } - - return inputSource + return candidates.first { FileManager.default.fileExists(atPath: $0.path) } } -public func getInputSourceEnabled() -> Bool { - guard let inputSource = getInputSource() else { - return false - } +// MARK: - TIS helpers - let isEnabled = TISGetInputSourceProperty(inputSource, kTISPropertyInputSourceIsEnabled) +/// Find the OpenBangla input source, **including disabled / not-yet-enabled +/// sources** (`includeAllInstalled: true`). +private func findInputSource() -> TISInputSource? { + let props = [kTISPropertyBundleID: bundleID] as CFDictionary + guard + let list = TISCreateInputSourceList(props, true)?.takeRetainedValue() as? [TISInputSource] + else { return nil } + return list.first +} - if let enabled = isEnabled, Unmanaged.fromOpaque(enabled).takeUnretainedValue() == kCFBooleanTrue { - return true - } +private func getBool(_ source: TISInputSource, _ key: CFString) -> Bool { + guard let ref = TISGetInputSourceProperty(source, key) else { return false } + return CFBooleanGetValue(unsafeBitCast(ref, to: CFBoolean.self)) +} - return false +// MARK: - Public API + +/// Returns `true` when the OpenBangla input source is installed and enabled. +public func getInputSourceEnabled() -> Bool { + guard let source = findInputSource() else { return false } + return getBool(source, kTISPropertyInputSourceIsEnabled) } +/// Registers and enables the OpenBangla input source. public func setupOpenBanglaInputSource() { - guard let inputSource = getInputSource() else { + if getInputSourceEnabled() { + NSLog("OpenBangla input source is already enabled.") return } - let enableStatus = TISEnableInputSource(inputSource) - if enableStatus != noErr { - NSLog("Error: Failed to enable input source: \(enableStatus)") + guard let imeURL = locateIME() else { + NSLog("Error: OpenBangla.app not found in any Input Methods directory.") return } - - // let selectStatus = TISSelectInputSource(inputSource) - // if selectStatus != noErr { - // print("Failed to select input source: \(selectStatus)") - // return - // } - - NSLog("OpenBangla IME enabled!") + + // Register the bundle so TIS can see it even before it is enabled. + TISRegisterInputSource(imeURL as CFURL) + + guard let source = findInputSource() else { + NSLog("Error: OpenBangla input source not found after registration (\(imeURL.path)).") + return + } + + let status = TISEnableInputSource(source) + if status == noErr { + NSLog("OpenBangla IME enabled.") + } else { + NSLog("Error: TISEnableInputSource failed with status \(status).") + } } From 9780087bd84e52617ac2de84409eb56655494225 Mon Sep 17 00:00:00 2001 From: Mominul Date: Mon, 23 Mar 2026 20:41:23 +0600 Subject: [PATCH 24/31] Fix postinstall script --- data/productbuild/postinstall | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/data/productbuild/postinstall b/data/productbuild/postinstall index abea68ee..b596d5fa 100755 --- a/data/productbuild/postinstall +++ b/data/productbuild/postinstall @@ -1,10 +1,6 @@ #!/bin/bash +set -e -# Launch IME to register -open /Library/Input\ Methods/OpenBangla.app -sleep 1 - -# Run helper to enable it -/Applications/OpenBangla\ Keyboard.app/Contents/MacOS/OpenBangla\ Keyboard --help +/Applications/OpenBangla\ Keyboard.app/Contents/MacOS/OpenBangla\ Keyboard --setup-macos exit 0 \ No newline at end of file From 1388961f93ba5ac1447b03a516e7d8ebb3581ccd Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 4 Apr 2026 16:24:18 +0600 Subject: [PATCH 25/31] Implement autoconfig for Cinnamon DE --- src/frontend/PlatformConfig.cpp | 40 +++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 07d78251..abf9c8b1 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -141,18 +141,15 @@ bool shouldShowTrayIcon() { return true; } -QString getGnomeInputSources() { - QString key = "/org/gnome/desktop/input-sources/sources"; - +QString readDConfKey(const QString &key) { QProcess process; process.start("dconf", {"read", key}); process.waitForFinished(); if (process.exitCode() == 0) { - QString output = process.readAllStandardOutput().trimmed(); - return output; + return process.readAllStandardOutput().trimmed(); } else { - LOG_ERROR("getGnomeInputSources Error: %s\n", process.readAllStandardError().toStdString().c_str()); + LOG_ERROR("readDConfKey(%s) Error: %s\n", key.toStdString().c_str(), process.readAllStandardError().toStdString().c_str()); return ""; } } @@ -170,14 +167,13 @@ void writeDConfSetting(QString key, QString value) { } } -void setupGnomeIME() { - QString sources = getGnomeInputSources(); +QStringList parseDConfInputSources(const QString &raw) { QStringList sourcesList; // It comes in an array of tuples like this: // [('xkb', 'us'), ('ibus', 'OpenBangla')] // So we need to do some preprocessing. - auto string = sources.replace("[", "").replace("]", ""); + auto string = QString(raw).replace("[", "").replace("]", ""); auto index = string.indexOf("),"); while(index != -1) { @@ -195,6 +191,13 @@ void setupGnomeIME() { LOG_DEBUG("Source: %s\n", source.toStdString().c_str()); } + return sourcesList; +} + +void setupGnomeIME() { + QString sources = readDConfKey("/org/gnome/desktop/input-sources/sources"); + QStringList sourcesList = parseDConfInputSources(sources); + QString firstSource = sourcesList.first(); // Check if OpenBangla exists in the sources @@ -213,6 +216,23 @@ void setupGnomeIME() { } } +void setupCinnamonIME() { + QString sources = readDConfKey("/org/cinnamon/desktop/input-sources/sources"); + QStringList sourcesList = parseDConfInputSources(sources); + + bool found = sourcesList.contains("('ibus', 'OpenBangla')"); + + if (found) { + LOG_DEBUG("[Cinnamon] OpenBangla found in sources\n"); + } else { + LOG_DEBUG("[Cinnamon] OpenBangla not found in sources\n"); + sourcesList.append("('ibus', 'OpenBangla')"); + auto sourcesString = QString("[%1]").arg(sourcesList.join(", ")); + writeDConfSetting("/org/cinnamon/desktop/input-sources/sources", sourcesString); + LOG_DEBUG("[Cinnamon] Added OpenBangla to sources\n"); + } +} + QString findFcitx5WaylandLauncher() { QStringList candidates = { @@ -424,6 +444,8 @@ void setupInputSources() { setupGnomeIME(); } else if(de == DesktopEnvironment::KDE) { setupKdeIME(); + } else if(de == DesktopEnvironment::Cinnamon) { + setupCinnamonIME(); } else if(de == DesktopEnvironment::Deepin) { setupFcitx5InputMethod(); } else if(de == DesktopEnvironment::macOS) { From fc51697f4dcd40e8d6846053b9feba88854711cc Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 4 Apr 2026 17:07:33 +0600 Subject: [PATCH 26/31] Implement autoconfig for ZorinOS --- src/frontend/PlatformConfig.cpp | 6 ++++-- src/frontend/PlatformConfig.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index abf9c8b1..05a358ad 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -55,6 +55,7 @@ DesktopEnvironment detectDesktopEnvironment() { const QString de = desktopEnvs.join(';').toLower(); + if (de.contains("zorin")) return DesktopEnvironment::ZorinOS; if (de.contains("gnome")) return DesktopEnvironment::GNOME; if (de.contains("kde")) return DesktopEnvironment::KDE; if (de.contains("xfce")) return DesktopEnvironment::XFCE; @@ -91,6 +92,7 @@ QString desktopEnvironmentToString(DesktopEnvironment de) { case DesktopEnvironment::Unity: return "Unity"; case DesktopEnvironment::Pantheon: return "Pantheon"; case DesktopEnvironment::Deepin: return "Deepin"; + case DesktopEnvironment::ZorinOS: return "ZorinOS"; case DesktopEnvironment::Wayland: return "Wayland"; case DesktopEnvironment::X11: return "X11"; default: return "Unknown"; @@ -131,7 +133,7 @@ bool isAppIndicatorEnabled() { bool shouldShowTrayIcon() { DesktopEnvironment de = detectDesktopEnvironment(); - if (de == DesktopEnvironment::GNOME) { + if (de == DesktopEnvironment::GNOME || de == DesktopEnvironment::ZorinOS) { return isAppIndicatorEnabled(); } else if(de == DesktopEnvironment::Pantheon) { // Pantheon (Elementary OS) does not support AppIndicator @@ -440,7 +442,7 @@ void setupKdeIME() { void setupInputSources() { auto de = detectDesktopEnvironment(); - if(de == DesktopEnvironment::GNOME) { + if(de == DesktopEnvironment::GNOME || de == DesktopEnvironment::ZorinOS) { setupGnomeIME(); } else if(de == DesktopEnvironment::KDE) { setupKdeIME(); diff --git a/src/frontend/PlatformConfig.h b/src/frontend/PlatformConfig.h index 396bb575..79ac6b82 100644 --- a/src/frontend/PlatformConfig.h +++ b/src/frontend/PlatformConfig.h @@ -31,6 +31,7 @@ Unity, Pantheon, Deepin, + ZorinOS, Wayland, X11 }; From 6c33a248965a246780ca0b82d486f2d033ee562d Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 4 Apr 2026 18:36:54 +0600 Subject: [PATCH 27/31] Implement autoconfig for Xfce DE --- src/frontend/PlatformConfig.cpp | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 05a358ad..37e0fc29 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -439,6 +439,76 @@ void setupKdeIME() { setupFcitx5InputMethod(); } +void configureImConfigForFcitx5() { + QString xinputrcPath = QDir::homePath() + "/.xinputrc"; + + // Check if already configured for fcitx5 + if (QFile::exists(xinputrcPath)) { + QFile file(xinputrcPath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QString content = file.readAll(); + file.close(); + if (content.contains("run_im fcitx5")) { + LOG_DEBUG("[XFCE] im-config already set to fcitx5\n"); + return; + } + } + } + + // Use im-config to set fcitx5 as the input method + QProcess process; + process.start("im-config", {"-n", "fcitx5"}); + process.waitForFinished(); + + if (process.exitCode() == 0) { + LOG_DEBUG("[XFCE] Configured im-config to use fcitx5\n"); + } else { + LOG_ERROR("[XFCE] Failed to configure im-config: %s\n", process.readAllStandardError().toStdString().c_str()); + } +} + +void setFcitx5EnvVarsForSession() { + // Set IM environment variables for the current DBus session so that + // applications launched after this point will use fcitx5. + QProcess process; + process.start("dbus-update-activation-environment", { + "GTK_IM_MODULE=fcitx", + "QT_IM_MODULE=fcitx", + "XMODIFIERS=@im=fcitx", + "SDL_IM_MODULE=fcitx" + }); + process.waitForFinished(); + + if (process.exitCode() == 0) { + LOG_DEBUG("[XFCE] Updated DBus activation environment for fcitx5\n"); + } else { + LOG_ERROR("[XFCE] Failed to update DBus environment: %s\n", process.readAllStandardError().toStdString().c_str()); + } +} + +void startFcitx5IfNeeded() { + // Check if fcitx5 is already running + QProcess pgrep; + pgrep.start("pgrep", {"-x", "fcitx5"}); + pgrep.waitForFinished(); + + if (pgrep.exitCode() == 0) { + LOG_DEBUG("[XFCE] fcitx5 is already running\n"); + return; + } + + // Start fcitx5 as a daemon + QProcess::startDetached("fcitx5", {"-d"}); + LOG_DEBUG("[XFCE] Started fcitx5 daemon\n"); +} + +void setupXfceIME() { + configureImConfigForFcitx5(); + setFcitx5EnvVarsForSession(); + startFcitx5IfNeeded(); + setupFcitx5InputMethod(); +} + void setupInputSources() { auto de = detectDesktopEnvironment(); @@ -450,6 +520,8 @@ void setupInputSources() { setupCinnamonIME(); } else if(de == DesktopEnvironment::Deepin) { setupFcitx5InputMethod(); + } else if(de == DesktopEnvironment::XFCE) { + setupXfceIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS bool enabled = macOS::getInputSourceEnabled(); From bfc9408c995f6715ad76a8bc538d2021d643a6e5 Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 4 Apr 2026 19:53:46 +0600 Subject: [PATCH 28/31] Implement autoconfig for Mate DE --- src/frontend/PlatformConfig.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 37e0fc29..2e0276cb 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -449,7 +449,7 @@ void configureImConfigForFcitx5() { QString content = file.readAll(); file.close(); if (content.contains("run_im fcitx5")) { - LOG_DEBUG("[XFCE] im-config already set to fcitx5\n"); + LOG_DEBUG("[Fcitx5] im-config already set to fcitx5\n"); return; } } @@ -461,9 +461,9 @@ void configureImConfigForFcitx5() { process.waitForFinished(); if (process.exitCode() == 0) { - LOG_DEBUG("[XFCE] Configured im-config to use fcitx5\n"); + LOG_DEBUG("[Fcitx5] Configured im-config to use fcitx5\n"); } else { - LOG_ERROR("[XFCE] Failed to configure im-config: %s\n", process.readAllStandardError().toStdString().c_str()); + LOG_ERROR("[Fcitx5] Failed to configure im-config: %s\n", process.readAllStandardError().toStdString().c_str()); } } @@ -480,9 +480,9 @@ void setFcitx5EnvVarsForSession() { process.waitForFinished(); if (process.exitCode() == 0) { - LOG_DEBUG("[XFCE] Updated DBus activation environment for fcitx5\n"); + LOG_DEBUG("[Fcitx5] Updated DBus activation environment for fcitx5\n"); } else { - LOG_ERROR("[XFCE] Failed to update DBus environment: %s\n", process.readAllStandardError().toStdString().c_str()); + LOG_ERROR("[Fcitx5] Failed to update DBus environment: %s\n", process.readAllStandardError().toStdString().c_str()); } } @@ -493,13 +493,13 @@ void startFcitx5IfNeeded() { pgrep.waitForFinished(); if (pgrep.exitCode() == 0) { - LOG_DEBUG("[XFCE] fcitx5 is already running\n"); + LOG_DEBUG("[Fcitx5] fcitx5 is already running\n"); return; } // Start fcitx5 as a daemon QProcess::startDetached("fcitx5", {"-d"}); - LOG_DEBUG("[XFCE] Started fcitx5 daemon\n"); + LOG_DEBUG("[Fcitx5] Started fcitx5 daemon\n"); } void setupXfceIME() { @@ -509,6 +509,13 @@ void setupXfceIME() { setupFcitx5InputMethod(); } +void setupMateIME() { + configureImConfigForFcitx5(); + setFcitx5EnvVarsForSession(); + startFcitx5IfNeeded(); + setupFcitx5InputMethod(); +} + void setupInputSources() { auto de = detectDesktopEnvironment(); @@ -522,6 +529,8 @@ void setupInputSources() { setupFcitx5InputMethod(); } else if(de == DesktopEnvironment::XFCE) { setupXfceIME(); + } else if(de == DesktopEnvironment::MATE) { + setupMateIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS bool enabled = macOS::getInputSourceEnabled(); From e674304823cf50304a31b9326309b46095b30bef Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 4 Apr 2026 22:12:27 +0600 Subject: [PATCH 29/31] Implement autoconfig for Budgie DE --- src/frontend/PlatformConfig.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 2e0276cb..f060bc95 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -516,6 +516,13 @@ void setupMateIME() { setupFcitx5InputMethod(); } +void setupBudgieIME() { + configureImConfigForFcitx5(); + setFcitx5EnvVarsForSession(); + startFcitx5IfNeeded(); + setupFcitx5InputMethod(); +} + void setupInputSources() { auto de = detectDesktopEnvironment(); @@ -531,6 +538,8 @@ void setupInputSources() { setupXfceIME(); } else if(de == DesktopEnvironment::MATE) { setupMateIME(); + } else if(de == DesktopEnvironment::Budgie) { + setupBudgieIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS bool enabled = macOS::getInputSourceEnabled(); From c361a2530268e1884b53763e84eaadeaec603ac1 Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 4 Apr 2026 23:38:48 +0600 Subject: [PATCH 30/31] Implement autoconfig for LXQt DE --- src/frontend/PlatformConfig.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index f060bc95..6c8091a9 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -523,6 +523,13 @@ void setupBudgieIME() { setupFcitx5InputMethod(); } +void setupLXQtIME() { + configureImConfigForFcitx5(); + setFcitx5EnvVarsForSession(); + startFcitx5IfNeeded(); + setupFcitx5InputMethod(); +} + void setupInputSources() { auto de = detectDesktopEnvironment(); @@ -540,6 +547,8 @@ void setupInputSources() { setupMateIME(); } else if(de == DesktopEnvironment::Budgie) { setupBudgieIME(); + } else if(de == DesktopEnvironment::LXQt) { + setupLXQtIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS bool enabled = macOS::getInputSourceEnabled(); From 3d13a86b86b7287cd3a79b038cd04760da335cbd Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 11 Apr 2026 21:53:22 +0600 Subject: [PATCH 31/31] postinstall script for deb and rpm --- CMakeLists.txt | 3 +++ data/linux/postinst.in | 6 ++++++ data/productbuild/postinstall | 2 +- src/frontend/PlatformConfig.cpp | 3 +-- src/frontend/main.cpp | 24 ++++++++---------------- 5 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 data/linux/postinst.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cf4aa42..eab316d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,9 @@ set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_RPM_PACKAGE_LICENSE "GPLv3") set(CPACK_RPM_PACKAGE_URL "https://openbangla.org/") set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) +configure_file("${CMAKE_SOURCE_DIR}/data/linux/postinst.in" "${CMAKE_BINARY_DIR}/postinst" @ONLY) +set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_BINARY_DIR}/postinst") +set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_BINARY_DIR}/postinst") # Prevents CPack from generating file conflicts set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/share/applications" "/usr/share/metainfo" "/usr/share/pixmaps" "/usr/share/icons" "/usr/share/icons/hicolor" diff --git a/data/linux/postinst.in b/data/linux/postinst.in new file mode 100644 index 00000000..f4266589 --- /dev/null +++ b/data/linux/postinst.in @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +@BIN_DIR@/openbangla-gui --setup-system + +exit 0 diff --git a/data/productbuild/postinstall b/data/productbuild/postinstall index b596d5fa..b3c3162c 100755 --- a/data/productbuild/postinstall +++ b/data/productbuild/postinstall @@ -1,6 +1,6 @@ #!/bin/bash set -e -/Applications/OpenBangla\ Keyboard.app/Contents/MacOS/OpenBangla\ Keyboard --setup-macos +/Applications/OpenBangla\ Keyboard.app/Contents/MacOS/OpenBangla\ Keyboard --setup-system exit 0 \ No newline at end of file diff --git a/src/frontend/PlatformConfig.cpp b/src/frontend/PlatformConfig.cpp index 6c8091a9..b1549fc5 100644 --- a/src/frontend/PlatformConfig.cpp +++ b/src/frontend/PlatformConfig.cpp @@ -551,8 +551,7 @@ void setupInputSources() { setupLXQtIME(); } else if(de == DesktopEnvironment::macOS) { #ifdef Q_OS_MACOS - bool enabled = macOS::getInputSourceEnabled(); - LOG_DEBUG("OpenBangla Input Source Enabled: %s\n", enabled ? "true" : "false"); + macOS::setupOpenBanglaInputSource(); #endif } else { LOG_DEBUG("Desktop Environment not supported for input source setup\n"); diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index 2ab750ed..8dd51a86 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -45,26 +45,18 @@ int main(int argc, char *argv[]) { parser.addVersionOption(); QCommandLineOption darkIcon("dark","Enable dark theme support"); QCommandLineOption startInTray("tray","Start in tray"); + QCommandLineOption setupSystem("setup-system","Setup OpenBangla input source"); parser.addOption(darkIcon); parser.addOption(startInTray); - - #ifdef Q_OS_MACOS - QCommandLineOption setTIS("setup-macos","Setup macOS input source"); - parser.addOption(setTIS); - #endif - + parser.addOption(setupSystem); parser.process(app); + + LOG_INFO("Detected Desktop Environment: %s\n", desktopEnvironmentToString(detectDesktopEnvironment()).toStdString().c_str()); - #ifdef Q_OS_MACOS - if(parser.isSet(setTIS)) { - macOS::setupOpenBanglaInputSource(); - return 0; - } - #endif - - LOG_DEBUG("Detected Desktop Environment: %s\n", desktopEnvironmentToString(detectDesktopEnvironment()).toStdString().c_str()); - - setupInputSources(); + if(parser.isSet(setupSystem)) { + setupInputSources(); + return 0; + } // Prevent many instances of the app to be launched QString name = "com.openbangla.keyboard";