21 Commits

Author SHA1 Message Date
deepend-tildeclub
3903d7b9e5 Change official documentation link in README
Updated the link for the official documentation from zoitechat.zoite.net to zoitechat.org.
2026-03-30 17:16:01 -06:00
ec4d698021 Bump to 2.18.0~pre6 2026-03-30 13:04:00 -06:00
deepend-tildeclub
da06c71389 Merge pull request #177 from ZoiteChat/client-cert-importer
Add client SSL cert import action
2026-03-30 12:30:26 -06:00
0f508bf438 Sanitize OpenSSL env for client cert actions 2026-03-30 11:57:58 -06:00
97dd7c5d57 Add client SSL cert import action 2026-03-30 11:46:08 -06:00
deepend-tildeclub
78219bf9e1 Merge pull request #176 from ZoiteChat/fix-font-consistency
Apply pref font to topic/tree/userlist/input
2026-03-30 11:07:59 -06:00
deepend-tildeclub
1c30cbfab1 Merge pull request #175 from ZoiteChat/fix-menu-hover-highlight
Fix fallback GTK menu highlight states
2026-03-30 11:07:43 -06:00
ac33dc5250 Apply pref font to topic/tree/userlist/input 2026-03-30 10:33:43 -06:00
8de5db18d6 Fix fallback GTK menu highlight states 2026-03-30 10:29:05 -06:00
deepend-tildeclub
913aa49df4 Merge pull request #169 from ZoiteChat/tab-close-button
UI: add close button to tabs
2026-03-30 09:44:01 -06:00
5e4633ee53 UI: Adjust channel tab height 2026-03-30 09:31:25 -06:00
deepend-tildeclub
30e573d87a Merge pull request #174 from ZoiteChat/mutli-line-topic-fix
Wrap topic bar in scroller, bound height
2026-03-30 09:20:37 -06:00
9e91d60bb1 Wrap topic bar in scroller, bound height 2026-03-29 17:48:56 -06:00
deepend-tildeclub
069652a5f1 Merge pull request #172 from sney/sysinfo-disable-disk
sysinfo: disable disk info
2026-03-29 17:38:55 -06:00
Jesse Rhodes
ab1e25bfb1 sysinfo: Disable storage output by default; it is always wrong. 2026-03-29 11:27:11 -04:00
Jesse Rhodes
862aa0ede5 sysinfo: Correct usage text DISK->STORAGE. 2026-03-29 11:25:44 -04:00
f75c27c843 Make tab close button smaller + flat 2026-03-28 22:20:21 -06:00
687b5fb40d UI: add close button to tabs 2026-03-28 11:33:03 -06:00
bb36651548 UI: Adjust headerbar icon size/padding. 2026-03-28 09:48:51 -06:00
65a2702294 CI: small installer logo fix. 2026-03-28 01:50:04 -06:00
94bcb57118 CI: installer logos 2026-03-28 01:43:39 -06:00
16 changed files with 401 additions and 36 deletions

View File

@@ -1,6 +1,30 @@
ZoiteChat ChangeLog
=================
2.18.0~pre6 (2026-03-30)
- Applied app theme CSS to the menubar consistently across the app.
- Restored horizontal separator lines in menus.
- Improved Windows installer VC++ redistributable handling by failing loudly when missing and using the official Microsoft download endpoint.
- Fixed Windows locale path resolution in both GTK and text frontends.
- Fixed duplicate dialog buttons persisting in the UI.
- Fixed GTK auto-replace cursor snapback.
- Restored hiding of formatting control bytes so only formatted output is shown.
- Added one-click client SSL certificate tools, including generation with P-256 certificates.
- Added client SSL certificate import support in the network editor.
- Added 99-color support.
- Fixed xtext link hit-testing coordinates.
- Fixed short-palette fallback clobbering tab colors.
- Lazy-loads Preferences pages on first open for faster dialog startup.
- Removed unused UI icons.
- Added a None option for resetting the GTK3 theme back to system/default behavior.
- Added channel-only mode to Ctrl+F search.
- Disabled disk info in sysinfo.
- Wrapped the topic bar in a scroller with bounded height.
- Added close buttons to tabs.
- Fixed fallback GTK menu highlight states.
- Applied configured font preferences to the topic bar, channel tree, user list, and input box.
2.18.0~pre5 (2026-03-22)
------------------------
- Overhauled preferences/config saving: fully staged and transactional, debounced

