Skip to content

Commit 3dc1ece

Browse files
64-bitmanchrisbra
authored andcommitted
patch 9.2.0587: GTK4: left scrollbar overlaps drawarea
Problem: GTK4: the drawarea is wrapped in a GtkOverlay with the scrollbar form layered on top, so the left scrollbar appears over the drawarea instead of beside it. Solution: Place the drawarea and the scrollbars as siblings inside the form widget, removing the GtkOverlay. Add gui_mch_update_scrollbar_size() to query the actual scrollbar dimensions and call it from gui_set_shellsize(), rename GtkForm to VimForm so the GTK namespace is not used (Foxe Chen). closes: #20375 Signed-off-by: Foxe Chen <chen.foxe@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 18c6b91 commit 3dc1ece

6 files changed

Lines changed: 281 additions & 321 deletions

File tree

src/gui.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,11 @@ gui_set_shellsize(
17031703
if (!gui.shell_created)
17041704
return;
17051705

1706+
#if defined(FEAT_GUI_GTK) && defined(USE_GTK4)
1707+
// Get the scrollbar width + height if possible
1708+
gui_mch_update_scrollbar_size();
1709+
#endif
1710+
17061711
#if defined(MSWIN) || defined(FEAT_GUI_GTK)
17071712
// If not setting to a user specified size and maximized, calculate the
17081713
// number of characters that fit in the maximized window.

src/gui_gtk4.c

Lines changed: 90 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -499,30 +499,21 @@ gui_mch_init(void)
499499
G_CALLBACK(on_tab_reordered), NULL);
500500
#endif
501501

502-
// The form widget manages absolute positioning of scrollbars.
503-
gui.formwin = gui_gtk_form_new();
502+
// The form widget manages absolute positioning of scrollbars and the draw
503+
// area.
504+
gui.formwin = vim_form_new();
504505
gtk_widget_set_name(gui.formwin, "vim-gtk-form");
505-
// formwin is overlaid on top of drawarea for scrollbar positioning.
506-
// GtkForm's contains() returns FALSE so empty-area clicks fall through
507-
// to the drawarea, while the scrollbar children still receive events.
506+
gtk_widget_set_vexpand(gui.formwin, TRUE);
507+
gtk_widget_set_hexpand(gui.formwin, TRUE);
508+
gtk_box_append(GTK_BOX(vbox), gui.formwin);
508509

509510
// The drawing area for the editor content.
510-
// Placed in an overlay so it fills the formwin, with scrollbars on top.
511511
gui.drawarea = gtk_drawing_area_new();
512512
gui.surface = NULL;
513513
gtk_widget_set_focusable(gui.drawarea, TRUE);
514514
gtk_widget_set_vexpand(gui.drawarea, TRUE);
515515
gtk_widget_set_hexpand(gui.drawarea, TRUE);
516-
517-
{
518-
// Use GtkOverlay: drawarea as the main child, formwin as overlay
519-
GtkWidget *overlay = gtk_overlay_new();
520-
gtk_overlay_set_child(GTK_OVERLAY(overlay), gui.drawarea);
521-
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), gui.formwin);
522-
gtk_widget_set_vexpand(overlay, TRUE);
523-
gtk_widget_set_hexpand(overlay, TRUE);
524-
gtk_box_append(GTK_BOX(vbox), overlay);
525-
}
516+
vim_form_put(VIM_FORM(gui.formwin), gui.drawarea, 0, 0);
526517

527518
// Set up drawing.
528519
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(gui.drawarea),
@@ -3007,8 +2998,8 @@ gui_gtk_draw_string_ext(
30072998
column_offset = len;
30082999
}
30093000
else
3010-
not_ascii:
30113001
{
3002+
not_ascii:;
30123003
PangoAttrList *attr_list;
30133004
GList *item_list;
30143005
int cluster_width;
@@ -4269,10 +4260,7 @@ gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
42694260
gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
42704261
{
42714262
if (sb->id != NULL)
4272-
{
4273-
gtk_widget_set_size_request(sb->id, w, h);
4274-
gui_gtk_form_move(GTK_FORM(gui.formwin), sb->id, x, y);
4275-
}
4263+
vim_form_move_resize(VIM_FORM(gui.formwin), sb->id, x, y, w, h);
42764264
}
42774265

42784266
int
@@ -4317,36 +4305,90 @@ adjustment_value_changed(GtkAdjustment *adj, gpointer data UNUSED)
43174305
void
43184306
gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
43194307
{
4308+
GtkAdjustment *adj;
43204309
if (orient == SBAR_HORIZ)
43214310
sb->id = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL);
43224311
else
43234312
sb->id = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL);
43244313

