From 18f9e37c8bc5f8ea21c9f3b3b6b3d0dee0b572cb Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 8 Oct 2014 22:39:18 -0700 Subject: [PATCH] psppire-output-view: Only render output items once the window is realized. Otherwise, in environments where the output view is not rendered immediately upon the call to gtk_widget_show_all() from psppire_output_submit(), psppire_output_view_put() called later in that function would dereference a null pointer trying to create a rendering from a null GTK_WIDGET (view->output)->window. Bug #43362. --- src/ui/gui/psppire-output-view.c | 61 +++++++++++++++++++----------- src/ui/gui/psppire-output-window.c | 14 ++++++- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/ui/gui/psppire-output-view.c b/src/ui/gui/psppire-output-view.c index 6b9445b404..3f254d7b63 100644 --- a/src/ui/gui/psppire-output-view.c +++ b/src/ui/gui/psppire-output-view.c @@ -194,7 +194,7 @@ rerender (struct psppire_output_view *view) struct output_view_item *item; cairo_t *cr; - if (!view->n_items) + if (!view->n_items || !GTK_WIDGET (view->output)->window) return; string_map_clear (&view->render_opts); @@ -209,6 +209,7 @@ rerender (struct psppire_output_view *view) { struct xr_rendering *r; int tw, th; + bool new; if (view->y > 0) view->y += view->font_height / 2; @@ -221,10 +222,18 @@ rerender (struct psppire_output_view *view) } xr_rendering_measure (r, &tw, &th); + + new = !item->drawing_area; + if (new) + item->drawing_area = gtk_drawing_area_new (); g_object_set_data_full (G_OBJECT (item->drawing_area), "rendering", r, free_rendering); + gtk_widget_set_size_request (item->drawing_area, tw, th); - gtk_layout_move (view->output, item->drawing_area, 0, view->y); + if (new) + gtk_layout_put (view->output, item->drawing_area, 0, view->y); + else + gtk_layout_move (view->output, item->drawing_area, 0, view->y); if (view->max_width < tw) view->max_width = tw; @@ -239,13 +248,14 @@ void psppire_output_view_put (struct psppire_output_view *view, const struct output_item *item) { + struct output_view_item *view_item; GtkWidget *drawing_area; struct xr_rendering *r; struct string name; GtkTreeStore *store; + cairo_t *cr = NULL; GtkTreePath *path; GtkTreeIter iter; - cairo_t *cr; int tw, th; if (is_text_item (item)) @@ -266,33 +276,38 @@ psppire_output_view_put (struct psppire_output_view *view, if (view->n_items >= view->allocated_items) view->items = x2nrealloc (view->items, &view->allocated_items, sizeof *view->items); - view->items[view->n_items].item = output_item_ref (item); - view->items[view->n_items].drawing_area = drawing_area = gtk_drawing_area_new (); - view->n_items++; + view_item = &view->items[view->n_items++]; + view_item->item = output_item_ref (item); + view_item->drawing_area = NULL; - cr = gdk_cairo_create (GTK_WIDGET (view->output)->window); - if (view->xr == NULL) - create_xr (view); + if (GTK_WIDGET (view->output)->window) + { + view_item->drawing_area = drawing_area = gtk_drawing_area_new (); - if (view->y > 0) - view->y += view->font_height / 2; + cr = gdk_cairo_create (GTK_WIDGET (view->output)->window); + if (view->xr == NULL) + create_xr (view); - r = xr_rendering_create (view->xr, item, cr); - if (r == NULL) - goto done; + if (view->y > 0) + view->y += view->font_height / 2; + + r = xr_rendering_create (view->xr, item, cr); + if (r == NULL) + goto done; - xr_rendering_measure (r, &tw, &th); + xr_rendering_measure (r, &tw, &th); - g_object_set_data_full (G_OBJECT (drawing_area), "rendering", r, free_rendering); - g_signal_connect (drawing_area, "realize", - G_CALLBACK (on_dwgarea_realize), view); - g_signal_connect (drawing_area, "expose_event", - G_CALLBACK (expose_event_callback), view); + g_object_set_data_full (G_OBJECT (drawing_area), "rendering", r, free_rendering); + g_signal_connect (drawing_area, "realize", + G_CALLBACK (on_dwgarea_realize), view); + g_signal_connect (drawing_area, "expose_event", + G_CALLBACK (expose_event_callback), view); - gtk_widget_set_size_request (drawing_area, tw, th); - gtk_layout_put (view->output, drawing_area, 0, view->y); + gtk_widget_set_size_request (drawing_area, tw, th); + gtk_layout_put (view->output, drawing_area, 0, view->y); - gtk_widget_show (drawing_area); + gtk_widget_show (drawing_area); + } if (view->overview && (!is_text_item (item) diff --git a/src/ui/gui/psppire-output-window.c b/src/ui/gui/psppire-output-window.c index 074f90a88b..3c889808a3 100644 --- a/src/ui/gui/psppire-output-window.c +++ b/src/ui/gui/psppire-output-window.c @@ -139,17 +139,27 @@ psppire_output_submit (struct output_driver *this, { struct psppire_output_driver *pod = psppire_output_cast (this); PsppireOutputWindow *window; + bool new; - if (pod->window == NULL) + new = pod->window == NULL; + if (new) { pod->window = PSPPIRE_OUTPUT_WINDOW (psppire_output_window_new ()); - gtk_widget_show_all (GTK_WIDGET (pod->window)); pod->window->driver = pod; } window = pod->window; psppire_output_view_put (window->view, item); + if (new) + { + /* We could have called this earlier in the previous "if (new)" block, + but doing it here finds, in a plain GTK+ environment, a bug that + otherwise only showed up on an Ubuntu Unity desktop. See bug + #43362. */ + gtk_widget_show_all (GTK_WIDGET (pod->window)); + } + gtk_window_set_urgency_hint (GTK_WINDOW (pod->window), TRUE); } -- 2.30.2