View File

@@ -29,6 +29,46 @@
<id>zoitechat.desktop</id>
</provides>
<releases>
<release date="2026-03-30" version="2.18.0~pre6">
<description>
<p>GTK theme and UI:</p>
<ul>
<li>Applied app theme CSS to the menubar consistently across the app.</li>
<li>Restored horizontal separator lines in menus.</li>
<li>Fixed duplicate dialog buttons persisting in the UI.</li>
<li>Fixed GTK auto-replace cursor snapback.</li>
<li>Restored hiding of formatting control bytes so only formatted output is shown.</li>
<li>Fixed xtext link hit-testing coordinates.</li>
<li>Fixed short-palette fallback clobbering tab colors.</li>
<li>Added a None option for resetting the GTK3 theme back to system/default behavior.</li>
<li>Wrapped the topic bar in a scroller with bounded height.</li>
<li>Fixed fallback GTK menu highlight states.</li>
<li>Applied configured font preferences to the topic bar, channel tree, user list, and input box.</li>
<li>Removed unused UI icons.</li>
<li>Added close buttons to tabs.</li>
</ul>
<p>Preferences and search:</p>
<ul>
<li>Lazy-loads Preferences pages on first open for faster dialog startup.</li>
<li>Added channel-only mode to Ctrl+F search.</li>
</ul>
<p>Security and certificates:</p>
<ul>
<li>Added one-click client SSL certificate tools, including generation with P-256 certificates.</li>
<li>Added client SSL certificate import support in the network editor.</li>
</ul>
<p>Windows and packaging:</p>
<ul>
<li>Improved Windows installer VC++ redistributable handling by failing loudly when missing and using the official Microsoft download endpoint.</li>
<li>Fixed Windows locale path resolution in both GTK and text frontends.</li>
</ul>
<p>Other changes:</p>
<ul>
<li>Added 99-color support.</li>
<li>Disabled disk info in sysinfo.</li>
</ul>
</description>
</release>
<release date="2026-03-22" version="2.18.0~pre5">
<description>
<p>Preferences and config saving:</p>

View File

