7 Commits

Author SHA1 Message Date
6d65871c4d Fix xtext resize paint clipping 2026-05-11 13:32:11 -06:00
deepend-tildeclub
dcb35fb80f Merge pull request #230 from ZoiteChat/fix-scrollbar-consistency
UI Consistency: Use native GTK scrollbars across main panes
2026-05-10 08:31:15 -06:00
b1768854c3 Tighten userlist count/pane width behavior 2026-05-09 12:53:35 -06:00
4ed4eaf8e8 fix FSF address. 2026-05-08 20:50:51 -06:00
deepend-tildeclub
d167b53b17 Merge pull request #227 from ZoiteChat/fix-tab-scroll-skip
Consume handled tab wheel events
2026-05-08 07:52:37 -06:00
18eff80a30 UI Consistency: Use native GTK scrollbars across main panes 2026-05-07 13:29:22 -06:00
a44ec5f624 Consume handled tab wheel events 2026-05-07 12:03:41 -06:00
6 changed files with 183 additions and 48 deletions

View File

@@ -2,10 +2,10 @@
* Copyright (C) 1998-2010 Peter Zelezny.
* Copyright (C) 2009-2013 Berke Viktor.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
* along with this program; if not, see
* <https://www.gnu.org/licenses/>.
*/
/* You can distribute this header with your plugins for easy compilation */

View File

@@ -304,21 +304,28 @@ tab_scroll_right_down_clicked (GtkWidget *widget, chanview *cv)
static gboolean
tab_scroll_cb (GtkWidget *widget, GdkEventScroll *event, gpointer cv)
{
int direction = cv_scroll_direction (event);
if (prefs.hex_gui_tab_scrollchans)
{
int direction = cv_scroll_direction (event);
if (direction != 0)
{
mg_switch_page (1, direction);
return TRUE;
}
}
else
{
int direction = cv_scroll_direction (event);
if (direction < 0)
{
tab_scroll_left_up_clicked (widget, cv);
return TRUE;
}
else if (direction > 0)
{
tab_scroll_right_down_clicked (widget, cv);
return TRUE;
}
}
return FALSE;
@@ -346,13 +353,12 @@ cv_tabs_init (chanview *cv)
viewport = gtk_scrolled_window_new (0, 0);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (viewport), GTK_SHADOW_NONE);
gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW (viewport), FALSE);
if (cv->vertical)
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (viewport),
GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
else
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (viewport),
GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (viewport), 1);
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (viewport), 1);
gtk_widget_set_hexpand (viewport, TRUE);

View File

