@@ -1613,6 +1613,33 @@ gnc_main_window_update_all_titles (void)
1613
1613
nullptr );
1614
1614
}
1615
1615
1616
+ /* Callback function invoked when the user clicks on a GtkNotebook tab.
1617
+ *
1618
+ * This function is needed to make it possible to close a tab
1619
+ * when it's clicked using the middle mouse button;
1620
+ * there does not seem to be a way to do this with GtkNotebook natively.
1621
+ *
1622
+ * @param widget The event box in the tab, which was clicked.
1623
+ *
1624
+ * @param event The event parameter describing where on the screen
1625
+ * the mouse was pointing when clicked, type of click, modifiers,
1626
+ * etc.
1627
+ *
1628
+ * @param page This is the GncPluginPage corresponding to the tab.
1629
+ *
1630
+ * @return Returns TRUE if this was a middle-click, meaning Gnucash
1631
+ * handled the click.
1632
+ */
1633
+ static gboolean
1634
+ gnc_tab_clicked_cb (GtkWidget *widget, GdkEventButton *event, GncPluginPage *page) {
1635
+ if (event->type == GDK_BUTTON_PRESS && event->button == 2 )
1636
+ {
1637
+ gnc_main_window_close_page (page);
1638
+ return TRUE ;
1639
+ }
1640
+ return FALSE ;
1641
+ }
1642
+
1616
1643
static void
1617
1644
gnc_main_window_book_dirty_cb (QofBook *book,
1618
1645
gboolean dirty,
@@ -2258,11 +2285,19 @@ main_window_find_tab_items (GncMainWindow *window,
2258
2285
2259
2286
tab_widget = gtk_notebook_get_tab_label (GTK_NOTEBOOK (priv->notebook ),
2260
2287
page->notebook_page );
2261
- if (GTK_IS_EVENT_BOX (tab_widget))
2262
- tab_hbox = gtk_bin_get_child (GTK_BIN (tab_widget));
2263
- else if (GTK_IS_BOX (tab_widget))
2264
- tab_hbox = tab_widget;
2265
- else
2288
+
2289
+ // Walk through children to find the box containing label+entry
2290
+ tab_hbox = tab_widget;
2291
+ while (tab_hbox) {
2292
+ if (g_strcmp0 (gtk_widget_get_name (tab_hbox), " tab-content" ) == 0 ) {
2293
+ break ;
2294
+ }
2295
+ GList* _children = gtk_container_get_children (GTK_CONTAINER (tab_hbox));
2296
+ tab_hbox = _children ? GTK_WIDGET (_children->data ) : nullptr ;
2297
+ g_list_free (_children);
2298
+ }
2299
+
2300
+ if (!GTK_IS_BOX (tab_hbox))
2266
2301
{
2267
2302
PWARN (" Unknown widget for tab label %p" , tab_widget);
2268
2303
return FALSE ;
@@ -3215,7 +3250,7 @@ gnc_main_window_open_page (GncMainWindow *window,
3215
3250
GncPluginPage *page)
3216
3251
{
3217
3252
GncMainWindowPrivate *priv;
3218
- GtkWidget *tab_hbox ;
3253
+ GtkWidget *tab_container, *tab_clickable_area ;
3219
3254
GtkWidget *label, *entry;
3220
3255
const gchar *icon, *text, *color_string, *lab_text;
3221
3256
GtkWidget *image;
@@ -3263,6 +3298,15 @@ gnc_main_window_open_page (GncMainWindow *window,
3263
3298
3264
3299
/*
3265
3300
* The page tab.
3301
+ * Component structure:
3302
+ *
3303
+ * tab_container (GtkBox)
3304
+ * ├── tab_clickable_area (GtkEventBox)
3305
+ * │ └── tab_content (GtkBox)
3306
+ * │ ├── image (GtkImage, optional)
3307
+ * │ ├── label (GtkLabel)
3308
+ * │ └── entry (GtkEntry, hidden)
3309
+ * └── close_button (GtkButton, if not immutable)
3266
3310
*/
3267
3311
icon = GNC_PLUGIN_PAGE_GET_CLASS (page)->tab_icon ;
3268
3312
lab_text = gnc_plugin_page_get_page_name (page);
@@ -3275,34 +3319,46 @@ gnc_main_window_open_page (GncMainWindow *window,
3275
3319
3276
3320
gtk_widget_show (label);
3277
3321
3278
- tab_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6 );
3322
+ tab_container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6 );
3323
+
3324
+ text = gnc_plugin_page_get_page_long_name (page);
3325
+ if (text)
3326
+ {
3327
+ gtk_widget_set_tooltip_text (tab_container, text);
3328
+ }
3279
3329
3280
3330
if (g_strcmp0 (gnc_plugin_page_get_plugin_name (page), " GncPluginPageAccountTree" ) == 0 )
3281
- gtk_widget_set_name (GTK_WIDGET (tab_hbox ), " gnc-id-account-page-tab-box" );
3331
+ gtk_widget_set_name (GTK_WIDGET (tab_container ), " gnc-id-account-page-tab-box" );
3282
3332
3283
- gtk_box_set_homogeneous (GTK_BOX (tab_hbox), FALSE );
3284
- gtk_widget_show (tab_hbox);
3333
+ gtk_box_set_homogeneous (GTK_BOX (tab_container), FALSE );
3334
+ gtk_widget_show (tab_container);
3335
+
3336
+ // Create a custom clickable area for the tab to support middle-clicking
3337
+ tab_clickable_area = gtk_event_box_new ();
3338
+ gtk_widget_show (tab_clickable_area);
3339
+ gtk_box_pack_start (GTK_BOX (tab_container), tab_clickable_area, TRUE , TRUE , 0 );
3340
+
3341
+ // Create a box for the tab's content
3342
+ // Give it a name so we can find it later (see main_window_find_tab_items)
3343
+ GtkWidget *tab_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6 );
3344
+ gtk_widget_set_name (tab_content, " tab-content" );
3345
+ gtk_container_add (GTK_CONTAINER (tab_clickable_area), tab_content);
3346
+ gtk_widget_show (tab_content);
3285
3347
3286
3348
if (icon != nullptr )
3287
3349
{
3288
3350
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU);
3289
3351
gtk_widget_show (image);
3290
- gtk_box_pack_start (GTK_BOX (tab_hbox ), image, FALSE , FALSE , 0 );
3352
+ gtk_box_pack_start (GTK_BOX (tab_content ), image, FALSE , FALSE , 0 );
3291
3353
gtk_widget_set_margin_start (GTK_WIDGET (image), 5 );
3292
- gtk_box_pack_start (GTK_BOX (tab_hbox ), label, TRUE , TRUE , 0 );
3354
+ gtk_box_pack_start (GTK_BOX (tab_content ), label, TRUE , TRUE , 0 );
3293
3355
}
3294
3356
else
3295
- gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE , TRUE , 0 );
3296
-
3297
- text = gnc_plugin_page_get_page_long_name (page);
3298
- if (text)
3299
- {
3300
- gtk_widget_set_tooltip_text (tab_hbox, text);
3301
- }
3357
+ gtk_box_pack_start (GTK_BOX (tab_content), label, TRUE , TRUE , 0 );
3302
3358
3303
3359
entry = gtk_entry_new ();
3304
3360
gtk_widget_hide (entry);
3305
- gtk_box_pack_start (GTK_BOX (tab_hbox ), entry, TRUE , TRUE , 0 );
3361
+ gtk_box_pack_start (GTK_BOX (tab_content ), entry, TRUE , TRUE , 0 );
3306
3362
g_signal_connect (G_OBJECT (entry), " activate" ,
3307
3363
G_CALLBACK (gnc_main_window_tab_entry_activate), page);
3308
3364
g_signal_connect (G_OBJECT (entry), " focus-out-event" ,
@@ -3334,10 +3390,14 @@ gnc_main_window_open_page (GncMainWindow *window,
3334
3390
else
3335
3391
gtk_widget_hide (close_button);
3336
3392
3393
+ // Custom handler to close on middle-clicks
3394
+ g_signal_connect (G_OBJECT (tab_clickable_area), " button-press-event" ,
3395
+ G_CALLBACK (gnc_tab_clicked_cb), page);
3396
+
3337
3397
g_signal_connect_swapped (G_OBJECT (close_button), " clicked" ,
3338
3398
G_CALLBACK (gnc_main_window_close_page), page);
3339
3399
3340
- gtk_box_pack_start (GTK_BOX (tab_hbox ), close_button, FALSE , FALSE , 0 );
3400
+ gtk_box_pack_start (GTK_BOX (tab_container ), close_button, FALSE , FALSE , 0 );
3341
3401
gtk_widget_set_margin_end (GTK_WIDGET (close_button), 5 );
3342
3402
g_object_set_data (G_OBJECT (page), PLUGIN_PAGE_CLOSE_BUTTON, close_button);
3343
3403
}
@@ -3350,7 +3410,7 @@ gnc_main_window_open_page (GncMainWindow *window,
3350
3410
/*
3351
3411
* Now install it all in the window.
3352
3412
*/
3353
- gnc_main_window_connect (window, page, tab_hbox , label);
3413
+ gnc_main_window_connect (window, page, tab_container , label);
3354
3414
3355
3415
color_string = gnc_plugin_page_get_page_color (page);
3356
3416
main_window_update_page_color (page, color_string);
0 commit comments