@@ -1,5 +1,5 @@
project('zoitechat', 'c',
version: '2.18.0~pre5',
version: '2.18.0~pre6',
meson_version: '>= 0.55.0',
default_options: [
'c_std=c17',

View File

@@ -19,7 +19,7 @@ else:
if not hasattr(sys, 'argv'):
sys.argv = ['<zoitechat>']
VERSION = b'2.18.0~pre5'
VERSION = b'2.18.0~pre6'
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)

View File

@@ -41,7 +41,7 @@ static zoitechat_plugin *ph;
static char name[] = "Sysinfo";
static char desc[] = "Display info about your hardware and OS";
static char version[] = "1.0";
static char sysinfo_help[] = "SysInfo Usage:\n /SYSINFO [-e|-o] [CLIENT|UI|OS|CPU|RAM|DISK|GPU|CHIPSET|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n /SYSINFO SET <variable>\n";
static char sysinfo_help[] = "SysInfo Usage:\n /SYSINFO [-e|-o] [CLIENT|UI|OS|CPU|RAM|STORAGE|GPU|CHIPSET|SOUND|ETHERNET|UPTIME], print various details about your system or print a summary without arguments\n /SYSINFO SET <variable>\n";
typedef struct
{
@@ -68,7 +68,7 @@ static hwinfo hwinfos[] = {
{"os", "OS", sysinfo_backend_get_os},
{"cpu", "CPU", sysinfo_backend_get_cpu},
{"memory", "Memory", sysinfo_backend_get_memory},
{"storage", "Storage", sysinfo_backend_get_disk},
{"storage", "Storage", sysinfo_backend_get_disk, TRUE},
{"gpu", "GPU", sysinfo_backend_get_gpu},
{"chipset", "CHIPSET", sysinfo_backend_get_chipset, TRUE},
{"sound", "Sound", sysinfo_backend_get_sound, TRUE},

View File

@@ -8,7 +8,7 @@
[![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-)
[![View Official Documentation](https://img.shields.io/badge/View_Official_Documentation-526CFE?style=for-the-badge&logo=MaterialForMkDocs&logoColor=white)](https://docs.zoitechat.zoite.net)
[![View Official Documentation](https://img.shields.io/badge/View_Official_Documentation-526CFE?style=for-the-badge&logo=MaterialForMkDocs&logoColor=white)](https://docs.zoitechat.org)
</div>

View File

@@ -27,8 +27,6 @@ typedef struct
GtkWidget *b2; /* button2 */
} tabview;
#define ICON_CHANVIEW_CLOSE "gtk-close"
static void chanview_populate (chanview *cv);
/* ignore "toggled" signal? */
@@ -334,12 +332,6 @@ tab_scroll_cb (GtkWidget *widget, GdkEventScroll *event, gpointer cv)
return FALSE;
}
static void
cv_tabs_xclick_cb (GtkWidget *button, chanview *cv)
{
cv->cb_xbutton (cv, cv->focused, cv->focused->tag, cv->focused->userdata);
}
/* make a Scroll (arrow) button */
static GtkWidget *
@@ -384,7 +376,6 @@ cv_tabs_init (chanview *cv)
GtkWidget *box, *hbox = NULL;
GtkWidget *viewport;
GtkWidget *outer;
GtkWidget *button;
if (cv->vertical)
{
@@ -451,11 +442,6 @@ cv_tabs_init (chanview *cv)
gtk_box_pack_start (GTK_BOX (outer), ((tabview *)cv)->b1, 0, 0, 0);
}
button = gtkutil_button (outer, ICON_CHANVIEW_CLOSE, NULL, cv_tabs_xclick_cb,
cv, 0);
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
gtk_widget_set_can_focus (button, FALSE);
gtk_container_add (GTK_CONTAINER (cv->box), outer);
}
@@ -659,20 +645,129 @@ tab_toggled_cb (GtkToggleButton *tab, chan *ch)
static gboolean
tab_click_cb (GtkWidget *wid, GdkEventButton *event, chan *ch)
{
GtkWidget *close_button;
gint close_x;
gint close_y;
GtkAllocation close_alloc;
if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
{
close_button = g_object_get_data (G_OBJECT (wid), "tab-close-button");
if (close_button &&
gtk_widget_translate_coordinates (close_button, wid, 0, 0, &close_x, &close_y))
{
gtk_widget_get_allocation (close_button, &close_alloc);
if (event->x >= close_x && event->x < close_x + close_alloc.width &&
event->y >= close_y && event->y < close_y + close_alloc.height)
{
ch->cv->cb_xbutton (ch->cv, ch, ch->tag, ch->userdata);
return TRUE;
}
}
}
return ch->cv->cb_contextmenu (ch->cv, ch, ch->tag, ch->userdata, event);
}
static gboolean
tab_close_motion_cb (GtkWidget *wid, GdkEventMotion *event, chan *ch)
{
GtkWidget *close_button;
gint close_x;
gint close_y;
GtkAllocation close_alloc;
gboolean hover = FALSE;
close_button = g_object_get_data (G_OBJECT (wid), "tab-close-button");
if (close_button &&
gtk_widget_translate_coordinates (close_button, wid, 0, 0, &close_x, &close_y))
{
gtk_widget_get_allocation (close_button, &close_alloc);
hover = event->x >= close_x && event->x < close_x + close_alloc.width &&
event->y >= close_y && event->y < close_y + close_alloc.height;
}
if (hover)
{
GdkCursor *cursor;
gtk_widget_set_state_flags (close_button, GTK_STATE_FLAG_PRELIGHT, TRUE);
if (gtk_widget_get_window (wid))
{
cursor = gdk_cursor_new_for_display (gtk_widget_get_display (wid), GDK_HAND2);
gdk_window_set_cursor (gtk_widget_get_window (wid), cursor);
g_object_unref (cursor);
}
}
else
{
gtk_widget_unset_state_flags (close_button, GTK_STATE_FLAG_PRELIGHT);
if (gtk_widget_get_window (wid))
gdk_window_set_cursor (gtk_widget_get_window (wid), NULL);
}
return FALSE;
}
static gboolean
tab_close_leave_cb (GtkWidget *wid, GdkEventCrossing *event, chan *ch)
{
GtkWidget *close_button;
close_button = g_object_get_data (G_OBJECT (wid), "tab-close-button");
if (close_button)
gtk_widget_unset_state_flags (close_button, GTK_STATE_FLAG_PRELIGHT);
if (gtk_widget_get_window (wid))
gdk_window_set_cursor (gtk_widget_get_window (wid), NULL);
return FALSE;
}
static GtkWidget *
tab_get_label (GtkWidget *tab)
{
GtkWidget *label;
label = g_object_get_data (G_OBJECT (tab), "tab-label");
if (label)
return label;
return gtk_bin_get_child (GTK_BIN (tab));
}
static void *
cv_tabs_add (chanview *cv, chan *ch, char *name, GtkTreeIter *parent)
{
GtkWidget *but;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *close_button;
GtkWidget *close_icon;
but = gtk_toggle_button_new_with_label (name);
but = gtk_toggle_button_new ();
gtk_widget_set_name (but, "zoitechat-tab");
gtk_widget_set_size_request (but, -1, 18);
gtk_widget_add_events (but, GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
label = gtk_label_new (name);
close_button = gtk_button_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (close_button), "flat");
close_icon = gtk_image_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_MENU);
gtk_image_set_pixel_size (GTK_IMAGE (close_icon), 8);
gtk_button_set_always_show_image (GTK_BUTTON (close_button), TRUE);
gtk_widget_set_can_focus (close_button, FALSE);
gtk_container_add (GTK_CONTAINER (close_button), close_icon);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (but), hbox);
g_object_set_data (G_OBJECT (but), "tab-label", label);
g_object_set_data (G_OBJECT (but), "tab-close-button", close_button);
g_object_set_data (G_OBJECT (but), "c", ch);
/* used to trap right-clicks */
g_signal_connect (G_OBJECT (but), "button-press-event",
G_CALLBACK (tab_click_cb), ch);
g_signal_connect (G_OBJECT (but), "motion-notify-event",
G_CALLBACK (tab_close_motion_cb), ch);
g_signal_connect (G_OBJECT (but), "leave-notify-event",
G_CALLBACK (tab_close_leave_cb), ch);
/* avoid prelights */
g_signal_connect (G_OBJECT (but), "enter-notify-event",
G_CALLBACK (tab_ignore_cb), NULL);
@@ -684,6 +779,7 @@ cv_tabs_add (chanview *cv, chan *ch, char *name, GtkTreeIter *parent)
g_signal_connect (G_OBJECT (but), "toggled",
G_CALLBACK (tab_toggled_cb), ch);
g_object_set_data (G_OBJECT (but), "u", ch->userdata);
gtk_widget_show_all (hbox);
tab_add_real (cv, but, ch);
@@ -892,7 +988,7 @@ cv_tabs_cleanup (chanview *cv)
static void
cv_tabs_set_color (chan *ch, PangoAttrList *list)
{
gtk_label_set_attributes (GTK_LABEL (gtk_bin_get_child (GTK_BIN (ch->impl))), list);
gtk_label_set_attributes (GTK_LABEL (tab_get_label (ch->impl)), list);
}
static void
@@ -901,16 +997,16 @@ cv_tabs_rename (chan *ch, char *name)
PangoAttrList *attr;
GtkWidget *tab = ch->impl;
attr = gtk_label_get_attributes (GTK_LABEL (gtk_bin_get_child (GTK_BIN (tab))));
attr = gtk_label_get_attributes (GTK_LABEL (tab_get_label (tab)));
if (attr)
pango_attr_list_ref (attr);
gtk_button_set_label (GTK_BUTTON (tab), name);
gtk_label_set_text (GTK_LABEL (tab_get_label (tab)), name);
gtk_widget_queue_resize (gtk_widget_get_parent(gtk_widget_get_parent(gtk_widget_get_parent(tab))));
if (attr)
{
gtk_label_set_attributes (GTK_LABEL (gtk_bin_get_child (GTK_BIN (tab))), attr);
gtk_label_set_attributes (GTK_LABEL (tab_get_label (tab)), attr);
pango_attr_list_unref (attr);
}
}

View File

@@ -2968,10 +2968,73 @@ mg_create_dialogbuttons (GtkWidget *box)
}
}
static void
mg_configure_topic_scroller (GtkWidget *scroller, GtkWidget *topic)
{
PangoContext *context;
PangoFontMetrics *metrics;
int line_height;
int min_height;
int max_height;
context = gtk_widget_get_pango_context (topic);
metrics = pango_context_get_metrics (context,
pango_context_get_font_description (context),
pango_context_get_language (context));
line_height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
pango_font_metrics_get_descent (metrics));
pango_font_metrics_unref (metrics);
if (line_height <= 0)
line_height = 16;
min_height = line_height + 8;
max_height = line_height * 4 + 8;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroller), GTK_SHADOW_NONE);
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (scroller), TRUE);
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scroller), min_height);
gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (scroller), max_height);
}
void
mg_apply_session_font_prefs (session_gui *gui)
{
const PangoFontDescription *font = NULL;
GtkWidget *topic_scroller;
if (!gui)
return;
if (input_style)
font = input_style->font_desc;
if (gui->topic_entry)
{
theme_manager_apply_entry_palette (gui->topic_entry, font);
topic_scroller = gtk_widget_get_parent (gui->topic_entry);
if (topic_scroller && GTK_IS_SCROLLED_WINDOW (topic_scroller))
mg_configure_topic_scroller (topic_scroller, gui->topic_entry);
}
if (gui->input_box && prefs.hex_gui_input_style)
theme_manager_apply_entry_palette (gui->input_box, font);
if (gui->chanview)
chanview_apply_theme (gui->chanview);
if (gui->user_tree)
theme_manager_apply_userlist_style (gui->user_tree,
theme_manager_get_userlist_palette_behavior (font));
}
static void
mg_create_topicbar (session *sess, GtkWidget *box)
{
GtkWidget *vbox, *hbox, *mode_hbox, *topic, *bbox;
GtkWidget *vbox, *hbox, *mode_hbox, *topic, *bbox, *topic_scroller;
session_gui *gui = sess->gui;
gui->topic_bar = vbox = mg_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
@@ -2984,12 +3047,15 @@ mg_create_topicbar (session *sess, GtkWidget *box)
sess->res->tab = NULL;
gui->topic_entry = topic = gtk_text_view_new ();
gtk_widget_set_name (topic, "zoitechat-inputbox");
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (topic), GTK_WRAP_WORD_CHAR);
gtk_widget_set_name (topic, "zoitechat-topicbox");
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (topic), GTK_WRAP_WORD);
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (topic), 4);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (topic), 4);
gtk_box_pack_start (GTK_BOX (hbox), topic, TRUE, TRUE, 0);
mg_apply_emoji_fallback_widget (topic);
topic_scroller = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (topic_scroller), topic);
theme_manager_apply_entry_palette (topic, input_style ? input_style->font_desc : NULL);
mg_configure_topic_scroller (topic_scroller, topic);
gtk_box_pack_start (GTK_BOX (hbox), topic_scroller, TRUE, TRUE, 0);
gtk_widget_add_events (topic, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
g_signal_connect (G_OBJECT (topic), "key-press-event",

View File

@@ -37,6 +37,7 @@ GtkWidget *mg_create_generic_tab (char *name, char *title, int force_toplevel, i
void mg_set_title (GtkWidget *button, char *title);
void mg_set_access_icon (session_gui *gui, GdkPixbuf *pix, gboolean away);
void mg_apply_setup (void);
void mg_apply_session_font_prefs (session_gui *gui);
void mg_close_sess (session *);
void mg_tab_close (session *sess);
void mg_detach (session *sess, int mode);

View File

@@ -91,6 +91,7 @@ static GtkWidget *edit_label_real;
static GtkWidget *edit_label_user;
static GtkWidget *edit_trees[N_TREES];
static GtkWidget *edit_button_cert_generate;
static GtkWidget *edit_button_cert_import;
static GtkWidget *edit_button_cert_info;
static GtkWidget *edit_button_cert_delete;
@@ -135,12 +136,98 @@ servlist_update_cert_buttons (ircnet *net)
if (edit_button_cert_generate)
gtk_widget_set_visible (edit_button_cert_generate, !has_cert);
if (edit_button_cert_import)
gtk_widget_set_visible (edit_button_cert_import, !has_cert);
if (edit_button_cert_info)
gtk_widget_set_visible (edit_button_cert_info, has_cert);
if (edit_button_cert_delete)
gtk_widget_set_visible (edit_button_cert_delete, has_cert);
}
static void
servlist_import_client_cert_cb (GtkWidget *button, gpointer userdata)
{
ircnet *net = (ircnet *)userdata;
GtkWidget *dialog;
GtkWidget *message;
GtkFileFilter *filter;
char *cert_dir;
char *cert_file;
char *source_file;
char *contents;
gsize length;
if (!net || !net->name || !net->name[0])
return;
dialog = gtk_file_chooser_dialog_new (_("Import Client Certificate"),
GTK_WINDOW (edit_win),
GTK_FILE_CHOOSER_ACTION_OPEN,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Open"), GTK_RESPONSE_ACCEPT,
NULL);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Certificate files"));
gtk_file_filter_add_pattern (filter, "*.pem");
gtk_file_filter_add_pattern (filter, "*.crt");
gtk_file_filter_add_pattern (filter, "*.cer");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("All files"));
gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
theme_manager_attach_window (dialog);
if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT)
{
gtk_widget_destroy (dialog);
return;
}
source_file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
gtk_widget_destroy (dialog);
if (!source_file)
return;
cert_dir = g_build_filename (get_xdir (), "certs", NULL);
cert_file = servlist_get_cert_file (net);
contents = NULL;
length = 0;
if (cert_file &&
g_mkdir_with_parents (cert_dir, 0700) == 0 &&
g_file_get_contents (source_file, &contents, &length, NULL) &&
g_file_set_contents (cert_file, contents, length, NULL))
{
chmod (cert_file, 0600);
servlist_update_cert_buttons (net);
message = gtk_message_dialog_new (GTK_WINDOW (edit_win),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
_("Client certificate imported for \"%s\"."),
net->name);
}
else
{
message = gtk_message_dialog_new (GTK_WINDOW (edit_win),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("Failed to import client certificate for \"%s\"."),
net->name);
}
theme_manager_attach_window (message);
g_signal_connect_swapped (message, "response", G_CALLBACK (gtk_widget_destroy), message);
gtk_widget_show (message);
g_free (contents);
g_free (cert_file);
g_free (cert_dir);
g_free (source_file);
}
static void
servlist_generate_client_cert_cb (GtkWidget *button, gpointer userdata)
{
@@ -165,6 +252,7 @@ servlist_generate_client_cert_cb (GtkWidget *button, gpointer userdata)
gboolean success;
gint status;
char *argv[20];
char **envp;
if (!net || !net->name || !net->name[0])
return;
@@ -187,6 +275,7 @@ servlist_generate_client_cert_cb (GtkWidget *button, gpointer userdata)
crt_len = 0;
success = FALSE;
status = 0;
envp = g_environ_unsetenv (g_get_environ (), "LD_LIBRARY_PATH");
if (g_mkdir_with_parents (cert_dir, 0700) == 0 &&
g_file_set_contents (openssl_conf, conf_data, -1, NULL))
@@ -212,7 +301,7 @@ servlist_generate_client_cert_cb (GtkWidget *button, gpointer userdata)
argv[18] = subject;
argv[19] = NULL;
spawned = g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
spawned = g_spawn_sync (NULL, argv, envp, G_SPAWN_SEARCH_PATH, NULL, NULL,
&stdout_data, &stderr_data, &status, NULL);
if (spawned && g_spawn_check_exit_status (status, NULL) &&
g_file_get_contents (key_file, &key_data, &key_len, NULL) &&
@@ -267,6 +356,7 @@ servlist_generate_client_cert_cb (GtkWidget *button, gpointer userdata)
g_free (openssl_conf);
g_free (cert_file);
g_free (cert_dir);
g_strfreev (envp);
#else
return;
#endif
@@ -284,6 +374,7 @@ servlist_cert_info_cb (GtkWidget *button, gpointer userdata)
gboolean spawned;
gint status;
char *argv[12];
char **envp;
cert_file = servlist_get_cert_file (net);
if (!cert_file)
@@ -292,6 +383,7 @@ servlist_cert_info_cb (GtkWidget *button, gpointer userdata)
stdout_data = NULL;
stderr_data = NULL;
status = 0;
envp = g_environ_unsetenv (g_get_environ (), "LD_LIBRARY_PATH");
argv[0] = "openssl";
argv[1] = "x509";
argv[2] = "-in";
@@ -305,7 +397,7 @@ servlist_cert_info_cb (GtkWidget *button, gpointer userdata)
argv[10] = "-sha256";
argv[11] = NULL;
spawned = g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
spawned = g_spawn_sync (NULL, argv, envp, G_SPAWN_SEARCH_PATH, NULL, NULL,
&stdout_data, &stderr_data, &status, NULL);
if (spawned && g_spawn_check_exit_status (status, NULL) && stdout_data && stdout_data[0])
@@ -336,6 +428,7 @@ servlist_cert_info_cb (GtkWidget *button, gpointer userdata)
g_free (stdout_data);
g_free (stderr_data);
g_free (cert_file);
g_strfreev (envp);
#else
return;
#endif
@@ -2285,6 +2378,11 @@ servlist_open_edit (GtkWidget *parent, ircnet *net)
G_CALLBACK (servlist_generate_client_cert_cb), net);
gtk_box_pack_start (GTK_BOX (hbox_cert_buttons), edit_button_cert_generate, FALSE, FALSE, 0);
edit_button_cert_import = gtk_button_new_with_mnemonic (_("Import client SSL cert"));
g_signal_connect (G_OBJECT (edit_button_cert_import), "clicked",
G_CALLBACK (servlist_import_client_cert_cb), net);
gtk_box_pack_start (GTK_BOX (hbox_cert_buttons), edit_button_cert_import, FALSE, FALSE, 0);
edit_button_cert_info = gtk_button_new_with_mnemonic (_("Client SSL cert info"));
g_signal_connect (G_OBJECT (edit_button_cert_info), "clicked",
G_CALLBACK (servlist_cert_info_cb), net);

View File

@@ -2066,7 +2066,7 @@ setup_apply_to_sess (session_gui *gui)
{
mg_update_xtext (gui->xtext);
theme_preferences_apply_to_session (gui, input_style);
mg_apply_session_font_prefs (gui);
if (prefs.hex_gui_ulist_buttons)
gtk_widget_show (gui->button_box);

View File

@@ -367,6 +367,12 @@ theme_css_build_toplevel_classes (void)
"color: @theme_fg_color;"
"border-color: @theme_bg_color;"
"}"
"window.%s menuitem:hover, window.%s menuitem:selected {"
"background-color: @theme_selected_bg_color;"
"background-image: none;"
"color: @theme_selected_fg_color;"
"border-color: @theme_selected_bg_color;"
"}"
"window.%s, window.%s:backdrop, .%s {"
"background-color: #f6f6f6;"
"color: #101010;"
@@ -377,6 +383,12 @@ theme_css_build_toplevel_classes (void)
"background-image: none;"
"color: @theme_fg_color;"
"border-color: @theme_bg_color;"
"}"
"window.%s menuitem:hover, window.%s menuitem:selected {"
"background-color: @theme_selected_bg_color;"
"background-image: none;"
"color: @theme_selected_fg_color;"
"border-color: @theme_selected_bg_color;"
"}",
theme_css_selector_dark_class,
theme_css_selector_dark_class,
@@ -387,6 +399,10 @@ theme_css_build_toplevel_classes (void)
theme_css_selector_dark_class,
theme_css_selector_dark_class,
theme_css_selector_dark_class,
theme_css_selector_dark_class,
theme_css_selector_dark_class,
theme_css_selector_light_class,
theme_css_selector_light_class,
theme_css_selector_light_class,
theme_css_selector_light_class,
theme_css_selector_light_class,

View File

@@ -415,6 +415,24 @@ theme_manager_is_kde_wayland (void)
return is_kde;
}
static gint
theme_manager_get_system_headerbar_height (void)
{
GtkWidget *probe;
gint minimum;
gint natural;
probe = gtk_header_bar_new ();
gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (probe), TRUE);
gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (probe), "menu:minimize,maximize,close");
gtk_widget_show (probe);
gtk_widget_get_preferred_height (probe, &minimum, &natural);
gtk_widget_destroy (probe);
if (natural > 0)
return natural;
return minimum;
}
static void
theme_manager_apply_wayland_kde_csd (GtkWidget *window)
{
@@ -442,10 +460,16 @@ theme_manager_apply_wayland_kde_csd (GtkWidget *window)
headerbar = gtk_header_bar_new ();
gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (headerbar), TRUE);
gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (headerbar), "menu:minimize,maximize,close");
icon_pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/icons/zoitechat.svg", 32, 32, TRUE, NULL);
g_object_set (G_OBJECT (headerbar), "spacing", 0, NULL);
gtk_widget_set_size_request (headerbar, -1, theme_manager_get_system_headerbar_height ());
icon_pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/icons/zoitechat.svg", 24, 24, TRUE, NULL);
if (!icon_pixbuf)
icon_pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/icons/zoitechat.png", 32, 32, TRUE, NULL);
icon_pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/icons/zoitechat.png", 24, 24, TRUE, NULL);
icon_image = icon_pixbuf ? gtk_image_new_from_pixbuf (icon_pixbuf) : gtk_image_new_from_resource ("/icons/zoitechat.png");
gtk_widget_set_margin_start (icon_image, 0);
gtk_widget_set_margin_end (icon_image, 0);
gtk_widget_set_margin_top (icon_image, 0);
gtk_widget_set_margin_bottom (icon_image, 0);
if (icon_pixbuf)
g_object_unref (icon_pixbuf);
gtk_header_bar_pack_start (GTK_HEADER_BAR (headerbar), icon_image);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1 +1 @@
2.18.0~pre5
2.18.0~pre6