@@ -3413,8 +3413,13 @@ mg_create_textarea (session *sess, GtkWidget *box)
inbox = mg_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), inbox, TRUE, TRUE, 0);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
frame = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_hexpand (frame, TRUE);
gtk_widget_set_vexpand (frame, TRUE);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (frame),
GTK_SHADOW_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (frame),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (inbox), frame, TRUE, TRUE, 0);
theme_get_xtext_colors_for_widget (frame, xtext_palette, XTEXT_COLS);
@@ -3431,9 +3436,7 @@ mg_create_textarea (session *sess, GtkWidget *box)
g_signal_connect (G_OBJECT (xtext), "word_click",
G_CALLBACK (mg_word_clicked), NULL);
gui->vscrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL,
GTK_XTEXT (xtext)->adj);
gtk_box_pack_start (GTK_BOX (inbox), gui->vscrollbar, FALSE, TRUE, 0);
gui->vscrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (frame));
gtk_drag_dest_set (gui->vscrollbar, 5, dnd_dest_targets, 2,
GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
@@ -3661,8 +3664,14 @@ mg_create_userlist (session_gui *gui, GtkWidget *box)
gtk_box_pack_start (GTK_BOX (box), vbox, TRUE, TRUE, 0);
gui->namelistinfo = gtk_label_new (NULL);
gtk_label_set_xalign (GTK_LABEL (gui->namelistinfo), 0.0f);
gtk_widget_set_halign (gui->namelistinfo, GTK_ALIGN_START);
gtk_label_set_xalign (GTK_LABEL (gui->namelistinfo), 0.5f);
gtk_label_set_justify (GTK_LABEL (gui->namelistinfo), GTK_JUSTIFY_CENTER);
gtk_label_set_ellipsize (GTK_LABEL (gui->namelistinfo), PANGO_ELLIPSIZE_END);
gtk_label_set_width_chars (GTK_LABEL (gui->namelistinfo), 1);
gtk_widget_set_margin_start (gui->namelistinfo, 0);
gtk_widget_set_margin_end (gui->namelistinfo, 0);
gtk_widget_set_hexpand (gui->namelistinfo, TRUE);
gtk_widget_set_halign (gui->namelistinfo, GTK_ALIGN_FILL);
if (prefs.hex_gui_ulist_count)
gtk_box_pack_start (GTK_BOX (vbox), gui->namelistinfo, 0, 0, 0);

View File

@@ -93,23 +93,14 @@ userlist_apply_saved_column_width (GtkTreeViewColumn *column, int width)
static void
userlist_update_min_width (session *sess)
{
GtkRequisition minimum;
GtkRequisition natural;
GtkWidget *scrolled_window;
int width;
if (!sess || !sess->gui || !sess->gui->user_box || !sess->gui->namelistinfo || !sess->gui->user_tree)
if (!sess || !sess->gui || !sess->gui->user_tree)
return;
gtk_widget_get_preferred_size (sess->gui->namelistinfo, &minimum, &natural);
width = MAX (minimum.width, natural.width);
if (width < 1)
width = 1;
scrolled_window = gtk_widget_get_parent (sess->gui->user_tree);
if (GTK_IS_SCROLLED_WINDOW (scrolled_window))
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (scrolled_window), width);
gtk_widget_set_size_request (sess->gui->user_box, width, -1);
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (scrolled_window), 1);
}
GdkPixbuf *
@@ -909,17 +900,19 @@ userlist_create (GtkWidget *box)
};
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_hexpand (sw, TRUE);
gtk_widget_set_vexpand (sw, TRUE);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_ETCHED_IN);
GTK_SHADOW_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
prefs.hex_gui_ulist_show_hosts ?
GTK_POLICY_AUTOMATIC :
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (sw), 1);
gtk_box_pack_start (GTK_BOX (box), sw, TRUE, TRUE, 0);
gtk_widget_show (sw);
treeview = gtk_tree_view_new ();
gtk_widget_set_hexpand (treeview, TRUE);
gtk_widget_set_vexpand (treeview, TRUE);
gtk_widget_set_name (treeview, "zoitechat-userlist");
gtk_widget_set_can_focus (treeview, TRUE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);

View File

