summaryrefslogtreecommitdiff
path: root/src/cwindow.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cwindow.c')
-rw-r--r--src/cwindow.c274
1 files changed, 157 insertions, 117 deletions
diff --git a/src/cwindow.c b/src/cwindow.c
index 5baecfd4..9d7470c5 100644
--- a/src/cwindow.c
+++ b/src/cwindow.c
@@ -3,8 +3,28 @@
#include "errors.h"
#include "compositor.h"
#include "matrix.h"
+#include <X11/extensions/Xcomposite.h>
#define SHADOW_OFFSET 3
+
+typedef struct Geometry Geometry;
+typedef struct FreezeInfo FreezeInfo;
+
+struct Geometry
+{
+ int x;
+ int y;
+ int width;
+ int height;
+ int border_width;
+};
+
+struct FreezeInfo
+{
+ Geometry geometry;
+ Pixmap pixmap;
+};
+
/* Unlike MetaWindow, there's one of these for _all_ toplevel windows,
* override redirect or not. We also track unmapped windows as
* otherwise on window map we'd have to determine where the
@@ -18,25 +38,15 @@ struct CWindow
#ifdef HAVE_COMPOSITE_EXTENSIONS
MetaCompositor *compositor;
-
- int x;
- int y;
- int width;
- int height;
- int border_width;
-
- int pending_x;
- int pending_y;
- int pending_width;
- int pending_height;
- int pending_border_width;
+
+ Geometry geometry;
Damage damage;
XserverRegion last_painted_extents;
XserverRegion border_size;
-
- Pixmap pixmap;
+
+ FreezeInfo *freeze_info;
unsigned int managed : 1;
unsigned int damaged : 1;
@@ -67,10 +77,11 @@ cwindow_free (CWindow *cwindow)
XDamageDestroy (cwindow_get_xdisplay (cwindow), cwindow->damage);
/* Free our window pixmap name */
- if (cwindow->pixmap != None)
- XFreePixmap (cwindow_get_xdisplay (cwindow),
- cwindow->pixmap);
- meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+ if (cwindow->freeze_info)
+ cwindow_thaw (cwindow);
+
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor),
+ FALSE);
g_free (cwindow);
}
@@ -80,12 +91,18 @@ cwindow_free (CWindow *cwindow)
XserverRegion
cwindow_extents (CWindow *cwindow)
{
+ Geometry *geometry;
XRectangle r;
+
+ if (cwindow->freeze_info)
+ geometry = &cwindow->freeze_info->geometry;
+ else
+ geometry = &cwindow->geometry;
- r.x = cwindow->x;
- r.y = cwindow->y;
- r.width = cwindow->width;
- r.height = cwindow->height;
+ r.x = geometry->x;
+ r.y = geometry->y;
+ r.width = geometry->width;
+ r.height = geometry->height;
r.width += SHADOW_OFFSET;
r.height += SHADOW_OFFSET;
@@ -98,10 +115,17 @@ XserverRegion
cwindow_get_opaque_region (CWindow *cwindow)
{
XRectangle rect;
- rect.x = cwindow->x;
- rect.y = cwindow->y;
- rect.width = cwindow->width;
- rect.height = cwindow->height;
+ Geometry *geometry;
+
+ if (cwindow->freeze_info)
+ geometry = &cwindow->freeze_info->geometry;
+ else
+ geometry = &cwindow->geometry;
+
+ rect.x = geometry->x;
+ rect.y = geometry->y;
+ rect.width = geometry->width;
+ rect.height = geometry->height;
return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &rect, 1);
}
@@ -109,10 +133,14 @@ cwindow_get_opaque_region (CWindow *cwindow)
Drawable
cwindow_get_drawable (CWindow *cwindow)
{
- if (cwindow->pixmap)
- return cwindow->pixmap;
+ if (cwindow->freeze_info)
+ {
+ return cwindow->freeze_info->pixmap;
+ }
else
- return cwindow->xwindow;
+ {
+ return cwindow->xwindow;
+ }
}
void
@@ -158,7 +186,9 @@ cwindow_get_screen (CWindow *cwindow)
}
CWindow *
-cwindow_new (MetaCompositor *compositor, Window xwindow, XWindowAttributes *attrs)
+cwindow_new (MetaCompositor *compositor,
+ Window xwindow,
+ XWindowAttributes *attrs)
{
CWindow *cwindow;
Damage damage;
@@ -178,11 +208,14 @@ cwindow_new (MetaCompositor *compositor, Window xwindow, XWindowAttributes *attr
cwindow->xwindow = xwindow;
cwindow->screen_index = XScreenNumberOfScreen (attrs->screen);
cwindow->damage = damage;
- cwindow->x = attrs->x;
- cwindow->y = attrs->y;
- cwindow->width = attrs->width;
- cwindow->height = attrs->height;
- cwindow->border_width = attrs->border_width;
+
+ cwindow->freeze_info = NULL;
+
+ cwindow->geometry.x = attrs->x;
+ cwindow->geometry.y = attrs->y;
+ cwindow->geometry.width = attrs->width;
+ cwindow->geometry.height = attrs->height;
+ cwindow->geometry.border_width = attrs->border_width;
if (attrs->class == InputOnly)
cwindow->input_only = TRUE;
@@ -191,16 +224,6 @@ cwindow_new (MetaCompositor *compositor, Window xwindow, XWindowAttributes *attr
cwindow->visual = attrs->visual;
-#if 0
- if (compositor->have_name_window_pixmap)
- {
- meta_error_trap_push (meta_compositor_get_display (compositor));
- cwindow->pixmap = XCompositeNameWindowPixmap (meta_compositor_get_display (compositor)->xdisplay,
- cwindow->xwindow);
- meta_error_trap_pop (meta_compositor_get_display (compositor), FALSE);
- }
-#endif
-
/* viewable == mapped for the root window, since root can't be unmapped */
cwindow->viewable = (attrs->map_state == IsViewable);
@@ -254,31 +277,31 @@ cwindow_get_last_painted_extents (CWindow *cwindow)
int
cwindow_get_x (CWindow *cwindow)
{
- return cwindow->x;
+ return cwindow->geometry.x;
}
int
cwindow_get_y (CWindow *cwindow)
{
- return cwindow->y;
+ return cwindow->geometry.y;
}
int
cwindow_get_width (CWindow *cwindow)
{
- return cwindow->width;
+ return cwindow->geometry.width;
}
int
cwindow_get_height (CWindow *cwindow)
{
- return cwindow->height;
+ return cwindow->geometry.height;
}
int
cwindow_get_border_width (CWindow *cwindow)
{
- return cwindow->border_width;
+ return cwindow->geometry.border_width;
}
Damage
@@ -287,12 +310,6 @@ cwindow_get_damage (CWindow *cwindow)
return cwindow->damage;
}
-Pixmap
-cwindow_get_pixmap (CWindow *cwindow)
-{
- return cwindow->pixmap;
-}
-
MetaCompositor *
cwindow_get_compositor (CWindow *cwindow)
{
@@ -300,57 +317,27 @@ cwindow_get_compositor (CWindow *cwindow)
}
void
-cwindow_set_pending_x (CWindow *cwindow, int pending_x)
-{
- cwindow->pending_x = pending_x;
-}
-
-void
-cwindow_set_pending_y (CWindow *cwindow, int pending_y)
-{
- cwindow->pending_y = pending_y;
-}
-
-void
-cwindow_set_pending_width (CWindow *cwindow, int pending_width)
-{
- cwindow->pending_width = pending_width;
-}
-
-void
-cwindow_set_pending_height (CWindow *cwindow, int pending_height)
-{
- cwindow->pending_height = pending_height;
-}
-
-void
-cwindow_set_pending_border_width (CWindow *cwindow, int pending_border_width)
-{
- cwindow->pending_border_width = pending_border_width;
-}
-
-void
cwindow_set_x (CWindow *cwindow, int x)
{
- cwindow->x = x;
+ cwindow->geometry.x = x;
}
void
cwindow_set_y (CWindow *cwindow, int y)
{
- cwindow->y = y;
+ cwindow->geometry.y = y;
}
void
cwindow_set_width (CWindow *cwindow, int width)
{
- cwindow->width = width;
+ cwindow->geometry.width = width;
}
void
cwindow_set_height (CWindow *cwindow, int height)
{
- cwindow->height = height;
+ cwindow->geometry.height = height;
}
@@ -364,7 +351,7 @@ cwindow_set_viewable (CWindow *cwindow, gboolean viewable)
void
cwindow_set_border_width (CWindow *cwindow, int border_width)
{
- cwindow->border_width = border_width;
+ cwindow->geometry.border_width = border_width;
}
static XFixed
@@ -735,7 +722,7 @@ cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event)
XserverRegion region;
MetaScreen *screen;
MetaWindow *window;
-
+
window = meta_display_lookup_x_window (meta_compositor_get_display (cwindow->compositor),
cwindow_get_xwindow (cwindow));
#if 0
@@ -762,7 +749,11 @@ cwindow_process_damage_notify (CWindow *cwindow, XDamageNotifyEvent *event)
screen = cwindow_get_screen (cwindow);
- meta_compositor_invalidate_region (cwindow->compositor, screen, region);
+ if (!cwindow->freeze_info)
+ {
+ /* ignore damage on frozen window */
+ meta_compositor_invalidate_region (cwindow->compositor, screen, region);
+ }
XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
}
@@ -775,31 +766,23 @@ cwindow_process_configure_notify (CWindow *cwindow, XConfigureEvent *event)
screen = cwindow_get_screen (cwindow);
- if (cwindow_get_last_painted_extents (cwindow))
+ if (cwindow_get_last_painted_extents (cwindow) && !cwindow->freeze_info)
{
meta_compositor_invalidate_region (cwindow->compositor, screen, cwindow_get_last_painted_extents (cwindow));
cwindow_set_last_painted_extents (cwindow, None);
}
- if (cwindow_get_pixmap (cwindow))
- {
- cwindow_set_pending_x (cwindow, event->x);
- cwindow_set_pending_y (cwindow, event->y);
- cwindow_set_pending_width (cwindow, event->width);
- cwindow_set_pending_height (cwindow, event->height);
- cwindow_set_pending_border_width (cwindow, event->border_width);
- }
- else
- {
- cwindow_set_x (cwindow, event->x);
- cwindow_set_y (cwindow, event->y);
- cwindow_set_width (cwindow, event->width);
- cwindow_set_height (cwindow, event->height);
- cwindow_set_border_width (cwindow, event->border_width);
- }
+ cwindow_set_x (cwindow, event->x);
+ cwindow_set_y (cwindow, event->y);
+ cwindow_set_width (cwindow, event->width);
+ cwindow_set_height (cwindow, event->height);
+ cwindow_set_border_width (cwindow, event->border_width);
- region = cwindow_extents (cwindow);
+ if (cwindow->freeze_info)
+ return;
+ region = cwindow_extents (cwindow);
+
meta_compositor_invalidate_region (cwindow->compositor,
screen,
region);
@@ -827,6 +810,59 @@ cwindow_set_transformation (CWindow *cwindow,
}
void
+cwindow_freeze (CWindow *cwindow)
+{
+ if (cwindow->freeze_info)
+ {
+ meta_print_backtrace();
+ return;
+ }
+
+ meta_error_trap_push (meta_compositor_get_display (cwindow->compositor));
+
+ cwindow->freeze_info = g_new (FreezeInfo, 1);
+ cwindow->freeze_info->geometry = cwindow->geometry;
+
+ cwindow->freeze_info->pixmap =
+ XCompositeNameWindowPixmap (cwindow_get_xdisplay (cwindow),
+ cwindow->xwindow);
+
+ meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE);
+}
+
+void
+cwindow_thaw (CWindow *cwindow)
+{
+ XserverRegion region;
+ if (!cwindow->freeze_info)
+ return;
+
+ if (cwindow_get_last_painted_extents (cwindow))
+ {
+ meta_compositor_invalidate_region (cwindow->compositor, cwindow_get_screen (cwindow),
+ cwindow_get_last_painted_extents (cwindow));
+ cwindow_set_last_painted_extents (cwindow, None);
+ }
+
+
+ if (cwindow->freeze_info->pixmap)
+ XFreePixmap (cwindow_get_xdisplay (cwindow),
+ cwindow->freeze_info->pixmap);
+
+ g_free (cwindow->freeze_info);
+ cwindow->freeze_info = NULL;
+
+ region = cwindow_extents (cwindow);
+
+ meta_compositor_invalidate_region (cwindow->compositor,
+ cwindow_get_screen (cwindow),
+ region);
+
+ XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region);
+
+}
+
+void
cwindow_draw (CWindow *cwindow, Picture destination)
{
XRenderPictFormat *format;
@@ -880,6 +916,10 @@ cwindow_draw (CWindow *cwindow, Picture destination)
else
{
Display *dpy = cwindow_get_xdisplay (cwindow);
+ Geometry *geometry = cwindow->freeze_info?
+ &cwindow->freeze_info->geometry :
+ &cwindow->geometry;
+
XRenderColor shadow_color = { 0x0000, 0x000, 0x0000, 0x70c0 };
XserverRegion shadow_clip;
XserverRegion old_clip = XFixesCreateRegionFromPicture (dpy, destination);
@@ -895,8 +935,8 @@ cwindow_draw (CWindow *cwindow, Picture destination)
PictOpOver,
destination,
&shadow_color,
- cwindow->x + SHADOW_OFFSET, cwindow->y + SHADOW_OFFSET,
- cwindow->width, cwindow->height);
+ geometry->x + SHADOW_OFFSET, geometry->y + SHADOW_OFFSET,
+ geometry->width, geometry->height);
XFixesSetPictureClipRegion (dpy, destination, 0, 0, old_clip);
@@ -906,10 +946,10 @@ cwindow_draw (CWindow *cwindow, Picture destination)
None,
destination,
0, 0, 0, 0,
- cwindow->x,
- cwindow->y,
- cwindow->width,
- cwindow->height);
+ geometry->x,
+ geometry->y,
+ geometry->width,
+ geometry->height);
XFixesDestroyRegion (dpy, old_clip);
XFixesDestroyRegion (dpy, shadow_clip);