53 Commits

Author SHA1 Message Date
deepend-tildeclub
7a4f744093 Delete .github/workflows/openbsd-build.yml 2026-02-22 09:23:04 -07:00
0e5d7dfb9f Updated the macOS CI staging steps (both arm64 and x86_64 jobs) to stage locales under "$STAGE_PREFIX/share/locale/" by creating "$STAGE_PREFIX/share" and syncing from "$BREW_PREFIX/share/locale/" there, instead of using a top-level "$STAGE_PREFIX/locale" directory.
Updated the gtk-mac-bundler bundle translation roots for both gtk30 and zoitechat to ${prefix}/share/locale (from ${prefix}/locale).
2026-02-19 17:46:27 -07:00
ec875e0709 Updated macOS bundle translation sources to use ${prefix}/locale for both GTK and ZoiteChat catalogs, preventing the bad .../ocale/...-style resolution path caused by prefix/path mismatch during bundling.
Updated both CI macOS staging jobs (arm64 and x86_64) to copy app-installed locale catalogs from $STAGE_PREFIX/share/locale into $STAGE_PREFIX/locale when present, so zoitechat.mo is available to gtk-mac-bundler in the staged tree.
2026-02-19 17:35:13 -07:00
a88eae5318 Updated macOS CI staging (arm64 + x86_64) to copy locales into $STAGE_PREFIX/locale/ (instead of $STAGE_PREFIX/share/locale) so gtk-mac-bundler can resolve gtk30.mo at the path it expects.
Updated both macOS packaging steps to pass BUNDLE_PREFIX with a trailing slash (.../stage/<arch>/).

    Replaced cp -a with rsync -aL when staging enchant so symlinks are dereferenced into the staged tree (avoids Homebrew opt symlink pitfalls).

    Adjusted osx/makebundle.sh to preserve a caller-provided trailing slash when writing the XML default prefix (instead of stripping it), matching the CI fix for malformed x86_64locale path concatenation.
2026-02-19 17:19:05 -07:00
29a35843f1 Fixed macOS bundling prefix serialization in osx/makebundle.sh by removing the forced trailing slash from BUNDLE_PREFIX_XML, so gtk-mac-bundler translation path rebasing no longer produces malformed .../ocale/... paths.
Updated the inline comments to document the exact failure mode and why a slashless <prefix> is required for this code path.
2026-02-19 16:39:38 -07:00
819535679c Fixed macOS bundling prefix rendering by introducing BUNDLE_PREFIX_XML="${BUNDLE_PREFIX%/}/" so the bundle XML always gets a trailing slash, preventing malformed translation paths like .../x86_64locale/... during gtk-mac-bundler translation copy steps.
Kept runtime path checks and enchant defaults based on the original BUNDLE_PREFIX, so only the XML-injected default prefix behavior changed.
2026-02-19 16:30:14 -07:00
1efba4ffdf Fixed the three Perl substitutions in osx/makebundle.sh that remove missing GTK module <binary> entries by changing the regex delimiter from |...| to #...#. This avoids delimiter collisions with | used inside (?:so|dylib), which was causing the CI parse error Unmatched ( in regex. 2026-02-19 14:40:19 -07:00
c2d0e7860c Updated osx/makebundle.sh to gracefully handle staged macOS dependency trees that omit GTK runtime module files by removing the corresponding <binary> entries from zoitechat.bundle before invoking gtk-mac-bundler. This prevents the exact Cannot find source to copy .../immodules/*.so class of failure you hit in CI.
Kept the existing .so/.dylib detection logic and reused that detected extension when checking whether immodules, printbackends, and gdk-pixbuf loaders files exist, so behavior stays compatible across different package-manager layouts.
2026-02-19 14:10:52 -07:00
e45c86249d Updated the macOS bundling script to detect whether staged GTK runtime modules are provided as .so or .dylib, using the current bundle prefix paths for GTK and GDK-Pixbuf. This avoids hard-coding .so assumptions in environments where Homebrew ships .dylib modules.
Added conditional rewrite logic that updates zoitechat.bundle glob patterns for immodules, printbackends, and loaders to the detected extension (.dylib or .so) before running gtk-mac-bundler.
2026-02-19 13:54:50 -07:00
8a166a9824 Fixed the macOS x86_64 CI build pipeline by adding the missing install step (meson install -C build-macos-x86_64) immediately after compilation, so the staged binary exists before makebundle.sh runs. This resolves the Cannot find main binary: .../stage/x86_64/bin/zoitechat packaging failure path. 2026-02-19 13:49:14 -07:00
7ab4b8d2eb Updated the macOS x86_64 GitHub Actions job to use runs-on: macos-15-intel instead of macos-13, which addresses unsupported macOS runner configuration issues. 2026-02-19 13:43:09 -07:00
deepend-tildeclub
29f1ac31ec Update macOS build workflow for arm64 and x86_64
Refactor macOS build workflow to support arm64 and x86_64 architectures. Add steps for staging dependencies and packaging unsigned apps for both architectures.
2026-02-19 13:30:47 -07:00
deepend-tildeclub
b0c1388d45 Enable darwin-arch-sanity-check in macOS build 2026-02-19 12:37:10 -07:00
676e8c7305 Updated the Darwin architecture sanity check in meson.build to consider Meson-provided c_args and c_link_args in addition to CFLAGS/LDFLAGS, so x86_64/universal targeting is detected even when -arch flags are passed via Meson options. This makes the early configure-time guard catch the Homebrew arm64-vs-x86_64 mismatch before the later linker failure you hit.
Kept the existing error behavior intact; only the architecture signal source was expanded (all_cflags / all_ldflags), so the same user-facing failure path now triggers in more real-world universal build setups.
2026-02-19 12:29:21 -07:00
02a0b02f03 Added fs = import('fs') in meson.build so we can safely test for dylib existence during Darwin sanity checks.
Extended the macOS architecture sanity logic to proactively inspect key link-time dependencies (gio, gobject, glib, gmodule, openssl, libcrypto, libintl) with lipo -archs whenever -arch x86_64 is requested, and fail at configure time if any dependency lacks an x86_64 slice.

    Kept the failure messaging actionable so users get an immediate explanation and remediation path (use universal/x86_64 deps, build arm64-only, or disable the check explicitly) instead of hitting late linker undefined symbol errors.
2026-02-19 12:14:21 -07:00
5ce88345ee Updated the macOS CI workflow so the x86_64 Meson configure step explicitly passes -Ddarwin-arch-sanity-check=false, preventing the architecture sanity guard from aborting that leg when dependencies are discovered via /opt/homebrew in GitHub-hosted macOS runners. 2026-02-19 12:07:53 -07:00
8d51b02ca0 Updated the macOS Darwin arch sanity check to detect when a build is intentionally universal (-arch arm64 and -arch x86_64) instead of treating it as an x86_64-only mismatch. This allows universal binary compile flows to proceed through configuration.
Kept the protective failure for true x86_64-only builds that resolve ARM Homebrew libraries (/opt/homebrew) and updated the error text to explicitly mention universal builds as a supported path.
2026-02-19 12:03:27 -07:00
7d49831886 Updated macOS architecture sanity-check flow in meson.build to first read the Meson option into a variable and then allow an environment-variable override (ZOITECHAT_DARWIN_ARCH_SANITY_CHECK) before running the mismatch guard. Accepted disable values are 0, false, no, and off.
Kept the existing mismatch detection logic intact, but updated the error text to document both bypass methods (-Ddarwin-arch-sanity-check=false or ZOITECHAT_DARWIN_ARCH_SANITY_CHECK=0).
2026-02-19 11:54:54 -07:00
d2e6dabdca Added a new Meson option, darwin-arch-sanity-check (default true), so macOS users can explicitly disable the architecture-mismatch guard when they need to proceed in mixed toolchain environments.
Updated the Darwin architecture check to run only when darwin-arch-sanity-check is enabled, preserving current behavior by default while allowing opt-out.

    Improved the check implementation to use pkg-config --libs-only-L glib-2.0 and only evaluate Homebrew path detection when the pkg-config call succeeds.

    Extended the error message to include the explicit bypass flag -Ddarwin-arch-sanity-check=false for clearer remediation guidance.
2026-02-19 11:42:39 -07:00
36c9504a4d Added a macOS-only Meson configure-time guard that checks for the exact mismatch you hit: -arch x86_64 in build flags while pkg-config resolves GLib from /opt/homebrew (ARM Homebrew). This now fails early with a clear actionable error instead of letting the build continue to a long linker failure.
The new error message explicitly tells users to choose one consistent setup: native arm64 with /opt/homebrew, or Rosetta/x86_64 with an x86_64 dependency stack (typically /usr/local).
2026-02-19 11:36:36 -07:00
98208cbc44 Updated the DH parameter initialization path to use legacy direct DH field assignment only on OpenSSL versions older than 1.1.0 (and non-LibreSSL), and otherwise always use DH_set0_pqg, which avoids opaque-struct access errors on OpenSSL 3.x.
Updated DH key extraction in dh1080_generate_key to use legacy direct member reads only for truly old OpenSSL, and DH_get0_key for modern OpenSSL, preventing dh->pub_key/dh->priv_key compile failures.

    Updated private-key injection in dh1080_compute_key to use DH_set0_key(dh, NULL, priv_key_num) on modern OpenSSL, removing the prior unnecessary temporary public-key allocation and avoiding direct dh->priv_key access.
2026-02-19 11:27:30 -07:00
c3c5731a58 Updated _SSL_socket to stop accessing SSL_CTX internals (ctx->method) on OpenSSL 1.1+/3, where SSL_CTX is opaque, and instead use SSL_is_server(ssl) to choose connect vs accept state on modern OpenSSL. Legacy pre-1.1 behavior is preserved behind version guards.
This directly addresses the reported build error at method = ctx->method; while keeping backward compatibility for older OpenSSL versions.
2026-02-19 11:22:36 -07:00
cbc6844987 Fixed _SSL_get_cert_info() to stop dereferencing OpenSSL-internal struct fields, which is what caused the macOS/OpenSSL opaque-struct build failure (peer_cert->sig_alg->algorithm). It now uses X509_ALGOR_get0() for the public key algorithm OID and OBJ_obj2nid() from that accessor output.
Reworked signature algorithm detection to use X509_get_signature_nid() when available, and a compatibility fallback (X509_get0_signature() + X509_ALGOR_get0() + OBJ_obj2nid()) when HAVE_X509_GET_SIGNATURE_NID is not defined.
2026-02-19 11:17:17 -07:00
5f0a8a4c1f Updated Perl plugin Meson logic to gracefully disable the plugin (instead of failing the whole configure) when ExtUtils::Embed cflags/ldflags cannot be retrieved. This is now handled with warnings plus subdir_done().
Added explicit check: false to both run_command() calls, resolving the Meson deprecation warning about implicit boolean check behavior in future Meson versions.

Changed the Perl compile/link suitability probe failure from fatal error() to non-fatal warning + plugin disable, so unsupported host Perl setups do not abort the build entirely.
2026-02-19 10:51:11 -07:00
b3f31004e6 Added universal build support to the macOS bundler script: UNIVERSAL=1 now targets both arm64 and x86_64, can auto-discover per-arch build outputs, and uses lipo -create to produce a universal ZoiteChat-bin before architecture validation.
Updated the macOS GitHub Actions workflow to build both architectures (build-macos-arm64 + build-macos-x86_64), then package a universal app by passing both binaries into osx/makebundle.sh.

Documented the universal build invocation in osx/DEBUGGING.md so local builds can reproduce Intel + Apple Silicon compatibility packaging.
2026-02-19 10:43:16 -07:00
c16dc8754d Updated the macOS bundle script to stop failing when the repo has no tags by introducing ARCHIVE_VERSION from git describe --tags --always (with stderr suppressed).
Added a fallback so that if git metadata is unavailable, the archive version falls back to VERSION_STRING instead of leaving an empty suffix in the zip name.

    Switched the final zip naming to use ARCHIVE_VERSION, avoiding ZoiteChat-.app.zip outputs and fatal git describe errors.
2026-02-19 10:30:30 -07:00
93854e42df Updated macOS bundling to detect the host architecture and introduce TARGET_ARCHES (overrideable) so bundle validation can target one or multiple architectures explicitly.
Added a post-bundle architecture check using lipo -archs against ZoiteChat-bin, and made bundling fail early with a clear error/hint when required architectures are missing (prevents shipping a bundle that will fail with “Bad CPU type”).

    Kept the existing architecture reporting via file, now reusing a single BIN_PATH variable for consistency.
2026-02-19 10:19:40 -07:00
cf2d5e5778 Fixed the macOS launcher errors you hit:
suppressed noisy defaults read failures for missing preference keys,

        fixed unsafe/empty test expressions that caused test: argument expected,

        corrected the gettext app domain from APP=name to APP=zoitechat.

    Improved launcher behavior for architecture mismatches (Bad CPU type in executable) by detecting exit 126 and printing a clear hint plus file output for ZoiteChat-bin.

    Updated osx/makebundle.sh so bundling is more Intel/Apple Silicon friendly:

        dynamically resolves/writes prefix and prefix:enchant (Homebrew Intel vs Apple Silicon layouts),

        still adapts enchant data path (share/enchant vs share/enchant-2),

        prints bundled binary architecture after bundling so mismatches are immediately visible.

    Extended macOS debugging docs with a dedicated “Bad CPU type in executable” section and explicit Intel (x86_64) build commands.
2026-02-19 10:06:49 -07:00
8a1dcee8e1 Updated the macOS bundling script to dynamically adapt the enchant data path before invoking gtk-mac-bundler, instead of assuming share/enchant always exists. It now checks the resolved enchant prefix and rewrites the bundle definition to use share/enchant or share/enchant-2 depending on what is present.
Added a fallback that removes the enchant <data> copy stanza entirely when neither share directory exists, preventing the exact Cannot find source to copy bundler failure you reported.
2026-02-18 16:09:30 -07:00
de9a78b38d Removed the deprecated Pango modules <binary> block from the macOS bundle manifest (osx/zoitechat.bundle), which eliminates the pango_module_version variable usage that breaks on newer Pango releases.
Committed the change on the current branch as 7a41c7b with message: osx: remove deprecated pango module reference from bundle.
2026-02-18 15:39:40 -07:00
f6942c7f3c Updated the macOS bundle definition to match Enchant 2’s actual install layout by:
narrowing the core library glob to libenchant-2*.dylib,

bundling provider modules from lib/enchant-2 as a <binary>,

bundling Enchant config files from share/enchant as <data>.

Removed the stale Enchant provider globs that targeted older/nonexistent paths (lib/enchant/libenchant_*.dylib), which caused the CI bundling failure you reported.
2026-02-18 15:33:04 -07:00
ca45939144 Updated macOS bundle definitions for enchant provider modules to use .dylib patterns (in both lib/enchant and lib/enchant-2) instead of .so, which aligns with Homebrew macOS layouts and avoids the gtk-mac-bundler copy-source failure you hit. 2026-02-18 15:11:47 -07:00
f558c99c22 Switched Darwin/macOS dependency resolution to require gtk-mac-integration directly, and removed the legacy gtkosxapplication fallback path in src/fe-gtk/meson.build.
Kept existing mac integration wiring behavior intact (HAVE_GTK_MAC still enabled when this dependency is present, now mandatory on Darwin).
2026-02-18 14:53:16 -07:00
ff77f32033 Fixed the macOS bundle spec to remove the invalid mid-path wildcard that caused gtk-mac-bundler to throw ValueError: Can't have wildcards except in the last path component. Specifically, I replaced .../lib/enchant*/libenchant_*.so with explicit entries for both supported enchant module layouts.
Added two explicit plugin paths so both directory variants are bundled correctly:

${prefix:enchant}/lib/enchant/libenchant_*.so

${prefix:enchant}/lib/enchant-2/libenchant_*.so
2026-02-18 14:39:52 -07:00
858f9daf64 Updated the macOS bundle definition to stop requiring a single hard-coded Enchant provider file (libenchant_applespell.so) and instead include any available Enchant provider modules under versioned/non-versioned provider directories (lib/enchant*/libenchant_*.so). This fixes bundling when Homebrew installs providers in paths like enchant-2 or when applespell isn’t present. 2026-02-18 14:21:02 -07:00
d3ae9d9d5d Updated the macOS bundle definition to default the enchant prefix to Homebrew’s enchant formula path (/usr/local/opt/enchant) instead of the older enchant-applespell path, aligning the bundle config with current installs.
Changed the bundled enchant dylib entry from a fixed filename to a wildcard (libenchant*.dylib) so gtk-mac-bundler can resolve versioned Homebrew library names (for example libenchant-2.2.dylib
2026-02-18 14:10:31 -07:00
a68a49f394 Fixed the macOS CI packaging step by exporting PREFIX and ENCHANT_PREFIX before the Perl substitutions that rewrite <prefix> entries in osx/zoitechat.bundle. This ensures $ENV{...} is populated during replacement and avoids invalid/empty metadata values that can crash gtk-mac-bundler with the NoneType error. 2026-02-18 14:00:26 -07:00
fdea5b25cb Fixed the macOS bundle definition by giving <run-install-name-tool> an explicit string value (yes) instead of leaving it empty, which prevents gtk-mac-bundler from receiving a None for that metadata node and hitting the reported NoneType crash path. 2026-02-18 13:26:57 -07:00
83143ff89d Fixed the macOS bundle definition by changing <run-install-name-tool/> to an explicit open/close tag, which avoids gtk-mac-bundler treating that node as None during <meta> parsing and crashing with the reported traceback. 2026-02-18 13:20:57 -07:00
e9869db82b Updated the macOS GitHub Actions dependency-install step to add a fallback installer for gtk-mac-bundler when neither the CLI executable nor the Python module is already available. The fallback downloads the upstream tarball, extracts it, and runs make install so osx/makebundle.sh can proceed in CI. 2026-02-18 13:12:40 -07:00
f1fe8f924e 7
Updated the Meson post-install script to import shutil and add a helper that checks tool availability before invoking post-install commands. This prevents hard failures when optional desktop tooling is not installed (e.g., on macOS/Homebrew CI).

Replaced direct subprocess.call(...) calls for gtk-update-icon-cache and update-desktop-database with guarded calls that emit a clear “Skipping …: command not found” message when absent, while preserving existing behavior when present.
2026-02-18 13:04:26 -07:00
3d9833ce4f Fixed dependency propagation in zoitechat_common_dep so it now exports common_deps (which includes OpenSSL when found) instead of only libgio_dep. This allows frontend targets depending on zoitechat_common_dep to inherit OpenSSL include/link flags and avoids openssl/ssl.h not found build failures. 2026-02-18 12:53:07 -07:00
2c4da1ff5e Reworked the prior change to preserve cross-OS default behavior by restoring with-lua default to luajit (instead of auto), so downstream builds that rely on historical defaults are not surprised.
Kept Lua fallback probing logic, but now it applies to both with-lua=auto and the default with-lua=luajit: Meson tries luajit, then lua-5.4, lua5.4, lua-5.3, lua5.3, and lua; if none are present it warns and disables the Lua plugin instead of hard-failing configure.

Updated the Lua plugin dependency selection so plugins/lua/meson.build consumes the pre-resolved fallback dependency for both auto and luajit paths, while keeping explicit custom pkg-config names unchanged.
2026-02-18 12:46:59 -07:00
bf24249001 Updated Meson DBus dependency handling so macOS always forces DBus support off before resolving dbus-glib-1, preventing configure-time failure on Darwin hosts where dbus-glib is unavailable. This now applies regardless of whether the dbus option is auto or enabled.
Added a clear Meson warning when -Ddbus=enabled is requested on macOS, so users get explicit feedback that DBus is being disabled on that platform.
2026-02-18 12:24:55 -07:00
505449f165 Updated Meson’s DBus dependency gating so that on macOS (darwin) with -Ddbus=auto, dbus-glib-1 is treated as optional instead of hard-required. This prevents configure-time failure in Homebrew CI environments where dbus-glib-1 is absent, while preserving strict behavior when -Ddbus=enabled is explicitly set.
Kept the existing libcanberra and surrounding dependency flow intact; only the required: logic for dbus-glib-1 was adjusted.
2026-02-18 11:53:12 -07:00
125c69c1b0 Updated the macOS CI workflow’s Meson configure step to explicitly disable libcanberra by adding -Dlibcanberra=disabled, which prevents Meson from treating that unavailable macOS dependency as required when -Dauto_features=enabled is set. 2026-02-18 11:34:25 -07:00
55d2dab620 Updated the macOS CI workflow to install gtk-mac-integration instead of gtk-mac-bundler in the Homebrew dependency list, resolving the reported “No available formula” failure during brew install. 2026-02-18 11:16:14 -07:00
590b44946b Updated the macOS GitHub Actions workflow to install enchant instead of the removed enchant-applespell Homebrew formula in the dependency step, which addresses the reported brew failure.
Updated the bundling step to resolve ENCHANT_PREFIX from brew --prefix enchant so packaging remains aligned with the installed formula.
2026-02-18 11:10:48 -07:00
857c8918d8 Fixed the invalid workflow expression by removing secrets.* checks from the job-level if on macos_release_signed (job-level expressions can’t reference secrets in that way).
Added a Check signing secrets availability step that inspects all required Apple signing/notarization secrets and emits a ready output for downstream gating.

Added an explicit skip message step when secrets are missing, and gated all signing/notarization/artifact-upload steps behind steps.signing_secrets.outputs.ready == 'true' so the workflow remains valid while preserving intended behavior.
2026-02-18 11:01:52 -07:00
04b8f1d5fa Added a new GitHub Actions workflow at .github/workflows/macos-build.yml with branch triggers aligned to existing CI (push/pull_request on master) and a two-job structure for unsigned CI build plus optional release signing/notarization.
Implemented the build-only unsigned macOS phase on macos-latest: installs Meson/Ninja/GTK tooling via Homebrew, configures/builds with Meson, installs for bundling, generates the .app zip via the existing macOS bundle script, and uploads the unsigned artifact with retention (14 days).

Implemented the release-grade gated phase: job is gated to push on master and only runs when required Apple signing/notarization secrets are present; it downloads the unsigned artifact, imports Developer ID cert, codesigns, notarizes with Apple API key credentials, staples the ticket, and uploads a signed artifact with retention (30 days).
2026-02-18 10:55:53 -07:00
1ab7e14422 Updated macOS app metadata in osx/Info.plist.in:
Raised LSMinimumSystemVersion to 11.0.

Aligned CFBundleIdentifier with project naming (net.zoite.Zoitechat).

Kept version placeholders (@VERSION@) in CFBundleGetInfoString, CFBundleShortVersionString, and CFBundleVersion so they map cleanly via template substitution.

Confirmed icon/document declarations still point to zoitechat.icns and zct/hct extensions.

Made Info.plist generation deterministic in bundling workflow by updating osx/makebundle.sh:

Force script execution from its own directory for stable relative paths.

Always render Info.plist from Info.plist.in before bundling.

Use a single explicit version source: VERSION env var or fallback to meson.build project version.

Use LC_ALL=C substitution and atomic temp-file move for stable output behavior.
2026-02-18 10:54:55 -07:00
815df2aeb0 Updated osx/makebundle.sh to use a robust bundler invocation flow: prefer gtk-mac-bundler, fall back to python3 -m gtk_mac_bundler, fail fast with clear install guidance if neither is available, and verify the .app was actually produced before zipping. Also added macOS prefix/library expectation comments.
Updated osx/zoitechat.bundle to target GTK3 (gtk+-3.0), refreshed runtime module paths (immodules, printbackends, gdk-pixbuf, pango), removed GTK2-specific engine/theme entries, and added prefix comments. This also keeps the requested anchor locations (launcher-script, ${prefix}/lib/${gtkdir}).

Updated osx/launcher.sh to remove obsolete GTK2 environment assumptions (including GTK2_RC_FILES and old GTK2 loader file paths), set GTK3-relevant variables (GTK_IM_MODULE_FILE, GDK_PIXBUF_MODULE_FILE, GSETTINGS_SCHEMA_DIR), and minimize DYLD path hacking by only prepending when already set. Added launcher-script comment anchor and prefix/library docs.
2026-02-18 10:50:24 -07:00
668c391a8a Added a dedicated darwin branch in src/fe-gtk/meson.build while preserving the existing Windows and non-Windows (freedesktop) notification branches. In this macOS branch, notifications/notification-osx.m is appended to sources, Objective-C is enabled via add_languages('objc'), and pkg-config probing now tries gtk-mac-integration first and falls back to gtkosxapplication.
When either mac integration dependency is found on darwin, Meson now adds that dependency and defines -DHAVE_GTK_MAC in zoitechat_gtk_cflags, which activates the existing #ifdef HAVE_GTK_MAC blocks in the GTK frontend code.

Verified the existing source guards that become active with HAVE_GTK_MAC are already present in the requested files:

fe-gtk.h (mac header include + extern).

fe-gtk.c (global mac app object and mac-specific paths).

menu.c (mac menubar/app-menu integration).

maingui.c (mac dock attention request).
2026-02-18 10:46:04 -07:00
91 changed files with 3210 additions and 803 deletions

View File

@@ -8,7 +8,7 @@ on:
jobs:
appimage_build:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
contents: read
@@ -34,7 +34,7 @@ jobs:
libxkbcommon0 \
libgtk-3-bin libglib2.0-bin shared-mime-info gsettings-desktop-schemas \
libluajit-5.1-dev libpci-dev libperl-dev libssl-dev libayatana-appindicator3-dev \
perl python3 python3-minimal python3-dev python3-cffi mono-devel desktop-file-utils \
python3-dev python3-cffi mono-devel desktop-file-utils \
patchelf file curl
- name: Configure
@@ -43,11 +43,11 @@ jobs:
rm -rf build
meson setup build \
--prefix=/usr \
-Dgtk3=true \
-Dtext-frontend=true \
-Dwith-perl=perl \
-Dwith-python=python3 \
-Dauto_features=enabled \
-Dappindicator=enabled
-Dauto_features=enabled
- name: Build
run: |
@@ -60,60 +60,6 @@ jobs:
rm -rf AppDir
DESTDIR="${PWD}/AppDir" ninja -C build install
- name: Bundle scripting runtimes in AppDir
run: |
set -eux
python3_version="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
install -Dm755 "$(command -v python3)" "AppDir/usr/bin/python3"
if [ -x "/usr/bin/perl" ]; then
install -Dm755 /usr/bin/perl AppDir/usr/bin/perl
fi
install -d AppDir/usr/lib
cp -a "/usr/lib/python${python3_version}" "AppDir/usr/lib/"
if [ -d "/usr/lib/python3/dist-packages" ]; then
install -d AppDir/usr/lib/python3
cp -a /usr/lib/python3/dist-packages AppDir/usr/lib/python3/
fi
if [ -d "/usr/lib/x86_64-linux-gnu/python3/dist-packages" ]; then
install -d AppDir/usr/lib/x86_64-linux-gnu/python3
cp -a /usr/lib/x86_64-linux-gnu/python3/dist-packages AppDir/usr/lib/x86_64-linux-gnu/python3/
fi
if [ -d "/usr/lib/x86_64-linux-gnu/perl" ]; then
install -d AppDir/usr/lib/x86_64-linux-gnu
cp -a /usr/lib/x86_64-linux-gnu/perl AppDir/usr/lib/x86_64-linux-gnu/
fi
if [ -d "/usr/share/perl" ]; then
install -d AppDir/usr/share
cp -a /usr/share/perl AppDir/usr/share/
fi
if [ -d "/usr/share/perl5" ]; then
install -d AppDir/usr/share
cp -a /usr/share/perl5 AppDir/usr/share/
fi
if compgen -G '/usr/lib/x86_64-linux-gnu/libpython3*.so*' > /dev/null; then
install -d AppDir/usr/lib/x86_64-linux-gnu
cp -a /usr/lib/x86_64-linux-gnu/libpython3*.so* AppDir/usr/lib/x86_64-linux-gnu/
fi
- name: Verify bundled plugins
run: |
set -eux
# Include every built-in plugin except the Windows-only update plugin.
find AppDir/usr/lib -maxdepth 4 -type f -name '*.so' -path '*/zoitechat/plugins/*' -print | sort
for plugin in checksum fishlim lua perl python sysinfo; do
find "AppDir/usr/lib" -maxdepth 4 -type f -name "${plugin}.so" -path '*/zoitechat/plugins/*' -print -quit | grep -q .
done
- name: Build AppImage
env:
APPIMAGE_EXTRACT_AND_RUN: 1
@@ -140,16 +86,10 @@ jobs:
APPDIR="${APPDIR:-$(dirname "$(readlink -f "$0")")}"
export PATH="${PATH:-/usr/bin:/bin}:$APPDIR/usr/bin"
export PATH="$APPDIR/usr/bin:${PATH:-/usr/bin:/bin}"
export LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}"
export XDG_DATA_DIRS="$APPDIR/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins" ]; then
export ZOITECHAT_LIBDIR="$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins"
elif [ -d "$APPDIR/usr/lib/zoitechat/plugins" ]; then
export ZOITECHAT_LIBDIR="$APPDIR/usr/lib/zoitechat/plugins"
fi
if [ -d "$APPDIR/usr/share/glib-2.0/schemas" ]; then
export GSETTINGS_SCHEMA_DIR="$APPDIR/usr/share/glib-2.0/schemas${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}"
fi
@@ -160,22 +100,6 @@ jobs:
export GIO_EXTRA_MODULES="$APPDIR/usr/lib/gio/modules${GIO_EXTRA_MODULES:+:$GIO_EXTRA_MODULES}"
fi
export PYTHONHOME="$APPDIR/usr"
python_stdlib_dir="$(find "$APPDIR/usr/lib" -maxdepth 1 -type d -name 'python3.*' | head -n 1 || true)"
pythonpath_entries=""
if [ -n "$python_stdlib_dir" ] && [ -d "$python_stdlib_dir/dist-packages" ]; then
pythonpath_entries="$python_stdlib_dir/dist-packages"
fi
if [ -d "$APPDIR/usr/lib/python3/dist-packages" ]; then
pythonpath_entries="${pythonpath_entries:+$pythonpath_entries:}$APPDIR/usr/lib/python3/dist-packages"
fi
if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/python3/dist-packages" ]; then
pythonpath_entries="${pythonpath_entries:+$pythonpath_entries:}$APPDIR/usr/lib/x86_64-linux-gnu/python3/dist-packages"
fi
if [ -n "$pythonpath_entries" ]; then
export PYTHONPATH="$pythonpath_entries${PYTHONPATH:+:$PYTHONPATH}"
fi
# OpenSSL trust store override
export SSL_CERT_FILE="${SSL_CERT_FILE:-$APPDIR/etc/ssl/certs/ca-certificates.crt}"
export SSL_CERT_DIR="${SSL_CERT_DIR:-$APPDIR/etc/ssl/certs}"

View File

@@ -31,8 +31,7 @@ jobs:
with:
bundle: zoitechat.flatpak
manifest-path: flatpak/net.zoite.Zoitechat.json
cache: false
restore-cache: false
cache-key: flatpak-builder-${{ github.sha }}
- name: Upload Flatpak Bundle
id: upload_flatpak

359
.github/workflows/macos-build.yml vendored Normal file
View File

@@ -0,0 +1,359 @@
name: macOS Build
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
macos_build_arm64:
runs-on: macos-15-arm64
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install build dependencies
run: |
set -eux
brew update
brew install \
meson ninja pkg-config gettext perl \
gtk+3 gdk-pixbuf pango adwaita-icon-theme \
hicolor-icon-theme glib dbus \
enchant gtk-mac-integration
if ! command -v gtk-mac-bundler >/dev/null 2>&1 && ! python3 -c 'import gtk_mac_bundler' >/dev/null 2>&1; then
curl -fsSL https://codeload.github.com/jralls/gtk-mac-bundler/tar.gz/refs/heads/master -o /tmp/gtk-mac-bundler.tar.gz
rm -rf /tmp/gtk-mac-bundler
mkdir -p /tmp/gtk-mac-bundler
tar -xzf /tmp/gtk-mac-bundler.tar.gz -C /tmp/gtk-mac-bundler --strip-components=1
(cd /tmp/gtk-mac-bundler && make install)
fi
- name: Configure and build (arm64)
run: |
set -eux
rm -rf build-macos-arm64 stage/arm64
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson setup build-macos-arm64 \
--prefix="$PWD/stage/arm64" \
-Dgtk3=true \
-Dtext-frontend=true \
-Dlibcanberra=disabled \
-Dwith-perl=perl \
-Dwith-python=python3 \
-Dauto_features=enabled
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson compile -C build-macos-arm64
meson install -C build-macos-arm64
- name: Stage runtime dependencies for bundling (arm64)
run: |
set -eux
STAGE_PREFIX="$PWD/stage/arm64"
BREW_PREFIX="$(brew --prefix)"
ENCHANT_PREFIX="$(brew --prefix enchant)"
mkdir -p "$STAGE_PREFIX/lib" "$STAGE_PREFIX/share"
rsync -a "$BREW_PREFIX/lib/gtk-3.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/lib/gdk-pixbuf-2.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/share/locale/" "$STAGE_PREFIX/share/locale/"
mkdir -p "$STAGE_PREFIX/opt"
rm -rf "$STAGE_PREFIX/opt/enchant"
rsync -aL "$ENCHANT_PREFIX/" "$STAGE_PREFIX/opt/enchant/"
- name: Package unsigned .app (arm64)
run: |
set -eux
VERSION="$(git describe --tags --always)"
export VERSION
(
cd osx
BUNDLE_PREFIX="$PWD/../stage/arm64/" \
ENCHANT_PREFIX="$PWD/../stage/arm64/opt/enchant" \
TARGET_ARCHES="arm64" \
./makebundle.sh
)
mv osx/ZoiteChat-*.app.zip ./ZoiteChat-arm64.app.zip
- name: Upload arm64 macOS app artifact
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-arm64
path: ZoiteChat-arm64.app.zip
if-no-files-found: error
retention-days: 14
macos_build_x86_64:
runs-on: macos-15-intel
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install build dependencies
run: |
set -eux
brew update
brew install \
meson ninja pkg-config gettext perl \
gtk+3 gdk-pixbuf pango adwaita-icon-theme \
hicolor-icon-theme glib dbus \
enchant gtk-mac-integration
if ! command -v gtk-mac-bundler >/dev/null 2>&1 && ! python3 -c 'import gtk_mac_bundler' >/dev/null 2>&1; then
curl -fsSL https://codeload.github.com/jralls/gtk-mac-bundler/tar.gz/refs/heads/master -o /tmp/gtk-mac-bundler.tar.gz
rm -rf /tmp/gtk-mac-bundler
mkdir -p /tmp/gtk-mac-bundler
tar -xzf /tmp/gtk-mac-bundler.tar.gz -C /tmp/gtk-mac-bundler --strip-components=1
(cd /tmp/gtk-mac-bundler && make install)
fi
- name: Configure and build (x86_64)
run: |
set -eux
rm -rf build-macos-x86_64 stage/x86_64
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson setup build-macos-x86_64 \
--prefix="$PWD/stage/x86_64" \
-Dgtk3=true \
-Dtext-frontend=true \
-Dlibcanberra=disabled \
-Ddarwin-arch-sanity-check=true \
-Dwith-perl=perl \
-Dwith-python=python3 \
-Dauto_features=enabled
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson compile -C build-macos-x86_64
meson install -C build-macos-x86_64
- name: Stage runtime dependencies for bundling (x86_64)
run: |
set -eux
STAGE_PREFIX="$PWD/stage/x86_64"
BREW_PREFIX="$(brew --prefix)"
ENCHANT_PREFIX="$(brew --prefix enchant)"
mkdir -p "$STAGE_PREFIX/lib" "$STAGE_PREFIX/share"
rsync -a "$BREW_PREFIX/lib/gtk-3.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/lib/gdk-pixbuf-2.0" "$STAGE_PREFIX/lib/"
rsync -a "$BREW_PREFIX/share/locale/" "$STAGE_PREFIX/share/locale/"
mkdir -p "$STAGE_PREFIX/opt"
rm -rf "$STAGE_PREFIX/opt/enchant"
rsync -aL "$ENCHANT_PREFIX/" "$STAGE_PREFIX/opt/enchant/"
- name: Package unsigned .app (x86_64)
run: |
set -eux
VERSION="$(git describe --tags --always)"
export VERSION
(
cd osx
BUNDLE_PREFIX="$PWD/../stage/x86_64/" \
ENCHANT_PREFIX="$PWD/../stage/x86_64/opt/enchant" \
TARGET_ARCHES="x86_64" \
./makebundle.sh
)
mv osx/ZoiteChat-*.app.zip ./ZoiteChat-x86_64.app.zip
- name: Upload x86_64 macOS app artifact
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-x86_64
path: ZoiteChat-x86_64.app.zip
if-no-files-found: error
retention-days: 14
macos_assemble_universal_unsigned:
needs:
- macos_build_arm64
- macos_build_x86_64
runs-on: macos-latest
steps:
- name: Download arm64 app artifact
uses: actions/download-artifact@v4
with:
name: zoitechat-macos-arm64
path: dist/arm64
- name: Download x86_64 app artifact
uses: actions/download-artifact@v4
with:
name: zoitechat-macos-x86_64
path: dist/x86_64
- name: Merge app bundles into universal
run: |
set -eux
unzip -q dist/arm64/ZoiteChat-arm64.app.zip -d dist/arm64
unzip -q dist/x86_64/ZoiteChat-x86_64.app.zip -d dist/x86_64
ARM_APP="$(find dist/arm64 -maxdepth 2 -name 'ZoiteChat.app' -type d | head -n 1)"
X86_APP="$(find dist/x86_64 -maxdepth 2 -name 'ZoiteChat.app' -type d | head -n 1)"
UNIVERSAL_APP="dist/universal/ZoiteChat.app"
rm -rf "$UNIVERSAL_APP"
mkdir -p dist/universal
cp -a "$ARM_APP" "$UNIVERSAL_APP"
while IFS= read -r relpath; do
arm_file="$ARM_APP/$relpath"
x86_file="$X86_APP/$relpath"
out_file="$UNIVERSAL_APP/$relpath"
if [ -f "$x86_file" ] && file -b "$arm_file" | grep -q 'Mach-O'; then
mkdir -p "$(dirname "$out_file")"
lipo -create "$arm_file" "$x86_file" -output "$out_file"
fi
done < <(cd "$ARM_APP" && find . -type f | sed 's|^./||')
while IFS= read -r macho_path; do
archs="$(lipo -archs "$macho_path")"
echo "$macho_path -> $archs"
echo " $archs " | grep -q ' arm64 '
echo " $archs " | grep -q ' x86_64 '
done < <(find "$UNIVERSAL_APP" -type f -exec sh -c 'file -b "$1" | grep -q "Mach-O" && printf "%s\n" "$1"' _ {} \;)
VERSION="$(git -C "$GITHUB_WORKSPACE" describe --tags --always)"
ditto -c -k --sequesterRsrc --keepParent "$UNIVERSAL_APP" "dist/ZoiteChat-$VERSION.app.zip"
- name: Upload unsigned macOS app artifact
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-unsigned
path: dist/ZoiteChat-*.app.zip
if-no-files-found: error
retention-days: 14
macos_release_signed:
needs: macos_assemble_universal_unsigned
runs-on: macos-latest
if: >-
github.event_name == 'push' &&
github.ref == 'refs/heads/master'
steps:
- name: Check signing secrets availability
id: signing_secrets
env:
APPLE_DEVELOPER_ID_APPLICATION: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION }}
APPLE_DEVELOPER_ID_CERT_P12: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12 }}
APPLE_DEVELOPER_ID_CERT_P12_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12_PASSWORD }}
APPLE_NOTARY_API_KEY: ${{ secrets.APPLE_NOTARY_API_KEY }}
APPLE_NOTARY_API_KEY_ID: ${{ secrets.APPLE_NOTARY_API_KEY_ID }}
APPLE_NOTARY_ISSUER_ID: ${{ secrets.APPLE_NOTARY_ISSUER_ID }}
run: |
set -eu
required_secrets=(
APPLE_DEVELOPER_ID_APPLICATION
APPLE_DEVELOPER_ID_CERT_P12
APPLE_DEVELOPER_ID_CERT_P12_PASSWORD
APPLE_NOTARY_API_KEY
APPLE_NOTARY_API_KEY_ID
APPLE_NOTARY_ISSUER_ID
)
missing=0
for key in "${required_secrets[@]}"; do
if [ -z "${!key:-}" ]; then
echo "Missing secret: $key"
missing=1
fi
done
if [ "$missing" -eq 1 ]; then
echo "ready=false" >> "$GITHUB_OUTPUT"
else
echo "ready=true" >> "$GITHUB_OUTPUT"
fi
- name: Skip signing because required secrets are missing
if: steps.signing_secrets.outputs.ready != 'true'
run: echo "Signing and notarization skipped due to missing required secrets."
- name: Download unsigned app artifact
if: steps.signing_secrets.outputs.ready == 'true'
uses: actions/download-artifact@v4
with:
name: zoitechat-macos-unsigned
path: dist
- name: Import Developer ID certificate
if: steps.signing_secrets.outputs.ready == 'true'
env:
CERT_P12_BASE64: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12 }}
CERT_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_CERT_P12_PASSWORD }}
run: |
set -eux
echo "$CERT_P12_BASE64" | base64 --decode > certificate.p12
security create-keychain -p "" build.keychain
security set-keychain-settings -lut 21600 build.keychain
security unlock-keychain -p "" build.keychain
security import certificate.p12 -k build.keychain -P "$CERT_PASSWORD" -A -T /usr/bin/codesign
security list-keychains -d user -s build.keychain $(security list-keychains -d user | tr -d '"')
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
- name: Codesign app bundle
if: steps.signing_secrets.outputs.ready == 'true'
env:
CODESIGN_IDENTITY: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION }}
run: |
set -eux
unzip -q dist/ZoiteChat-*.app.zip -d dist
APP_PATH="$(find dist -maxdepth 1 -name 'ZoiteChat.app' -type d | head -n 1)"
codesign --force --deep --options runtime --timestamp \
--sign "$CODESIGN_IDENTITY" "$APP_PATH"
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
spctl --assess --type execute --verbose "$APP_PATH"
- name: Notarize and staple
if: steps.signing_secrets.outputs.ready == 'true'
env:
NOTARY_API_KEY_BASE64: ${{ secrets.APPLE_NOTARY_API_KEY }}
NOTARY_KEY_ID: ${{ secrets.APPLE_NOTARY_API_KEY_ID }}
NOTARY_ISSUER_ID: ${{ secrets.APPLE_NOTARY_ISSUER_ID }}
run: |
set -eux
APP_PATH="$(find dist -maxdepth 1 -name 'ZoiteChat.app' -type d | head -n 1)"
NOTARY_ZIP="dist/ZoiteChat-notarize.zip"
SIGNED_ZIP="dist/ZoiteChat-signed.app.zip"
echo "$NOTARY_API_KEY_BASE64" | base64 --decode > AuthKey_${NOTARY_KEY_ID}.p8
ditto -c -k --keepParent "$APP_PATH" "$NOTARY_ZIP"
xcrun notarytool submit "$NOTARY_ZIP" \
--key "AuthKey_${NOTARY_KEY_ID}.p8" \
--key-id "$NOTARY_KEY_ID" \
--issuer "$NOTARY_ISSUER_ID" \
--wait
xcrun stapler staple "$APP_PATH"
xcrun stapler validate "$APP_PATH"
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$SIGNED_ZIP"
- name: Upload signed macOS app artifact
if: steps.signing_secrets.outputs.ready == 'true'
uses: actions/upload-artifact@v4
with:
name: zoitechat-macos-signed
path: dist/ZoiteChat-signed.app.zip
if-no-files-found: error
retention-days: 30