@@ -110,6 +110,15 @@ enum
TARGET_COMPOUND_TEXT
};
enum
{
PROP_0,
PROP_HADJUSTMENT,
PROP_VADJUSTMENT,
PROP_HSCROLL_POLICY,
PROP_VSCROLL_POLICY
};
/* Selection targets for PRIMARY selection / copy-paste.
*
@@ -158,7 +167,8 @@ gtk_xtext_install_selection_targets (GtkWidget *widget)
static guint xtext_signals[LAST_SIGNAL];
G_DEFINE_TYPE (GtkXText, gtk_xtext, GTK_TYPE_WIDGET)
G_DEFINE_TYPE_WITH_CODE (GtkXText, gtk_xtext, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
char *nocasestrstr (const char *text, const char *tofind); /* util.c */
int xtext_get_stamp_str (time_t, char **);
@@ -168,9 +178,13 @@ static gboolean gtk_xtext_is_selecting (GtkXText *xtext);
static char *gtk_xtext_selection_get_text (GtkXText *xtext, int *len_ret);
static textentry *gtk_xtext_nth (GtkXText *xtext, int line, int *subline);
static void gtk_xtext_adjustment_changed (GtkAdjustment * adj,
GtkXText * xtext);
GtkXText * xtext);
static void gtk_xtext_scroll_adjustments (GtkXText *xtext, GtkAdjustment *hadj,
GtkAdjustment *vadj);
static void gtk_xtext_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void gtk_xtext_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static int gtk_xtext_render_ents (GtkXText * xtext, textentry *, textentry *);
static void gtk_xtext_recalc_widths (xtext_buffer *buf, int);
static void gtk_xtext_fix_indent (xtext_buffer *buf);
@@ -794,6 +808,9 @@ gtk_xtext_init (GtkXText * xtext)
xtext->recycle = FALSE;
xtext->dont_render = FALSE;
xtext->dont_render2 = FALSE;
xtext->hadj = NULL;
xtext->hscroll_policy = GTK_SCROLL_MINIMUM;
xtext->vscroll_policy = GTK_SCROLL_MINIMUM;
gtk_xtext_scroll_adjustments (xtext, NULL, NULL);
gtk_xtext_install_selection_targets (GTK_WIDGET (xtext));
@@ -886,6 +903,66 @@ gtk_xtext_adjustment_changed (GtkAdjustment * adj, GtkXText * xtext)
xtext->buffer->old_value = xtext_adj_get_value (adj);
}
static void
gtk_xtext_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
GtkXText *xtext = GTK_XTEXT (object);
GtkAdjustment *adj;
switch (prop_id)
{
case PROP_HADJUSTMENT:
adj = g_value_get_object (value);
if (xtext->hadj == adj)
break;
if (xtext->hadj)
g_object_unref (xtext->hadj);
xtext->hadj = adj ? g_object_ref (adj) : NULL;
g_object_notify (object, "hadjustment");
break;
case PROP_VADJUSTMENT:
gtk_xtext_scroll_adjustments (xtext, NULL, g_value_get_object (value));
g_object_notify (object, "vadjustment");
break;
case PROP_HSCROLL_POLICY:
xtext->hscroll_policy = g_value_get_enum (value);
g_object_notify (object, "hscroll-policy");
break;
case PROP_VSCROLL_POLICY:
xtext->vscroll_policy = g_value_get_enum (value);
g_object_notify (object, "vscroll-policy");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_xtext_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
GtkXText *xtext = GTK_XTEXT (object);
switch (prop_id)
{
case PROP_HADJUSTMENT:
g_value_set_object (value, xtext->hadj);
break;
case PROP_VADJUSTMENT:
g_value_set_object (value, xtext->adj);
break;
case PROP_HSCROLL_POLICY:
g_value_set_enum (value, xtext->hscroll_policy);
break;
case PROP_VSCROLL_POLICY:
g_value_set_enum (value, xtext->vscroll_policy);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
GtkWidget *
gtk_xtext_new (const XTextColor *palette, int separator)
{
@@ -952,6 +1029,11 @@ gtk_xtext_cleanup (GtkXText *xtext)
xtext->adj = NULL;
}
if (xtext->hadj)
{
g_object_unref (G_OBJECT (xtext->hadj));
xtext->hadj = NULL;
}
if (xtext->hand_cursor)
{
@@ -1201,13 +1283,25 @@ gtk_xtext_get_preferred_height_for_width (GtkWidget *widget, gint width,
*natural = requisition.height;
}
static void
gtk_xtext_invalidate_resize (GtkXText *xtext, xtext_buffer *buf)
{
buf->pagetop_ent = NULL;
dontscroll (buf);
xtext->force_render = TRUE;
}
static void
gtk_xtext_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
{
GtkXText *xtext = GTK_XTEXT (widget);
int height_only = FALSE;
gboolean resized;
GdkWindow *window;
resized = allocation->width != xtext->buffer->window_width ||
allocation->height != xtext->buffer->window_height;
if (allocation->width == xtext->buffer->window_width)
height_only = TRUE;
@@ -1233,6 +1327,11 @@ gtk_xtext_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
xtext_adj_set_value (xtext->adj,
xtext_adj_get_upper (xtext->adj) -
xtext_adj_get_page_size (xtext->adj));
if (resized)
{
gtk_xtext_invalidate_resize (xtext, xtext->buffer);
gtk_widget_queue_draw (widget);
}
}
}
@@ -1505,6 +1604,17 @@ gtk_xtext_render (GtkWidget *widget, GdkRectangle *area, cairo_t *cr)
gtk_widget_get_allocation (widget, &allocation);
if (xtext->force_render && area->x == 0 && area->y == 0 &&
area->height == allocation.height &&
area->width == allocation.width)
{
xtext->force_render = FALSE;
}
else if (xtext->force_render)
{
gtk_widget_queue_draw (widget);
}
if (area->x == 0 && area->y == 0 &&
area->height == allocation.height &&
area->width == allocation.width)
@@ -2924,6 +3034,13 @@ gtk_xtext_class_init (GtkXTextClass * class)
widget_class = (GtkWidgetClass *) class;
xtext_class = (GtkXTextClass *) class;
object_class->set_property = gtk_xtext_set_property;
object_class->get_property = gtk_xtext_get_property;
g_object_class_override_property (object_class, PROP_HADJUSTMENT, "hadjustment");
g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment");
g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
xtext_signals[WORD_CLICK] =
g_signal_new ("word_click",
G_TYPE_FROM_CLASS (object_class),
@@ -4213,13 +4330,9 @@ gtk_xtext_calc_lines (xtext_buffer *buf, int fire_signal)
int width;
int height;
int lines;
GdkWindow *window;
window = gtk_widget_get_window (GTK_WIDGET (buf->xtext));
if (!window)
return;
height = gdk_window_get_height (window);
width = gdk_window_get_width (window);
height = buf->window_height;
width = buf->window_width;
width -= MARGIN;
if (width < 30 || height < buf->xtext->fontsize || width < buf->indent + 30)
@@ -4431,6 +4544,7 @@ gtk_xtext_render_page (GtkXText * xtext)
int startline = adj_value;
int pos, overlap;
GdkWindow *window;
GtkAllocation allocation;
if(!gtk_widget_get_realized(GTK_WIDGET(xtext)))
return;
@@ -4441,8 +4555,9 @@ gtk_xtext_render_page (GtkXText * xtext)
window = gtk_widget_get_window (GTK_WIDGET (xtext));
if (!window)
return;
width = gdk_window_get_width (window);
height = gdk_window_get_height (window);
gtk_widget_get_allocation (GTK_WIDGET (xtext), &allocation);
width = allocation.width;
height = allocation.height;
if (width < 34 || height < xtext->fontsize || width < xtext->buffer->indent + 32)
return;
@@ -5653,6 +5768,7 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
{
int w, h;
GdkWindow *window;
GtkAllocation allocation;
buf->xtext = xtext;
@@ -5679,8 +5795,9 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
window = gtk_widget_get_window (GTK_WIDGET (xtext));
if (!window)
return;
h = gdk_window_get_height (window);
w = gdk_window_get_width (window);
gtk_widget_get_allocation (GTK_WIDGET (xtext), &allocation);
h = allocation.height;
w = allocation.width;
/* after a font change */
if (buf->needs_recalc)
@@ -5718,6 +5835,10 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
if (render)
{
gboolean resized;
resized = buf->window_width != w || buf->window_height != h;
/* did the window change size since this buffer was last shown? */
if (buf->window_width != w)
{
@@ -5738,6 +5859,9 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
gtk_xtext_adjustment_set (buf, FALSE);
}
if (resized)
gtk_xtext_invalidate_resize (xtext, buf);
gtk_xtext_render_page (xtext);
{
GtkAllocation allocation;

View File

@@ -134,6 +134,9 @@ struct _GtkXText
xtext_buffer *selection_buffer;
GtkAdjustment *adj;
GtkAdjustment *hadj;
GtkScrollablePolicy hscroll_policy;
GtkScrollablePolicy vscroll_policy;
cairo_surface_t *background_surface; /* 0 = use palette[19] */
cairo_surface_t *background_clip_surface;
GdkWindow *draw_window; /* points to ->window */