summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Thurman <thomas@thurman.org.uk>2007-04-12 03:48:50 +0000
committerThomas James Alexander Thurman <tthurman@src.gnome.org>2007-04-12 03:48:50 +0000
commit2034a309e55b459f6689185a318df777736bf135 (patch)
treeb0e631a520a8b96acce9681e2e63feaa27eaa52b
parent7626f74b8562ba8f1440f52ebf34f2f6131af545 (diff)
downloadmetacity-2034a309e55b459f6689185a318df777736bf135.tar.gz
Workaround for a gdk bug which dies with BadAlloc if you try to allocate
2007-04-11 Thomas Thurman <thomas@thurman.org.uk> Workaround for a gdk bug which dies with BadAlloc if you try to allocate an insanely huge rectangle for an insanely huge window. Fixes #399529. svn path=/trunk/; revision=3191
-rw-r--r--ChangeLog6
-rw-r--r--src/frames.c119
2 files changed, 93 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index f6cad704..ab624e23 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2007-04-11 Thomas Thurman <thomas@thurman.org.uk>
+
+ Workaround for a gdk bug which dies with BadAlloc if you try
+ to allocate an insanely huge rectangle for an insanely huge
+ window. Fixes #399529.
+
2007-04-11 Elijah Newren <newren gmail com>
Advertise support of Above and Below operations (assuming the
diff --git a/src/frames.c b/src/frames.c
index 71a906fe..977099e9 100644
--- a/src/frames.c
+++ b/src/frames.c
@@ -33,6 +33,7 @@
#include "fixedtip.h"
#include "theme.h"
#include "prefs.h"
+#include "errors.h"
#ifdef HAVE_SHAPE
#include <X11/extensions/shape.h>
@@ -2174,6 +2175,11 @@ meta_frames_expose_event (GtkWidget *widget,
return TRUE;
}
+/* How far off the screen edge the window decorations should
+ * be drawn. Used only in meta_frames_paint_to_drawable, below.
+ */
+#define DECORATING_BORDER 100
+
static void
meta_frames_paint_to_drawable (MetaFrames *frames,
MetaUIFrame *frame,
@@ -2191,12 +2197,6 @@ meta_frames_paint_to_drawable (MetaFrames *frames,
MetaButtonState button_states[META_BUTTON_TYPE_LAST];
Window grab_frame;
int i;
- int top, bottom, left, right;
- GdkRegion *edges;
- GdkRegion *tmp_region;
- GdkRectangle area;
- GdkRectangle *areas;
- int n_areas;
MetaButtonLayout button_layout;
MetaGrabOp grab_op;
@@ -2307,35 +2307,95 @@ meta_frames_paint_to_drawable (MetaFrames *frames,
meta_frames_ensure_layout (frames, frame);
- meta_theme_get_frame_borders (meta_theme_get_current (),
- type, frame->text_height, flags,
- &top, &bottom, &left, &right);
+ meta_prefs_get_button_layout (&button_layout);
- /* Repaint each side of the frame */
-
- edges = gdk_region_copy (region);
+ if (G_LIKELY (GDK_IS_WINDOW (drawable)))
+ {
+ /* A window; happens about 2/3 of the time */
- /* Punch out the client area */
- area.x = left;
- area.y = top;
- area.width = w;
- area.height = h;
- tmp_region = gdk_region_rectangle (&area);
- gdk_region_subtract (edges, tmp_region);
- gdk_region_destroy (tmp_region);
+ GdkRectangle area, *areas;
+ int n_areas;
+ int screen_width, screen_height;
+ GdkRegion *edges, *tmp_region;
+ int top, bottom, left, right;
+
+ /* Repaint each side of the frame */
- /* Now draw remaining portion of region */
- gdk_region_get_rectangles (edges, &areas, &n_areas);
+ meta_theme_get_frame_borders (meta_theme_get_current (),
+ type, frame->text_height, flags,
+ &top, &bottom, &left, &right);
- meta_prefs_get_button_layout (&button_layout);
- for (i = 0; i < n_areas; i++)
+ meta_core_get_screen_size (gdk_display,
+ frame->xwindow,
+ &screen_width, &screen_height);
+
+ edges = gdk_region_copy (region);
+
+ /* Punch out the client area */
+
+ area.x = left;
+ area.y = top;
+ area.width = w;
+ area.height = h;
+ tmp_region = gdk_region_rectangle (&area);
+ gdk_region_subtract (edges, tmp_region);
+ gdk_region_destroy (tmp_region);
+
+ /* Now draw remaining portion of region */
+
+ gdk_region_get_rectangles (edges, &areas, &n_areas);
+
+ for (i = 0; i < n_areas; i++)
+ {
+ /* Bug 399529: clamp areas[i] so that it doesn't go too far
+ * off the edge of the screen. This works around a GDK bug
+ * which makes gdk_window_begin_paint_rect cause an X error
+ * if the window is insanely huge. If the client is a GDK program
+ * and does this, it will still probably cause an X error in that
+ * program, but the last thing we want is for Metacity to crash
+ * because it attempted to decorate the silly window.
+ */
+
+ areas[i].x = MAX (areas[i].x, -DECORATING_BORDER);
+ areas[i].y = MAX (areas[i].y, -DECORATING_BORDER);
+ if (areas[i].x+areas[i].width > screen_width + DECORATING_BORDER)
+ areas[i].width = MIN (0, screen_width - areas[i].x);
+ if (areas[i].y+areas[i].height > screen_height + DECORATING_BORDER)
+ areas[i].height = MIN (0, screen_height - areas[i].y);
+
+ /* Okay, so let's start painting. */
+
+ gdk_window_begin_paint_rect (drawable, &areas[i]);
+
+ meta_theme_draw_frame (meta_theme_get_current (),
+ widget,
+ drawable,
+ NULL, /* &areas[i], */
+ x_offset, y_offset,
+ type,
+ flags,
+ w, h,
+ frame->layout,
+ frame->text_height,
+ &button_layout,
+ button_states,
+ mini_icon, icon);
+
+ gdk_window_end_paint (drawable);
+ }
+
+ g_free (areas);
+ gdk_region_destroy (edges);
+
+ }
+ else
{
- if (GDK_IS_WINDOW (drawable))
- gdk_window_begin_paint_rect (drawable, &areas[i]);
+ /* Not a window; happens about 1/3 of the time */
+
meta_theme_draw_frame (meta_theme_get_current (),
widget,
drawable,
- NULL, /* &areas[i], */
+ NULL,
x_offset, y_offset,
type,
flags,
@@ -2345,13 +2405,8 @@ meta_frames_paint_to_drawable (MetaFrames *frames,
&button_layout,
button_states,
mini_icon, icon);
-
- if (GDK_IS_WINDOW (drawable))
- gdk_window_end_paint (drawable);
}
- gdk_region_destroy (edges);
- g_free (areas);
}
static void