View File

@@ -1,81 +0,0 @@
name: Manjaro Package Build
on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
workflow_dispatch:
permissions:
contents: read
jobs:
manjaro-package:
runs-on: ubuntu-latest
container:
image: manjarolinux/base:latest
steps:
- name: Install packaging toolchain
run: |
set -euxo pipefail
pacman -Syu --noconfirm
pacman -S --noconfirm --needed \
base-devel \
git \
namcap \
meson \
ninja \
pkgconf \
glib2 \
glib2-devel \
gtk3 \
openssl \
dbus-glib \
libcanberra \
libayatana-appindicator \
luajit \
iso-codes \
lua \
perl \
python \
python-cffi \
pciutils
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Build package and generate .SRCINFO (non-root)
run: |
set -euxo pipefail
id -u builder >/dev/null 2>&1 || useradd -m builder
chown -R builder:builder "$GITHUB_WORKSPACE"
su builder -c "cd '$GITHUB_WORKSPACE/packaging/manjaro' && makepkg --noconfirm --syncdeps --cleanbuild"
su builder -c "cd '$GITHUB_WORKSPACE/packaging/manjaro' && makepkg --printsrcinfo > .SRCINFO"
- name: Lint PKGBUILD and package with namcap
run: |
set -euxo pipefail
cd "$GITHUB_WORKSPACE/packaging/manjaro"
namcap PKGBUILD
pkg_file="$(find . -maxdepth 1 -type f -name '*.pkg.tar.*' | head -n1)"
namcap "$pkg_file"
- name: Collect artifacts
run: |
set -euxo pipefail
mkdir -p artifacts
cp -v "$GITHUB_WORKSPACE"/packaging/manjaro/*.pkg.tar.* artifacts/
cp -v "$GITHUB_WORKSPACE"/packaging/manjaro/PKGBUILD artifacts/
cp -v "$GITHUB_WORKSPACE"/packaging/manjaro/.SRCINFO artifacts/
- name: Upload package artifacts
uses: actions/upload-artifact@v4
with:
name: zoitechat-manjaro-package
path: artifacts/*
if-no-files-found: error

View File

@@ -10,7 +10,7 @@ on:
solus_image:
description: "Solus container image"
required: false
default: "docker.io/silkeh/solus:latest"
default: "ghcr.io/getsolus/solus:latest"
push:
branches:
- main
@@ -24,7 +24,7 @@ jobs:
build-eopkg:
runs-on: ubuntu-latest
env:
SOLUS_IMAGE: ${{ inputs.solus_image || 'docker.io/silkeh/solus:latest' }}
SOLUS_IMAGE: ${{ inputs.solus_image || 'ghcr.io/getsolus/solus:latest' }}
PACKAGE_YML: ${{ inputs.package_yml || 'packaging/solus/package.yml' }}
steps:
- name: Checkout
@@ -48,11 +48,7 @@ jobs:
exit 1
fi
if ! docker pull "$SOLUS_IMAGE"; then
echo "Failed to pull SOLUS_IMAGE=$SOLUS_IMAGE" >&2
echo "Set workflow input 'solus_image' to a valid image that provides eopkg/ypkg." >&2
exit 1
fi
docker pull "$SOLUS_IMAGE"
docker run --rm \
-v "$PWD":/workspace \
@@ -62,19 +58,7 @@ jobs:
sh -lc '
set -euo pipefail
eopkg update-repo -y
# Do not remove openssl-11 here: it can trigger a very large
# dependency cascade (including python3/eopkg itself), which
# breaks the build environment before package build starts.
# Some Solus base images still contain openssl-11 files that
# conflict with openssl 3.x when the package set is refreshed.
# Allowing file-conflict resolution keeps the CI image usable
# long enough to install ypkg and complete the package build.
# The base image does not guarantee Meson toolchain packages,
# while our package.yml setup phase calls meson directly.
# Install the essential build tools up front to avoid
# `/tmp/ypkg-setup*: meson: command not found` failures.
eopkg install -y --ignore-file-conflicts \
ypkg git meson ninja pkgconf gcc gettext
eopkg install -y ypkg git
ypkg build "$PACKAGE_YML"
mkdir -p /workspace/artifacts
find . -maxdepth 3 -name "*.eopkg" -type f -exec cp -v {} /workspace/artifacts/ \;

View File

@@ -1,16 +1,6 @@
ZoiteChat ChangeLog
=================
2.18.0~pre2 (2026-02-25)
------------------------
- Added HexChat plugin compatibility improvements.
- Fixed the user info right-click menu so it updates properly.
- Added support for emoji characters in alert highlights.
- clicking links in chat window with appimage build now works.
- Removed remaining unused GTK2 code paths.
- Continued GTK3 cleanup and packaging alignment work.
2.18.0-pre1 (2026-02-16)
------------------------

View File

@@ -7,5 +7,5 @@
<url type="homepage">https://zoitechat.zoite.net/</url>
<project_license>@LICENSE@</project_license>
<metadata_license>CC0-1.0</metadata_license>
<update_contact>deepend_AT_zoite.net</update_contact>
</component>
<update_contact>tingping_AT_fedoraproject.org</update_contact>
</component>

View File

@@ -14,7 +14,7 @@
</description>
<url type="homepage">http://zoitechat.zoite.net</url>
<url type="bugtracker">https://github.com/zoitechat/zoitechat</url>
<url type="help">https://docs.zoitechat.zoite.net/en/latest/</url>
<url type="help">https://zoitechat.zoite.net/docs</url>
<screenshots>
<screenshot type="default">
<image>https://zoitechat.zoite.net/assets/ZoiteChat.png</image>
@@ -25,17 +25,6 @@
<id>zoitechat.desktop</id>
</provides>
<releases>
<release date="2026-02-25" version="2.18.0~pre2">
<description>
<p>Compatibility and UI improvements:</p>
<ul>
<li>Added HexChat plugin compatibility improvements.</li>
<li>Fixed the user info right-click menu so it updates properly.</li>
<li>Added support for emoji characters in alert highlights.</li>
<li>Removed remaining unused GTK2 code paths.</li>
</ul>
</description>
</release>
<release date="2026-02-16" version="2.18.0-pre1">
<description>
<p>Packaging and GTK3 improvements:</p>

View File

@@ -22,117 +22,61 @@
<file alias="tree_util.png" preprocess="to-pixdata">icons/tree_util.png</file>
<file alias="menu/light/new.png" preprocess="to-pixdata">icons/menu/light/new.png</file>
<file alias="menu/light/new.svg">icons/menu/light/new.svg</file>
<file alias="menu/light/network-list.png" preprocess="to-pixdata">icons/menu/light/network-list.png</file>
<file alias="menu/light/network-list.svg">icons/menu/light/network-list.svg</file>
<file alias="menu/light/load-plugin.png" preprocess="to-pixdata">icons/menu/light/load-plugin.png</file>
<file alias="menu/light/load-plugin.svg">icons/menu/light/load-plugin.svg</file>
<file alias="menu/light/detach.png" preprocess="to-pixdata">icons/menu/light/detach.png</file>
<file alias="menu/light/detach.svg">icons/menu/light/detach.svg</file>
<file alias="menu/light/close.png" preprocess="to-pixdata">icons/menu/light/close.png</file>
<file alias="menu/light/close.svg">icons/menu/light/close.svg</file>
<file alias="menu/light/quit.png" preprocess="to-pixdata">icons/menu/light/quit.png</file>
<file alias="menu/light/quit.svg">icons/menu/light/quit.svg</file>
<file alias="menu/light/disconnect.png" preprocess="to-pixdata">icons/menu/light/disconnect.png</file>
<file alias="menu/light/disconnect.svg">icons/menu/light/disconnect.svg</file>
<file alias="menu/light/connect.png" preprocess="to-pixdata">icons/menu/light/connect.png</file>
<file alias="menu/light/connect.svg">icons/menu/light/connect.svg</file>
<file alias="menu/light/join.png" preprocess="to-pixdata">icons/menu/light/join.png</file>
<file alias="menu/light/join.svg">icons/menu/light/join.svg</file>
<file alias="menu/light/chanlist.png" preprocess="to-pixdata">icons/menu/light/chanlist.png</file>
<file alias="menu/light/chanlist.svg">icons/menu/light/chanlist.svg</file>
<file alias="menu/light/preferences.png" preprocess="to-pixdata">icons/menu/light/preferences.png</file>
<file alias="menu/light/preferences.svg">icons/menu/light/preferences.svg</file>
<file alias="menu/light/clear.png" preprocess="to-pixdata">icons/menu/light/clear.png</file>
<file alias="menu/light/clear.svg">icons/menu/light/clear.svg</file>
<file alias="menu/light/copy.png" preprocess="to-pixdata">icons/menu/light/copy.png</file>
<file alias="menu/light/copy.svg">icons/menu/light/copy.svg</file>
<file alias="menu/light/delete.png" preprocess="to-pixdata">icons/menu/light/delete.png</file>
<file alias="menu/light/delete.svg">icons/menu/light/delete.svg</file>
<file alias="menu/light/add.png" preprocess="to-pixdata">icons/menu/light/add.png</file>
<file alias="menu/light/add.svg">icons/menu/light/add.svg</file>
<file alias="menu/light/remove.png" preprocess="to-pixdata">icons/menu/light/remove.png</file>
<file alias="menu/light/remove.svg">icons/menu/light/remove.svg</file>
<file alias="menu/light/spell-check.png" preprocess="to-pixdata">icons/menu/light/spell-check.png</file>
<file alias="menu/light/spell-check.svg">icons/menu/light/spell-check.svg</file>
<file alias="menu/light/save.png" preprocess="to-pixdata">icons/menu/light/save.png</file>
<file alias="menu/light/save.svg">icons/menu/light/save.svg</file>
<file alias="menu/light/save-as.png" preprocess="to-pixdata">icons/menu/light/save-as.png</file>
<file alias="menu/light/save-as.svg">icons/menu/light/save-as.svg</file>
<file alias="menu/light/refresh.png" preprocess="to-pixdata">icons/menu/light/refresh.png</file>
<file alias="menu/light/refresh.svg">icons/menu/light/refresh.svg</file>
<file alias="menu/light/search.png" preprocess="to-pixdata">icons/menu/light/search.png</file>
<file alias="menu/light/search.svg">icons/menu/light/search.svg</file>
<file alias="menu/light/find.png" preprocess="to-pixdata">icons/menu/light/find.png</file>
<file alias="menu/light/find.svg">icons/menu/light/find.svg</file>
<file alias="menu/light/previous.png" preprocess="to-pixdata">icons/menu/light/previous.png</file>
<file alias="menu/light/previous.svg">icons/menu/light/previous.svg</file>
<file alias="menu/light/next.png" preprocess="to-pixdata">icons/menu/light/next.png</file>
<file alias="menu/light/next.svg">icons/menu/light/next.svg</file>
<file alias="menu/light/help.png" preprocess="to-pixdata">icons/menu/light/help.png</file>
<file alias="menu/light/help.svg">icons/menu/light/help.svg</file>
<file alias="menu/light/about.png" preprocess="to-pixdata">icons/menu/light/about.png</file>
<file alias="menu/light/about.svg">icons/menu/light/about.svg</file>
<file alias="menu/light/update.png" preprocess="to-pixdata">icons/menu/light/update.png</file>
<file alias="menu/light/update.svg">icons/menu/light/update.svg</file>
<file alias="menu/light/emoji.png" preprocess="to-pixdata">icons/menu/light/emoji.png</file>
<file alias="menu/light/emoji.svg">icons/menu/light/emoji.svg</file>
<file alias="menu/dark/new.png" preprocess="to-pixdata">icons/menu/dark/new.png</file>
<file alias="menu/dark/new.svg">icons/menu/dark/new.svg</file>
<file alias="menu/dark/network-list.png" preprocess="to-pixdata">icons/menu/dark/network-list.png</file>
<file alias="menu/dark/network-list.svg">icons/menu/dark/network-list.svg</file>
<file alias="menu/dark/load-plugin.png" preprocess="to-pixdata">icons/menu/dark/load-plugin.png</file>
<file alias="menu/dark/load-plugin.svg">icons/menu/dark/load-plugin.svg</file>
<file alias="menu/dark/detach.png" preprocess="to-pixdata">icons/menu/dark/detach.png</file>
<file alias="menu/dark/detach.svg">icons/menu/dark/detach.svg</file>
<file alias="menu/dark/close.png" preprocess="to-pixdata">icons/menu/dark/close.png</file>
<file alias="menu/dark/close.svg">icons/menu/dark/close.svg</file>
<file alias="menu/dark/quit.png" preprocess="to-pixdata">icons/menu/dark/quit.png</file>
<file alias="menu/dark/quit.svg">icons/menu/dark/quit.svg</file>
<file alias="menu/dark/disconnect.png" preprocess="to-pixdata">icons/menu/dark/disconnect.png</file>
<file alias="menu/dark/disconnect.svg">icons/menu/dark/disconnect.svg</file>
<file alias="menu/dark/connect.png" preprocess="to-pixdata">icons/menu/dark/connect.png</file>
<file alias="menu/dark/connect.svg">icons/menu/dark/connect.svg</file>
<file alias="menu/dark/join.png" preprocess="to-pixdata">icons/menu/dark/join.png</file>
<file alias="menu/dark/join.svg">icons/menu/dark/join.svg</file>
<file alias="menu/dark/chanlist.png" preprocess="to-pixdata">icons/menu/dark/chanlist.png</file>
<file alias="menu/dark/chanlist.svg">icons/menu/dark/chanlist.svg</file>
<file alias="menu/dark/preferences.png" preprocess="to-pixdata">icons/menu/dark/preferences.png</file>
<file alias="menu/dark/preferences.svg">icons/menu/dark/preferences.svg</file>
<file alias="menu/dark/clear.png" preprocess="to-pixdata">icons/menu/dark/clear.png</file>
<file alias="menu/dark/clear.svg">icons/menu/dark/clear.svg</file>
<file alias="menu/dark/copy.png" preprocess="to-pixdata">icons/menu/dark/copy.png</file>
<file alias="menu/dark/copy.svg">icons/menu/dark/copy.svg</file>
<file alias="menu/dark/delete.png" preprocess="to-pixdata">icons/menu/dark/delete.png</file>
<file alias="menu/dark/delete.svg">icons/menu/dark/delete.svg</file>
<file alias="menu/dark/add.png" preprocess="to-pixdata">icons/menu/dark/add.png</file>
<file alias="menu/dark/add.svg">icons/menu/dark/add.svg</file>
<file alias="menu/dark/remove.png" preprocess="to-pixdata">icons/menu/dark/remove.png</file>
<file alias="menu/dark/remove.svg">icons/menu/dark/remove.svg</file>
<file alias="menu/dark/spell-check.png" preprocess="to-pixdata">icons/menu/dark/spell-check.png</file>
<file alias="menu/dark/spell-check.svg">icons/menu/dark/spell-check.svg</file>
<file alias="menu/dark/save.png" preprocess="to-pixdata">icons/menu/dark/save.png</file>
<file alias="menu/dark/save.svg">icons/menu/dark/save.svg</file>
<file alias="menu/dark/save-as.png" preprocess="to-pixdata">icons/menu/dark/save-as.png</file>
<file alias="menu/dark/save-as.svg">icons/menu/dark/save-as.svg</file>
<file alias="menu/dark/refresh.png" preprocess="to-pixdata">icons/menu/dark/refresh.png</file>
<file alias="menu/dark/refresh.svg">icons/menu/dark/refresh.svg</file>
<file alias="menu/dark/search.png" preprocess="to-pixdata">icons/menu/dark/search.png</file>
<file alias="menu/dark/search.svg">icons/menu/dark/search.svg</file>
<file alias="menu/dark/find.png" preprocess="to-pixdata">icons/menu/dark/find.png</file>
<file alias="menu/dark/find.svg">icons/menu/dark/find.svg</file>
<file alias="menu/dark/previous.png" preprocess="to-pixdata">icons/menu/dark/previous.png</file>
<file alias="menu/dark/previous.svg">icons/menu/dark/previous.svg</file>
<file alias="menu/dark/next.png" preprocess="to-pixdata">icons/menu/dark/next.png</file>
<file alias="menu/dark/next.svg">icons/menu/dark/next.svg</file>
<file alias="menu/dark/help.png" preprocess="to-pixdata">icons/menu/dark/help.png</file>
<file alias="menu/dark/help.svg">icons/menu/dark/help.svg</file>
<file alias="menu/dark/about.png" preprocess="to-pixdata">icons/menu/dark/about.png</file>
<file alias="menu/dark/about.svg">icons/menu/dark/about.svg</file>
<file alias="menu/dark/update.png" preprocess="to-pixdata">icons/menu/dark/update.png</file>
<file alias="menu/dark/update.svg">icons/menu/dark/update.svg</file>
<file alias="menu/dark/emoji.png" preprocess="to-pixdata">icons/menu/dark/emoji.png</file>
<file alias="menu/dark/emoji.svg">icons/menu/dark/emoji.svg</file>
</gresource>
</gresources>

10
debian/changelog vendored
View File

@@ -1,13 +1,3 @@
zoitechat (2.18.0~pre2-1) unstable; urgency=medium
* New upstream pre-release 2.18.0~pre2.
* Added HexChat plugin compatibility improvements.
* Fixed user info right-click menu refresh behavior.
* Added support for emoji characters in alert highlight matching.
* Removed remaining unused GTK2 code paths.
-- ZoiteChat Maintainers <zoitechat@users.noreply.github.com> Wed, 25 Feb 2026 02:16:43 +0000
zoitechat (2.18.0~pre1-1) unstable; urgency=medium
* New upstream pre-release 2.18.0~pre1.

2
debian/control vendored
View File

@@ -39,7 +39,7 @@ Suggests:
zoitechat-python3,
zoitechat-otr,
unifont
Description: IRC client for GNOME (fork of HexChat 2.18.0~pre2 base)
Description: IRC client for GNOME (fork of HexChat 2.18.0-pre1 base)
ZoiteChat is a graphical IRC client with a GTK 3 GUI. Features include Python,
Perl and Lua scripting support, a plugin API, multiple server/channel
windows, spell checking, multiple authentication methods including SASL, and

1
debian/rules vendored
View File

@@ -7,6 +7,7 @@ export DH_VERBOSE=1
override_dh_auto_configure:
dh_auto_configure -- \
-Dgtk3=true \
-Dinstall-plugin-metainfo=false \
-Dwith-lua=lua53

View File

@@ -1,5 +1,4 @@
usr/lib/*/zoitechat/plugins/python.so
usr/lib/*/zoitechat/python/_zoitechat.py
usr/lib/*/zoitechat/python/hexchat.py
usr/lib/*/zoitechat/python/xchat.py
usr/lib/*/zoitechat/python/zoitechat.py

View File

