summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compositor.c296
-rw-r--r--src/compositor.h2
-rw-r--r--src/display.c60
-rw-r--r--src/main.c6
-rw-r--r--src/screen.c5
-rw-r--r--src/screen.h2
-rw-r--r--src/ui.h6
7 files changed, 319 insertions, 58 deletions
diff --git a/src/compositor.c b/src/compositor.c
index d10ee77c6..8d986677a 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -24,6 +24,8 @@
#include "compositor.h"
#include "screen.h"
#include "errors.h"
+#include "window.h"
+#include "frame.h"
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include <X11/extensions/Xcomposite.h>
@@ -32,6 +34,9 @@
#endif /* HAVE_COMPOSITE_EXTENSIONS */
+#define SHADOW_OFFSET 3
+#define FRAME_INTERVAL_MILLISECONDS ((int)(1000.0/40.0))
+
/* 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
@@ -82,6 +87,7 @@ struct MetaCompositor
GHashTable *window_hash;
guint repair_idle;
+ guint repair_timeout;
guint enabled : 1;
guint have_composite : 1;
@@ -94,8 +100,15 @@ struct MetaCompositor
static void
meta_compositor_window_free (MetaCompositorWindow *cwindow)
{
+ g_assert (cwindow->damage != None);
+
+ /* This seems to cause an error if the window
+ * is destroyed?
+ */
+ meta_error_trap_push (cwindow->compositor->display);
XDamageDestroy (cwindow->compositor->display->xdisplay,
cwindow->damage);
+ meta_error_trap_pop (cwindow->compositor->display, FALSE);
g_free (cwindow);
}
@@ -209,6 +222,12 @@ remove_repair_idle (MetaCompositor *compositor)
g_source_remove (compositor->repair_idle);
compositor->repair_idle = 0;
}
+
+ if (compositor->repair_timeout != 0)
+ {
+ g_source_remove (compositor->repair_timeout);
+ compositor->repair_timeout = 0;
+ }
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -239,6 +258,9 @@ window_extents (MetaCompositorWindow *cwindow)
r.width = cwindow->width;
r.height = cwindow->height;
+ r.width += SHADOW_OFFSET;
+ r.height += SHADOW_OFFSET;
+
return XFixesCreateRegion (cwindow->compositor->display->xdisplay, &r, 1);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -255,7 +277,13 @@ paint_screen (MetaCompositor *compositor,
Display *xdisplay;
XRenderPictFormat *format;
GList *tmp;
+ GC gc;
+
+ meta_verbose ("Repainting screen %d root 0x%lx\n",
+ screen->number, screen->xroot);
+ meta_display_grab (screen->display);
+
xdisplay = screen->display->xdisplay;
if (damage_region == None)
@@ -272,17 +300,23 @@ paint_screen (MetaCompositor *compositor,
else
{
region = XFixesCreateRegion (xdisplay, NULL, 0);
-
+
XFixesCopyRegion (compositor->display->xdisplay,
region,
damage_region);
}
- buffer_pixmap = XCreatePixmap (xdisplay, None,
+ buffer_pixmap = XCreatePixmap (xdisplay, screen->xroot,
screen->width,
screen->height,
DefaultDepth (xdisplay,
screen->number));
+
+ gc = XCreateGC (xdisplay, buffer_pixmap, 0, NULL);
+ XSetForeground (xdisplay, gc, WhitePixel (xdisplay, screen->number));
+ XFixesSetGCClipRegion (xdisplay, gc, 0, 0, region);
+ XFillRectangle (xdisplay, buffer_pixmap, gc, 0, 0,
+ screen->width, screen->height);
format = XRenderFindVisualFormat (xdisplay,
DefaultVisual (xdisplay,
@@ -293,16 +327,25 @@ paint_screen (MetaCompositor *compositor,
format,
0, 0);
- /* set clip on the root window */
+ /* set clip */
XFixesSetPictureClipRegion (xdisplay,
- screen->root_picture, 0, 0, region);
+ buffer_picture, 0, 0,
+ region);
/* draw windows from bottom to top */
+
meta_error_trap_push (compositor->display);
tmp = g_list_last (screen->compositor_windows);
while (tmp != NULL)
{
MetaCompositorWindow *cwindow = tmp->data;
+ XRenderColor shadow_color;
+ MetaWindow *window;
+
+ shadow_color.red = 0;
+ shadow_color.green = 0;
+ shadow_color.blue = 0;
+ shadow_color.alpha = 0x90c0;
if (cwindow->picture == None) /* InputOnly */
goto next;
@@ -312,22 +355,56 @@ paint_screen (MetaCompositor *compositor,
cwindow->last_painted_extents);
cwindow->last_painted_extents = window_extents (cwindow);
-
- XFixesSetPictureClipRegion (xdisplay,
- buffer_picture, 0, 0,
- region);
/* XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); */
+
+ meta_verbose (" Compositing window 0x%lx %d,%d %dx%d\n",
+ cwindow->xwindow,
+ cwindow->x, cwindow->y,
+ cwindow->width, cwindow->height);
- XRenderComposite (xdisplay,
- PictOpSrc, /* PictOpOver for alpha */
- cwindow->picture,
- None, buffer_picture,
- 0, 0, 0, 0,
- cwindow->x + cwindow->border_width,
- cwindow->y + cwindow->border_width,
- cwindow->width,
- cwindow->height);
+ window = meta_display_lookup_x_window (compositor->display,
+ cwindow->xwindow);
+ if (window != NULL &&
+ window == compositor->display->grab_window &&
+ (meta_grab_op_is_resizing (compositor->display->grab_op) ||
+ meta_grab_op_is_moving (compositor->display->grab_op)))
+ {
+ /* Draw window transparent while resizing */
+ XRenderComposite (xdisplay,
+ PictOpOver, /* PictOpOver for alpha, PictOpSrc without */
+ cwindow->picture,
+ screen->trans_picture,
+ buffer_picture,
+ 0, 0, 0, 0,
+ cwindow->x + cwindow->border_width,
+ cwindow->y + cwindow->border_width,
+ cwindow->width,
+ cwindow->height);
+ }
+ else
+ {
+ /* Draw window normally */
+
+ /* superlame drop shadow */
+ XRenderFillRectangle (xdisplay, PictOpOver,
+ buffer_picture,
+ &shadow_color,
+ cwindow->x + SHADOW_OFFSET,
+ cwindow->y + SHADOW_OFFSET,
+ cwindow->width, cwindow->height);
+
+ XRenderComposite (xdisplay,
+ PictOpSrc, /* PictOpOver for alpha, PictOpSrc without */
+ cwindow->picture,
+ None,
+ buffer_picture,
+ 0, 0, 0, 0,
+ cwindow->x + cwindow->border_width,
+ cwindow->y + cwindow->border_width,
+ cwindow->width,
+ cwindow->height);
+ }
next:
tmp = tmp->prev;
@@ -335,8 +412,16 @@ paint_screen (MetaCompositor *compositor,
meta_error_trap_pop (compositor->display, FALSE);
/* Copy buffer to root window */
+ meta_verbose ("Copying buffer to root window 0x%lx picture 0x%lx\n",
+ screen->xroot, screen->root_picture);
+
+#if 1
+ XFixesSetPictureClipRegion (xdisplay,
+ screen->root_picture,
+ 0, 0, region);
+#endif
- XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None);
+ /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */
XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None,
screen->root_picture,
0, 0, 0, 0, 0, 0,
@@ -345,17 +430,18 @@ paint_screen (MetaCompositor *compositor,
XFixesDestroyRegion (xdisplay, region);
XFreePixmap (xdisplay, buffer_pixmap);
XRenderFreePicture (xdisplay, buffer_picture);
+ XFreeGC (xdisplay, gc);
+
+ meta_display_ungrab (screen->display);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_COMPOSITE_EXTENSIONS
-static gboolean
-repair_idle_func (void *data)
+static void
+do_repair (MetaCompositor *compositor)
{
GSList *tmp;
- MetaCompositor *compositor = data;
-
tmp = compositor->display->screens;
while (tmp != NULL)
{
@@ -373,7 +459,32 @@ repair_idle_func (void *data)
tmp = tmp->next;
}
+ remove_repair_idle (compositor);
+}
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
+
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+static gboolean
+repair_idle_func (void *data)
+{
+ MetaCompositor *compositor = data;
+
compositor->repair_idle = 0;
+ do_repair (compositor);
+
+ return FALSE;
+}
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
+
+
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+static gboolean
+repair_timeout_func (void *data)
+{
+ MetaCompositor *compositor = data;
+
+ compositor->repair_timeout = 0;
+ do_repair (compositor);
return FALSE;
}
@@ -412,8 +523,11 @@ ensure_repair_idle (MetaCompositor *compositor)
{
if (compositor->repair_idle != 0)
return;
-
- compositor->repair_idle = g_idle_add (repair_idle_func, compositor);
+
+ compositor->repair_idle = g_idle_add_full (META_PRIORITY_COMPOSITE,
+ repair_idle_func, compositor, NULL);
+ compositor->repair_timeout = g_timeout_add (FRAME_INTERVAL_MILLISECONDS,
+ repair_timeout_func, compositor);
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
@@ -425,9 +539,9 @@ merge_and_destroy_damage_region (MetaCompositor *compositor,
{
if (screen->damage_region != None)
{
- XFixesCopyRegion (compositor->display->xdisplay,
- screen->damage_region,
- region);
+ XFixesUnionRegion (compositor->display->xdisplay,
+ screen->damage_region,
+ region, screen->damage_region);
XFixesDestroyRegion (compositor->display->xdisplay,
region);
}
@@ -450,9 +564,9 @@ merge_damage_region (MetaCompositor *compositor,
screen->damage_region =
XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
- XFixesCopyRegion (compositor->display->xdisplay,
- screen->damage_region,
- region);
+ XFixesUnionRegion (compositor->display->xdisplay,
+ screen->damage_region,
+ region, screen->damage_region);
ensure_repair_idle (compositor);
}
@@ -474,9 +588,13 @@ process_damage_notify (MetaCompositor *compositor,
region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0);
- /* translate region to screen */
+ /* translate region to screen; can error if window of damage is
+ * destroyed
+ */
+ meta_error_trap_push (compositor->display);
XDamageSubtract (compositor->display->xdisplay,
cwindow->damage, None, region);
+ meta_error_trap_pop (compositor->display, FALSE);
XFixesTranslateRegion (compositor->display->xdisplay,
region,
@@ -509,9 +627,10 @@ process_configure_notify (MetaCompositor *compositor,
if (cwindow->last_painted_extents)
{
- merge_damage_region (compositor,
- screen,
- cwindow->last_painted_extents);
+ merge_and_destroy_damage_region (compositor,
+ screen,
+ cwindow->last_painted_extents);
+ cwindow->last_painted_extents = None;
}
cwindow->x = event->x;
@@ -575,6 +694,32 @@ process_configure_notify (MetaCompositor *compositor,
}
#endif /* HAVE_COMPOSITE_EXTENSIONS */
+
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+static void
+process_expose (MetaCompositor *compositor,
+ XExposeEvent *event)
+{
+ XserverRegion region;
+ MetaScreen *screen;
+ XRectangle r;
+
+ screen = meta_display_screen_for_root (compositor->display,
+ event->window);
+
+ if (screen == NULL || screen->root_picture == None)
+ return;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = screen->width;
+ r.height = screen->height;
+ region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1);
+
+ merge_and_destroy_damage_region (compositor, screen, region);
+}
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
+
void
meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
@@ -594,6 +739,11 @@ meta_compositor_process_event (MetaCompositor *compositor,
process_configure_notify (compositor,
(XConfigureEvent*) event);
}
+ else if (event->type == Expose)
+ {
+ process_expose (compositor,
+ (XExposeEvent*) event);
+ }
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -611,6 +761,7 @@ meta_compositor_add_window (MetaCompositor *compositor,
Damage damage;
XRenderPictFormat *format;
XRenderPictureAttributes pa;
+ XserverRegion region;
if (!compositor->enabled)
return; /* no extension */
@@ -666,9 +817,15 @@ meta_compositor_add_window (MetaCompositor *compositor,
&cwindow->xwindow, cwindow);
/* assume cwindow is at the top of the stack */
+ /* FIXME this is wrong, switch workspaces to see an example;
+ * in fact we map windows up from the bottom
+ */
screen->compositor_windows = g_list_prepend (screen->compositor_windows,
cwindow);
-
+
+ /* schedule paint of the new window */
+ region = window_extents (cwindow);
+ merge_and_destroy_damage_region (compositor, screen, region);
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -715,6 +872,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
{
#ifdef HAVE_COMPOSITE_EXTENSIONS
XRenderPictureAttributes pa;
+ XRectangle r;
+ XRenderColor c;
if (!compositor->enabled)
return; /* no extension */
@@ -731,7 +890,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
XCompositeRedirectSubwindows (screen->display->xdisplay,
screen->xroot,
CompositeRedirectManual);
- g_print ("Subwindows redirected\n");
+ meta_verbose ("Subwindows redirected, we are now the compositing manager\n");
pa.subwindow_mode = IncludeInferiors;
@@ -745,6 +904,35 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
&pa);
g_assert (screen->root_picture != None);
+
+ screen->trans_pixmap = XCreatePixmap (compositor->display->xdisplay,
+ screen->xroot, 1, 1, 8);
+
+ pa.repeat = True;
+ screen->trans_picture =
+ XRenderCreatePicture (compositor->display->xdisplay,
+ screen->trans_pixmap,
+ XRenderFindStandardFormat (compositor->display->xdisplay,
+ PictStandardA8),
+ CPRepeat,
+ &pa);
+
+ c.red = c.green = c.blue = 0;
+ c.alpha = 0xc0c0;
+ XRenderFillRectangle (compositor->display->xdisplay,
+ PictOpSrc,
+ screen->trans_picture, &c, 0, 0, 1, 1);
+
+ /* Damage the whole screen */
+ r.x = 0;
+ r.y = 0;
+ r.width = screen->width;
+ r.height = screen->height;
+
+ merge_and_destroy_damage_region (compositor,
+ screen,
+ XFixesCreateRegion (compositor->display->xdisplay,
+ &r, 1));
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
@@ -760,6 +948,12 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
XRenderFreePicture (screen->display->xdisplay,
screen->root_picture);
screen->root_picture = None;
+ XRenderFreePicture (screen->display->xdisplay,
+ screen->trans_picture);
+ screen->trans_picture = None;
+ XFreePixmap (screen->display->xdisplay,
+ screen->trans_pixmap);
+ screen->trans_pixmap = None;
while (screen->compositor_windows != NULL)
{
@@ -770,6 +964,36 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
#endif /* HAVE_COMPOSITE_EXTENSIONS */
}
+void
+meta_compositor_damage_window (MetaCompositor *compositor,
+ MetaWindow *window)
+{
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+ Window xwindow;
+ MetaCompositorWindow *cwindow;
+
+ if (!compositor->enabled)
+ return;
+
+ if (window->screen->root_picture == None)
+ return;
+
+ if (window->frame)
+ xwindow = window->frame->xwindow;
+ else
+ xwindow = window->xwindow;
+
+ cwindow = g_hash_table_lookup (compositor->window_hash,
+ &xwindow);
+ if (cwindow == NULL)
+ return;
+
+ merge_and_destroy_damage_region (compositor,
+ window->screen,
+ window_extents (cwindow));
+#endif /* HAVE_COMPOSITE_EXTENSIONS */
+}
+
diff --git a/src/compositor.h b/src/compositor.h
index 48be7b11c..d1e824b33 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -41,6 +41,8 @@ void meta_compositor_manage_screen (MetaCompositor *compositor,
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen);
+void meta_compositor_damage_window (MetaCompositor *compositor,
+ MetaWindow *window);
#endif /* META_COMPOSITOR_H */
diff --git a/src/display.c b/src/display.c
index bbfba65bf..4ff003275 100644
--- a/src/display.c
+++ b/src/display.c
@@ -1738,26 +1738,33 @@ event_callback (XEvent *event,
break;
case MapNotify:
{
- /* If a window becomes viewable, then we need to
- * add it to the compositor
+ /* If a window becomes viewable and is a child of the root,
+ * then we need to add it to the compositor. If the window
+ * has a frame we definitely don't want to add it, it's
+ * just being mapped inside the frame.
*/
- XWindowAttributes attrs;
-
- meta_error_trap_push_with_return (display);
-
- XGetWindowAttributes (display->xdisplay,
- modified, &attrs);
-
- if (meta_error_trap_pop_with_return (display, TRUE) != Success)
+ if (window == NULL ||
+ (window && window->frame == NULL) ||
+ frame_was_receiver)
{
- meta_verbose ("Failed to get attributes for window 0x%lx\n",
- modified);
- }
- else
- {
- if (attrs.map_state == IsViewable)
- meta_compositor_add_window (display->compositor,
- modified, &attrs);
+ XWindowAttributes attrs;
+
+ meta_error_trap_push_with_return (display);
+
+ XGetWindowAttributes (display->xdisplay,
+ modified, &attrs);
+
+ if (meta_error_trap_pop_with_return (display, TRUE) != Success)
+ {
+ meta_verbose ("Failed to get attributes for window 0x%lx\n",
+ modified);
+ }
+ else
+ {
+ if (attrs.map_state == IsViewable)
+ meta_compositor_add_window (display->compositor,
+ modified, &attrs);
+ }
}
}
break;
@@ -3078,7 +3085,15 @@ meta_display_begin_grab_op (MetaDisplay *display,
}
if (display->grab_window)
- meta_window_refresh_resize_popup (display->grab_window);
+ {
+ meta_window_refresh_resize_popup (display->grab_window);
+
+ /* repaint window in case we draw it differently
+ * when grabbed
+ */
+ meta_compositor_damage_window (display->compositor,
+ display->grab_window);
+ }
return TRUE;
}
@@ -3152,6 +3167,13 @@ meta_display_end_grab_op (MetaDisplay *display,
display->grab_wireframe_rect.height);
meta_window_calc_showing (display->grab_window);
}
+
+ /* repaint window in case the grab op drew it in a
+ * nonstandard way such as transparent or wireframe
+ */
+ if (display->grab_window != NULL)
+ meta_compositor_damage_window (display->compositor,
+ display->grab_window);
display->grab_window = NULL;
display->grab_screen = NULL;
diff --git a/src/main.c b/src/main.c
index ef8218beb..a65643c2e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -378,7 +378,11 @@ main (int argc, char **argv)
#else
meta_verbose ("Compiled without startup notification\n");
#endif
-
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+ meta_verbose ("Compiled with composite extensions\n");
+#else
+ meta_verbose ("Compiled without composite extensions\n");
+#endif
/* Load prefs */
meta_prefs_init ();
diff --git a/src/screen.c b/src/screen.c
index 9f7741cc0..2af481fff 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -502,6 +502,9 @@ meta_screen_new (MetaDisplay *display,
LeaveWindowMask | EnterWindowMask |
KeyPressMask | KeyReleaseMask |
FocusChangeMask | StructureNotifyMask |
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+ ExposureMask |
+#endif
attr.your_event_mask);
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
{
@@ -546,6 +549,8 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_windows = NULL;
screen->damage_region = None;
screen->root_picture = None;
+ screen->trans_pixmap = None;
+ screen->trans_picture = None;
{
XGCValues gc_values;
diff --git a/src/screen.h b/src/screen.h
index 9428cf84c..3a938a108 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -118,6 +118,8 @@ struct _MetaScreen
GList *compositor_windows;
XID root_picture;
XID damage_region;
+ XID trans_pixmap;
+ XID trans_picture;
};
MetaScreen* meta_screen_new (MetaDisplay *display,
diff --git a/src/ui.h b/src/ui.h
index f4cb8d0fd..3740d870f 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -29,8 +29,10 @@
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
-/* This is between GTK_PRIORITY_RESIZE and GTK_PRIORITY_REDRAW */
-#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15)
+/* This is between GTK_PRIORITY_RESIZE (+10) and GTK_PRIORITY_REDRAW (+20) */
+#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15)
+/* lower than GTK_PRIORITY_REDRAW */
+#define META_PRIORITY_COMPOSITE (G_PRIORITY_HIGH_IDLE + 25)
typedef struct _MetaUI MetaUI;