diff --git a/src/ui/frames.c b/src/ui/frames.c index 9e87f6718..3ec67c986 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -97,7 +97,6 @@ static MetaFrameControl get_control (MetaFrames *frames, MetaUIFrame *frame, int x, int y); -static void invalidate_all_caches (MetaFrames *frames); static void invalidate_whole_window (MetaFrames *frames, MetaUIFrame *frame); @@ -261,10 +260,6 @@ meta_frames_init (MetaFrames *frames) frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); - frames->invalidate_cache_timeout_id = 0; - frames->invalidate_frames = NULL; - frames->cache = g_hash_table_new (g_direct_hash, g_direct_equal); - frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); update_style_contexts (frames); @@ -331,90 +326,13 @@ meta_frames_finalize (GObject *object) meta_prefs_remove_listener (prefs_changed_callback, frames); g_hash_table_destroy (frames->text_heights); - - invalidate_all_caches (frames); - if (frames->invalidate_cache_timeout_id) - g_source_remove (frames->invalidate_cache_timeout_id); g_assert (g_hash_table_size (frames->frames) == 0); g_hash_table_destroy (frames->frames); - g_hash_table_destroy (frames->cache); G_OBJECT_CLASS (meta_frames_parent_class)->finalize (object); } -typedef struct -{ - cairo_rectangle_int_t rect; - cairo_surface_t *pixmap; -} CachedFramePiece; - -typedef struct -{ - /* Caches of the four rendered sides in a MetaFrame. - * Order: top (titlebar), left, right, bottom. - */ - CachedFramePiece piece[4]; -} CachedPixels; - -static CachedPixels * -get_cache (MetaFrames *frames, - MetaUIFrame *frame) -{ - CachedPixels *pixels; - - pixels = g_hash_table_lookup (frames->cache, frame); - - if (!pixels) - { - pixels = g_new0 (CachedPixels, 1); - g_hash_table_insert (frames->cache, frame, pixels); - } - - return pixels; -} - -static void -invalidate_cache (MetaFrames *frames, - MetaUIFrame *frame) -{ - CachedPixels *pixels = get_cache (frames, frame); - int i; - - for (i = 0; i < 4; i++) - if (pixels->piece[i].pixmap) - cairo_surface_destroy (pixels->piece[i].pixmap); - - g_free (pixels); - g_hash_table_remove (frames->cache, frame); -} - -static void -invalidate_all_caches (MetaFrames *frames) -{ - GList *l; - - for (l = frames->invalidate_frames; l; l = l->next) - { - MetaUIFrame *frame = l->data; - - invalidate_cache (frames, frame); - } - - g_list_free (frames->invalidate_frames); - frames->invalidate_frames = NULL; -} - -static gboolean -invalidate_cache_timeout (gpointer data) -{ - MetaFrames *frames = data; - - invalidate_all_caches (frames); - frames->invalidate_cache_timeout_id = 0; - return FALSE; -} - static void queue_recalc_func (gpointer key, gpointer value, gpointer data) { @@ -719,11 +637,6 @@ meta_frames_unmanage_window (MetaFrames *frames, if (frame) { - /* invalidating all caches ensures the frame - * is not actually referenced anymore - */ - invalidate_all_caches (frames); - /* restore the cursor */ meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow, @@ -1125,7 +1038,6 @@ redraw_control (MetaFrames *frames, rect = control_rect (control, &fgeom); gdk_window_invalidate_rect (frame->window, rect, FALSE); - invalidate_cache (frames, frame); } static gboolean @@ -1899,222 +1811,50 @@ setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset) } } -/* Returns a pixmap with a piece of the windows frame painted on it. -*/ - -static cairo_surface_t * -generate_pixmap (MetaFrames *frames, - MetaUIFrame *frame, - cairo_rectangle_int_t *rect) -{ - cairo_surface_t *result; - cairo_t *cr; - - /* do not create a pixmap for nonexisting areas */ - if (rect->width <= 0 || rect->height <= 0) - return NULL; - - result = gdk_window_create_similar_surface (frame->window, - CAIRO_CONTENT_COLOR, - rect->width, rect->height); - - cr = cairo_create (result); - cairo_translate (cr, -rect->x, -rect->y); - - setup_bg_cr (cr, frame->window, 0, 0); - cairo_paint (cr); - - meta_frames_paint (frames, frame, cr); - - cairo_destroy (cr); - - return result; -} - - static void -populate_cache (MetaFrames *frames, - MetaUIFrame *frame) -{ - MetaFrameBorders borders; - int width, height; - int frame_width, frame_height, screen_width, screen_height; - CachedPixels *pixels; - MetaFrameType frame_type; - MetaFrameFlags frame_flags; - int i; - - meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), - frame->xwindow, - META_CORE_GET_FRAME_WIDTH, &frame_width, - META_CORE_GET_FRAME_HEIGHT, &frame_height, - META_CORE_GET_SCREEN_WIDTH, &screen_width, - META_CORE_GET_SCREEN_HEIGHT, &screen_height, - META_CORE_GET_CLIENT_WIDTH, &width, - META_CORE_GET_CLIENT_HEIGHT, &height, - META_CORE_GET_FRAME_TYPE, &frame_type, - META_CORE_GET_FRAME_FLAGS, &frame_flags, - META_CORE_GET_END); - - /* don't cache extremely large windows */ - if (frame_width > 2 * screen_width || - frame_height > 2 * screen_height) - { - return; - } - - meta_theme_get_frame_borders (meta_theme_get_current (), - frame_type, - frame->text_height, - frame_flags, - &borders); - - pixels = get_cache (frames, frame); - - /* Setup the rectangles for the four visible frame borders. First top, then - * left, right and bottom. Top and bottom extend to the invisible borders - * while left and right snugly fit in between: - * ----- - * | | - * ----- - */ - - /* width and height refer to the client window's - * size without any border added. */ - - /* top */ - pixels->piece[0].rect.x = borders.invisible.left; - pixels->piece[0].rect.y = borders.invisible.top; - pixels->piece[0].rect.width = width + borders.visible.left + borders.visible.right; - pixels->piece[0].rect.height = borders.visible.top; - - /* left */ - pixels->piece[1].rect.x = borders.invisible.left; - pixels->piece[1].rect.y = borders.total.top; - pixels->piece[1].rect.height = height; - pixels->piece[1].rect.width = borders.visible.left; - - /* right */ - pixels->piece[2].rect.x = borders.total.left + width; - pixels->piece[2].rect.y = borders.total.top; - pixels->piece[2].rect.width = borders.visible.right; - pixels->piece[2].rect.height = height; - - /* bottom */ - pixels->piece[3].rect.x = borders.invisible.left; - pixels->piece[3].rect.y = borders.total.top + height; - pixels->piece[3].rect.width = width + borders.visible.left + borders.visible.right; - pixels->piece[3].rect.height = borders.visible.bottom; - - for (i = 0; i < 4; i++) - { - CachedFramePiece *piece = &pixels->piece[i]; - /* generate_pixmap() returns NULL for 0 width/height pieces, but - * does so cheaply so we don't need to cache the NULL return */ - if (!piece->pixmap) - piece->pixmap = generate_pixmap (frames, frame, &piece->rect); - } - - if (frames->invalidate_cache_timeout_id) - g_source_remove (frames->invalidate_cache_timeout_id); - - frames->invalidate_cache_timeout_id = g_timeout_add (1000, invalidate_cache_timeout, frames); - - if (!g_list_find (frames->invalidate_frames, frame)) - frames->invalidate_frames = - g_list_prepend (frames->invalidate_frames, frame); -} - -static void -clip_to_screen (cairo_region_t *region, - MetaUIFrame *frame) -{ - cairo_rectangle_int_t frame_area; - cairo_rectangle_int_t screen_area = { 0, 0, 0, 0 }; - cairo_region_t *tmp_region; - - /* Chop off stuff outside the screen; this optimization - * is crucial to handle huge client windows, - * like "xterm -geometry 1000x1000" - */ - meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), - frame->xwindow, - META_CORE_GET_FRAME_X, &frame_area.x, - META_CORE_GET_FRAME_Y, &frame_area.y, - META_CORE_GET_FRAME_WIDTH, &frame_area.width, - META_CORE_GET_FRAME_HEIGHT, &frame_area.height, - META_CORE_GET_SCREEN_WIDTH, &screen_area.width, - META_CORE_GET_SCREEN_HEIGHT, &screen_area.height, - META_CORE_GET_END); - - cairo_region_translate (region, frame_area.x, frame_area.y); - - tmp_region = cairo_region_create_rectangle (&frame_area); - cairo_region_intersect (region, tmp_region); - cairo_region_destroy (tmp_region); - - tmp_region = cairo_region_create_rectangle (&screen_area); - cairo_region_intersect (region, tmp_region); - cairo_region_destroy (tmp_region); - - cairo_region_translate (region, - frame_area.x, - frame_area.y); -} - -static void -subtract_client_area (cairo_region_t *region, - MetaUIFrame *frame) +clip_region_to_visible_frame_border (cairo_region_t *region, + MetaUIFrame *frame) { cairo_rectangle_int_t area; + cairo_region_t *frame_border; MetaFrameFlags flags; MetaFrameType type; MetaFrameBorders borders; - cairo_region_t *tmp_region; Display *display; + int frame_width, frame_height; display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); meta_core_get (display, frame->xwindow, META_CORE_GET_FRAME_FLAGS, &flags, META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_CLIENT_WIDTH, &area.width, - META_CORE_GET_CLIENT_HEIGHT, &area.height, + META_CORE_GET_FRAME_WIDTH, &frame_width, + META_CORE_GET_FRAME_HEIGHT, &frame_height, META_CORE_GET_END); + meta_theme_get_frame_borders (meta_theme_get_current (), type, frame->text_height, flags, &borders); - area.x = borders.total.left; - area.y = borders.total.top; + /* Visible frame rect */ + area.x = borders.invisible.left; + area.y = borders.invisible.top; + area.width = frame_width - borders.invisible.left - borders.invisible.right; + area.height = frame_height - borders.invisible.top - borders.invisible.bottom; - tmp_region = cairo_region_create_rectangle (&area); - cairo_region_subtract (region, tmp_region); - cairo_region_destroy (tmp_region); -} + frame_border = cairo_region_create_rectangle (&area); -static void -cached_pixels_draw (CachedPixels *pixels, - cairo_t *cr, - cairo_region_t *region) -{ - cairo_region_t *region_piece; - int i; + /* Client rect */ + area.x += borders.visible.left; + area.y += borders.visible.top; + area.width -= borders.visible.left + borders.visible.right; + area.height -= borders.visible.top + borders.visible.bottom; - for (i = 0; i < 4; i++) - { - CachedFramePiece *piece; - piece = &pixels->piece[i]; - - if (piece->pixmap) - { - cairo_set_source_surface (cr, piece->pixmap, - piece->rect.x, piece->rect.y); - cairo_paint (cr); - - region_piece = cairo_region_create_rectangle (&piece->rect); - cairo_region_subtract (region, region_piece); - cairo_region_destroy (region_piece); - } - } + /* Visible frame border */ + cairo_region_subtract_rectangle (frame_border, &area); + cairo_region_intersect (region, frame_border); + + cairo_region_destroy (frame_border); } static gboolean @@ -2123,10 +1863,8 @@ meta_frames_draw (GtkWidget *widget, { MetaUIFrame *frame; MetaFrames *frames; - CachedPixels *pixels; - cairo_region_t *region; cairo_rectangle_int_t clip; - int i, n_areas; + cairo_region_t *region; cairo_surface_t *target; frames = META_FRAMES (widget); @@ -2138,40 +1876,23 @@ meta_frames_draw (GtkWidget *widget, if (frame == NULL) return FALSE; - populate_cache (frames, frame); - region = cairo_region_create_rectangle (&clip); - - pixels = get_cache (frames, frame); + clip_region_to_visible_frame_border (region, frame); - cached_pixels_draw (pixels, cr, region); - - clip_to_screen (region, frame); - subtract_client_area (region, frame); + if (cairo_region_is_empty (region)) + goto out; - n_areas = cairo_region_num_rectangles (region); + gdk_cairo_region (cr, region); + cairo_clip (cr); - for (i = 0; i < n_areas; i++) - { - cairo_rectangle_int_t area; + cairo_save (cr); + setup_bg_cr (cr, frame->window, 0, 0); + cairo_paint (cr); + cairo_restore (cr); - cairo_region_get_rectangle (region, i, &area); - - cairo_save (cr); - - cairo_rectangle (cr, area.x, area.y, area.width, area.height); - cairo_clip (cr); - - cairo_push_group (cr); - - meta_frames_paint (frames, frame, cr); - - cairo_pop_group_to_source (cr); - cairo_paint (cr); - - cairo_restore (cr); - } + meta_frames_paint (frames, frame, cr); + out: cairo_region_destroy (region); return TRUE; @@ -2615,5 +2336,4 @@ invalidate_whole_window (MetaFrames *frames, MetaUIFrame *frame) { gdk_window_invalidate_rect (frame->window, NULL, FALSE); - invalidate_cache (frames, frame); } diff --git a/src/ui/frames.h b/src/ui/frames.h index b42c65104..be238a84b 100644 --- a/src/ui/frames.h +++ b/src/ui/frames.h @@ -97,10 +97,6 @@ struct _MetaFrames GtkStyleContext *normal_style; GHashTable *style_variants; - - int invalidate_cache_timeout_id; - GList *invalidate_frames; - GHashTable *cache; }; struct _MetaFramesClass