@@ -1,31 +1,24 @@
{
"app-id": "net.zoite.Zoitechat",
"branch": "master",
"branch": "stable",
"runtime": "org.gnome.Platform",
"runtime-version": "49",
"sdk": "org.gnome.Sdk",
"command": "zoitechat",
"finish-args": [
"--share=ipc",
"--socket=x11",
"--socket=wayland",
"--share=network",
"--socket=pulseaudio",
"--filesystem=xdg-download",
"--filesystem=xdg-data/themes:ro",
"--filesystem=xdg-data/icons:ro",
"--filesystem=~/.themes:ro",
"--filesystem=~/.icons:ro",
"--filesystem=xdg-run/tray-icon:create",
"--talk-name=org.freedesktop.Notifications",
"--talk-name=org.kde.StatusNotifierWatcher",
"--talk-name=com.canonical.AppMenu.Registrar",
"--talk-name=org.mpris.MediaPlayer2.*"
],
"add-extensions": {
"net.zoite.Zoitechat.Plugin": {
"version": "49",
"version": "20.08",
"directory": "extensions",
"add-ld-path": "lib",
"merge-dirs": "lib/zoitechat/plugins",
@@ -36,7 +29,7 @@
},
"modules": [
"shared-modules/dbus-glib/dbus-glib.json",
"shared-modules/lua5.4/lua-5.4.json",
"shared-modules/lua5.3/lua-5.3.5.json",
"shared-modules/libcanberra/libcanberra.json",
"shared-modules/libayatana-appindicator/libayatana-appindicator-gtk3.json",
"python3-cffi.json",
@@ -47,7 +40,7 @@
{
"type": "git",
"url": "https://github.com/pavouk/lgi.git",
"commit": "c9b8e4473c6421f2a215d8c06c0d94b86eb0b26a"
"commit": "95418635aa8151a516d43166227ea2b9d4c4403f"
}
]
},
@@ -55,6 +48,8 @@
"name": "zoitechat",
"buildsystem": "meson",
"config-opts": [
"--buildtype=release",
"-Dgtk3=true",
"-Ddbus-service-use-appid=true",
"-Dwith-perl=false",
"-Dwith-python=false",

View File

@@ -1,5 +1,5 @@
project('zoitechat', 'c',
version: '2.18.0~pre2',
version: '2.18.0-pre1',
meson_version: '>= 0.55.0',
default_options: [
'c_std=c17',
@@ -10,6 +10,7 @@ project('zoitechat', 'c',
i18n = import('i18n')
gnome = import('gnome')
fs = import('fs')
cc = meson.get_compiler('c')
@@ -18,7 +19,14 @@ libgmodule_dep = dependency('gmodule-2.0')
libcanberra_dep = dependency('libcanberra', version: '>= 0.22',
required: get_option('libcanberra'))
dbus_glib_dep = dependency('dbus-glib-1', required: get_option('dbus'))
dbus_required = get_option('dbus')
if host_machine.system() == 'darwin'
if dbus_required.enabled()
warning('dbus-glib is not available on macOS; disabling DBus support')
endif
dbus_required = false
endif
dbus_glib_dep = dependency('dbus-glib-1', required: dbus_required)
global_deps = []
if cc.get_id() == 'msvc'
@@ -28,6 +36,82 @@ else
required: get_option('tls'))
endif
darwin_arch_sanity_check = get_option('darwin-arch-sanity-check')
if host_machine.system() == 'darwin' and darwin_arch_sanity_check
darwin_arch_sanity_check_env = run_command('sh', '-c', 'printf %s "$ZOITECHAT_DARWIN_ARCH_SANITY_CHECK"', check: false).stdout().strip().to_lower()
if ['0', 'false', 'no', 'off'].contains(darwin_arch_sanity_check_env)
darwin_arch_sanity_check = false
endif
endif
if host_machine.system() == 'darwin' and darwin_arch_sanity_check
cflags_env = run_command('sh', '-c', 'printf %s "$CFLAGS"', check: false).stdout().strip()
ldflags_env = run_command('sh', '-c', 'printf %s "$LDFLAGS"', check: false).stdout().strip()
c_args_opt = ' ' + ' '.join(get_option('c_args')) + ' '
c_link_args_opt = ' ' + ' '.join(get_option('c_link_args')) + ' '
all_cflags = cflags_env + ' ' + c_args_opt
all_ldflags = ldflags_env + ' ' + c_link_args_opt
pkgconfig_glib = run_command('pkg-config', '--libs-only-L', 'glib-2.0', check: false)
targeting_x86_64 = all_cflags.contains('-arch x86_64') or all_ldflags.contains('-arch x86_64')
targeting_arm64 = all_cflags.contains('-arch arm64') or all_ldflags.contains('-arch arm64')
targeting_universal = targeting_x86_64 and targeting_arm64
using_arm_homebrew = pkgconfig_glib.returncode() == 0 and pkgconfig_glib.stdout().contains('/opt/homebrew/')
if targeting_x86_64 and not targeting_universal and using_arm_homebrew
error('Detected x86_64 build flags (-arch x86_64) while pkg-config resolves glib from /opt/homebrew (arm64). ' +
'Use arm64 build flags with /opt/homebrew, use a universal build (-arch arm64 -arch x86_64) with universal dependencies, or run an x86_64/Rosetta environment with an x86_64 dependency stack (typically /usr/local). ' +
'To bypass this safety check, configure with -Ddarwin-arch-sanity-check=false or set ZOITECHAT_DARWIN_ARCH_SANITY_CHECK=0.')
endif
if targeting_x86_64
# When building x86_64-only or universal binaries on Apple Silicon,
# pkg-config can still resolve arm64-only Homebrew libraries.
# Detect this at configure time and fail fast with a clear message.
macos_link_deps = [
['gio-2.0', 'libgio-2.0.dylib'],
['gobject-2.0', 'libgobject-2.0.dylib'],
['glib-2.0', 'libglib-2.0.dylib'],
['gmodule-2.0', 'libgmodule-2.0.dylib'],
['openssl', 'libssl.dylib'],
['openssl', 'libcrypto.dylib'],
['libintl', 'libintl.dylib'],
]
foreach dep_spec : macos_link_deps
dep_pkg = dep_spec[0]
dep_lib = dep_spec[1]
dep_libdir_cmd = run_command('pkg-config', '--libs-only-L', dep_pkg, check: false)
if dep_libdir_cmd.returncode() != 0
continue
endif
foreach dep_libdir_arg : dep_libdir_cmd.stdout().strip().split()
if not dep_libdir_arg.startswith('-L')
continue
endif
dep_lib_path = join_paths(dep_libdir_arg.substring(2), dep_lib)
if not fs.exists(dep_lib_path)
continue
endif
dep_archs = run_command('lipo', '-archs', dep_lib_path, check: false)
if dep_archs.returncode() != 0
continue
endif
if not dep_archs.stdout().contains('x86_64')
error('Detected x86_64 build flags, but dependency ' + dep_lib_path +
' does not contain x86_64 architecture (archs: ' + dep_archs.stdout().strip() + '). ' +
'Use dependencies that include x86_64 (or universal) slices, or build only arm64. ' +
'To bypass this safety check, configure with -Ddarwin-arch-sanity-check=false or set ZOITECHAT_DARWIN_ARCH_SANITY_CHECK=0.')
endif
endforeach
endforeach
endif
endif
config_h = configuration_data()
config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
config_h.set_quoted('PACKAGE_NAME', meson.project_name())
@@ -42,7 +126,6 @@ config_h.set('USE_OPENSSL', libssl_dep.found())
config_h.set('USE_LIBCANBERRA', libcanberra_dep.found())
config_h.set('USE_DBUS', dbus_glib_dep.found())
config_h.set('USE_PLUGIN', get_option('plugin'))
config_h.set('USE_GTK_FRONTEND', get_option('gtk-frontend'))
config_h.set('G_DISABLE_SINGLE_INCLUDES', true)
config_h.set('GTK_DISABLE_DEPRECATED', true)
@@ -178,7 +261,6 @@ if meson.version().version_compare('>= 0.55.0')
}, section: 'Directories')
summary({
'GTK Frontend': get_option('gtk-frontend') ? 'enabled (GTK+ 3.22+)' : 'disabled',
'TLS (openssl)': libssl_dep.found(),
'Plugin Support': get_option('plugin'),
'DBus Support': dbus_glib_dep.found(),

View File

@@ -2,6 +2,9 @@
option('gtk-frontend', type: 'boolean',
description: 'Main graphical interface'
)
option('gtk3', type: 'boolean', value: false,
description: 'Build GTK frontend against GTK 3'
)
option('text-frontend', type: 'boolean', value: false,
description: 'Text interface (not generally useful)'
)
@@ -19,8 +22,8 @@ option('dbus', type: 'feature', value: 'auto',
option('libcanberra', type: 'feature', value: 'auto',
description: 'Support for sound alerts, Unix only'
)
option('appindicator', type: 'feature', value: 'auto',
description: 'Use Ayatana/AppIndicator-based tray backend for GTK frontend (non-Windows only)'
option('darwin-arch-sanity-check', type: 'boolean', value: true,
description: 'Fail fast when macOS build flags and Homebrew dependency architectures are mixed'
)
# Install options

View File

@@ -3,16 +3,24 @@
import os
import sys
import subprocess
import shutil
prefix = os.environ.get('MESON_INSTALL_PREFIX', '/usr/local')
datadir = os.path.join(prefix, 'share')
# Packaging tools define DESTDIR and this isn't needed for them
if 'DESTDIR' not in os.environ:
def run_if_available(command, *args):
if shutil.which(command) is None:
print(f'Skipping {command}: command not found')
return
subprocess.call([command, *args])
print('Updating icon cache...')
subprocess.call(['gtk-update-icon-cache', '-qtf',
os.path.join(datadir, 'icons', 'hicolor')])
run_if_available('gtk-update-icon-cache', '-qtf',
os.path.join(datadir, 'icons', 'hicolor'))
print('Updating desktop database...')
subprocess.call(['update-desktop-database', '-q',
os.path.join(datadir, 'applications')])
run_if_available('update-desktop-database', '-q',
os.path.join(datadir, 'applications'))

207
osx/DEBUGGING.md Normal file
View File

@@ -0,0 +1,207 @@
# Debugging ZoiteChat on macOS (Xcode + CLI)
If the unsigned `.app` launches but does nothing (or immediately exits), use the steps below to get actionable logs and a debugger session.
## 1) Build with debug symbols
ZoiteChat uses Meson. Build a debug configuration first so LLDB can show useful backtraces.
```bash
meson setup build-macos-debug --buildtype=debug
meson compile -C build-macos-debug
```
This project default is `debugoptimized`, but a full `debug` build is better while diagnosing crashes/startup issues.
## 2) Bundle the app and verify deployment target
Use the existing bundle script:
```bash
cd osx
./makebundle.sh
```
The generated `Info.plist` should keep:
- `LSMinimumSystemVersion = 11.0`
That is the projects explicit minimum runtime target for macOS 11+.
## 3) Sanity-check the Mach-O binary in the bundle
Confirm architecture(s), deployment target, and linked libraries:
```bash
file ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
otool -l ZoiteChat.app/Contents/MacOS/ZoiteChat-bin | rg -n "LC_BUILD_VERSION|minos|sdk"
otool -L ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
```
For widest compatibility, build universal (`arm64` + `x86_64`) or build separately per arch and test each on matching hosts.
## 4) Ad-hoc sign for local debugging
Unsigned GUI binaries can fail in unhelpful ways because of hardened runtime/quarantine/Gatekeeper interactions. For local debugging, ad-hoc sign the app:
```bash
xattr -dr com.apple.quarantine ZoiteChat.app
codesign --force --deep --sign - ZoiteChat.app
codesign --verify --deep --strict --verbose=2 ZoiteChat.app
```
## 5) Launch from Terminal first (before Xcode)
Direct launch exposes stdout/stderr and validates the launcher environment:
```bash
./ZoiteChat.app/Contents/MacOS/ZoiteChat
```
The launcher script sets GTK/Pango/GDK environment variables. If direct launch fails, capture that output first.
## 6) Debug with LLDB (reliable baseline)
Debug the real executable inside the bundle:
```bash
lldb -- ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
(lldb) run
(lldb) bt
```
If it exits instantly, set breakpoints on startup entry points (for example `main`) and re-run.
## 7) Debug with Xcode (if you prefer GUI)
Xcode works best when opening the executable directly instead of importing build scripts.
1. **File → Open…** and select `ZoiteChat.app/Contents/MacOS/ZoiteChat-bin`.
2. In **Product → Scheme → Edit Scheme…**
- Executable: `ZoiteChat-bin`
- Working directory: repo root (or `osx/`)
- Add environment variables equivalent to the launcher if needed.
3. Run under debugger.
If Xcode “runs” but no UI appears, compare its environment to `osx/launcher.sh` and copy missing GTK-related variables into the scheme.
## 8) Capture macOS crash diagnostics
Even if no dialog appears, macOS usually logs termination reasons:
```bash
log stream --style compact --predicate 'process == "ZoiteChat-bin"'
```
Also check:
- `~/Library/Logs/DiagnosticReports/`
## 9) Frequent root causes for “silent” startup failures
- Missing GTK runtime libraries in app bundle (`otool -L` shows unresolved paths).
- Incorrect `@rpath`/install names after bundling.
- Running under Rosetta mismatch (x86_64 binary with arm64-only deps or vice versa).
- Quarantine/signature issues on unsigned artifacts.
- Missing `GDK_PIXBUF_MODULE_FILE`, `GTK_IM_MODULE_FILE`, or schema paths.
### "Bad CPU type in executable"
This means the bundled `ZoiteChat-bin` architecture does not match the Mac you are running on.
- Intel Mac requires `x86_64`
- Apple Silicon requires `arm64` (or Rosetta + `x86_64`)
Check the binary quickly:
```bash
file ZoiteChat.app/Contents/MacOS/ZoiteChat-bin
```
Build for Intel explicitly when needed:
```bash
export CFLAGS="-arch x86_64"
export LDFLAGS="-arch x86_64"
meson setup build-macos-intel --buildtype=debug
meson compile -C build-macos-intel
```
If your dependency stack supports it, build universal (`arm64` + `x86_64`) and verify with `lipo -info`.
### Linker says `found architecture 'arm64', required architecture 'x86_64'`
If you see warnings like this during `meson compile`:
```text
ld: warning: ignoring file '/opt/homebrew/.../libgio-2.0.dylib': found architecture 'arm64', required architecture 'x86_64'
Undefined symbols for architecture x86_64: ...
```
your compile target architecture and dependency architecture do not match.
On Apple Silicon, this usually means you are trying to build `x86_64` while linking against ARM Homebrew libraries from `/opt/homebrew`.
Quick checks:
```bash
echo "$CFLAGS" "$LDFLAGS"
pkg-config --libs glib-2.0
lipo -info "$(brew --prefix glib)/lib/libglib-2.0.dylib"
```
Use one of these consistent setups:
- Native Apple Silicon build (`arm64`) with `/opt/homebrew` dependencies.
- Intel build (`x86_64`) with an x86_64 dependency stack (typically Homebrew under `/usr/local` run under Rosetta).
Example x86_64 setup on Apple Silicon:
```bash
# Open a Rosetta shell first (or prefix commands with `arch -x86_64`)
arch -x86_64 /bin/bash -lc '
export PATH="/usr/local/bin:$PATH"
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig"
export CFLAGS="-arch x86_64"
export LDFLAGS="-arch x86_64"
meson setup build-macos-x86_64 --prefix="/usr/local"
meson compile -C build-macos-x86_64
'
```
If you do not specifically need Intel compatibility, remove any forced `-arch x86_64` flags and build native `arm64`.
Example with this repo's scripts:
```bash
PREFIX="$(brew --prefix)"
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson setup build-macos-arm64 --prefix="$PREFIX"
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson setup build-macos-x86_64 --prefix="$PREFIX"
CFLAGS="-arch arm64" LDFLAGS="-arch arm64" meson compile -C build-macos-arm64
CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" meson compile -C build-macos-x86_64
sudo meson install -C build-macos-arm64
cd osx
UNIVERSAL=1 \
UNIVERSAL_BINARIES="../build-macos-arm64/src/fe-gtk/zoitechat ../build-macos-x86_64/src/fe-gtk/zoitechat" \
./makebundle.sh
```
## 10) Recommended compatibility settings for macOS 11+
- Keep `LSMinimumSystemVersion` at `11.0`.
- Build on the oldest macOS SDK/toolchain that still supports your dependencies, or explicitly set:
```bash
export MACOSX_DEPLOYMENT_TARGET=11.0
```
- Verify with `otool -l` that `minos` is actually `11.0` in the final executable.
---
If you want, we can add an Xcode scheme file to this repo that mirrors `osx/launcher.sh` so “Run” in Xcode behaves exactly like launching the app bundle from Finder/Terminal.

View File

@@ -11,7 +11,7 @@
<key>CFBundleIconFile</key>
<string>zoitechat.icns</string>
<key>CFBundleIdentifier</key>
<string>org.zoitechat</string>
<string>net.zoite.Zoitechat</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
@@ -41,6 +41,6 @@
<key>NSHumanReadableCopyright</key>
<string></string>
<key>LSMinimumSystemVersion</key>
<string>10.4</string>
<string>11.0</string>
</dict>
</plist>

View File

@@ -1,13 +1,13 @@
#!/bin/sh
#!/usr/bin/env bash
if test "x$GTK_DEBUG_LAUNCHER" != x; then
set -x
fi
if test "x$GTK_DEBUG_GDB" != x; then
EXEC="gdb --args"
EXEC_PREFIX=(gdb --args)
else
EXEC=exec
EXEC_PREFIX=()
fi
name=`basename "$0"`
@@ -23,25 +23,34 @@ bundle_data="$bundle_res"/share
bundle_etc="$bundle_res"/etc
export PREFIX="$bundle_res"
export DYLD_LIBRARY_PATH="$bundle_lib"
# launcher-script: runtime environment for bundled GTK3 on macOS.
# Expected package prefixes when building the app bundle:
# Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel)
# MacPorts: /opt/local
# Required libraries include GTK3, Pango, GDK-Pixbuf and enchant.
# Keep DYLD path hacks to a minimum; install_name_tool should resolve most libs.
if test -n "${DYLD_LIBRARY_PATH:-}"; then
export DYLD_LIBRARY_PATH="$bundle_lib:$DYLD_LIBRARY_PATH"
fi
export XDG_CONFIG_DIRS="$bundle_etc"/xdg
export XDG_DATA_DIRS="$bundle_data"
export GTK_DATA_PREFIX="$bundle_res"
export GTK_EXE_PREFIX="$bundle_res"
export GTK_PATH="$bundle_res"
export GTK_THEME="Mac"
export GTK_KEY_THEME="Mac"
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-3.0/gtk.immodules"
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-3.0/gdk-pixbuf.loaders"
export PANGO_LIBDIR="$bundle_lib"
export PANGO_SYSCONFDIR="$bundle_etc"
export GSETTINGS_SCHEMA_DIR="$bundle_data/glib-2.0/schemas"
export OPENSSL_CONF="/System/Library/OpenSSL/openssl.cnf"
export ZOITECHAT_LIBDIR="$bundle_lib/zoitechat/plugins"
APP=name
APP=zoitechat
I18NDIR="$bundle_data/locale"
# Set the locale-related variables appropriately:
unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
@@ -49,7 +58,7 @@ unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
# Has a language ordering been set?
# If so, set LC_MESSAGES and LANG accordingly; otherwise skip it.
# First step uses sed to clean off the quotes and commas, to change - to _, and change the names for the chinese scripts from "Hans" to CN and "Hant" to TW.
APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `
APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages 2>/dev/null | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `
if test "$APPLELANGUAGES"; then
# A language ordering exists.
# Test, item per item, to see whether there is an corresponding locale.
@@ -80,26 +89,26 @@ fi
unset APPLELANGUAGES L
# If we didn't get a language from the language list, try the Collation preference, in case it's the only setting that exists.
APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder`
if test -z ${LANG} -a -n $APPLECOLLATION; then
APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null || true`
if test -z "${LANG:-}" -a -n "${APPLECOLLATION:-}"; then
if test -f "$I18NDIR/${APPLECOLLATION:0:2}/LC_MESSAGES/$APP.mo"; then
export LANG=${APPLECOLLATION:0:2}
fi
fi
if test ! -z $APPLECOLLATION; then
if test -n "${APPLECOLLATION:-}"; then
export LC_COLLATE=$APPLECOLLATION
fi
unset APPLECOLLATION
# Continue by attempting to find the Locale preference.
APPLELOCALE=`defaults read .GlobalPreferences AppleLocale`
APPLELOCALE=`defaults read .GlobalPreferences AppleLocale 2>/dev/null || true`
if test -f "$I18NDIR/${APPLELOCALE:0:5}/LC_MESSAGES/$APP.mo"; then
if test -z $LANG; then
if test -z "${LANG:-}"; then
export LANG="${APPLELOCALE:0:5}"
fi
elif test -z $LANG -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then
elif test -z "${LANG:-}" -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then
export LANG="${APPLELOCALE:0:2}"
fi
@@ -107,20 +116,20 @@ fi
#5-character locale to avoid the "Locale not supported by C library"
#warning from Gtk -- even though Gtk will translate with a
#two-character code.
if test -n $LANG; then
if test -n "${LANG:-}"; then
#If the language code matches the applelocale, then that's the message
#locale; otherwise, if it's longer than two characters, then it's
#probably a good message locale and we'll go with it.
if test $LANG == ${APPLELOCALE:0:5} -o $LANG != ${LANG:0:2}; then
if test "$LANG" = "${APPLELOCALE:0:5}" -o "$LANG" != "${LANG:0:2}"; then
export LC_MESSAGES=$LANG
#Next try if the Applelocale is longer than 2 chars and the language
#bit matches $LANG
elif test $LANG == ${APPLELOCALE:0:2} -a $APPLELOCALE > ${APPLELOCALE:0:2}; then
elif test "$LANG" = "${APPLELOCALE:0:2}" -a "$APPLELOCALE" \> "${APPLELOCALE:0:2}"; then
export LC_MESSAGES=${APPLELOCALE:0:5}
#Fail. Get a list of the locales in $PREFIX/share/locale that match
#our two letter language code and pick the first one, special casing
#english to set en_US
elif test $LANG == "en"; then
elif test "$LANG" = "en"; then
export LC_MESSAGES="en_US"
else
LOC=`find $PREFIX/share/locale -name $LANG???`
@@ -172,4 +181,18 @@ if /bin/expr "x$1" : '^x-psn_' > /dev/null; then
shift 1
fi
$EXEC "$bundle_contents/MacOS/$name-bin" "$@" $EXTRA_ARGS
BIN_PATH="$bundle_contents/MacOS/$name-bin"
if test ${#EXEC_PREFIX[@]} -gt 0; then
"${EXEC_PREFIX[@]}" "$BIN_PATH" "$@" $EXTRA_ARGS
else
"$BIN_PATH" "$@" $EXTRA_ARGS
fi
status=$?
if test "$status" -eq 126; then
echo "error: $BIN_PATH could not execute on this Mac (possible architecture mismatch)." >&2
if command -v file >/dev/null 2>&1; then
file "$BIN_PATH" >&2 || true
fi
echo "hint: build ZoiteChat for this architecture (x86_64 on Intel, arm64 on Apple Silicon) or as a universal binary." >&2
fi
exit "$status"

View File

@@ -1,11 +1,210 @@
#!/bin/sh
rm -rf ZoiteChat.app
rm -f *.app.zip
set -eu
python $HOME/.local/bin/gtk-mac-bundler zoitechat.bundle
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
cd "$SCRIPT_DIR"
BUNDLE_DEF="zoitechat.bundle"
APP_NAME="ZoiteChat.app"
HOST_ARCH="$(uname -m 2>/dev/null || echo unknown)"
if [ -z "${TARGET_ARCHES+x}" ]; then
TARGET_ARCHES="$HOST_ARCH"
fi
UNIVERSAL_BINARIES="${UNIVERSAL_BINARIES:-}"
UNIVERSAL_BUILD_DIRS="${UNIVERSAL_BUILD_DIRS:-../build-macos-arm64 ../build-macos-x86_64}"
if [ "${UNIVERSAL:-0}" = "1" ]; then
TARGET_ARCHES="arm64 x86_64"
fi
# Expected prefixes for macOS GTK dependencies:
# - Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel)
# - MacPorts: /opt/local
# Required runtime stack includes GTK3, Pango, GDK-Pixbuf and enchant.
if command -v gtk-mac-bundler >/dev/null 2>&1; then
BUNDLER_CMD="gtk-mac-bundler"
elif command -v python3 >/dev/null 2>&1 && python3 -c 'import gtk_mac_bundler' >/dev/null 2>&1; then
BUNDLER_CMD="python3 -m gtk_mac_bundler"
else
cat >&2 <<'MSG'
error: gtk-mac-bundler not found.
Install one of the following before running osx/makebundle.sh:
- executable: gtk-mac-bundler
- python module: gtk_mac_bundler (invoked via: python3 -m gtk_mac_bundler)
MSG
exit 1
fi
rm -rf "$APP_NAME"
rm -f ./*.app.zip
# Enchant packaging changed between releases/package managers:
# - some installs provide share/enchant
# - others provide share/enchant-2
# - some have no share-level config dir at all
# Keep the bundle definition in sync with what's actually available so
# gtk-mac-bundler doesn't fail on a missing source path.
# Resolve package-manager prefix dynamically so Intel (/usr/local) and
# Apple Silicon (/opt/homebrew) hosts both bundle correctly.
BUNDLE_PREFIX="${BUNDLE_PREFIX:-}"
if [ -z "$BUNDLE_PREFIX" ] && command -v brew >/dev/null 2>&1; then
BUNDLE_PREFIX="$(brew --prefix 2>/dev/null || true)"
fi
if [ -z "$BUNDLE_PREFIX" ]; then
BUNDLE_PREFIX="/usr/local"
fi
# Keep a caller-provided trailing slash so gtk-mac-bundler path concatenation
# does not produce malformed locale paths like ".../x86_64locale/...".
# CI explicitly sets BUNDLE_PREFIX with a trailing slash.
BUNDLE_PREFIX_XML="$BUNDLE_PREFIX"
ENCHANT_PREFIX_DEFAULT="${BUNDLE_PREFIX}/opt/enchant"
ENCHANT_PREFIX_PATH="${ENCHANT_PREFIX:-$ENCHANT_PREFIX_DEFAULT}"
perl -0pi -e 's|(<prefix\s+name="default">)[^<]+(</prefix>)|$1'"$BUNDLE_PREFIX_XML"'$2|s' "$BUNDLE_DEF"
perl -0pi -e 's|(<prefix\s+name="enchant">)[^<]+(</prefix>)|$1'"$ENCHANT_PREFIX_PATH"'$2|s' "$BUNDLE_DEF"
if command -v brew >/dev/null 2>&1; then
BREW_ENCHANT_PREFIX="$(brew --prefix enchant 2>/dev/null || true)"
if [ -n "$BREW_ENCHANT_PREFIX" ]; then
ENCHANT_PREFIX_PATH="$BREW_ENCHANT_PREFIX"
perl -0pi -e 's|(<prefix\s+name="enchant">)[^<]+(</prefix>)|$1'"$ENCHANT_PREFIX_PATH"'$2|s' "$BUNDLE_DEF"
fi
fi
if [ -n "$ENCHANT_PREFIX_PATH" ]; then
if [ -d "$ENCHANT_PREFIX_PATH/share/enchant" ]; then
perl -0pi -e 's|(<data>\s*)\$\{prefix:enchant\}/share/enchant(?:-2)?(\s*</data>)|$1\$\{prefix:enchant\}/share/enchant$2|s' "$BUNDLE_DEF"
elif [ -d "$ENCHANT_PREFIX_PATH/share/enchant-2" ]; then
perl -0pi -e 's|(<data>\s*)\$\{prefix:enchant\}/share/enchant(?:-2)?(\s*</data>)|$1\$\{prefix:enchant\}/share/enchant-2$2|s' "$BUNDLE_DEF"
else
perl -0pi -e 's|\n\s*<data>\s*\$\{prefix:enchant\}/share/enchant(?:-2)?\s*</data>\n|\n|s' "$BUNDLE_DEF"
fi
fi
# GTK module extension differs across package manager builds:
# - Homebrew commonly installs .dylib modules
# - Some environments still ship .so modules
# Detect what exists in the staged prefix and rewrite the bundle definition
# so gtk-mac-bundler does not fail on a missing glob.
GTK_MODULE_EXT="so"
if find "$BUNDLE_PREFIX/lib/gtk-3.0" -type f \( -path '*/immodules/*.dylib' -o -path '*/printbackends/*.dylib' \) -print -quit 2>/dev/null | grep -q . \
|| find "$BUNDLE_PREFIX/lib/gdk-pixbuf-2.0" -type f -path '*/loaders/*.dylib' -print -quit 2>/dev/null | grep -q .; then
GTK_MODULE_EXT="dylib"
fi
if [ "$GTK_MODULE_EXT" = "dylib" ]; then
perl -0pi -e 's|(/immodules/)\*\.so|$1*.dylib|g; s|(/printbackends/)\*\.so|$1*.dylib|g; s|(/loaders/)\*\.so|$1*.dylib|g' "$BUNDLE_DEF"
else
perl -0pi -e 's|(/immodules/)\*\.dylib|$1*.so|g; s|(/printbackends/)\*\.dylib|$1*.so|g; s|(/loaders/)\*\.dylib|$1*.so|g' "$BUNDLE_DEF"
fi
# Some staged builds omit GTK runtime module directories entirely
# (for example stripped-down CI artifacts). Remove bundle entries for
# missing globs so gtk-mac-bundler does not abort.
if ! find "$BUNDLE_PREFIX/lib/gtk-3.0" -type f -path "*/immodules/*.${GTK_MODULE_EXT}" -print -quit 2>/dev/null | grep -q .; then
perl -0pi -e 's#\n\s*<binary>\s*\$\{prefix\}/lib/\$\{gtkdir\}/\$\{pkg:\$\{gtk\}:gtk_binary_version\}/immodules/\*\.(?:so|dylib)\s*</binary>\n#\n#g' "$BUNDLE_DEF"
fi
if ! find "$BUNDLE_PREFIX/lib/gtk-3.0" -type f -path "*/printbackends/*.${GTK_MODULE_EXT}" -print -quit 2>/dev/null | grep -q .; then
perl -0pi -e 's#\n\s*<binary>\s*\$\{prefix\}/lib/\$\{gtkdir\}/\$\{pkg:\$\{gtk\}:gtk_binary_version\}/printbackends/\*\.(?:so|dylib)\s*</binary>\n#\n#g' "$BUNDLE_DEF"
fi
if ! find "$BUNDLE_PREFIX/lib/gdk-pixbuf-2.0" -type f -path "*/loaders/*.${GTK_MODULE_EXT}" -print -quit 2>/dev/null | grep -q .; then
perl -0pi -e 's#\n\s*<binary>\s*\$\{prefix\}/lib/gdk-pixbuf-2\.0/\$\{pkg:gdk-pixbuf-2\.0:gdk_pixbuf_binary_version\}/loaders/\*\.(?:so|dylib)\s*</binary>\n#\n#g' "$BUNDLE_DEF"
fi
# Keep Info.plist generation deterministic by always rendering from template
# using a single, explicit version source.
VERSION_STRING="${VERSION:-$(sed -n "s/^ version: '\([^']*\)',$/\1/p" ../meson.build | head -n1)}"
if [ -z "$VERSION_STRING" ]; then
echo "error: unable to determine VERSION_STRING for Info.plist" >&2
exit 1
fi
TMP_PLIST="Info.plist.tmp"
LC_ALL=C sed "s/@VERSION@/$VERSION_STRING/g" Info.plist.in > "$TMP_PLIST"
mv -f "$TMP_PLIST" Info.plist
# shellcheck disable=SC2086
$BUNDLER_CMD "$BUNDLE_DEF"
if [ ! -d "$APP_NAME" ]; then
echo "error: bundler finished but $APP_NAME was not created" >&2
exit 1
fi
BIN_PATH="$APP_NAME/Contents/MacOS/ZoiteChat-bin"
if [ "${UNIVERSAL:-0}" = "1" ] && [ -z "$UNIVERSAL_BINARIES" ]; then
for build_dir in $UNIVERSAL_BUILD_DIRS; do
candidate="$build_dir/src/fe-gtk/zoitechat"
if [ -f "$candidate" ]; then
UNIVERSAL_BINARIES="${UNIVERSAL_BINARIES:+$UNIVERSAL_BINARIES }$candidate"
fi
done
if [ -z "$UNIVERSAL_BINARIES" ]; then
cat >&2 <<'MSG'
error: UNIVERSAL=1 requested, but no source binaries were found.
Set UNIVERSAL_BINARIES to one or more architecture-specific zoitechat binaries,
or place builds at:
../build-macos-arm64/src/fe-gtk/zoitechat
../build-macos-x86_64/src/fe-gtk/zoitechat
MSG
exit 1
fi
fi
if [ -n "$UNIVERSAL_BINARIES" ]; then
if ! command -v lipo >/dev/null 2>&1; then
echo "error: UNIVERSAL_BINARIES requires lipo, but lipo is unavailable" >&2
exit 1
fi
for binary in $UNIVERSAL_BINARIES; do
if [ ! -f "$binary" ]; then
echo "error: universal source binary not found: $binary" >&2
exit 1
fi
done
echo "Creating universal ZoiteChat-bin from: $UNIVERSAL_BINARIES"
# shellcheck disable=SC2086
lipo -create $UNIVERSAL_BINARIES -output "$BIN_PATH"
fi
if command -v lipo >/dev/null 2>&1; then
BIN_ARCHS="$(lipo -archs "$BIN_PATH" 2>/dev/null || true)"
if [ -z "$BIN_ARCHS" ]; then
echo "error: unable to detect architectures for $BIN_PATH" >&2
exit 1
fi
for required_arch in $TARGET_ARCHES; do
if ! echo " $BIN_ARCHS " | grep -q " $required_arch "; then
cat >&2 <<MSG
error: bundled binary architecture mismatch.
required: $TARGET_ARCHES
actual: $BIN_ARCHS
hint: rebuild ZoiteChat-bin with matching architecture(s) before bundling.
MSG
exit 1
fi
done
fi
if command -v file >/dev/null 2>&1; then
echo "Bundled binary architecture:"
file "$BIN_PATH" || true
fi
echo "Compressing bundle"
#hdiutil create -format UDBZ -srcdir ZoiteChat.app -quiet ZoiteChat-2.9.6.1-$(git rev-parse --short master).dmg
zip -9rXq ./ZoiteChat-$(git describe --tags).app.zip ./ZoiteChat.app
ARCHIVE_VERSION="$(git describe --tags --always 2>/dev/null || true)"
if [ -z "$ARCHIVE_VERSION" ]; then
ARCHIVE_VERSION="$VERSION_STRING"
fi
zip -9rXq "./ZoiteChat-$ARCHIVE_VERSION.app.zip" "./$APP_NAME"

View File

@@ -1,5 +0,0 @@
[Settings]
gtk-theme-name=Mac
gtk-key-theme-name=Mac
gtk-menu-images=0
gtk-button-images=0

View File

@@ -2,12 +2,15 @@
<app-bundle>
<meta>
<!-- Expected prefixes:
Homebrew: /opt/homebrew (Apple Silicon) or /usr/local (Intel)
MacPorts: /opt/local -->
<prefix name="default">/usr/local</prefix>
<prefix name="enchant">/usr/local/opt/enchant-applespell</prefix>
<prefix name="enchant">/usr/local/opt/enchant</prefix>
<destination overwrite="yes">${project}</destination>
<run-install-name-tool/>
<launcher-script>${project}/launcher.sh</launcher-script >
<run-install-name-tool>yes</run-install-name-tool>
<launcher-script>${project}/launcher.sh</launcher-script>
<gtk>gtk+-3.0</gtk>
</meta>
@@ -21,35 +24,31 @@
${prefix}/lib/zoitechat/plugins/*.so
</binary>
<!-- Enchant 2 runtime layout (Homebrew/MacPorts):
- core dylib in lib/
- provider modules in lib/enchant-2/ loaded via dlopen()
- config files in share/enchant/ -->
<binary>
${prefix:enchant}/lib/libenchant.dylib
${prefix:enchant}/lib/libenchant-2*.dylib
</binary>
<binary>
${prefix:enchant}/lib/enchant/libenchant_applespell.so
${prefix:enchant}/lib/enchant-2
</binary>
<data>
${prefix:enchant}/share/enchant
</data>
<!-- GTK3 runtime modules: ${prefix}/lib/${gtkdir} -->
<binary>
${prefix}/lib/${gtkdir}/modules/*.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libquartz.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libxamarin.so
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/*.so
</binary>
<binary>
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
</binary>
<data>
${prefix}/share/themes/Mac/gtk-3.0/gtk-keys.css
</data>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
</binary>
<translations name="gtk30">
${prefix}/share/locale
</translations>
@@ -57,10 +56,6 @@
${prefix}/share/locale
</translations>
<data dest="${bundle}/Contents/Resources/etc/${gtkdir}/settings.ini">
${project}/settings.ini
</data>
<data dest="${bundle}/Contents/Resources">
${project}/zoitechat.icns
</data>

Binary file not shown.

View File

@@ -1,70 +0,0 @@
# Maintainer: ZoiteChat Maintainers <zoitechat@users.noreply.github.com>
pkgname=zoitechat-git
pkgver=0
pkgrel=1
pkgdesc='IRC client for GNOME (ZoiteChat development snapshot)'
arch=('x86_64')
url='https://github.com/zoitechat/zoitechat'
license=('GPL-2.0-or-later')
depends=(
'dbus-glib'
'glib2'
'gtk3'
'iso-codes'
'libcanberra'
'lua'
'openssl'
'perl'
'python-cffi'
)
makedepends=(
'git'
'meson'
'ninja'
'pkgconf'
'python'
)
optdepends=(
'libayatana-appindicator: Ayatana/AppIndicator tray backend'
'pciutils: sysinfo plugin hardware detection details'
)
provides=('zoitechat')
conflicts=('zoitechat')
_repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source=("zoitechat::git+file://${_repo_root}")
sha256sums=('SKIP')
pkgver() {
cd "$srcdir/zoitechat"
if git describe --long --tags --abbrev=7 >/dev/null 2>&1; then
git describe --long --tags --abbrev=7 \
| sed 's/^v//' \
| sed -E 's/([^-]+)-([0-9]+)-g/\1.r\2.g/' \
| sed 's/-/./g'
else
printf '0.r%s.%s\n' \
"$(git rev-list --count HEAD)" \
"$(git rev-parse --short=7 HEAD)"
fi
}
build() {
arch-meson zoitechat build \
-Dtext-frontend=false \
-Dwith-checksum=true \
-Dwith-fishlim=true \
-Dwith-lua=lua \
-Dwith-perl=perl \
-Dwith-python=python3 \
-Dwith-sysinfo=true \
-Dinstall-plugin-metainfo=true
meson compile -C build
}
package() {
meson install -C build --destdir "$pkgdir"
}

View File

@@ -1,8 +1,8 @@
name : zoitechat
version : 2.18.0~pre2
release : 2
version : 2.18.0-pre1
release : 1
source :
- https://github.com/ZoiteChat/zoitechat/archive/e060d57baee1be22bee1f9c3b047be3fa71c6d35.tar.gz : ed315a0b1c46e798912fd830d3845427972857c43ccaa16284969c6f542add38
- https://github.com/ZoiteChat/zoitechat/archive/refs/tags/zoitechat-2.18.0-pre1.tar.gz : 77d787cf00abd533326440eab01ca077c21cdfd2eb56807fc21d6fb70f34ada6
homepage : https://zoitechat.zoite.net/
license : GPL-2.0-only
component : network.irc
@@ -20,12 +20,13 @@ builddeps :
- pkgconfig(iso-codes)
- meson
- ninja
- pkgconf
- pkgconfig
- gcc
- gettext
setup : |
%meson_configure \
-Dgtk-frontend=true \
-Dgtk3=true \
-Dinstall-appdata=true
build : |
%ninja_build

View File

@@ -75,7 +75,7 @@ dh1080_init (void)
BN_set_word (g, 2);
#ifndef HAVE_DH_SET0_PQG
#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
g_dh->p = p;
g_dh->g = g;
#else
@@ -163,7 +163,7 @@ dh1080_generate_key (char **priv_key, char **pub_key)
return 0;
}
#ifndef HAVE_DH_GET0_KEY
#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
dh_pub_key = dh->pub_key;
dh_priv_key = dh->priv_key;
#else
@@ -190,9 +190,6 @@ dh1080_compute_key (const char *priv_key, const char *pub_key, char **secret_key
gsize pub_key_len;
BIGNUM *pk;
DH *dh;
#ifdef HAVE_DH_SET0_KEY
BIGNUM *temp_pub_key = BN_new();
#endif
g_assert (secret_key != NULL);
@@ -217,10 +214,10 @@ dh1080_compute_key (const char *priv_key, const char *pub_key, char **secret_key
priv_key_data = dh1080_decode_b64 (priv_key, &priv_key_len);
priv_key_num = BN_bin2bn(priv_key_data, priv_key_len, NULL);
#ifndef HAVE_DH_SET0_KEY
#if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
dh->priv_key = priv_key_num;
#else
DH_set0_key (dh, temp_pub_key, priv_key_num);
DH_set0_key (dh, NULL, priv_key_num);
#endif
shared_len = DH_compute_key (shared_key, pk, dh);

View File

@@ -1105,8 +1105,6 @@ static int luaopen_zoitechat(lua_State *L)
lua_pushinteger(L, ZOITECHAT_PRI_LOWEST); lua_setfield(L, -2, "PRI_LOWEST");
lua_pushinteger(L, ZOITECHAT_EAT_NONE); lua_setfield(L, -2, "EAT_NONE");
lua_pushinteger(L, ZOITECHAT_EAT_ZOITECHAT); lua_setfield(L, -2, "EAT_ZOITECHAT");
lua_pushinteger(L, ZOITECHAT_EAT_ZOITECHAT); lua_setfield(L, -2, "EAT_XCHAT");
lua_pushinteger(L, ZOITECHAT_EAT_ZOITECHAT); lua_setfield(L, -2, "EAT_HEXCHAT");
lua_pushinteger(L, ZOITECHAT_EAT_PLUGIN); lua_setfield(L, -2, "EAT_PLUGIN");
lua_pushinteger(L, ZOITECHAT_EAT_ALL); lua_setfield(L, -2, "EAT_ALL");
@@ -1273,13 +1271,6 @@ static void prepare_state(lua_State *L, script_info *info)
lua_setfield(L, LUA_REGISTRYINDEX, registry_field);
luaopen_zoitechat(L);
lua_setglobal(L, "zoitechat");
lua_getglobal(L, "zoitechat");
lua_setglobal(L, "xchat");
lua_getglobal(L, "zoitechat");
lua_setglobal(L, "hexchat");
lua_getglobal(L, "zoitechat");
lua_getfield(L, -1, "print");
lua_setglobal(L, "print");

View File

@@ -22,7 +22,31 @@ if get_option('with-fishlim')
subdir('fishlim')
endif
if get_option('with-lua') != 'false'
lua_option = get_option('with-lua')
if lua_option == 'auto' or lua_option == 'luajit'
lua_auto_dep = dependency('luajit', required: false)
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua-5.4', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua5.4', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua-5.3', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua5.3', required: false)
endif
if not lua_auto_dep.found()
lua_auto_dep = dependency('lua', required: false)
endif
if lua_auto_dep.found()
subdir('lua')
else
warning('LuaJIT/Lua development files not found, disabling Lua plugin')
endif
elif lua_option != 'false'
subdir('lua')
endif

View File

@@ -1 +0,0 @@
require ZoiteChat;

View File

@@ -53,16 +53,14 @@ sub ZoiteChat::Internal::print;
#keep compatibility with Xchat scripts
sub EAT_XCHAT ();
sub EAT_HEXCHAT ();
BEGIN {
*Xchat:: = *ZoiteChat::;
*HexChat:: = *ZoiteChat::;
}
our %EXPORT_TAGS = (
constants => [
qw(PRI_HIGHEST PRI_HIGH PRI_NORM PRI_LOW PRI_LOWEST), # priorities
qw(EAT_NONE EAT_ZOITECHAT EAT_XCHAT EAT_HEXCHAT EAT_PLUGIN EAT_ALL), # callback return values
qw(EAT_NONE EAT_ZOITECHAT EAT_XCHAT EAT_PLUGIN EAT_ALL), # callback return values
qw(FD_READ FD_WRITE FD_EXCEPTION FD_NOTSOCKET), # fd flags
qw(KEEP REMOVE), # timers
],

View File

@@ -4,7 +4,6 @@ zoitechat_perl_module = custom_target('zoitechat-perl-header',
input: [
'lib/ZoiteChat.pm',
'lib/Xchat.pm',
'lib/HexChat.pm',
'lib/ZoiteChat/Embed.pm',
'lib/ZoiteChat/List/Network.pm',
'lib/ZoiteChat/List/Network/Entry.pm',
@@ -28,9 +27,10 @@ endif
perl = find_program(get_option('with-perl'))
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ccopts'])
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ccopts'], check: false)
if ret.returncode() != 0
error('perl: Failed to get cflags')
warning('Perl development files not found, disabling Perl plugin')
subdir_done()
endif
foreach flag : ret.stdout().strip().split(' ')
if flag.startswith('-I') or flag.startswith('-D')
@@ -38,9 +38,10 @@ foreach flag : ret.stdout().strip().split(' ')
endif
endforeach
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ldopts'])
ret = run_command([perl, '-MExtUtils::Embed', '-e', 'ldopts'], check: false)
if ret.returncode() != 0
error('perl: Failed to get ldflags')
warning('Perl development files not found, disabling Perl plugin')
subdir_done()
endif
perl_ldflags = []
perl_rpath = ''
@@ -74,7 +75,8 @@ int main(void) {
return 0;
}
''', args: perl_cflags + perl_ldflags)
error('found perl not suitable for plugin')
warning('Found perl is not suitable for plugin, disabling Perl plugin')
subdir_done()
endif
perl_dep = declare_dependency(

View File

@@ -1365,7 +1365,6 @@ xs_init (pTHX)
newCONSTSUB (stash, "EAT_NONE", newSViv (ZOITECHAT_EAT_NONE));
newCONSTSUB (stash, "EAT_ZOITECHAT", newSViv (ZOITECHAT_EAT_ZOITECHAT));
newCONSTSUB (stash, "EAT_XCHAT", newSViv (ZOITECHAT_EAT_ZOITECHAT)); /* for compatibility */
newCONSTSUB (stash, "EAT_HEXCHAT", newSViv (ZOITECHAT_EAT_ZOITECHAT)); /* for compatibility */
newCONSTSUB (stash, "EAT_PLUGIN", newSViv (ZOITECHAT_EAT_PLUGIN));
newCONSTSUB (stash, "EAT_ALL", newSViv (ZOITECHAT_EAT_ALL));
newCONSTSUB (stash, "FD_READ", newSViv (ZOITECHAT_FD_READ));

View File

@@ -5,7 +5,7 @@ from contextlib import contextmanager
from _zoitechat_embedded import ffi, lib
__all__ = [
'EAT_ALL', 'EAT_ZOITECHAT', 'EAT_NONE', 'EAT_PLUGIN', 'EAT_XCHAT', 'EAT_HEXCHAT',
'EAT_ALL', 'EAT_ZOITECHAT', 'EAT_NONE', 'EAT_PLUGIN', 'EAT_XCHAT',
'PRI_HIGH', 'PRI_HIGHEST', 'PRI_LOW', 'PRI_LOWEST', 'PRI_NORM',
'__doc__', '__version__', 'command', 'del_pluginpref', 'emit_print',
'find_context', 'get_context', 'get_info',
@@ -22,7 +22,6 @@ __license__ = 'GPL-2.0+'
EAT_NONE = 0
EAT_ZOITECHAT = 1
EAT_XCHAT = EAT_ZOITECHAT
EAT_HEXCHAT = EAT_ZOITECHAT
EAT_PLUGIN = 2
EAT_ALL = EAT_ZOITECHAT | EAT_PLUGIN

View File

@@ -1 +0,0 @@
from _zoitechat import *

View File

@@ -19,7 +19,7 @@ python3_source = custom_target('python-bindings',
command: [find_program('generate_plugin.py'), '@INPUT@', '@OUTPUT@']
)
install_data(['_zoitechat.py', 'zoitechat.py', 'xchat.py', 'hexchat.py'],
install_data(['_zoitechat.py', 'zoitechat.py', 'xchat.py'],
install_dir: join_paths(get_option('libdir'), 'zoitechat/python')
)

View File

@@ -19,7 +19,7 @@ else:
if not hasattr(sys, 'argv'):
sys.argv = ['<zoitechat>']
VERSION = b'2.18.0~pre2' # Sync with zoitechat.__version__
VERSION = b'2.18.0-pre1' # Sync with zoitechat.__version__
PLUGIN_NAME = ffi.new('char[]', b'Python')
PLUGIN_DESC = ffi.new('char[]', b'Python %d.%d scripting interface' % (sys.version_info[0], sys.version_info[1]))
PLUGIN_VERSION = ffi.new('char[]', VERSION)
@@ -538,28 +538,8 @@ def _on_plugin_init(plugin_name, plugin_desc, plugin_version, arg, libdir):
try:
libdir = __decode(_cstr(libdir))
modpaths = [
os.path.abspath(os.path.join(libdir, '..', 'python')),
os.path.abspath(os.path.join(libdir, 'python')),
]
appdir = os.getenv('APPDIR')
if appdir:
modpaths.extend([
os.path.join(appdir, 'usr', 'lib', 'zoitechat', 'python'),
os.path.join(appdir, 'usr', 'lib', 'x86_64-linux-gnu', 'zoitechat', 'python'),
])
if os.getenv('FLATPAK_ID'):
modpaths.extend([
'/app/lib/zoitechat/python',
'/app/lib/x86_64-linux-gnu/zoitechat/python',
])
for modpath in modpaths:
if os.path.isdir(modpath) and modpath not in sys.path:
sys.path.append(modpath)
modpath = os.path.join(libdir, '..', 'python')
sys.path.append(os.path.abspath(modpath))
zoitechat = importlib.import_module('zoitechat')
except (UnicodeDecodeError, ImportError) as e:

View File

@@ -67,7 +67,6 @@
<None Include="python.def" />
<None Include="python.py" />
<None Include="xchat.py" />
<None Include="hexchat.py" />
<None Include="_zoitechat.py" />
</ItemGroup>
<ItemGroup>

View File

@@ -30,8 +30,5 @@
<None Include="xchat.py">
<Filter>Source Files</Filter>
</None>
<None Include="hexchat.py">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>
</Project>

View File

@@ -10,7 +10,7 @@ sysinfo_deps = [
]
sysinfo_includes = []
sysinfo_cargs = ['-DHAVE_CONFIG_H']
sysinfo_cargs = []
system = host_machine.system()
if system == 'linux' or system == 'gnu' or system.startswith('gnu/') or system == 'darwin' or system == 'freebsd'
@@ -19,10 +19,6 @@ if system == 'linux' or system == 'gnu' or system.startswith('gnu/') or system =
'shared/df.c'
]
if get_option('gtk-frontend')
sysinfo_cargs += '-DUSE_GTK_FRONTEND'
endif
if system == 'linux' or system == 'gnu' or system.startswith('gnu/') or system == 'freebsd'
libpci = dependency('libpci', required: false, method: 'pkg-config')
if libpci.found()
@@ -34,10 +30,6 @@ if system == 'linux' or system == 'gnu' or system.startswith('gnu/') or system =
pciids = join_paths(picidsdir, 'pci.ids')
sysinfo_cargs += '-DPCIIDS_FILE="@0@"'.format(pciids)
endif
if get_option('gtk-frontend')
sysinfo_deps += dependency('gtk+-3.0', version: '>= 3.22')
endif
sysinfo_includes += 'unix'
sysinfo_sources += [
'unix/backend.c',
@@ -60,7 +52,7 @@ endif
shared_module('sysinfo', sysinfo_sources,
dependencies: sysinfo_deps,
include_directories: [config_h_include, include_directories(sysinfo_includes)],
include_directories: include_directories(sysinfo_includes),
c_args: sysinfo_cargs,
install: true,
install_dir: plugindir,

View File

@@ -32,10 +32,6 @@
#include <glib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "format.h"
#include "df.h"
@@ -280,8 +276,12 @@ sysinfo_backend_get_network(void)
static const char *sysinfo_detect_toolkit(void)
{
#if defined(USE_GTK_FRONTEND)
#if defined(HAVE_GTK3)
return "GTK3";
#elif defined(HAVE_GTK2)
return "GTK2";
#elif defined(HAVE_GTK)
return "GTK";
#else
return NULL;
#endif

View File

@@ -32,7 +32,7 @@ char *sysinfo_backend_get_network(void);
/*
* Short description of the UI/toolkit + display backend.
* Examples: "GTK3 / Wayland", "Windows / GTK3".
* Examples: "GTK3 / Wayland", "GTK2 / X11", "Windows / GTK3".
*/
char *sysinfo_backend_get_ui(void);

View File

@@ -19,11 +19,7 @@
#include <glib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(USE_GTK_FRONTEND)
#if defined(HAVE_GTK3) || defined(HAVE_GTK2) || defined(HAVE_GTK)
#include <gdk/gdk.h>
#endif
#include "parse.h"
@@ -179,8 +175,12 @@ char *sysinfo_backend_get_network(void)
static const char *sysinfo_detect_toolkit(void)
{
#if defined(USE_GTK_FRONTEND)
#if defined(HAVE_GTK3)
return "GTK3";
#elif defined(HAVE_GTK2)
return "GTK2";
#elif defined(HAVE_GTK)
return "GTK";
#else
return NULL;
#endif
@@ -194,7 +194,7 @@ static const char *sysinfo_detect_display_backend(void)
const gboolean session_wayland = session && g_ascii_strcasecmp(session, "wayland") == 0;
/* Best-effort: ask GDK what it actually opened, if available. */
#if defined(USE_GTK_FRONTEND)
#if defined(HAVE_GTK3) || defined(HAVE_GTK2) || defined(HAVE_GTK)
{
GdkDisplay *display = gdk_display_get_default();
if (display)

View File

@@ -26,10 +26,6 @@
#include <glib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../../../src/common/sysinfo/sysinfo.h"
#include "../format.h"
@@ -110,8 +106,12 @@ static char *get_memory_info (void)
static const char *sysinfo_detect_toolkit(void)
{
#if defined(USE_GTK_FRONTEND)
#if defined(HAVE_GTK3)
return "GTK3";
#elif defined(HAVE_GTK2)
return "GTK2";
#elif defined(HAVE_GTK)
return "GTK";
#else
return NULL;
#endif

View File

@@ -5,6 +5,7 @@
[![Flatpak Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/flatpak-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/flatpak-build.yml)
[![AppImage Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/appimage-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/appimage-build.yml)
[![Windows Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/windows-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/windows-build.yml)
[![OpenBSD Build](https://github.com/ZoiteChat/zoitechat/actions/workflows/openbsd-build.yml/badge.svg)](https://github.com/ZoiteChat/zoitechat/actions/workflows/openbsd-build.yml)
[![Version][github-version-img]][github-version-uri] [![Downloads][github-downloads-img]][github-downloads-uri] [![Size][github-size-img]][github-size-img] [![Last Commit][github-commit-img]][github-commit-img] [![Contributors][contribs-all-img]](#contributors-)
@@ -36,9 +37,6 @@ See [IRCHelp.org](http://irchelp.org) for information about IRC in general.
For more information on ZoiteChat please read our [documentation](https://docs.zoitechat.zoite.net/):
- [Downloads](https://zoitechat.zoite.net/download)
- [Troubleshooting](troubleshooting.md)
---
<sub>
@@ -54,3 +52,7 @@ provide binary packages linked to the OpenSSL libraries, provided that
all other requirements of the GPL are met.
See file COPYING for details.
</sub>
## macOS debugging
If you are troubleshooting local macOS build/run/debug issues (including Xcode setup), see `osx/DEBUGGING.md`.

View File

@@ -222,51 +222,15 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id,
/* used for Alerts section. Masks can be separated by commas and spaces. */
static char *
alert_normalize_word (const char *text)
{
GString *normalized;
char *composed;
const char *p;
composed = g_utf8_normalize (text, -1, G_NORMALIZE_ALL_COMPOSE);
if (!composed)
composed = g_strdup (text);
normalized = g_string_sized_new (strlen (composed));
p = composed;
while (*p)
{
gunichar ch = g_utf8_get_char ((const guchar *)p);
/* Ignore selector/joiner codepoints that vary by input method. */
if (ch != 0x200D && ch != 0xFE0E && ch != 0xFE0F)
g_string_append_unichar (normalized, ch);
p = g_utf8_next_char (p);
}
g_free (composed);
return g_string_free (normalized, FALSE);
}
gboolean
alert_match_word (char *word, char *masks)
{
char *p = masks;
char endchar;
char *word_normalized;
char *mask_normalized;
int res;
word_normalized = alert_normalize_word (word);
if (masks[0] == 0)
{
g_free (word_normalized);
return FALSE;
}
while (1)
{
@@ -275,23 +239,15 @@ alert_match_word (char *word, char *masks)
{
endchar = *p;
*p = 0;
mask_normalized = alert_normalize_word (g_strchug (masks));
res = match (mask_normalized, word_normalized);
g_free (mask_normalized);
res = match (g_strchug (masks), word);
*p = endchar;
if (res)
{
g_free (word_normalized);
return TRUE; /* yes, matched! */
}
masks = p + 1;
if (*p == 0)
{
g_free (word_normalized);
return FALSE;
}
}
p++;
}
@@ -302,8 +258,6 @@ alert_match_text (char *text, char *masks)
{
unsigned char *p = text;
unsigned char endchar;
gunichar ch;
GUnicodeType ch_type;
int res;
if (masks[0] == 0)
@@ -311,38 +265,26 @@ alert_match_text (char *text, char *masks)
while (1)
{
ch = g_utf8_get_char (p);
ch_type = g_unichar_type (ch);
if (g_unichar_isdigit (ch) || g_unichar_isalpha (ch))
if (*p >= '0' && *p <= '9')
{
p += g_utf8_skip [p[0]];
p++;
continue;
}
/* if it's RFC1459 <special>, it can be inside a word */
switch (ch)
switch (*p)
{
case '-': case '[': case ']': case '\\':
case '`': case '^': case '{': case '}':
case '_': case '|':
p += g_utf8_skip [p[0]];
p++;
continue;
}
/* Symbols (including emoji) can be part of highlighted words. */
if (ch_type == G_UNICODE_MATH_SYMBOL ||
ch_type == G_UNICODE_CURRENCY_SYMBOL ||
ch_type == G_UNICODE_MODIFIER_SYMBOL ||
ch_type == G_UNICODE_OTHER_SYMBOL)
{
p += g_utf8_skip [p[0]];
continue;
}
/* Delimiters end the word. */
if (*p == 0 || g_unichar_isspace (ch) || g_unichar_ispunct (ch) ||
g_unichar_iscntrl (ch))
/* if it's a 0, space or comma, the word has ended. */
if (*p == 0 || *p == ' ' || *p == ',' ||
/* if it's anything BUT a letter, the word has ended. */
(!g_unichar_isalpha (g_utf8_get_char (p))))
{
endchar = *p;
*p = 0;

View File

@@ -55,39 +55,12 @@ if host_machine.system() == 'windows'
common_includes += include_directories('sysinfo')
endif
glib_genmarshal = find_program(
'glib-genmarshal',
'glib-genmarshal-2.0',
required: true,
marshal = gnome.genmarshal('marshal',
sources: 'marshalers.list',
prefix: '_zoitechat_marshal',
internal: true
)
marshal = [
custom_target('marshal_h',
input: 'marshalers.list',
output: 'marshal.h',
command: [
glib_genmarshal,
'--prefix=_zoitechat_marshal',
'--header',
'@INPUT@',
'--output',
'@OUTPUT@',
]
),
custom_target('marshal_c',
input: 'marshalers.list',
output: 'marshal.c',
command: [
glib_genmarshal,
'--prefix=_zoitechat_marshal',
'--body',
'@INPUT@',
'--output',
'@OUTPUT@',
]
)
]
make_te = find_program('make-te.py')
textevents = custom_target('textevents',
@@ -130,7 +103,7 @@ zoitechat_common_dep = declare_dependency(
link_with: zoitechat_common,
include_directories: common_includes,
compile_args: common_cflags,
dependencies: libgio_dep,
dependencies: common_deps,
)
zoitechat_plugin_dep = declare_dependency(

View File

@@ -4109,7 +4109,7 @@ const struct commands xc_cmds[] = {
{"ME", cmd_me, 0, 0, 1,
N_("ME <action>, sends the action to the current channel (actions are written in the 3rd person, like /me jumps)")},
{"MENU", cmd_menu, 0, 0, 1, "MENU [-eX] [-i<ICONFILE>] [-k<mod>,<key>] [-m] [-pX] [-r<X,group>] [-tX] {ADD|DEL} <path> [command] [unselect command]\n"
" See https://docs.zoitechat.zoite.net/en/latest/en/latest/plugins.html#controlling-the-gui for more details."},
" See http://zoitechat.zoite.net/docs/en/latest/plugins.html#controlling-the-gui for more details."},
{"MHOP", cmd_mhop, 1, 1, 1,
N_("MHOP, Mass hop's all users in the current channel (needs chanop)")},
{"MKICK", cmd_mkick, 1, 1, 1,

View File

@@ -1447,16 +1447,6 @@ server_child (server * serv)
GProxyResolver *resolver;
GError *error = NULL;
/*
* In Flatpak, auto proxy resolution may block indefinitely when
* proxy backends are unavailable in the sandbox. If this happens,
* the connection attempt appears to hang after pressing Connect.
* Prefer direct connections there unless the user configured a
* specific proxy manually.
*/
if (g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS))
goto proxy_lookup_done;
resolver = g_proxy_resolver_get_default ();
url = g_strdup_printf ("irc://%s:%d", hostname, port);
proxy_list = g_proxy_resolver_lookup (resolver, url, NULL, &error);
@@ -1487,8 +1477,6 @@ server_child (server * serv)
g_strfreev (proxy_list);
g_free (url);
proxy_lookup_done:;
}
if (prefs.hex_net_proxy_host[0] &&

View File

@@ -154,6 +154,7 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
X509 *peer_cert;
X509_PUBKEY *key;
X509_ALGOR *algor = NULL;
const ASN1_OBJECT *algor_obj = NULL;
EVP_PKEY *peer_pkey;
char notBefore[64];
char notAfter[64];
@@ -175,11 +176,19 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
if (!X509_PUBKEY_get0_param(NULL, NULL, 0, &algor, key))
return 1;
alg = OBJ_obj2nid (algor->algorithm);
#ifndef HAVE_X509_GET_SIGNATURE_NID
sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm);
#else
X509_ALGOR_get0 (&algor_obj, NULL, NULL, algor);
alg = OBJ_obj2nid (algor_obj);
#ifdef HAVE_X509_GET_SIGNATURE_NID
sign_alg = X509_get_signature_nid (peer_cert);
#else
{
const X509_ALGOR *signature_algor = NULL;
const ASN1_OBJECT *signature_algor_obj = NULL;
X509_get0_signature (NULL, &signature_algor, peer_cert);
X509_ALGOR_get0 (&signature_algor_obj, NULL, NULL, signature_algor);
sign_alg = OBJ_obj2nid (signature_algor_obj);
}
#endif
ASN1_TIME_snprintf (notBefore, sizeof (notBefore),
X509_get_notBefore (peer_cert));
@@ -298,7 +307,10 @@ SSL *
_SSL_socket (SSL_CTX *ctx, int sd)
{
SSL *ssl;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
const SSL_METHOD *method;
#endif
if (!(ssl = SSL_new (ctx)))
/* FATAL */
@@ -306,6 +318,12 @@ _SSL_socket (SSL_CTX *ctx, int sd)
SSL_set_fd (ssl, sd);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (SSL_is_server (ssl))
SSL_set_accept_state (ssl);
else
SSL_set_connect_state (ssl);
#else
#ifndef HAVE_SSL_CTX_GET_SSL_METHOD
method = ctx->method;
#else
@@ -314,7 +332,8 @@ _SSL_socket (SSL_CTX *ctx, int sd)
if (method == SSLv23_client_method())
SSL_set_connect_state (ssl);
else
SSL_set_accept_state(ssl);
SSL_set_accept_state (ssl);
#endif
return (ssl);
}

View File

@@ -229,10 +229,6 @@ zoitechat_remote_win32 (void)
{
sent = zoitechat_send_command_to_existing (hwnd, arg_command) || sent;
}
else if (arg_existing)
{
sent = zoitechat_send_command_to_existing (hwnd, "__WIN32_TASKBAR_TOGGLE__") || sent;
}
if (arg_urls)
{

View File

@@ -137,7 +137,11 @@ ascii_open (void)
if (table_pos[0] == '\n' || i == 0)
{
table_pos++;
#if HAVE_GTK3
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
#elif !HAVE_GTK3
hbox = gtk_hbox_new (0, 0);
#endif
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_widget_show (hbox);
i++;

View File

@@ -37,9 +37,16 @@
#include "maingui.h"
#include "banlist.h"
#if HAVE_GTK3
#define ICON_BANLIST_REMOVE "list-remove"
#define ICON_BANLIST_CLEAR "edit-clear"
#define ICON_BANLIST_REFRESH "view-refresh"
#endif
#if !HAVE_GTK3
#define ICON_BANLIST_REMOVE GTK_STOCK_REMOVE
#define ICON_BANLIST_CLEAR GTK_STOCK_CLEAR
#define ICON_BANLIST_REFRESH GTK_STOCK_REFRESH
#endif
/*
* These supports_* routines set capable, readable, writable bits */
@@ -488,6 +495,7 @@ banlist_unban_inner (gpointer none, banlist_info *banl, int mode_num)
int num_sel, i;
/* grab the list of selected items */
model = GTK_TREE_MODEL (get_store (sess));
sel = gtk_tree_view_get_selection (get_view (sess));
@@ -500,11 +508,14 @@ banlist_unban_inner (gpointer none, banlist_info *banl, int mode_num)
{
if (gtk_tree_selection_iter_is_selected (sel, &iter))
{
/* Get the mask part of this selected line */
gtk_tree_model_get (model, &iter, TYPE_COLUMN, &type, MASK_COLUMN, &mask, -1);
/* If it's the wrong type of mask, just continue */
if (strcmp (_(modes[mode_num].type), type) != 0)
continue;
/* Otherwise add it to our array of mask pointers */
masks[num_sel++] = g_strdup (mask);
g_free (mask);
g_free (type);
@@ -512,9 +523,11 @@ banlist_unban_inner (gpointer none, banlist_info *banl, int mode_num)
}
while (gtk_tree_model_iter_next (model, &iter));
/* and send to server */
if (num_sel)
send_channel_modes (sess, tbuf, masks, 0, num_sel, '-', modes[mode_num].letter, 0);
/* now free everything */
for (i=0; i < num_sel; i++)
g_free (masks[i]);
g_free (masks);
@@ -530,6 +543,7 @@ banlist_unban (GtkWidget * wid, banlist_info *banl)
for (i = 0; i < MODE_CT; i++)
num += banlist_unban_inner (wid, banl, i);
/* This really should not occur with the redesign */
if (num < 1)
{
fe_message (_("You must select some bans."), FE_MSG_ERROR);
@@ -595,11 +609,14 @@ banlist_crop (GtkWidget * wid, banlist_info *banl)
GSList *list = NULL, *node;
int num_sel;
/* remember which bans are selected */
select = gtk_tree_view_get_selection (get_view (sess));
/* gtk_tree_selected_get_selected_rows() isn't present in gtk 2.0.x */
gtk_tree_selection_selected_foreach (select, banlist_add_selected_cb,
&list);
num_sel = g_slist_length (list);
/* select all, then unselect those that we remembered */
if (num_sel)
{
gtk_tree_selection_select_all (select);
@@ -628,7 +645,7 @@ banlist_toggle (GtkWidget *item, gpointer data)
break;
}
if (bit)
if (bit) /* Should be gassert() */
{
banl->checked &= ~bit;
banl->checked |= (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item)))? bit: 0;
@@ -771,7 +788,11 @@ banlist_table_new (void)
{
GtkWidget *table = gtkutil_grid_new (1, MODE_CT, FALSE);
#if HAVE_GTK3
gtk_grid_set_column_spacing (GTK_GRID (table), 16);
#else
gtk_table_set_col_spacings (GTK_TABLE (table), 16);
#endif
return table;
}
@@ -836,8 +857,13 @@ banlist_opengui (struct session *sess)
GTKUTIL_ATTACH_FILL, GTKUTIL_ATTACH_FILL, 0, 0);
}
#if HAVE_GTK3
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
gtk_box_pack_end (GTK_BOX (vbox), bbox, 0, 0, 0);
gtk_widget_show (bbox);

View File

@@ -77,10 +77,15 @@ chanlistrow;
static void
chanlist_set_label_alignment (GtkWidget *widget)
{
#if HAVE_GTK3
gtk_widget_set_halign (widget, GTK_ALIGN_START);
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
#endif
}
#if HAVE_GTK3
static void
chanlist_grid_attach (GtkWidget *grid, GtkWidget *child,
gint column, gint row,
@@ -94,14 +99,19 @@ chanlist_grid_attach (GtkWidget *grid, GtkWidget *child,
gtk_widget_set_valign (child, valign);
gtk_grid_attach (GTK_GRID (grid), child, column, row, width, height);
}
#endif
static GtkWidget *
chanlist_box_new (void)
{
#if HAVE_GTK3
GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_set_homogeneous (GTK_BOX (box), FALSE);
return box;
#elif !HAVE_GTK3
return gtk_hbox_new (FALSE, 0);
#endif
}
static GtkWidget *
@@ -126,6 +136,7 @@ chanlist_icon_menu_item (const char *label, const char *icon_name,
GCallback callback, gpointer userdata)
{
GtkWidget *item;
#if HAVE_GTK3
GtkWidget *box;
GtkWidget *image = NULL;
GtkWidget *label_widget;
@@ -138,6 +149,13 @@ chanlist_icon_menu_item (const char *label, const char *icon_name,
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), label_widget, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (item), box);
#else
GtkWidget *image;
item = gtk_image_menu_item_new_with_mnemonic (label);
image = gtkutil_image_new_from_stock (icon_name, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
#endif
g_signal_connect (G_OBJECT (item), "activate", callback, userdata);
gtk_widget_show_all (item);
@@ -717,6 +735,7 @@ chanlist_button_cb (GtkTreeView *tree, GdkEventButton *event, server *serv)
menu_addfavoritemenu (serv, menu, chan, FALSE);
g_free (chan);
#if HAVE_GTK3
if (event)
{
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
@@ -728,6 +747,10 @@ chanlist_button_cb (GtkTreeView *tree, GdkEventButton *event, server *serv)
GDK_GRAVITY_NORTH_WEST,
NULL);
}
#endif
#if !HAVE_GTK3
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, event ? event->time : 0);
#endif
return TRUE;
}
@@ -879,48 +902,108 @@ chanlist_opengui (server *serv, int do_refresh)
/* ============================================================= */
#if HAVE_GTK3
table = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (table), 12);
gtk_grid_set_row_spacing (GTK_GRID (table), 3);
#else
table = gtk_table_new (4, 4, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 12);
gtk_table_set_row_spacings (GTK_TABLE (table), 3);
#endif
gtk_box_pack_start (GTK_BOX (vbox), table, 0, 1, 0);
gtk_widget_show (table);
#if HAVE_GTK3
wid = chanlist_icon_button (_("_Search"), ICON_CHANLIST_FIND,
G_CALLBACK (chanlist_search_pressed), serv);
#endif
#if !HAVE_GTK3
wid = gtkutil_button (NULL, ICON_CHANLIST_FIND, 0, chanlist_search_pressed, serv,
_("_Search"));
#endif
serv->gui->chanlist_search = wid;
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 3, 3, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), wid, 3, 4, 3, 4,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
#if HAVE_GTK3
wid = chanlist_icon_button (_("_Download List"), ICON_CHANLIST_REFRESH,
G_CALLBACK (chanlist_refresh), serv);
#endif
#if !HAVE_GTK3
wid = gtkutil_button (NULL, ICON_CHANLIST_REFRESH, 0, chanlist_refresh, serv,
_("_Download List"));
#endif
serv->gui->chanlist_refresh = wid;
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 3, 2, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), wid, 3, 4, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
#if HAVE_GTK3
wid = chanlist_icon_button (_("Save _List..."), ICON_CHANLIST_SAVE,
G_CALLBACK (chanlist_save), serv);
#endif
#if !HAVE_GTK3
wid = gtkutil_button (NULL, ICON_CHANLIST_SAVE, 0, chanlist_save, serv,
_("Save _List..."));
#endif
serv->gui->chanlist_savelist = wid;
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 3, 1, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), wid, 3, 4, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
#if HAVE_GTK3
wid = chanlist_icon_button (_("_Join Channel"), ICON_CHANLIST_JOIN,
G_CALLBACK (chanlist_join), serv);
#endif
#if !HAVE_GTK3
wid = gtkutil_button (NULL, ICON_CHANLIST_JOIN, 0, chanlist_join, serv,
_("_Join Channel"));
#endif
serv->gui->chanlist_join = wid;
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 3, 0, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), wid, 3, 4, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
/* ============================================================= */
wid = gtk_label_new (_("Show only:"));
chanlist_set_label_alignment (wid);
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 0, 3, 1, 1, FALSE, FALSE,
GTK_ALIGN_START, GTK_ALIGN_CENTER);
#else
gtk_table_attach (GTK_TABLE (table), wid, 0, 1, 3, 4,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
gtk_widget_show (wid);
hbox = chanlist_box_new ();
gtk_box_set_spacing (GTK_BOX (hbox), 9);
#if HAVE_GTK3
chanlist_grid_attach (table, hbox, 1, 3, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 3, 4,
GTK_FILL, GTK_FILL, 0, 0);
#endif
gtk_widget_show (hbox);
wid = gtk_label_new (_("channels with"));
@@ -956,14 +1039,24 @@ chanlist_opengui (server *serv, int do_refresh)
wid = gtk_label_new (_("Look in:"));
chanlist_set_label_alignment (wid);
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 0, 2, 1, 1, FALSE, FALSE,
GTK_ALIGN_START, GTK_ALIGN_CENTER);
#else
gtk_table_attach (GTK_TABLE (table), wid, 0, 1, 2, 3,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
gtk_widget_show (wid);
hbox = chanlist_box_new ();
gtk_box_set_spacing (GTK_BOX (hbox), 12);
#if HAVE_GTK3
chanlist_grid_attach (table, hbox, 1, 2, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 2, 3,
GTK_FILL, GTK_FILL, 0, 0);
#endif
gtk_widget_show (hbox);
wid = gtk_check_button_new_with_label (_("Channel name"));
@@ -988,8 +1081,13 @@ chanlist_opengui (server *serv, int do_refresh)
wid = gtk_label_new (_("Search type:"));
chanlist_set_label_alignment (wid);
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 0, 1, 1, 1, FALSE, FALSE,
GTK_ALIGN_START, GTK_ALIGN_CENTER);
#else
gtk_table_attach (GTK_TABLE (table), wid, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
gtk_widget_show (wid);
wid = gtk_combo_box_text_new ();
@@ -997,8 +1095,13 @@ chanlist_opengui (server *serv, int do_refresh)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (wid), _("Pattern Match (Wildcards)"));
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (wid), _("Regular Expression"));
gtk_combo_box_set_active (GTK_COMBO_BOX (wid), serv->gui->chanlist_search_type);
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 1, 1, 1, 1, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_CENTER);
#else
gtk_table_attach (GTK_TABLE (table), wid, 1, 2, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
g_signal_connect (G_OBJECT (wid), "changed",
G_CALLBACK (chanlist_combo_cb), serv);
gtk_widget_show (wid);
@@ -1007,8 +1110,13 @@ chanlist_opengui (server *serv, int do_refresh)
wid = gtk_label_new (_("Find:"));
chanlist_set_label_alignment (wid);
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 0, 0, 1, 1, FALSE, FALSE,
GTK_ALIGN_START, GTK_ALIGN_CENTER);
#else
gtk_table_attach (GTK_TABLE (table), wid, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
gtk_widget_show (wid);
wid = gtk_entry_new ();
@@ -1018,8 +1126,13 @@ chanlist_opengui (server *serv, int do_refresh)
g_signal_connect (G_OBJECT (wid), "activate",
G_CALLBACK (chanlist_search_pressed),
(gpointer) serv);
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 1, 0, 1, 1, TRUE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_CENTER);
#else
gtk_table_attach (GTK_TABLE (table), wid, 1, 2, 0, 1,
GTK_EXPAND | GTK_FILL, 0, 0, 0);
#endif
gtk_widget_show (wid);
serv->gui->chanlist_wild = wid;
@@ -1027,9 +1140,18 @@ chanlist_opengui (server *serv, int do_refresh)
/* ============================================================= */
#if HAVE_GTK3
wid = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
#else
wid = gtk_vseparator_new ();
#endif
#if HAVE_GTK3
chanlist_grid_attach (table, wid, 2, 0, 1, 5, FALSE, FALSE,
GTK_ALIGN_FILL, GTK_ALIGN_FILL);
#else
gtk_table_attach (GTK_TABLE (table), wid, 2, 3, 0, 5,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
gtk_widget_show (wid);
g_signal_connect (G_OBJECT (serv->gui->chanlist_window), "destroy",

View File

@@ -27,7 +27,12 @@ typedef struct
GtkWidget *b2; /* button2 */
} tabview;
#if HAVE_GTK3
#define ICON_CHANVIEW_CLOSE "window-close"
#endif
#if !HAVE_GTK3
#define ICON_CHANVIEW_CLOSE GTK_STOCK_CLOSE
#endif
static void chanview_populate (chanview *cv);
@@ -52,10 +57,17 @@ cv_tabs_get_viewport_size (GdkWindow *parent_win, gboolean vertical)
{
gint viewport_size = 0;
#if HAVE_GTK3
if (vertical)
viewport_size = gdk_window_get_height (parent_win);
else
viewport_size = gdk_window_get_width (parent_win);
#else
if (vertical)
gdk_window_get_geometry (parent_win, 0, 0, 0, &viewport_size, 0);
else
gdk_window_get_geometry (parent_win, 0, 0, &viewport_size, 0, 0);
#endif
return viewport_size;
}
@@ -281,9 +293,12 @@ static GtkWidget *
make_sbutton (GtkArrowType type, void *click_cb, void *userdata)
{
GtkWidget *button, *arrow;
#if HAVE_GTK3
const char *icon_name = "pan-end-symbolic";
#endif
button = gtk_button_new ();
#if HAVE_GTK3
switch (type)
{
case GTK_ARROW_UP:
@@ -302,6 +317,9 @@ make_sbutton (GtkArrowType type, void *click_cb, void *userdata)
}
arrow = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
#elif !HAVE_GTK3
arrow = gtk_arrow_new (type, GTK_SHADOW_NONE);
#endif
gtk_container_add (GTK_CONTAINER (button), arrow);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
g_signal_connect (G_OBJECT (button), "clicked",
@@ -528,12 +546,20 @@ tab_add_real (chanview *cv, GtkWidget *tab, chan *ch)
{
/* vertical */
box = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#if HAVE_GTK3
sep = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
#elif !HAVE_GTK3
sep = gtk_hseparator_new ();
#endif
} else
{
/* horiz */
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#if HAVE_GTK3
sep = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
#elif !HAVE_GTK3
sep = gtk_vseparator_new ();
#endif
}
gtk_box_pack_end (GTK_BOX (box), sep, 0, 0, 4);

View File

@@ -137,11 +137,21 @@ cv_tree_init (chanview *cv)
gtk_widget_set_vexpand (view, TRUE);
gtk_widget_set_name (view, "zoitechat-tree");
if (
#if HAVE_GTK3
cv->font_desc
#else
cv->style
#endif
)
{
#if HAVE_GTK3
gtkutil_apply_palette (view, &colors[COL_BG], &colors[COL_FG],
cv->font_desc);
#else
gtkutil_apply_palette (view, &cv->style->base[GTK_STATE_NORMAL],
&cv->style->text[GTK_STATE_NORMAL],
cv->style->font_desc);
#endif
}
/*gtk_widget_modify_base (view, GTK_STATE_NORMAL, &colors[COL_BG]);*/
gtk_widget_set_can_focus (view, FALSE);

View File

@@ -46,7 +46,11 @@ struct _chanview
int size; /* number of channels in view */
GtkWidget *box; /* the box we destroy when changing implementations */
#if HAVE_GTK3
PangoFontDescription *font_desc; /* font used for tree */
#else
InputStyle *style; /* style used for tree */
#endif
chan *focused; /* currently focused channel */
int trunc_len;
@@ -297,7 +301,11 @@ chanview_box_destroy_cb (GtkWidget *box, chanview *cv)
chanview *
chanview_new (int type, int trunc_len, gboolean sort, gboolean use_icons,
#if HAVE_GTK3
PangoFontDescription *font_desc
#else
InputStyle *style
#endif
)
{
chanview *cv;
@@ -305,8 +313,16 @@ chanview_new (int type, int trunc_len, gboolean sort, gboolean use_icons,
cv = g_new0 (chanview, 1);
cv->store = gtk_tree_store_new (5, G_TYPE_STRING, G_TYPE_POINTER,
PANGO_TYPE_ATTR_LIST, GDK_TYPE_PIXBUF, G_TYPE_INT);
#if HAVE_GTK3
cv->font_desc = font_desc;
#else
cv->style = style;
#endif
#if HAVE_GTK3
cv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
#elif !HAVE_GTK3
cv->box = gtk_hbox_new (0, 0);
#endif
cv->trunc_len = trunc_len;
cv->sorted = sort;
cv->use_icons = use_icons;

View File

@@ -26,7 +26,11 @@ typedef struct _chanview chanview;
typedef struct _chan chan;
chanview *chanview_new (int type, int trunc_len, gboolean sort, gboolean use_icons,
#if HAVE_GTK3
PangoFontDescription *font_desc
#else
InputStyle *style
#endif
);
void chanview_set_callbacks (chanview *cv,
void (*cb_focus) (chanview *, chan *, int tag, void *userdata),

View File

@@ -73,7 +73,11 @@ chanlistrow;
* structure. */
struct _CustomList
{
#if HAVE_GTK3
GObject parent_instance;
#else
GObject parent;
#endif
guint num_rows; /* number of rows that we have used */
guint num_alloc; /* number of rows allocated */

View File

@@ -37,10 +37,18 @@
#include "palette.h"
#include "maingui.h"
#if HAVE_GTK3
#define ICON_DCC_CANCEL "dialog-cancel"
#define ICON_DCC_ACCEPT "dialog-apply"
#define ICON_DCC_RESUME "view-refresh"
#define ICON_DCC_CLEAR "edit-clear"
#endif
#if !HAVE_GTK3
#define ICON_DCC_CANCEL GTK_STOCK_CANCEL
#define ICON_DCC_ACCEPT GTK_STOCK_APPLY
#define ICON_DCC_RESUME GTK_STOCK_REFRESH
#define ICON_DCC_CLEAR GTK_STOCK_CLEAR
#endif
enum /* DCC SEND/RECV */
@@ -108,6 +116,7 @@ static short view_mode; /* 1=download 2=upload 3=both */
#define VIEW_UPLOAD 2
#define VIEW_BOTH 3
#if HAVE_GTK3
static GdkPixbuf *
dcc_load_icon (const char *stock_name)
{
@@ -125,6 +134,7 @@ dcc_load_icon (const char *stock_name)
return gtk_icon_theme_load_icon (theme, icon_name, width, 0, NULL);
}
#endif
static void
@@ -182,6 +192,7 @@ dcc_store_color (GtkListStore *store, GtkTreeIter *iter, int column, int color_i
if (color_index != 1)
color = &colors[color_index];
#if HAVE_GTK3
if (color)
{
GdkRGBA rgba = *color;
@@ -191,6 +202,9 @@ dcc_store_color (GtkListStore *store, GtkTreeIter *iter, int column, int color_i
{
gtk_list_store_set (store, iter, column, NULL, -1);
}
#else
gtk_list_store_set (store, iter, column, color, -1);
#endif
}
static void
@@ -226,7 +240,12 @@ dcc_prepare_row_send (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
float per;
if (!pix_up)
#if HAVE_GTK3
pix_up = dcc_load_icon ("gtk-go-up");
#elif !HAVE_GTK3
pix_up = gtk_widget_render_icon (dccfwin.window, "gtk-go-up",
GTK_ICON_SIZE_MENU, NULL);
#endif
/* percentage ack'ed */
per = (float) ((dcc->ack * 100.00) / dcc->size);
@@ -275,7 +294,12 @@ dcc_prepare_row_recv (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
int to_go;
if (!pix_dn)
#if HAVE_GTK3
pix_dn = dcc_load_icon ("gtk-go-down");
#elif !HAVE_GTK3
pix_dn = gtk_widget_render_icon (dccfwin.window, "gtk-go-down",
GTK_ICON_SIZE_MENU, NULL);
#endif
proper_unit (dcc->size, size, sizeof (size));
if (dcc->dccstat == STAT_QUEUED)
@@ -767,19 +791,31 @@ dcc_detail_label (char *text, GtkWidget *box, int num)
label = gtk_label_new (NULL);
g_snprintf (buf, sizeof (buf), "<b>%s</b>", text);
gtk_label_set_markup (GTK_LABEL (label), buf);
#if HAVE_GTK3
gtk_widget_set_hexpand (label, FALSE);
gtk_widget_set_vexpand (label, FALSE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_START);
gtk_grid_attach (GTK_GRID (box), label, 0, 0 + num, 1, 1);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
gtk_table_attach (GTK_TABLE (box), label, 0, 1, 0 + num, 1 + num,
GTK_FILL, GTK_FILL, 0, 0);
#endif
label = gtk_label_new (NULL);
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_hexpand (label, FALSE);
gtk_widget_set_vexpand (label, FALSE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_START);
gtk_grid_attach (GTK_GRID (box), label, 1, 0 + num, 1, 1);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
gtk_table_attach (GTK_TABLE (box), label, 1, 2, 0 + num, 1 + num,
GTK_FILL, GTK_FILL, 0, 0);
#endif
return label;
}
@@ -878,63 +914,100 @@ fe_dcc_open_recv_win (int passive)
g_signal_connect (G_OBJECT (view), "row-activated",
G_CALLBACK (dcc_dclick_cb), NULL);
#if HAVE_GTK3
table = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (table), 16);
#else
table = gtk_table_new (1, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 16);
#endif
gtk_box_pack_start (GTK_BOX (vbox), table, 0, 0, 0);
radio = gtk_radio_button_new_with_mnemonic (NULL, _("Both"));
g_signal_connect (G_OBJECT (radio), "toggled",
G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_BOTH));
#if HAVE_GTK3
gtk_widget_set_hexpand (radio, FALSE);
gtk_widget_set_vexpand (radio, FALSE);
gtk_widget_set_halign (radio, GTK_ALIGN_FILL);
gtk_widget_set_valign (radio, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), radio, 3, 0, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
#endif
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
radio = gtk_radio_button_new_with_mnemonic (group, _("Uploads"));
g_signal_connect (G_OBJECT (radio), "toggled",
G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_UPLOAD));
#if HAVE_GTK3
gtk_widget_set_hexpand (radio, FALSE);
gtk_widget_set_vexpand (radio, FALSE);
gtk_widget_set_halign (radio, GTK_ALIGN_FILL);
gtk_widget_set_valign (radio, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), radio, 1, 0, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
#endif
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
radio = gtk_radio_button_new_with_mnemonic (group, _("Downloads"));
g_signal_connect (G_OBJECT (radio), "toggled",
G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_DOWNLOAD));
#if HAVE_GTK3
gtk_widget_set_hexpand (radio, FALSE);
gtk_widget_set_vexpand (radio, FALSE);
gtk_widget_set_halign (radio, GTK_ALIGN_FILL);
gtk_widget_set_valign (radio, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), radio, 2, 0, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
#endif
exp = gtk_expander_new (_("Details"));
#if HAVE_GTK3
gtk_widget_set_hexpand (exp, TRUE);
gtk_widget_set_vexpand (exp, FALSE);
gtk_widget_set_halign (exp, GTK_ALIGN_FILL);
gtk_widget_set_valign (exp, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), exp, 0, 0, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table), exp, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
#endif
#if HAVE_GTK3
detailbox = gtk_grid_new ();
gtk_grid_set_column_spacing (GTK_GRID (detailbox), 6);
gtk_grid_set_row_spacing (GTK_GRID (detailbox), 2);
gtk_container_set_border_width (GTK_CONTAINER (detailbox), 6);
#else
detailbox = gtk_table_new (3, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (detailbox), 6);
gtk_table_set_row_spacings (GTK_TABLE (detailbox), 2);
gtk_container_set_border_width (GTK_CONTAINER (detailbox), 6);
#endif
g_signal_connect (G_OBJECT (exp), "activate",
G_CALLBACK (dcc_exp_cb), detailbox);
#if HAVE_GTK3
gtk_widget_set_hexpand (detailbox, TRUE);
gtk_widget_set_vexpand (detailbox, FALSE);
gtk_widget_set_halign (detailbox, GTK_ALIGN_FILL);
gtk_widget_set_valign (detailbox, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), detailbox, 0, 1, 4, 1);
#else
gtk_table_attach (GTK_TABLE (table), detailbox, 0, 4, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
#endif
dccfwin.file_label = dcc_detail_label (_("File:"), detailbox, 0);
dccfwin.address_label = dcc_detail_label (_("Address:"), detailbox, 1);
#if HAVE_GTK3
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 2);
dccfwin.abort_button = gtkutil_button (bbox, ICON_DCC_CANCEL, 0, abort_clicked, 0, _("Abort"));
@@ -1136,8 +1209,13 @@ fe_dcc_open_chat_win (int passive)
g_signal_connect (G_OBJECT (view), "row-activated",
G_CALLBACK (dcc_chat_dclick_cb), NULL);
#if HAVE_GTK3
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 2);
dcccwin.abort_button = gtkutil_button (bbox, ICON_DCC_CANCEL, 0, abort_chat_clicked, 0, _("Abort"));

View File

@@ -42,10 +42,18 @@
#include "maingui.h"
#include "editlist.h"
#if HAVE_GTK3
#define ICON_EDITLIST_NEW "document-new"
#define ICON_EDITLIST_DELETE "edit-delete"
#define ICON_EDITLIST_CANCEL "dialog-cancel"
#define ICON_EDITLIST_SAVE "document-save"
#endif
#if !HAVE_GTK3
#define ICON_EDITLIST_NEW GTK_STOCK_NEW
#define ICON_EDITLIST_DELETE GTK_STOCK_DELETE
#define ICON_EDITLIST_CANCEL GTK_STOCK_CANCEL
#define ICON_EDITLIST_SAVE GTK_STOCK_SAVE
#endif
enum
{
@@ -353,8 +361,13 @@ editlist_gui_open (char *title1, char *title2, GSList *list, char *title, char *
if (help)
gtk_widget_set_tooltip_text (view, help);
#if HAVE_GTK3
box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
box = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 2);
gtk_container_set_border_width (GTK_CONTAINER (box), 5);
gtk_widget_show (box);

View File

@@ -589,6 +589,7 @@ fe_apply_windows_theme (gboolean dark)
g_object_set (settings, "gtk-application-prefer-dark-theme", dark, NULL);
}
#if HAVE_GTK3
{
static GtkCssProvider *win_theme_provider = NULL;
GdkScreen *screen = gdk_screen_get_default ();
@@ -612,6 +613,7 @@ fe_apply_windows_theme (gboolean dark)
GTK_STYLE_PROVIDER (win_theme_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
#endif
}
#endif
@@ -673,7 +675,7 @@ fe_apply_theme_to_toplevel (GtkWidget *window)
if (!window)
return;
#ifdef G_OS_WIN32
#if defined(G_OS_WIN32) && HAVE_GTK3
{
GtkStyleContext *context = gtk_widget_get_style_context (window);
gboolean dark = fe_dark_mode_is_enabled ();
@@ -716,6 +718,7 @@ create_input_style (InputStyle *style)
{
char buf[256];
static int done_rc = FALSE;
#if HAVE_GTK3
static GtkCssProvider *input_css_provider = NULL;
static char *last_theme_name = NULL;
static gboolean last_dark_mode = FALSE;
@@ -727,9 +730,12 @@ create_input_style (InputStyle *style)
static guint16 last_bg_red;
static guint16 last_bg_green;
static guint16 last_bg_blue;
#endif
#if HAVE_GTK3
if (!style)
style = g_new0 (InputStyle, 1);
#endif
if (style->font_desc)
pango_font_description_free (style->font_desc);
@@ -746,6 +752,31 @@ create_input_style (InputStyle *style)
if (prefs.hex_gui_input_style)
{
#if !HAVE_GTK3
if (!done_rc)
{
GtkSettings *settings = gtk_settings_get_default ();
char *theme_name;
/* gnome-themes-standard 3.20+ relies on images to do theming
* so we have to override that. */
g_object_get (settings, "gtk-theme-name", &theme_name, NULL);
if (g_str_has_prefix (theme_name, "Adwaita") || g_str_has_prefix (theme_name, "Yaru"))
gtk_rc_parse_string (adwaita_workaround_rc);
g_free (theme_name);
{
guint16 red;
guint16 green;
guint16 blue;
palette_color_get_rgb16 (&colors[COL_FG], &red, &green, &blue);
sprintf (buf, cursor_color_rc, (red >> 8), (green >> 8), (blue >> 8));
}
gtk_rc_parse_string (buf);
done_rc = TRUE;
}
#else
GtkSettings *settings = gtk_settings_get_default ();
GdkScreen *screen = gdk_screen_get_default ();
char *theme_name;
@@ -846,7 +877,9 @@ create_input_style (InputStyle *style)
}
g_free (theme_name);
#endif
}
#if HAVE_GTK3
else
{
GdkScreen *screen = gdk_screen_get_default ();
@@ -863,7 +896,13 @@ create_input_style (InputStyle *style)
last_input_style = FALSE;
last_colors_set = FALSE;
}
#endif
#if !HAVE_GTK3
style->bg[GTK_STATE_NORMAL] = colors[COL_FG];
style->base[GTK_STATE_NORMAL] = colors[COL_BG];
style->text[GTK_STATE_NORMAL] = colors[COL_FG];
#endif
return style;
}
@@ -886,7 +925,11 @@ fe_init (void)
gtkosx_application_set_dock_icon_pixbuf (osx_app, pix_zoitechat);
#endif
channelwin_pix = pixmap_load_from_file (prefs.hex_text_background);
#if HAVE_GTK3
input_style = create_input_style (input_style);
#else
input_style = create_input_style (gtk_style_new ());
#endif
if (settings)
{
@@ -1680,62 +1723,9 @@ fe_open_url_inner (const char *url)
#elif defined(__APPLE__)
osx_show_uri (url);
#else
GError *error = NULL;
char *escaped_url = maybe_escape_uri (url);
gchar *xdg_open_argv[] = {(gchar *) "xdg-open", escaped_url, NULL};
gchar **spawn_env = NULL;
gboolean opened = FALSE;
g_debug ("Opening URL \"%s\" (%s)", escaped_url, url);
/* AppImage runtime variables can point host binaries like /bin/sh at
* bundled libraries, which may not be ABI-compatible with system tools. */
spawn_env = g_get_environ ();
{
gchar **tmp_env = spawn_env;
spawn_env = g_environ_unsetenv (tmp_env, "LD_LIBRARY_PATH");
if (spawn_env != tmp_env)
g_strfreev (tmp_env);
tmp_env = spawn_env;
spawn_env = g_environ_unsetenv (tmp_env, "LD_PRELOAD");
if (spawn_env != tmp_env)
g_strfreev (tmp_env);
}
/* Prefer xdg-open when available because gtk_show_uri can inherit
* AppImage runtime state and fail before we can control the environment. */
{
gchar *xdg_open_path = g_find_program_in_path ("xdg-open");
if (xdg_open_path &&
g_spawn_async (NULL, xdg_open_argv, spawn_env,
G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
NULL, NULL, NULL, &error))
{
opened = TRUE;
}
else
{
g_clear_error (&error);
}
g_free (xdg_open_path);
}
if (!opened && gtk_show_uri (NULL, escaped_url, GDK_CURRENT_TIME, &error))
{
opened = TRUE;
}
else if (!opened)
{
g_warning ("gtk_show_uri failed for '%s': %s", escaped_url, error ? error->message : "unknown error");
g_clear_error (&error);
}
if (!opened)
{
g_warning ("Unable to open URL '%s' via xdg-open or gtk_show_uri", escaped_url);
}
g_strfreev (spawn_env);
gtk_show_uri (NULL, escaped_url, GDK_CURRENT_TIME, NULL);
g_free (escaped_url);
#endif
}

View File

@@ -32,6 +32,22 @@
#include <gtk/gtk.h>
#include <cairo.h>
#ifndef HAVE_GTK3
#if GTK_MAJOR_VERSION >= 3
#define HAVE_GTK3 1
#else
#define HAVE_GTK3 0
#endif
#endif
#if !HAVE_GTK3
/* GtkWidget expansion APIs were introduced in GTK3. Keep GTK2 builds
* source-compatible by accepting the calls as no-ops.
*/
#define gtk_widget_set_hexpand(widget, expand) G_STMT_START { (void) (widget); (void) (expand); } G_STMT_END
#define gtk_widget_set_vexpand(widget, expand) G_STMT_START { (void) (widget); (void) (expand); } G_STMT_END
#endif
#ifdef HAVE_GTK_MAC
#include <gtkosxapplication.h>
#endif
@@ -48,10 +64,14 @@
#define flag_b flag_wid[7]
#define NUM_FLAG_WIDS 8
#if HAVE_GTK3
typedef struct _input_style
{
PangoFontDescription *font_desc;
} InputStyle;
#else
typedef GtkStyle InputStyle;
#endif
#ifdef HAVE_GTK_MAC
extern GtkosxApplication *osx_app;

View File

@@ -53,10 +53,18 @@
#include "textgui.h"
#include "fkeys.h"
#if HAVE_GTK3
#define ICON_FKEYS_NEW "document-new"
#define ICON_FKEYS_DELETE "edit-delete"
#define ICON_FKEYS_CANCEL "dialog-cancel"
#define ICON_FKEYS_SAVE "document-save"
#endif
#if !HAVE_GTK3
#define ICON_FKEYS_NEW GTK_STOCK_NEW
#define ICON_FKEYS_DELETE GTK_STOCK_DELETE
#define ICON_FKEYS_CANCEL GTK_STOCK_CANCEL
#define ICON_FKEYS_SAVE GTK_STOCK_SAVE
#endif
static void replace_handle (GtkWidget * wid);
void key_check_replace_on_change (GtkEditable *editable, gpointer data);
@@ -745,6 +753,7 @@ key_dialog_treeview_new (GtkWidget *box)
g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW(view))),
"changed", G_CALLBACK (key_dialog_selection_changed), NULL);
#if HAVE_GTK3
gtk_widget_set_name (view, "fkeys-treeview");
{
GtkCssProvider *provider = gtk_css_provider_new ();
@@ -764,6 +773,10 @@ key_dialog_treeview_new (GtkWidget *box)
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
}
#endif
#if !HAVE_GTK3
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
#endif
render = gtk_cell_renderer_accel_new ();
g_object_set (render, "editable", TRUE,
@@ -912,8 +925,13 @@ key_dialog_show ()
g_object_set_data (G_OBJECT (key_dialog), "view", view);
g_object_set_data (G_OBJECT (key_dialog), "xtext", xtext);
#if HAVE_GTK3
box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
box = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 2);
gtk_container_set_border_width (GTK_CONTAINER (box), 5);

View File

@@ -62,6 +62,7 @@ struct file_req
int flags; /* FRF_* flags */
};
#if HAVE_GTK3
static const char *
gtkutil_menu_custom_icon_from_stock (const char *stock_name)
{
@@ -161,7 +162,60 @@ gtkutil_menu_custom_icon_from_icon_name (const char *icon_name)
return NULL;
}
#endif
#if !HAVE_GTK3
static const char *
gtkutil_stock_from_menu_custom_icon (const char *custom_icon)
{
static const struct
{
const char *custom_icon;
const char *stock;
} icon_map[] = {
{ "zc-menu-new", GTK_STOCK_NEW },
{ "zc-menu-network-list", GTK_STOCK_INDEX },
{ "zc-menu-load-plugin", GTK_STOCK_REVERT_TO_SAVED },
{ "zc-menu-detach", GTK_STOCK_REDO },
{ "zc-menu-close", GTK_STOCK_CLOSE },
{ "zc-menu-quit", GTK_STOCK_QUIT },
{ "zc-menu-disconnect", GTK_STOCK_DISCONNECT },
{ "zc-menu-connect", GTK_STOCK_CONNECT },
{ "zc-menu-join", GTK_STOCK_JUMP_TO },
{ "zc-menu-chanlist", GTK_STOCK_INDEX },
{ "zc-menu-preferences", GTK_STOCK_PREFERENCES },
{ "zc-menu-clear", GTK_STOCK_CLEAR },
{ "zc-menu-copy", GTK_STOCK_COPY },
{ "zc-menu-delete", GTK_STOCK_DELETE },
{ "zc-menu-add", GTK_STOCK_ADD },
{ "zc-menu-remove", GTK_STOCK_REMOVE },
{ "zc-menu-spell-check", GTK_STOCK_SPELL_CHECK },
{ "zc-menu-save", GTK_STOCK_SAVE },
{ "zc-menu-save-as", GTK_STOCK_SAVE_AS },
{ "zc-menu-refresh", GTK_STOCK_REFRESH },
{ "zc-menu-search", GTK_STOCK_JUSTIFY_LEFT },
{ "zc-menu-find", GTK_STOCK_FIND },
{ "zc-menu-previous", GTK_STOCK_GO_BACK },
{ "zc-menu-next", GTK_STOCK_GO_FORWARD },
{ "zc-menu-help", GTK_STOCK_HELP },
{ "zc-menu-about", GTK_STOCK_ABOUT },
{ "zc-menu-emoji", GTK_STOCK_CONVERT },
{ "zc-menu-update", GTK_STOCK_REFRESH },
};
size_t i;
if (!custom_icon)
return NULL;
for (i = 0; i < G_N_ELEMENTS (icon_map); i++)
{
if (strcmp (custom_icon, icon_map[i].custom_icon) == 0)
return icon_map[i].stock;
}
return custom_icon;
}
#endif
static GdkPixbuf *
gtkutil_menu_icon_pixbuf_new (const char *icon_name)
@@ -185,6 +239,7 @@ gtkutil_menu_icon_pixbuf_new (const char *icon_name)
return pixbuf;
}
#if HAVE_GTK3
const char *
gtkutil_icon_name_from_stock (const char *stock_name)
{
@@ -241,7 +296,9 @@ gtkutil_icon_name_from_stock (const char *stock_name)
return stock_name;
}
#endif
#if HAVE_GTK3
static const char *
gtkutil_menu_icon_theme_variant (void)
{
@@ -321,10 +378,12 @@ gtkutil_menu_icon_image_new (const char *icon_name, GtkIconSize size)
return image;
}
#endif
GtkWidget *
gtkutil_image_new_from_stock (const char *stock, GtkIconSize size)
{
#if HAVE_GTK3
GtkWidget *image;
const char *icon_name;
@@ -347,11 +406,29 @@ gtkutil_image_new_from_stock (const char *stock, GtkIconSize size)
return image;
return gtk_image_new_from_icon_name (icon_name, size);
#elif !HAVE_GTK3
if (stock && g_str_has_prefix (stock, "zc-menu-"))
{
GdkPixbuf *pixbuf = gtkutil_menu_icon_pixbuf_new (stock);
if (pixbuf)
{
GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
return image;
}
}
if (stock && g_str_has_prefix (stock, "zc-menu-"))
stock = gtkutil_stock_from_menu_custom_icon (stock);
return gtk_image_new_from_stock (stock, size);
#endif
}
GtkWidget *
gtkutil_button_new_from_stock (const char *stock, const char *label)
{
#if HAVE_GTK3
GtkWidget *button = label ? gtk_button_new_with_mnemonic (label) : gtk_button_new ();
if (stock)
@@ -366,8 +443,16 @@ gtkutil_button_new_from_stock (const char *stock, const char *label)
}
return button;
#elif !HAVE_GTK3
if (stock)
return gtk_button_new_from_stock (stock);
if (label)
return gtk_button_new_with_mnemonic (label);
return gtk_button_new ();
#endif
}
#if HAVE_GTK3
void
gtkutil_append_font_css (GString *css, const PangoFontDescription *font_desc)
{
@@ -483,10 +568,16 @@ gtkutil_append_font_css (GString *css, const PangoFontDescription *font_desc)
void
gtkutil_apply_palette (GtkWidget *widget, const GdkRGBA *bg, const GdkRGBA *fg,
const PangoFontDescription *font_desc)
#else
void
gtkutil_apply_palette (GtkWidget *widget, const GdkColor *bg, const GdkColor *fg,
const PangoFontDescription *font_desc)
#endif
{
if (!widget)
return;
#if HAVE_GTK3
{
static const char *class_name = "zoitechat-palette";
GtkStyleContext *context = gtk_widget_get_style_context (widget);
@@ -544,6 +635,11 @@ gtkutil_apply_palette (GtkWidget *widget, const GdkRGBA *bg, const GdkRGBA *fg,
g_free (bg_color);
g_free (fg_color);
}
#else
gtk_widget_modify_base (widget, GTK_STATE_NORMAL, bg);
gtk_widget_modify_text (widget, GTK_STATE_NORMAL, fg);
gtk_widget_modify_font (widget, (PangoFontDescription *) font_desc);
#endif
}
static void
@@ -686,7 +782,7 @@ gtkutil_file_req_response (GtkWidget *dialog, gint res, struct file_req *freq)
gtk_widget_destroy (dialog);
}
#ifdef WIN32
#if defined (WIN32) && HAVE_GTK3
static gboolean
gtkutil_native_dialog_unref_idle (gpointer native)
{
@@ -730,7 +826,7 @@ gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *us
xdir = get_xdir ();
#ifdef WIN32
#if defined (WIN32) && HAVE_GTK3
{
GtkFileChooserNative *native = gtk_file_chooser_native_new (
title,
@@ -806,21 +902,37 @@ gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *us
if (flags & FRF_WRITE)
{
#if HAVE_GTK3
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_SAVE,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Save"), GTK_RESPONSE_ACCEPT,
NULL);
#elif !HAVE_GTK3
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL);
#endif
if (!(flags & FRF_NOASKOVERWRITE))
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
}
else
#if HAVE_GTK3
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Open"), GTK_RESPONSE_ACCEPT,
NULL);
#elif !HAVE_GTK3
dialog = gtk_file_chooser_dialog_new (title, NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
#endif
if (filter && filter[0] && (flags & FRF_FILTERISINITIAL))
{
@@ -976,10 +1088,17 @@ fe_get_str (char *msg, char *def, void *callback, void *userdata)
GtkWidget *label;
extern GtkWidget *parent_window;
#if HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (msg, NULL, 0,
_("_Cancel"), GTK_RESPONSE_REJECT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
#elif !HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (msg, NULL, 0,
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
#endif
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE);
@@ -1071,10 +1190,17 @@ fe_get_int (char *msg, int def, void *callback, void *userdata)
GtkAdjustment *adj;
extern GtkWidget *parent_window;
#if HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (msg, NULL, 0,
_("_Cancel"), GTK_RESPONSE_REJECT,
_("_OK"), GTK_RESPONSE_ACCEPT,
NULL);
#elif !HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (msg, NULL, 0,
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
#endif
gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
@@ -1111,10 +1237,17 @@ fe_get_bool (char *title, char *prompt, void *callback, void *userdata)
GtkWidget *prompt_label;
extern GtkWidget *parent_window;
#if HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (title, NULL, 0,
_("_No"), GTK_RESPONSE_REJECT,
_("_Yes"), GTK_RESPONSE_ACCEPT,
NULL);
#elif !HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (title, NULL, 0,
GTK_STOCK_NO, GTK_RESPONSE_REJECT,
GTK_STOCK_YES, GTK_RESPONSE_ACCEPT,
NULL);
#endif
gtk_box_set_homogeneous (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
@@ -1145,12 +1278,20 @@ gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callback,
{
gtk_button_set_label (GTK_BUTTON (wid), labeltext);
img = NULL;
#if HAVE_GTK3
if (stock)
img = gtkutil_image_new_from_stock (stock, GTK_ICON_SIZE_BUTTON);
#endif
#if !HAVE_GTK3
if (stock)
img = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_BUTTON);
#endif
if (img)
{
gtk_button_set_image (GTK_BUTTON (wid), img);
#if HAVE_GTK3
gtk_button_set_always_show_image (GTK_BUTTON (wid), TRUE);
#endif
}
gtk_button_set_use_underline (GTK_BUTTON (wid), TRUE);
if (box)
@@ -1163,13 +1304,21 @@ gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callback,
gtk_widget_show (bbox);
img = NULL;
#if HAVE_GTK3
if (stock)
img = gtkutil_image_new_from_stock (stock, GTK_ICON_SIZE_BUTTON);
#endif
#if !HAVE_GTK3
if (stock)
img = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_BUTTON);
#endif
if (img)
{
gtk_container_add (GTK_CONTAINER (bbox), img);
gtk_widget_show (img);
#if HAVE_GTK3
gtk_button_set_always_show_image (GTK_BUTTON (wid), TRUE);
#endif
}
gtk_box_pack_start (GTK_BOX (box), wid, 0, 0, 0);
}
@@ -1396,8 +1545,10 @@ gtkutil_tray_icon_supported (GtkWindow *window)
#ifdef GDK_WINDOWING_X11
GdkScreen *screen = gtk_window_get_screen (window);
GdkDisplay *display = gdk_screen_get_display (screen);
#if HAVE_GTK3
if (!GDK_IS_X11_DISPLAY (display))
return FALSE;
#endif
int screen_number = gdk_screen_get_number (screen);
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
char *selection_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d", screen_number);
@@ -1452,22 +1603,34 @@ gtkutil_find_font (const char *fontname)
GtkWidget *
gtkutil_box_new (GtkOrientation orientation, gboolean homogeneous, gint spacing)
{
#if HAVE_GTK3
GtkWidget *box = gtk_box_new (orientation, spacing);
gtk_box_set_homogeneous (GTK_BOX (box), homogeneous);
return box;
#elif !HAVE_GTK3
if (orientation == GTK_ORIENTATION_HORIZONTAL)
return gtk_hbox_new (homogeneous, spacing);
return gtk_vbox_new (homogeneous, spacing);
#endif
}
GtkWidget *
gtkutil_grid_new (guint rows, guint columns, gboolean homogeneous)
{
#if HAVE_GTK3
GtkWidget *grid = gtk_grid_new ();
gtk_grid_set_row_homogeneous (GTK_GRID (grid), homogeneous);
gtk_grid_set_column_homogeneous (GTK_GRID (grid), homogeneous);
return grid;
#elif !HAVE_GTK3
return gtk_table_new (rows, columns, homogeneous);
#endif
}
#if HAVE_GTK3
static GtkAlign
gtkutil_align_from_options (GtkutilAttachOptions options, GtkAlign default_align)
{
@@ -1476,6 +1639,7 @@ gtkutil_align_from_options (GtkutilAttachOptions options, GtkAlign default_align
return default_align;
}
#endif
static gboolean
gtkutil_expansion_from_options (GtkutilAttachOptions options, gboolean default_expand)
@@ -1493,6 +1657,7 @@ gtkutil_grid_attach (GtkWidget *table, GtkWidget *child,
GtkutilAttachOptions xoptions, GtkutilAttachOptions yoptions,
guint xpad, guint ypad)
{
#if HAVE_GTK3
gtk_widget_set_hexpand (child, gtkutil_expansion_from_options (xoptions, FALSE));
gtk_widget_set_vexpand (child, gtkutil_expansion_from_options (yoptions, FALSE));
gtk_widget_set_halign (child, gtkutil_align_from_options (xoptions, GTK_ALIGN_CENTER));
@@ -1503,6 +1668,10 @@ gtkutil_grid_attach (GtkWidget *table, GtkWidget *child,
gtk_widget_set_margin_bottom (child, ypad);
gtk_grid_attach (GTK_GRID (table), child, left_attach, top_attach,
right_attach - left_attach, bottom_attach - top_attach);
#elif !HAVE_GTK3
gtk_table_attach (GTK_TABLE (table), child, left_attach, right_attach,
top_attach, bottom_attach, xoptions, yoptions, xpad, ypad);
#endif
}
void
@@ -1510,10 +1679,15 @@ gtkutil_grid_attach_defaults (GtkWidget *table, GtkWidget *child,
guint left_attach, guint right_attach,
guint top_attach, guint bottom_attach)
{
#if HAVE_GTK3
gtk_widget_set_hexpand (child, TRUE);
gtk_widget_set_vexpand (child, TRUE);
gtk_widget_set_halign (child, GTK_ALIGN_FILL);
gtk_widget_set_valign (child, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), child, left_attach, top_attach,
right_attach - left_attach, bottom_attach - top_attach);
#elif !HAVE_GTK3
gtk_table_attach_defaults (GTK_TABLE (table), child, left_attach, right_attach,
top_attach, bottom_attach);
#endif
}

View File

@@ -26,13 +26,27 @@
typedef void (*filereqcallback) (void *, char *file);
#ifndef HAVE_GTK3
#if GTK_MAJOR_VERSION >= 3
#define HAVE_GTK3 1
#else
#define HAVE_GTK3 0
#endif
#endif
#if HAVE_GTK3
typedef enum
{
GTKUTIL_ATTACH_EXPAND = 1 << 0,
GTKUTIL_ATTACH_SHRINK = 1 << 1,
GTKUTIL_ATTACH_FILL = 1 << 2
} GtkutilAttachOptions;
#else
typedef GtkAttachOptions GtkutilAttachOptions;
#define GTKUTIL_ATTACH_EXPAND GTK_EXPAND
#define GTKUTIL_ATTACH_SHRINK GTK_SHRINK
#define GTKUTIL_ATTACH_FILL GTK_FILL
#endif
void gtkutil_file_req (GtkWindow *parent, const char *title, void *callback, void *userdata, char *filter, char *extensions, int flags);
void gtkutil_destroy (GtkWidget * igad, GtkWidget * dgad);
@@ -41,7 +55,9 @@ GtkWidget *gtkutil_button (GtkWidget *box, char *stock, char *tip, void *callbac
void *userdata, char *labeltext);
GtkWidget *gtkutil_image_new_from_stock (const char *stock, GtkIconSize size);
GtkWidget *gtkutil_button_new_from_stock (const char *stock, const char *label);
#if HAVE_GTK3
const char *gtkutil_icon_name_from_stock (const char *stock_name);
#endif
void gtkutil_label_new (char *text, GtkWidget * box);
GtkWidget *gtkutil_entry_new (int max, GtkWidget * box, void *callback,
gpointer userdata);
@@ -66,9 +82,14 @@ void gtkutil_grid_attach (GtkWidget *table, GtkWidget *child,
void gtkutil_grid_attach_defaults (GtkWidget *table, GtkWidget *child,
guint left_attach, guint right_attach,
guint top_attach, guint bottom_attach);
#if HAVE_GTK3
void gtkutil_apply_palette (GtkWidget *widget, const GdkRGBA *bg, const GdkRGBA *fg,
const PangoFontDescription *font_desc);
void gtkutil_append_font_css (GString *css, const PangoFontDescription *font_desc);
#else
void gtkutil_apply_palette (GtkWidget *widget, const GdkColor *bg, const GdkColor *fg,
const PangoFontDescription *font_desc);
#endif
#if defined (WIN32) || defined (__APPLE__)
gboolean gtkutil_find_font (const char *fontname);

View File

@@ -31,9 +31,16 @@
#include "gtkutil.h"
#include "maingui.h"
#if HAVE_GTK3
#define ICON_IGNORE_NEW "document-new"
#define ICON_IGNORE_DELETE "edit-delete"
#define ICON_IGNORE_CLEAR "edit-clear"
#endif
#if !HAVE_GTK3
#define ICON_IGNORE_NEW GTK_STOCK_NEW
#define ICON_IGNORE_DELETE GTK_STOCK_DELETE
#define ICON_IGNORE_CLEAR GTK_STOCK_CLEAR
#endif
enum
{
@@ -364,7 +371,11 @@ ignore_gui_open ()
frame = gtk_frame_new (_("Ignore Stats:"));
gtk_widget_show (frame);
#if HAVE_GTK3
stat_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
#elif !HAVE_GTK3
stat_box = gtk_hbox_new (0, 2);
#endif
gtk_container_set_border_width (GTK_CONTAINER (stat_box), 6);
gtk_container_add (GTK_CONTAINER (frame), stat_box);
gtk_widget_show (stat_box);
@@ -377,8 +388,13 @@ ignore_gui_open ()
gtk_box_pack_start (GTK_BOX (vbox), frame, 0, 0, 5);
#if HAVE_GTK3
box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
box = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 2);
gtk_container_set_border_width (GTK_CONTAINER (box), 5);
gtk_widget_show (box);

View File

@@ -40,7 +40,12 @@
#include "chanlist.h"
#include "gtkutil.h"
#if HAVE_GTK3
#define ICON_JOIND_NETWORK "network-workgroup"
#endif
#if !HAVE_GTK3
#define ICON_JOIND_NETWORK GTK_STOCK_NETWORK
#endif
static void
@@ -154,9 +159,13 @@ joind_show_dialog (server *serv)
image1 = gtkutil_image_new_from_stock (ICON_JOIND_NETWORK, GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_widget_show (image1);
gtk_box_pack_start (GTK_BOX (hbox1), image1, FALSE, TRUE, 24);
#if HAVE_GTK3
gtk_widget_set_halign (image1, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image1, GTK_ALIGN_START);
gtk_widget_set_margin_top (image1, 2);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (image1), 0.5f, 0.06f);
#endif
vbox2 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6);
@@ -170,21 +179,33 @@ joind_show_dialog (server *serv)
gtk_widget_show (label);
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
label = gtk_label_new (_("In the server list window, no channel (chat room) has been entered to be automatically joined for this network."));
gtk_widget_show (label);
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
label = gtk_label_new (_("What would you like to do next?"));
gtk_widget_show (label);
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
serv->gui->joind_radio1 = radiobutton1 = gtk_radio_button_new_with_mnemonic (NULL, _("_Nothing, I'll join a channel later."));
gtk_widget_show (radiobutton1);
@@ -212,8 +233,12 @@ joind_show_dialog (server *serv)
gtk_widget_show (label);
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
radiobutton3 = gtk_radio_button_new_with_mnemonic (NULL, _("O_pen the channel list."));
gtk_widget_show (radiobutton3);
@@ -226,8 +251,12 @@ joind_show_dialog (server *serv)
gtk_widget_show (label);
gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
serv->gui->joind_check = checkbutton1 = gtk_check_button_new_with_mnemonic (_("_Always show this dialog after connecting."));
if (prefs.hex_gui_join_dialog)
@@ -237,7 +266,18 @@ joind_show_dialog (server *serv)
okbutton1 = gtkutil_button_new_from_stock ("gtk-ok", _("_OK"));
gtk_widget_show (okbutton1);
#if HAVE_GTK3
gtk_dialog_add_action_widget (GTK_DIALOG (dialog1), okbutton1, GTK_RESPONSE_OK);
#elif !HAVE_GTK3
{
GtkWidget *dialog_action_area1;
dialog_action_area1 = gtk_dialog_get_action_area (GTK_DIALOG (dialog1));
gtk_widget_show (dialog_action_area1);
gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
gtk_box_pack_end (GTK_BOX (dialog_action_area1), okbutton1, FALSE, TRUE, 0);
}
#endif
gtk_widget_set_can_default (okbutton1, TRUE);
g_signal_connect (G_OBJECT (dialog1), "destroy",
@@ -252,7 +292,7 @@ joind_show_dialog (server *serv)
G_CALLBACK (joind_ok_cb), serv);
if (serv->network)
if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "Zoite") == 0)
if (g_ascii_strcasecmp(((ircnet*)serv->network)->name, "Libera.Chat") == 0)
{
gtk_entry_set_text (GTK_ENTRY (entry1), "#zoitechat");
}

View File

@@ -60,11 +60,20 @@
#include <windows.h>
#endif
#if HAVE_GTK3
#define ICON_TAB_DETACH "zc-menu-detach"
#define ICON_TAB_CLOSE "zc-menu-close"
#define ICON_TAB_PREVIOUS "zc-menu-previous"
#define ICON_TAB_NEXT "zc-menu-next"
#define ICON_ENTRY_ERROR "dialog-error"
#endif
#if !HAVE_GTK3
#define ICON_TAB_DETACH GTK_STOCK_REDO
#define ICON_TAB_CLOSE GTK_STOCK_CLOSE
#define ICON_TAB_PREVIOUS GTK_STOCK_GO_BACK
#define ICON_TAB_NEXT GTK_STOCK_GO_FORWARD
#define ICON_ENTRY_ERROR GTK_STOCK_DIALOG_ERROR
#endif
#define GUI_SPACING (3)
#define GUI_BORDER (0)
@@ -104,6 +113,7 @@ mg_color_component_to_pango (double value)
return (guint16)(value * 65535.0 + 0.5);
}
#if HAVE_GTK3
static void
mg_apply_font_css (GtkWidget *widget, const PangoFontDescription *desc,
const char *class_name, const char *provider_key)
@@ -138,21 +148,33 @@ mg_apply_font_css (GtkWidget *widget, const PangoFontDescription *desc,
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
#endif
static void
mg_set_label_alignment_start (GtkWidget *widget)
{
#if HAVE_GTK3
gtk_widget_set_halign (widget, GTK_ALIGN_START);
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
#endif
}
static GtkWidget *
mg_box_new (GtkOrientation orientation, gboolean homogeneous, gint spacing)
{
#if HAVE_GTK3
GtkWidget *box = gtk_box_new (orientation, spacing);
gtk_box_set_homogeneous (GTK_BOX (box), homogeneous);
return box;
#elif !HAVE_GTK3
if (orientation == GTK_ORIENTATION_HORIZONTAL)
return gtk_hbox_new (homogeneous, spacing);
return gtk_vbox_new (homogeneous, spacing);
#endif
}
static void
@@ -641,13 +663,14 @@ fe_set_title (session *sess)
static gboolean
mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata)
{
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
gtkutil_tray_icon_supported (wid))
{
tray_toggle_visibility (TRUE);
}
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
gtkutil_tray_icon_supported (wid))
{
tray_toggle_visibility (TRUE);
gtk_window_deiconify (wid);
}
prefs.hex_gui_win_state = 0;
if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
@@ -759,11 +782,21 @@ mg_progressbar_update (GtkWidget *bar)
if (type == 0)
{
type = 1;
#if HAVE_GTK3
gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (bar), TRUE);
#else
gtk_progress_bar_set_orientation ((GtkProgressBar *) bar,
GTK_PROGRESS_RIGHT_TO_LEFT);
#endif
} else
{
type = 0;
#if HAVE_GTK3
gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (bar), FALSE);
#else
gtk_progress_bar_set_orientation ((GtkProgressBar *) bar,
GTK_PROGRESS_LEFT_TO_RIGHT);
#endif
}
pos = 0.05;
}
@@ -1386,23 +1419,44 @@ mg_open_quit_dialog (gboolean minimize_button)
dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
gtk_widget_show (dialog_vbox1);
#if HAVE_GTK3
table1 = gtk_grid_new ();
gtk_widget_show (table1);
gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (table1), 6);
gtk_grid_set_row_spacing (GTK_GRID (table1), 12);
gtk_grid_set_column_spacing (GTK_GRID (table1), 12);
#else
table1 = gtk_table_new (2, 2, FALSE);
gtk_widget_show (table1);
gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (table1), 6);
gtk_table_set_row_spacings (GTK_TABLE (table1), 12);
gtk_table_set_col_spacings (GTK_TABLE (table1), 12);
#endif
#if HAVE_GTK3
image = gtk_image_new_from_icon_name ("dialog-warning", GTK_ICON_SIZE_DIALOG);
#endif
#if !HAVE_GTK3
image = gtk_image_new_from_stock ("gtk-dialog-warning", GTK_ICON_SIZE_DIALOG);
#endif
gtk_widget_show (image);
#if HAVE_GTK3
gtk_widget_set_hexpand (image, FALSE);
gtk_widget_set_vexpand (image, FALSE);
gtk_widget_set_halign (image, GTK_ALIGN_FILL);
gtk_widget_set_valign (image, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table1), image, 0, 0, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table1), image, 0, 1, 0, 1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 0, 0);
#endif
checkbutton1 = gtk_check_button_new_with_mnemonic (_("Don't ask next time."));
gtk_widget_show (checkbutton1);
#if HAVE_GTK3
gtk_widget_set_hexpand (checkbutton1, TRUE);
gtk_widget_set_vexpand (checkbutton1, FALSE);
gtk_widget_set_halign (checkbutton1, GTK_ALIGN_FILL);
@@ -1410,6 +1464,11 @@ mg_open_quit_dialog (gboolean minimize_button)
gtk_widget_set_margin_top (checkbutton1, 4);
gtk_widget_set_margin_bottom (checkbutton1, 4);
gtk_grid_attach (GTK_GRID (table1), checkbutton1, 0, 1, 2, 1);
#else
gtk_table_attach (GTK_TABLE (table1), checkbutton1, 0, 2, 1, 2,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (0), 0, 4);
#endif
connecttext = g_strdup_printf (_("You are connected to %i IRC networks."), cons);
text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n%s",
@@ -1421,14 +1480,30 @@ mg_open_quit_dialog (gboolean minimize_button)
g_free (text);
gtk_widget_show (label);
mg_set_label_alignment_start (label);
#if HAVE_GTK3
gtk_widget_set_hexpand (label, TRUE);
gtk_widget_set_vexpand (label, TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_FILL);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
gtk_grid_attach (GTK_GRID (table1), label, 1, 0, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table1), label, 1, 2, 0, 1,
(GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL),
(GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK), 0, 0);
#endif
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
#if !HAVE_GTK3
{
GtkWidget *dialog_action_area1;
dialog_action_area1 = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
gtk_widget_show (dialog_action_area1);
gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1),
GTK_BUTTONBOX_END);
}
#endif
if (minimize_button && gtkutil_tray_icon_supported (GTK_WINDOW(dialog)))
{
@@ -1437,17 +1512,27 @@ mg_open_quit_dialog (gboolean minimize_button)
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, 1);
}
#if HAVE_GTK3
button = gtk_button_new_with_mnemonic (_("_Cancel"));
gtk_button_set_image (GTK_BUTTON (button),
gtk_image_new_from_icon_name ("dialog-cancel", GTK_ICON_SIZE_BUTTON));
#endif
#if !HAVE_GTK3
button = gtk_button_new_from_stock ("gtk-cancel");
#endif
gtk_widget_show (button);
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
GTK_RESPONSE_CANCEL);
gtk_widget_grab_focus (button);
#if HAVE_GTK3
button = gtk_button_new_with_mnemonic (_("_Quit"));
gtk_button_set_image (GTK_BUTTON (button),
gtk_image_new_from_icon_name ("application-exit", GTK_ICON_SIZE_BUTTON));
#endif
#if !HAVE_GTK3
button = gtk_button_new_from_stock ("gtk-quit");
#endif
gtk_widget_show (button);
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, 0);
@@ -1824,7 +1909,11 @@ mg_create_tabmenu (session *sess, GdkEventButton *event, chan *ch)
g_object_unref (menu);
g_signal_connect (G_OBJECT (menu), "selection-done",
G_CALLBACK (mg_menu_destroy), NULL);
#if HAVE_GTK3
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
#else
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, event->time);
#endif
}
static gboolean
@@ -1941,11 +2030,15 @@ mg_userlist_button (GtkWidget * box, char *label, char *cmd,
GtkWidget *wid = gtk_button_new_with_label (label);
g_signal_connect (G_OBJECT (wid), "clicked",
G_CALLBACK (userlist_button_cb), cmd);
#if HAVE_GTK3
gtk_widget_set_hexpand (wid, TRUE);
gtk_widget_set_vexpand (wid, TRUE);
gtk_widget_set_halign (wid, GTK_ALIGN_FILL);
gtk_widget_set_valign (wid, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (box), wid, a, c, b - a, d - c);
#else
gtk_table_attach_defaults (GTK_TABLE (box), wid, a, b, c, d);
#endif
show_and_unfocus (wid);
}
@@ -1957,7 +2050,11 @@ mg_create_userlistbuttons (GtkWidget *box)
int a = 0, b = 0;
GtkWidget *tab;
#if HAVE_GTK3
tab = gtk_grid_new ();
#else
tab = gtk_table_new (5, 2, FALSE);
#endif
gtk_box_pack_end (GTK_BOX (box), tab, FALSE, FALSE, 0);
while (list)
@@ -2587,8 +2684,12 @@ mg_create_textarea (session *sess, GtkWidget *box)
g_signal_connect (G_OBJECT (xtext), "word_click",
G_CALLBACK (mg_word_clicked), NULL);
#if HAVE_GTK3
gui->vscrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL,
GTK_XTEXT (xtext)->adj);
#elif !HAVE_GTK3
gui->vscrollbar = gtk_vscrollbar_new (GTK_XTEXT (xtext)->adj);
#endif
gtk_box_pack_start (GTK_BOX (inbox), gui->vscrollbar, FALSE, TRUE, 0);
gtk_drag_dest_set (gui->vscrollbar, 5, dnd_dest_targets, 2,
@@ -2715,7 +2816,7 @@ mg_create_userlist (session_gui *gui, GtkWidget *box)
* - When "Use the text box font and colors" is enabled, we already want the
* palette background.
* - When "Dark mode" is enabled, we also force the user list to use the
* palette colors so it doesn't stay blindingly white on dark themes.
* palette colors so it doesn't stay blindingly white on GTK2 themes.
*/
if (prefs.hex_gui_ulist_style || fe_dark_mode_is_enabled ())
{
@@ -2773,18 +2874,34 @@ mg_create_center (session *sess, session_gui *gui, GtkWidget *box)
GtkWidget *vbox, *hbox, *book;
/* sep between top and bottom of left side */
#if HAVE_GTK3
gui->vpane_left = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
#elif !HAVE_GTK3
gui->vpane_left = gtk_vpaned_new ();
#endif
/* sep between top and bottom of right side */
#if HAVE_GTK3
gui->vpane_right = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
#elif !HAVE_GTK3
gui->vpane_right = gtk_vpaned_new ();
#endif
/* sep between left and xtext */
#if HAVE_GTK3
gui->hpane_left = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
gtk_paned_set_wide_handle (GTK_PANED (gui->hpane_left), FALSE);
#elif !HAVE_GTK3
gui->hpane_left = gtk_hpaned_new ();
#endif
gtk_paned_set_position (GTK_PANED (gui->hpane_left), prefs.hex_gui_pane_left_size);
/* sep between xtext and right side */
#if HAVE_GTK3
gui->hpane_right = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
#elif !HAVE_GTK3
gui->hpane_right = gtk_hpaned_new ();
#endif
if (prefs.hex_gui_win_swap)
{
@@ -2901,8 +3018,13 @@ mg_place_userlist_and_chanview_real (session_gui *gui, GtkWidget *userlist, GtkW
/* incase the previous pos was POS_HIDDEN */
gtk_widget_show (chanview);
#if HAVE_GTK3
gtk_widget_set_margin_top (chanview, 0);
gtk_widget_set_margin_bottom (chanview, 0);
#else
gtk_table_set_row_spacing (GTK_TABLE (gui->main_table), 1, 0);
gtk_table_set_row_spacing (GTK_TABLE (gui->main_table), 2, 2);
#endif
/* then place them back in their new positions */
switch (prefs.hex_gui_tab_pos)
@@ -2920,6 +3042,7 @@ mg_place_userlist_and_chanview_real (session_gui *gui, GtkWidget *userlist, GtkW
gtk_paned_pack2 (GTK_PANED (gui->vpane_right), chanview, FALSE, TRUE);
break;
case POS_TOP:
#if HAVE_GTK3
gtk_widget_set_margin_bottom (chanview, GUI_SPACING - 1);
gtk_widget_set_hexpand (chanview, FALSE);
gtk_widget_set_vexpand (chanview, FALSE);
@@ -2927,11 +3050,17 @@ mg_place_userlist_and_chanview_real (session_gui *gui, GtkWidget *userlist, GtkW
gtk_widget_set_valign (chanview, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (gui->main_table), chanview,
1, 1, 1, 1);
#else
gtk_table_set_row_spacing (GTK_TABLE (gui->main_table), 1, GUI_SPACING-1);
gtk_table_attach (GTK_TABLE (gui->main_table), chanview,
1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
#endif
break;
case POS_HIDDEN:
gtk_widget_hide (chanview);
/* always attach it to something to avoid ref_count=0 */
if (prefs.hex_gui_ulist_pos == POS_TOP)
#if HAVE_GTK3
{
gtk_widget_set_hexpand (chanview, FALSE);
gtk_widget_set_vexpand (chanview, FALSE);
@@ -2940,8 +3069,13 @@ mg_place_userlist_and_chanview_real (session_gui *gui, GtkWidget *userlist, GtkW
gtk_grid_attach (GTK_GRID (gui->main_table), chanview,
1, 3, 1, 1);
}
#else
gtk_table_attach (GTK_TABLE (gui->main_table), chanview,
1, 2, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
#endif
else
#if HAVE_GTK3
{
gtk_widget_set_hexpand (chanview, FALSE);
gtk_widget_set_vexpand (chanview, FALSE);
@@ -2950,8 +3084,13 @@ mg_place_userlist_and_chanview_real (session_gui *gui, GtkWidget *userlist, GtkW
gtk_grid_attach (GTK_GRID (gui->main_table), chanview,
1, 1, 1, 1);
}
#else
gtk_table_attach (GTK_TABLE (gui->main_table), chanview,
1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
#endif
break;
default:/* POS_BOTTOM */
#if HAVE_GTK3
gtk_widget_set_margin_top (chanview, 3);
gtk_widget_set_hexpand (chanview, FALSE);
gtk_widget_set_vexpand (chanview, FALSE);
@@ -2959,6 +3098,11 @@ mg_place_userlist_and_chanview_real (session_gui *gui, GtkWidget *userlist, GtkW
gtk_widget_set_valign (chanview, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (gui->main_table), chanview,
1, 3, 1, 1);
#else
gtk_table_set_row_spacing (GTK_TABLE (gui->main_table), 2, 3);
gtk_table_attach (GTK_TABLE (gui->main_table), chanview,
1, 2, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
#endif
}
}
@@ -3041,7 +3185,7 @@ mg_inputbox_rightclick (GtkEntry *entry, GtkWidget *menu)
}
/* ------------------------------------------------------------------------- *
* Emoji font handling
* Emoji font handling (GTK2)
*
* Goal: prefer color emoji fonts when available, without changing existing
* font size/style/weight, and without breaking user-configured fonts.
@@ -3126,12 +3270,17 @@ static void
mg_apply_emoji_fallback_widget (GtkWidget *widget)
{
PangoFontDescription *desc;
#if HAVE_GTK3
GtkStyleContext *context;
const PangoFontDescription *base_desc;
#else
GtkStyle *style;
#endif
if (!widget)
return;
#if HAVE_GTK3
context = gtk_widget_get_style_context (widget);
if (!context)
return;
@@ -3141,11 +3290,22 @@ mg_apply_emoji_fallback_widget (GtkWidget *widget)
return;
desc = mg_fontdesc_with_fallback (base_desc, FALSE);
#else
style = gtk_widget_get_style (widget);
if (!style || !style->font_desc)
return;
desc = mg_fontdesc_with_fallback (style->font_desc, FALSE);
#endif
if (!desc)
return;
#if HAVE_GTK3
mg_apply_font_css (widget, desc, "zoitechat-emoji-font",
"zoitechat-emoji-font-provider");
#else
gtk_widget_modify_font (widget, desc);
#endif
pango_font_description_free (desc);
}
@@ -3181,7 +3341,12 @@ search_handle_event(int search_type, session *sess)
if (err)
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, ICON_ENTRY_ERROR);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
#endif
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _(err->message));
g_error_free (err);
}
@@ -3189,7 +3354,12 @@ search_handle_event(int search_type, session *sess)
{
if (text && text[0] == 0) /* empty string, no error */
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
}
else
{
@@ -3197,14 +3367,24 @@ search_handle_event(int search_type, session *sess)
last = gtk_xtext_search (GTK_XTEXT (sess->gui->xtext), text, flags, &err);
if (!last) /* Not found error */
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, ICON_ENTRY_ERROR);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
#endif
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _("No results found."));
}
}
}
else
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
}
}
@@ -3251,7 +3431,12 @@ mg_search_toggle(session *sess)
else
{
/* Reset search state */
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
/* Show and focus */
gtk_widget_show(sess->gui->shbox);
@@ -3278,7 +3463,12 @@ mg_create_search(session *sess, GtkWidget *box)
gtk_box_pack_start(GTK_BOX(box), gui->shbox, FALSE, FALSE, 0);
close = gtk_button_new ();
#if HAVE_GTK3
gtk_button_set_image (GTK_BUTTON (close), gtkutil_image_new_from_stock (ICON_TAB_CLOSE, GTK_ICON_SIZE_MENU));
#endif
#if !HAVE_GTK3
gtk_button_set_image (GTK_BUTTON (close), gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
#endif
gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (close, FALSE);
gtk_box_pack_start(GTK_BOX(gui->shbox), close, FALSE, FALSE, 0);
@@ -3298,14 +3488,24 @@ mg_create_search(session *sess, GtkWidget *box)
gtk_entry_set_icon_tooltip_text (GTK_ENTRY (sess->gui->shentry), GTK_ENTRY_ICON_SECONDARY, _("Search hit end or not found."));
previous = gtk_button_new ();
#if HAVE_GTK3
gtk_button_set_image (GTK_BUTTON (previous), gtkutil_image_new_from_stock (ICON_TAB_PREVIOUS, GTK_ICON_SIZE_MENU));
#endif
#if !HAVE_GTK3
gtk_button_set_image (GTK_BUTTON (previous), gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU));
#endif
gtk_button_set_relief(GTK_BUTTON(previous), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (previous, FALSE);
gtk_box_pack_start(GTK_BOX(gui->shbox), previous, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(previous), "clicked", G_CALLBACK(mg_search_handle_previous), sess);
next = gtk_button_new ();
#if HAVE_GTK3
gtk_button_set_image (GTK_BUTTON (next), gtkutil_image_new_from_stock (ICON_TAB_NEXT, GTK_ICON_SIZE_MENU));
#endif
#if !HAVE_GTK3
gtk_button_set_image (GTK_BUTTON (next), gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU));
#endif
gtk_button_set_relief(GTK_BUTTON(next), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (next, FALSE);
gtk_box_pack_start(GTK_BOX(gui->shbox), next, FALSE, FALSE, 0);
@@ -3339,6 +3539,7 @@ mg_create_entry (session *sess, GtkWidget *box)
{
GtkWidget *hbox, *but, *entry;
session_gui *gui = sess->gui;
#if HAVE_GTK3
const char *emoji_fallback_icon_names[] = {
"face-smile-symbolic",
"face-smile",
@@ -3348,6 +3549,7 @@ mg_create_entry (session *sess, GtkWidget *box)
NULL
};
const char *emoji_fallback_icon_name;
#endif
hbox = mg_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), hbox, 0, 0, 0);
@@ -3387,6 +3589,7 @@ mg_create_entry (session *sess, GtkWidget *box)
if (prefs.hex_gui_input_style)
mg_apply_entry_style (entry);
#if HAVE_GTK3
g_object_set (G_OBJECT (entry), "show-emoji-icon", TRUE, NULL);
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
@@ -3395,6 +3598,7 @@ mg_create_entry (session *sess, GtkWidget *box)
if (emoji_fallback_icon_name)
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, emoji_fallback_icon_name);
}
#endif
}
static void
@@ -3455,7 +3659,11 @@ mg_create_tabs (session_gui *gui)
gui->chanview = chanview_new (prefs.hex_gui_tab_layout, prefs.hex_gui_tab_trunc,
prefs.hex_gui_tab_sort, use_icons,
#if HAVE_GTK3
input_style ? input_style->font_desc : NULL
#else
prefs.hex_gui_ulist_style ? input_style : NULL
#endif
);
chanview_set_callbacks (gui->chanview, mg_switch_tab_cb, mg_xbutton_cb,
mg_tab_contextmenu_cb, (void *)mg_tabs_compare);
@@ -3499,11 +3707,16 @@ mg_create_menu (session_gui *gui, GtkWidget *table, int away_state)
gui->menu = menu_create_main (accel_group, TRUE, away_state, !gui->is_tab,
gui->menu_item);
#if HAVE_GTK3
gtk_widget_set_hexpand (gui->menu, TRUE);
gtk_widget_set_vexpand (gui->menu, FALSE);
gtk_widget_set_halign (gui->menu, GTK_ALIGN_FILL);
gtk_widget_set_valign (gui->menu, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), gui->menu, 0, 0, 3, 1);
#else
gtk_table_attach (GTK_TABLE (table), gui->menu, 0, 3, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
#endif
}
static void
@@ -3513,11 +3726,16 @@ mg_create_irctab (session *sess, GtkWidget *table)
session_gui *gui = sess->gui;
vbox = mg_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#if HAVE_GTK3
gtk_widget_set_hexpand (vbox, TRUE);
gtk_widget_set_vexpand (vbox, TRUE);
gtk_widget_set_halign (vbox, GTK_ALIGN_FILL);
gtk_widget_set_valign (vbox, GTK_ALIGN_FILL);
gtk_grid_attach (GTK_GRID (table), vbox, 1, 2, 1, 1);
#else
gtk_table_attach (GTK_TABLE (table), vbox, 1, 2, 2, 3,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
#endif
mg_create_center (sess, gui, vbox);
}
@@ -3550,11 +3768,20 @@ mg_create_topwindow (session *sess)
palette_alloc (win);
#if HAVE_GTK3
table = gtk_grid_new ();
/* spacing under the menubar */
gtk_grid_set_row_spacing (GTK_GRID (table), GUI_SPACING);
/* left and right borders */
gtk_grid_set_column_spacing (GTK_GRID (table), 1);
#else
table = gtk_table_new (4, 3, FALSE);
/* spacing under the menubar */
gtk_table_set_row_spacing (GTK_TABLE (table), 0, GUI_SPACING);
/* left and right borders */
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1);
gtk_table_set_col_spacing (GTK_TABLE (table), 1, 1);
#endif
gtk_container_add (GTK_CONTAINER (win), table);
mg_create_irctab (sess, table);
@@ -3666,17 +3893,7 @@ mg_win32_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
if (command)
{
if (strcmp (command, "__WIN32_TASKBAR_TOGGLE__") == 0)
{
if (gtk_widget_get_visible (current_sess->gui->window))
fe_ctrl_gui (current_sess, FE_GUI_ICONIFY, 0);
else
fe_ctrl_gui (current_sess, FE_GUI_SHOW, 0);
}
else
{
handle_command (current_sess, command, FALSE);
}
handle_command (current_sess, command, FALSE);
g_free (command);
return GDK_FILTER_REMOVE;
}
@@ -3742,11 +3959,20 @@ mg_create_tabwindow (session *sess)
palette_alloc (win);
#if HAVE_GTK3
sess->gui->main_table = table = gtk_grid_new ();
/* spacing under the menubar */
gtk_grid_set_row_spacing (GTK_GRID (table), GUI_SPACING);
/* left and right borders */
gtk_grid_set_column_spacing (GTK_GRID (table), 1);
#else
sess->gui->main_table = table = gtk_table_new (4, 3, FALSE);
/* spacing under the menubar */
gtk_table_set_row_spacing (GTK_TABLE (table), 0, GUI_SPACING);
/* left and right borders */
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 1);
gtk_table_set_col_spacing (GTK_TABLE (table), 1, 1);
#endif
gtk_container_add (GTK_CONTAINER (win), table);
mg_create_irctab (sess, table);
@@ -4362,9 +4588,13 @@ mg_drag_motion_cb (GtkWidget *widget, GdkDragContext *context, int x, int y, gui
parent = gtk_widget_get_parent (widget);
grandparent = parent ? gtk_widget_get_parent (parent) : NULL;
paned = grandparent ? GTK_PANED (grandparent) : NULL;
#if HAVE_GTK3
if (paned != NULL &&
gtk_paned_get_child1 (paned) != NULL &&
gtk_paned_get_child2 (paned) != NULL)
#else
if (paned != NULL && paned->child1 != NULL && paned->child2 != NULL)
#endif
{
cairo_rectangle (cr, 1 + ox, 2 + oy, width - 3, height - 4);
cairo_rectangle (cr, 0 + ox, 1 + oy, width - 1, height - 2);

View File

@@ -130,7 +130,9 @@ menu_new (void)
{
GtkWidget *menu = gtk_menu_new ();
#if HAVE_GTK3
gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
#endif
return menu;
}
@@ -336,9 +338,11 @@ menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
gpointer userdata, char *icon)
{
GtkWidget *img, *item;
#if HAVE_GTK3
GtkWidget *box;
GtkWidget *image = NULL;
GtkWidget *label_widget;
#endif
if (!label)
item = gtk_menu_item_new ();
@@ -351,6 +355,7 @@ menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
else*/
img = menu_icon_widget_new (icon);
#if HAVE_GTK3
item = gtk_menu_item_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
if (img)
@@ -360,6 +365,11 @@ menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), label_widget, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (item), box);
#else
item = gtk_image_menu_item_new_with_mnemonic (label);
if (img)
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
#endif
}
else
{
@@ -368,10 +378,18 @@ menu_quick_item (char *cmd, char *label, GtkWidget * menu, int flags,
item = gtk_menu_item_new_with_label ("");
if (flags & XCMENU_MNEMONIC)
{
#if HAVE_GTK3
gtk_label_set_markup_with_mnemonic (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item))), label);
#else
gtk_label_set_markup_with_mnemonic (GTK_LABEL (GTK_BIN (item)->child), label);
#endif
} else
{
#if HAVE_GTK3
gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item))), label);
#else
gtk_label_set_markup (GTK_LABEL (GTK_BIN (item)->child), label);
#endif
}
} else
{
@@ -421,7 +439,11 @@ menu_quick_sub (char *name, GtkWidget *menu, GtkWidget **sub_item_ret, int flags
if (flags & XCMENU_MARKUP)
{
sub_item = gtk_menu_item_new_with_label ("");
#if HAVE_GTK3
gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (sub_item))), name);
#else
gtk_label_set_markup (GTK_LABEL (GTK_BIN (sub_item)->child), name);
#endif
}
else
{
@@ -461,7 +483,11 @@ toggle_cb (GtkWidget *item, char *pref_name)
{
char buf[256];
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
#else
if (GTK_CHECK_MENU_ITEM (item)->active)
#endif
g_snprintf (buf, sizeof (buf), "set %s 1", pref_name);
else
g_snprintf (buf, sizeof (buf), "set %s 0", pref_name);
@@ -642,6 +668,7 @@ menu_popup (GtkWidget *menu, GdkEventButton *event, gpointer objtounref)
g_object_unref (menu);
g_signal_connect (G_OBJECT (menu), "selection-done",
G_CALLBACK (menu_destroy), objtounref);
#if HAVE_GTK3
if (event)
{
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
@@ -657,6 +684,10 @@ menu_popup (GtkWidget *menu, GdkEventButton *event, gpointer objtounref)
{
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
}
#else
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
0, event ? event->time : 0);
#endif
}
static void
@@ -777,8 +808,9 @@ void
fe_userlist_update (session *sess, struct User *user)
{
GList *items, *next;
#if HAVE_GTK3
GList *iter;
gboolean needs_refresh;
#endif
if (!nick_submenu || !str_copy)
return;
@@ -791,6 +823,7 @@ fe_userlist_update (session *sess, struct User *user)
g_signal_handlers_disconnect_by_func (nick_submenu, menu_nickinfo_cb, sess);
/* destroy all the old items */
#if HAVE_GTK3
items = gtk_container_get_children (GTK_CONTAINER (nick_submenu));
iter = items;
while (iter)
@@ -800,16 +833,18 @@ fe_userlist_update (session *sess, struct User *user)
iter = next;
}
g_list_free (items);
#else
items = ((GtkMenuShell *) nick_submenu)->children;
while (items)
{
next = items->next;
gtk_widget_destroy (items->data);
items = next;
}
#endif
/* and re-create them with new info */
needs_refresh = menu_create_nickinfo_menu (user, nick_submenu) ||
!user->hostname || !user->realname || !user->servername;
if (needs_refresh)
{
g_signal_connect (G_OBJECT (nick_submenu), "show",
G_CALLBACK (menu_nickinfo_cb), sess);
}
menu_create_nickinfo_menu (user, nick_submenu);
}
void
@@ -936,7 +971,11 @@ menu_setting_foreach (void (*callback) (session *), int id, guint state)
if (menu_item != NULL)
{
#if HAVE_GTK3
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), state);
#else
GTK_CHECK_MENU_ITEM (menu_item)->active = state;
#endif
}
}
if (callback)
@@ -1270,6 +1309,7 @@ usermenu_destroy (GtkWidget * menu)
{
GList *items;
GList *next;
#if HAVE_GTK3
GList *iter;
items = gtk_container_get_children (GTK_CONTAINER (menu));
@@ -1281,6 +1321,16 @@ usermenu_destroy (GtkWidget * menu)
iter = next;
}
g_list_free (items);
#else
items = ((GtkMenuShell *) menu)->children;
while (items)
{
next = items->next;
gtk_widget_destroy (items->data);
items = next;
}
#endif
}
void
@@ -1491,7 +1541,11 @@ menu_join_cb (GtkWidget *dialog, gint response, GtkEntry *entry)
switch (response)
{
case GTK_RESPONSE_ACCEPT:
#if HAVE_GTK3
menu_chan_join (NULL, (char *)gtk_entry_get_text (GTK_ENTRY (entry)));
#else
menu_chan_join (NULL, entry->text);
#endif
break;
case GTK_RESPONSE_HELP:
@@ -1512,8 +1566,11 @@ static void
menu_join (GtkWidget * wid, gpointer none)
{
GtkWidget *hbox, *dialog, *entry, *label;
#if HAVE_GTK3
GtkWidget *content_area;
#endif
#if HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
GTK_WINDOW (parent_window), 0,
_("Retrieve channel list"), GTK_RESPONSE_HELP,
@@ -1538,13 +1595,30 @@ menu_join (GtkWidget * wid, gpointer none)
gtk_button_set_image (GTK_BUTTON (button),
gtk_image_new_from_icon_name ("dialog-ok", GTK_ICON_SIZE_BUTTON));
}
#endif
#if !HAVE_GTK3
dialog = gtk_dialog_new_with_buttons (_("Join Channel"),
GTK_WINDOW (parent_window), 0,
_("Retrieve channel list"), GTK_RESPONSE_HELP,
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
#endif
#if HAVE_GTK3
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
gtk_box_set_homogeneous (GTK_BOX (content_area), TRUE);
#else
gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dialog)->vbox), TRUE);
#endif
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, TRUE, 0);
entry = gtk_entry_new ();
#if HAVE_GTK3
gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE); /* avoid auto-selection */
#else
GTK_ENTRY (entry)->editable = 0; /* avoid auto-selection */
#endif
gtk_entry_set_text (GTK_ENTRY (entry), "#");
g_signal_connect (G_OBJECT (entry), "activate",
G_CALLBACK (menu_join_entry_cb), dialog);
@@ -1556,7 +1630,11 @@ menu_join (GtkWidget * wid, gpointer none)
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (menu_join_cb), entry);
#if HAVE_GTK3
gtk_container_add (GTK_CONTAINER (content_area), hbox);
#else
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
#endif
gtk_widget_show_all (dialog);
@@ -1737,7 +1815,7 @@ menu_ctcpguiopen (void)
static void
menu_docs (GtkWidget *wid, gpointer none)
{
fe_open_url ("https://docs.zoitechat.zoite.net/en/latest/");
fe_open_url ("http://zoitechat.zoite.net/docs");
}
/*static void
@@ -1779,7 +1857,11 @@ static void
menu_layout_cb (GtkWidget *item, gpointer none)
{
prefs.hex_gui_tab_layout = 2;
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
#else
if (GTK_CHECK_MENU_ITEM (item)->active)
#endif
prefs.hex_gui_tab_layout = 0;
menu_change_layout ();
@@ -1794,7 +1876,11 @@ menu_apply_metres_cb (session *sess)
static void
menu_metres_off (GtkWidget *item, gpointer none)
{
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
#else
if (GTK_CHECK_MENU_ITEM (item)->active)
#endif
{
prefs.hex_gui_lagometer = 0;
prefs.hex_gui_throttlemeter = 0;
@@ -1806,7 +1892,11 @@ menu_metres_off (GtkWidget *item, gpointer none)
static void
menu_metres_text (GtkWidget *item, gpointer none)
{
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
#else
if (GTK_CHECK_MENU_ITEM (item)->active)
#endif
{
prefs.hex_gui_lagometer = 2;
prefs.hex_gui_throttlemeter = 2;
@@ -1818,7 +1908,11 @@ menu_metres_text (GtkWidget *item, gpointer none)
static void
menu_metres_graph (GtkWidget *item, gpointer none)
{
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
#else
if (GTK_CHECK_MENU_ITEM (item)->active)
#endif
{
prefs.hex_gui_lagometer = 1;
prefs.hex_gui_throttlemeter = 1;
@@ -1830,7 +1924,11 @@ menu_metres_graph (GtkWidget *item, gpointer none)
static void
menu_metres_both (GtkWidget *item, gpointer none)
{
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
#else
if (GTK_CHECK_MENU_ITEM (item)->active)
#endif
{
prefs.hex_gui_lagometer = 3;
prefs.hex_gui_throttlemeter = 3;
@@ -1881,7 +1979,11 @@ menu_about (GtkWidget *wid, gpointer sess)
gtk_about_dialog_set_program_name (dialog, _(DISPLAY_NAME));
gtk_about_dialog_set_version (dialog, PACKAGE_VERSION);
#if HAVE_GTK3
gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG (dialog), GTK_LICENSE_GPL_2_0);
#else
gtk_about_dialog_set_license (dialog, license);
#endif
gtk_about_dialog_set_website (dialog, "http://zoitechat.zoite.net");
gtk_about_dialog_set_website_label (dialog, "Website");
gtk_about_dialog_set_logo (dialog, pix_zoitechat);
@@ -1912,6 +2014,7 @@ menu_about (GtkWidget *wid, gpointer sess)
#define ICON_FIND "zc-menu-find"
#define ICON_HELP "zc-menu-help"
#define ICON_ABOUT "zc-menu-about"
#define ICON_UPDATE "zc-menu-update"
static struct mymenu mymenu[] = {
{N_("_ZoiteChat"), 0, 0, M_NEWMENU, MENU_ID_ZOITECHAT, 0, 1},
@@ -2007,6 +2110,7 @@ static struct mymenu mymenu[] = {
{N_("_Help"), 0, 0, M_NEWMENU, 0, 0, 1}, /* 74 */
{N_("_Contents"), menu_docs, ICON_HELP, M_MENUSTOCK, 0, 0, 1, GDK_KEY_F1},
{N_("_Update"), menu_docs, ICON_UPDATE, M_MENUSTOCK, 0, 0, 1},
{N_("_About"), menu_about, ICON_ABOUT, M_MENUSTOCK, 0, 0, 1},
{0, 0, 0, M_END, 0, 0, 0},
@@ -2037,8 +2141,10 @@ create_icon_menu (char *labeltext, void *stock_name, int is_stock)
{
GtkWidget *item;
GtkWidget *img = NULL;
#if HAVE_GTK3
GtkWidget *box;
GtkWidget *label_widget;
#endif
if (is_stock)
{
@@ -2048,6 +2154,7 @@ create_icon_menu (char *labeltext, void *stock_name, int is_stock)
{
img = gtk_image_new_from_pixbuf (*((GdkPixbuf **)stock_name));
}
#if HAVE_GTK3
item = gtk_menu_item_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
label_widget = gtk_label_new_with_mnemonic (labeltext);
@@ -2059,15 +2166,21 @@ create_icon_menu (char *labeltext, void *stock_name, int is_stock)
gtk_widget_show (img);
gtk_widget_show (label_widget);
gtk_widget_show (box);
#else
item = gtk_image_menu_item_new_with_mnemonic (labeltext);
gtk_image_menu_item_set_image ((GtkImageMenuItem *)item, img);
gtk_widget_show (img);
#endif
return item;
}
/* Override the default handler, which would make menu
/* Override the default GTK2.4 handler, which would make menu
bindings not work when the menu-bar is hidden. */
static gboolean
menu_canacaccel (GtkWidget *widget, guint signal_id, gpointer user_data)
{
/* GTK2.2 behaviour */
return gtk_widget_is_sensitive (widget);
}
@@ -2077,18 +2190,28 @@ static GtkMenuItem *
menu_find_item (GtkWidget *menu, char *name)
{
GList *items;
#if HAVE_GTK3
GList *items_head;
#endif
GtkMenuItem *item;
GtkWidget *child;
const char *labeltext;
GtkMenuItem *found = NULL;
#if HAVE_GTK3
items_head = gtk_container_get_children (GTK_CONTAINER (menu));
items = items_head;
#else
items = ((GtkMenuShell *) menu)->children;
#endif
while (items)
{
item = items->data;
#if HAVE_GTK3
child = gtk_bin_get_child (GTK_BIN (item));
#else
child = GTK_BIN (item)->child;
#endif
if (child) /* separators arn't labels, skip them */
{
labeltext = g_object_get_data (G_OBJECT (item), "name");
@@ -2096,6 +2219,7 @@ menu_find_item (GtkWidget *menu, char *name)
{
if (GTK_IS_LABEL (child))
labeltext = gtk_label_get_text (GTK_LABEL (child));
#ifdef HAVE_GTK3
else if (GTK_IS_CONTAINER (child))
{
GList *kids, *l;
@@ -2110,6 +2234,7 @@ menu_find_item (GtkWidget *menu, char *name)
}
g_list_free (kids);
}
#endif
}
if (!menu_streq (labeltext, name, 1))
@@ -2124,7 +2249,9 @@ menu_find_item (GtkWidget *menu, char *name)
}
items = items->next;
}
#if HAVE_GTK3
g_list_free (items_head);
#endif
return found;
}
@@ -2208,7 +2335,11 @@ menu_update_cb (GtkWidget *menu, menu_entry *me, char *target)
gtk_widget_set_sensitive (item, me->enable);
/* must do it without triggering the callback */
if (GTK_IS_CHECK_MENU_ITEM (item))
#if HAVE_GTK3
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), me->state);
#else
GTK_CHECK_MENU_ITEM (item)->active = me->state;
#endif
}
}
@@ -2217,7 +2348,11 @@ static void
menu_radio_cb (GtkCheckMenuItem *item, menu_entry *me)
{
me->state = 0;
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (item))
#else
if (item->active)
#endif
me->state = 1;
/* update the state, incase this was changed via right-click. */
@@ -2233,7 +2368,11 @@ static void
menu_toggle_cb (GtkCheckMenuItem *item, menu_entry *me)
{
me->state = 0;
#if HAVE_GTK3
if (gtk_check_menu_item_get_active (item))
#else
if (item->active)
#endif
me->state = 1;
/* update the state, incase this was changed via right-click. */
@@ -2275,6 +2414,7 @@ menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
return;
if (pos < 0) /* position offset from end/bottom */
#if HAVE_GTK3
{
GList *children = gtk_container_get_children (GTK_CONTAINER (menu));
int length = g_list_length (children);
@@ -2282,6 +2422,9 @@ menu_reorder (GtkMenu *menu, GtkWidget *item, int pos)
g_list_free (children);
gtk_menu_reorder_child (menu, item, (length + pos) - 1);
}
#else
gtk_menu_reorder_child (menu, item, (g_list_length (GTK_MENU_SHELL (menu)->children) + pos) - 1);
#endif
else
gtk_menu_reorder_child (menu, item, pos);
}
@@ -2347,6 +2490,7 @@ menu_add_sub (GtkWidget *menu, menu_entry *me)
{
pos = me->pos;
if (pos < 0) /* position offset from end/bottom */
#if HAVE_GTK3
{
GList *children = gtk_container_get_children (GTK_CONTAINER (menu));
int length = g_list_length (children);
@@ -2354,6 +2498,9 @@ menu_add_sub (GtkWidget *menu, menu_entry *me)
g_list_free (children);
pos = length + pos;
}
#else
pos = g_list_length (GTK_MENU_SHELL (menu)->children) + pos;
#endif
menu_quick_sub (me->label, menu, &item, me->markup ? XCMENU_MARKUP|XCMENU_MNEMONIC : XCMENU_MNEMONIC, pos);
}
return item;
@@ -2631,7 +2778,11 @@ normalitem:
item = gtk_check_menu_item_new_with_mnemonic (_(mymenu[i].text));
togitem:
/* must avoid callback for Radio buttons */
#if HAVE_GTK3
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), mymenu[i].state);
#else
GTK_CHECK_MENU_ITEM (item)->active = mymenu[i].state;
#endif
/*gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
mymenu[i].state);*/
if (mymenu[i].key != 0)

