11 Commits

Author SHA1 Message Date
30f8f84f6b fix: source AppRun hook scripts so GTK runtime setup actually runs in AppImage 2026-03-13 01:03:08 -06:00
4cebe2ac8b fix: expose shared tray label updater on Windows; keep non-win tray bits guarded 2026-03-12 19:34:17 -06:00
44431d2c10 fix: unnest tray cb guards so Windows callbacks actually get defined 2026-03-12 19:13:26 -06:00
14a1ac0dfb fix: keep tray hide/restore label synced to real window state 2026-03-12 18:51:07 -06:00
52af960175 fix: refresh AppIndicator tray label on menu map/open 2026-03-12 18:31:20 -06:00
deepend-tildeclub
3baa5d92f4 Merge pull request #105 from ZoiteChat/plugins-retention
fix: persist manual addons by copying em into user addon dir
2026-03-12 16:54:27 -06:00
deepend-tildeclub
6d1e7da475 Merge pull request #104 from ZoiteChat/bug-fixes-pre3-prep
Merge color-changer: import colors.conf, fix userlist/GTK3 tabs, embed SVG icon, clean GTK/OpenSSL warnings.
2026-03-12 15:22:04 -06:00
deepend-tildeclub
f676aa56e6 Merge pull request #103 from ZoiteChat/theme-features-fixes
Theme update
2026-03-09 10:50:12 -06:00
deepend-tildeclub
5e86f363ed Merge pull request #100 from ZoiteChat/theme-module
Theme module
2026-03-02 19:59:43 -07:00
deepend-tildeclub
0523b0639b Merge pull request #99 from ZoiteChat/consistent-icons
icon-resolver unifies gtk icons; win32/ci now ships real hicolor theme
2026-03-01 14:55:32 -07:00
deepend-tildeclub
b3f692f00c Update server addresses for Zoite 2026-02-28 23:02:02 -07:00
5 changed files with 118 additions and 17 deletions

View File