4325-
if (sb->id != NULL && GTK_IS_SCROLLBAR(sb->id))
4326-
{
4327-
GtkAdjustment *adj = gtk_scrollbar_get_adjustment(GTK_SCROLLBAR(sb->id));
4314+
gtk_widget_add_css_class(sb->id, "vim-scrollbar");
4315+
adj = gtk_scrollbar_get_adjustment(GTK_SCROLLBAR(sb->id));
43284316

4329-
gtk_widget_set_visible(sb->id, FALSE);
4330-
gui_gtk_form_put(GTK_FORM(gui.formwin), sb->id, 0, 0);
4331-
if (adj != NULL && G_IS_OBJECT(adj))
4332-
{
4333-
g_object_set_data(G_OBJECT(adj), "vim-sb", (gpointer)sb);
4334-
g_signal_connect(G_OBJECT(adj), "value-changed",
4335-
G_CALLBACK(adjustment_value_changed), NULL);
4336-
}
4337-
}
4317+
gtk_widget_set_visible(sb->id, FALSE);
4318+
vim_form_put(VIM_FORM(gui.formwin), sb->id, 0, 0);
4319+
4320+
g_object_set_data(G_OBJECT(adj), "vim-sb", (gpointer)sb);
4321+
g_signal_connect(G_OBJECT(adj), "value-changed",
4322+
G_CALLBACK(adjustment_value_changed), NULL);
43384323
}
43394324

43404325
void
43414326
gui_mch_destroy_scrollbar(scrollbar_T *sb)
43424327
{
43434328
if (sb->id != NULL)
43444329
{
4345-
gui_gtk_form_remove(GTK_FORM(gui.formwin), sb->id);
4330+
vim_form_remove(VIM_FORM(gui.formwin), sb->id);
43464331
sb->id = NULL;
43474332
}
43484333
}
43494334