View File

@@ -35,12 +35,11 @@ zoitechat_gtk_deps = [
libgmodule_dep, # used by libsexy
]
gtk_dep = dependency('gtk+-3.0', version: '>= 3.22')
if get_option('gtk3')
gtk_dep = dependency('gtk+-3.0', version: '>= 3.22')
zoitechat_gtk_cflags += '-DHAVE_GTK3'
if host_machine.system() != 'windows'
appindicator_opt = get_option('appindicator')
if appindicator_opt.allowed()
if host_machine.system() != 'windows'
appindicator_dep = dependency('ayatana-appindicator3-0.1', required: false)
if appindicator_dep.found()
zoitechat_gtk_deps += appindicator_dep
@@ -50,19 +49,22 @@ if host_machine.system() != 'windows'
if appindicator_dep.found()
zoitechat_gtk_deps += appindicator_dep
zoitechat_gtk_cflags += '-DHAVE_APPINDICATOR'
elif appindicator_opt.enabled()
error('appindicator=enabled, but neither ayatana-appindicator3-0.1 nor appindicator3-0.1 was found')
endif
endif
endif
else
gtk_dep = dependency('gtk+-2.0', version: '>= 2.24.0')
zoitechat_gtk_cflags += '-DHAVE_GTK2'
endif
zoitechat_gtk_deps += gtk_dep
if host_machine.system() != 'windows'
gdk_x11_dep = dependency('gdk-x11-3.0', required: false)
if gdk_x11_dep.found()
zoitechat_gtk_deps += gdk_x11_dep
if get_option('gtk3')
gdk_x11_dep = dependency('gdk-x11-3.0', required: false)
if gdk_x11_dep.found()
zoitechat_gtk_deps += gdk_x11_dep
endif
endif
x11_dep = dependency('x11', required: false)
@@ -83,6 +85,14 @@ if host_machine.system() == 'windows'
# sources: 'notifications/notification-winrt.cpp'
#)
elif host_machine.system() == 'darwin'
zoitechat_gtk_sources += 'notifications/notification-osx.m'
add_languages('objc')
gtk_mac_dep = dependency('gtk-mac-integration', required: true)
zoitechat_gtk_deps += gtk_mac_dep
zoitechat_gtk_cflags += '-DHAVE_GTK_MAC'
else
zoitechat_gtk_sources += 'notifications/notification-freedesktop.c'
endif