@@ -36,6 +36,7 @@ jobs:
libgtk-3-bin libglib2.0-bin shared-mime-info gsettings-desktop-schemas \ 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 \ 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 \ perl python3 python3-minimal python3-dev python3-cffi mono-devel desktop-file-utils \
fonts-noto-color-emoji \
patchelf file curl patchelf file curl
- name: Configure - name: Configure
@@ -104,6 +105,16 @@ jobs:
cp -a /usr/lib/x86_64-linux-gnu/libpython3*.so* 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 fi
if [ -d "/usr/share/gtk-3.0/emoji" ]; then
install -d AppDir/usr/share/gtk-3.0
cp -a /usr/share/gtk-3.0/emoji AppDir/usr/share/gtk-3.0/
fi
if [ -f "/usr/share/fonts/truetype/noto/NotoColorEmoji.ttf" ]; then
install -d AppDir/usr/share/fonts/truetype/noto
cp -a /usr/share/fonts/truetype/noto/NotoColorEmoji.ttf AppDir/usr/share/fonts/truetype/noto/
fi
- name: Verify bundled plugins - name: Verify bundled plugins
run: | run: |
set -eux set -eux
@@ -144,6 +155,16 @@ jobs:
export PATH="${PATH:-/usr/bin:/bin}:$APPDIR/usr/bin" export PATH="${PATH:-/usr/bin:/bin}:$APPDIR/usr/bin"
export LD_LIBRARY_PATH="$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH:-}" 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}" export XDG_DATA_DIRS="$APPDIR/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
export GTK_EXE_PREFIX="$APPDIR/usr"
export GTK_DATA_PREFIX="$APPDIR/usr"
if [ -d "$APPDIR/etc/fonts" ]; then
export FONTCONFIG_SYSROOT="$APPDIR"
export FONTCONFIG_PATH="$APPDIR/etc/fonts${FONTCONFIG_PATH:+:$FONTCONFIG_PATH}"
if [ -f "$APPDIR/etc/fonts/fonts.conf" ]; then
export FONTCONFIG_FILE="$APPDIR/etc/fonts/fonts.conf"
fi
fi
if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins" ]; then if [ -d "$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins" ]; then
export ZOITECHAT_LIBDIR="$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins" export ZOITECHAT_LIBDIR="$APPDIR/usr/lib/x86_64-linux-gnu/zoitechat/plugins"
@@ -192,6 +213,16 @@ jobs:
fi fi
fi fi
for hook_dir in "$APPDIR/apprun-hooks" "$APPDIR/usr/apprun-hooks"; do
if [ -d "$hook_dir" ]; then
for hook in "$hook_dir"/*.sh; do
if [ -f "$hook" ]; then
. "$hook"
fi
done
fi
done
exec "$APPDIR/usr/bin/zoitechat" "$@" exec "$APPDIR/usr/bin/zoitechat" "$@"
EOF EOF
chmod +x AppRun chmod +x AppRun

View File

@@ -338,8 +338,8 @@ static const struct defaultserver def[] =
{"Zoite", 0, 0, 0, LOGIN_SASL, 0, TRUE}, {"Zoite", 0, 0, 0, LOGIN_SASL, 0, TRUE},
{0, "irc.zoite.net"}, {0, "irc.zoite.net"},
{0, "penumbra.newnet.net"}, {0, "penumbra.zoite.net"},
{0, "hedy.newnet.net"}, {0, "hedy.zoite.net"},
{0,0} {0,0}
}; };

View File

@@ -1144,6 +1144,12 @@ fe_gui_info (session *sess, int info_type)
return 2; /* hidden (iconified or systray) */ return 2; /* hidden (iconified or systray) */
} }
{
GdkWindow *gdk_win = gtk_widget_get_window (GTK_WIDGET (sess->gui->window));
if (gdk_win && (gdk_window_get_state (gdk_win) & GDK_WINDOW_STATE_ICONIFIED))
return 2;
}
if (gtk_window_is_active (GTK_WINDOW (sess->gui->window))) if (gtk_window_is_active (GTK_WINDOW (sess->gui->window)))
{ {
return 1; /* active/focused */ return 1; /* active/focused */

View File

@@ -122,6 +122,9 @@ static void tray_init (void);
static void tray_set_icon_state (TrayIcon icon, TrayIconState state); static void tray_set_icon_state (TrayIcon icon, TrayIconState state);
static void tray_menu_restore_cb (GtkWidget *item, gpointer userdata); static void tray_menu_restore_cb (GtkWidget *item, gpointer userdata);
static void tray_menu_notify_cb (GObject *tray, GParamSpec *pspec, gpointer user_data); static void tray_menu_notify_cb (GObject *tray, GParamSpec *pspec, gpointer user_data);
static void tray_update_toggle_item_label (void);
static gboolean tray_window_state_cb (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata);
static void tray_window_visibility_cb (GtkWidget *widget, gpointer userdata);
#if HAVE_APPINDICATOR_BACKEND #if HAVE_APPINDICATOR_BACKEND
static void tray_menu_show_cb (GtkWidget *menu, gpointer userdata) G_GNUC_UNUSED; static void tray_menu_show_cb (GtkWidget *menu, gpointer userdata) G_GNUC_UNUSED;
#endif #endif
@@ -165,6 +168,7 @@ static int tray_pub_count = 0;
static int tray_hilight_count = 0; static int tray_hilight_count = 0;
static int tray_file_count = 0; static int tray_file_count = 0;
static int tray_restore_timer = 0; static int tray_restore_timer = 0;
static GtkWidget *tray_toggle_item = NULL;
#if HAVE_APPINDICATOR_BACKEND #if HAVE_APPINDICATOR_BACKEND
static TrayCustomIcon static TrayCustomIcon
@@ -424,6 +428,8 @@ tray_app_indicator_init (void)
tray_menu = gtk_menu_new (); tray_menu = gtk_menu_new ();
g_signal_connect (G_OBJECT (tray_menu), "show", g_signal_connect (G_OBJECT (tray_menu), "show",
G_CALLBACK (tray_menu_show_cb), NULL); G_CALLBACK (tray_menu_show_cb), NULL);
g_signal_connect (G_OBJECT (tray_menu), "map",
G_CALLBACK (tray_menu_show_cb), NULL);
app_indicator_set_menu (tray_indicator, GTK_MENU (tray_menu)); app_indicator_set_menu (tray_indicator, GTK_MENU (tray_menu));
app_indicator_set_status (tray_indicator, APP_INDICATOR_STATUS_ACTIVE); app_indicator_set_status (tray_indicator, APP_INDICATOR_STATUS_ACTIVE);
@@ -581,11 +587,21 @@ static WinStatus
tray_get_window_status (void) tray_get_window_status (void)
{ {
GtkWindow *win; GtkWindow *win;
GtkWidget *widget;
GdkWindow *gdk_win;
const char *st; const char *st;
win = GTK_WINDOW (zoitechat_get_info (ph, "gtkwin_ptr")); win = GTK_WINDOW (zoitechat_get_info (ph, "gtkwin_ptr"));
if (win && !gtk_widget_get_visible (GTK_WIDGET (win))) if (win)
return WS_HIDDEN; {
widget = GTK_WIDGET (win);
if (!gtk_widget_get_visible (widget))
return WS_HIDDEN;
gdk_win = gtk_widget_get_window (widget);
if (gdk_win && (gdk_window_get_state (gdk_win) & GDK_WINDOW_STATE_ICONIFIED))
return WS_HIDDEN;
}
st = zoitechat_get_info (ph, "win_status"); st = zoitechat_get_info (ph, "win_status");
@@ -878,6 +894,8 @@ tray_toggle_visibility (gboolean force_hide)
gtk_window_present (win); gtk_window_present (win);
} }
tray_update_toggle_item_label ();
return TRUE; return TRUE;
} }
@@ -1071,10 +1089,8 @@ tray_menu_populate (GtkWidget *menu)
/* ph may have an invalid context now */ /* ph may have an invalid context now */
zoitechat_set_context (ph, zoitechat_find_context (ph, NULL, NULL)); zoitechat_set_context (ph, zoitechat_find_context (ph, NULL, NULL));
if (tray_get_window_status () == WS_HIDDEN) tray_toggle_item = tray_make_item (menu, _("_Hide Window"), tray_menu_restore_cb, NULL);
tray_make_item (menu, _("_Restore Window"), tray_menu_restore_cb, NULL); tray_update_toggle_item_label ();
else
tray_make_item (menu, _("_Hide Window"), tray_menu_restore_cb, NULL);
tray_make_item (menu, NULL, tray_menu_quit_cb, NULL); tray_make_item (menu, NULL, tray_menu_quit_cb, NULL);
#ifndef WIN32 /* submenus are buggy on win32 */ #ifndef WIN32 /* submenus are buggy on win32 */
@@ -1116,8 +1132,28 @@ tray_menu_clear (GtkWidget *menu)
for (iter = children; iter; iter = iter->next) for (iter = children; iter; iter = iter->next)
gtk_widget_destroy (GTK_WIDGET (iter->data)); gtk_widget_destroy (GTK_WIDGET (iter->data));
g_list_free (children); g_list_free (children);
tray_toggle_item = NULL;
}
#endif
static void
tray_update_toggle_item_label (void)
{
const char *label;
if (!tray_toggle_item)
return;
if (tray_get_window_status () == WS_HIDDEN)
label = _("_Restore Window");
else
label = _("_Hide Window");
gtk_menu_item_set_label (GTK_MENU_ITEM (tray_toggle_item), label);
gtk_menu_item_set_use_underline (GTK_MENU_ITEM (tray_toggle_item), TRUE);
} }
#if !defined(WIN32)
static void G_GNUC_UNUSED static void G_GNUC_UNUSED
tray_menu_show_cb (GtkWidget *menu, gpointer userdata) tray_menu_show_cb (GtkWidget *menu, gpointer userdata)
{ {
@@ -1128,6 +1164,27 @@ tray_menu_show_cb (GtkWidget *menu, gpointer userdata)
} }
#endif #endif
static gboolean
tray_window_state_cb (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
{
(void)widget;
(void)event;
(void)userdata;
tray_update_toggle_item_label ();
return FALSE;
}
static void
tray_window_visibility_cb (GtkWidget *widget, gpointer userdata)
{
(void)widget;
(void)userdata;
tray_update_toggle_item_label ();
}
#if !HAVE_APPINDICATOR_BACKEND #if !HAVE_APPINDICATOR_BACKEND
static void static void
tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata) tray_menu_cb (GtkWidget *widget, guint button, guint time, gpointer userdata)
@@ -1369,6 +1426,19 @@ tray_plugin_init (zoitechat_plugin *plugin_handle, char **plugin_name,
zoitechat_hook_print (ph, "Focus Window", -1, tray_focus_cb, NULL); zoitechat_hook_print (ph, "Focus Window", -1, tray_focus_cb, NULL);
GtkWindow *window = GTK_WINDOW(zoitechat_get_info (ph, "gtkwin_ptr")); GtkWindow *window = GTK_WINDOW(zoitechat_get_info (ph, "gtkwin_ptr"));
GtkWidget *window_widget;
if (window)
{
window_widget = GTK_WIDGET (window);
g_signal_connect (G_OBJECT (window_widget), "window-state-event",
G_CALLBACK (tray_window_state_cb), NULL);
g_signal_connect (G_OBJECT (window_widget), "show",
G_CALLBACK (tray_window_visibility_cb), NULL);
g_signal_connect (G_OBJECT (window_widget), "hide",
G_CALLBACK (tray_window_visibility_cb), NULL);
}
if (prefs.hex_gui_tray && gtkutil_tray_icon_supported (window)) if (prefs.hex_gui_tray && gtkutil_tray_icon_supported (window))
tray_init (); tray_init ();

View File

@@ -198,8 +198,6 @@ plugingui_load_cb (session *sess, char *file)
char *addons_dir; char *addons_dir;
char *basename; char *basename;
char *addons_target; char *addons_target;
char *canonical_addons;
char *canonical_file;
gboolean file_in_addons; gboolean file_in_addons;
target_sess = is_session (sess) ? sess : current_sess; target_sess = is_session (sess) ? sess : current_sess;
@@ -211,11 +209,9 @@ plugingui_load_cb (session *sess, char *file)
load_target = g_strdup (file); load_target = g_strdup (file);
addons_dir = g_build_filename (get_xdir (), "addons", NULL); addons_dir = g_build_filename (get_xdir (), "addons", NULL);
canonical_addons = g_canonicalize_filename (addons_dir, NULL); file_in_addons = g_str_has_prefix (file, addons_dir)
canonical_file = g_canonicalize_filename (file, NULL); && (file[strlen (addons_dir)] == G_DIR_SEPARATOR
file_in_addons = g_str_has_prefix (canonical_file, canonical_addons) || file[strlen (addons_dir)] == '\0');
&& (canonical_file[strlen (canonical_addons)] == G_DIR_SEPARATOR
|| canonical_file[strlen (canonical_addons)] == '\0');
if (!file_in_addons) if (!file_in_addons)
{ {
@@ -240,8 +236,6 @@ plugingui_load_cb (session *sess, char *file)
} }
} }
g_free (canonical_addons);
g_free (canonical_file);
g_free (addons_dir); g_free (addons_dir);
#ifdef WIN32 #ifdef WIN32