mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-10-21 12:17:14 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bae96668a |
@@ -29,13 +29,13 @@ jobs:
|
||||
build-essential pkg-config meson ninja-build cmake \
|
||||
gettext \
|
||||
libcanberra-dev libglib2.0-dev \
|
||||
libarchive-dev \
|
||||
libarchive-dev libxss-dev \
|
||||
libgtk-3-dev libfontconfig1-dev libpango1.0-dev xvfb xauth dbus-daemon at-spi2-core \
|
||||
libwayland-client0 libwayland-cursor0 libwayland-egl1 \
|
||||
libxkbcommon0 \
|
||||
libgtk-3-bin libglib2.0-bin glib-networking shared-mime-info gsettings-desktop-schemas \
|
||||
liblua5.4-dev libpci-dev libperl-dev libssl-dev libayatana-appindicator3-dev \
|
||||
perl python3 python3-minimal python3-dev python3-cffi python3-sphinx mono-devel desktop-file-utils \
|
||||
perl python3 python3-minimal python3-dev python3-cffi mono-devel desktop-file-utils \
|
||||
breeze-gtk-theme \
|
||||
patchelf file curl
|
||||
|
||||
@@ -45,7 +45,6 @@ jobs:
|
||||
rm -rf build
|
||||
meson setup build \
|
||||
--prefix=/usr \
|
||||
-Dinstall-docs=true \
|
||||
-Dtext-frontend=true \
|
||||
-Dwith-perl=perl \
|
||||
-Dwith-python=python3 \
|
||||
@@ -58,7 +57,7 @@ jobs:
|
||||
ninja -C build
|
||||
|
||||
- name: Test emoji catalog, font coverage and picker
|
||||
run: xvfb-run -a dbus-run-session -- meson test -C build --print-errorlogs "Emoji Data Tests" "Emoji Font Tests" "Emoji UI Tests"
|
||||
run: xvfb-run -a dbus-run-session -- meson test -C build --print-errorlogs "Autoaway Tests" "Idle Backend Tests" "Emoji Data Tests" "Emoji Font Tests" "Emoji UI Tests"
|
||||
|
||||
- name: Install to AppDir
|
||||
run: |
|
||||
|
||||
@@ -198,7 +198,7 @@ jobs:
|
||||
)
|
||||
shell: cmd
|
||||
|
||||
- name: Test emoji catalog, font coverage and picker
|
||||
- name: Test autoaway, emoji catalog, font coverage and picker
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
|
||||
@@ -213,6 +213,10 @@ jobs:
|
||||
..\zoitechat-build\x64\tests\emoji-%%T-tests.exe --tap
|
||||
if errorlevel 1 exit /b 1
|
||||
)
|
||||
msbuild win32\autoaway-tests.vcxproj /m /verbosity:minimal /p:Configuration=Release /p:Platform=x64
|
||||
if errorlevel 1 exit /b 1
|
||||
..\zoitechat-build\x64\tests\autoaway-tests.exe --tap
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
- name: Preparing Artifacts
|
||||
run: |
|
||||
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
|
||||
# Master added native emoji font staging and tests after the release
|
||||
# branch split. Run these before packaging so MSI/MSIX use verified files.
|
||||
- name: Test emoji catalog, font coverage and picker
|
||||
- name: Test autoaway, emoji catalog, font coverage and picker
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
|
||||
@@ -224,6 +224,10 @@ jobs:
|
||||
..\zoitechat-build\x64\tests\emoji-%%T-tests.exe --tap
|
||||
if errorlevel 1 exit /b 1
|
||||
)
|
||||
msbuild win32\autoaway-tests.vcxproj /m /verbosity:minimal /p:Configuration=Release /p:Platform=x64
|
||||
if errorlevel 1 exit /b 1
|
||||
..\zoitechat-build\x64\tests\autoaway-tests.exe --tap
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
- name: Install WiX Toolset
|
||||
shell: pwsh
|
||||
|
||||
+5
-11
@@ -5,14 +5,10 @@ Unicode Emoji 17.0. It is vendored from Debian's
|
||||
`fonts-noto-color-emoji` 2.051 package, built from the corresponding
|
||||
Google Noto Emoji release.
|
||||
|
||||
By default, GTK builds install this exact file, including Windows
|
||||
(installer and portable builds), AppImage, Flatpak, and native Meson/RPM.
|
||||
Meson packagers can set `-Dinstall-emoji-font=false` to omit the bundled
|
||||
font and its installed notices and use system emoji fonts instead. An
|
||||
explicit `ZOITECHAT_EMOJI_FONT` path still enables the private font map
|
||||
in such builds. With the bundled font, it is registered privately as
|
||||
`ZoiteChat Emoji`; an older system Noto font cannot replace it. No font
|
||||
is installed globally on Windows.
|
||||
Every GTK build installs this exact file: Windows (installer and portable
|
||||
build files), AppImage, Flatpak and native Meson/RPM builds. It is loaded
|
||||
into a private Pango/FreeType font map as `ZoiteChat Emoji`; an older system
|
||||
Noto font cannot replace it. No font is installed globally on Windows.
|
||||
|
||||
Chat windows and the emoji picker share this map. Fontconfig still loads
|
||||
system fonts and configuration for ordinary text, and the configured text
|
||||
@@ -33,9 +29,7 @@ directory; Windows resolves it relative to the executable. AppImage sets
|
||||
ZOITECHAT_EMOJI_FONT="$PWD/data/fonts/NotoColorEmoji.ttf" build/src/fe-gtk/zoitechat
|
||||
```
|
||||
|
||||
An unexpectedly missing or unloadable bundled font logs a warning and retains
|
||||
system-font fallback. When installation is disabled deliberately, fallback is
|
||||
quiet unless an explicit `ZOITECHAT_EMOJI_FONT` override is invalid.
|
||||
A missing/unloadable file logs a warning and retains system-font fallback.
|
||||
CI verifies the installed copy and tests catalog/font coverage; AppImage and
|
||||
Windows also run the interactive picker regression tests. Native themes,
|
||||
DPI and different Pango/Cairo versions can still affect pixel-level output.
|
||||
|
||||
+9
-11
@@ -1,15 +1,13 @@
|
||||
emoji_font_dir = join_paths(get_option('datadir'), 'fonts', 'zoitechat')
|
||||
emoji_font_doc_dir = join_paths(get_option('datadir'), 'doc', 'zoitechat', 'fonts')
|
||||
|
||||
if get_option('install-emoji-font')
|
||||
install_data(
|
||||
'NotoColorEmoji.ttf',
|
||||
install_dir: emoji_font_dir,
|
||||
)
|
||||
install_data(
|
||||
'NotoColorEmoji.ttf',
|
||||
install_dir: emoji_font_dir,
|
||||
)
|
||||
|
||||
install_data(
|
||||
'OFL.txt',
|
||||
'README.md',
|
||||
install_dir: emoji_font_doc_dir,
|
||||
)
|
||||
endif
|
||||
install_data(
|
||||
'OFL.txt',
|
||||
'README.md',
|
||||
install_dir: emoji_font_doc_dir,
|
||||
)
|
||||
|
||||
@@ -71,12 +71,6 @@ Packagers may exclude `docs/_theme/basicstrap/` from the source package.
|
||||
The default theme continues to build without that directory. No pre-minified
|
||||
third-party assets need to be added or rebuilt for this theme.
|
||||
|
||||
The Meson option `-Dinstall-docs` defaults to `false`, so platforms that
|
||||
do not ship offline documentation do not need Sphinx just to build ZoiteChat.
|
||||
Pass `-Dinstall-docs=true` when packaging local HTML documentation. Fedora
|
||||
and AppImage enable it explicitly; the Debian documentation package can do
|
||||
the same.
|
||||
|
||||
Build with the distribution's `python3-sphinx`. After installing the HTML
|
||||
into the package staging directory, use `dh_sphinxdoc` (or `dh --with
|
||||
sphinxdoc`) to replace Sphinx's standard JavaScript files with system
|
||||
|
||||
Vendored
+1
-1
@@ -807,7 +807,7 @@ a.headerlink:focus-visible {
|
||||
:root {
|
||||
--page: var(--bg);
|
||||
--panel: var(--chrome);
|
||||
--font: system-ui, -apple-system, "Segoe UI", "DejaVu Sans", sans-serif;
|
||||
--font: system-ui, -apple-system, "Segoe UI", sans-serif;
|
||||
}
|
||||
.site-header { padding: 0; }
|
||||
.appearance select { min-height: 0; border-radius: 3px; }
|
||||
|
||||
Vendored
+2
-2
@@ -16,7 +16,7 @@
|
||||
--success: #236741;
|
||||
--code: #f2f4f6;
|
||||
--shadow: none;
|
||||
--mono: Consolas,"DejaVu Sans Mono","Liberation Mono",monospace;
|
||||
--mono: Consolas,"Liberation Mono",monospace;
|
||||
}
|
||||
|
||||
html[data-theme=dark] {
|
||||
@@ -45,7 +45,7 @@ body {
|
||||
margin: 0;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font: 15px/1.6 system-ui,-apple-system,"Segoe UI","DejaVu Sans",sans-serif;
|
||||
font: 15px/1.6 system-ui,-apple-system,"Segoe UI",sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
Vendored
-2
@@ -135,9 +135,7 @@
|
||||
{{ js_tag(scriptfile) }}
|
||||
{%- endif -%}
|
||||
{%- endfor %}
|
||||
{%- if theme_theme_preview|tobool %}
|
||||
<script type="text/javascript" src="{{ pathto('_static/js/jquery.cookie.min.js', 1) }}"></script>
|
||||
{%- endif %}
|
||||
<script type="text/javascript" src="{{ pathto('_static/js/basicstrap.js', 1) }}"></script>
|
||||
<script type="text/javascript">
|
||||
DOCUMENTATION_OPTIONS.FILE_SUFFIX = DOCUMENTATION_OPTIONS.FILE_SUFFIX || '.html';
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def prune_unused_local_assets(output_dir):
|
||||
index_path = os.path.join(output_dir, "index.html")
|
||||
|
||||
try:
|
||||
with open(index_path, "r", encoding="utf-8") as index_file:
|
||||
index_html = index_file.read()
|
||||
except OSError:
|
||||
return
|
||||
|
||||
if "bootswatch-" not in index_html:
|
||||
for bootstrap_version in ("bootstrap2", "bootstrap3"):
|
||||
css_dir = os.path.join(
|
||||
output_dir, "_static", "css", bootstrap_version
|
||||
)
|
||||
if not os.path.isdir(css_dir):
|
||||
continue
|
||||
|
||||
for filename in os.listdir(css_dir):
|
||||
if filename.startswith("bootswatch-") and filename.endswith(".css"):
|
||||
os.remove(os.path.join(css_dir, filename))
|
||||
|
||||
if "jquery.cookie.min.js" not in index_html:
|
||||
js_dir = os.path.join(output_dir, "_static", "js")
|
||||
for filename in ("jquery.cookie.min.js", "jquery.cookie-1.4.1.min.js"):
|
||||
path = os.path.join(js_dir, filename)
|
||||
if os.path.isfile(path):
|
||||
os.remove(path)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 4:
|
||||
raise SystemExit("usage: build-docs.py SOURCE_DIR OUTPUT_DIR STAMP_FILE")
|
||||
|
||||
source_dir = os.path.abspath(sys.argv[1])
|
||||
output_dir = os.path.abspath(sys.argv[2])
|
||||
stamp_file = os.path.abspath(sys.argv[3])
|
||||
doctree_dir = output_dir + ".doctrees"
|
||||
|
||||
shutil.rmtree(output_dir, ignore_errors=True)
|
||||
shutil.rmtree(doctree_dir, ignore_errors=True)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"sphinx",
|
||||
"-b",
|
||||
"html",
|
||||
"-d",
|
||||
doctree_dir,
|
||||
source_dir,
|
||||
output_dir,
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
prune_unused_local_assets(output_dir)
|
||||
|
||||
with open(stamp_file, "w", encoding="utf-8") as stamp:
|
||||
stamp.write("built\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 4:
|
||||
raise SystemExit("usage: install-docs.py STAMP_FILE SOURCE_DIR DATADIR")
|
||||
|
||||
_, source_dir, datadir = sys.argv[1:]
|
||||
source_dir = os.path.abspath(source_dir)
|
||||
|
||||
if not os.path.isfile(sys.argv[1]):
|
||||
raise SystemExit("documentation build did not produce its stamp file")
|
||||
if not os.path.isfile(os.path.join(source_dir, "index.html")):
|
||||
raise SystemExit("documentation build did not produce index.html")
|
||||
|
||||
if os.path.isabs(datadir):
|
||||
destdir = os.environ.get("DESTDIR", "")
|
||||
if destdir:
|
||||
data_root = os.path.join(destdir, datadir.lstrip("/\\"))
|
||||
else:
|
||||
data_root = datadir
|
||||
else:
|
||||
data_root = os.path.join(os.environ["MESON_INSTALL_DESTDIR_PREFIX"], datadir)
|
||||
|
||||
destination = os.path.join(data_root, "doc", "zoitechat", "html")
|
||||
shutil.rmtree(destination, ignore_errors=True)
|
||||
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
||||
shutil.copytree(source_dir, destination)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -628,3 +628,38 @@ List of Settings
|
||||
+------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| **url\_logging** | Toggle logging URLs to *<config>/url.log*. |
|
||||
+------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Autoaway
|
||||
--------
|
||||
|
||||
In **Preferences > Chatting > General > Away**, set **Autoaway after** to a
|
||||
number of minutes. The default is 0 (disabled). The separate **Autoaway
|
||||
message** defaults to "Idle". No plugin or scripting language is required.
|
||||
The same options are available immediately through ``/SET``::
|
||||
|
||||
/SET away_auto_timeout 10
|
||||
/SET away_auto_reason Idle
|
||||
/SET away_auto_system ON
|
||||
|
||||
With desktop activity enabled, Windows uses the current login session's last
|
||||
input time, macOS uses CoreGraphics input time, and native X11 uses the
|
||||
XScreenSaver extension if its development library was available at build time.
|
||||
Debian/Ubuntu builders can install ``libxss-dev``; Fedora builders can install
|
||||
``libXScrnSaver-devel``. Meson detects this optional dependency automatically.
|
||||
|
||||
On native Wayland, XWayland, unsupported desktops, and builds without XScreenSaver,
|
||||
autoaway falls back to keyboard, mouse, scroll and touch activity **inside
|
||||
ZoiteChat**. Activity in other applications does not reset that fallback timer.
|
||||
Set ``away_auto_system OFF`` to always use ZoiteChat activity on every platform.
|
||||
The text frontend uses submitted user input. Network traffic, redraws and window
|
||||
focus changes do not count as user activity.
|
||||
|
||||
Autoaway checks every five seconds, after IRC login finishes, independently on
|
||||
each connected network. Returning clears only away states set by autoaway.
|
||||
Manual ``/AWAY`` (including ``/AWAY`` while already automatically away) takes
|
||||
ownership, so activity does not clear it. ``/BACK`` resets the inactivity timer.
|
||||
The existing **Automatically unmark away** setting keeps its separate behaviour
|
||||
when sending messages. Do not run another autoaway script at the same time.
|
||||
Disabling autoaway clears its own away states. Reconnecting re-evaluates current
|
||||
inactivity instead of restoring an outdated automatic away state; manual away
|
||||
restoration is unchanged.
|
||||
|
||||
@@ -55,11 +55,10 @@
|
||||
"run-tests": true,
|
||||
"test-rule": "",
|
||||
"test-commands": [
|
||||
"meson test --print-errorlogs 'Emoji Data Tests' 'Emoji Font Tests'"
|
||||
"meson test --print-errorlogs 'Autoaway Tests' 'Idle Backend Tests' 'Emoji Data Tests' 'Emoji Font Tests'"
|
||||
],
|
||||
"config-opts": [
|
||||
"-Ddbus-service-use-appid=true",
|
||||
"-Dinstall-docs=false",
|
||||
"-Dwith-perl=perl",
|
||||
"-Dwith-python=python3",
|
||||
"-Dwith-lua=lua"
|
||||
|
||||
-39
@@ -38,15 +38,11 @@ endif
|
||||
|
||||
config_h = configuration_data()
|
||||
config_h.set('HAVE_GTK_MAC', host_machine.system() == 'darwin' and gtk_mac_dep.found())
|
||||
config_h.set10('ZOITECHAT_INSTALL_EMOJI_FONT', get_option('install-emoji-font'))
|
||||
config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
config_h.set_quoted('PACKAGE_NAME', meson.project_name())
|
||||
config_h.set_quoted('GETTEXT_PACKAGE', 'zoitechat')
|
||||
config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'),
|
||||
get_option('datadir'), 'locale'))
|
||||
config_h.set_quoted('ZOITECHAT_DOCDIR',
|
||||
join_paths(get_option('prefix'), get_option('datadir'), 'doc', 'zoitechat', 'html')
|
||||
)
|
||||
config_h.set10('ENABLE_NLS', true)
|
||||
config_h.set_quoted('ZOITECHAT_DATADIR', join_paths(get_option('prefix'), get_option('datadir')))
|
||||
|
||||
@@ -183,41 +179,6 @@ if host_machine.system() == 'darwin'
|
||||
endif
|
||||
add_project_link_arguments(global_ldflags, language: 'c')
|
||||
|
||||
if get_option('install-docs')
|
||||
docs_python = find_program('python3', 'python')
|
||||
docs_sphinx = run_command(docs_python, '-c', 'import sphinx', check: false)
|
||||
if docs_sphinx.returncode() != 0
|
||||
error('Sphinx is required to build the local HTML documentation. Install Sphinx or configure with -Dinstall-docs=false.')
|
||||
endif
|
||||
|
||||
docs_source_dir = join_paths(meson.source_root(), 'docs')
|
||||
docs_output_dir = join_paths(meson.build_root(), 'docs-html')
|
||||
docs_build_script = join_paths(docs_source_dir, 'build-docs.py')
|
||||
docs_install_script = join_paths(docs_source_dir, 'install-docs.py')
|
||||
|
||||
docs_target = custom_target(
|
||||
'html-documentation',
|
||||
output: 'html-documentation.stamp',
|
||||
command: [
|
||||
docs_python,
|
||||
docs_build_script,
|
||||
docs_source_dir,
|
||||
docs_output_dir,
|
||||
'@OUTPUT@',
|
||||
],
|
||||
build_by_default: true,
|
||||
build_always_stale: true,
|
||||
)
|
||||
|
||||
meson.add_install_script(
|
||||
docs_python,
|
||||
docs_install_script,
|
||||
docs_target,
|
||||
docs_output_dir,
|
||||
get_option('datadir'),
|
||||
)
|
||||
endif
|
||||
|
||||
subdir('src')
|
||||
if get_option('plugin')
|
||||
subdir('plugins')
|
||||
|
||||
@@ -37,12 +37,6 @@ option('install-appdata', type: 'boolean',
|
||||
option('install-plugin-metainfo', type: 'boolean', value: false,
|
||||
description: 'Installs metainfo files for enabled plugins, useful when distros create split packages'
|
||||
)
|
||||
option('install-emoji-font', type: 'boolean', value: true,
|
||||
description: 'Install the bundled Noto Color Emoji font instead of using system emoji fonts'
|
||||
)
|
||||
option('install-docs', type: 'boolean', value: false,
|
||||
description: 'Build and install the local HTML documentation'
|
||||
)
|
||||
|
||||
# Plugins
|
||||
option('with-checksum', type: 'boolean',
|
||||
|
||||
@@ -15,7 +15,6 @@ BuildRequires: perl
|
||||
BuildRequires: perl-devel
|
||||
BuildRequires: python3
|
||||
BuildRequires: python3-cffi
|
||||
BuildRequires: python3-sphinx
|
||||
BuildRequires: publicsuffix-list
|
||||
BuildRequires: xwayland-run
|
||||
BuildRequires: weston
|
||||
@@ -26,6 +25,7 @@ BuildRequires: pkgconfig(gmodule-2.0)
|
||||
BuildRequires: pkgconfig(gtk+-3.0) >= 3.22
|
||||
BuildRequires: pkgconfig(fontconfig) >= 2.13
|
||||
BuildRequires: pkgconfig(pangoft2) >= 1.44
|
||||
BuildRequires: pkgconfig(xscrnsaver)
|
||||
BuildRequires: pkgconfig(iso-codes)
|
||||
BuildRequires: pkgconfig(libarchive)
|
||||
BuildRequires: pkgconfig(libcanberra) >= 0.22
|
||||
@@ -53,7 +53,6 @@ systems.
|
||||
|
||||
%build
|
||||
%meson \
|
||||
-Dinstall-docs=true \
|
||||
-Dtext-frontend=false \
|
||||
-Dwith-checksum=true \
|
||||
-Dwith-fishlim=true \
|
||||
@@ -96,7 +95,6 @@ xwfb-run -- /usr/bin/meson test -C %{_vpath_builddir} --num-processes %{_smp_bui
|
||||
%{_datadir}/icons/hicolor/scalable/apps/net.zoite.Zoitechat.svg
|
||||
%{_datadir}/metainfo/net.zoite.Zoitechat.appdata.xml
|
||||
%{_datadir}/metainfo/net.zoite.Zoitechat*.metainfo.xml
|
||||
%{_datadir}/doc/zoitechat/html/
|
||||
%dir %{_libdir}/zoitechat
|
||||
%dir %{_libdir}/zoitechat/plugins
|
||||
%dir %{_libdir}/zoitechat/python
|
||||
|
||||
@@ -48,7 +48,6 @@ def main() -> None:
|
||||
"--prefix=/", "--libdir=lib", "--buildtype=release", "-Dgtk-frontend=true",
|
||||
"-Dtext-frontend=false", "-Dmac-integration=enabled", "-Ddbus=disabled",
|
||||
"-Dlibcanberra=disabled", "-Dappindicator=disabled", "-Dinstall-appdata=false",
|
||||
"-Dinstall-docs=false",
|
||||
"-Dwith-sysinfo=false", "-Dwith-python=false", "-Dwith-perl=false",
|
||||
"-Dwith-lua=lua", "-Dwith-fishlim=true", "-Dwith-checksum=true",
|
||||
"-Dplugin=" + ("false" if args.store_experimental else "true"),
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/* ZoiteChat
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "zoitechat.h"
|
||||
#include "zoitechatc.h"
|
||||
#include "server.h"
|
||||
#include "fe.h"
|
||||
#include "autoaway.h"
|
||||
|
||||
static gint64 last_activity;
|
||||
static int timer_tag;
|
||||
static int previous_timeout;
|
||||
static unsigned int previous_system;
|
||||
|
||||
void
|
||||
autoaway_activity (void)
|
||||
{
|
||||
last_activity = g_get_monotonic_time ();
|
||||
}
|
||||
|
||||
/* A manual /AWAY takes ownership even if the server already says away. */
|
||||
void
|
||||
autoaway_manual (server *serv)
|
||||
{
|
||||
serv->autoaway_owned = FALSE;
|
||||
autoaway_activity ();
|
||||
}
|
||||
|
||||
void
|
||||
autoaway_reset (server *serv)
|
||||
{
|
||||
if (!serv->autoaway_owned)
|
||||
return;
|
||||
|
||||
serv->autoaway_owned = FALSE;
|
||||
serv->reconnect_away = FALSE;
|
||||
g_clear_pointer (&serv->last_away_reason, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
autoaway_release (server *serv)
|
||||
{
|
||||
if (!serv->autoaway_owned)
|
||||
return;
|
||||
|
||||
/* Cancel even an unacknowledged AWAY. IRC replies may arrive later. */
|
||||
if (serv->connected && serv->end_of_motd)
|
||||
serv->p_set_back (serv);
|
||||
autoaway_reset (serv);
|
||||
}
|
||||
|
||||
void
|
||||
autoaway_check (gint64 now, gint64 desktop_idle)
|
||||
{
|
||||
GSList *list;
|
||||
gint64 idle = MAX ((gint64)0, now - last_activity);
|
||||
gint64 limit = (gint64)prefs.hex_away_auto_timeout * 60 * G_USEC_PER_SEC;
|
||||
|
||||
if (prefs.hex_away_auto_system && desktop_idle >= 0)
|
||||
idle = MIN (idle, desktop_idle);
|
||||
|
||||
for (list = serv_list; list; list = list->next)
|
||||
{
|
||||
server *serv = list->data;
|
||||
|
||||
if (!serv->connected)
|
||||
{
|
||||
/* Re-evaluate idle after login instead of restoring stale autoaway. */
|
||||
autoaway_reset (serv);
|
||||
continue;
|
||||
}
|
||||
if (!serv->end_of_motd)
|
||||
continue;
|
||||
|
||||
if (limit <= 0 || idle < limit)
|
||||
{
|
||||
autoaway_release (serv);
|
||||
continue;
|
||||
}
|
||||
if (serv->is_away || serv->reconnect_away)
|
||||
continue;
|
||||
|
||||
/* Retry a rejected/lost request slowly, never once per poll. */
|
||||
if (serv->autoaway_owned &&
|
||||
now - serv->autoaway_sent_at < 30 * G_USEC_PER_SEC)
|
||||
continue;
|
||||
|
||||
g_free (serv->last_away_reason);
|
||||
serv->last_away_reason = g_strdup (prefs.hex_away_auto_reason[0] ?
|
||||
prefs.hex_away_auto_reason : _("Idle"));
|
||||
serv->autoaway_owned = TRUE;
|
||||
serv->autoaway_sent_at = now;
|
||||
serv->p_set_away (serv, serv->last_away_reason);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
autoaway_timer (void)
|
||||
{
|
||||
autoaway_check (g_get_monotonic_time (),
|
||||
prefs.hex_away_auto_system ? fe_get_idle_time () : -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
autoaway_reinit (void)
|
||||
{
|
||||
if (previous_timeout != prefs.hex_away_auto_timeout ||
|
||||
previous_system != prefs.hex_away_auto_system)
|
||||
{
|
||||
autoaway_activity ();
|
||||
previous_timeout = prefs.hex_away_auto_timeout;
|
||||
previous_system = prefs.hex_away_auto_system;
|
||||
}
|
||||
|
||||
if (prefs.hex_away_auto_timeout > 0)
|
||||
{
|
||||
if (!timer_tag)
|
||||
{
|
||||
autoaway_activity ();
|
||||
timer_tag = fe_timeout_add_seconds (5, autoaway_timer, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timer_tag)
|
||||
{
|
||||
fe_timeout_remove (timer_tag);
|
||||
timer_tag = 0;
|
||||
}
|
||||
/* Disabling autoaway must also work without another input event. */
|
||||
autoaway_check (g_get_monotonic_time (), -1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* ZoiteChat
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ZOITECHAT_AUTOAWAY_H
|
||||
#define ZOITECHAT_AUTOAWAY_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
struct server;
|
||||
|
||||
void autoaway_activity (void);
|
||||
void autoaway_manual (struct server *serv);
|
||||
void autoaway_reset (struct server *serv);
|
||||
void autoaway_reinit (void);
|
||||
/* Both samples are in microseconds; -1 means desktop idle is unavailable. */
|
||||
void autoaway_check (gint64 now, gint64 desktop_idle);
|
||||
|
||||
#endif
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "fe.h"
|
||||
#include "text.h"
|
||||
#include "zoitechatc.h"
|
||||
#include "autoaway.h"
|
||||
#include "typedef.h"
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -359,6 +360,9 @@ default_file (void)
|
||||
|
||||
const struct prefs vars[] =
|
||||
{
|
||||
{"away_auto_reason", P_OFFSET (hex_away_auto_reason), TYPE_STR},
|
||||
{"away_auto_system", P_OFFINT (hex_away_auto_system), TYPE_BOOL, autoaway_reinit},
|
||||
{"away_auto_timeout", P_OFFINT (hex_away_auto_timeout), TYPE_INT, autoaway_reinit},
|
||||
{"away_auto_unmark", P_OFFINT (hex_away_auto_unmark), TYPE_BOOL},
|
||||
{"away_omit_alerts", P_OFFINT (hex_away_omit_alerts), TYPE_BOOL},
|
||||
{"away_reason", P_OFFSET (hex_away_reason), TYPE_STR},
|
||||
@@ -767,6 +771,7 @@ load_default_config(void)
|
||||
/* put in default values, anything left out is automatically zero */
|
||||
|
||||
/* BOOLEANS */
|
||||
prefs.hex_away_auto_system = 1;
|
||||
prefs.hex_away_show_once = 1;
|
||||
prefs.hex_away_track = 1;
|
||||
prefs.hex_dcc_auto_resume = 1;
|
||||
@@ -887,6 +892,7 @@ load_default_config(void)
|
||||
prefs.hex_url_grabber_limit = 100; /* 0 means unlimited */
|
||||
|
||||
/* STRINGS */
|
||||
strcpy (prefs.hex_away_auto_reason, _("Idle"));
|
||||
strcpy (prefs.hex_away_reason, _("I'm busy"));
|
||||
strcpy (prefs.hex_completion_suffix, ",");
|
||||
#ifdef WIN32
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="autoaway.h" />
|
||||
<ClInclude Include="cfgfiles.h" />
|
||||
<ClInclude Include="chanopt.h" />
|
||||
<ClInclude Include="ctcp.h" />
|
||||
@@ -52,6 +53,7 @@
|
||||
<ClInclude Include="gtk3-theme-service.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="autoaway.c" />
|
||||
<ClCompile Include="cfgfiles.c" />
|
||||
<ClCompile Include="chanopt.c" />
|
||||
<ClCompile Include="ctcp.c" />
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="autoaway.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cfgfiles.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -136,6 +139,9 @@
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="autoaway.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cfgfiles.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -142,6 +142,7 @@ void fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gtk_xtext_sea
|
||||
void fe_set_lag (server *serv, long lag);
|
||||
void fe_set_throttle (server *serv);
|
||||
void fe_set_away (server *serv);
|
||||
gint64 fe_get_idle_time (void);
|
||||
void fe_serverlist_open (session *sess);
|
||||
void fe_get_bool (char *title, char *prompt, void *callback, void *userdata);
|
||||
void fe_get_str (char *prompt, char *def, void *callback, void *ud);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
common_sources = [
|
||||
'autoaway.c',
|
||||
'cfgfiles.c',
|
||||
'chanopt.c',
|
||||
'ctcp.c',
|
||||
@@ -224,3 +225,10 @@ test('Hex Color Tests', hexcolor_tests,
|
||||
protocol: 'tap',
|
||||
timeout: 120,
|
||||
)
|
||||
|
||||
autoaway_tests = executable('autoaway_tests',
|
||||
['tests/test-autoaway.c', 'autoaway.c'],
|
||||
include_directories: [config_h_include, include_directories('.')],
|
||||
dependencies: zoitechat_common_header_deps,
|
||||
)
|
||||
test('Autoaway Tests', autoaway_tests, protocol: 'tap', timeout: 30)
|
||||
|
||||
+12
-1
@@ -54,6 +54,7 @@
|
||||
#include "server.h"
|
||||
#include "tree.h"
|
||||
#include "outbound.h"
|
||||
#include "autoaway.h"
|
||||
#include "chanopt.h"
|
||||
|
||||
#define TBUFSIZE 4096
|
||||
@@ -360,6 +361,10 @@ cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
{
|
||||
char *reason = word_eol[2];
|
||||
|
||||
/* Restoring a manual away after reconnect is not new user input. */
|
||||
if (!sess->server->reconnect_away)
|
||||
autoaway_manual (sess->server);
|
||||
|
||||
if (!(*reason))
|
||||
{
|
||||
if (sess->server->is_away)
|
||||
@@ -396,7 +401,10 @@ cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
static int
|
||||
cmd_back (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
{
|
||||
if (sess->server->is_away)
|
||||
gboolean was_autoaway = sess->server->autoaway_owned;
|
||||
|
||||
autoaway_manual (sess->server);
|
||||
if (sess->server->is_away || was_autoaway)
|
||||
{
|
||||
sess->server->p_set_back (sess->server);
|
||||
}
|
||||
@@ -5051,6 +5059,9 @@ handle_user_input (session *sess, char *text, int history, int nocommand)
|
||||
if (*text == '\0')
|
||||
return 1;
|
||||
|
||||
if (history)
|
||||
autoaway_activity ();
|
||||
|
||||
if (history)
|
||||
history_add (&sess->history, text);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "zoitechat.h"
|
||||
#include "proto-irc.h"
|
||||
#include "autoaway.h"
|
||||
#include "ctcp.h"
|
||||
#include "fe.h"
|
||||
#include "ignore.h"
|
||||
@@ -438,6 +439,12 @@ irc_raw (server *serv, char *raw)
|
||||
{
|
||||
int len;
|
||||
char tbuf[8704];
|
||||
|
||||
/* /QUOTE AWAY and scripts sending raw AWAY also take manual ownership. */
|
||||
if (!g_ascii_strncasecmp (raw, "AWAY", 4) &&
|
||||
(raw[4] == 0 || raw[4] == ' '))
|
||||
autoaway_manual (serv);
|
||||
|
||||
if (*raw)
|
||||
{
|
||||
len = strlen (raw);
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "proto-irc.h"
|
||||
#include "servlist.h"
|
||||
#include "server.h"
|
||||
#include "autoaway.h"
|
||||
#include "sts.h"
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
@@ -1873,6 +1874,7 @@ is_server (server *serv)
|
||||
void
|
||||
server_set_defaults (server *serv)
|
||||
{
|
||||
autoaway_reset (serv);
|
||||
g_free (serv->chantypes);
|
||||
g_clear_pointer (&serv->clienttagdeny, g_free);
|
||||
g_free (serv->chanmodes);
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
/* ZoiteChat
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "../zoitechat.h"
|
||||
#include "../autoaway.h"
|
||||
|
||||
struct zoitechatprefs prefs;
|
||||
GSList *serv_list;
|
||||
static server servers[3];
|
||||
static int away_count, back_count, timer_adds, timer_removes;
|
||||
static gint64 base;
|
||||
static char *sent_reason;
|
||||
|
||||
/* Protocol stubs deliberately do not acknowledge requests. */
|
||||
static void
|
||||
send_away (server *serv, char *reason)
|
||||
{
|
||||
away_count++;
|
||||
g_free (sent_reason);
|
||||
sent_reason = g_strdup (reason);
|
||||
}
|
||||
|
||||
static void
|
||||
send_back (server *serv)
|
||||
{
|
||||
back_count++;
|
||||
}
|
||||
|
||||
int
|
||||
fe_timeout_add_seconds (int interval, void *callback, void *data)
|
||||
{
|
||||
g_assert_cmpint (interval, ==, 5);
|
||||
timer_adds++;
|
||||
return 42;
|
||||
}
|
||||
|
||||
void
|
||||
fe_timeout_remove (int tag)
|
||||
{
|
||||
g_assert_cmpint (tag, ==, 42);
|
||||
timer_removes++;
|
||||
}
|
||||
|
||||
gint64
|
||||
fe_get_idle_time (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
prefs.hex_away_auto_timeout = 0;
|
||||
autoaway_reinit ();
|
||||
for (i = 0; i < 3; i++)
|
||||
g_free (servers[i].last_away_reason);
|
||||
g_slist_free (serv_list);
|
||||
serv_list = NULL;
|
||||
memset (servers, 0, sizeof servers);
|
||||
memset (&prefs, 0, sizeof prefs);
|
||||
away_count = back_count = timer_adds = timer_removes = 0;
|
||||
g_clear_pointer (&sent_reason, g_free);
|
||||
prefs.hex_away_auto_timeout = 10;
|
||||
prefs.hex_away_auto_system = TRUE;
|
||||
g_strlcpy (prefs.hex_away_auto_reason, "Auto idle", sizeof prefs.hex_away_auto_reason);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
servers[i].connected = TRUE;
|
||||
servers[i].end_of_motd = TRUE;
|
||||
servers[i].p_set_away = send_away;
|
||||
servers[i].p_set_back = send_back;
|
||||
}
|
||||
serv_list = g_slist_append (NULL, &servers[0]);
|
||||
autoaway_activity ();
|
||||
base = g_get_monotonic_time ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_fallback_boundary (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_check (base + 599 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 0);
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
g_assert_true (servers[0].autoaway_owned);
|
||||
g_assert_cmpstr (sent_reason, ==, "Auto idle");
|
||||
/* An ACK is not required to avoid flooding the connection. */
|
||||
autoaway_check (base + 605 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
servers[0].is_away = TRUE;
|
||||
autoaway_check (base + 640 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
autoaway_activity ();
|
||||
autoaway_check (g_get_monotonic_time (), -1);
|
||||
g_assert_cmpint (back_count, ==, 1);
|
||||
g_assert_false (servers[0].autoaway_owned);
|
||||
g_assert_null (servers[0].last_away_reason);
|
||||
}
|
||||
|
||||
static void
|
||||
test_desktop_activity (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_check (base + 900 * G_USEC_PER_SEC, 5 * G_USEC_PER_SEC);
|
||||
g_assert_cmpint (away_count, ==, 0);
|
||||
autoaway_check (base + 900 * G_USEC_PER_SEC, 700 * G_USEC_PER_SEC);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
servers[0].is_away = TRUE;
|
||||
autoaway_check (base + 905 * G_USEC_PER_SEC, 0);
|
||||
g_assert_cmpint (back_count, ==, 1);
|
||||
/* App input wins even if the native backend still has an old sample. */
|
||||
autoaway_activity ();
|
||||
autoaway_check (g_get_monotonic_time (), 900 * G_USEC_PER_SEC);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_app_mode (void)
|
||||
{
|
||||
setup ();
|
||||
prefs.hex_away_auto_system = FALSE;
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, 0);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_manual_away (void)
|
||||
{
|
||||
setup ();
|
||||
servers[0].is_away = TRUE;
|
||||
servers[0].last_away_reason = g_strdup ("Lunch");
|
||||
autoaway_check (base + 900 * G_USEC_PER_SEC, -1);
|
||||
autoaway_check (base + 905 * G_USEC_PER_SEC, 0);
|
||||
prefs.hex_away_auto_timeout = 0;
|
||||
autoaway_reinit ();
|
||||
g_assert_cmpint (away_count, ==, 0);
|
||||
g_assert_cmpint (back_count, ==, 0);
|
||||
g_assert_cmpstr (servers[0].last_away_reason, ==, "Lunch");
|
||||
}
|
||||
|
||||
static void
|
||||
test_manual_takeover (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
servers[0].is_away = TRUE;
|
||||
/* This is also called for /AWAY with no reason, even if already away. */
|
||||
autoaway_manual (&servers[0]);
|
||||
autoaway_check (g_get_monotonic_time (), 0);
|
||||
prefs.hex_away_auto_timeout = 0;
|
||||
autoaway_reinit ();
|
||||
g_assert_cmpint (back_count, ==, 0);
|
||||
g_assert_true (servers[0].is_away);
|
||||
}
|
||||
|
||||
static void
|
||||
test_pending_away_cancel (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
g_assert_false (servers[0].is_away);
|
||||
autoaway_activity ();
|
||||
autoaway_check (g_get_monotonic_time (), -1);
|
||||
g_assert_cmpint (back_count, ==, 1);
|
||||
/* A late 306 must not make us own the away state again. */
|
||||
servers[0].is_away = TRUE;
|
||||
autoaway_check (g_get_monotonic_time (), -1);
|
||||
g_assert_cmpint (back_count, ==, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_login_and_multiple_servers (void)
|
||||
{
|
||||
setup ();
|
||||
serv_list = g_slist_append (serv_list, &servers[1]);
|
||||
serv_list = g_slist_append (serv_list, &servers[2]);
|
||||
servers[1].is_away = TRUE;
|
||||
servers[1].last_away_reason = g_strdup ("Manual");
|
||||
servers[2].end_of_motd = FALSE;
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
servers[2].end_of_motd = TRUE;
|
||||
autoaway_check (base + 605 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 2);
|
||||
autoaway_check (base + 610 * G_USEC_PER_SEC, 0);
|
||||
g_assert_cmpint (back_count, ==, 2);
|
||||
g_assert_cmpstr (servers[1].last_away_reason, ==, "Manual");
|
||||
}
|
||||
|
||||
static void
|
||||
test_disconnect_and_reconnect (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
servers[0].connected = FALSE;
|
||||
servers[0].is_away = TRUE;
|
||||
servers[0].reconnect_away = TRUE;
|
||||
autoaway_check (base + 605 * G_USEC_PER_SEC, -1);
|
||||
g_assert_false (servers[0].autoaway_owned);
|
||||
g_assert_false (servers[0].reconnect_away);
|
||||
g_assert_null (servers[0].last_away_reason);
|
||||
g_assert_cmpint (back_count, ==, 0);
|
||||
servers[0].is_away = FALSE;
|
||||
servers[0].connected = TRUE;
|
||||
servers[0].end_of_motd = FALSE;
|
||||
autoaway_check (base + 610 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
servers[0].end_of_motd = TRUE;
|
||||
autoaway_check (base + 615 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 2);
|
||||
/* server_set_defaults resets ownership even before the next timer tick. */
|
||||
servers[0].reconnect_away = TRUE;
|
||||
autoaway_reset (&servers[0]);
|
||||
g_assert_false (servers[0].reconnect_away);
|
||||
/* Existing manual reconnect-away must be left alone. */
|
||||
servers[0].reconnect_away = TRUE;
|
||||
servers[0].last_away_reason = g_strdup ("Manual");
|
||||
autoaway_reset (&servers[0]);
|
||||
g_assert_true (servers[0].reconnect_away);
|
||||
g_assert_cmpstr (servers[0].last_away_reason, ==, "Manual");
|
||||
}
|
||||
|
||||
static void
|
||||
test_retry (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
autoaway_check (base + 629 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
autoaway_check (base + 630 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_disable_and_timers (void)
|
||||
{
|
||||
setup ();
|
||||
autoaway_reinit ();
|
||||
autoaway_reinit ();
|
||||
g_assert_cmpint (timer_adds, ==, 1);
|
||||
base = g_get_monotonic_time ();
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
prefs.hex_away_auto_timeout = 0;
|
||||
autoaway_reinit ();
|
||||
g_assert_cmpint (back_count, ==, 1);
|
||||
g_assert_cmpint (timer_removes, ==, 1);
|
||||
g_assert_false (servers[0].autoaway_owned);
|
||||
autoaway_reinit ();
|
||||
g_assert_cmpint (back_count, ==, 1);
|
||||
prefs.hex_away_auto_timeout = -1;
|
||||
autoaway_reinit ();
|
||||
g_assert_cmpint (away_count, ==, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_empty_reason_and_large_timeout (void)
|
||||
{
|
||||
setup ();
|
||||
prefs.hex_away_auto_reason[0] = 0;
|
||||
autoaway_check (base + 600 * G_USEC_PER_SEC, -1);
|
||||
g_assert_nonnull (sent_reason);
|
||||
g_assert_cmpstr (sent_reason, !=, "");
|
||||
setup ();
|
||||
prefs.hex_away_auto_timeout = G_MAXINT;
|
||||
autoaway_check (base + 900 * G_USEC_PER_SEC, -1);
|
||||
g_assert_cmpint (away_count, ==, 0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int result, i;
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_add_func ("/autoaway/fallback-boundary", test_fallback_boundary);
|
||||
g_test_add_func ("/autoaway/desktop-activity", test_desktop_activity);
|
||||
g_test_add_func ("/autoaway/app-mode", test_app_mode);
|
||||
g_test_add_func ("/autoaway/manual-away", test_manual_away);
|
||||
g_test_add_func ("/autoaway/manual-takeover", test_manual_takeover);
|
||||
g_test_add_func ("/autoaway/pending-cancel", test_pending_away_cancel);
|
||||
g_test_add_func ("/autoaway/login-multiple-servers", test_login_and_multiple_servers);
|
||||
g_test_add_func ("/autoaway/reconnect", test_disconnect_and_reconnect);
|
||||
g_test_add_func ("/autoaway/retry", test_retry);
|
||||
g_test_add_func ("/autoaway/disable-timers", test_disable_and_timers);
|
||||
g_test_add_func ("/autoaway/empty-reason-large-timeout", test_empty_reason_and_large_timeout);
|
||||
result = g_test_run ();
|
||||
for (i = 0; i < 3; i++)
|
||||
g_free (servers[i].last_away_reason);
|
||||
g_free (sent_reason);
|
||||
g_slist_free (serv_list);
|
||||
return result;
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "plugin.h"
|
||||
#include "plugin-identd.h"
|
||||
#include "plugin-timer.h"
|
||||
#include "autoaway.h"
|
||||
#include "notify.h"
|
||||
#include "server.h"
|
||||
#include "servlist.h"
|
||||
@@ -499,6 +500,8 @@ zoitechat_reinit_timers (void)
|
||||
static int lag_check_tag = 0;
|
||||
static int away_tag = 0;
|
||||
|
||||
autoaway_reinit ();
|
||||
|
||||
if (prefs.hex_notify_timeout && notify_tag == 0)
|
||||
{
|
||||
notify_tag = fe_timeout_add_seconds (prefs.hex_notify_timeout,
|
||||
|
||||
@@ -105,6 +105,7 @@ struct zoitechatprefs
|
||||
/* these are the rebranded, consistent, sorted zoitechat variables */
|
||||
|
||||
/* BOOLEANS */
|
||||
unsigned int hex_away_auto_system;
|
||||
unsigned int hex_away_auto_unmark;
|
||||
unsigned int hex_away_omit_alerts;
|
||||
unsigned int hex_away_show_once;
|
||||
@@ -233,6 +234,7 @@ struct zoitechatprefs
|
||||
unsigned int hex_url_logging;
|
||||
|
||||
/* NUMBERS */
|
||||
int hex_away_auto_timeout;
|
||||
int hex_away_size_max;
|
||||
int hex_away_timeout;
|
||||
int hex_completion_amount;
|
||||
@@ -311,6 +313,7 @@ struct zoitechatprefs
|
||||
int hex_url_grabber_limit;
|
||||
|
||||
/* STRINGS */
|
||||
char hex_away_auto_reason[256];
|
||||
char hex_away_reason[256];
|
||||
char hex_completion_suffix[4]; /* Only ever holds a one-character string. */
|
||||
char hex_dcc_completed_dir[PATHLEN + 1];
|
||||
@@ -597,6 +600,7 @@ typedef struct server
|
||||
/*time_t connect_time;*/ /* when did it connect? */
|
||||
unsigned long lag_sent; /* we are still waiting for this ping response*/
|
||||
time_t ping_recv; /* when we last got a ping reply */
|
||||
gint64 autoaway_sent_at;
|
||||
time_t away_time; /* when we were marked away */
|
||||
|
||||
char *encoding;
|
||||
@@ -616,6 +620,7 @@ typedef struct server
|
||||
unsigned int end_of_motd:1; /* end of motd reached (logged in) */
|
||||
unsigned int sent_quit:1; /* sent a QUIT already? */
|
||||
unsigned int use_listargs:1; /* undernet and dalnet need /list >0,<10000 */
|
||||
unsigned int autoaway_owned:1;
|
||||
unsigned int is_away:1;
|
||||
unsigned int reconnect_away:1; /* whether to reconnect in is_away state */
|
||||
unsigned int dont_use_proxy:1; /* to proxy or not to proxy */
|
||||
|
||||
@@ -52,16 +52,6 @@ emoji_font_get_map (void)
|
||||
return map;
|
||||
attempted = TRUE;
|
||||
|
||||
#if defined(ZOITECHAT_INSTALL_EMOJI_FONT) && !ZOITECHAT_INSTALL_EMOJI_FONT
|
||||
/* A distribution package can deliberately omit our private font. Keep
|
||||
* its native/system emoji rendering unless an explicit font is given. */
|
||||
{
|
||||
const char *override = g_getenv ("ZOITECHAT_EMOJI_FONT");
|
||||
if (!override || !*override)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
path = emoji_font_path ();
|
||||
if (!path || !g_file_test (path, G_FILE_TEST_IS_REGULAR))
|
||||
{
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "notifygui.h"
|
||||
#include "textgui.h"
|
||||
#include "fkeys.h"
|
||||
#include "idle.h"
|
||||
#include "plugin-tray.h"
|
||||
#include "urlgrab.h"
|
||||
#include "setup.h"
|
||||
@@ -638,6 +639,7 @@ fe_init (void)
|
||||
{
|
||||
theme_manager_init ();
|
||||
key_init ();
|
||||
idle_init ();
|
||||
pixmaps_init ();
|
||||
|
||||
#ifdef HAVE_GTK_MAC
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(ArchiveLibDir);$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>$(DepLibs);$(ZoiteChatLib)common.lib;wbemuuid.lib;dwmapi.lib;pangoft2-1.0.lib;fontconfig.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>$(DepLibs);$(ZoiteChatLib)common.lib;wbemuuid.lib;dwmapi.lib;user32.lib;pangoft2-1.0.lib;fontconfig.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -49,6 +49,7 @@ powershell "Get-Content -Encoding UTF8 '$(ZoiteChatLib)zoitechat.rc.utf8' | Out-
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="idle.h" />
|
||||
<ClInclude Include="ascii.h" />
|
||||
<ClInclude Include="banlist.h" />
|
||||
<ClInclude Include="chanlist.h" />
|
||||
@@ -91,6 +92,7 @@ powershell "Get-Content -Encoding UTF8 '$(ZoiteChatLib)zoitechat.rc.utf8' | Out-
|
||||
<ClInclude Include="theme\theme-preferences.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="idle.c" />
|
||||
<ClCompile Include="ascii.c" />
|
||||
<ClCompile Include="banlist.c" />
|
||||
<ClCompile Include="chanlist.c" />
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="idle.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ascii.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -137,6 +140,9 @@
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="idle.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ascii.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* ZoiteChat
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include "../common/autoaway.h"
|
||||
#include "idle.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <math.h>
|
||||
#elif defined(HAVE_XSS) && defined(GDK_WINDOWING_X11)
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
#endif
|
||||
|
||||
/* Do not count focus changes, redraws, timers or incoming IRC traffic. */
|
||||
static void
|
||||
idle_event (GdkEvent *event, gpointer data)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_SCROLL:
|
||||
case GDK_MOTION_NOTIFY:
|
||||
case GDK_TOUCH_BEGIN:
|
||||
case GDK_TOUCH_UPDATE:
|
||||
autoaway_activity ();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_main_do_event (event);
|
||||
}
|
||||
|
||||
void
|
||||
idle_init (void)
|
||||
{
|
||||
autoaway_activity ();
|
||||
/* Keep GTK's normal dispatch, including detached windows and dialogs. */
|
||||
gdk_event_handler_set (idle_event, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Microseconds since desktop input, or -1 for the portable app fallback. */
|
||||
gint64
|
||||
fe_get_idle_time (void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
LASTINPUTINFO input = {0};
|
||||
DWORD elapsed;
|
||||
|
||||
input.cbSize = sizeof input;
|
||||
if (!GetLastInputInfo (&input))
|
||||
return -1;
|
||||
|
||||
/* DWORD subtraction handles the 49-day GetTickCount wrap. Some injected
|
||||
* input has a slightly newer timestamp; do not treat it as weeks idle. */
|
||||
elapsed = GetTickCount () - input.dwTime;
|
||||
if ((gint32)elapsed < 0)
|
||||
elapsed = 0;
|
||||
return (gint64)elapsed * 1000;
|
||||
#elif defined(__APPLE__)
|
||||
CFTimeInterval seconds = CGEventSourceSecondsSinceLastEventType (
|
||||
kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType);
|
||||
if (!isfinite (seconds) || seconds < 0 ||
|
||||
seconds >= (double)G_MAXINT64 / G_USEC_PER_SEC)
|
||||
return -1;
|
||||
return (gint64)(seconds * G_USEC_PER_SEC);
|
||||
#elif defined(HAVE_XSS) && defined(GDK_WINDOWING_X11)
|
||||
GdkDisplay *display = gdk_display_get_default ();
|
||||
XScreenSaverInfo info = {0};
|
||||
Display *xdisplay;
|
||||
int event_base, error_base, error;
|
||||
Status ok;
|
||||
const char *wayland = g_getenv ("WAYLAND_DISPLAY");
|
||||
|
||||
/* XWayland idle is not desktop-wide. Never pass a Wayland display to Xlib. */
|
||||
if (!display || !GDK_IS_X11_DISPLAY (display) || (wayland && *wayland))
|
||||
return -1;
|
||||
|
||||
xdisplay = gdk_x11_display_get_xdisplay (display);
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
ok = XScreenSaverQueryExtension (xdisplay, &event_base, &error_base);
|
||||
if (ok)
|
||||
ok = XScreenSaverQueryInfo (xdisplay, DefaultRootWindow (xdisplay), &info);
|
||||
error = gdk_x11_display_error_trap_pop (display);
|
||||
if (!ok || error)
|
||||
return -1;
|
||||
return (gint64)info.idle * 1000;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* ZoiteChat
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ZOITECHAT_IDLE_H
|
||||
#define ZOITECHAT_IDLE_H
|
||||
|
||||
void idle_init (void);
|
||||
|
||||
#endif
|
||||
@@ -1810,50 +1810,9 @@ menu_ctcpguiopen (void)
|
||||
editlist_gui_open (NULL, NULL, ctcp_list, buf, "ctcpreply", "ctcpreply.conf", ctcp_help);
|
||||
}
|
||||
|
||||
static char *
|
||||
menu_find_local_docs (void)
|
||||
{
|
||||
char *path;
|
||||
|
||||
#ifdef WIN32
|
||||
char *base_path;
|
||||
|
||||
base_path = g_win32_get_package_installation_directory_of_module (NULL);
|
||||
if (!base_path)
|
||||
return NULL;
|
||||
|
||||
path = g_build_filename (base_path, "share", "doc", "zoitechat", "html", "index.html", NULL);
|
||||
g_free (base_path);
|
||||
#else
|
||||
const char *appdir;
|
||||
|
||||
appdir = g_getenv ("APPDIR");
|
||||
if (appdir && *appdir)
|
||||
path = g_build_filename (appdir, "usr", "share", "doc", "zoitechat", "html", "index.html", NULL);
|
||||
else
|
||||
path = g_build_filename (ZOITECHAT_DOCDIR, "index.html", NULL);
|
||||
#endif
|
||||
|
||||
if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
|
||||
return path;
|
||||
|
||||
g_free (path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
menu_docs (GtkWidget *wid, gpointer none)
|
||||
{
|
||||
char *path;
|
||||
|
||||
path = menu_find_local_docs ();
|
||||
if (path)
|
||||
{
|
||||
fe_open_url (path);
|
||||
g_free (path);
|
||||
return;
|
||||
}
|
||||
|
||||
fe_open_url ("https://docs.zoitechat.org/en/latest/");
|
||||
}
|
||||
|
||||
|
||||
+22
-1
@@ -25,6 +25,7 @@ zoitechat_gtk_sources = [
|
||||
'gtkutil.c',
|
||||
'icon-resolver.c',
|
||||
'ignoregui.c',
|
||||
'idle.c',
|
||||
'inline-image.c',
|
||||
'joind.c',
|
||||
'menu.c',
|
||||
@@ -45,6 +46,7 @@ zoitechat_gtk_sources = [
|
||||
]
|
||||
|
||||
zoitechat_gtk_cflags = []
|
||||
idle_deps = []
|
||||
|
||||
zoitechat_gtk_deps = [
|
||||
zoitechat_common_dep,
|
||||
@@ -93,9 +95,17 @@ if host_machine.system() != 'windows'
|
||||
zoitechat_gtk_deps += gdk_x11_dep
|
||||
endif
|
||||
|
||||
xss_dep = dependency('xscrnsaver', required: false)
|
||||
if gdk_x11_dep.found() and xss_dep.found()
|
||||
zoitechat_gtk_deps += xss_dep
|
||||
idle_deps += [gdk_x11_dep, xss_dep]
|
||||
zoitechat_gtk_cflags += '-DHAVE_XSS'
|
||||
endif
|
||||
|
||||
x11_dep = dependency('x11', required: false)
|
||||
if x11_dep.found()
|
||||
zoitechat_gtk_deps += x11_dep
|
||||
idle_deps += x11_dep
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -105,13 +115,16 @@ zoitechat_gtk_objcflags = []
|
||||
if host_machine.system() == 'windows'
|
||||
zoitechat_gtk_sources += 'notifications/notification-windows.c'
|
||||
zoitechat_gtk_deps += cc.find_library('dwmapi', required: true)
|
||||
idle_deps += cc.find_library('user32', required: true)
|
||||
zoitechat_gtk_deps += idle_deps
|
||||
zoitechat_theme_deps += cc.find_library('dwmapi', required: true)
|
||||
|
||||
elif host_machine.system() == 'darwin'
|
||||
add_languages('objc', required: true)
|
||||
zoitechat_gtk_sources += 'macos-shortcuts.c'
|
||||
zoitechat_gtk_sources += 'notifications/notification-osx.m'
|
||||
zoitechat_gtk_deps += dependency('appleframeworks', modules: ['Cocoa', 'UserNotifications'])
|
||||
zoitechat_gtk_deps += dependency('appleframeworks', modules: ['Cocoa', 'UserNotifications', 'CoreGraphics'])
|
||||
idle_deps += dependency('appleframeworks', modules: ['CoreGraphics'])
|
||||
zoitechat_gtk_objcflags += '-fobjc-arc'
|
||||
else
|
||||
zoitechat_gtk_sources += 'notifications/notification-freedesktop.c'
|
||||
@@ -302,3 +315,11 @@ xtext_tests = executable('xtext_tests',
|
||||
dependencies: [gtk_dep],
|
||||
)
|
||||
test('XText Tests', xtext_tests, protocol: 'tap', timeout: 120)
|
||||
|
||||
idle_tests = executable('idle_tests',
|
||||
'tests/test-idle.c',
|
||||
include_directories: [config_h_include],
|
||||
dependencies: [gtk_dep] + idle_deps,
|
||||
c_args: zoitechat_gtk_cflags,
|
||||
)
|
||||
test('Idle Backend Tests', idle_tests, protocol: 'tap', timeout: 30)
|
||||
|
||||
@@ -558,6 +558,10 @@ static const setting general_settings[] =
|
||||
{ST_ENTRY, N_("Away:"), P_OFFSETNL(hex_away_reason), 0, 0, sizeof prefs.hex_away_reason},
|
||||
|
||||
{ST_HEADER, N_("Away"),0,0,0},
|
||||
{ST_NUMBER, N_("Autoaway after:"), P_OFFINTNL(hex_away_auto_timeout), N_("Set to 0 to disable automatic away."), (const char **)N_("minutes (0 = off)."), 1440},
|
||||
{ST_ENTRY, N_("Autoaway message:"), P_OFFSETNL(hex_away_auto_reason), 0, 0, sizeof prefs.hex_away_auto_reason},
|
||||
{ST_TOGGLE, N_("Use desktop activity when available"), P_OFFINTNL(hex_away_auto_system), N_("Use desktop input on Windows, macOS and X11. Otherwise, use keyboard and mouse activity in ZoiteChat."), 0, 0},
|
||||
{ST_LABEL, N_("On Wayland, autoaway uses activity in ZoiteChat.\nOnly automatically set away states are cleared when activity resumes.")},
|
||||
{ST_TOGGLE, N_("Show away once"), P_OFFINTNL(hex_away_show_once), N_("Show identical away messages only once."), 0, 0},
|
||||
{ST_TOGGLE, N_("Automatically unmark away"), P_OFFINTNL(hex_away_auto_unmark), N_("Unmark yourself as away before sending messages."), 0, 0},
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/* ZoiteChat
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "../idle.h"
|
||||
|
||||
static int activity_count, dispatch_count;
|
||||
static void test_gtk_dispatch (GdkEvent *event);
|
||||
|
||||
void
|
||||
autoaway_activity (void)
|
||||
{
|
||||
activity_count++;
|
||||
}
|
||||
|
||||
/* Exercise the real handler without delivering synthetic input to a widget. */
|
||||
#define gtk_main_do_event test_gtk_dispatch
|
||||
#include "../idle.c"
|
||||
#undef gtk_main_do_event
|
||||
|
||||
static void
|
||||
test_gtk_dispatch (GdkEvent *event)
|
||||
{
|
||||
dispatch_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
test_user_input_and_dispatch (void)
|
||||
{
|
||||
GdkEvent event = {0};
|
||||
GdkEventType input[] = {GDK_KEY_PRESS, GDK_BUTTON_PRESS, GDK_SCROLL,
|
||||
GDK_MOTION_NOTIFY, GDK_TOUCH_BEGIN, GDK_TOUCH_UPDATE};
|
||||
GdkEventType other[] = {GDK_FOCUS_CHANGE, GDK_CONFIGURE, GDK_WINDOW_STATE,
|
||||
GDK_PROPERTY_NOTIFY, GDK_VISIBILITY_NOTIFY};
|
||||
unsigned int i;
|
||||
|
||||
activity_count = dispatch_count = 0;
|
||||
for (i = 0; i < G_N_ELEMENTS (input); i++)
|
||||
{
|
||||
event.type = input[i];
|
||||
idle_event (&event, NULL);
|
||||
}
|
||||
g_assert_cmpint (activity_count, ==, G_N_ELEMENTS (input));
|
||||
for (i = 0; i < G_N_ELEMENTS (other); i++)
|
||||
{
|
||||
event.type = other[i];
|
||||
idle_event (&event, NULL);
|
||||
}
|
||||
g_assert_cmpint (activity_count, ==, G_N_ELEMENTS (input));
|
||||
g_assert_cmpint (dispatch_count, ==, G_N_ELEMENTS (input) + G_N_ELEMENTS (other));
|
||||
}
|
||||
|
||||
static void
|
||||
test_native_idle (void)
|
||||
{
|
||||
gint64 idle = fe_get_idle_time ();
|
||||
g_assert_cmpint (idle, >=, -1);
|
||||
#if defined(HAVE_XSS) && defined(GDK_WINDOWING_X11)
|
||||
if (gdk_display_get_default () && GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
|
||||
{
|
||||
/* XWayland must use the app fallback, even if XSS is compiled in. */
|
||||
char *saved = g_strdup (g_getenv ("WAYLAND_DISPLAY"));
|
||||
g_unsetenv ("WAYLAND_DISPLAY");
|
||||
g_assert_cmpint (fe_get_idle_time (), >=, 0);
|
||||
g_setenv ("WAYLAND_DISPLAY", "wayland-test", TRUE);
|
||||
g_assert_cmpint (fe_get_idle_time (), ==, -1);
|
||||
if (saved)
|
||||
g_setenv ("WAYLAND_DISPLAY", saved, TRUE);
|
||||
else
|
||||
g_unsetenv ("WAYLAND_DISPLAY");
|
||||
g_free (saved);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
gtk_init_check (&argc, &argv);
|
||||
g_test_add_func ("/idle/user-input-and-dispatch", test_user_input_and_dispatch);
|
||||
g_test_add_func ("/idle/native-backend", test_native_idle);
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -48,6 +48,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
gint64
|
||||
fe_get_idle_time (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int done = FALSE;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{EE388A27-6992-43C0-BA9B-61D8968D42E3}</ProjectGuid>
|
||||
<SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="zoitechat.props" />
|
||||
<PropertyGroup>
|
||||
<TargetName>autoaway-tests</TargetName>
|
||||
<OutDir>$(ZoiteChatBuild)\$(ZoiteChatPlatform)\tests\</OutDir>
|
||||
<IntDir>$(ZoiteChatObj)autoaway-tests\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_CONSOLE;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ZoiteChatLib);$(DepsRoot)\include;$(OpenSslInclude);$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>gio-2.0.lib;gobject-2.0.lib;glib-2.0.lib;$(IntlLib);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\common\autoaway.c" />
|
||||
<ClCompile Include="..\src\common\tests\test-autoaway.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
Reference in New Issue
Block a user