View File

@@ -37,10 +37,18 @@
#include "palette.h"
#include "notifygui.h"
#if HAVE_GTK3
#define ICON_NOTIFY_NEW "document-new"
#define ICON_NOTIFY_DELETE "edit-delete"
#define LABEL_NOTIFY_CANCEL _("_Cancel")
#define LABEL_NOTIFY_OK _("_OK")
#endif
#if !HAVE_GTK3
#define ICON_NOTIFY_NEW GTK_STOCK_NEW
#define ICON_NOTIFY_DELETE GTK_STOCK_DELETE
#define LABEL_NOTIFY_CANCEL GTK_STOCK_CANCEL
#define LABEL_NOTIFY_OK GTK_STOCK_OK
#endif
/* model for the notify treeview */
@@ -83,16 +91,24 @@ notify_treecell_property_mapper (GtkTreeViewColumn *col, GtkCellRenderer *cell,
gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
COLOUR_COLUMN, &colour,
model_column, &text, -1);
#if HAVE_GTK3
g_object_set (G_OBJECT (cell), "text", text,
PALETTE_FOREGROUND_PROPERTY, colour, NULL);
if (colour)
gdk_rgba_free (colour);
#else
g_object_set (G_OBJECT (cell), "text", text,
PALETTE_FOREGROUND_PROPERTY, colour, NULL);
if (colour)
gdk_color_free (colour);
#endif
g_free (text);
}
static void
notify_store_color (GtkListStore *store, GtkTreeIter *iter, const PaletteColor *color)
{
#if HAVE_GTK3
if (color)
{
GdkRGBA rgba = *color;
@@ -102,6 +118,9 @@ notify_store_color (GtkListStore *store, GtkTreeIter *iter, const PaletteColor *
{
gtk_list_store_set (store, iter, COLOUR_COLUMN, NULL, -1);
}
#else
gtk_list_store_set (store, iter, COLOUR_COLUMN, color, -1);
#endif
}
static void
@@ -379,8 +398,13 @@ fe_notify_ask (char *nick, char *networks)
table = gtkutil_grid_new (2, 3, FALSE);
gtk_container_set_border_width (GTK_CONTAINER (table), 12);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (table), 3);
gtk_grid_set_column_spacing (GTK_GRID (table), 8);
#else
gtk_table_set_row_spacings (GTK_TABLE (table), 3);
gtk_table_set_col_spacings (GTK_TABLE (table), 8);
#endif
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), table);
label = gtk_label_new (msg);
@@ -441,8 +465,13 @@ notify_opengui (void)
view = notify_treeview_new (vbox);
g_object_set_data (G_OBJECT (notify_window), "view", view);
#if HAVE_GTK3
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
gtk_box_pack_end (GTK_BOX (vbox), bbox, 0, 0, 0);
gtk_widget_show (bbox);

