aboutsummaryrefslogtreecommitdiffstats
path: root/matchbox/mb-wm-comp-mgr-xrender.c
diff options
context:
space:
mode:
Diffstat (limited to 'matchbox/mb-wm-comp-mgr-xrender.c')
-rw-r--r--matchbox/mb-wm-comp-mgr-xrender.c1837
1 files changed, 1837 insertions, 0 deletions
diff --git a/matchbox/mb-wm-comp-mgr-xrender.c b/matchbox/mb-wm-comp-mgr-xrender.c
new file mode 100644
index 0000000..b3ae255
--- /dev/null
+++ b/matchbox/mb-wm-comp-mgr-xrender.c
@@ -0,0 +1,1837 @@
+/*
+ * Matchbox Window Manager - A lightweight window manager not for the
+ * desktop.
+ *
+ * Authored By Matthew Allum <mallum@o-hand.com>
+ * Tomas Frydrych <tf@o-hand.com>
+ *
+ * Copyright (c) 2002, 2004, 2007, 2008 OpenedHand Ltd - http://o-hand.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "matchbox.h"
+#include "mb-wm-client.h"
+#include "mb-wm-comp-mgr.h"
+#include "mb-wm-comp-mgr-xrender.h"
+
+#include <math.h>
+
+#include <X11/Xresource.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/Xcomposite.h>
+
+#define SHADOW_RADIUS 6
+#define SHADOW_OPACITY 0.75
+#define SHADOW_OFFSET_X (-SHADOW_RADIUS)
+#define SHADOW_OFFSET_Y (-SHADOW_RADIUS)
+
+/*
+ * A helper object to store manager's per-client data
+ */
+struct MBWMCompMgrDefaultClient
+{
+ MBWMCompMgrClient parent;
+
+ int damaged;
+ Damage damage;
+ Picture picture;
+ XserverRegion extents;
+ XserverRegion border_clip;
+};
+
+static void
+mb_wm_comp_mgr_xrender_client_show_real (MBWMCompMgrClient * client);
+
+static void
+mb_wm_comp_mgr_xrender_client_hide_real (MBWMCompMgrClient * client);
+
+static void
+mb_wm_comp_mgr_xrender_client_repair_real (MBWMCompMgrClient * client);
+
+static void
+mb_wm_comp_mgr_xrender_client_configure_real (MBWMCompMgrClient * client);
+
+static void
+mb_wm_comp_mgr_xrender_client_class_init (MBWMObjectClass *klass)
+{
+ MBWMCompMgrClientClass *c_klass = MB_WM_COMP_MGR_CLIENT_CLASS (klass);
+
+ c_klass->show = mb_wm_comp_mgr_xrender_client_show_real;
+ c_klass->hide = mb_wm_comp_mgr_xrender_client_hide_real;
+ c_klass->repair = mb_wm_comp_mgr_xrender_client_repair_real;
+ c_klass->configure = mb_wm_comp_mgr_xrender_client_configure_real;
+
+#if MBWM_WANT_DEBUG
+ klass->klass_name = "MBWMCompMgrDefaultClient";
+#endif
+}
+
+static int
+mb_wm_comp_mgr_xrender_client_init (MBWMObject *obj, va_list vap)
+{
+ MBWMCompMgrClient *client = MB_WM_COMP_MGR_CLIENT (obj);
+ MBWMCompMgrDefaultClient *dclient = MB_WM_COMP_MGR_DEFAULT_CLIENT (obj);
+ MBWindowManager *wm;
+ MBWindowManagerClient *wm_client = client->wm_client;
+
+ if (!wm_client || !wm_client->wmref)
+ return 0;
+
+ return 1;
+}
+
+static void
+mb_wm_comp_mgr_xrender_client_destroy (MBWMObject* obj)
+{
+ MBWMCompMgrClient * c = MB_WM_COMP_MGR_CLIENT (obj);
+ MBWMCompMgrDefaultClient * dc = MB_WM_COMP_MGR_DEFAULT_CLIENT (obj);
+ MBWindowManager * wm = c->wm;
+
+ mb_wm_comp_mgr_client_hide (c);
+
+ if (dc->damage)
+ XDamageDestroy (wm->xdpy, dc->damage);
+
+ if (dc->picture)
+ XRenderFreePicture (wm->xdpy, dc->picture);
+
+ if (dc->extents)
+ XFixesDestroyRegion (wm->xdpy, dc->extents);
+
+ if (dc->border_clip)
+ XFixesDestroyRegion (wm->xdpy, dc->border_clip);
+}
+
+int
+mb_wm_comp_mgr_xrender_client_class_type ()
+{
+ static int type = 0;
+
+ if (UNLIKELY(type == 0))
+ {
+ static MBWMObjectClassInfo info = {
+ sizeof (MBWMCompMgrDefaultClientClass),
+ sizeof (MBWMCompMgrDefaultClient),
+ mb_wm_comp_mgr_xrender_client_init,
+ mb_wm_comp_mgr_xrender_client_destroy,
+ mb_wm_comp_mgr_xrender_client_class_init
+ };
+
+ type =
+ mb_wm_object_register_class (&info, MB_WM_TYPE_COMP_MGR_CLIENT, 0);
+ }
+
+ return type;
+}
+
+/*
+ * This is a private method, hence static
+ */
+static MBWMCompMgrClient *
+mb_wm_comp_mgr_xrender_client_new (MBWindowManagerClient * client)
+{
+ MBWMObject *c;
+
+ c = mb_wm_object_new (MB_WM_TYPE_COMP_MGR_DEFAULT_CLIENT,
+ MBWMObjectPropClient, client,
+ NULL);
+
+ return MB_WM_COMP_MGR_CLIENT (c);
+}
+
+static void
+mb_wm_comp_mgr_xrender_add_damage (MBWMCompMgr * mgr, XserverRegion damage);
+
+static XserverRegion
+mb_wm_comp_mgr_xrender_client_extents (MBWMCompMgrClient *client);
+
+static void
+mb_wm_comp_mgr_xrender_client_hide_real (MBWMCompMgrClient * client)
+{
+ MBWMCompMgrDefaultClient * dclient = MB_WM_COMP_MGR_DEFAULT_CLIENT (client);
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ MBWMCompMgr * mgr = wm->comp_mgr;
+ MBWindowManagerClient * c;
+ Bool is_modal = mb_wm_client_is_modal (wm_client);
+
+ if (is_modal && ((c = mb_wm_get_visible_main_client (wm)) != NULL))
+ {
+ XserverRegion extents;
+ /* We need to make sure the any lowlighting on a 'parent'
+ * modal for app gets cleared. This is kind of a sledgehammer
+ * approach to it, but more suttle attempts oddly fail at times.
+ *
+ * FIXME: keep an eye on this for future revisions of composite
+ * - there may be a better way.
+ */
+ mb_wm_comp_mgr_xrender_client_repair_real (c->cm_client);
+ extents = mb_wm_comp_mgr_xrender_client_extents (c->cm_client);
+ mb_wm_comp_mgr_xrender_add_damage (mgr, extents);
+ }
+
+ if (dclient->damage)
+ {
+ XDamageDestroy (wm->xdpy, dclient->damage);
+ dclient->damage = None;
+ }
+
+ if (dclient->extents)
+ {
+ mb_wm_comp_mgr_xrender_add_damage (mgr, dclient->extents);
+ dclient->extents = None;
+ }
+
+ if (dclient->picture)
+ {
+ XRenderFreePicture (wm->xdpy, dclient->picture);
+ dclient->picture = None;
+ }
+}
+
+static void
+mb_wm_comp_mgr_xrender_client_show_real (MBWMCompMgrClient * client)
+{
+ MBWMCompMgrDefaultClient * dclient = MB_WM_COMP_MGR_DEFAULT_CLIENT (client);
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ MBWMCompMgr * mgr = wm->comp_mgr;
+ XserverRegion region;
+ XRenderPictureAttributes pa;
+ MBWMClientType ctype = MB_WM_CLIENT_CLIENT_TYPE (wm_client);
+ Bool is_modal;
+
+ /*
+ * Destroying / Recreating the client pictures should hopefully save
+ * some memory in the server.
+ */
+ if (!dclient->picture)
+ {
+ pa.subwindow_mode = IncludeInferiors;
+
+ dclient->picture =
+ XRenderCreatePicture (wm->xdpy,
+ wm_client->xwin_frame ?
+ wm_client->xwin_frame :
+ wm_client->window->xwindow,
+ client->is_argb32 ?
+ XRenderFindStandardFormat (wm->xdpy,
+ PictStandardARGB32)
+
+ : XRenderFindVisualFormat (wm->xdpy,
+ wm_client->window->visual),
+ CPSubwindowMode,
+ &pa);
+ }
+
+ if (dclient->damage != None)
+ XDamageDestroy (wm->xdpy, dclient->damage);
+
+ dclient->damage = XDamageCreate (wm->xdpy,
+ wm_client->xwin_frame ?
+ wm_client->xwin_frame :
+ wm_client->window->xwindow,
+ XDamageReportNonEmpty);
+
+ region = mb_wm_comp_mgr_xrender_client_extents (client);
+
+ mb_wm_comp_mgr_xrender_add_damage (mgr, region);
+
+ /*
+ * If the wm client is modal we have to add its parent to the damage
+ * in order for lowlighting to work
+ */
+ if (mb_wm_client_is_modal (wm_client))
+ {
+ MBWindowManagerClient * parent =
+ mb_wm_client_get_transient_for (wm_client);
+
+ if (parent && parent->cm_client)
+ {
+ XserverRegion extents =
+ mb_wm_comp_mgr_xrender_client_extents (parent->cm_client);
+
+ mb_wm_comp_mgr_xrender_add_damage (mgr, extents);
+ }
+ }
+
+ if (!dclient->extents)
+ {
+ dclient->extents = mb_wm_comp_mgr_xrender_client_extents (client);
+ }
+}
+
+
+/*
+ * The Manager itself
+ */
+
+typedef struct MBGaussianMap
+{
+ int size;
+ double * data;
+} MBGaussianMap;
+
+
+struct MBWMCompMgrDefaultPrivate
+{
+ MBGaussianMap * gaussian_map;
+
+ Picture shadow_n_pic;
+ Picture shadow_e_pic;
+ Picture shadow_s_pic;
+ Picture shadow_w_pic;
+
+ Picture shadow_ne_pic;
+ Picture shadow_nw_pic;
+ Picture shadow_se_pic;
+ Picture shadow_sw_pic;
+
+ Picture shadow_pic;
+
+ int shadow_dx;
+ int shadow_dy;
+ int shadow_padding_width;
+ int shadow_padding_height;
+ int shadow_style;
+ unsigned int shadow_color[4]; /* RGBA */
+
+ Picture trans_picture;
+ Picture black_picture;
+ Picture lowlight_picture;
+ unsigned int lowlight_params[4]; /* RGBA */
+
+ Picture root_picture;
+ Picture root_buffer;
+
+ XserverRegion all_damage;
+ Bool dialog_shade;
+};
+
+static void
+mb_wm_comp_mgr_xrender_private_free (MBWMCompMgrDefault *mgr)
+{
+ MBWMCompMgrDefaultPrivate * priv = mgr->priv;
+ Display * xdpy = MB_WM_COMP_MGR (mgr)->wm->xdpy;
+
+ if (priv->gaussian_map)
+ free (priv->gaussian_map);
+
+ XRenderFreePicture (xdpy, priv->shadow_n_pic);
+ XRenderFreePicture (xdpy, priv->shadow_e_pic);
+ XRenderFreePicture (xdpy, priv->shadow_s_pic);
+ XRenderFreePicture (xdpy, priv->shadow_w_pic);
+
+ XRenderFreePicture (xdpy, priv->shadow_ne_pic);
+ XRenderFreePicture (xdpy, priv->shadow_nw_pic);
+ XRenderFreePicture (xdpy, priv->shadow_se_pic);
+ XRenderFreePicture (xdpy, priv->shadow_sw_pic);
+
+ XRenderFreePicture (xdpy, priv->shadow_pic);
+
+ XRenderFreePicture (xdpy, priv->black_picture);
+ XRenderFreePicture (xdpy, priv->lowlight_picture);
+ XRenderFreePicture (xdpy, priv->trans_picture);
+
+ if (priv->root_picture)
+ XRenderFreePicture (xdpy, priv->root_picture);
+
+ if (priv->root_buffer)
+ XRenderFreePicture (xdpy, priv->root_buffer);
+
+ if (priv->all_damage)
+ XDamageDestroy (xdpy, priv->all_damage);
+
+ free (priv);
+}
+
+static void
+mb_wm_comp_mgr_xrender_register_client_real (MBWMCompMgr * mgr,
+ MBWindowManagerClient * c)
+{
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+
+ MBWM_NOTE (COMPOSITOR, "@@@@ registering client for %x @@@@\n",
+ c->window->xwindow);
+
+ if (c->cm_client)
+ return;
+
+ c->cm_client = mb_wm_comp_mgr_xrender_client_new (c);
+}
+
+static void
+mb_wm_comp_mgr_xrender_turn_on_real (MBWMCompMgr *mgr);
+
+static void
+mb_wm_comp_mgr_xrender_turn_off_real (MBWMCompMgr *mgr);
+
+static void
+mb_wm_comp_mgr_xrender_render_real (MBWMCompMgr *mgr);
+
+static Bool
+mb_wm_comp_mgr_xrender_handle_damage (XDamageNotifyEvent * de,
+ MBWMCompMgr * mgr);
+
+static void
+mb_wm_comp_mgr_xrender_class_init (MBWMObjectClass *klass)
+{
+ MBWMCompMgrClass *cm_klass = MB_WM_COMP_MGR_CLASS (klass);
+
+#if MBWM_WANT_DEBUG
+ klass->klass_name = "MBWMCompMgrDefault";
+#endif
+
+ cm_klass->register_client = mb_wm_comp_mgr_xrender_register_client_real;
+ cm_klass->turn_on = mb_wm_comp_mgr_xrender_turn_on_real;
+ cm_klass->turn_off = mb_wm_comp_mgr_xrender_turn_off_real;
+ cm_klass->render = mb_wm_comp_mgr_xrender_render_real;
+ cm_klass->handle_damage = mb_wm_comp_mgr_xrender_handle_damage;
+}
+
+static void
+mb_wm_comp_mgr_xrender_init_pictures (MBWMCompMgr *mgr);
+
+static int
+mb_wm_comp_mgr_xrender_init (MBWMObject *obj, va_list vap)
+{
+ MBWMCompMgr * mgr = MB_WM_COMP_MGR (obj);
+ MBWMCompMgrDefault * dmgr = MB_WM_COMP_MGR_DEFAULT (obj);
+ MBWindowManager * wm = mgr->wm;
+ MBWMCompMgrDefaultPrivate * priv;
+
+ if (!wm)
+ return 0;
+
+ dmgr->priv = mb_wm_util_malloc0 (sizeof (MBWMCompMgrDefaultPrivate));
+ priv = dmgr->priv;
+
+ priv->shadow_dx = SHADOW_OFFSET_X;
+ priv->shadow_dy = SHADOW_OFFSET_Y;
+
+ /* Not really used yet */
+ priv->shadow_padding_width = 0;
+ priv->shadow_padding_height = 0;
+
+ mgr->disabled = True;
+
+ XCompositeRedirectSubwindows (wm->xdpy, wm->root_win->xwindow,
+ CompositeRedirectManual);
+
+ mb_wm_theme_get_shadow_color (wm->theme,
+ &priv->shadow_color[0],
+ &priv->shadow_color[1],
+ &priv->shadow_color[2],
+ &priv->shadow_color[3]);
+
+ mb_wm_theme_get_lowlight_color (wm->theme,
+ &priv->lowlight_params[0],
+ &priv->lowlight_params[1],
+ &priv->lowlight_params[2],
+ &priv->lowlight_params[3]);
+
+ priv->shadow_style = mb_wm_theme_get_shadow_type (wm->theme);
+
+ mb_wm_comp_mgr_xrender_init_pictures (mgr);
+
+ return 1;
+}
+
+static void
+mb_wm_comp_mgr_xrender_destroy (MBWMObject * obj)
+{
+ MBWMCompMgr * mgr = MB_WM_COMP_MGR (obj);
+ MBWMCompMgrDefault * dmgr = MB_WM_COMP_MGR_DEFAULT (obj);
+
+ mb_wm_comp_mgr_turn_off (mgr);
+ mb_wm_comp_mgr_xrender_private_free (dmgr);
+}
+
+int
+mb_wm_comp_mgr_xrender_class_type ()
+{
+ static int type = 0;
+
+ if (UNLIKELY(type == 0))
+ {
+ static MBWMObjectClassInfo info = {
+ sizeof (MBWMCompMgrDefaultClass),
+ sizeof (MBWMCompMgrDefault),
+ mb_wm_comp_mgr_xrender_init,
+ mb_wm_comp_mgr_xrender_destroy,
+ mb_wm_comp_mgr_xrender_class_init
+ };
+
+ type = mb_wm_object_register_class (&info, MB_WM_TYPE_COMP_MGR, 0);
+ }
+
+ return type;
+}
+
+/* Shadow Generation */
+static double
+gaussian (double r, double x, double y)
+{
+ return ((1 / (sqrt (2 * M_PI * r))) *
+ exp ((- (x * x + y * y)) / (2 * r * r)));
+}
+
+
+static MBGaussianMap *
+mb_wm_comp_mgr_xrender_make_gaussian_map (double r)
+{
+ MBGaussianMap *c;
+ int size = ((int) ceil ((r * 3)) + 1) & ~1;
+ int center = size / 2;
+ int x, y;
+ double t = 0.0;
+ double g;
+
+ c = malloc (sizeof (MBGaussianMap) + size * size * sizeof (double));
+ c->size = size;
+
+ c->data = (double *) (c + 1);
+
+ for (y = 0; y < size; y++)
+ for (x = 0; x < size; x++)
+ {
+ g = gaussian (r, (double) (x - center), (double) (y - center));
+ t += g;
+ c->data[y * size + x] = g;
+ }
+
+ for (y = 0; y < size; y++)
+ for (x = 0; x < size; x++)
+ c->data[y*size + x] /= t;
+
+ return c;
+}
+
+static unsigned char
+mb_wm_comp_mgr_xrender_sum_gaussian (MBWMCompMgr * mgr, double opacity,
+ int x, int y, int width, int height)
+{
+ MBGaussianMap * map = MB_WM_COMP_MGR_DEFAULT (mgr)->priv->gaussian_map;
+ int fx, fy;
+ double * g_data;
+ double * g_line = map->data;
+ int g_size = map->size;
+ int center = g_size / 2;
+ int fx_start, fx_end;
+ int fy_start, fy_end;
+ double v;
+
+ /*
+ * Compute set of filter values which are "in range",
+ * that's the set with:
+ * 0 <= x + (fx-center) && x + (fx-center) < width &&
+ * 0 <= y + (fy-center) && y + (fy-center) < height
+ *
+ * 0 <= x + (fx - center) x + fx - center < width
+ * center - x <= fx fx < width + center - x
+ */
+
+ fx_start = center - x;
+ if (fx_start < 0)
+ fx_start = 0;
+ fx_end = width + center - x;
+ if (fx_end > g_size)
+ fx_end = g_size;
+
+ fy_start = center - y;
+ if (fy_start < 0)
+ fy_start = 0;
+ fy_end = height + center - y;
+ if (fy_end > g_size)
+ fy_end = g_size;
+
+ g_line = g_line + fy_start * g_size + fx_start;
+
+ v = 0;
+ for (fy = fy_start; fy < fy_end; fy++)
+ {
+ g_data = g_line;
+ g_line += g_size;
+
+ for (fx = fx_start; fx < fx_end; fx++)
+ v += *g_data++;
+ }
+ if (v > 1)
+ v = 1;
+
+ return ((unsigned int) (v * opacity * 255.0));
+}
+
+#define MAX_TILE_SZ 16 /* make sure size/2 < MAX_TILE_SZ */
+#define WIDTH 320
+#define HEIGHT 320
+
+static void
+mb_wm_comp_mgr_xrender_shadow_setup_part (MBWMCompMgr * mgr,
+ XImage ** ximage,
+ Picture * pic,
+ Pixmap * pxm,
+ int width,
+ int height)
+{
+ MBWindowManager * wm = mgr->wm;
+
+ *ximage = XCreateImage (wm->xdpy, DefaultVisual(wm->xdpy, wm->xscreen),
+ 8, ZPixmap, 0, 0,
+ width, height, 8, width * sizeof (unsigned char));
+
+ (*ximage)->data = malloc (width * height * sizeof (unsigned char));
+
+ *pxm = XCreatePixmap (wm->xdpy, wm->root_win->xwindow,
+ width, height, 8);
+
+ *pic = XRenderCreatePicture (wm->xdpy, *pxm,
+ XRenderFindStandardFormat (wm->xdpy,
+ PictStandardA8),
+ 0, 0);
+}
+
+static void
+mb_wm_comp_mgr_xrender_shadow_finalise_part (MBWMCompMgr * mgr,
+ XImage * ximage,
+ Picture pic,
+ Pixmap pxm,
+ int width,
+ int height)
+{
+ MBWindowManager * wm = mgr->wm;
+
+ GC gc = XCreateGC (wm->xdpy, pxm, 0, 0);
+ XPutImage (wm->xdpy, pxm, gc, ximage, 0, 0, 0, 0, width, height);
+ XDestroyImage (ximage);
+ XFreeGC (wm->xdpy, gc);
+ XFreePixmap (wm->xdpy, pxm);
+}
+
+static void
+mb_wm_comp_mgr_xrender_shadow_setup (MBWMCompMgr * mgr)
+{
+ MBWindowManager * wm = mgr->wm;
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ XImage * ximage;
+ Pixmap pxm;
+ unsigned char * data;
+ int size;
+ int center;
+ int x, y;
+ unsigned char d;
+ int pwidth, pheight;
+ double opacity = SHADOW_OPACITY;
+
+ if (priv->shadow_style == MBWM_COMP_MGR_SHADOW_NONE)
+ return;
+
+ if (priv->shadow_style == MBWM_COMP_MGR_SHADOW_SIMPLE)
+ {
+ priv->shadow_padding_width = 0;
+ priv->shadow_padding_height = 0;
+ return;
+ }
+
+ /* SHADOW_STYLE_GAUSSIAN */
+ priv->gaussian_map =
+ mb_wm_comp_mgr_xrender_make_gaussian_map (SHADOW_RADIUS);
+
+ priv->shadow_padding_width = priv->gaussian_map->size;
+ priv->shadow_padding_height = priv->gaussian_map->size;
+
+ size = priv->gaussian_map->size;
+ center = size / 2;
+
+ /* Top & bottom */
+ pwidth = MAX_TILE_SZ;
+ pheight = size/2;
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr,
+ &ximage, &priv->shadow_n_pic, &pxm,
+ pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (y = 0; y < pheight; y++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ center, y - center,
+ WIDTH, HEIGHT);
+ for (x = 0; x < pwidth; x++)
+ data[y * pwidth + x] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage, priv->shadow_n_pic,
+ pxm, pwidth, pheight);
+
+ pwidth = MAX_TILE_SZ;
+ pheight = MAX_TILE_SZ;
+
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_s_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (y = 0; y < pheight; y++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ center, y - center,
+ WIDTH, HEIGHT);
+ for (x = 0; x < pwidth; x++)
+ data[(pheight - y - 1) * pwidth + x] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage, priv->shadow_s_pic,
+ pxm, pwidth, pheight);
+
+ /* Sides */
+ pwidth = MAX_TILE_SZ;
+ pheight = MAX_TILE_SZ;
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_w_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (x = 0; x < pwidth; x++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ x - center, center,
+ WIDTH, HEIGHT);
+ for (y = 0; y < pheight; y++)
+ data[y * pwidth + (pwidth - x - 1)] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage, priv->shadow_w_pic,
+ pxm, pwidth, pheight);
+
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_e_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (x = 0; x < pwidth; x++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ x - center, center,
+ WIDTH, HEIGHT);
+ for (y = 0; y < pheight; y++)
+ data[y * pwidth + x] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage, priv->shadow_e_pic,
+ pxm, pwidth, pheight);
+
+ /* Corners */
+ pwidth = MAX_TILE_SZ;
+ pheight = MAX_TILE_SZ;
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_nw_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (x = 0; x < pwidth; x++)
+ for (y = 0; y < pheight; y++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ x-center, y-center,
+ WIDTH, HEIGHT);
+
+ data[y * pwidth + x] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage,
+ priv->shadow_nw_pic,
+ pxm, pwidth, pheight);
+
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_sw_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (x = 0; x < pwidth; x++)
+ for (y = 0; y < pheight; y++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ x-center, y-center,
+ WIDTH, HEIGHT);
+
+ data[(pheight - y - 1) * pwidth + x] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage,
+ priv->shadow_sw_pic,
+ pxm, pwidth, pheight);
+
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_se_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (x = 0; x < pwidth; x++)
+ for (y = 0; y < pheight; y++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ x-center, y-center,
+ WIDTH, HEIGHT);
+
+ data[(pheight - y - 1) * pwidth + (pwidth - x -1)] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage,
+ priv->shadow_se_pic,
+ pxm, pwidth, pheight);
+
+ mb_wm_comp_mgr_xrender_shadow_setup_part(mgr, &ximage, &priv->shadow_ne_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ for (x = 0; x < pwidth; x++)
+ for (y = 0; y < pheight; y++)
+ {
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ x-center, y-center, WIDTH, HEIGHT);
+
+ data[y * pwidth + (pwidth - x -1)] = d;
+ }
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage,
+ priv->shadow_ne_pic,
+ pxm, pwidth, pheight);
+
+ /* Finally center */
+ pwidth = MAX_TILE_SZ;
+ pheight = MAX_TILE_SZ;
+ mb_wm_comp_mgr_xrender_shadow_setup_part (mgr, &ximage, &priv->shadow_pic,
+ &pxm, pwidth, pheight);
+
+ data = (unsigned char*)ximage->data;
+
+ d = mb_wm_comp_mgr_xrender_sum_gaussian (mgr, opacity,
+ center, center, WIDTH, HEIGHT);
+
+ for (x = 0; x < pwidth; x++)
+ for (y = 0; y < pheight; y++)
+ data[y * pwidth + x] = d;
+
+ mb_wm_comp_mgr_xrender_shadow_finalise_part (mgr, ximage, priv->shadow_pic,
+ pxm, pwidth, pheight);
+
+}
+
+static Picture
+mb_wm_comp_mgr_xrender_shadow_gaussian_make_picture (MBWMCompMgr * mgr,
+ int width, int height)
+{
+ MBWindowManager * wm = mgr->wm;
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ Picture pic;
+ Pixmap pxm;
+ int pwidth, pheight, x, y, dw, dh;
+
+ pxm = XCreatePixmap (wm->xdpy, wm->root_win->xwindow, width, height, 8);
+ pic = XRenderCreatePicture (wm->xdpy, pxm,
+ XRenderFindStandardFormat (wm->xdpy,
+ PictStandardA8),
+ 0,0);
+
+ pwidth = MAX_TILE_SZ;
+ pheight = MAX_TILE_SZ;
+
+ for (x=0; x < width; x += pwidth)
+ for (y=0; y < height; y += pheight)
+ {
+ if ( (y + pheight) > height )
+ dh = pheight - ((y + pheight)-height);
+ else
+ dh = pheight;
+
+ if ( (x + pwidth) > width )
+ dw = pwidth - ((x + pwidth)-width);
+ else
+ dw = pwidth;
+
+ XRenderComposite (wm->xdpy, PictOpSrc,
+ priv->shadow_pic, None, pic,
+ 0, 0, 0, 0, x, y, dw, dh);
+ }
+
+ /* Top & bottom */
+ if ( width > (MAX_TILE_SZ*2) )
+ {
+ pwidth = MAX_TILE_SZ; pheight = MAX_TILE_SZ;
+
+ for (x=0; x < width; x += pwidth )
+ {
+ if ( (x + pwidth) > width )
+ dw = pwidth - ((x + pwidth)-width);
+ else
+ dw = pwidth;
+
+ XRenderComposite (wm->xdpy, PictOpSrc,
+ priv->shadow_n_pic, None, pic,
+ 0, 0, 0, 0, x, 0, dw, pheight);
+ XRenderComposite (wm->xdpy, PictOpSrc,
+ priv->shadow_s_pic, None, pic,
+ 0, 0, 0, 0, x, height - pheight, dw, pheight);
+ }
+ }
+
+ /* Sides */
+ if ( height > (MAX_TILE_SZ*2) )
+ {
+ pwidth = MAX_TILE_SZ; pheight = MAX_TILE_SZ;
+
+ for (y=0; y < height; y += pheight)
+ {
+ if ( (y + pheight) > height )
+ dh = pheight - ((y + pheight)-height);
+ else
+ dh = pheight;
+
+ XRenderComposite (wm->xdpy, PictOpSrc /* PictOpIn */,
+ priv->shadow_e_pic, None, pic,
+ 0, 0, 0, 0, 0, y, pwidth, dh);
+ XRenderComposite (wm->xdpy, PictOpSrc /* PictOpIn */,
+ priv->shadow_w_pic, None, pic,
+ 0, 0, 0, 0, width - pwidth, y, pwidth, dh);
+ }
+ }
+
+ /* Corners */
+ pwidth = MAX_TILE_SZ; pheight = MAX_TILE_SZ;
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->shadow_nw_pic, None, pic,
+ 0, 0, 0, 0, 0, 0, pwidth, pheight);
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->shadow_ne_pic, None, pic,
+ 0, 0, 0, 0, width - pwidth, 0, pwidth, pheight);
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->shadow_sw_pic, None, pic,
+ 0, 0, 0, 0, 0, height - pheight, pwidth, pheight);
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->shadow_se_pic, None, pic,
+ 0, 0, 0, 0, width - pwidth, height - pheight,
+ pwidth, pheight);
+
+ XFreePixmap (wm->xdpy, pxm);
+ return pic;
+}
+
+static XserverRegion
+mb_wm_comp_mgr_xrender_client_extents (MBWMCompMgrClient *client)
+{
+ MBWindowManagerClient *wm_client = client->wm_client;
+ MBWindowManager *wm = client->wm;
+ MBWMCompMgr *mgr = wm->comp_mgr;
+ MBWMCompMgrDefaultPrivate *priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ MBGeometry geom;
+ XRectangle r;
+ MBWMClientType ctype = MB_WM_CLIENT_CLIENT_TYPE (wm_client);
+ XserverRegion extents;
+
+ mb_wm_client_get_coverage (wm_client, &geom);
+
+ r.x = geom.x;
+ r.y = geom.y;
+ r.width = geom.width;
+ r.height = geom.height;
+
+ if (priv->shadow_style)
+ {
+ if (ctype == MBWMClientTypeDialog ||
+ ctype == MBWMClientTypeMenu ||
+ ctype == MBWMClientTypeOverride)
+ {
+ if (priv->shadow_style == MBWM_COMP_MGR_SHADOW_SIMPLE)
+ {
+ r.width += priv->shadow_dx;
+ r.height += priv->shadow_dy;
+ }
+ else
+ {
+ r.x += priv->shadow_dx;
+ r.y += priv->shadow_dy;
+ r.width += priv->shadow_padding_width;
+ r.height += priv->shadow_padding_height;
+ }
+ }
+ }
+
+ extents = XFixesCreateRegion (wm->xdpy, &r, 1);
+
+ return extents;
+}
+
+static XserverRegion
+mb_wm_comp_mgr_xrender_client_border_size (MBWMCompMgrClient * client,
+ int x, int y)
+{
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ XserverRegion border;
+
+ border = XFixesCreateRegionFromWindow (wm->xdpy,
+ wm_client->xwin_frame ?
+ wm_client->xwin_frame :
+ wm_client->window->xwindow,
+ WindowRegionBounding);
+ /* translate this */
+ XFixesTranslateRegion (wm->xdpy, border, x, y);
+ return border;
+}
+
+static XserverRegion
+mb_wm_comp_mgr_xrender_client_window_region (MBWMCompMgrClient *client,
+ Window xwin, int x, int y)
+{
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ XserverRegion region;
+
+ region =
+ XFixesCreateRegionFromWindow (wm->xdpy, xwin, WindowRegionBounding);
+
+ /* translate this */
+ XFixesTranslateRegion (wm->xdpy, region, x, y);
+
+ return region;
+}
+
+static Visual*
+mb_wm_comp_mgr_xrender_get_argb32_visual (MBWMCompMgr * mgr)
+{
+ MBWindowManager * wm = mgr->wm;
+ XVisualInfo * xvi;
+ XVisualInfo template;
+ int nvi;
+ int i;
+ XRenderPictFormat * format;
+ Visual * visual = NULL;
+
+ template.screen = wm->xscreen;
+ template.depth = 32;
+ template.class = TrueColor;
+
+ if ((xvi = XGetVisualInfo (wm->xdpy,
+ VisualScreenMask|VisualDepthMask|VisualClassMask,
+ &template,
+ &nvi)) == NULL)
+ return NULL;
+
+ for (i = 0; i < nvi; i++)
+ {
+ format = XRenderFindVisualFormat (wm->xdpy, xvi[i].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask)
+ {
+ visual = xvi[i].visual;
+ break;
+ }
+ }
+
+ XFree (xvi);
+ return visual;
+}
+
+static void
+mb_wm_comp_mgr_xrender_init_pictures (MBWMCompMgr *mgr)
+{
+ MBWindowManager * wm;
+ Window rwin;
+ MBWMCompMgrDefaultPrivate * priv;
+ Pixmap transPixmap, blackPixmap, lowlightPixmap,
+ redPixmap;
+ XRenderPictureAttributes pa;
+ XRenderColor c;
+ int i;
+
+ if (!mgr)
+ return;
+
+ wm = mgr->wm;
+ rwin = wm->root_win->xwindow;
+ priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+
+ {
+ Picture pics_to_free[] = { priv->trans_picture,
+ priv->black_picture,
+ priv->lowlight_picture,
+ priv->shadow_n_pic,
+ priv->shadow_e_pic,
+ priv->shadow_s_pic,
+ priv->shadow_w_pic,
+ priv->shadow_ne_pic,
+ priv->shadow_nw_pic,
+ priv->shadow_se_pic,
+ priv->shadow_sw_pic,
+ priv->shadow_pic };
+
+ for (i=0; i < (sizeof(pics_to_free)/sizeof(Picture)); i++)
+ if (pics_to_free[i] != None)
+ XRenderFreePicture (wm->xdpy, pics_to_free[i]);
+ }
+
+ if (priv->shadow_style == MBWM_COMP_MGR_SHADOW_GAUSSIAN)
+ mb_wm_comp_mgr_xrender_shadow_setup (mgr);
+
+ pa.subwindow_mode = IncludeInferiors;
+ pa.repeat = True;
+
+ transPixmap = XCreatePixmap (wm->xdpy, rwin, 1, 1, 8);
+
+ priv->trans_picture
+ = XRenderCreatePicture (wm->xdpy, transPixmap,
+ XRenderFindStandardFormat (wm->xdpy,
+ PictStandardA8),
+ CPRepeat,
+ &pa);
+
+ c.red = c.green = c.blue = 0;
+ c.alpha = 0xddff;
+
+ XRenderFillRectangle (wm->xdpy, PictOpSrc, priv->trans_picture,
+ &c, 0, 0, 1, 1);
+
+ /* black pixmap used for shadows */
+
+ blackPixmap = XCreatePixmap (wm->xdpy, rwin, 1, 1, 32);
+
+ priv->black_picture
+ = XRenderCreatePicture (wm->xdpy, blackPixmap,
+ XRenderFindStandardFormat (wm->xdpy,
+ PictStandardARGB32),
+ CPRepeat,
+ &pa);
+
+ c.red = priv->shadow_color[0];
+ c.green = priv->shadow_color[1];
+ c.blue = priv->shadow_color[2];
+
+ if (priv->shadow_style == MBWM_COMP_MGR_SHADOW_GAUSSIAN)
+ c.alpha = 0xffff;
+ else
+ c.alpha = priv->shadow_color[3];
+
+ XRenderFillRectangle (wm->xdpy, PictOpSrc, priv->black_picture,
+ &c, 0, 0, 1, 1);
+
+ /* Used for lowlights */
+ lowlightPixmap = XCreatePixmap (wm->xdpy, rwin, 1, 1, 32);
+ priv->lowlight_picture
+ = XRenderCreatePicture (wm->xdpy, lowlightPixmap,
+ XRenderFindStandardFormat (wm->xdpy,
+ PictStandardARGB32),
+ CPRepeat,
+ &pa);
+
+ c.red = priv->lowlight_params[0];
+ c.green = priv->lowlight_params[1];
+ c.blue = priv->lowlight_params[2];
+ c.alpha = priv->lowlight_params[3];
+
+ XRenderFillRectangle (wm->xdpy, PictOpSrc, priv->lowlight_picture,
+ &c, 0, 0, 1, 1);
+
+
+ pa.repeat = False;
+
+ priv->root_picture
+ = XRenderCreatePicture (wm->xdpy, rwin,
+ XRenderFindVisualFormat (wm->xdpy,
+ DefaultVisual (wm->xdpy,
+ wm->xscreen)),
+ CPSubwindowMode,
+ &pa);
+
+ priv->all_damage = None;
+}
+
+/* Shuts the compositing down */
+static void
+mb_wm_comp_mgr_xrender_turn_off_real (MBWMCompMgr *mgr)
+{
+ MBWindowManager * wm;
+ Window rwin;
+ MBWMCompMgrDefaultPrivate * priv;
+ MBWMList * l;
+
+ if (!mgr)
+ return;
+
+ priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+
+ if (mgr->disabled)
+ return;
+
+ wm = mgr->wm;
+ rwin = wm->root_win->xwindow;
+
+ /*
+ * really shut down the composite manager.
+ */
+ XCompositeUnredirectSubwindows (wm->xdpy, rwin, CompositeRedirectManual);
+
+ if (priv->root_picture)
+ {
+ XRenderFreePicture (wm->xdpy, priv->root_picture);
+ priv->root_picture = None;
+ }
+
+ if (priv->root_buffer)
+ {
+ XRenderFreePicture (wm->xdpy, priv->root_buffer);
+ priv->root_buffer = None;
+ }
+
+ if (priv->all_damage)
+ {
+ XDamageDestroy (wm->xdpy, priv->all_damage);
+ priv->all_damage = None;
+ }
+
+ /* Free up any client composite resources */
+ l = wm->clients;
+
+ while (l)
+ {
+ MBWindowManagerClient * wmc = l->data;
+ MBWMCompMgrClient * c = wmc->cm_client;
+
+ if (c)
+ {
+ mb_wm_object_unref (MB_WM_OBJECT (c));
+ wmc->cm_client = NULL;
+ }
+
+ l = l->next;
+ }
+
+ mgr->disabled = True;
+}
+
+static void
+mb_wm_comp_mgr_xrender_render_region (MBWMCompMgr *mgr, XserverRegion region);
+
+static void
+mb_wm_comp_mgr_xrender_turn_on_real (MBWMCompMgr *mgr)
+{
+ MBWindowManager * wm;
+ Window rwin;
+ MBWMCompMgrDefaultPrivate * priv;
+ MBWMList * l;
+
+ if (!mgr)
+ return;
+
+ priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+
+ if (!mgr->disabled)
+ return;
+
+ wm = mgr->wm;
+ rwin = wm->root_win->xwindow;
+
+ XCompositeRedirectSubwindows (wm->xdpy, wm->root_win->xwindow,
+ CompositeRedirectManual);
+
+ mb_wm_comp_mgr_xrender_init_pictures (mgr);
+
+ XSync (wm->xdpy, False);
+
+ mgr->disabled = False;
+
+ if (!mb_wm_stack_empty (wm))
+ {
+ MBWindowManagerClient * c;
+
+ mb_wm_stack_enumerate (wm, c)
+ {
+ mb_wm_comp_mgr_xrender_register_client_real (mgr, c);
+ mb_wm_comp_mgr_xrender_client_show_real (c->cm_client);
+ }
+
+ mb_wm_comp_mgr_xrender_render_region (mgr, None);
+ }
+}
+
+static int
+mb_wm_comp_mgr_xrender_client_get_translucency (MBWMCompMgrClient *client)
+{
+ MBWindowManagerClient * wm_client = client->wm_client;
+
+ return wm_client->window->translucency;
+}
+
+static void
+mb_wm_comp_mgr_xrender_add_damage (MBWMCompMgr * mgr, XserverRegion damage)
+{
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ MBWindowManager * wm = mgr->wm;
+
+ if (priv->all_damage)
+ {
+ XFixesUnionRegion (wm->xdpy, priv->all_damage, priv->all_damage,
+ damage);
+
+ XFixesDestroyRegion (wm->xdpy, damage);
+ }
+ else
+ priv->all_damage = damage;
+
+ mb_wm_display_sync_queue (wm, MBWMSyncVisibility);
+}
+
+static void
+mb_wm_comp_mgr_xrender_client_repair_real (MBWMCompMgrClient * client)
+{
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ MBWMCompMgr * mgr = wm->comp_mgr;
+ XserverRegion parts;
+ MBGeometry geom;
+
+ parts = XFixesCreateRegion (wm->xdpy, 0, 0);
+
+ /* translate region */
+ XDamageSubtract (wm->xdpy, MB_WM_COMP_MGR_DEFAULT_CLIENT (client)->damage,
+ None, parts);
+
+ mb_wm_client_get_coverage (wm_client, &geom);
+
+ XFixesTranslateRegion (wm->xdpy, parts, geom.x, geom.y);
+ mb_wm_comp_mgr_xrender_add_damage (mgr, parts);
+}
+
+static void
+mb_wm_comp_mgr_xrender_client_configure_real (MBWMCompMgrClient * client)
+{
+ MBWMCompMgrDefaultClient * dclient = MB_WM_COMP_MGR_DEFAULT_CLIENT (client);
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ MBWMCompMgr * mgr = wm->comp_mgr;
+ XserverRegion damage = None;
+ XserverRegion extents;
+
+ extents = mb_wm_comp_mgr_xrender_client_extents (client);
+
+ if (dclient->picture)
+ {
+ XRenderFreePicture (wm->xdpy, dclient->picture);
+ dclient->picture = None;
+ }
+
+ damage = XFixesCreateRegion (wm->xdpy, 0, 0);
+
+ if (dclient->extents)
+ {
+ XFixesCopyRegion (wm->xdpy, damage, dclient->extents);
+ XFixesDestroyRegion (wm->xdpy, dclient->extents);
+ }
+
+ XFixesUnionRegion (wm->xdpy, damage, damage, extents);
+
+ dclient->extents = extents;
+
+ mb_wm_comp_mgr_xrender_add_damage (mgr, damage);
+}
+
+static Bool
+mb_wm_comp_mgr_xrender_handle_damage (XDamageNotifyEvent * de,
+ MBWMCompMgr * mgr)
+{
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ MBWindowManager * wm = mgr->wm;
+ MBWindowManagerClient * c;
+
+ c = mb_wm_managed_client_from_frame (wm, de->drawable);
+
+ if (c && c->cm_client)
+ {
+ MBWM_NOTE (COMPOSITOR,
+ "Reparing window %x, a %d,%d;%dx%d, g %d,%d;%dx%d\n",
+ de->drawable,
+ de->area.x,
+ de->area.y,
+ de->area.width,
+ de->area.height,
+ de->geometry.x,
+ de->geometry.y,
+ de->geometry.width,
+ de->geometry.height);
+
+ mb_wm_comp_mgr_xrender_client_repair_real (c->cm_client);
+ }
+ else
+ {
+ MBWM_NOTE (COMPOSITOR, "Failed to find client for window %x\n",
+ de->drawable);
+ }
+
+ return False;
+}
+
+static void
+_render_a_client (MBWMCompMgrClient * client,
+ XserverRegion region,
+ int lowlight_type) /*0 none, 1 app, 2 full*/
+{
+ MBWMCompMgrDefaultClient * dclient = MB_WM_COMP_MGR_DEFAULT_CLIENT (client);
+ MBWindowManagerClient * wm_client = client->wm_client;
+ MBWindowManager * wm = client->wm;
+ MBWMCompMgr * mgr = wm->comp_mgr;
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ MBWMClientType ctype = MB_WM_CLIENT_CLIENT_TYPE (wm_client);
+ MBGeometry geom;
+
+ if (!dclient->picture)
+ return;
+
+ mb_wm_client_get_coverage (wm_client, &geom);
+
+ /* Translucency only done for dialogs and overides */
+ if ( !client->is_argb32 &&
+ (ctype == MBWMClientTypeApp ||
+ ctype == MBWMClientTypeDesktop ||
+ ctype == MBWMClientTypeInput ||
+ ctype == MBWMClientTypePanel ||
+ mb_wm_comp_mgr_xrender_client_get_translucency (client) == -1))
+ {
+ XserverRegion winborder;
+
+ winborder = mb_wm_comp_mgr_xrender_client_border_size (client,
+ geom.x, geom.y);
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, region);
+
+ XFixesSubtractRegion (wm->xdpy, region, region, winborder);
+
+ XRenderComposite (wm->xdpy, PictOpSrc,
+ dclient->picture,
+ None, priv->root_buffer,
+ 0, 0, 0, 0,
+ geom.x, geom.y, geom.width, geom.height);
+
+ XFixesDestroyRegion (wm->xdpy, winborder);
+ }
+ else if (client->is_argb32 ||
+ mb_wm_comp_mgr_xrender_client_get_translucency (client) != -1)
+ {
+ /*
+ * If the client is translucent, paint the decors only (solid).
+ */
+ MBWMList * l = wm_client->decor;
+
+ while (l)
+ {
+ MBWMDecor * d = l->data;
+ MBGeometry * g = & d->geom;
+ XserverRegion r;
+
+ r = mb_wm_comp_mgr_xrender_client_window_region (client, d->xwin,
+ g->x, g->y);
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, r);
+ XFixesSubtractRegion (wm->xdpy, region, region, r);
+
+ XRenderComposite (wm->xdpy, PictOpSrc,
+ dclient->picture,
+ None, priv->root_buffer,
+ 0, 0, 0, 0,
+ geom.x + g->x, geom.y + g->y,
+ g->width, g->height);
+
+ XFixesDestroyRegion (wm->xdpy, r);
+
+ l = l->next;
+ }
+ }
+
+
+ /* Render lowlight dialog modal for app */
+ if (lowlight_type == 1 &&
+ (ctype & (MBWMClientTypeApp | MBWMClientTypeDesktop)))
+ {
+ int title_offset = 0;
+
+ if (ctype == MBWMClientTypeApp)
+ title_offset = mb_wm_client_title_height (wm_client);
+
+ XRenderComposite (wm->xdpy, PictOpOver, priv->lowlight_picture, None,
+ priv->root_buffer,
+ 0, 0, 0, 0, geom.x, geom.y + title_offset,
+ geom.width, geom.height - title_offset);
+ }
+ else if (lowlight_type == 2 /* && client->win_modal_blocker == None */)
+ {
+ /* Render lowlight dialog modal for root - e.g lowlight everything */
+ XRenderComposite (wm->xdpy, PictOpOver, priv->lowlight_picture, None,
+ priv->root_buffer,
+ 0, 0, 0, 0, geom.x, geom.y,
+ geom.width, geom.height);
+ }
+
+ if (dclient->border_clip)
+ {
+ XFixesDestroyRegion (wm->xdpy, dclient->border_clip);
+ dclient->border_clip = None;
+ }
+
+ dclient->border_clip = XFixesCreateRegion (wm->xdpy, 0, 0);
+ XFixesCopyRegion (wm->xdpy, dclient->border_clip, region);
+}
+
+static void
+mb_wm_comp_mgr_xrender_render_real (MBWMCompMgr *mgr)
+{
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+
+ mb_wm_comp_mgr_xrender_render_region (mgr, priv->all_damage);
+
+ if (priv->all_damage)
+ {
+ XDamageDestroy (mgr->wm->xdpy, priv->all_damage);
+ priv->all_damage = None;
+ }
+}
+
+static void
+mb_wm_comp_mgr_xrender_render_region (MBWMCompMgr *mgr, XserverRegion region)
+{
+ MBWindowManager * wm = mgr->wm;
+ MBWMCompMgrDefaultPrivate * priv = MB_WM_COMP_MGR_DEFAULT (mgr)->priv;
+ MBWindowManagerClient * wmc_top, * wmc_temp, * wmc_solid = NULL;
+ int lowlight = 0;
+ int destroy_region = 0;
+ Bool done;
+ Bool top_translucent = False;
+
+ if (mgr->disabled)
+ return;
+
+ if (!region)
+ {
+ /*
+ * Fullscreen render
+ */
+ XRectangle r;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = wm->xdpy_width;
+ r.height = wm->xdpy_height;
+
+ region = XFixesCreateRegion (wm->xdpy, &r, 1);
+ destroy_region = 1;
+ }
+
+ wmc_top = mb_wm_get_visible_main_client (wm);
+
+ if (wmc_top)
+ top_translucent =
+ (mb_wm_comp_mgr_xrender_client_get_translucency(wmc_top->cm_client) == -1);
+
+ if (!priv->root_buffer)
+ {
+ Pixmap rootPixmap =
+ XCreatePixmap (wm->xdpy, wm->root_win->xwindow,
+ wm->xdpy_width, wm->xdpy_height,
+ DefaultDepth (wm->xdpy, wm->xscreen));
+
+ priv->root_buffer =
+ XRenderCreatePicture (wm->xdpy, rootPixmap,
+ XRenderFindVisualFormat (wm->xdpy,
+ DefaultVisual (wm->xdpy,
+ wm->xscreen)),
+ 0, 0);
+
+ XFreePixmap (wm->xdpy, rootPixmap);
+ }
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_picture, 0, 0, region);
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, region);
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->black_picture,
+ None, priv->root_buffer, 0, 0, 0, 0, 0, 0,
+ wm->xdpy_width, wm->xdpy_height);
+
+ /*
+ * Check initially to see what kind of lowlight todo ( if any )
+ */
+ mb_wm_stack_enumerate_reverse (wm, wmc_temp)
+ {
+ MBWMClientType type = MB_WM_CLIENT_CLIENT_TYPE (wmc_temp);
+ Bool is_modal = mb_wm_client_is_modal (wmc_temp);
+
+ if (type == MBWMClientTypeDialog && is_modal)
+ {
+ MBWMModality modality = mb_wm_get_modality_type (wm);
+ switch (modality)
+ {
+ case MBWMModalityNormal:
+ default:
+ lowlight = 1;
+ break;
+ case MBWMModalitySystem:
+ lowlight = 2;
+ break;
+ case MBWMModalityNone:
+ lowlight = 0;
+ break;
+ }
+ }
+
+ if (wmc_temp == wmc_top)
+ break;
+ }
+
+ /* Render top -> bottom */
+ done = False;
+ mb_wm_stack_enumerate_reverse (wm, wmc_temp)
+ {
+ _render_a_client(wmc_temp->cm_client, region, lowlight);
+
+ /*
+ * Render clients until we reach first client on/below the top
+ * which is not translucent and is either and application or desktop
+ * (to have adequate coverage).
+ */
+ if (wmc_temp == wmc_top)
+ {
+ done = True;
+ }
+
+ if (done &&
+ (MB_WM_CLIENT_CLIENT_TYPE (wmc_temp) &
+ (MBWMClientTypeApp | MBWMClientTypeDesktop)) &&
+ !wmc_temp->cm_client->is_argb32 &&
+ mb_wm_comp_mgr_xrender_client_get_translucency (wmc_temp->cm_client)
+ == -1)
+ {
+ wmc_solid = wmc_temp;
+ break;
+ }
+ }
+
+ if (!wmc_top)
+ {
+ /* Render block of boring black in case of no top app or desktop */
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, region);
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->black_picture,
+ None, priv->root_buffer, 0, 0, 0, 0, 0, 0,
+ wm->xdpy_width, wm->xdpy_height);
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, None);
+
+ wmc_top = wm->stack_bottom;
+ }
+
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, None);
+
+ /*
+ * Now render shadows and any translucent clients but bottom -> top this
+ * time
+ *
+ * We start from the first solid client on the stack, so that any
+ * translucent windows on the top of the stack get correctly rendered.
+ */
+ for (wmc_temp = wmc_solid ? wmc_solid : wmc_top;
+ wmc_temp; wmc_temp=wmc_temp->stacked_above)
+ {
+ MBWMClientType type = MB_WM_CLIENT_CLIENT_TYPE (wmc_temp);
+ MBWMCompMgrClient * c = wmc_temp->cm_client;
+ MBWMCompMgrDefaultClient * dc = MB_WM_COMP_MGR_DEFAULT_CLIENT (c);
+ Bool is_translucent;
+
+ if (!dc || !dc->picture)
+ continue;
+
+ /*
+ * We have to process all dialogs and, if the top client is translucent,
+ * any translucent windows as well.
+ */
+ is_translucent = (c->is_argb32 ||
+ mb_wm_comp_mgr_xrender_client_get_translucency (c)
+ != -1);
+
+ if (mb_wm_client_is_mapped (wmc_temp) &&
+ (type == MBWMClientTypeDialog ||
+ type == MBWMClientTypeMenu ||
+ type == MBWMClientTypeOverride ||
+ (top_translucent && is_translucent)))
+ {
+ if (priv->shadow_style)
+ {
+ Picture shadow_pic;
+ MBGeometry geom;
+
+ mb_wm_client_get_coverage (wmc_temp, &geom);
+
+ if (priv->shadow_style == MBWM_COMP_MGR_SHADOW_SIMPLE)
+ {
+ XserverRegion shadow_region;
+
+ /* Grab 'shape' region of window */
+ shadow_region =
+ mb_wm_comp_mgr_xrender_client_border_size (c,
+ geom.x, geom.y);
+
+ /* Offset it. */
+ XFixesTranslateRegion (wm->xdpy, shadow_region,
+ priv->shadow_dx,
+ priv->shadow_dy);
+
+ /* Intersect it, so only border remains */
+ XFixesIntersectRegion (wm->xdpy, shadow_region,
+ dc->border_clip,
+ shadow_region );
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer,
+ 0, 0, shadow_region);
+
+ /* now paint them */
+ if (wmc_temp->cm_client->is_argb32)
+ {
+ XRenderComposite (wm->xdpy, PictOpOver,
+ priv->black_picture,
+ dc->picture,
+ priv->root_buffer,
+ 0, 0, 0, 0,
+ geom.x + priv->shadow_dx,
+ geom.y + priv->shadow_dy,
+ geom.width +
+ priv->shadow_padding_width,
+ geom.height +
+ priv->shadow_padding_height);
+ }
+ else
+ {
+ XRenderComposite (wm->xdpy, PictOpOver,
+ priv->black_picture,
+ None,
+ priv->root_buffer,
+ 0, 0, 0, 0,
+ geom.x + priv->shadow_dx,
+ geom.y + priv->shadow_dy,
+ geom.width +
+ priv->shadow_padding_width,
+ geom.height +
+ priv->shadow_padding_height);
+ }
+
+ /* Paint any translucent window contents, but no the
+ * decors.
+ */
+ if (is_translucent)
+ {
+ MBGeometry * win_geom = & wmc_temp->window->geometry;
+
+ XFixesDestroyRegion (wm->xdpy, shadow_region);
+
+ shadow_region =
+ mb_wm_comp_mgr_xrender_client_border_size (c,
+ geom.x, geom.y);
+
+ XFixesIntersectRegion (wm->xdpy, shadow_region,
+ dc->border_clip, shadow_region );
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer,
+ 0, 0, shadow_region);
+
+ if (c->is_argb32)
+ XRenderComposite (wm->xdpy, PictOpOver,
+ dc->picture, None,
+ priv->root_buffer,
+ win_geom->x, win_geom->y, 0, 0,
+ win_geom->x + geom.x,
+ win_geom->y + geom.y,
+ win_geom->width, win_geom->height);
+ else
+ XRenderComposite (wm->xdpy, PictOpOver,
+ dc->picture, priv->trans_picture,
+ priv->root_buffer,
+ win_geom->x, win_geom->y, 0, 0,
+ win_geom->x + geom.x,
+ win_geom->y + geom.y,
+ win_geom->width, win_geom->height);
+ }
+
+ XFixesDestroyRegion (wm->xdpy, shadow_region);
+ }
+ else /* GAUSSIAN */
+ {
+ MBGeometry * win_geom = & wmc_temp->window->geometry;
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer,
+ 0, 0, dc->border_clip);
+
+ if (is_translucent)
+ {
+ /* No shadows currently for transparent windows */
+ XRenderComposite (wm->xdpy, PictOpOver,
+ dc->picture, priv->trans_picture,
+ priv->root_buffer,
+ win_geom->x, win_geom->y, 0, 0,
+ win_geom->x + geom.x,
+ win_geom->y + geom.y,
+ win_geom->width, win_geom->height);
+ }
+ else
+ {
+ /* Combine pregenerated shadow tiles */
+ shadow_pic =
+ mb_wm_comp_mgr_xrender_shadow_gaussian_make_picture (mgr,
+ geom.width + priv->shadow_padding_width,
+ geom.height + priv->shadow_padding_height);
+
+ XRenderComposite (wm->xdpy, PictOpOver,
+ priv->black_picture,
+ shadow_pic,
+ priv->root_buffer,
+ win_geom->x, win_geom->y, 0, 0,
+ geom.x + priv->shadow_dx,
+ geom.y + priv->shadow_dy,
+ geom.width +
+ priv->shadow_padding_width,
+ geom.height +
+ priv->shadow_padding_height);
+
+ XRenderFreePicture (wm->xdpy, shadow_pic);
+ }
+ }
+ }
+ }
+ }
+
+ XFixesSetPictureClipRegion (wm->xdpy, priv->root_buffer, 0, 0, None);
+
+ XRenderComposite (wm->xdpy, PictOpSrc, priv->root_buffer, None,
+ priv->root_picture,
+ 0, 0, 0, 0, 0, 0, wm->xdpy_width, wm->xdpy_height);
+
+ if (destroy_region)
+ XDamageDestroy (wm->xdpy, region);
+}
+
+MBWMCompMgr *
+mb_wm_comp_mgr_xrender_new (MBWindowManager *wm)
+{
+ MBWMObject *mgr;
+
+ mgr = mb_wm_object_new (MB_WM_TYPE_COMP_MGR_DEFAULT, MBWMObjectPropWm, wm, NULL);
+
+ return MB_WM_COMP_MGR (mgr);
+}
+