4335+
/*
4336+
* Try getting the actual size of the scrollbar, and update gui.scrollbar_width
4337+
* and gui.scrollbar_height.
4338+
*/
4339+
void
4340+
gui_mch_update_scrollbar_size(void)
4341+
{
4342+
win_T *wp;
4343+
int w = -1, h = -1;
4344+
GtkWidget *sbar;
4345+
4346+
FOR_ALL_WINDOWS(wp)
4347+
{
4348+
sbar = wp->w_scrollbars[SBAR_LEFT].id;
4349+
4350+
if (sbar == NULL || !gtk_widget_get_visible(sbar)
4351+
|| (!gui.which_scrollbars[SBAR_LEFT]
4352+
&& wp->w_scrollbars[SBAR_RIGHT].id != NULL))
4353+
sbar = wp->w_scrollbars[SBAR_RIGHT].id;
4354+
4355+
if (sbar != NULL && gtk_widget_get_visible(sbar))
4356+
{
4357+
GtkRequisition min, nat;
4358+
int sw;
4359+
4360+
// Use preferred size, since widget may not have its size allocated
4361+
// yet.
4362+
gtk_widget_get_preferred_size(sbar, &min, &nat);
4363+
sw = MAX(min.width, nat.width);
4364+
if (sw > 0)
4365+
{
4366+
w = sw;
4367+
break;
4368+
}
4369+
}
4370+
4371+
}
4372+
4373+
sbar = gui.bottom_sbar.id;
4374+
if (sbar != NULL && gtk_widget_get_visible(sbar))
4375+
{
4376+
GtkRequisition min, nat;
4377+
int sh;
4378+
4379+
gtk_widget_get_preferred_size(sbar, &min, &nat);
4380+
sh = MAX(min.height, nat.height);
4381+
4382+
if (sh > 0)
4383+
h = sh;
4384+
}
4385+
4386+
if (w != -1)
4387+
gui.scrollbar_width = w;
4388+
if (h != -1)
4389+
gui.scrollbar_height = h;
4390+
}
4391+
43504392
/*
43514393
* ============================================================
43524394
* Text area position
@@ -4358,11 +4400,11 @@ gui_mch_set_text_area_pos(int x, int y, int w, int h)
43584400
{
43594401
last_text_area_w = w;
43604402
last_text_area_h = h;
4361-
// Don't use gui_gtk_form_move_resize for drawarea because its
4403+
// Don't use vim_form_move_resize for drawarea because its
43624404
// set_size_request would prevent the window from shrinking.
43634405
// Just update position; the actual allocation is handled by
4364-
// form_size_allocate which gives drawarea the formwin's full size.
4365-
gui_gtk_form_move(GTK_FORM(gui.formwin), gui.drawarea, x, y);
4406+
// vim_form_size_allocate which gives drawarea the formwin's full size.
4407+
vim_form_move(VIM_FORM(gui.formwin), gui.drawarea, x, y);
43664408

43674409
// Surface sizing is owned by drawarea_resize_cb; don't recreate it
43684410
// here. Recreating on every text-area change wiped any preserved
@@ -4704,7 +4746,7 @@ find_replace_dialog_create(char_u *arg, int do_replace)
47044746
char_u *entry_text;
47054747
int wword = FALSE;
47064748
int mcase = !p_ic;
4707-
GtkWidget *vbox, *grid, *hbox, *tmp, *btn;
4749+
GtkWidget *vertbox, *grid, *hbox, *tmp, *btn;
47084750
gboolean sensitive;
47094751

47104752
frdp = do_replace ? &repl_widgets : &find_widgets;
@@ -4748,18 +4790,18 @@ find_replace_dialog_create(char_u *arg, int do_replace)
47484790
g_signal_connect(frdp->dialog, "destroy",
47494791
G_CALLBACK(dialog_destroyed_cb), &frdp->dialog);
47504792

4751-
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
4752-
gtk_widget_set_margin_start(vbox, 12);
4753-
gtk_widget_set_margin_end(vbox, 12);
4754-
gtk_widget_set_margin_top(vbox, 12);
4755-
gtk_widget_set_margin_bottom(vbox, 12);
4756-
gtk_window_set_child(GTK_WINDOW(frdp->dialog), vbox);
4793+
vertbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
4794+
gtk_widget_set_margin_start(vertbox, 12);
4795+
gtk_widget_set_margin_end(vertbox, 12);
4796+
gtk_widget_set_margin_top(vertbox, 12);
4797+
gtk_widget_set_margin_bottom(vertbox, 12);
4798+
gtk_window_set_child(GTK_WINDOW(frdp->dialog), vertbox);
47574799

47584800
// Grid for labels + entries
47594801
grid = gtk_grid_new();
47604802
gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
47614803
gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
4762-
gtk_box_append(GTK_BOX(vbox), grid);
4804+
gtk_box_append(GTK_BOX(vertbox), grid);
47634805

47644806
// "Find what:" label + entry
47654807
tmp = gtk_label_new(_("Find what:"));
@@ -4787,7 +4829,7 @@ find_replace_dialog_create(char_u *arg, int do_replace)
47874829

47884830
// Checkboxes
47894831
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
4790-
gtk_box_append(GTK_BOX(vbox), hbox);
4832+
gtk_box_append(GTK_BOX(vertbox), hbox);
47914833

47924834
frdp->wword = gtk_check_button_new_with_label(_("Match whole word only"));
47934835
gtk_check_button_set_active(GTK_CHECK_BUTTON(frdp->wword),
@@ -4801,7 +4843,7 @@ find_replace_dialog_create(char_u *arg, int do_replace)
48014843

48024844
// Direction radio buttons
48034845
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
4804-
gtk_box_append(GTK_BOX(vbox), hbox);
4846+
gtk_box_append(GTK_BOX(vertbox), hbox);
48054847

48064848
tmp = gtk_label_new(_("Direction:"));
48074849
gtk_box_append(GTK_BOX(hbox), tmp);
@@ -4818,7 +4860,7 @@ find_replace_dialog_create(char_u *arg, int do_replace)
48184860
// Action buttons
48194861
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
48204862
gtk_widget_set_halign(hbox, GTK_ALIGN_END);
4821-
gtk_box_append(GTK_BOX(vbox), hbox);
4863+
gtk_box_append(GTK_BOX(vertbox), hbox);
48224864

48234865
btn = gtk_button_new_with_label(_("Find Next"));
48244866
gtk_widget_set_sensitive(btn, sensitive);

0 commit comments

Comments
 (0)