View File

@@ -38,11 +38,16 @@
#include "../common/cfgfiles.h"
#include "../common/typedef.h"
#if HAVE_GTK3
#define PALETTE_COLOR_INIT(r, g, b) { (r) / 65535.0, (g) / 65535.0, (b) / 65535.0, 1.0 }
#else
#define PALETTE_COLOR_INIT(r, g, b) { 0, (r), (g), (b) }
#endif
static void
palette_color_set_rgb16 (PaletteColor *color, guint16 red, guint16 green, guint16 blue)
{
#if HAVE_GTK3
char color_string[16];
GdkRGBA parsed = { 0 };
gboolean parsed_ok;
@@ -58,6 +63,18 @@ palette_color_set_rgb16 (PaletteColor *color, guint16 red, guint16 green, guint1
parsed.alpha = 1.0;
}
*color = parsed;
#else
char color_string[16];
g_snprintf (color_string, sizeof (color_string), "#%04x%04x%04x", red, green, blue);
if (!gdk_color_parse (color_string, color))
{
color->red = red;
color->green = green;
color->blue = blue;
color->pixel = 0;
}
#endif
}
static XTextColor
@@ -65,10 +82,17 @@ palette_color_from_gdk (const PaletteColor *color)
{
XTextColor result;
#if HAVE_GTK3
result.red = color->red;
result.green = color->green;
result.blue = color->blue;
result.alpha = color->alpha;
#else
result.red = color->red / 65535.0;
result.green = color->green / 65535.0;
result.blue = color->blue / 65535.0;
result.alpha = 1.0;
#endif
return result;
}
@@ -203,7 +227,14 @@ palette_user_set_color (int idx, const PaletteColor *col)
user_colors_valid = TRUE;
}
#if HAVE_GTK3
user_colors[idx] = *col;
#else
user_colors[idx].red = col->red;
user_colors[idx].green = col->green;
user_colors[idx].blue = col->blue;
user_colors[idx].pixel = 0;
#endif
}
void
@@ -221,7 +252,14 @@ palette_dark_set_color (int idx, const PaletteColor *col)
dark_user_colors_valid = TRUE;
}
#if HAVE_GTK3
dark_user_colors[idx] = *col;
#else
dark_user_colors[idx].red = col->red;
dark_user_colors[idx].green = col->green;
dark_user_colors[idx].blue = col->blue;
dark_user_colors[idx].pixel = 0;
#endif
}
void

View File

@@ -24,18 +24,30 @@
#include "xtext-color.h"
#if HAVE_GTK3
typedef GdkRGBA PaletteColor;
#define PALETTE_GDK_TYPE GDK_TYPE_RGBA
#define PALETTE_FOREGROUND_PROPERTY "foreground-rgba"
#else
typedef GdkColor PaletteColor;
#define PALETTE_GDK_TYPE GDK_TYPE_COLOR
#define PALETTE_FOREGROUND_PROPERTY "foreground-gdk"
#endif
extern PaletteColor colors[];
static inline void
palette_color_get_rgb16 (const PaletteColor *color, guint16 *red, guint16 *green, guint16 *blue)
{
#if HAVE_GTK3
*red = (guint16) CLAMP (color->red * 65535.0 + 0.5, 0.0, 65535.0);
*green = (guint16) CLAMP (color->green * 65535.0 + 0.5, 0.0, 65535.0);
*blue = (guint16) CLAMP (color->blue * 65535.0 + 0.5, 0.0, 65535.0);
#else
*red = color->red;
*green = color->green;
*blue = color->blue;
#endif
}
#define COL_MARK_FG 32

View File

