diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/compositor.c | 1221 | ||||
-rw-r--r-- | src/compositor.h | 23 | ||||
-rw-r--r-- | src/cwindow.c | 902 | ||||
-rw-r--r-- | src/cwindow.h | 106 | ||||
-rw-r--r-- | src/effects.c | 4 | ||||
-rw-r--r-- | src/matrix.c | 615 | ||||
-rw-r--r-- | src/matrix.h | 118 | ||||
-rw-r--r-- | src/screen.c | 16 | ||||
-rw-r--r-- | src/ui.c | 2 | ||||
-rw-r--r-- | src/window.c | 23 |
13 files changed, 2490 insertions, 572 deletions
@@ -1,3 +1,11 @@ +Thu Jan 13 18:43:17 2005 Søren Sandmann <sandmann@redhat.com> + + * Initial check-in of changes to compositing manager. New files: + matrix.[ch] matrix manipulation from The Gimp + cwindow.[ch] the CWindow class + + It is not yet very smooth or spiffy, and it is not snappy at all. + 2005-01-11 Elijah Newren <newren@gmail.com> Correct highlighting of windows in workspace switcher popup. diff --git a/configure.in b/configure.in index 2d67a776..02e6e3fe 100644 --- a/configure.in +++ b/configure.in @@ -199,12 +199,20 @@ fi have_xrender=no XCOMPOSITE_VERSION=1.0 -AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION]) -if $PKG_CONFIG --atleast-version $XCOMPOSITE_VERSION xcomposite; then - have_xcomposite=yes -else - have_xcomposite=no + +XCOMPOSITE_LIBS= +found_xcomposite=no +AC_CHECK_LIB(Xcomposite, XCompositeQueryExtension, + [AC_CHECK_HEADER(X11/extensions/composite.h, + found_xcomposite=yes,, + [#include <X11/Xlib.h>])], + , $ALL_X_LIBS) + +if test x$enable_xcompositor = xno; then + found_xcomposite=no fi + +AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION]) AC_MSG_RESULT($have_xcomposite) if test x$enable_compositor = xyes; then diff --git a/src/Makefile.am b/src/Makefile.am index 3ed5e1db..4ad59658 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ EGGFILES= \ eggaccelerators.c \ eggaccelerators.h -metacity_SOURCES= \ +metacity_SOURCES= \ async-getprop.c \ async-getprop.h \ bell.h \ @@ -20,6 +20,8 @@ metacity_SOURCES= \ constraints.h \ core.c \ core.h \ + cwindow.c \ + cwindow.h \ delete.c \ display.c \ display.h \ @@ -49,6 +51,8 @@ metacity_SOURCES= \ inlinepixbufs.h \ keybindings.c \ keybindings.h \ + matrix.c \ + matrix.h \ main.c \ main.h \ menu.c \ diff --git a/src/compositor.c b/src/compositor.c index d82fadbf..c04c58bc 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -26,64 +26,24 @@ #include "errors.h" #include "window.h" #include "frame.h" +#include "matrix.h" +#include <math.h> +#include "cwindow.h" #ifdef HAVE_COMPOSITE_EXTENSIONS #include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xdamage.h> #include <X11/extensions/Xrender.h> -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 -#define HAVE_NAME_WINDOW_PIXMAP 1 -#endif - #endif /* HAVE_COMPOSITE_EXTENSIONS */ -#define SHADOW_OFFSET 3 +#define SHADOW_OFFSET 10 #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 - * newly-mapped window was in the stack. A MetaCompositorWindow may - * correspond to a metacity window frame rather than an application - * window. - */ -typedef struct -{ - Window xwindow; - -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositor *compositor; - - int x; - int y; - int width; - int height; - int border_width; - - Damage damage; - XserverRegion last_painted_extents; - - Picture picture; - XserverRegion border_size; - -#if HAVE_NAME_WINDOW_PIXMAP - Pixmap pixmap; -#endif - - unsigned int managed : 1; - unsigned int damaged : 1; - unsigned int viewable : 1; - - unsigned int screen_index : 8; - -#endif -} MetaCompositorWindow; - struct MetaCompositor { MetaDisplay *display; - + int composite_error_base; int composite_event_base; int damage_error_base; @@ -92,7 +52,7 @@ struct MetaCompositor int fixes_event_base; GHashTable *window_hash; - + guint repair_idle; guint repair_timeout; @@ -100,43 +60,18 @@ struct MetaCompositor guint have_composite : 1; guint have_damage : 1; guint have_fixes : 1; -#ifdef HAVE_NAME_WINDOW_PIXMAP guint have_name_window_pixmap : 1; -#endif -}; - -#ifdef HAVE_COMPOSITE_EXTENSIONS -static void -meta_compositor_window_free (MetaCompositorWindow *cwindow) -{ - g_assert (cwindow->damage != None); - - meta_error_trap_push (cwindow->compositor->display); - /* This seems to cause an error if the window - * is destroyed? - */ - XDamageDestroy (cwindow->compositor->display->xdisplay, - cwindow->damage); - -#if HAVE_NAME_WINDOW_PIXMAP - /* Free our window pixmap name */ - if (cwindow->pixmap != None) - XFreePixmap (cwindow->compositor->display->xdisplay, - cwindow->pixmap); -#endif - meta_error_trap_pop (cwindow->compositor->display, FALSE); - g_free (cwindow); -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ + GList *ignored_damage; +}; #ifdef HAVE_COMPOSITE_EXTENSIONS static void free_window_hash_value (void *v) { - MetaCompositorWindow *cwindow = v; - - meta_compositor_window_free (cwindow); + CWindow *cwindow = v; + + cwindow_free (cwindow); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -145,9 +80,9 @@ meta_compositor_new (MetaDisplay *display) { #ifdef HAVE_COMPOSITE_EXTENSIONS MetaCompositor *compositor; - + compositor = g_new0 (MetaCompositor, 1); - + compositor->display = display; if (!XCompositeQueryExtension (display->xdisplay, @@ -162,22 +97,16 @@ meta_compositor_new (MetaDisplay *display) int composite_major, composite_minor; compositor->have_composite = TRUE; - -#if HAVE_NAME_WINDOW_PIXMAP + XCompositeQueryVersion (display->xdisplay, &composite_major, &composite_minor); - -#if 0 - if (composite_major > 0 || composite_minor >= 2) - compositor->have_name_window_pixmap = TRUE; -#endif -#endif + } - + meta_topic (META_DEBUG_COMPOSITOR, "Composite extension event base %d error base %d\n", compositor->composite_event_base, compositor->composite_error_base); - + if (!XDamageQueryExtension (display->xdisplay, &compositor->damage_event_base, &compositor->damage_error_base)) @@ -187,7 +116,7 @@ meta_compositor_new (MetaDisplay *display) } else compositor->have_damage = TRUE; - + meta_topic (META_DEBUG_COMPOSITOR, "Damage extension event base %d error base %d\n", compositor->damage_event_base, compositor->damage_error_base); @@ -201,7 +130,7 @@ meta_compositor_new (MetaDisplay *display) } else compositor->have_fixes = TRUE; - + meta_topic (META_DEBUG_COMPOSITOR, "Fixes extension event base %d error base %d\n", compositor->fixes_event_base, compositor->fixes_error_base); @@ -212,6 +141,15 @@ meta_compositor_new (MetaDisplay *display) META_DISPLAY_HAS_RENDER (compositor->display))) { meta_topic (META_DEBUG_COMPOSITOR, "Failed to find all extensions needed for compositing manager, disabling compositing manager\n"); + + if (!compositor->have_composite) + g_print ("no composite\n"); + if (!compositor->have_fixes) + g_print ("no fixes\n"); + if (!compositor->have_damage) + g_print ("have damage\n"); + + g_assert (!compositor->enabled); return compositor; } @@ -241,7 +179,7 @@ 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); @@ -258,7 +196,7 @@ meta_compositor_unref (MetaCompositor *compositor) * there's no ref() */ remove_repair_idle (compositor); - + if (compositor->window_hash) g_hash_table_destroy (compositor->window_hash); @@ -267,73 +205,114 @@ meta_compositor_unref (MetaCompositor *compositor) } #ifdef HAVE_COMPOSITE_EXTENSIONS -static XserverRegion -window_extents (MetaCompositorWindow *cwindow) -{ - XRectangle r; - - r.x = cwindow->x; - r.y = cwindow->y; - 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 */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS static void -window_get_paint_bounds (MetaCompositorWindow *cwindow, - int *x, - int *y, - int *w, - int *h) +draw_windows (MetaCompositor *compositor, + MetaScreen *screen, + GList *list, + XserverRegion damaged_region, + Picture picture) { -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (cwindow->pixmap != None) + CWindow *cwindow; + XserverRegion region_below; + Display *dpy = compositor->display->xdisplay; + int x, y, w, h; + + if (!list) + return; + + cwindow = list->data; + + region_below = XFixesCreateRegion (dpy, NULL, 0); + XFixesCopyRegion (dpy, region_below, damaged_region); + + cwindow_get_paint_bounds (cwindow, &x, &y, &w, &h); + + if (!cwindow_is_translucent (cwindow) && !cwindow_get_input_only (cwindow) && cwindow_get_viewable (cwindow)) { - *x = cwindow->x; - *y = cwindow->y; - *w = cwindow->width + cwindow->border_width * 2; - *h = cwindow->height + cwindow->border_width * 2; - } - else + XRectangle rect = { x, y, w, h }; + XserverRegion window_region = XFixesCreateRegion (dpy, &rect, 1); + XFixesSubtractRegion (dpy, region_below, region_below, window_region); + XFixesDestroyRegion (dpy, window_region); + +#if 0 + XSetForeground (xdisplay, gc, 0x00ffff00); + XFillRectangle (xdisplay, screen->xroot, gc, 0, 0, screen->width, screen->height); #endif - { - *x = cwindow->x + cwindow->border_width; - *y = cwindow->y + cwindow->border_width; - *w = cwindow->width; - *h = cwindow->height; } + + draw_windows (compositor, screen, list->next, region_below, picture); + + XFixesDestroyRegion (dpy, region_below); + + cwindow_new_draw (cwindow, picture, damaged_region); } -static void -paint_screen (MetaCompositor *compositor, - MetaScreen *screen, - XserverRegion damage_region) +static Picture +create_root_buffer (MetaScreen *screen) { - XserverRegion region; - Picture buffer_picture; + GC gc; + Display *display = screen->display->xdisplay; Pixmap buffer_pixmap; - Display *xdisplay; + XGCValues value; XRenderPictFormat *format; - GList *tmp; - GC gc; - - meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n", - screen->number, screen->xroot); - - /* meta_display_grab (screen->display); */ + Picture buffer_picture; - xdisplay = screen->display->xdisplay; + buffer_pixmap = XCreatePixmap (display, screen->xroot, + screen->width, + screen->height, + DefaultDepth (display, + screen->number)); + + value.function = GXcopy; + value.subwindow_mode = IncludeInferiors; + + gc = XCreateGC (display, buffer_pixmap, GCFunction | GCSubwindowMode, &value); + XSetForeground (display, gc, WhitePixel (display, screen->number)); + XSetForeground (display, gc, 0x00ff0099); +#if 0 + XFillRectangle (display, buffer_pixmap, gc, 0, 0, + screen->width, screen->height); +#endif + + format = XRenderFindVisualFormat (display, + DefaultVisual (display, + screen->number)); + + buffer_picture = XRenderCreatePicture (display, + buffer_pixmap, + format, + 0, 0); + + XFreePixmap (display, buffer_pixmap); + XFreeGC (display, gc); + + return buffer_picture; +} + +static void +paint_buffer (MetaScreen *screen, Picture buffer) +{ + XRenderComposite (screen->display->xdisplay, + PictOpSrc, + buffer, None, + screen->root_picture, + 0, 0, 0, 0, 0, 0, + screen->width, screen->height); +} + +static XserverRegion +do_paint_screen (MetaCompositor *compositor, + MetaScreen *screen, + Picture picture, + XserverRegion damage_region) +{ + Display *xdisplay = compositor->display->xdisplay; + XserverRegion region; if (damage_region == None) { XRectangle r; - + r.x = 0; r.y = 0; r.width = screen->width; @@ -346,142 +325,62 @@ paint_screen (MetaCompositor *compositor, region = XFixesCreateRegion (xdisplay, NULL, 0); XFixesCopyRegion (compositor->display->xdisplay, - region, - damage_region); + region, + damage_region); } - - 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, - screen->number)); - buffer_picture = XRenderCreatePicture (xdisplay, - buffer_pixmap, - format, - 0, 0); - - /* set clip */ + meta_error_trap_push (compositor->display); XFixesSetPictureClipRegion (xdisplay, - buffer_picture, 0, 0, - region); - - /* draw windows from bottom to top */ + picture, 0, 0, + region); - 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; - - if (!cwindow->viewable) - goto next; /* not viewable */ - - if (cwindow->last_painted_extents) - XFixesDestroyRegion (xdisplay, - cwindow->last_painted_extents); - - cwindow->last_painted_extents = window_extents (cwindow); - - /* XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0); */ - - meta_topic (META_DEBUG_COMPOSITOR, " Compositing window 0x%lx %d,%d %dx%d\n", - cwindow->xwindow, - cwindow->x, cwindow->y, - 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 */ - int x, y, w, h; - - window_get_paint_bounds (cwindow, &x, &y, &w, &h); - - XRenderComposite (xdisplay, - PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ - cwindow->picture, - screen->trans_picture, - buffer_picture, - 0, 0, 0, 0, - x, y, w, h); - } - else - { - /* Draw window normally */ - int x, y, w, h; - - window_get_paint_bounds (cwindow, &x, &y, &w, &h); - - /* 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, - x, y, w, h); - } - - next: - tmp = tmp->prev; - } + draw_windows (compositor, screen, screen->compositor_windows, region, picture); meta_error_trap_pop (compositor->display, FALSE); + + return region; +} +static void +paint_screen (MetaCompositor *compositor, + MetaScreen *screen, + XserverRegion damage_region) +{ + Picture buffer_picture; + Display *xdisplay; + XserverRegion region; + + meta_topic (META_DEBUG_COMPOSITOR, "Repainting screen %d root 0x%lx\n", + screen->number, screen->xroot); + + /* meta_display_grab (screen->display); */ + + xdisplay = screen->display->xdisplay; + + buffer_picture = create_root_buffer (screen); + + /* set clip */ + region = do_paint_screen (compositor, screen, buffer_picture, damage_region); + /* Copy buffer to root window */ meta_topic (META_DEBUG_COMPOSITOR, "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); */ - XRenderComposite (xdisplay, PictOpSrc, buffer_picture, None, - screen->root_picture, - 0, 0, 0, 0, 0, 0, - screen->width, screen->height); + paint_buffer (screen, buffer_picture); XFixesDestroyRegion (xdisplay, region); - XFreePixmap (xdisplay, buffer_pixmap); + + + + /* XFixesSetPictureClipRegion (xdisplay, buffer_picture, 0, 0, None); */ XRenderFreePicture (xdisplay, buffer_picture); - XFreeGC (xdisplay, gc); - + /* meta_display_ungrab (screen->display); */ - + XSync (screen->display->xdisplay, False); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -496,7 +395,7 @@ do_repair (MetaCompositor *compositor) while (tmp != NULL) { MetaScreen *s = tmp->data; - + if (s->damage_region != None) { paint_screen (compositor, s, @@ -508,7 +407,7 @@ do_repair (MetaCompositor *compositor) tmp = tmp->next; } - + remove_repair_idle (compositor); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -518,7 +417,7 @@ static gboolean repair_idle_func (void *data) { MetaCompositor *compositor = data; - + compositor->repair_idle = 0; do_repair (compositor); @@ -532,7 +431,7 @@ static gboolean repair_timeout_func (void *data) { MetaCompositor *compositor = data; - + compositor->repair_timeout = 0; do_repair (compositor); @@ -541,48 +440,22 @@ repair_timeout_func (void *data) #endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS -static MetaScreen* -meta_compositor_window_get_screen (MetaCompositorWindow *cwindow) -{ - MetaScreen *screen; - GSList *tmp; - - screen = NULL; - tmp = cwindow->compositor->display->screens; - while (tmp != NULL) - { - MetaScreen *s = tmp->data; - - if (s->number == cwindow->screen_index) - { - screen = s; - break; - } - - tmp = tmp->next; - } - g_assert (screen != NULL); - - return screen; -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS static void ensure_repair_idle (MetaCompositor *compositor) { if (compositor->repair_idle != 0) return; - + 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); - + meta_topic (META_DEBUG_COMPOSITOR, "Damage idle queued\n"); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ +#if 0 #ifdef HAVE_COMPOSITE_EXTENSIONS static void merge_and_destroy_damage_region (MetaCompositor *compositor, @@ -601,28 +474,26 @@ merge_and_destroy_damage_region (MetaCompositor *compositor, { screen->damage_region = region; } - + ensure_repair_idle (compositor); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ +#endif #ifdef HAVE_COMPOSITE_EXTENSIONS -static void -merge_damage_region (MetaCompositor *compositor, - MetaScreen *screen, - XserverRegion region) +void +meta_compositor_invalidate_region (MetaCompositor *compositor, + MetaScreen *screen, + XserverRegion invalid_area) { if (screen->damage_region == None) screen->damage_region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); - - meta_topic (META_DEBUG_COMPOSITOR, - "(Merging damage region)\n"); XFixesUnionRegion (compositor->display->xdisplay, screen->damage_region, - region, screen->damage_region); - + invalid_area, screen->damage_region); + ensure_repair_idle (compositor); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -632,135 +503,54 @@ static void process_damage_notify (MetaCompositor *compositor, XDamageNotifyEvent *event) { - MetaCompositorWindow *cwindow; - XserverRegion region; - MetaScreen *screen; + CWindow *cwindow; cwindow = g_hash_table_lookup (compositor->window_hash, &event->drawable); + if (cwindow == NULL) return; - region = XFixesCreateRegion (compositor->display->xdisplay, NULL, 0); + cwindow_process_damage_notify (cwindow, event); +} +#endif /* HAVE_COMPOSITE_EXTENSIONS */ - /* 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, - cwindow->x, - cwindow->y); - screen = meta_compositor_window_get_screen (cwindow); +static void +handle_restacking (MetaCompositor *compositor, + CWindow *cwindow, + CWindow *above) +{ + GList *window_link, *above_link; + MetaScreen *screen = cwindow_get_screen (cwindow); - merge_and_destroy_damage_region (compositor, screen, region); + window_link = g_list_find (screen->compositor_windows, cwindow); + above_link = g_list_find (screen->compositor_windows, above); + + if (window_link->next != above_link) + { + screen->compositor_windows = g_list_delete_link (screen->compositor_windows, window_link); + screen->compositor_windows = g_list_insert_before (screen->compositor_windows, above_link, cwindow); + } } -#endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS static void process_configure_notify (MetaCompositor *compositor, XConfigureEvent *event) { - MetaCompositorWindow *cwindow; - MetaScreen *screen; - GList *link; - Window above; - XserverRegion region; + CWindow *cwindow; cwindow = g_hash_table_lookup (compositor->window_hash, &event->window); if (cwindow == NULL) return; - - screen = meta_compositor_window_get_screen (cwindow); - - g_assert (screen != NULL); - - if (screen->xroot != event->event) - { - meta_topic (META_DEBUG_COMPOSITOR, - "ConfigureNotify for 0x%lx received by 0x%lx not using\n", - event->window, event->event); - return; /* ignore ConfigureNotify not received on root window */ - } - - meta_topic (META_DEBUG_COMPOSITOR, - "ConfigureNotify for 0x%lx received by 0x%lx %d,%d %dx%d\n", - event->window, event->event, - event->x, event->y, event->width, event->height); - - if (cwindow->last_painted_extents) - { - merge_and_destroy_damage_region (compositor, - screen, - cwindow->last_painted_extents); - cwindow->last_painted_extents = None; - } - - cwindow->x = event->x; - cwindow->y = event->y; - cwindow->width = event->width; - cwindow->height = event->height; - cwindow->border_width = event->border_width; - - link = g_list_find (screen->compositor_windows, - cwindow); - - g_assert (link != NULL); - - if (link->next) - above = ((MetaCompositorWindow*) link->next)->xwindow; - else - above = None; - if (above != event->above) - { - GList *tmp; - - screen->compositor_windows = - g_list_delete_link (screen->compositor_windows, - link); - link = NULL; - - /* Note that event->above is None if our window is on the bottom */ - tmp = screen->compositor_windows; - while (tmp != NULL) - { - MetaCompositorWindow *t = tmp->data; - - if (t->xwindow == event->above) - { - /* We are above this window, i.e. earlier in list */ - break; - } - - tmp = tmp->next; - } - - if (tmp != NULL) - { - screen->compositor_windows = - g_list_insert_before (screen->compositor_windows, - tmp, - cwindow); - } - else - screen->compositor_windows = - g_list_prepend (screen->compositor_windows, - cwindow); - } + cwindow_process_configure_notify (cwindow, event); - region = window_extents (cwindow); - merge_damage_region (compositor, - screen, - region); - XFixesDestroyRegion (compositor->display->xdisplay, region); + handle_restacking (compositor, cwindow, + g_hash_table_lookup (compositor->window_hash, &event->above)); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -773,21 +563,26 @@ process_expose (MetaCompositor *compositor, 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); + meta_compositor_invalidate_region (compositor, + screen, + region); + + XFixesDestroyRegion (compositor->display->xdisplay, region); } + #endif /* HAVE_COMPOSITE_EXTENSIONS */ #ifdef HAVE_COMPOSITE_EXTENSIONS @@ -795,13 +590,13 @@ static void process_map (MetaCompositor *compositor, XMapEvent *event) { - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; /* See if window was mapped as child of root */ screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -836,8 +631,13 @@ process_map (MetaCompositor *compositor, } else { - cwindow->viewable = TRUE; + cwindow_set_viewable (cwindow, TRUE); } + + /* We don't actually need to invalidate anything, because we will + * get damage events as the server fills the background and the client + * draws + */ } #endif /* HAVE_COMPOSITE_EXTENSIONS */ @@ -846,13 +646,13 @@ static void process_unmap (MetaCompositor *compositor, XUnmapEvent *event) { - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; - + /* See if window was unmapped as child of root */ screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -865,14 +665,14 @@ process_unmap (MetaCompositor *compositor, &event->window); if (cwindow != NULL) { - cwindow->viewable = FALSE; - - if (cwindow->last_painted_extents) + cwindow_set_viewable (cwindow, FALSE); + + if (cwindow_get_last_painted_extents (cwindow)) { - merge_and_destroy_damage_region (compositor, - screen, - cwindow->last_painted_extents); - cwindow->last_painted_extents = None; + meta_compositor_invalidate_region (compositor, + screen, + cwindow_get_last_painted_extents (cwindow)); + cwindow_set_last_painted_extents (cwindow, None); } } } @@ -885,10 +685,10 @@ process_create (MetaCompositor *compositor, { MetaScreen *screen; XWindowAttributes attrs; - + screen = meta_display_screen_for_root (compositor->display, event->parent); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -896,7 +696,8 @@ process_create (MetaCompositor *compositor, event->parent, event->window); return; } - + + g_print ("hello\n"); meta_error_trap_push_with_return (compositor->display); XGetWindowAttributes (compositor->display->xdisplay, @@ -904,11 +705,13 @@ process_create (MetaCompositor *compositor, if (meta_error_trap_pop_with_return (compositor->display, TRUE) != Success) { + g_print ("couldn't get\n"); meta_topic (META_DEBUG_COMPOSITOR, "Failed to get attributes for window 0x%lx\n", event->window); } else { + g_print ("adding\n"); meta_topic (META_DEBUG_COMPOSITOR, "Create window 0x%lx, adding\n", event->window); meta_compositor_add_window (compositor, @@ -923,10 +726,10 @@ process_destroy (MetaCompositor *compositor, XDestroyWindowEvent *event) { MetaScreen *screen; - + screen = meta_display_screen_for_root (compositor->display, event->event); - + if (screen == NULL || screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -934,7 +737,7 @@ process_destroy (MetaCompositor *compositor, event->event, event->window); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Destroy window 0x%lx\n", event->window); meta_compositor_remove_window (compositor, event->window); @@ -952,12 +755,12 @@ process_reparent (MetaCompositor *compositor, */ MetaScreen *event_screen; MetaScreen *parent_screen; - MetaCompositorWindow *cwindow; + CWindow *cwindow; XWindowAttributes attrs; event_screen = meta_display_screen_for_root (compositor->display, event->event); - + if (event_screen == NULL || event_screen->root_picture == None) { meta_topic (META_DEBUG_COMPOSITOR, @@ -965,11 +768,11 @@ process_reparent (MetaCompositor *compositor, event->event, event->window); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Reparent window 0x%lx new parent 0x%lx received on 0x%lx\n", event->window, event->parent, event->event); - + parent_screen = meta_display_screen_for_root (compositor->display, event->parent); @@ -989,11 +792,11 @@ process_reparent (MetaCompositor *compositor, meta_topic (META_DEBUG_COMPOSITOR, "Window reparented to new screen at %d,%d\n", event->x, event->y); - cwindow->x = event->x; - cwindow->y = event->y; + cwindow_set_x (cwindow, event->x); + cwindow_set_y (cwindow, event->y); return; } - + meta_error_trap_push_with_return (compositor->display); XGetWindowAttributes (compositor->display->xdisplay, @@ -1023,7 +826,7 @@ meta_compositor_process_event (MetaCompositor *compositor, #ifdef HAVE_COMPOSITE_EXTENSIONS if (!compositor->enabled) return; /* no extension */ - + /* FIXME support CirculateNotify */ if (event->type == (compositor->damage_event_base + XDamageNotify)) @@ -1079,106 +882,60 @@ meta_compositor_add_window (MetaCompositor *compositor, XWindowAttributes *attrs) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; - Damage damage; - XRenderPictFormat *format; - XRenderPictureAttributes pa; + XserverRegion region; if (!compositor->enabled) return; /* no extension */ - + screen = meta_screen_for_x_screen (attrs->screen); g_assert (screen != NULL); cwindow = g_hash_table_lookup (compositor->window_hash, &xwindow); - + if (cwindow != NULL) { meta_topic (META_DEBUG_COMPOSITOR, "Window 0x%lx already added\n", xwindow); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Adding window 0x%lx (%s) to compositor\n", xwindow, attrs->map_state == IsViewable ? "mapped" : "unmapped"); - /* Create Damage object to monitor window damage */ - meta_error_trap_push (compositor->display); - damage = XDamageCreate (compositor->display->xdisplay, - xwindow, XDamageReportNonEmpty); - meta_error_trap_pop (compositor->display, FALSE); - - if (damage == None) - return; - - cwindow = g_new0 (MetaCompositorWindow, 1); - - cwindow->compositor = compositor; - cwindow->xwindow = xwindow; - cwindow->screen_index = screen->number; - 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; - -#if HAVE_NAME_WINDOW_PIXMAP - if (compositor->have_name_window_pixmap) - { - meta_error_trap_push (compositor->display); - cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay, - cwindow->xwindow); - meta_error_trap_pop (compositor->display, FALSE); - } -#endif + cwindow = cwindow_new (compositor, xwindow, attrs); - /* viewable == mapped for the root window, since root can't be unmapped */ - cwindow->viewable = (attrs->map_state == IsViewable); /* FIXME this assertion can fail somehow... */ g_assert (attrs->map_state != IsUnviewable); - - pa.subwindow_mode = IncludeInferiors; +#if 0 + if (attrs->map_state == Mapped) + g_print ("mapped\n"); - if (attrs->class != InputOnly) - { - format = XRenderFindVisualFormat (compositor->display->xdisplay, - attrs->visual); - cwindow->picture = XRenderCreatePicture (compositor->display->xdisplay, -#if HAVE_NAME_WINDOW_PIXMAP - cwindow->pixmap != None ? - cwindow->pixmap : - cwindow->xwindow, -#else - cwindow->xwindow, + if (attrs->map_state == Viewable) + g_pritn ("viewable\n"); #endif - format, - CPSubwindowMode, - &pa); - } - else - { - cwindow->picture = None; - } g_hash_table_insert (compositor->window_hash, - &cwindow->xwindow, cwindow); - + cwindow_get_xid_address (cwindow), cwindow); + /* assume cwindow is at the top of the stack as it was either just * created or just reparented to the root window */ 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); + region = cwindow_extents (cwindow); + + meta_compositor_invalidate_region (compositor, screen, region); + + XFixesDestroyRegion (compositor->display->xdisplay, region); #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -1187,7 +944,7 @@ meta_compositor_remove_window (MetaCompositor *compositor, Window xwindow) { #ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorWindow *cwindow; + CWindow *cwindow; MetaScreen *screen; if (!compositor->enabled) @@ -1195,27 +952,27 @@ meta_compositor_remove_window (MetaCompositor *compositor, cwindow = g_hash_table_lookup (compositor->window_hash, &xwindow); - + if (cwindow == NULL) { meta_topic (META_DEBUG_COMPOSITOR, "Window 0x%lx already removed\n", xwindow); return; } - + meta_topic (META_DEBUG_COMPOSITOR, "Removing window 0x%lx (%s) from compositor\n", xwindow, - cwindow->viewable ? "mapped" : "unmapped"); + cwindow_get_viewable (cwindow) ? "mapped" : "unmapped"); - screen = meta_compositor_window_get_screen (cwindow); - - if (cwindow->last_painted_extents) + screen = cwindow_get_screen (cwindow); + + if (cwindow_get_last_painted_extents (cwindow)) { - merge_and_destroy_damage_region (compositor, - screen, - cwindow->last_painted_extents); - cwindow->last_painted_extents = None; + meta_compositor_invalidate_region (compositor, + screen, + cwindow_get_last_painted_extents (cwindow)); + cwindow_set_last_painted_extents (cwindow, None); } screen->compositor_windows = g_list_remove (screen->compositor_windows, @@ -1236,22 +993,41 @@ meta_compositor_manage_screen (MetaCompositor *compositor, XRenderPictureAttributes pa; XRectangle r; XRenderColor c; + XserverRegion region; if (!compositor->enabled) return; /* no extension */ - + /* FIXME we need to handle root window resize by recreating the * root_picture */ g_assert (screen->root_picture == None); - + + /* FIXME add flag for whether we're composite-managing each + * screen and detect failure here + */ + + /* CompositeRedirectSubwindows result in all mapped windows + * getting unmapped/mapped, which confuses Metacity since it + * thinks that non-override redirect windows should only + * be mapped by the window manager. + * + * To work around this, we discard all events generated + * by XCompositeRedirectSubwindows + */ + + XSync (screen->display->xdisplay, False); + /* FIXME add flag for whether we're composite-managing each * screen and detect failure here */ XCompositeRedirectSubwindows (screen->display->xdisplay, - screen->xroot, - CompositeRedirectManual); + screen->xroot, + CompositeRedirectManual); + + XSync (screen->display->xdisplay, True); + meta_topic (META_DEBUG_COMPOSITOR, "Subwindows redirected, we are now the compositing manager\n"); pa.subwindow_mode = IncludeInferiors; @@ -1264,12 +1040,12 @@ meta_compositor_manage_screen (MetaCompositor *compositor, screen->number)), CPSubwindowMode, &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, @@ -1280,7 +1056,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor, &pa); c.red = c.green = c.blue = 0; - c.alpha = 0xc0c0; + c.alpha = 0xb0b0; XRenderFillRectangle (compositor->display->xdisplay, PictOpSrc, screen->trans_picture, &c, 0, 0, 1, 1); @@ -1291,10 +1067,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor, r.width = screen->width; r.height = screen->height; - merge_and_destroy_damage_region (compositor, - screen, - XFixesCreateRegion (compositor->display->xdisplay, - &r, 1)); + region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1); + #endif /* HAVE_COMPOSITE_EXTENSIONS */ } @@ -1306,7 +1080,7 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor, #ifdef HAVE_COMPOSITE_EXTENSIONS if (!compositor->enabled) return; /* no extension */ - + XRenderFreePicture (screen->display->xdisplay, screen->root_picture); screen->root_picture = None; @@ -1319,41 +1093,392 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor, while (screen->compositor_windows != NULL) { - MetaCompositorWindow *cwindow = screen->compositor_windows->data; - + CWindow *cwindow = screen->compositor_windows->data; + meta_topic (META_DEBUG_COMPOSITOR, - "Unmanage screen for 0x%lx\n", cwindow->xwindow); - meta_compositor_remove_window (compositor, cwindow->xwindow); + "Unmanage screen for 0x%lx\n", cwindow_get_xwindow (cwindow)); + meta_compositor_remove_window (compositor, cwindow_get_xwindow (cwindow)); } #endif /* HAVE_COMPOSITE_EXTENSIONS */ } +static CWindow * +window_to_cwindow (MetaCompositor *compositor, + MetaWindow *window) +{ + Window xwindow; + CWindow *cwindow; + + if (window->frame) + xwindow = window->frame->xwindow; + else + xwindow = window->xwindow; + + cwindow = g_hash_table_lookup (compositor->window_hash, + &xwindow); + + return cwindow; +} + void meta_compositor_damage_window (MetaCompositor *compositor, MetaWindow *window) { #ifdef HAVE_COMPOSITE_EXTENSIONS - Window xwindow; - MetaCompositorWindow *cwindow; - + XserverRegion region; + CWindow *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); + cwindow = window_to_cwindow (compositor, window); + if (cwindow == NULL) return; - merge_and_destroy_damage_region (compositor, - window->screen, - window_extents (cwindow)); + region = cwindow_extents (cwindow); + + meta_compositor_invalidate_region (compositor, cwindow_get_screen (cwindow), region); + + XFixesDestroyRegion (compositor->display->xdisplay, region); #endif /* HAVE_COMPOSITE_EXTENSIONS */ } + +void +meta_compositor_stop_compositing (MetaCompositor *compositor, + MetaWindow *window) +{ +#if 0 + CWindow *cwindow = window_to_cwindow (compositor, window); + + if (cwindow) + { + if (cwindow->pixmap) + XFreePixmap (compositor->display->xdisplay, cwindow->pixmap); + + cwindow->pixmap = XCompositeNameWindowPixmap (compositor->display->xdisplay, + cwindow->xwindow); + + cwindow->pending_x = cwindow->x; + cwindow->pending_y = cwindow->y; + cwindow->pending_width = cwindow->width; + cwindow->pending_height = cwindow->height; + cwindow->pending_border_width = cwindow->border_width; + } +#endif +} + +void +meta_compositor_start_compositing (MetaCompositor *compositor, + MetaWindow *window) +{ +#if 0 + CWindow *cwindow = window_to_cwindow (compositor, window); + + if (cwindow) + { + if (cwindow->pixmap) + { + XFreePixmap (compositor->display->xdisplay, cwindow->pixmap); + cwindow->pixmap = None; + } + + cwindow->x = cwindow->pending_x; + cwindow->y = cwindow->pending_y; + cwindow->width = cwindow->pending_width; + cwindow->height = cwindow->pending_height; + cwindow->border_width = cwindow->pending_border_width; + + meta_compositor_damage_window (compositor, window); + } +#endif +} + +static void +quad_to_quad_interpolate (Quad *start, Quad *end, Quad *dest, gdouble t) +{ + int i; + + for (i = 0; i < 4; ++i) + { + if (i == 3) + { + dest->points[i].x = + start->points[i].x + (end->points[i].x - start->points[i].x) * t; + } + else + { + dest->points[i].x = + start->points[i].x + (end->points[i].x - start->points[i].x) * pow (t, 1.5); + } + if (i == 1) + { + dest->points[i].y = + start->points[i].y + (end->points[i].y - start->points[i].y) * pow (t, 1.5); + } + else + { + dest->points[i].y = + start->points[i].y + (end->points[i].y - start->points[i].y) * t; + } + } +} + +void +meta_compositor_old_genie (MetaCompositor *compositor, + MetaWindow *window) +{ +#if 0 + int i; + int x, y, w, h; +#if 0 + int dx, dy, dw, dh; +#endif + + Quad start; + Quad end; + Quad dest; + + CWindow *cwindow = window_to_cwindow (compositor, window); + + if (!cwindow) + return; + + x = cwindow_get_x (cwindow); + y = cwindow_get_y (cwindow); + w = cwindow_get_width (cwindow) + cwindow_get_border_width (cwindow) * 2; + h = cwindow_get_height (cwindow) + cwindow_get_border_width (cwindow) * 2; + + start.points[0].x = x; + start.points[0].y = y; + start.points[1].x = x + w - 1; + start.points[1].y = y; + start.points[2].x = x; + start.points[2].y = y + h - 1; + start.points[3].x = x + w - 1; + start.points[3].y = y + h - 1; + + end.points[0].x = 0; + end.points[0].y = 1200 - 30; + end.points[1].x = 100; + end.points[1].y = 1200 - 30; + end.points[2].x = 0; + end.points[2].y = 1200 - 1; + end.points[3].x = 100; + end.points[3].y = 1200 - 1; + +#define N_STEPS 5 + + for (i = 0; i < N_STEPS; ++i) + { +#if 0 + int j; +#endif +#if 0 + XTransform trans = { + {{ XDoubleToFixed(1.0), XDoubleToFixed(0), XDoubleToFixed(0) }, + { XDoubleToFixed(0), XDoubleToFixed(1.0), XDoubleToFixed(0) }, + { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed((49 - i)/49.0)}} + }; +#endif +#if 0 + XRenderPictFormat *format; +#endif + Picture buffer; + +#if 0 + wpicture = XRenderCreatePicture (compositor->display->xdisplay, + cwindow_get_drawable (cwindow), + format, + CPSubwindowMode, + &pa); + + g_assert (compositor->display); +#endif + + quad_to_quad_interpolate (&start, &end, &dest, i/((double)N_STEPS - 1)); + + buffer = create_root_buffer (window->screen); + + XFixesSetPictureClipRegion (compositor->display->xdisplay, + buffer, 0, 0, + None); + + { + XRectangle r; + XserverRegion region; + + r.x = 0; + r.y = 0; + r.width = window->screen->width; + r.height = window->screen->height; + + region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1); + + XFixesDestroyRegion (compositor->display->xdisplay, + do_paint_screen (compositor, window->screen, buffer, region)); + XFixesDestroyRegion (compositor->display->xdisplay, region); + } + + cwindow_draw_warped (cwindow, window->screen, buffer, &dest); + +#if 0 + XRenderColor c = { 0x1000, 0x1000, 0x1000, 0x70c0 }; +#endif + + XFixesSetPictureClipRegion (compositor->display->xdisplay, window->screen->root_picture, 0, 0, None); + +#if 0 + XRenderFillRectangle (compositor->display->xdisplay, PictOpOver, buffer, &c, 0, 0, 100, 100); +#endif + + paint_buffer (window->screen, buffer); + + XRenderFreePicture (compositor->display->xdisplay, buffer); + + XSync (compositor->display->xdisplay, False); + /* Copy buffer to root window */ +#if 0 + meta_topic (META_DEBUG_COMPOSITOR, "Copying buffer to root window 0x%lx picture 0x%lx\n", + screen->xroot, screen->root_picture); +#endif +#if 0 + g_print ("%d %d %d %d %d %d %d %d\n", + dest.points[0].x, dest.points[0].y, + dest.points[1].x, dest.points[1].y, + dest.points[2].x, dest.points[2].y, + dest.points[3].x, dest.points[3].y); +#endif +#if 0 + g_usleep (30000); +#endif + } +#endif +} + +void +meta_compositor_genie (MetaCompositor *compositor, + MetaWindow *window) +{ + int i; + int x, y, w, h; +#if 0 + int dx, dy, dw, dh; +#endif + + Quad start1; + Quad end1; + + Quad start2; + Quad end2; + + CWindow *cwindow = window_to_cwindow (compositor, window); + + if (!cwindow) + return; + + x = cwindow_get_x (cwindow); + y = cwindow_get_y (cwindow); + w = cwindow_get_width (cwindow) + cwindow_get_border_width (cwindow) * 2; + h = cwindow_get_height (cwindow) + cwindow_get_border_width (cwindow) * 2; + + start1.points[0].x = x; + start1.points[0].y = y; + start1.points[1].x = x + w/2 - 1; + start1.points[1].y = y; + start1.points[2].x = x; + start1.points[2].y = y + h - 1; + start1.points[3].x = x + w/2 - 1; + start1.points[3].y = y + h - 1; + + end1.points[0].x = 500; + end1.points[0].y = 200 + 50; + end1.points[1].x = 600; + end1.points[1].y = 200 + 50; + end1.points[2].x = 500; + end1.points[2].y = 200 + 80; + end1.points[3].x = 600; + end1.points[3].y = 200 + 80; + + start2.points[0].x = x + w/2; + start2.points[0].y = y; + start2.points[1].x = x + w - 1; + start2.points[1].y = y; + start2.points[2].x = x + w/2; + start2.points[2].y = y + h - 1; + start2.points[3].x = x + w - 1; + start2.points[3].y = y + h - 1; + + end2.points[0].x = 600; + end2.points[0].y = 200 + 50; + end2.points[1].x = 700; + end2.points[1].y = 200 + 50; + end2.points[2].x = 600; + end2.points[2].y = 200 + 80; + end2.points[3].x = 700; + end2.points[3].y = 200 + 130; + +#define STEPS 50 + + for (i = 0; i < STEPS; ++i) + { + Distortion distortion[2]; + Picture buffer; + + quad_to_quad_interpolate (&start1, &end1, &distortion[0].destination, i/((double)STEPS - 1)); + quad_to_quad_interpolate (&start2, &end2, &distortion[1].destination, i/((double)STEPS - 1)); + + distortion[0].source.x = 0; + distortion[0].source.y = 0; + distortion[0].source.width = cwindow_get_width (cwindow) / 2; + distortion[0].source.height = cwindow_get_height (cwindow); + + distortion[1].source.x = cwindow_get_width (cwindow) / 2; + distortion[1].source.y = 0; + distortion[1].source.width = cwindow_get_width (cwindow) / 2; + distortion[1].source.height = cwindow_get_height (cwindow); + + cwindow_set_transformation (cwindow, distortion, 2); + + buffer = create_root_buffer (window->screen); + + { + XRectangle r; + XserverRegion region; + + r.x = 0; + r.y = 0; + r.width = window->screen->width; + r.height = window->screen->height; + + region = XFixesCreateRegion (compositor->display->xdisplay, &r, 1); + + XFixesDestroyRegion (compositor->display->xdisplay, + do_paint_screen (compositor, window->screen, buffer, region)); + XFixesDestroyRegion (compositor->display->xdisplay, region); + } + + cwindow_new_draw (cwindow, buffer, None); + + XFixesSetPictureClipRegion (compositor->display->xdisplay, + window->screen->root_picture, 0, 0, None); + /* Copy buffer to root window */ + paint_buffer (window->screen, buffer); + + XRenderFreePicture (compositor->display->xdisplay, buffer); + + XSync (compositor->display->xdisplay, False); +#if 0 + g_usleep (500000); +#endif + } +} + +MetaDisplay * +meta_compositor_get_display (MetaCompositor *compositor) +{ + return compositor->display; +} diff --git a/src/compositor.h b/src/compositor.h index d1e824b3..4b37e7f6 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -25,6 +25,8 @@ #include "util.h" #include "display.h" +#include <X11/extensions/Xfixes.h> + MetaCompositor* meta_compositor_new (MetaDisplay *display); void meta_compositor_unref (MetaCompositor *compositor); void meta_compositor_process_event (MetaCompositor *compositor, @@ -44,13 +46,18 @@ void meta_compositor_unmanage_screen (MetaCompositor *compositor, void meta_compositor_damage_window (MetaCompositor *compositor, MetaWindow *window); -#endif /* META_COMPOSITOR_H */ - - - - - - - +void meta_compositor_stop_compositing (MetaCompositor *compositor, + MetaWindow *window); +void meta_compositor_start_compositing (MetaCompositor *compositor, + MetaWindow *window); +MetaDisplay *meta_compositor_get_display (MetaCompositor *compositor); +void +meta_compositor_genie (MetaCompositor *compositor, + MetaWindow *window); +void +meta_compositor_invalidate_region (MetaCompositor *compositor, + MetaScreen *screen, + XserverRegion invalid_area); +#endif /* META_COMPOSITOR_H */ diff --git a/src/cwindow.c b/src/cwindow.c new file mode 100644 index 00000000..6d4020ab --- /dev/null +++ b/src/cwindow.c @@ -0,0 +1,902 @@ +#include <X11/Xlib.h> +#include "cwindow.h" +#include "errors.h" +#include "compositor.h" +#include "matrix.h" + +#define SHADOW_OFFSET 10 +/* 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 + * newly-mapped window was in the stack. A MetaCompositorWindow may + * correspond to a metacity window frame rather than an application + * window. + */ +struct CWindow +{ + Window xwindow; + +#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; + + Damage damage; + XserverRegion last_painted_extents; + + XserverRegion border_size; + + Pixmap pixmap; + + unsigned int managed : 1; + unsigned int damaged : 1; + unsigned int viewable : 1; + unsigned int input_only : 1; + + unsigned int screen_index : 8; + + Visual *visual; + + Distortion *distortions; + int n_distortions; +#endif +}; + +static Display *cwindow_get_xdisplay (CWindow *cwindow); + +#ifdef HAVE_COMPOSITE_EXTENSIONS +void +cwindow_free (CWindow *cwindow) +{ + g_assert (cwindow->damage != None); + + meta_error_trap_push (meta_compositor_get_display (cwindow->compositor)); + /* This seems to cause an error if the window + * is destroyed? + */ + 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); + + g_free (cwindow); +} +#endif /* HAVE_COMPOSITE_EXTENSIONS */ + +#ifdef HAVE_COMPOSITE_EXTENSIONS +XserverRegion +cwindow_extents (CWindow *cwindow) +{ + XRectangle r; + + r.x = cwindow->x; + r.y = cwindow->y; + r.width = cwindow->width; + r.height = cwindow->height; + + r.width += SHADOW_OFFSET; + r.height += SHADOW_OFFSET; + + return XFixesCreateRegion (cwindow_get_xdisplay (cwindow), &r, 1); +} +#endif /* HAVE_COMPOSITE_EXTENSIONS */ + +void +cwindow_get_paint_bounds (CWindow *cwindow, + int *x, + int *y, + int *w, + int *h) +{ + if (cwindow->pixmap != None) + { + *x = cwindow->x; + *y = cwindow->y; + *w = cwindow->width + cwindow->border_width * 2; + *h = cwindow->height + cwindow->border_width * 2; + } + else + { + *x = cwindow->x + cwindow->border_width; + *y = cwindow->y + cwindow->border_width; + *w = cwindow->width; + *h = cwindow->height; + } +} + +Drawable +cwindow_get_drawable (CWindow *cwindow) +{ + if (cwindow->pixmap) + return cwindow->pixmap; + else + return cwindow->xwindow; +} + +void +cwindow_destroy_last_painted_extents (CWindow *cwindow) +{ + if (cwindow->last_painted_extents) + { + XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), cwindow->last_painted_extents); + cwindow->last_painted_extents = None; + } +} + +void +cwindow_set_last_painted_extents (CWindow *cwindow, XserverRegion extents) +{ + cwindow_destroy_last_painted_extents (cwindow); + cwindow->last_painted_extents = extents; +} + +MetaScreen* +cwindow_get_screen (CWindow *cwindow) +{ + MetaScreen *screen; + GSList *tmp; + + screen = NULL; + tmp = meta_compositor_get_display (cwindow->compositor)->screens; + while (tmp != NULL) + { + MetaScreen *s = tmp->data; + + if (s->number == cwindow->screen_index) + { + screen = s; + break; + } + + tmp = tmp->next; + } + g_assert (screen != NULL); + + return screen; +} + +CWindow * +cwindow_new (MetaCompositor *compositor, Window xwindow, XWindowAttributes *attrs) +{ + CWindow *cwindow; + Damage damage; + + /* Create Damage object to monitor window damage */ + meta_error_trap_push (meta_compositor_get_display (compositor)); + damage = XDamageCreate (meta_compositor_get_display (compositor)->xdisplay, + xwindow, XDamageReportNonEmpty); + meta_error_trap_pop (meta_compositor_get_display (compositor), FALSE); + + if (damage == None) + return NULL; + + cwindow = g_new0 (CWindow, 1); + + cwindow->compositor = compositor; + 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; + + if (attrs->class == InputOnly) + cwindow->input_only = TRUE; + else + cwindow->input_only = FALSE; + + 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); + + return cwindow; +} + +XID * +cwindow_get_xid_address (CWindow *cwindow) +{ + return &cwindow->xwindow; +} + +static Display * +cwindow_get_xdisplay (CWindow *cwindow) +{ + return meta_compositor_get_display (cwindow->compositor)->xdisplay; +} + + +Window +cwindow_get_xwindow (CWindow *cwindow) +{ + return cwindow->xwindow; +} + +gboolean +cwindow_get_viewable (CWindow *cwindow) +{ + return cwindow->viewable; +} + +gboolean +cwindow_get_input_only (CWindow *cwindow) +{ + return cwindow->input_only; +} + +Visual * +cwindow_get_visual (CWindow *cwindow) +{ + return cwindow->visual; +} + +XserverRegion +cwindow_get_last_painted_extents (CWindow *cwindow) +{ + return cwindow->last_painted_extents; +} + + +int +cwindow_get_x (CWindow *cwindow) +{ + return cwindow->x; +} + +int +cwindow_get_y (CWindow *cwindow) +{ + return cwindow->y; +} + +int +cwindow_get_width (CWindow *cwindow) +{ + return cwindow->width; +} + +int +cwindow_get_height (CWindow *cwindow) +{ + return cwindow->height; +} + +int +cwindow_get_border_width (CWindow *cwindow) +{ + return cwindow->border_width; +} + +Damage +cwindow_get_damage (CWindow *cwindow) +{ + return cwindow->damage; +} + +Pixmap +cwindow_get_pixmap (CWindow *cwindow) +{ + return cwindow->pixmap; +} + +MetaCompositor * +cwindow_get_compositor (CWindow *cwindow) +{ + return cwindow->compositor; +} + +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; +} + +void +cwindow_set_y (CWindow *cwindow, int y) +{ + cwindow->y = y; +} + +void +cwindow_set_width (CWindow *cwindow, int width) +{ + cwindow->width = width; +} + +void +cwindow_set_height (CWindow *cwindow, int height) +{ + cwindow->height = height; +} + + +void +cwindow_set_viewable (CWindow *cwindow, gboolean viewable) +{ + cwindow->viewable = viewable; +} + + +void +cwindow_set_border_width (CWindow *cwindow, int border_width) +{ + cwindow->border_width = border_width; +} + +static XFixed +double_to_fixed (gdouble d) +{ + return XDoubleToFixed (d); +} + +static void +convert_matrix (Matrix3 *matrix, XTransform *trans) +{ +#if 0 + matrix3_transpose (matrix); +#endif + trans->matrix[0][0] = double_to_fixed (matrix->coeff[0][0]); + trans->matrix[1][0] = double_to_fixed (matrix->coeff[1][0]); + trans->matrix[2][0] = double_to_fixed (matrix->coeff[2][0]); + trans->matrix[0][1] = double_to_fixed (matrix->coeff[0][1]); + trans->matrix[1][1] = double_to_fixed (matrix->coeff[1][1]); + trans->matrix[2][1] = double_to_fixed (matrix->coeff[2][1]); + trans->matrix[0][2] = double_to_fixed (matrix->coeff[0][2]); + trans->matrix[1][2] = double_to_fixed (matrix->coeff[1][2]); + trans->matrix[2][2] = double_to_fixed (matrix->coeff[2][2]); +} + +static void +get_transform (XTransform *trans, int x, int y, int w, int h) +{ + Matrix3 tmp; + + matrix3_identity (&tmp); + + transform_matrix_perspective (0, 0, w, h, + 0, 0, w - 1 - 0.1 * w, 0, + 0, 0 + h - 1 - 0.1 * h, 0 + w - 1, 0 + h - 1, + + &tmp); + +#if 0 + matrix3_translate (&tmp, 50, 50); +#endif + + matrix3_invert (&tmp); + + convert_matrix (&tmp, trans); +} + +void +cwindow_draw (CWindow *cwindow, Picture picture, XserverRegion damaged_region) +{ + /* Actually draw the window */ + XRenderPictFormat *format; + Picture wpicture; + XRenderPictureAttributes pa; + XTransform trans; + int x, y, w, h; + + if (cwindow_get_input_only (cwindow)) + return; + + if (!cwindow_get_viewable (cwindow)) + return; + + cwindow_get_paint_bounds (cwindow, &x, &y, &w, &h); + + format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow), + cwindow_get_visual (cwindow)); + pa.subwindow_mode = IncludeInferiors; + wpicture = XRenderCreatePicture (cwindow_get_xdisplay (cwindow), + cwindow_get_drawable (cwindow), + format, + CPSubwindowMode, + &pa); + + get_transform (&trans, x, y, w, h); + + if (cwindow_get_last_painted_extents (cwindow)) + cwindow_destroy_last_painted_extents (cwindow); + + cwindow_set_last_painted_extents (cwindow, cwindow_extents (cwindow)); + +#if 0 + meta_topic (META_DEBUG_COMPOSITOR, " Compositing window 0x%lx %d,%d %dx%d\n", + cwindow_get_xwindow (cwindow), + cwindow->x, cwindow->y, + cwindow->width, cwindow->height); +#endif + +#if 0 + { + XGCValues value; + GC gc; + + value.function = GXcopy; + value.subwindow_mode = IncludeInferiors; + + gc = XCreateGC (dpy, screen->xroot, GCFunction | GCSubwindowMode, &value); + XSetForeground (dpy, gc, rand()); + XFixesSetGCClipRegion (dpy, gc, 0, 0, damaged_region); + XFillRectangle (dpy, screen->xroot, gc, 0, 0, + screen->width, screen->height); + XFreeGC (dpy, gc); + XSync (dpy, False); + g_usleep (70000); + } +#endif + + if (cwindow_is_translucent (cwindow)) + { + XRenderColor shadow_color = { 0x0000, 0, 0x0000, 0x70c0 }; + XFixesSetPictureClipRegion (cwindow_get_xdisplay (cwindow), + picture, 0, 0, + damaged_region); + + + + XRenderFillRectangle (cwindow_get_xdisplay (cwindow), PictOpOver, + picture, + &shadow_color, + cwindow_get_x (cwindow) + SHADOW_OFFSET, + cwindow_get_y (cwindow) + SHADOW_OFFSET, + cwindow_get_width (cwindow), + cwindow_get_height (cwindow)); + /* Draw window transparent while resizing */ + XRenderComposite (cwindow_get_xdisplay (cwindow), PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ + wpicture, + cwindow_get_screen (cwindow)->trans_picture, + picture, + 0, 0, 0, 0, + x, y, w, h); + } + else + { +#if 0 + XRenderSetPictureTransform (cwindow_get_xdisplay (cwindow), + wpicture, + &trans); + XRenderSetPictureFilter (cwindow_get_xdisplay (cwindow), wpicture, "bilinear", 0, 0); +#endif + + /* Draw window normally */ + XRenderColor shadow_color = { 0x0000, 0, 0x0000, 0x70c0 }; + +#if 0 + XFixesSetPictureClipRegion (dpy, + picture, 0, 0, + region_below); +#endif + + XFixesSetPictureClipRegion (cwindow_get_xdisplay (cwindow), + picture, 0, 0, + damaged_region); + + /* superlame drop shadow */ + XRenderFillRectangle (cwindow_get_xdisplay (cwindow), PictOpOver, + picture, + &shadow_color, + cwindow_get_x (cwindow) + SHADOW_OFFSET, + cwindow_get_y (cwindow) + SHADOW_OFFSET, + cwindow_get_width (cwindow), + cwindow_get_height (cwindow)); + + XRenderComposite (cwindow_get_xdisplay (cwindow), + PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ + wpicture, + None, + picture, + 0, 0, 0, 0, + x, y, w, h); + + } + XRenderFreePicture (cwindow_get_xdisplay (cwindow), wpicture); +} + +gboolean +cwindow_is_translucent (CWindow *cwindow) +{ + MetaCompositor *compositor = cwindow_get_compositor (cwindow); + MetaWindow *window = meta_display_lookup_x_window (meta_compositor_get_display (compositor), cwindow_get_xwindow (cwindow)); + return (window != NULL && + window == meta_compositor_get_display (compositor)->grab_window && + (meta_grab_op_is_resizing (meta_compositor_get_display (compositor)->grab_op) || + meta_grab_op_is_moving (meta_compositor_get_display (compositor)->grab_op))); +} + + +static XRectangle +bbox (Quad *q) +{ + int x1, x2, y1, y2; + XRectangle result; + int i; + + x2 = x1 = q->points[0].x; + y2 = y1 = q->points[0].y; + + for (i = 0; i < 4; ++i) + x1 = MIN (x1, q->points[i].x); + + for (i = 0; i < 4; ++i) + y1 = MIN (y1, q->points[i].y); + + for (i = 0; i < 4; ++i) + x2 = MAX (x2, q->points[i].x); + + for (i = 0; i < 4; ++i) + y2 = MAX (y2, q->points[i].y); + + result.x = x1; + result.y = y1; + result.width = x2 - x1 + 1; + result.height = y2 - y1 + 1; + +#if 0 + g_print ("bbox: %d %d %d %d\n", result.x, result.y, result.width, result.height); +#endif + + return result; +} + +static void +compute_transform (int x, int y, + int width, int height, + Quad *destination, + XTransform *transform) +{ + int tx, ty; + int i; + Quad tmp = *destination; + Matrix3 matrix; + + /* Translate destination so it starts in (x, y); + * + * We will position it correctly with the composite request + * Coordinates are source coordinates + * + * I believe this is a hackaround a bug in render transformation (basically + * it translates source coordinates, not destination as it's supposed to). + */ + tx = bbox (&tmp).x - x; + ty = bbox (&tmp).y - y; + + for (i = 0; i < 4; ++i) + { + tmp.points[i].x -= tx; + tmp.points[i].y -= ty; + } + + /* Compute the matrix */ + matrix3_identity (&matrix); + +#if 0 + matrix3_translate (&matrix, (gdouble)-x, (gdouble)-y); +#endif + + g_print ("mapping from %d %d %d %d to (%d %d) (%d %d) (%d %d) (%d %d)\n", x, y, width, height, + tmp.points[0].x, tmp.points[0].y, + tmp.points[1].x, tmp.points[1].y, + tmp.points[2].x, tmp.points[2].y, + tmp.points[3].x, tmp.points[3].y); + + transform_matrix_perspective (x, y, + x + width - 1, + y + height - 1, + + tmp.points[0].x, tmp.points[0].y, + tmp.points[1].x, tmp.points[1].y, + tmp.points[2].x, tmp.points[2].y, + tmp.points[3].x, tmp.points[3].y, + + &matrix); + + matrix3_invert (&matrix); + + /* convert to XTransform */ + convert_matrix (&matrix, transform); +} + +void +cwindow_draw_warped (CWindow *cwindow, + MetaScreen *screen, + Picture picture, + Quad *destination) +{ + MetaCompositor *compositor; + Display *display; + + Picture wpicture; + XRenderPictureAttributes pa; + XRenderPictFormat *format; + + XTransform transform; + + if (!cwindow) + return; + + if (cwindow_get_input_only (cwindow)) + return; + + if (!cwindow_get_viewable (cwindow)) + return; + + compositor = cwindow_get_compositor (cwindow); + display = meta_compositor_get_display (compositor)->xdisplay; + + + format = XRenderFindVisualFormat (meta_compositor_get_display (compositor)->xdisplay, + cwindow_get_visual (cwindow)); + pa.subwindow_mode = IncludeInferiors; + g_assert (meta_compositor_get_display (compositor)); + + wpicture = XRenderCreatePicture (display, cwindow_get_drawable (cwindow), format, CPSubwindowMode, &pa); + + g_assert (wpicture); + + compute_transform (0, 0, cwindow_get_width (cwindow), cwindow_get_height (cwindow), + destination, &transform); + + XRenderSetPictureTransform (display, wpicture, &transform); + XRenderSetPictureFilter (meta_compositor_get_display (compositor)->xdisplay, wpicture, "bilinear", 0, 0); + + XRenderComposite (meta_compositor_get_display (compositor)->xdisplay, + PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ + wpicture, + screen->trans_picture, + picture, + 0, 0, + 0, 0, + bbox (destination).x, bbox (destination).y, + bbox (destination).width, bbox (destination).height + 100); + + XRenderFreePicture (display, wpicture); +} + +#if 0 +static void +compute_transformation (int x, int y, int w, int h, Quad *dest, XTransform *trans) +{ + Matrix3 tmp; + + matrix3_identity (&tmp); + + transform_matrix_perspective (x, y, w, h, + + dest->points[0].x, dest->points[0].y, + dest->points[1].x, dest->points[1].y, + dest->points[2].x, dest->points[2].y, + dest->points[3].x, dest->points[3].y, + + &tmp); + + matrix3_invert (&tmp); + + convert_matrix (&tmp, trans); +} +#endif + +void +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 + if (window) + g_print ("damage on %lx (%s)\n", cwindow->xwindow, window->title); + else + g_print ("damage on unknown window\n"); +#endif + + region = XFixesCreateRegion (cwindow_get_xdisplay (cwindow), NULL, 0); + + /* translate region to screen; can error if window of damage is + * destroyed + */ + meta_error_trap_push (meta_compositor_get_display (cwindow->compositor)); + XDamageSubtract (cwindow_get_xdisplay (cwindow), + cwindow_get_damage (cwindow), None, region); + meta_error_trap_pop (meta_compositor_get_display (cwindow->compositor), FALSE); + + XFixesTranslateRegion (cwindow_get_xdisplay (cwindow), + region, + cwindow_get_x (cwindow), + cwindow_get_y (cwindow)); + + screen = cwindow_get_screen (cwindow); + + meta_compositor_invalidate_region (cwindow->compositor, screen, region); + + XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region); +} + +void +cwindow_process_configure_notify (CWindow *cwindow, XConfigureEvent *event) +{ + XserverRegion region; + MetaScreen *screen; + + screen = cwindow_get_screen (cwindow); + + if (cwindow_get_last_painted_extents (cwindow)) + { + 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); + } + + region = cwindow_extents (cwindow); + + meta_compositor_invalidate_region (cwindow->compositor, + screen, + region); + + XFixesDestroyRegion (cwindow_get_xdisplay (cwindow), region); +} + +void +cwindow_set_transformation (CWindow *cwindow, + const Distortion *distortions, + int n_distortions) +{ + if (cwindow->distortions) + g_free (cwindow->distortions); + + cwindow->distortions = g_memdup (distortions, n_distortions * sizeof (Distortion)); + cwindow->n_distortions = n_distortions; +} + +void +cwindow_new_draw (CWindow *cwindow, Picture destination, XserverRegion damaged_region) +{ + XRenderPictFormat *format; + int i; + + if (cwindow_get_input_only (cwindow)) + return; + + if (!cwindow_get_viewable (cwindow)) + return; + + format = XRenderFindVisualFormat (cwindow_get_xdisplay (cwindow), + cwindow_get_visual (cwindow)); + + for (i = 0; i < cwindow->n_distortions; ++i) + { + XTransform transform; + Picture picture; + XRenderPictureAttributes pa; + + Distortion *dist = &cwindow->distortions[i]; + compute_transform (dist->source.x, + dist->source.y, + dist->source.width, dist->source.height, + &dist->destination, &transform); + + /* Draw window */ + pa.subwindow_mode = IncludeInferiors; + picture = XRenderCreatePicture (cwindow_get_xdisplay (cwindow), + cwindow_get_drawable (cwindow), + format, + CPSubwindowMode, + &pa); + + XRenderSetPictureTransform (cwindow_get_xdisplay (cwindow), picture, &transform); + XRenderSetPictureFilter (cwindow_get_xdisplay (cwindow), picture, "bilinear", 0, 0); + + XRenderComposite (cwindow_get_xdisplay (cwindow), + PictOpOver, /* PictOpOver for alpha, PictOpSrc without */ + picture, + cwindow_get_screen (cwindow)->trans_picture, + destination, + dist->source.x, dist->source.y, + 0, 0, + bbox (&dist->destination).x, bbox (&dist->destination).y, + bbox (&dist->destination).width, bbox (&dist->destination).height); + + { + int j = i + 2; + XRenderColor hilit_color = { (j / 10.0) * 0x0000, 0, (j / 10.0) * 0x9999, (j / 10.0) * 0xFFFF } ; + +#if 0 + XRenderFillRectangle (cwindow_get_xdisplay (cwindow), PictOpOver, + destination, + &hilit_color, + bbox (&dist->destination).x, bbox (&dist->destination).y, + bbox (&dist->destination).width, bbox (&dist->destination).height); +#endif + +#if 0 + g_print ("destination (%d %d) (%d %d) (%d %d) (%d %d)\n", + dist->destination.points[0].x, dist->destination.points[0].y, + dist->destination.points[1].x, dist->destination.points[1].y, + dist->destination.points[2].x, dist->destination.points[2].y, + dist->destination.points[3].x, dist->destination.points[3].y); + + g_print ("filling: %d %d %d %d\n", + bbox (&dist->destination).x, bbox (&dist->destination).y, + bbox (&dist->destination).width, bbox (&dist->destination).height); +#endif + + } + + XRenderFreePicture (cwindow_get_xdisplay (cwindow), picture); + } +} diff --git a/src/cwindow.h b/src/cwindow.h new file mode 100644 index 00000000..95ae9414 --- /dev/null +++ b/src/cwindow.h @@ -0,0 +1,106 @@ +#include "config.h" +#include <X11/extensions/Xfixes.h> +#include <X11/extensions/Xdamage.h> +#include <X11/extensions/Xrender.h> +#include <glib.h> +#include "screen.h" + +typedef struct CWindow CWindow; +typedef struct Quad Quad; +typedef struct Point Point; +typedef struct Rectangle Rectangle; +typedef struct Distortion Distortion; + +struct Point +{ + int x, y; +}; + +struct Quad +{ + Point points[4]; +}; + +struct Rectangle +{ + int x, y; + int width, height; +}; + +struct Distortion +{ + Rectangle source; + Quad destination; +}; + +void cwindow_set_transformation (CWindow *window, + const Distortion *distortions, + int n_distortions); +void cwindow_free (CWindow *cwindow); +XserverRegion cwindow_extents (CWindow *cwindow); +void cwindow_get_paint_bounds (CWindow *cwindow, + int *x, + int *y, + int *w, + int *h); +Drawable cwindow_get_drawable (CWindow *cwindow); +Window cwindow_get_xwindow (CWindow *cwindow); +gboolean cwindow_get_viewable (CWindow *cwindow); +gboolean cwindow_get_input_only (CWindow *cwindow); +Visual * cwindow_get_visual (CWindow *cwindow); +XserverRegion cwindow_get_last_painted_extents (CWindow *cwindow); +void cwindow_set_last_painted_extents (CWindow *cwindow, + XserverRegion region); +void cwindow_destroy_last_painted_extents (CWindow *cwindow); +int cwindow_get_x (CWindow *cwindow); +int cwindow_get_y (CWindow *cwindow); +int cwindow_get_width (CWindow *cwindow); +int cwindow_get_height (CWindow *cwindow); +int cwindow_get_border_width (CWindow *cwindow); +MetaScreen * cwindow_get_screen (CWindow *cwindow); +Damage cwindow_get_damage (CWindow *cwindow); +void cwindow_set_pending_x (CWindow *cwindow, + int pending_x); +void cwindow_set_pending_y (CWindow *cwindow, + int pending_y); +void cwindow_set_pending_width (CWindow *cwindow, + int width); +void cwindow_set_pending_height (CWindow *cwindow, + int height); +void cwindow_set_pending_border_width (CWindow *cwindow, + int border_width); +void cwindow_set_x (CWindow *cwindow, + int x); +void cwindow_set_y (CWindow *cwindow, + int y); +void cwindow_set_width (CWindow *cwindow, + int width); +void cwindow_set_height (CWindow *cwindow, + int height); +Pixmap cwindow_get_pixmap (CWindow *cwindow); +void cwindow_set_border_width (CWindow *cwindow, + int border_width); +void cwindow_set_viewable (CWindow *cwindow, + gboolean viewable); +CWindow * cwindow_new (MetaCompositor *compositor, + Window xwindow, + XWindowAttributes *attrs); +XID * cwindow_get_xid_address (CWindow *cwindow); +MetaCompositor *cwindow_get_compositor (CWindow *cwindow); +#if 0 +void cwindow_draw (CWindow *cwindow, + Picture picture, + XserverRegion damaged_region); +#endif +gboolean cwindow_is_translucent (CWindow *cwindow); +void cwindow_draw_warped (CWindow *cwindow, + MetaScreen *screen, + Picture picture, + Quad *destination); +void cwindow_process_damage_notify (CWindow *cwindow, + XDamageNotifyEvent *event); +void cwindow_process_configure_notify (CWindow *cwindow, + XConfigureEvent *event); +void cwindow_new_draw (CWindow *cwindow, + Picture destination, + XserverRegion damaged_region); diff --git a/src/effects.c b/src/effects.c index 0f5ccd4f..83a8668f 100644 --- a/src/effects.c +++ b/src/effects.c @@ -78,7 +78,7 @@ update_wireframe_window (MetaDisplay *display, XMoveResizeWindow (display->xdisplay, xwindow, rect->x, rect->y, - rect->width, rect->height); + rect->width, rect->height); #ifdef HAVE_SHAPE @@ -307,7 +307,7 @@ meta_effects_draw_box_animation (MetaScreen *screen, double seconds_duration, MetaBoxAnimType anim_type) { - BoxAnimationContext *context; + BoxAnimationContext *context; g_return_if_fail (seconds_duration > 0.0); diff --git a/src/matrix.c b/src/matrix.c new file mode 100644 index 00000000..55074585 --- /dev/null +++ b/src/matrix.c @@ -0,0 +1,615 @@ +/* This file is from The Gimp */ + +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * matrix.c + * Copyright (C) 1998 Jay Cox <jaycox@earthlink.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <glib.h> +#include "matrix.h" +#include <math.h> + +#define EPSILON 1e-6 + + +/** + * matrix2_identity: + * @matrix: A matrix. + * + * Sets the matrix to the identity matrix. + */ +void +matrix2_identity (Matrix2 *matrix) +{ + static const Matrix2 identity = { { { 1.0, 0.0 }, + { 0.0, 1.0 } } }; + + *matrix = identity; +} + +/** + * matrix2_mult: + * @matrix1: The first input matrix. + * @matrix2: The second input matrix which will be overwritten by the result. + * + * Multiplies two matrices and puts the result into the second one. + */ +void +matrix2_mult (const Matrix2 *matrix1, + Matrix2 *matrix2) +{ + Matrix2 tmp; + + tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] + + matrix1->coeff[0][1] * matrix2->coeff[1][0]); + tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] + + matrix1->coeff[0][1] * matrix2->coeff[1][1]); + tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] + + matrix1->coeff[1][1] * matrix2->coeff[1][0]); + tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] + + matrix1->coeff[1][1] * matrix2->coeff[1][1]); + + *matrix2 = tmp; +} + +/** + * matrix3_identity: + * @matrix: A matrix. + * + * Sets the matrix to the identity matrix. + */ +void +matrix3_identity (Matrix3 *matrix) +{ + static const Matrix3 identity = { { { 1.0, 0.0, 0.0 }, + { 0.0, 1.0, 0.0 }, + { 0.0, 0.0, 1.0 } } }; + + *matrix = identity; +} +/** + * matrix3_mult: + * @matrix1: The first input matrix. + * @matrix2: The second input matrix which will be overwritten by the result. + * + * Multiplies two matrices and puts the result into the second one. + */ +void +matrix3_mult (const Matrix3 *matrix1, + Matrix3 *matrix2) +{ + gint i, j; + Matrix3 tmp; + gdouble t1, t2, t3; + + for (i = 0; i < 3; i++) + { + t1 = matrix1->coeff[i][0]; + t2 = matrix1->coeff[i][1]; + t3 = matrix1->coeff[i][2]; + + for (j = 0; j < 3; j++) + { + tmp.coeff[i][j] = t1 * matrix2->coeff[0][j]; + tmp.coeff[i][j] += t2 * matrix2->coeff[1][j]; + tmp.coeff[i][j] += t3 * matrix2->coeff[2][j]; + } + } + + *matrix2 = tmp; +} + +/** + * matrix3_translate: + * @matrix: The matrix that is to be translated. + * @x: Translation in X direction. + * @y: Translation in Y direction. + * + * Translates the matrix by x and y. + */ +void +matrix3_translate (Matrix3 *matrix, + gdouble x, + gdouble y) +{ + gdouble g, h, i; + + g = matrix->coeff[2][0]; + h = matrix->coeff[2][1]; + i = matrix->coeff[2][2]; + + matrix->coeff[0][0] += x * g; + matrix->coeff[0][1] += x * h; + matrix->coeff[0][2] += x * i; + matrix->coeff[1][0] += y * g; + matrix->coeff[1][1] += y * h; + matrix->coeff[1][2] += y * i; +} + +void +matrix3_transpose (Matrix3 *matrix) +{ + int i, j; + for (i = 0; i < 3; ++i) + for (j = 0; j < 3; ++j) + { + int tmp; + tmp = matrix->coeff[i][j]; + matrix->coeff[i][j] = matrix->coeff[j][i]; + matrix->coeff[j][i] = tmp; + } +} + +/** + * matrix3_scale: + * @matrix: The matrix that is to be scaled. + * @x: X scale factor. + * @y: Y scale factor. + * + * Scales the matrix by x and y + */ +void +matrix3_scale (Matrix3 *matrix, + gdouble x, + gdouble y) +{ + matrix->coeff[0][0] *= x; + matrix->coeff[0][1] *= x; + matrix->coeff[0][2] *= x; + + matrix->coeff[1][0] *= y; + matrix->coeff[1][1] *= y; + matrix->coeff[1][2] *= y; +} + +/** + * matrix3_rotate: + * @matrix: The matrix that is to be rotated. + * @theta: The angle of rotation (in radians). + * + * Rotates the matrix by theta degrees. + */ +void +matrix3_rotate (Matrix3 *matrix, + gdouble theta) +{ + gdouble t1, t2; + gdouble cost, sint; + + cost = cos (theta); + sint = sin (theta); + + t1 = matrix->coeff[0][0]; + t2 = matrix->coeff[1][0]; + matrix->coeff[0][0] = cost * t1 - sint * t2; + matrix->coeff[1][0] = sint * t1 + cost * t2; + + t1 = matrix->coeff[0][1]; + t2 = matrix->coeff[1][1]; + matrix->coeff[0][1] = cost * t1 - sint * t2; + matrix->coeff[1][1] = sint * t1 + cost * t2; + + t1 = matrix->coeff[0][2]; + t2 = matrix->coeff[1][2]; + matrix->coeff[0][2] = cost * t1 - sint * t2; + matrix->coeff[1][2] = sint * t1 + cost * t2; +} + +/** + * matrix3_xshear: + * @matrix: The matrix that is to be sheared. + * @amount: X shear amount. + * + * Shears the matrix in the X direction. + */ +void +matrix3_xshear (Matrix3 *matrix, + gdouble amount) +{ + matrix->coeff[0][0] += amount * matrix->coeff[1][0]; + matrix->coeff[0][1] += amount * matrix->coeff[1][1]; + matrix->coeff[0][2] += amount * matrix->coeff[1][2]; +} + +/** + * matrix3_yshear: + * @matrix: The matrix that is to be sheared. + * @amount: Y shear amount. + * + * Shears the matrix in the Y direction. + */ +void +matrix3_yshear (Matrix3 *matrix, + gdouble amount) +{ + matrix->coeff[1][0] += amount * matrix->coeff[0][0]; + matrix->coeff[1][1] += amount * matrix->coeff[0][1]; + matrix->coeff[1][2] += amount * matrix->coeff[0][2]; +} + + +/** + * matrix3_affine: + * @matrix: The input matrix. + * @a: + * @b: + * @c: + * @d: + * @e: + * @f: + * + * Applies the affine transformation given by six values to @matrix. + * The six values form define an affine transformation matrix as + * illustrated below: + * + * ( a c e ) + * ( b d f ) + * ( 0 0 1 ) + **/ +void +matrix3_affine (Matrix3 *matrix, + gdouble a, + gdouble b, + gdouble c, + gdouble d, + gdouble e, + gdouble f) +{ + Matrix3 affine; + + affine.coeff[0][0] = a; + affine.coeff[1][0] = b; + affine.coeff[2][0] = 0.0; + + affine.coeff[0][1] = c; + affine.coeff[1][1] = d; + affine.coeff[2][1] = 0.0; + + affine.coeff[0][2] = e; + affine.coeff[1][2] = f; + affine.coeff[2][2] = 1.0; + + matrix3_mult (&affine, matrix); +} + + +/** + * matrix3_determinant: + * @matrix: The input matrix. + * + * Calculates the determinant of the given matrix. + * + * Returns: The determinant. + */ +gdouble +matrix3_determinant (const Matrix3 *matrix) +{ + gdouble determinant; + + determinant = (matrix->coeff[0][0] * + (matrix->coeff[1][1] * matrix->coeff[2][2] - + matrix->coeff[1][2] * matrix->coeff[2][1])); + determinant -= (matrix->coeff[1][0] * + (matrix->coeff[0][1] * matrix->coeff[2][2] - + matrix->coeff[0][2] * matrix->coeff[2][1])); + determinant += (matrix->coeff[2][0] * + (matrix->coeff[0][1] * matrix->coeff[1][2] - + matrix->coeff[0][2] * matrix->coeff[1][1])); + + return determinant; +} + +/** + * matrix3_invert: + * @matrix: The matrix that is to be inverted. + * + * Inverts the given matrix. + * + * Returns FALSE if the matrix is not invertible + */ +gboolean +matrix3_invert (Matrix3 *matrix) +{ + Matrix3 inv; + gdouble det; + + det = matrix3_determinant (matrix); + + if (det == 0.0) + return FALSE; + + det = 1.0 / det; + + inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] - + matrix->coeff[1][2] * matrix->coeff[2][1]) * det; + + inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] - + matrix->coeff[1][2] * matrix->coeff[2][0]) * det; + + inv.coeff[2][0] = (matrix->coeff[1][0] * matrix->coeff[2][1] - + matrix->coeff[1][1] * matrix->coeff[2][0]) * det; + + inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] - + matrix->coeff[0][2] * matrix->coeff[2][1]) * det; + + inv.coeff[1][1] = (matrix->coeff[0][0] * matrix->coeff[2][2] - + matrix->coeff[0][2] * matrix->coeff[2][0]) * det; + + inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] - + matrix->coeff[0][1] * matrix->coeff[2][0]) * det; + + inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] - + matrix->coeff[0][2] * matrix->coeff[1][1]) * det; + + inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] - + matrix->coeff[0][2] * matrix->coeff[1][0]) * det; + + inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] - + matrix->coeff[0][1] * matrix->coeff[1][0]) * det; + + *matrix = inv; + + return TRUE; +} + + +/* functions to test for matrix properties */ + + +/** + * matrix3_is_diagonal: + * @matrix: The matrix that is to be tested. + * + * Checks if the given matrix is diagonal. + * + * Returns: TRUE if the matrix is diagonal. + */ +gboolean +matrix3_is_diagonal (const Matrix3 *matrix) +{ + gint i, j; + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (i != j && fabs (matrix->coeff[i][j]) > EPSILON) + return FALSE; + } + } + + return TRUE; +} + +/** + * matrix3_is_identity: + * @matrix: The matrix that is to be tested. + * + * Checks if the given matrix is the identity matrix. + * + * Returns: TRUE if the matrix is the identity matrix. + */ +gboolean +matrix3_is_identity (const Matrix3 *matrix) +{ + gint i, j; + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (i == j) + { + if (fabs (matrix->coeff[i][j] - 1.0) > EPSILON) + return FALSE; + } + else + { + if (fabs (matrix->coeff[i][j]) > EPSILON) + return FALSE; + } + } + } + + return TRUE; +} + +/* Check if we'll need to interpolate when applying this matrix. + This function returns TRUE if all entries of the upper left + 2x2 matrix are either 0 or 1 +*/ + + +/** + * matrix3_is_simple: + * @matrix: The matrix that is to be tested. + * + * Checks if we'll need to interpolate when applying this matrix as + * a transformation. + * + * Returns: TRUE if all entries of the upper left 2x2 matrix are either + * 0 or 1 + */ +gboolean +matrix3_is_simple (const Matrix3 *matrix) +{ + gdouble absm; + gint i, j; + + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + { + absm = fabs (matrix->coeff[i][j]); + if (absm > EPSILON && fabs (absm - 1.0) > EPSILON) + return FALSE; + } + } + + return TRUE; +} + +/** + * matrix4_to_deg: + * @matrix: + * @a: + * @b: + * @c: + * + * + **/ +void +matrix4_to_deg (const Matrix4 *matrix, + gdouble *a, + gdouble *b, + gdouble *c) +{ + *a = 180 * (asin (matrix->coeff[1][0]) / G_PI_2); + *b = 180 * (asin (matrix->coeff[2][0]) / G_PI_2); + *c = 180 * (asin (matrix->coeff[2][1]) / G_PI_2); +} + +void +transform_matrix_perspective (gint x1, + gint y1, + gint x2, + gint y2, + gdouble tx1, + gdouble ty1, + gdouble tx2, + gdouble ty2, + gdouble tx3, + gdouble ty3, + gdouble tx4, + gdouble ty4, + Matrix3 *result) +{ + Matrix3 matrix; + gdouble scalex; + gdouble scaley; + + scalex = scaley = 1.0; + + if ((x2 - x1) > 0) + scalex = 1.0 / (gdouble) (x2 - x1); + + if ((y2 - y1) > 0) + scaley = 1.0 / (gdouble) (y2 - y1); + + /* Determine the perspective transform that maps from + * the unit cube to the transformed coordinates + */ + { + gdouble dx1, dx2, dx3, dy1, dy2, dy3; + + dx1 = tx2 - tx4; + dx2 = tx3 - tx4; + dx3 = tx1 - tx2 + tx4 - tx3; + + dy1 = ty2 - ty4; + dy2 = ty3 - ty4; + dy3 = ty1 - ty2 + ty4 - ty3; + + /* Is the mapping affine? */ + if ((dx3 == 0.0) && (dy3 == 0.0)) + { + matrix.coeff[0][0] = tx2 - tx1; + matrix.coeff[0][1] = tx4 - tx2; + matrix.coeff[0][2] = tx1; + matrix.coeff[1][0] = ty2 - ty1; + matrix.coeff[1][1] = ty4 - ty2; + matrix.coeff[1][2] = ty1; + matrix.coeff[2][0] = 0.0; + matrix.coeff[2][1] = 0.0; + } + else + { + gdouble det1, det2; + + det1 = dx3 * dy2 - dy3 * dx2; + det2 = dx1 * dy2 - dy1 * dx2; + + if (det1 == 0.0 && det2 == 0.0) + matrix.coeff[2][0] = 1.0; + else + matrix.coeff[2][0] = det1 / det2; + + det1 = dx1 * dy3 - dy1 * dx3; + + if (det1 == 0.0 && det2 == 0.0) + matrix.coeff[2][1] = 1.0; + else + matrix.coeff[2][1] = det1 / det2; + + matrix.coeff[0][0] = tx2 - tx1 + matrix.coeff[2][0] * tx2; + matrix.coeff[0][1] = tx3 - tx1 + matrix.coeff[2][1] * tx3; + matrix.coeff[0][2] = tx1; + + matrix.coeff[1][0] = ty2 - ty1 + matrix.coeff[2][0] * ty2; + matrix.coeff[1][1] = ty3 - ty1 + matrix.coeff[2][1] * ty3; + matrix.coeff[1][2] = ty1; + } + + matrix.coeff[2][2] = 1.0; + } + + matrix3_identity (result); + matrix3_translate (result, -x1, -y1); + matrix3_scale (result, scalex, scaley); + matrix3_mult (&matrix, result); +} + +void +matrix3_multiply_vector (const Matrix3 *A, + const Vector3 *v, + Vector3 *result) +{ + result->coeff[0] = + v->coeff[0] * A->coeff[0][0] + + v->coeff[1] * A->coeff[1][0] + + v->coeff[2] * A->coeff[2][0]; + result->coeff[1] = + v->coeff[0] * A->coeff[0][1] + + v->coeff[1] * A->coeff[1][1] + + v->coeff[2] * A->coeff[2][1]; + result->coeff[2] = + v->coeff[0] * A->coeff[0][2] + + v->coeff[1] * A->coeff[1][2] + + v->coeff[2] * A->coeff[2][2]; +} + +#if 0 +void +solve_3x3 (const Matrix3 *A, + Vector3 *x, + const Vector3 *b) +{ + Matrix3 inv = *A; + if (matrix3_invert (&inv)) + { + matrix3_multiply_vector (&inv, b, x); + return TRUE; + } + else + { + return FALSE; + } +} +#endif diff --git a/src/matrix.h b/src/matrix.h new file mode 100644 index 00000000..1bc6cba9 --- /dev/null +++ b/src/matrix.h @@ -0,0 +1,118 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * matrix.h + * Copyright (C) 1998 Jay Cox <jaycox@earthlink.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __MATRIX_H__ +#define __MATRIX_H__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + +typedef struct _Matrix2 Matrix2; +typedef struct _Matrix3 Matrix3; +typedef struct _Matrix4 Matrix4; +typedef struct _Vector3 Vector3; + +struct _Matrix2 +{ + gdouble coeff[2][2]; +}; + +struct _Matrix3 +{ + gdouble coeff[3][3]; +}; + +struct _Matrix4 +{ + gdouble coeff[4][4]; +}; + +struct _Vector3 +{ + gdouble coeff[3]; +}; + + +void matrix2_identity (Matrix2 *matrix); +void matrix2_mult (const Matrix2 *matrix1, + Matrix2 *matrix2); + +void matrix3_transpose (Matrix3 *matrix); + +void matrix3_identity (Matrix3 *matrix); +void matrix3_mult (const Matrix3 *matrix1, + Matrix3 *matrix2); +void matrix3_translate (Matrix3 *matrix, + gdouble x, + gdouble y); +void matrix3_scale (Matrix3 *matrix, + gdouble x, + gdouble y); +void matrix3_rotate (Matrix3 *matrix, + gdouble theta); +void matrix3_xshear (Matrix3 *matrix, + gdouble amount); +void matrix3_yshear (Matrix3 *matrix, + gdouble amount); +void matrix3_affine (Matrix3 *matrix, + gdouble a, + gdouble b, + gdouble c, + gdouble d, + gdouble e, + gdouble f); +gdouble matrix3_determinant (const Matrix3 *matrix); +gboolean matrix3_invert (Matrix3 *matrix); +gboolean matrix3_is_diagonal (const Matrix3 *matrix); +gboolean matrix3_is_identity (const Matrix3 *matrix); +gboolean matrix3_is_simple (const Matrix3 *matrix); +void matrix3_multiply_vector (const Matrix3 *A, + const Vector3 *x, + Vector3 *result); +void matrix3_transform_point (const Matrix3 *matrix, + gdouble x, + gdouble y, + gdouble *newx, + gdouble *newy); + +void matrix4_to_deg (const Matrix4 *matrix, + gdouble *a, + gdouble *b, + gdouble *c); +void transform_matrix_perspective (gint x1, + gint y1, + gint x2, + gint y2, + gdouble tx1, + gdouble ty1, + gdouble tx2, + gdouble ty2, + gdouble tx3, + gdouble ty3, + gdouble tx4, + gdouble ty4, + Matrix3 *result); + +G_END_DECLS + +#endif /* __MATRIX_H__ */ diff --git a/src/screen.c b/src/screen.c index ab07dd80..07bb4336 100644 --- a/src/screen.c +++ b/src/screen.c @@ -644,6 +644,8 @@ meta_screen_new (MetaDisplay *display, meta_compositor_manage_screen (screen->display->compositor, screen); + + XSync (screen->display->xdisplay, False); meta_verbose ("Added screen %d ('%s') root 0x%lx\n", screen->number, screen->screen_name, screen->xroot); @@ -756,11 +758,21 @@ meta_screen_manage_all_windows (MetaScreen *screen) } else { - meta_window_new_with_attrs (screen->display, children[i], TRUE, - &attrs); + MetaWindow *window = + meta_window_new_with_attrs (screen->display, children[i], TRUE, + &attrs); meta_compositor_add_window (screen->display->compositor, children[i], &attrs); + + if (window && window->frame) + { + XGetWindowAttributes (screen->display->xdisplay, + window->frame->xwindow, &attrs); + + meta_compositor_add_window (screen->display->compositor, + window->frame->xwindow, &attrs); + } } ++i; @@ -261,6 +261,8 @@ meta_ui_map_frame (MetaUI *ui, window = gdk_xid_table_lookup (xwindow); + meta_verbose ("Mapping 0x%lx which is a frame window\n", xwindow); + if (window) gdk_window_show_unraised (window); } diff --git a/src/window.c b/src/window.c index c410a2d2..75bdeaaa 100644 --- a/src/window.c +++ b/src/window.c @@ -39,6 +39,7 @@ #include "group.h" #include "window-props.h" #include "constraints.h" +#include "compositor.h" #include <X11/Xatom.h> #include <string.h> @@ -226,11 +227,14 @@ meta_window_new_with_attrs (MetaDisplay *display, Atom initial_props[N_INITIAL_PROPS]; int i; gboolean has_shape; + char *name = NULL; g_assert (attrs != NULL); g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); - - meta_verbose ("Attempting to manage 0x%lx\n", xwindow); + + XFetchName (display->xdisplay, xwindow, &name); + + meta_verbose ("Attempting to manage 0x%lx (%s)\n", xwindow, name? name : "<no name>"); if (xwindow == display->no_focus_window) { @@ -521,9 +525,8 @@ meta_window_new_with_attrs (MetaDisplay *display, window->stack_position = -1; window->initial_workspace = 0; /* not used */ window->initial_timestamp = 0; /* not used */ - - meta_display_register_x_window (display, &window->xwindow, window); + meta_display_register_x_window (display, &window->xwindow, window); /* assign the window to its group, or create a new group if needed */ @@ -1327,11 +1330,14 @@ implement_showing (MetaWindow *window, meta_window_get_outer_rect (window, &window_rect); /* Draw a nice cool animation */ +#if 0 meta_effects_draw_box_animation (window->screen, &window_rect, &icon_rect, META_MINIMIZE_ANIMATION_LENGTH, META_BOX_ANIM_SCALE); +#endif + meta_compositor_genie (window->display->compositor, window); } meta_window_hide (window); @@ -2455,6 +2461,9 @@ meta_window_move_resize_internal (MetaWindow *window, meta_frame_calc_geometry (window->frame, &fgeom); + + meta_compositor_stop_compositing (window->display->compositor, window); + if (is_configure_request || do_gravity_adjust) { adjust_for_gravity (window, @@ -6275,6 +6284,8 @@ update_resize (MetaWindow *window, gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); g_assert (gravity >= 0); + meta_compositor_start_compositing (window->display->compositor, window); + if (window->display->grab_wireframe_active) { /* FIXME This is crap. For example, the wireframe isn't @@ -6307,7 +6318,7 @@ update_resize (MetaWindow *window, } else { - meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); + meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); } /* Store the latest resize time, if we actually resized. */ @@ -6414,7 +6425,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, window->disable_sync = FALSE; window->sync_request_time.tv_sec = 0; window->sync_request_time.tv_usec = 0; - + /* This means we are ready for another configure. */ switch (window->display->grab_op) { |