diff --git a/ChangeLog b/ChangeLog index 5c1255040..a8a047c83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2002-05-04 Havoc Pennington + + * src/frames.c (meta_frames_paint_to_drawable): chop out the + portion of the region that's outside the screen. + + * src/core.c (meta_core_get_screen_size): new function + (meta_core_get_frame_extents): new function + 2002-05-04 Havoc Pennington * src/frames.c (meta_frames_init): disable automatic GTK double diff --git a/src/core.c b/src/core.c index 89b294502..61c16b82b 100644 --- a/src/core.c +++ b/src/core.c @@ -451,6 +451,34 @@ meta_core_get_frame_workspace (Display *xdisplay, return meta_window_get_net_wm_desktop (window); } +void +meta_core_get_frame_extents (Display *xdisplay, + Window frame_xwindow, + int *x, + int *y, + int *width, + int *height) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + if (x) + *x = window->frame->rect.x; + if (y) + *y = window->frame->rect.y; + if (width) + *width = window->frame->rect.width; + if (height) + *height = window->frame->rect.height; +} + + void meta_core_show_window_menu (Display *xdisplay, Window frame_xwindow, @@ -579,6 +607,27 @@ meta_core_set_screen_cursor (Display *xdisplay, meta_screen_set_cursor (window->screen, cursor); } +void +meta_core_get_screen_size (Display *xdisplay, + Window frame_on_screen, + int *width, + int *height) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_on_screen); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_on_screen); + + if (width) + *width = window->screen->width; + if (height) + *height = window->screen->height; +} + void meta_core_increment_event_serial (Display *xdisplay) { diff --git a/src/core.h b/src/core.h index 7952e88ec..bcd9dd90d 100644 --- a/src/core.h +++ b/src/core.h @@ -99,6 +99,14 @@ int meta_core_get_active_workspace (Screen *xscreen); int meta_core_get_frame_workspace (Display *xdisplay, Window frame_xwindow); +void meta_core_get_frame_extents (Display *xdisplay, + Window frame_xwindow, + int *x, + int *y, + int *width, + int *height); + + void meta_core_show_window_menu (Display *xdisplay, Window frame_xwindow, int root_x, @@ -129,6 +137,11 @@ void meta_core_set_screen_cursor (Display *xdisplay, Window frame_on_screen, MetaCursor cursor); +void meta_core_get_screen_size (Display *xdisplay, + Window frame_on_screen, + int *width, + int *height); + /* Used because we ignore EnterNotify when a window is unmapped that * really shouldn't cause focus changes, by comparing the event serial * of the EnterNotify and the UnmapNotify. diff --git a/src/frames.c b/src/frames.c index ab56bd541..aadb86bbb 100644 --- a/src/frames.c +++ b/src/frames.c @@ -1299,10 +1299,11 @@ meta_frames_paint_to_drawable (MetaFrames *frames, int i; int top, bottom, left, right; GdkRegion *edges; - GdkRegion *client; + GdkRegion *tmp_region; GdkRectangle area; GdkRectangle *areas; int n_areas; + int screen_width, screen_height; widget = GTK_WIDGET (frames); @@ -1380,19 +1381,52 @@ meta_frames_paint_to_drawable (MetaFrames *frames, /* Repaint each side of the frame */ edges = gdk_region_copy (region); + + /* Punch out the client area */ area.x = left; area.y = top; area.width = w; area.height = h; - client = gdk_region_rectangle (&area); - gdk_region_subtract (edges, client); - gdk_region_destroy (client); + tmp_region = gdk_region_rectangle (&area); + gdk_region_subtract (edges, tmp_region); + gdk_region_destroy (tmp_region); + /* Chop off stuff outside the screen; this optimization + * is crucial to handle huge client windows, + * like "xterm -geometry 1000x1000" + */ + meta_core_get_frame_extents (gdk_display, + frame->xwindow, + &area.x, &area.y, + &area.width, &area.height); + + meta_core_get_screen_size (gdk_display, + frame->xwindow, + &screen_width, &screen_height); + + if ((area.x + area.width) > screen_width) + area.width = screen_width - area.x; + if (area.width < 0) + area.width = 0; + + if ((area.y + area.height) > screen_height) + area.height = screen_height - area.y; + if (area.height < 0) + area.height = 0; + + area.x = 0; /* make relative to frame rather than screen */ + area.y = 0; + + tmp_region = gdk_region_rectangle (&area); + gdk_region_intersect (edges, tmp_region); + gdk_region_destroy (tmp_region); + + /* Now draw remaining portion of region */ gdk_region_get_rectangles (edges, &areas, &n_areas); i = 0; while (i < n_areas) - { + { if (GDK_IS_WINDOW (drawable)) gdk_window_begin_paint_rect (drawable, &areas[i]);