@@ -31,6 +31,7 @@
#include "menu.h"
#include "gtkutil.h"
#if HAVE_GTK3
#include <gio/gio.h>
#if defined(GTK_DISABLE_DEPRECATED)
typedef struct _GtkStatusIcon GtkStatusIcon;
@@ -42,6 +43,7 @@ typedef struct _GtkStatusIcon GtkStatusIcon;
#include <libappindicator/app-indicator.h>
#endif
#endif
#endif
#define ICON_TRAY_PREFERENCES "zc-menu-preferences"
#define ICON_TRAY_QUIT "zc-menu-quit"
@@ -68,7 +70,7 @@ typedef enum
WS_HIDDEN
} WinStatus;
#if !defined(WIN32) && (defined(HAVE_AYATANA_APPINDICATOR) || defined(HAVE_APPINDICATOR))
#if HAVE_GTK3 && !defined(WIN32) && (defined(HAVE_AYATANA_APPINDICATOR) || defined(HAVE_APPINDICATOR))
#define HAVE_APPINDICATOR_BACKEND 1
#else
#define HAVE_APPINDICATOR_BACKEND 0
@@ -107,7 +109,7 @@ typedef GdkPixbuf* TrayCustomIcon;
#define ICON_HILIGHT pix_tray_highlight
#define ICON_FILE pix_tray_fileoffer
#endif
#if defined(GTK_DISABLE_DEPRECATED) && !HAVE_APPINDICATOR_BACKEND
#if HAVE_GTK3 && defined(GTK_DISABLE_DEPRECATED) && !HAVE_APPINDICATOR_BACKEND
GtkStatusIcon *gtk_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf);
void gtk_status_icon_set_from_pixbuf (GtkStatusIcon *status_icon, GdkPixbuf *pixbuf);
void gtk_status_icon_set_tooltip_text (GtkStatusIcon *status_icon, const gchar *text);
@@ -309,19 +311,6 @@ tray_gtk3_icon_to_name (TrayIcon icon, char **allocated)
names = g_themed_icon_get_names (G_THEMED_ICON (icon));
if (names && names[0])
{
/*
* Some StatusNotifier hosts (e.g. XFCE plugin combinations) can fail to
* resolve our desktop-id icon name even when GTK's icon theme lookup says
* it exists. Prefer an absolute PNG fallback for the app's normal icon so
* the tray item never renders as a blank placeholder.
*/
if (g_strcmp0 (names[0], ICON_NORMAL_NAME) == 0)
{
*allocated = tray_gtk3_fallback_icon_path_for_name (names[0]);
if (*allocated)
return *allocated;
}
theme = gtk_icon_theme_get_default ();
if (theme && gtk_icon_theme_has_icon (theme, names[0]))
return names[0];
@@ -1096,7 +1085,7 @@ tray_menu_populate (GtkWidget *menu)
mg_create_icon_item (_("_Quit"), ICON_TRAY_QUIT, menu, tray_menu_quit_cb, NULL);
}
#if !defined(WIN32)
#if HAVE_GTK3 && !defined(WIN32)
static void
tray_menu_clear (GtkWidget *menu)
{

View File

@@ -68,6 +68,7 @@ plugingui_get_target_session (void)
#define ICON_PLUGIN_UNLOAD "zc-menu-delete"
#define ICON_PLUGIN_RELOAD "zc-menu-refresh"
#if HAVE_GTK3
static GtkWidget *
plugingui_icon_button (GtkWidget *box, const char *label,
const char *icon_name, GCallback callback,
@@ -86,6 +87,7 @@ plugingui_icon_button (GtkWidget *box, const char *label,
return button;
}
#endif
static GtkWidget *
@@ -353,11 +355,17 @@ plugingui_open (void)
g_object_set_data (G_OBJECT (plugin_window), "view", view);
#if HAVE_GTK3
hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
hbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
gtk_box_pack_end (GTK_BOX (vbox), hbox, 0, 0, 0);
#if HAVE_GTK3
{
plugingui_icon_button (hbox, _("_Load..."), ICON_PLUGIN_LOAD,
G_CALLBACK (plugingui_loadbutton_cb), NULL);
@@ -366,6 +374,17 @@ plugingui_open (void)
plugingui_icon_button (hbox, _("_Reload"), ICON_PLUGIN_RELOAD,
G_CALLBACK (plugingui_reloadbutton_cb), view);
}
#endif
#if !HAVE_GTK3
gtkutil_button (hbox, ICON_PLUGIN_LOAD, NULL,
plugingui_loadbutton_cb, NULL, _("_Load..."));
gtkutil_button (hbox, ICON_PLUGIN_UNLOAD, NULL,
plugingui_unload, NULL, _("_Unload"));
gtkutil_button (hbox, ICON_PLUGIN_RELOAD, NULL,
plugingui_reloadbutton_cb, view, _("_Reload"));
#endif
fe_pluginlist_update ();

View File

@@ -42,8 +42,14 @@
#include "xtext.h"
#include "fkeys.h"
#if HAVE_GTK3
#define ICON_RAWLOG_CLEAR "zc-menu-clear"
#define ICON_RAWLOG_SAVE_AS "zc-menu-save-as"
#endif
#if !HAVE_GTK3
#define ICON_RAWLOG_CLEAR GTK_STOCK_CLEAR
#define ICON_RAWLOG_SAVE_AS GTK_STOCK_SAVE_AS
#endif
static void
close_rawlog (GtkWidget *wid, server *serv)
@@ -122,9 +128,13 @@ open_rawlog (struct server *serv)
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN);
#if HAVE_GTK3
gtk_widget_set_hexpand (scrolledwindow, TRUE);
gtk_widget_set_vexpand (scrolledwindow, TRUE);
gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
#elif !HAVE_GTK3
gtk_container_add (GTK_CONTAINER (vbox), scrolledwindow);
#endif
palette_get_xtext_colors (xtext_palette, XTEXT_COLS);
serv->gui->rawlog_textlist = gtk_xtext_new (xtext_palette, 0);
@@ -132,8 +142,13 @@ open_rawlog (struct server *serv)
gtk_xtext_set_font (GTK_XTEXT (serv->gui->rawlog_textlist), prefs.hex_text_font);
GTK_XTEXT (serv->gui->rawlog_textlist)->ignore_hidden = 1;
#if HAVE_GTK3
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
bbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_end (GTK_BOX (vbox), bbox, 0, 0, 4);
gtkutil_button (bbox, ICON_RAWLOG_CLEAR, NULL, rawlog_clearbutton,

View File

@@ -39,11 +39,20 @@
#define SERVLIST_X_PADDING 4 /* horizontal paddig in the network editor */
#define SERVLIST_Y_PADDING 0 /* vertical padding in the network editor */
#if HAVE_GTK3
#define ICON_SERVLIST_CONNECT "zc-menu-connect"
#define ICON_SERVLIST_ADD "list-add"
#define ICON_SERVLIST_REMOVE "list-remove"
#define ICON_SERVLIST_CLOSE "window-close"
#define ICON_SERVLIST_ERROR "dialog-error"
#endif
#if !HAVE_GTK3
#define ICON_SERVLIST_CONNECT GTK_STOCK_CONNECT
#define ICON_SERVLIST_ADD GTK_STOCK_ADD
#define ICON_SERVLIST_REMOVE GTK_STOCK_REMOVE
#define ICON_SERVLIST_CLOSE GTK_STOCK_CLOSE
#define ICON_SERVLIST_ERROR GTK_STOCK_DIALOG_ERROR
#endif
#ifdef USE_OPENSSL
# define DEFAULT_SERVER "newserver/6697"
@@ -98,6 +107,7 @@ static session *servlist_sess;
static void servlist_network_row_cb (GtkTreeSelection *sel, gpointer user_data);
static GtkWidget *servlist_open_edit (GtkWidget *parent, ircnet *net);
#if HAVE_GTK3
static GtkWidget *
servlist_icon_button_new (const char *label, const char *icon_name)
{
@@ -111,6 +121,7 @@ servlist_icon_button_new (const char *label, const char *icon_name)
return button;
}
#endif
static const char *pages[]=
@@ -1278,6 +1289,7 @@ typedef enum
SERVLIST_ALIGN_FILL
} servlist_align;
#if HAVE_GTK3
static GtkAlign
servlist_align_to_gtk (servlist_align align)
{
@@ -1292,6 +1304,7 @@ servlist_align_to_gtk (servlist_align align)
return GTK_ALIGN_START;
}
}
#endif
static void
servlist_table_attach (GtkWidget *table, GtkWidget *child,
@@ -1301,6 +1314,7 @@ servlist_table_attach (GtkWidget *table, GtkWidget *child,
servlist_align halign, servlist_align valign,
guint xpad, guint ypad)
{
#if HAVE_GTK3
gtk_widget_set_hexpand (child, hexpand);
gtk_widget_set_vexpand (child, vexpand);
gtk_widget_set_halign (child, servlist_align_to_gtk (halign));
@@ -1311,6 +1325,28 @@ servlist_table_attach (GtkWidget *table, GtkWidget *child,
gtk_widget_set_margin_bottom (child, ypad);
gtk_grid_attach (GTK_GRID (table), child, left_attach, top_attach,
right_attach - left_attach, bottom_attach - top_attach);
#else
GtkAttachOptions xoptions = 0;
GtkAttachOptions yoptions = 0;
if (hexpand)
xoptions |= GTK_EXPAND;
else
xoptions |= GTK_SHRINK;
if (halign == SERVLIST_ALIGN_FILL)
xoptions |= GTK_FILL;
if (vexpand)
yoptions |= GTK_EXPAND;
else
yoptions |= GTK_SHRINK;
if (valign == SERVLIST_ALIGN_FILL)
yoptions |= GTK_FILL;
gtk_table_attach (GTK_TABLE (table), child, left_attach, right_attach,
top_attach, bottom_attach, xoptions, yoptions,
xpad, ypad);
#endif
}
static GtkWidget *
@@ -1345,8 +1381,12 @@ servlist_create_entry (GtkWidget *table, char *labeltext, int row,
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
entry = gtk_entry_new ();
gtk_widget_set_tooltip_text (entry, tip);
@@ -1635,14 +1675,24 @@ servlist_username_changed_cb (GtkEntry *entry, gpointer userdata)
if (gtk_entry_get_text (entry)[0] == 0)
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, ICON_SERVLIST_ERROR);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
#endif
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
_("User name cannot be left blank."));
gtk_widget_set_sensitive (connect_btn, FALSE);
}
else
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
gtk_widget_set_sensitive (connect_btn, TRUE);
}
}
@@ -1657,22 +1707,38 @@ servlist_nick_changed_cb (GtkEntry *entry, gpointer userdata)
if (!nick1[0] || !nick2[0])
{
entry = GTK_ENTRY(!nick1[0] ? entry_nick1 : entry_nick2);
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, ICON_SERVLIST_ERROR);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
#endif
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
_("You cannot have an empty nick name."));
gtk_widget_set_sensitive (connect_btn, FALSE);
}
else if (!rfc_casecmp (nick1, nick2))
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, ICON_SERVLIST_ERROR);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (entry, GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_ERROR);
#endif
gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY,
_("You must have two unique nick names."));
gtk_widget_set_sensitive (connect_btn, FALSE);
}
else
{
#if HAVE_GTK3
gtk_entry_set_icon_from_icon_name (GTK_ENTRY(entry_nick1), GTK_ENTRY_ICON_SECONDARY, NULL);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY(entry_nick2), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
#if !HAVE_GTK3
gtk_entry_set_icon_from_stock (GTK_ENTRY(entry_nick1), GTK_ENTRY_ICON_SECONDARY, NULL);
gtk_entry_set_icon_from_stock (GTK_ENTRY(entry_nick2), GTK_ENTRY_ICON_SECONDARY, NULL);
#endif
gtk_widget_set_sensitive (connect_btn, TRUE);
}
}
@@ -1752,8 +1818,12 @@ bold_label (char *text)
g_snprintf (buf, sizeof (buf), "<b>%s</b>", text);
label = gtk_label_new (buf);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
gtk_widget_show (label);
return label;
@@ -1918,18 +1988,32 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
/* Button Box */
#if HAVE_GTK3
vbuttonbox1 = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
#elif !HAVE_GTK3
vbuttonbox1 = gtk_vbutton_box_new ();
#endif
gtk_box_set_spacing (GTK_BOX (vbuttonbox1), 3);
gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox1), GTK_BUTTONBOX_START);
gtk_box_pack_start (GTK_BOX (hbox1), vbuttonbox1, FALSE, FALSE, 3);
#if HAVE_GTK3
buttonadd = servlist_icon_button_new (_("_Add"), ICON_SERVLIST_ADD);
#endif
#if !HAVE_GTK3
buttonadd = gtk_button_new_from_stock (GTK_STOCK_ADD);
#endif
g_signal_connect (G_OBJECT (buttonadd), "clicked",
G_CALLBACK (servlist_addbutton_cb), notebook);
gtk_container_add (GTK_CONTAINER (vbuttonbox1), buttonadd);
gtk_widget_set_can_default (buttonadd, TRUE);
#if HAVE_GTK3
buttonremove = servlist_icon_button_new (_("_Remove"), ICON_SERVLIST_REMOVE);
#endif
#if !HAVE_GTK3
buttonremove = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
#endif
g_signal_connect (G_OBJECT (buttonremove), "clicked",
G_CALLBACK (servlist_deletebutton_cb), notebook);
gtk_container_add (GTK_CONTAINER (vbuttonbox1), buttonremove);
@@ -1945,8 +2029,13 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
/* Checkboxes and entries */
table3 = gtkutil_grid_new (13, 2, FALSE);
gtk_box_pack_start (GTK_BOX (vbox5), table3, FALSE, FALSE, 0);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (table3), 2);
gtk_grid_set_column_spacing (GTK_GRID (table3), 8);
#else
gtk_table_set_row_spacings (GTK_TABLE (table3), 2);
gtk_table_set_col_spacings (GTK_TABLE (table3), 8);
#endif
check = servlist_create_check (0, !(net->flags & FLAG_CYCLE), table3, 0, 0, _("Connect to selected server only"));
gtk_widget_set_tooltip_text (check, _("Don't cycle through all the servers when the connection fails."));
@@ -1972,8 +2061,12 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
#if HAVE_GTK3
gtk_widget_set_halign (label_logintype, GTK_ALIGN_START);
gtk_widget_set_valign (label_logintype, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label_logintype), 0, 0.5);
#endif
combobox_logintypes = servlist_create_logintypecombo (notebook);
servlist_table_attach (table3, combobox_logintypes, 1, 2, 10, 11,
FALSE, FALSE,
@@ -1990,8 +2083,12 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
SERVLIST_X_PADDING, SERVLIST_Y_PADDING);
#if HAVE_GTK3
gtk_widget_set_halign (label34, GTK_ALIGN_START);
gtk_widget_set_valign (label34, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5);
#endif
comboboxentry_charset = servlist_create_charsetcombo ();
servlist_table_attach (table3, comboboxentry_charset, 1, 2, 12, 13,
FALSE, FALSE,
@@ -2000,14 +2097,28 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
/* Rule and Close button */
#if HAVE_GTK3
hseparator2 = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
#elif !HAVE_GTK3
hseparator2 = gtk_hseparator_new ();
#endif
gtk_box_pack_start (GTK_BOX (vbox5), hseparator2, FALSE, FALSE, 8);
#if HAVE_GTK3
hbuttonbox4 = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox4), GTK_BUTTONBOX_END);
#elif !HAVE_GTK3
hbuttonbox4 = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox4), GTK_BUTTONBOX_END);
#endif
gtk_box_pack_start (GTK_BOX (vbox5), hbuttonbox4, FALSE, FALSE, 0);
#if HAVE_GTK3
button10 = servlist_icon_button_new (_("_Close"), ICON_SERVLIST_CLOSE);
#endif
#if !HAVE_GTK3
button10 = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
#endif
g_signal_connect (G_OBJECT (button10), "clicked",
G_CALLBACK (servlist_edit_close_cb), 0);
gtk_container_add (GTK_CONTAINER (hbuttonbox4), button10);
@@ -2092,8 +2203,13 @@ servlist_open_networks (void)
gtk_widget_show (table1);
gtk_box_pack_start (GTK_BOX (vbox1), table1, FALSE, FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER (table1), 8);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (table1), 2);
gtk_grid_set_column_spacing (GTK_GRID (table1), 4);
#else
gtk_table_set_row_spacings (GTK_TABLE (table1), 2);
gtk_table_set_col_spacings (GTK_TABLE (table1), 4);
#endif
label3 = gtk_label_new_with_mnemonic (_("_Nick name:"));
gtk_widget_show (label3);
@@ -2101,8 +2217,12 @@ servlist_open_networks (void)
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
0, 0);
#if HAVE_GTK3
gtk_widget_set_halign (label3, GTK_ALIGN_START);
gtk_widget_set_valign (label3, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label3), 0, 0.5);
#endif
label4 = gtk_label_new (_("Second choice:"));
gtk_widget_show (label4);
@@ -2110,8 +2230,12 @@ servlist_open_networks (void)
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
0, 0);
#if HAVE_GTK3
gtk_widget_set_halign (label4, GTK_ALIGN_START);
gtk_widget_set_valign (label4, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label4), 0, 0.5);
#endif
label5 = gtk_label_new (_("Third choice:"));
gtk_widget_show (label5);
@@ -2119,8 +2243,12 @@ servlist_open_networks (void)
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
0, 0);
#if HAVE_GTK3
gtk_widget_set_halign (label5, GTK_ALIGN_START);
gtk_widget_set_valign (label5, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label5), 0, 0.5);
#endif
label6 = gtk_label_new_with_mnemonic (_("_User name:"));
gtk_widget_show (label6);
@@ -2128,8 +2256,12 @@ servlist_open_networks (void)
FALSE, FALSE,
SERVLIST_ALIGN_START, SERVLIST_ALIGN_CENTER,
0, 0);
#if HAVE_GTK3
gtk_widget_set_halign (label6, GTK_ALIGN_START);
gtk_widget_set_valign (label6, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label6), 0, 0.5);
#endif
/* label7 = gtk_label_new_with_mnemonic (_("Rea_l name:"));
gtk_widget_show (label7);
@@ -2188,8 +2320,13 @@ servlist_open_networks (void)
gtk_widget_show (table4);
gtk_box_pack_start (GTK_BOX (vbox2), table4, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (table4), 8);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (table4), 2);
gtk_grid_set_column_spacing (GTK_GRID (table4), 3);
#else
gtk_table_set_row_spacings (GTK_TABLE (table4), 2);
gtk_table_set_col_spacings (GTK_TABLE (table4), 3);
#endif
scrolledwindow3 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (scrolledwindow3);
@@ -2248,7 +2385,11 @@ servlist_open_networks (void)
G_CALLBACK (fav_servlist), 0);
gtk_widget_show (checkbutton_fav);
#if HAVE_GTK3
vbuttonbox2 = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
#elif !HAVE_GTK3
vbuttonbox2 = gtk_vbutton_box_new ();
#endif
gtk_box_set_spacing (GTK_BOX (vbuttonbox2), 3);
gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox2), GTK_BUTTONBOX_START);
gtk_widget_show (vbuttonbox2);
@@ -2257,14 +2398,24 @@ servlist_open_networks (void)
SERVLIST_ALIGN_FILL, SERVLIST_ALIGN_FILL,
0, 0);
#if HAVE_GTK3
button_add = servlist_icon_button_new (_("_Add"), ICON_SERVLIST_ADD);
#endif
#if !HAVE_GTK3
button_add = gtk_button_new_from_stock (GTK_STOCK_ADD);
#endif
g_signal_connect (G_OBJECT (button_add), "clicked",
G_CALLBACK (servlist_addnet_cb), networks_tree);
gtk_widget_show (button_add);
gtk_container_add (GTK_CONTAINER (vbuttonbox2), button_add);
gtk_widget_set_can_default (button_add, TRUE);
#if HAVE_GTK3
button_remove = servlist_icon_button_new (_("_Remove"), ICON_SERVLIST_REMOVE);
#endif
#if !HAVE_GTK3
button_remove = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
#endif
g_signal_connect (G_OBJECT (button_remove), "clicked",
G_CALLBACK (servlist_deletenet_cb), 0);
gtk_widget_show (button_remove);
@@ -2295,17 +2446,31 @@ servlist_open_networks (void)
gtk_container_add (GTK_CONTAINER (vbuttonbox2), button_sort);
gtk_widget_set_can_default (button_sort, TRUE);
#if HAVE_GTK3
hseparator1 = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
#elif !HAVE_GTK3
hseparator1 = gtk_hseparator_new ();
#endif
gtk_widget_show (hseparator1);
gtk_box_pack_start (GTK_BOX (vbox1), hseparator1, FALSE, TRUE, 4);
#if HAVE_GTK3
hbuttonbox1 = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
hbuttonbox1 = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD);
#endif
gtk_widget_show (hbuttonbox1);
gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, FALSE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1), 8);
#if HAVE_GTK3
button_close = servlist_icon_button_new (_("_Close"), ICON_SERVLIST_CLOSE);
#endif
#if !HAVE_GTK3
button_close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
#endif
gtk_widget_show (button_close);
g_signal_connect (G_OBJECT (button_close), "clicked",
G_CALLBACK (servlist_close_cb), 0);

View File

@@ -713,6 +713,7 @@ typedef enum
SETUP_ALIGN_FILL
} setup_align;
#if HAVE_GTK3
static GtkAlign
setup_align_to_gtk (setup_align align)
{
@@ -727,6 +728,7 @@ setup_align_to_gtk (setup_align align)
return GTK_ALIGN_START;
}
}
#endif
static void
setup_table_attach (GtkWidget *table, GtkWidget *child,
@@ -736,6 +738,7 @@ setup_table_attach (GtkWidget *table, GtkWidget *child,
setup_align halign, setup_align valign,
guint xpad, guint ypad)
{
#if HAVE_GTK3
gtk_widget_set_hexpand (child, hexpand);
gtk_widget_set_vexpand (child, vexpand);
gtk_widget_set_halign (child, setup_align_to_gtk (halign));
@@ -747,6 +750,28 @@ setup_table_attach (GtkWidget *table, GtkWidget *child,
gtk_grid_attach (GTK_GRID (table), child, left_attach, top_attach,
right_attach - left_attach, bottom_attach - top_attach);
#else
GtkAttachOptions xoptions = 0;
GtkAttachOptions yoptions = 0;
if (hexpand)
xoptions |= GTK_EXPAND;
else
xoptions |= GTK_SHRINK;
if (halign == SETUP_ALIGN_FILL)
xoptions |= GTK_FILL;
if (vexpand)
yoptions |= GTK_EXPAND;
else
yoptions |= GTK_SHRINK;
if (valign == SETUP_ALIGN_FILL)
yoptions |= GTK_FILL;
gtk_table_attach (GTK_TABLE (table), child, left_attach, right_attach,
top_attach, bottom_attach, xoptions, yoptions,
xpad, ypad);
#endif
}
@@ -770,8 +795,12 @@ setup_headlabel (GtkWidget *tab, int row, int col, char *text)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), buf);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (tab, label, col, col + 1, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER, 4, 0);
}
@@ -793,8 +822,12 @@ setup_create_3oggle (GtkWidget *tab, int row, const setting *set)
int *offsets = (int *)set->list;
label = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
if (set->tooltip)
{
gtk_widget_set_tooltip_text (label, _(set->tooltip));
@@ -909,20 +942,36 @@ static GtkWidget *
setup_create_spin (GtkWidget *table, int row, const setting *set)
{
GtkWidget *label, *wid, *rbox;
#if !HAVE_GTK3
GtkWidget *align;
#endif
char *text;
label = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (table, label, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
#if HAVE_GTK3
rbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
gtk_widget_set_halign (rbox, GTK_ALIGN_START);
gtk_widget_set_valign (rbox, GTK_ALIGN_CENTER);
setup_table_attach (table, rbox, 3, 4, row, row + 1, TRUE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
#elif !HAVE_GTK3
align = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
setup_table_attach (table, align, 3, 4, row, row + 1, TRUE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
rbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
gtk_container_add (GTK_CONTAINER (align), rbox);
#endif
wid = gtk_spin_button_new_with_range (0, set->extra, 1);
g_object_set_data (G_OBJECT (wid), "lbl", label);
@@ -978,13 +1027,21 @@ setup_create_hscale (GtkWidget *table, int row, const setting *set)
GtkWidget *wid;
wid = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (wid, GTK_ALIGN_START);
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (wid), 0.0, 0.5);
#endif
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
#if HAVE_GTK3
wid = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0., 255., 1.);
#elif !HAVE_GTK3
wid = gtk_hscale_new_with_range (0., 255., 1.);
#endif
gtk_scale_set_value_pos (GTK_SCALE (wid), GTK_POS_RIGHT);
gtk_range_set_value (GTK_RANGE (wid), setup_get_int (&setup_prefs, set));
g_signal_connect (G_OBJECT(wid), "value_changed",
@@ -1039,13 +1096,21 @@ setup_create_radio (GtkWidget *table, int row, const setting *set)
GSList *group;
wid = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (wid, GTK_ALIGN_START);
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (wid), 0.0, 0.5);
#endif
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
#if HAVE_GTK3
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#elif !HAVE_GTK3
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#endif
setup_table_attach (table, hbox, 3, 4, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
@@ -1104,8 +1169,12 @@ setup_create_id_menu (GtkWidget *table, char *label, int row, char *dest)
};
wid = gtk_label_new (label);
#if HAVE_GTK3
gtk_widget_set_halign (wid, GTK_ALIGN_START);
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (wid), 0.0, 0.5);
#endif
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1152,8 +1221,12 @@ setup_create_menu (GtkWidget *table, int row, const setting *set)
int i;
wid = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (wid, GTK_ALIGN_START);
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (wid), 0.0, 0.5);
#endif
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1168,7 +1241,11 @@ setup_create_menu (GtkWidget *table, int row, const setting *set)
g_signal_connect (G_OBJECT (cbox), "changed",
G_CALLBACK (setup_menu_cb), (gpointer)set);
#if HAVE_GTK3
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#elif !HAVE_GTK3
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#endif
gtk_box_pack_start (GTK_BOX (box), cbox, 0, 0, 0);
setup_table_attach (table, box, 3, 4, row, row + 1, TRUE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
@@ -1202,7 +1279,38 @@ setup_browsefile_cb (GtkWidget *button, GtkWidget *entry)
entry, NULL, filter, filter_type|FRF_RECENTLYUSED|FRF_MODAL);
}
#if !HAVE_GTK3
static void
setup_fontsel_destroy (GtkWidget *button, GtkFontSelectionDialog *dialog)
{
font_dialog = NULL;
}
static void
setup_fontsel_cb (GtkWidget *button, GtkFontSelectionDialog *dialog)
{
GtkWidget *entry;
char *font_name;
entry = g_object_get_data (G_OBJECT (button), "e");
font_name = gtk_font_selection_dialog_get_font_name (dialog);
gtk_entry_set_text (GTK_ENTRY (entry), font_name);
g_free (font_name);
gtk_widget_destroy (GTK_WIDGET (dialog));
font_dialog = NULL;
}
static void
setup_fontsel_cancel (GtkWidget *button, GtkFontSelectionDialog *dialog)
{
gtk_widget_destroy (GTK_WIDGET (dialog));
font_dialog = NULL;
}
#endif
#if HAVE_GTK3
static void
setup_fontchooser_response (GtkDialog *dialog, gint response, GtkWidget *entry)
{
@@ -1221,6 +1329,7 @@ setup_fontchooser_response (GtkDialog *dialog, gint response, GtkWidget *entry)
gtk_widget_destroy (GTK_WIDGET (dialog));
font_dialog = NULL;
}
#endif
static void
setup_browsefolder_cb (GtkWidget *button, GtkEntry *entry)
@@ -1231,6 +1340,7 @@ setup_browsefolder_cb (GtkWidget *button, GtkEntry *entry)
static void
setup_browsefont_cb (GtkWidget *button, GtkWidget *entry)
{
#if HAVE_GTK3
GtkWidget *dialog;
const char *font_name;
@@ -1247,6 +1357,34 @@ setup_browsefont_cb (GtkWidget *button, GtkWidget *entry)
G_CALLBACK (setup_fontchooser_response), entry);
gtk_widget_show (dialog);
#elif !HAVE_GTK3
GtkFontSelection *sel;
GtkFontSelectionDialog *dialog;
GtkWidget *ok_button;
dialog = (GtkFontSelectionDialog *) gtk_font_selection_dialog_new (_("Select font"));
font_dialog = (GtkWidget *)dialog; /* global var */
gtk_window_set_transient_for (GTK_WINDOW (font_dialog), GTK_WINDOW (setup_window));
gtk_window_set_modal (GTK_WINDOW (font_dialog), TRUE);
sel = (GtkFontSelection *) gtk_font_selection_dialog_get_font_selection (dialog);
if (gtk_entry_get_text (GTK_ENTRY (entry))[0])
gtk_font_selection_set_font_name (sel, gtk_entry_get_text (GTK_ENTRY (entry)));
ok_button = gtk_font_selection_dialog_get_ok_button (dialog);
g_object_set_data (G_OBJECT (ok_button), "e", entry);
g_signal_connect (G_OBJECT (dialog), "destroy",
G_CALLBACK (setup_fontsel_destroy), dialog);
g_signal_connect (G_OBJECT (ok_button), "clicked",
G_CALLBACK (setup_fontsel_cb), dialog);
g_signal_connect (G_OBJECT (gtk_font_selection_dialog_get_cancel_button (dialog)), "clicked",
G_CALLBACK (setup_fontsel_cancel), dialog);
gtk_widget_show (GTK_WIDGET (dialog));
#endif
}
static void
@@ -1296,8 +1434,12 @@ setup_create_entry (GtkWidget *table, int row, const setting *set)
GtkWidget *wid, *bwid;
label = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (table, label, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1361,8 +1503,12 @@ setup_create_header (GtkWidget *table, int row, char *labeltext)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), buf);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (table, label, 0, 4, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER, 0, 5);
}
@@ -1383,8 +1529,13 @@ setup_create_frame (void)
tab = gtkutil_grid_new (3, 2, FALSE);
gtk_container_set_border_width (GTK_CONTAINER (tab), 6);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (tab), 2);
gtk_grid_set_column_spacing (GTK_GRID (tab), 3);
#else
gtk_table_set_row_spacings (GTK_TABLE (tab), 2);
gtk_table_set_col_spacings (GTK_TABLE (tab), 3);
#endif
return tab;
}
@@ -1505,8 +1656,12 @@ setup_create_dark_mode_menu (GtkWidget *table, int row, const setting *set)
int i;
wid = gtk_label_new (_(set->label));
#if HAVE_GTK3
gtk_widget_set_halign (wid, GTK_ALIGN_START);
gtk_widget_set_valign (wid, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (wid), 0.0, 0.5);
#endif
setup_table_attach (table, wid, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1521,7 +1676,11 @@ setup_create_dark_mode_menu (GtkWidget *table, int row, const setting *set)
g_signal_connect (G_OBJECT (cbox), "changed",
G_CALLBACK (setup_dark_mode_menu_cb), (gpointer)set);
#if HAVE_GTK3
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#elif !HAVE_GTK3
box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
#endif
gtk_box_pack_start (GTK_BOX (box), cbox, 0, 0, 0);
setup_table_attach (table, box, 3, 4, row, row + 1, TRUE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL, 0, 0);
@@ -1534,15 +1693,36 @@ setup_color_button_apply (GtkWidget *button, const PaletteColor *color)
{
GtkWidget *target = g_object_get_data (G_OBJECT (button), "zoitechat-color-box");
GtkWidget *apply_widget = GTK_IS_WIDGET (target) ? target : button;
#if !HAVE_GTK3
GtkStateType states[] = {
GTK_STATE_NORMAL,
GTK_STATE_PRELIGHT,
GTK_STATE_ACTIVE,
GTK_STATE_SELECTED,
GTK_STATE_INSENSITIVE
};
guint i;
#endif
#if HAVE_GTK3
gtkutil_apply_palette (apply_widget, color, NULL, NULL);
#else
for (i = 0; i < G_N_ELEMENTS (states); i++)
gtk_widget_modify_bg (apply_widget, states[i], color);
#endif
if (apply_widget != button)
#if HAVE_GTK3
gtkutil_apply_palette (button, color, NULL, NULL);
#else
for (i = 0; i < G_N_ELEMENTS (states); i++)
gtk_widget_modify_bg (button, states[i], color);
#endif
gtk_widget_queue_draw (button);
}
#if HAVE_GTK3
typedef struct
{
GtkWidget *button;
@@ -1590,10 +1770,42 @@ setup_color_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data
gtk_widget_destroy (GTK_WIDGET (dialog));
g_free (data);
}
#else
static void
setup_color_ok_cb (GtkWidget *button, GtkWidget *dialog)
{
GtkColorSelectionDialog *cdialog = GTK_COLOR_SELECTION_DIALOG (dialog);
PaletteColor *col;
col = g_object_get_data (G_OBJECT (button), "c");
button = g_object_get_data (G_OBJECT (button), "b");
if (!GTK_IS_WIDGET (button))
{
gtk_widget_destroy (dialog);
return;
}
color_change = TRUE;
gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (cdialog)), col);
setup_color_button_apply (button, col);
/* Persist custom colors for the palette the user is editing. */
if (fe_dark_mode_is_enabled_for (setup_prefs.hex_gui_dark_mode))
palette_dark_set_color ((int)(col - colors), col);
else
palette_user_set_color ((int)(col - colors), col);
gtk_widget_destroy (dialog);
}
#endif
static void
setup_color_cb (GtkWidget *button, gpointer userdata)
{
#if HAVE_GTK3
GtkWidget *dialog;
PaletteColor *color;
GdkRGBA rgba;
@@ -1611,6 +1823,37 @@ setup_color_cb (GtkWidget *button, gpointer userdata)
data->color = color;
g_signal_connect (dialog, "response", G_CALLBACK (setup_color_response_cb), data);
gtk_widget_show (dialog);
#else
GtkWidget *dialog, *cancel_button, *ok_button, *help_button;
GtkColorSelectionDialog *cdialog;
PaletteColor *color;
color = &colors[GPOINTER_TO_INT (userdata)];
dialog = gtk_color_selection_dialog_new (_("Select color"));
cdialog = GTK_COLOR_SELECTION_DIALOG (dialog);
g_object_get (G_OBJECT(cdialog), "cancel-button", &cancel_button,
"ok-button", &ok_button,
"help-button", &help_button, NULL);
gtk_widget_hide (help_button);
g_signal_connect (G_OBJECT (ok_button), "clicked",
G_CALLBACK (setup_color_ok_cb), dialog);
g_signal_connect (G_OBJECT (cancel_button), "clicked",
G_CALLBACK (gtkutil_destroy), dialog);
g_object_set_data (G_OBJECT (ok_button), "c", color);
g_object_set_data (G_OBJECT (ok_button), "b", button);
gtk_widget_set_sensitive (help_button, FALSE);
gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (gtk_color_selection_dialog_get_color_selection (cdialog)), color);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (setup_window));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_widget_show (dialog);
g_object_unref (cancel_button);
g_object_unref (ok_button);
g_object_unref (help_button);
#endif
}
static void
@@ -1619,6 +1862,9 @@ setup_create_color_button (GtkWidget *table, int num, int row, int col)
GtkWidget *but;
GtkWidget *label;
GtkWidget *box;
#if !HAVE_GTK3
GtkWidget *alignment;
#endif
char buf[64];
if (num > 31)
@@ -1635,8 +1881,17 @@ setup_create_color_button (GtkWidget *table, int num, int row, int col)
gtk_event_box_set_visible_window (GTK_EVENT_BOX (box), TRUE);
gtk_container_add (GTK_CONTAINER (box), label);
gtk_container_add (GTK_CONTAINER (but), box);
#if HAVE_GTK3
gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
#else
alignment = gtk_bin_get_child (GTK_BIN (but));
if (GTK_IS_ALIGNMENT (alignment))
{
gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 1.0, 1.0);
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 0, 0);
}
#endif
gtk_widget_show (label);
gtk_widget_show (box);
/* win32 build uses this to turn off themeing */
@@ -1658,8 +1913,12 @@ setup_create_other_colorR (char *text, int num, int row, GtkWidget *tab)
GtkWidget *label;
label = gtk_label_new (text);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (tab, label, 5, 9, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1672,8 +1931,12 @@ setup_create_other_color (char *text, int num, int row, GtkWidget *tab)
GtkWidget *label;
label = gtk_label_new (text);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (tab, label, 2, 3, row, row + 1, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1693,15 +1956,24 @@ setup_create_color_page (void)
tab = gtkutil_grid_new (9, 2, FALSE);
gtk_container_set_border_width (GTK_CONTAINER (tab), 6);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (tab), 2);
gtk_grid_set_column_spacing (GTK_GRID (tab), 3);
#else
gtk_table_set_row_spacings (GTK_TABLE (tab), 2);
gtk_table_set_col_spacings (GTK_TABLE (tab), 3);
#endif
gtk_container_add (GTK_CONTAINER (box), tab);
setup_create_header (tab, 0, N_("Text Colors"));
label = gtk_label_new (_("mIRC colors:"));
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (tab, label, 2, 3, 1, 2, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1710,8 +1982,12 @@ setup_create_color_page (void)
setup_create_color_button (tab, i, 1, i+3);
label = gtk_label_new (_("Local colors:"));
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (tab, label, 2, 3, 2, 3, FALSE, FALSE,
SETUP_ALIGN_START, SETUP_ALIGN_CENTER,
LABEL_INDENT, 0);
@@ -1740,8 +2016,12 @@ setup_create_color_page (void)
setup_create_header (tab, 15, N_("Color Stripping"));
/* label = gtk_label_new (_("Strip colors from:"));
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
setup_table_attach (tab, label, 2, 3, 16, 17, FALSE, FALSE,
SETUP_ALIGN_FILL, SETUP_ALIGN_FILL,
LABEL_INDENT, 0); */
@@ -1891,7 +2171,11 @@ setup_create_theme_page (void)
ui = g_new0 (setup_theme_ui, 1);
#if HAVE_GTK3
box = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 6);
#elif !HAVE_GTK3
box = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 6);
#endif
gtk_container_set_border_width (GTK_CONTAINER (box), 6);
themes_dir = g_build_filename (get_xdir (), "themes", NULL);
@@ -1899,13 +2183,21 @@ setup_create_theme_page (void)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
g_free (markup);
g_free (themes_dir);
#if HAVE_GTK3
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
#elif !HAVE_GTK3
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
#endif
gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, FALSE, 0);
ui->combo = gtk_combo_box_text_new ();
@@ -1913,7 +2205,11 @@ setup_create_theme_page (void)
g_signal_connect (G_OBJECT (ui->combo), "changed",
G_CALLBACK (setup_theme_selection_changed), ui);
#if HAVE_GTK3
button_box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
#elif !HAVE_GTK3
button_box = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
#endif
gtk_box_pack_start (GTK_BOX (hbox), button_box, FALSE, FALSE, 0);
ui->apply_button = gtk_button_new_with_mnemonic (_("_Apply Theme"));
@@ -1932,8 +2228,12 @@ setup_create_theme_page (void)
G_CALLBACK (setup_theme_open_folder_cb), ui);
ui->status_label = gtk_label_new (NULL);
#if HAVE_GTK3
gtk_widget_set_halign (ui->status_label, GTK_ALIGN_START);
gtk_widget_set_valign (ui->status_label, GTK_ALIGN_CENTER);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (ui->status_label), 0.0, 0.5);
#endif
gtk_box_pack_start (GTK_BOX (box), ui->status_label, FALSE, FALSE, 0);
setup_theme_populate (ui);
@@ -2126,11 +2426,19 @@ setup_create_sound_page (void)
GtkWidget *sound_play;
GtkTreeSelection *sel;
#if HAVE_GTK3
vbox1 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#elif !HAVE_GTK3
vbox1 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#endif
gtk_container_set_border_width (GTK_CONTAINER (vbox1), 6);
gtk_widget_show (vbox1);
#if HAVE_GTK3
vbox2 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#elif !HAVE_GTK3
vbox2 = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#endif
gtk_widget_show (vbox2);
gtk_container_add (GTK_CONTAINER (vbox1), vbox2);
@@ -2156,8 +2464,13 @@ setup_create_sound_page (void)
table1 = gtkutil_grid_new (2, 3, FALSE);
gtk_widget_show (table1);
gtk_box_pack_start (GTK_BOX (vbox2), table1, FALSE, TRUE, 8);
#if HAVE_GTK3
gtk_grid_set_row_spacing (GTK_GRID (table1), 2);
gtk_grid_set_column_spacing (GTK_GRID (table1), 4);
#else
gtk_table_set_row_spacings (GTK_TABLE (table1), 2);
gtk_table_set_col_spacings (GTK_TABLE (table1), 4);
#endif
sound_label = gtk_label_new_with_mnemonic (_("Sound file:"));
gtk_widget_show (sound_label);
@@ -2197,18 +2510,27 @@ setup_add_page (const char *title, GtkWidget *book, GtkWidget *tab)
GtkScrolledWindow *sw;
char buf[128];
#if HAVE_GTK3
vvbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#elif !HAVE_GTK3
vvbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
#endif
/* label */
label = gtk_label_new (NULL);
g_snprintf (buf, sizeof (buf), "<b><big>%s</big></b>", _(title));
gtk_label_set_markup (GTK_LABEL (label), buf);
#if HAVE_GTK3
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
gtk_widget_set_margin_start (label, 2);
gtk_widget_set_margin_end (label, 2);
gtk_widget_set_margin_top (label, 1);
gtk_widget_set_margin_bottom (label, 1);
#elif !HAVE_GTK3
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_misc_set_padding (GTK_MISC (label), 2, 1);
#endif
gtk_box_pack_start (GTK_BOX (vvbox), label, FALSE, FALSE, 2);
gtk_container_add (GTK_CONTAINER (vvbox), tab);
@@ -2410,8 +2732,14 @@ setup_create_tree (GtkWidget *box, GtkWidget *book)
static void
setup_apply_entry_style (GtkWidget *entry)
{
#if HAVE_GTK3
gtkutil_apply_palette (entry, &colors[COL_BG], &colors[COL_FG],
input_style->font_desc);
#else
gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &colors[COL_BG]);
gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &colors[COL_FG]);
gtk_widget_modify_font (entry, input_style->font_desc);
#endif
}
static void
@@ -2420,7 +2748,12 @@ setup_apply_to_sess (session_gui *gui)
mg_update_xtext (gui->xtext);
chanview_apply_theme ((chanview *) gui->chanview);
#if !HAVE_GTK3
if (prefs.hex_gui_ulist_style)
gtk_widget_modify_font (gui->user_tree, input_style->font_desc);
#endif
#if HAVE_GTK3
{
const PaletteColor *bg = NULL;
const PaletteColor *fg = NULL;
@@ -2435,9 +2768,25 @@ setup_apply_to_sess (session_gui *gui)
gtkutil_apply_palette (gui->user_tree, bg, fg, font);
}
#else
if (prefs.hex_gui_ulist_style || fe_dark_mode_is_enabled ())
{
gtk_widget_modify_base (gui->user_tree, GTK_STATE_NORMAL, &colors[COL_BG]);
if (fe_dark_mode_is_enabled ())
gtk_widget_modify_text (gui->user_tree, GTK_STATE_NORMAL, &colors[COL_FG]);
else
gtk_widget_modify_text (gui->user_tree, GTK_STATE_NORMAL, NULL);
}
else
{
gtk_widget_modify_base (gui->user_tree, GTK_STATE_NORMAL, NULL);
gtk_widget_modify_text (gui->user_tree, GTK_STATE_NORMAL, NULL);
}
#endif
if (prefs.hex_gui_input_style)
{
#if HAVE_GTK3
char buf[128];
GtkCssProvider *provider = gtk_css_provider_new ();
GtkStyleContext *context;
@@ -2462,6 +2811,15 @@ setup_apply_to_sess (session_gui *gui)
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
#else
extern char cursor_color_rc[];
char buf[256];
sprintf (buf, cursor_color_rc,
(colors[COL_FG].red >> 8),
(colors[COL_FG].green >> 8),
(colors[COL_FG].blue >> 8));
gtk_rc_parse_string (buf);
#endif
setup_apply_entry_style (gui->input_box);
setup_apply_entry_style (gui->limit_entry);
@@ -2718,18 +3076,31 @@ setup_window_open (void)
g_snprintf(buf, sizeof(buf), _("Preferences - %s"), _(DISPLAY_NAME));
win = gtkutil_window_new (buf, "prefs", 0, 600, 2);
#if HAVE_GTK3
vbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 5);
#elif !HAVE_GTK3
vbox = gtkutil_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 5);
#endif
gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
gtk_container_add (GTK_CONTAINER (win), vbox);
#if HAVE_GTK3
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 4);
#elif !HAVE_GTK3
hbox = gtkutil_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 4);
#endif
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
setup_create_tree (hbox, setup_create_pages (hbox));
/* prepare the button box */
#if HAVE_GTK3
hbbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_END);
#elif !HAVE_GTK3
hbbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_END);
#endif
gtk_box_set_spacing (GTK_BOX (hbbox), 4);
gtk_box_pack_end (GTK_BOX (vbox), hbbox, FALSE, FALSE, 0);

View File

@@ -51,6 +51,13 @@
#include "xtext.h"
#include "gtkutil.h"
#ifndef HAVE_GTK3
#if GTK_MAJOR_VERSION >= 3
#define HAVE_GTK3 1
#else
#define HAVE_GTK3 0
#endif
#endif
#define ICON_ADD "zc-menu-add"
#define ICON_REMOVE "zc-menu-remove"
@@ -101,11 +108,21 @@ struct _SexySpellEntryPriv
};
static void sexy_spell_entry_class_init(SexySpellEntryClass *klass);
#if HAVE_GTK3
static void sexy_spell_entry_editable_init (GtkEditableInterface *iface);
#endif
#if !HAVE_GTK3
static void sexy_spell_entry_editable_init (GtkEditableClass *iface);
#endif
static void sexy_spell_entry_init(SexySpellEntry *entry);
static void sexy_spell_entry_finalize(GObject *obj);
static void sexy_spell_entry_destroy(GObject *obj);
#if HAVE_GTK3
static gboolean sexy_spell_entry_draw(GtkWidget *widget, cairo_t *cr);
#endif
#if !HAVE_GTK3
static gint sexy_spell_entry_expose(GtkWidget *widget, GdkEventExpose *event);
#endif
static gint sexy_spell_entry_button_press(GtkWidget *widget, GdkEventButton *event);
/* GtkEditable handlers */
@@ -249,7 +266,12 @@ sexy_spell_entry_class_init(SexySpellEntryClass *klass)
object_class->dispose = sexy_spell_entry_destroy;
#if HAVE_GTK3
widget_class->draw = sexy_spell_entry_draw;
#endif
#if !HAVE_GTK3
widget_class->expose_event = sexy_spell_entry_expose;
#endif
widget_class->button_press_event = sexy_spell_entry_button_press;
/**
@@ -280,11 +302,19 @@ sexy_spell_entry_class_init(SexySpellEntryClass *klass)
}
}
#if HAVE_GTK3
static void
sexy_spell_entry_editable_init (GtkEditableInterface *iface)
{
}
#endif
#if !HAVE_GTK3
static void
sexy_spell_entry_editable_init (GtkEditableClass *iface)
{
}
#endif
static gint
gtk_entry_find_position (GtkEntry *entry, gint x)
@@ -297,6 +327,7 @@ gtk_entry_find_position (GtkEntry *entry, gint x)
gint pos;
gboolean trailing;
#if HAVE_GTK3
{
gint layout_x;
gint layout_y;
@@ -304,16 +335,35 @@ gtk_entry_find_position (GtkEntry *entry, gint x)
gtk_entry_get_layout_offsets(entry, &layout_x, &layout_y);
x -= layout_x;
}
#endif
#if !HAVE_GTK3
x = x + entry->scroll_offset;
#endif
layout = gtk_entry_get_layout(entry);
text = pango_layout_get_text(layout);
#if HAVE_GTK3
cursor_index = g_utf8_offset_to_pointer(
text,
gtk_editable_get_position(GTK_EDITABLE(entry))) - text;
#endif
#if !HAVE_GTK3
cursor_index = g_utf8_offset_to_pointer(text, entry->current_pos) - text;
#endif
line = pango_layout_get_lines(layout)->data;
pango_layout_line_x_to_index(line, x * PANGO_SCALE, &index, &trailing);
#if !HAVE_GTK3
if (index >= cursor_index && entry->preedit_length) {
if (index >= cursor_index + entry->preedit_length) {
index -= entry->preedit_length;
} else {
index = cursor_index;
trailing = FALSE;
}
}
#endif
pos = g_utf8_pointer_to_offset (text, text + index);
pos += trailing;
@@ -668,6 +718,7 @@ static GtkWidget *
sexy_spell_entry_icon_menu_item (const char *label, const char *stock_name)
{
GtkWidget *item;
#if HAVE_GTK3
const char *icon_name;
GtkWidget *box;
GtkWidget *image = NULL;
@@ -685,6 +736,13 @@ sexy_spell_entry_icon_menu_item (const char *label, const char *stock_name)
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), label_widget, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (item), box);
#else
GtkWidget *image;
item = gtk_image_menu_item_new_with_label (label);
image = gtkutil_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
#endif
return item;
}
@@ -1186,6 +1244,7 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry)
}
}
#if HAVE_GTK3
static gboolean
sexy_spell_entry_draw(GtkWidget *widget, cairo_t *cr)
{
@@ -1198,7 +1257,29 @@ sexy_spell_entry_draw(GtkWidget *widget, cairo_t *cr)
return GTK_WIDGET_CLASS(parent_class)->draw (widget, cr);
}
#endif
#if !HAVE_GTK3
static gint
sexy_spell_entry_expose(GtkWidget *widget, GdkEventExpose *event)
{
SexySpellEntry *entry = SEXY_SPELL_ENTRY(widget);
GtkEntry *gtk_entry = GTK_ENTRY(widget);
PangoLayout *layout;
layout = gtk_entry_get_layout(gtk_entry);
if (gtk_entry->preedit_length == 0)
{
pango_layout_set_attributes(layout, entry->priv->attr_list);
}
else
{
pango_layout_set_attributes(layout, empty_attrs_list);
}
return GTK_WIDGET_CLASS(parent_class)->expose_event (widget, event);
}
#endif
static gint
sexy_spell_entry_button_press(GtkWidget *widget, GdkEventButton *event)

View File

@@ -44,7 +44,11 @@ typedef enum {
struct _SexySpellEntry
{
#if HAVE_GTK3
GtkEntry parent_instance;
#else
GtkEntry parent_object;
#endif
SexySpellEntryPriv *priv;

View File

@@ -38,9 +38,16 @@
#include "palette.h"
#include "textgui.h"
#if HAVE_GTK3
#define ICON_TEXTEVENT_SAVE_AS "document-save-as"
#define ICON_TEXTEVENT_OPEN "document-open"
#define ICON_TEXTEVENT_OK "dialog-ok"
#endif
#if !HAVE_GTK3
#define ICON_TEXTEVENT_SAVE_AS GTK_STOCK_SAVE_AS
#define ICON_TEXTEVENT_OPEN GTK_STOCK_OPEN
#define ICON_TEXTEVENT_OK GTK_STOCK_OK
#endif
extern struct text_event te[];
extern char *pntevts_text[];
@@ -455,7 +462,11 @@ pevent_dialog_show ()
TRUE, FALSE, pevent_dialog_close, NULL,
600, 455, &vbox, 0);
#if HAVE_GTK3
pane = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
#elif !HAVE_GTK3
pane = gtk_vpaned_new ();
#endif
gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
pevent_dialog_list = pevent_treeview_new (pane);
@@ -474,8 +485,13 @@ pevent_dialog_show ()
gtk_container_add (GTK_CONTAINER (wid), pevent_dialog_twid);
gtk_xtext_set_font (GTK_XTEXT (pevent_dialog_twid), prefs.hex_text_font);
#if HAVE_GTK3
hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
hbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
gtkutil_button (hbox, ICON_TEXTEVENT_SAVE_AS, NULL, pevent_save_cb,
(void *) 1, _("Save As..."));

View File

@@ -33,9 +33,16 @@
#include "maingui.h"
#include "urlgrab.h"
#if HAVE_GTK3
#define ICON_URLGRAB_CLEAR "zc-menu-clear"
#define ICON_URLGRAB_COPY "zc-menu-copy"
#define ICON_URLGRAB_SAVE_AS "zc-menu-save-as"
#endif
#if !HAVE_GTK3
#define ICON_URLGRAB_CLEAR GTK_STOCK_CLEAR
#define ICON_URLGRAB_COPY GTK_STOCK_COPY
#define ICON_URLGRAB_SAVE_AS GTK_STOCK_SAVE_AS
#endif
/* model for the URL treeview */
enum
@@ -211,8 +218,13 @@ url_opengui ()
g_object_set_data (G_OBJECT (urlgrabberwindow), "model",
gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
#if HAVE_GTK3
hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
#elif !HAVE_GTK3
hbox = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
#endif
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
gtk_box_pack_end (GTK_BOX (vbox), hbox, 0, 0, 0);
gtk_widget_show (hbox);

View File

@@ -473,6 +473,7 @@ userlist_store_color (GtkListStore *store, GtkTreeIter *iter, int color_index)
{
const PaletteColor *color = color_index ? &colors[color_index] : NULL;
#if HAVE_GTK3
if (color)
{
GdkRGBA rgba = *color;
@@ -482,6 +483,9 @@ userlist_store_color (GtkListStore *store, GtkTreeIter *iter, int color_index)
{
gtk_list_store_set (store, iter, COL_GDKCOLOR, NULL, -1);
}
#else
gtk_list_store_set (store, iter, COL_GDKCOLOR, color, -1);
#endif
}
GtkListStore *

View File

@@ -203,7 +203,11 @@ gtk_xtext_cursor_unref (GdkCursor *cursor)
{
if (!cursor)
return;
#if !HAVE_GTK3
gdk_cursor_unref (cursor);
#else
g_object_unref (cursor);
#endif
}
static inline void
@@ -216,70 +220,117 @@ xtext_set_source_color (cairo_t *cr, const XTextColor *color, gdouble alpha)
static inline gdouble
xtext_adj_get_value (GtkAdjustment *adj)
{
#if !HAVE_GTK3
return adj->value;
#else
return gtk_adjustment_get_value (adj);
#endif
}
static inline void
xtext_adj_set_value (GtkAdjustment *adj, gdouble value)
{
#if !HAVE_GTK3
adj->value = value;
#else
gtk_adjustment_set_value (adj, value);
#endif
}
static inline gdouble
xtext_adj_get_upper (GtkAdjustment *adj)
{
#if !HAVE_GTK3
return adj->upper;
#else
return gtk_adjustment_get_upper (adj);
#endif
}
static inline void
xtext_adj_set_upper (GtkAdjustment *adj, gdouble upper)
{
#if !HAVE_GTK3
adj->upper = upper;
#else
gtk_adjustment_set_upper (adj, upper);
#endif
}
static inline gdouble
xtext_adj_get_lower (GtkAdjustment *adj)
{
#if !HAVE_GTK3
return adj->lower;
#else
return gtk_adjustment_get_lower (adj);
#endif
}
static inline void
xtext_adj_set_lower (GtkAdjustment *adj, gdouble lower)
{
#if !HAVE_GTK3
adj->lower = lower;
#else
gtk_adjustment_set_lower (adj, lower);
#endif
}
static inline gdouble
xtext_adj_get_page_size (GtkAdjustment *adj)
{
#if !HAVE_GTK3
return adj->page_size;
#else
return gtk_adjustment_get_page_size (adj);
#endif
}
static inline void
xtext_adj_set_page_size (GtkAdjustment *adj, gdouble page_size)
{
#if !HAVE_GTK3
adj->page_size = page_size;
#else
gtk_adjustment_set_page_size (adj, page_size);
#endif
}
static inline gdouble
xtext_adj_get_page_increment (GtkAdjustment *adj)
{
#if !HAVE_GTK3
return adj->page_increment;
#else
return gtk_adjustment_get_page_increment (adj);
#endif
}
static void
xtext_adjustment_apply (GtkAdjustment *adj, gdouble lower, gdouble upper, gdouble value, gdouble page_size)
{
#if HAVE_GTK3
gtk_adjustment_set_lower (adj, lower);
gtk_adjustment_set_upper (adj, upper);
gtk_adjustment_set_page_size (adj, page_size);
gtk_adjustment_set_value (adj, value);
#else
adj->lower = lower;
adj->upper = upper;
adj->page_size = page_size;
adj->value = value;
#endif
}
static inline void
xtext_adj_set_page_increment (GtkAdjustment *adj, gdouble page_increment)
{
#if !HAVE_GTK3
adj->page_increment = page_increment;
#else
gtk_adjustment_set_page_increment (adj, page_increment);
#endif
}
static cairo_surface_t *
@@ -684,10 +735,15 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
if (upper == 0)
upper = 1;
#if HAVE_GTK3
GtkAllocation allocation;
gtk_widget_get_allocation (GTK_WIDGET (buf->xtext), &allocation);
page_size = allocation.height / buf->xtext->fontsize;
#else
page_size = GTK_WIDGET (buf->xtext)->allocation.height /
buf->xtext->fontsize;
#endif
if (value > upper - page_size)
{
@@ -703,7 +759,11 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
if (fire_signal)
{
#if HAVE_GTK3
gtk_adjustment_value_changed (adj);
#else
gtk_adjustment_changed (adj);
#endif
}
}
}
@@ -765,7 +825,11 @@ gtk_xtext_new (const XTextColor *palette, int separator)
xtext->buffer = gtk_xtext_buffer_new (xtext);
xtext->orig_buffer = xtext->buffer;
#if !HAVE_GTK3
gtk_widget_set_double_buffered (GTK_WIDGET (xtext), FALSE);
#else
/* GTK3 already uses the GTK render pipeline; no manual double-buffering toggle. */
#endif
gtk_xtext_set_palette (xtext, palette);
return GTK_WIDGET (xtext);
@@ -833,7 +897,20 @@ gtk_xtext_cleanup (GtkXText *xtext)
}
}
#if !HAVE_GTK3
static void
gtk_xtext_destroy (GtkObject * object)
{
GtkXText *xtext = GTK_XTEXT (object);
gtk_xtext_cleanup (xtext);
if (GTK_OBJECT_CLASS (gtk_xtext_parent_class)->destroy)
(*GTK_OBJECT_CLASS (gtk_xtext_parent_class)->destroy) (object);
}
#endif
#if HAVE_GTK3
static void
gtk_xtext_dispose (GObject *object)
{
@@ -851,6 +928,7 @@ gtk_xtext_finalize (GObject *object)
if (G_OBJECT_CLASS (gtk_xtext_parent_class)->finalize)
(*G_OBJECT_CLASS (gtk_xtext_parent_class)->finalize) (object);
}
#endif
static void
gtk_xtext_unrealize (GtkWidget * widget)
@@ -862,17 +940,25 @@ gtk_xtext_unrealize (GtkWidget * widget)
* GtkWidget's unrealize path unregisters the window and expects
* gdk_window_get_user_data(window) == widget.
*/
#if !HAVE_GTK3
gdk_window_set_user_data (widget->window, NULL);
#endif
if (GTK_WIDGET_CLASS (gtk_xtext_parent_class)->unrealize)
(*GTK_WIDGET_CLASS (gtk_xtext_parent_class)->unrealize) (widget);
#if HAVE_GTK3
gtk_widget_set_window (widget, NULL);
gtk_widget_set_realized (widget, FALSE);
#endif
}
static void
gtk_xtext_get_pointer (GdkWindow *window, gint *x, gint *y, GdkModifierType *mask)
{
#if !HAVE_GTK3
gdk_window_get_pointer (window, x, y, mask);
#else
GdkDisplay *display;
GdkSeat *seat;
GdkDevice *device;
@@ -926,14 +1012,19 @@ gtk_xtext_get_pointer (GdkWindow *window, gint *x, gint *y, GdkModifierType *mas
*y = root_y - win_y;
if (mask)
gdk_device_get_state (device, window, NULL, mask);
#endif
}
static inline void
gtk_xtext_clear_background (GtkWidget *widget)
{
#if !HAVE_GTK3
gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
#else
GdkWindow *window = gtk_widget_get_window (widget);
if (window)
gdk_window_set_background_pattern (window, NULL);
#endif
}
static void
@@ -949,10 +1040,19 @@ gtk_xtext_realize (GtkWidget * widget)
xtext = GTK_XTEXT (widget);
gtk_widget_set_realized (widget, TRUE);
#if HAVE_GTK3
gtk_widget_get_allocation (widget, &allocation);
parent_window = gtk_widget_get_parent_window (widget);
attributes.visual = gtk_widget_get_visual (widget);
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
#endif
#if !HAVE_GTK3
allocation = widget->allocation;
parent_window = widget->parent->window;
attributes.colormap = gtk_widget_get_colormap (widget);
attributes.visual = gtk_widget_get_visual (widget);
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
#endif
attributes.x = allocation.x;
attributes.y = allocation.y;
@@ -966,7 +1066,11 @@ gtk_xtext_realize (GtkWidget * widget)
window = gdk_window_new (parent_window, &attributes, attributes_mask);
#if HAVE_GTK3
gtk_widget_set_window (widget, window);
#else
widget->window = window;
#endif
gdk_window_set_user_data (window, widget);
@@ -1027,7 +1131,15 @@ gtk_xtext_size_request_internal (GtkWidget *widget, GtkRequisition *requisition)
requisition->height = 90;
}
#if !HAVE_GTK3
static void
gtk_xtext_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
gtk_xtext_size_request_internal (widget, requisition);
}
#endif
#if HAVE_GTK3
static void
gtk_xtext_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural)
{
@@ -1059,6 +1171,7 @@ gtk_xtext_get_preferred_height_for_width (GtkWidget *widget, gint width,
*minimum = requisition.height;
*natural = requisition.height;
}
#endif
static void
gtk_xtext_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
@@ -1070,13 +1183,23 @@ gtk_xtext_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
if (allocation->width == xtext->buffer->window_width)
height_only = TRUE;
#if HAVE_GTK3
gtk_widget_set_allocation (widget, allocation);
#endif
#if !HAVE_GTK3
widget->allocation = *allocation;
#endif
if (gtk_widget_get_realized (GTK_WIDGET(widget)))
{
xtext->buffer->window_width = allocation->width;
xtext->buffer->window_height = allocation->height;
#if HAVE_GTK3
window = gtk_widget_get_window (widget);
#endif
#if !HAVE_GTK3
window = widget->window;
#endif
if (window)
gdk_window_move_resize (window, allocation->x, allocation->y,
allocation->width, allocation->height);
@@ -1268,8 +1391,13 @@ gtk_xtext_draw_sep (GtkXText * xtext, int y)
if (y == -1)
{
y = 0;
#if HAVE_GTK3
gtk_widget_get_allocation (GTK_WIDGET (xtext), &allocation);
height = allocation.height;
#endif
#if !HAVE_GTK3
height = GTK_WIDGET (xtext)->allocation.height;
#endif
} else
{
height = xtext->fontsize;
@@ -1332,7 +1460,12 @@ gtk_xtext_draw_marker (GtkXText * xtext, textentry * ent, int y)
else return;
x = 0;
#if HAVE_GTK3
gtk_widget_get_allocation (GTK_WIDGET (xtext), &allocation);
#endif
#if !HAVE_GTK3
allocation = GTK_WIDGET (xtext)->allocation;
#endif
width = allocation.width;
cr = xtext_create_context (xtext);
@@ -1356,7 +1489,12 @@ gtk_xtext_render (GtkWidget *widget, GdkRectangle *area, cairo_t *cr)
xtext->draw_cr = cr;
#if HAVE_GTK3
gtk_widget_get_allocation (widget, &allocation);
#endif
#if !HAVE_GTK3
allocation = widget->allocation;
#endif
if (area->x == 0 && area->y == 0 &&
area->height == allocation.height &&
@@ -1428,6 +1566,7 @@ gtk_xtext_paint (GtkWidget *widget, GdkRectangle *area)
* can be buffered without ever being presented. Queue a redraw instead and
* let the widget's ::draw handler do the actual painting.
*/
#if HAVE_GTK3
if (G_LIKELY (gtk_widget_get_realized (widget)))
{
if (area)
@@ -1435,8 +1574,12 @@ gtk_xtext_paint (GtkWidget *widget, GdkRectangle *area)
else
gtk_widget_queue_draw (widget);
}
#else
gtk_xtext_render (widget, area, NULL);
#endif
}
#if HAVE_GTK3
static gboolean
gtk_xtext_draw (GtkWidget *widget, cairo_t *cr)
{
@@ -1456,7 +1599,16 @@ gtk_xtext_draw (GtkWidget *widget, cairo_t *cr)
gtk_xtext_render (widget, &area, cr);
return FALSE;
}
#endif
#if !HAVE_GTK3
static gboolean
gtk_xtext_expose (GtkWidget * widget, GdkEventExpose * event)
{
gtk_xtext_render (widget, &event->area, NULL);
return FALSE;
}
#endif
/* render a selection that has extended or contracted upward */
@@ -1781,7 +1933,12 @@ gtk_xtext_scrolldown_timeout (GtkXText * xtext)
GtkAdjustment *adj = xtext->adj;
GdkWindow *window;
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return 0;
gtk_xtext_get_pointer (window, NULL, &p_y, NULL);
@@ -1820,7 +1977,12 @@ gtk_xtext_scrollup_timeout (GtkXText * xtext)
int delta_y;
GdkWindow *window;
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return 0;
gtk_xtext_get_pointer (window, NULL, &p_y, NULL);
@@ -1867,7 +2029,12 @@ gtk_xtext_selection_update (GtkXText * xtext, GdkEventMotion * event, int p_y, g
return;
}
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return;
win_height = gdk_window_get_height (window);
@@ -2042,7 +2209,9 @@ static gboolean
gtk_xtext_leave_notify (GtkWidget * widget, GdkEventCrossing * event)
{
GtkXText *xtext = GTK_XTEXT (widget);
#if HAVE_GTK3
GdkWindow *window = gtk_widget_get_window (widget);
#endif
if (xtext->cursor_hand)
{
@@ -2050,8 +2219,13 @@ gtk_xtext_leave_notify (GtkWidget * widget, GdkEventCrossing * event)
xtext->hilight_start = -1;
xtext->hilight_end = -1;
xtext->cursor_hand = FALSE;
#if HAVE_GTK3
if (window)
gdk_window_set_cursor (window, 0);
#endif
#if !HAVE_GTK3
gdk_window_set_cursor (widget->window, 0);
#endif
xtext->hilight_ent = NULL;
}
@@ -2061,8 +2235,13 @@ gtk_xtext_leave_notify (GtkWidget * widget, GdkEventCrossing * event)
xtext->hilight_start = -1;
xtext->hilight_end = -1;
xtext->cursor_resize = FALSE;
#if HAVE_GTK3
if (window)
gdk_window_set_cursor (window, 0);
#endif
#if !HAVE_GTK3
gdk_window_set_cursor (widget->window, 0);
#endif
xtext->hilight_ent = NULL;
}
@@ -2154,8 +2333,14 @@ gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event)
GdkWindow *window;
GtkAllocation allocation;
#if HAVE_GTK3
window = gtk_widget_get_window (widget);
gtk_widget_get_allocation (widget, &allocation);
#endif
#if !HAVE_GTK3
window = widget->window;
allocation = widget->allocation;
#endif
if (!window)
return FALSE;
@@ -2337,7 +2522,12 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event)
int old;
GtkAllocation allocation;
#if HAVE_GTK3
gtk_widget_get_allocation (widget, &allocation);
#endif
#if !HAVE_GTK3
allocation = widget->allocation;
#endif
if (xtext->moving_separator)
{
@@ -2416,7 +2606,12 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
int line_x, x, y, offset, len;
GdkWindow *window;
#if HAVE_GTK3
window = gtk_widget_get_window (widget);
#endif
#if !HAVE_GTK3
window = widget->window;
#endif
if (!window)
return FALSE;
@@ -2650,6 +2845,7 @@ gtk_xtext_selection_get (GtkWidget * widget,
#ifdef GDK_WINDOWING_X11
{
GdkDisplay *display;
#if HAVE_GTK3
GdkWindow *window = gtk_widget_get_window (widget);
if (!window || !GDK_IS_WINDOW (window))
@@ -2657,6 +2853,10 @@ gtk_xtext_selection_get (GtkWidget * widget,
display = gdk_window_get_display (window);
if (!display)
break;
#endif
#if !HAVE_GTK3
display = gdk_window_get_display (widget->window);
#endif
GdkAtom encoding;
gint format;
gint new_length;
@@ -2729,10 +2929,15 @@ gtk_xtext_scroll_adjustments (GtkXText *xtext, GtkAdjustment *hadj, GtkAdjustmen
if (xtext->adj != vadj)
{
xtext->adj = vadj;
#if HAVE_GTK3
if (g_object_is_floating (xtext->adj))
g_object_ref_sink (xtext->adj);
else
g_object_ref (xtext->adj);
#endif
#if !HAVE_GTK3
g_object_ref_sink (xtext->adj);
#endif
xtext->vc_signal_tag = g_signal_connect (xtext->adj, "value-changed",
G_CALLBACK (gtk_xtext_adjustment_changed),
@@ -2747,9 +2952,19 @@ gtk_xtext_class_init (GtkXTextClass * class)
{
GtkWidgetClass *widget_class;
GtkXTextClass *xtext_class;
#if HAVE_GTK3
GObjectClass *object_class;
#endif
#if !HAVE_GTK3
GtkObjectClass *object_class;
#endif
#if HAVE_GTK3
object_class = G_OBJECT_CLASS (class);
#endif
#if !HAVE_GTK3
object_class = (GtkObjectClass *) class;
#endif
widget_class = (GtkWidgetClass *) class;
xtext_class = (GtkXTextClass *) class;
@@ -2772,23 +2987,38 @@ gtk_xtext_class_init (GtkXTextClass * class)
G_TYPE_NONE,
2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
#if HAVE_GTK3
object_class->dispose = gtk_xtext_dispose;
object_class->finalize = gtk_xtext_finalize;
#else
object_class->destroy = gtk_xtext_destroy;
#endif
widget_class->realize = gtk_xtext_realize;
widget_class->unrealize = gtk_xtext_unrealize;
#if !HAVE_GTK3
widget_class->size_request = gtk_xtext_size_request;
#endif
widget_class->size_allocate = gtk_xtext_size_allocate;
widget_class->button_press_event = gtk_xtext_button_press;
widget_class->button_release_event = gtk_xtext_button_release;
widget_class->motion_notify_event = gtk_xtext_motion_notify;
widget_class->selection_clear_event = (void *)gtk_xtext_selection_kill;
widget_class->selection_get = gtk_xtext_selection_get;
#if HAVE_GTK3
widget_class->draw = gtk_xtext_draw;
widget_class->get_preferred_width = gtk_xtext_get_preferred_width;
widget_class->get_preferred_height = gtk_xtext_get_preferred_height;
widget_class->get_preferred_height_for_width = gtk_xtext_get_preferred_height_for_width;
#endif
#if !HAVE_GTK3
widget_class->expose_event = gtk_xtext_expose;
#endif
widget_class->scroll_event = gtk_xtext_scroll;
widget_class->leave_notify_event = gtk_xtext_leave_notify;
#if !HAVE_GTK3
widget_class->set_scroll_adjustments_signal = xtext_signals[SET_SCROLL_ADJUSTMENTS];
#endif
xtext_class->word_click = NULL;
xtext_class->set_scroll_adjustments = gtk_xtext_scroll_adjustments;
@@ -2976,7 +3206,9 @@ gtk_xtext_render_flush (GtkXText * xtext, int x, int y, unsigned char *str,
int dest_x = 0, dest_y = 0;
int tile_x = xtext->ts_x;
int tile_y = xtext->ts_y;
#if HAVE_GTK3
GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
if (xtext->dont_render || len < 1 || xtext->hidden)
return 0;
@@ -3000,10 +3232,16 @@ gtk_xtext_render_flush (GtkXText * xtext, int x, int y, unsigned char *str,
goto dounder;
}
#if HAVE_GTK3
if (!window)
return str_width;
surface = gdk_window_create_similar_surface (window,
CAIRO_CONTENT_COLOR_ALPHA, str_width, xtext->fontsize);
#endif
#if !HAVE_GTK3
surface = gdk_window_create_similar_surface (GTK_WIDGET (xtext)->window,
CAIRO_CONTENT_COLOR_ALPHA, str_width, xtext->fontsize);
#endif
if (surface)
{
dest_x = x;
@@ -4050,7 +4288,12 @@ gtk_xtext_calc_lines (xtext_buffer *buf, int fire_signal)
int lines;
GdkWindow *window;
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (buf->xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (buf->xtext)->window;
#endif
if (!window)
return;
height = gdk_window_get_height (window);
@@ -4142,6 +4385,7 @@ gtk_xtext_render_ents (GtkXText * xtext, textentry * enta, textentry * entb)
* window painting may not be presented immediately. Queue a frame instead so
* selections appear right away.
*/
#if HAVE_GTK3
if (xtext->draw_cr == NULL)
{
GtkWidget *w = GTK_WIDGET (xtext);
@@ -4149,6 +4393,7 @@ gtk_xtext_render_ents (GtkXText * xtext, textentry * enta, textentry * entb)
gtk_widget_queue_draw (w);
return 0;
}
#endif
textentry *ent, *orig_ent, *tmp_ent;
int line;
@@ -4162,7 +4407,12 @@ gtk_xtext_render_ents (GtkXText * xtext, textentry * enta, textentry * entb)
if (xtext->buffer->indent < MARGIN)
xtext->buffer->indent = MARGIN; /* 2 pixels is our left margin */
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return 0;
height = gdk_window_get_height (window);
@@ -4247,6 +4497,7 @@ gtk_xtext_render_page (GtkXText * xtext)
* If we're not currently inside ::draw, xtext->draw_cr is NULL. In that case
* just request a redraw and let the normal GTK paint cycle do the work.
*/
#if HAVE_GTK3
if (xtext->draw_cr == NULL)
{
GtkWidget *w = GTK_WIDGET (xtext);
@@ -4254,6 +4505,7 @@ gtk_xtext_render_page (GtkXText * xtext)
gtk_widget_queue_draw (w);
return;
}
#endif
textentry *ent;
int line;
@@ -4273,7 +4525,12 @@ gtk_xtext_render_page (GtkXText * xtext)
if (xtext->buffer->indent < MARGIN)
xtext->buffer->indent = MARGIN; /* 2 pixels is our left margin */
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return;
width = gdk_window_get_width (window);
@@ -4324,7 +4581,12 @@ gtk_xtext_render_page (GtkXText * xtext)
cr = xtext_create_context (xtext);
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
#if HAVE_GTK3
surface = xtext_surface_from_window (window);
#endif
#if !HAVE_GTK3
surface = xtext_surface_from_window (GTK_WIDGET (xtext)->window);
#endif
if (!surface)
{
cairo_restore (cr);
@@ -4351,7 +4613,12 @@ gtk_xtext_render_page (GtkXText * xtext)
cr = xtext_create_context (xtext);
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
#if HAVE_GTK3
surface = xtext_surface_from_window (window);
#endif
#if !HAVE_GTK3
surface = xtext_surface_from_window (GTK_WIDGET (xtext)->window);
#endif
if (!surface)
{
cairo_restore (cr);
@@ -4623,7 +4890,12 @@ gtk_xtext_check_ent_visibility (GtkXText * xtext, textentry *find_ent, int add)
return FALSE;
}
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return FALSE;
height = gdk_window_get_height (window);
@@ -5508,7 +5780,12 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
if (!gtk_widget_get_realized (GTK_WIDGET (xtext)))
gtk_widget_realize (GTK_WIDGET (xtext));
#if HAVE_GTK3
window = gtk_widget_get_window (GTK_WIDGET (xtext));
#endif
#if !HAVE_GTK3
window = GTK_WIDGET (xtext)->window;
#endif
if (!window)
return;
h = gdk_window_get_height (window);
@@ -5571,6 +5848,7 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
}
gtk_xtext_render_page (xtext);
#if HAVE_GTK3
{
GtkAllocation allocation;
gdouble lower = 0;
@@ -5597,6 +5875,9 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
gtk_adjustment_set_page_increment (xtext->adj, page_size);
gtk_adjustment_value_changed (xtext->adj);
}
#else
gtk_adjustment_changed (xtext->adj);
#endif
}
}

View File

@@ -21,6 +21,9 @@
#define ZOITECHAT_XTEXT_H
#include <gtk/gtk.h>
#if !defined(GTK_MAJOR_VERSION) || GTK_MAJOR_VERSION < 3
#include <gtk/gtkobject.h>
#endif
#include <cairo.h>
#include "xtext-color.h"
@@ -127,7 +130,11 @@ typedef struct {
struct _GtkXText
{
#if HAVE_GTK3
GtkWidget parent_instance;
#else
GtkWidget parent;
#endif
xtext_buffer *buffer;
xtext_buffer *orig_buffer;

View File

@@ -1,41 +0,0 @@
# Troubleshooting
## Flatpak
If `flatpak run net.zoite.Zoitechat` only prints `Gtk-WARNING **: cannot open display`,
collect extra diagnostics with:
```bash
flatpak run --devel --command=sh net.zoite.Zoitechat
```
Then inside that shell:
```bash
echo "DISPLAY=$DISPLAY WAYLAND_DISPLAY=$WAYLAND_DISPLAY XDG_SESSION_TYPE=$XDG_SESSION_TYPE"
xdpyinfo >/tmp/xdpyinfo.log 2>&1 || true
env G_MESSAGES_DEBUG=all zoitechat 2>&1 | tee /tmp/zoitechat-debug.log
```
To inspect sandbox permissions from the host:
```bash
flatpak info --show-permissions net.zoite.Zoitechat
flatpak override --user --show net.zoite.Zoitechat
```
If needed, try running with direct access to your active display stack:
```bash
# X11 sessions
flatpak override --user --socket=x11 net.zoite.Zoitechat
# Wayland sessions
flatpak override --user --socket=wayland net.zoite.Zoitechat
```
You can reset overrides after testing:
```bash
flatpak override --user --reset net.zoite.Zoitechat
```

View File

@@ -114,7 +114,6 @@
<Copy SourceFiles="@(LuaLib)" DestinationFiles="@(LuaLib->'$(ZoiteChatRel)\lib\lua\%(RecursiveDir)%(Filename)%(Extension)')" />
<Copy SourceFiles="@(Typelib)" DestinationFiles="@(Typelib->'$(ZoiteChatRel)\lib\girepository-1.0\%(Filename)%(Extension)')" />
<Copy SourceFiles="..\..\plugins\python\xchat.py" DestinationFolder="$(ZoiteChatRel)\python" />
<Copy SourceFiles="..\..\plugins\python\hexchat.py" DestinationFolder="$(ZoiteChatRel)\python" />
<Copy SourceFiles="..\..\plugins\python\zoitechat.py" DestinationFolder="$(ZoiteChatRel)\python" />
<Copy SourceFiles="..\..\plugins\python\_zoitechat.py" DestinationFolder="$(ZoiteChatRel)\python" />

View File

@@ -1 +1 @@
2.18.0~pre2
2.18.0-pre1

View File

@@ -17,7 +17,7 @@
<!-- G_DISABLE_DEPRECATED is unfeasible due to g_completion_* -->
<!-- must be buildable with GSEAL_ENABLE in the future, xtext, setup, and chanview-tabs stand in the way -->
<OwnFlags>GTK_DISABLE_DEPRECATED;GDK_PIXBUF_DISABLE_DEPRECATED;G_DISABLE_SINGLE_INCLUDES;GDK_PIXBUF_DISABLE_SINGLE_INCLUDES;GTK_DISABLE_SINGLE_INCLUDES;HAVE_X509_GET_SIGNATURE_NID;HAVE_SSL_CTX_GET_SSL_METHOD;DEFAULT_CERT_FILE="cert.pem";HAVE_STRTOULL;strtoull=_strtoui64;strcasecmp=stricmp;strncasecmp=strnicmp;__inline__=__inline</OwnFlags>
<OwnFlags>GTK_DISABLE_DEPRECATED;GDK_PIXBUF_DISABLE_DEPRECATED;G_DISABLE_SINGLE_INCLUDES;GDK_PIXBUF_DISABLE_SINGLE_INCLUDES;GTK_DISABLE_SINGLE_INCLUDES;HAVE_X509_GET_SIGNATURE_NID;HAVE_SSL_CTX_GET_SSL_METHOD;DEFAULT_CERT_FILE="cert.pem";HAVE_STRTOULL;strtoull=_strtoui64;strcasecmp=stricmp;strncasecmp=strnicmp;__inline__=__inline;$(GtkDefines)</OwnFlags>
<!-- FIXME: Add ability to use debug builds -->
<DepsRoot>$(YourDepsPath)\$(ZoiteChatPlatform)\release</DepsRoot>
@@ -67,6 +67,7 @@
<Glib>$(DepsRoot)\include\glib-2.0;$(DepsRoot)\lib\glib-2.0\include;$(DepsRoot)\include\libxml2</Glib>
<UsingGtk3 Condition="Exists('$(DepsRoot)\\include\\gtk-3.0\\gtk\\gtk.h')">true</UsingGtk3>
<GtkDefines>HAVE_GTK3</GtkDefines>
<Gtk3>$(DepsRoot)\include\gtk-3.0;$(DepsRoot)\lib\gtk-3.0\include</Gtk3>
<GtkCommon>$(DepsRoot)\include\atk-1.0;$(DepsRoot)\include\cairo;$(DepsRoot)\include\pango-1.0;$(DepsRoot)\include\gdk-pixbuf-2.0;$(DepsRoot)\include\harfbuzz</GtkCommon>
<Gtk>$(Gtk3);$(GtkCommon)</Gtk>