#include <signal.h>
#include <xcb/xcb.h>
#include <xcb/damage.h>
+#include <xcb/shape.h>
typedef struct {
int foo;
screen_refresh(w->sc);
break;
}
+ case XCB_CIRCULATE_NOTIFY:
+ {
+ xcb_circulate_notify_event_t *cev;
+ d_screen_t *sc;
+ d_window_t *w;
+
+ cev = (xcb_circulate_notify_event_t*)ev;
+ sc = display_screen_from_root(dpy, cev->event);
+ if (!sc) break;
+ w = screen_find_window(sc, cev->window);
+ if (cev->place == XCB_PLACE_ON_TOP)
+ screen_stacking_move_to_top(sc, w);
+ else
+ screen_stacking_move_to_bottom(sc, w);
+ screen_refresh(w->sc);
+ }
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t *cev;
xcb_damage_subtract(dpy->conn, dev->damage,
XCB_NONE, XCB_NONE);
}
+ else if (dpy->shape.present &&
+ ev->response_type - dpy->shape.event == XCB_SHAPE_NOTIFY)
+ {
+ xcb_shape_notify_event_t *sev;
+ d_list_it_t *it;
+
+ sev = (xcb_shape_notify_event_t*)ev;
+ for (it = list_top(dpy->screens); it; it = it->next) {
+ d_screen_t *sc = it->data;
+ d_window_t *w;
+
+ w = screen_find_window(sc, sev->affected_window);
+ if (w) {
+ sc->window_reshape(w);
+ screen_refresh(w->sc);
+ break;
+ }
+ }
+ }
break;
}
free(ev);
#define find_extension_render(dpy) &dpy->render;
#define find_extension_composite(dpy) &dpy->composite;
#define find_extension_damage(dpy) &dpy->damage;
+#define find_extension_shape(dpy) &dpy->shape;
#define version_extension_xfixes \
XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MAJOR_VERSION
ext->error = rep ? rep->first_error : 0; \
ext->event = rep ? rep->first_event : 0; \
ext->opcode = rep ? rep->major_opcode : 0; \
+}
+
+#define query_extension_version(dpy, name) \
+{ \
+ d_display_ext_t *ext; \
+\
+ ext = find_extension_##name(dpy) \
\
if (ext->present) \
ck_##name = xcb_##name##_query_version(dpy->conn, \
version_extension_##name); \
}
+#define query_extension_version_no_client_version(dpy, name) \
+{ \
+ d_display_ext_t *ext; \
+\
+ ext = find_extension_##name(dpy) \
+\
+ if (ext->present) \
+ ck_##name = xcb_##name##_query_version(dpy->conn); \
+}
+
#define reply_extension(dpy, name) \
{ \
xcb_##name##_query_version_reply_t *rep; \
setup_extension(render);
setup_extension(composite);
setup_extension(damage);
+ setup_extension(shape);
query_extension(dpy, xfixes);
query_extension(dpy, render);
query_extension(dpy, composite);
query_extension(dpy, damage);
+ query_extension(dpy, shape);
+
+ query_extension_version(dpy, xfixes);
+ query_extension_version(dpy, render);
+ query_extension_version(dpy, composite);
+ query_extension_version(dpy, damage);
+ query_extension_version_no_client_version(dpy, shape);
for (i = 0; atoms[i].atom != NULL; ++i)
query_atom(dpy, &atoms[i]);
reply_extension(dpy, render);
reply_extension(dpy, composite);
reply_extension(dpy, damage);
+ reply_extension(dpy, shape);
for (i = 0; atoms[i].atom != NULL; ++i)
reply_atom(dpy, &atoms[i]);
case 8: req = "CompositeReleaseOverlayWindow"; break;
default: break;
}
+ else if (major_opcode == dpy->shape.opcode)
+ switch (minor_opcode)
+ {
+ case 0: req = "ShapeQueryVersion"; break;
+ case 1: req = "ShapeRectangles"; break;
+ case 2: req = "ShapeMask"; break;
+ case 3: req = "ShapeCombine"; break;
+ case 4: req = "ShapeOffset"; break;
+ case 5: req = "ShapeQueryExtents"; break;
+ case 6: req = "ShapeSelectInput"; break;
+ case 7: req = "ShapeInputSelected"; break;
+ case 8: req = "ShapeGetRectangles"; break;
+ default: break;
+ }
if (name && req)
- printf("XError: %s %s!\n",
+ printf("XError: %s %s\n",
name, req);
else if (name)
- printf("XError: %s major opcode %d minor opcode %d!\n",
+ printf("XError: %s major opcode %d minor opcode %d\n",
name, major_opcode, minor_opcode);
else
- printf("XError: code %d major opcode %d minor opcode %d!\n",
+ printf("XError: code %d major opcode %d minor opcode %d\n",
ev->error_code, major_opcode, minor_opcode);
//abort();
d_display_ext_t render;
d_display_ext_t composite;
d_display_ext_t damage;
+ d_display_ext_t shape;
struct {
/* types */
void (*window_show)(d_window_t *w);
void (*window_hide)(d_window_t *w);
void (*window_resize)(d_window_t *w);
+ void (*window_reshape)(d_window_t *w);
xcb_render_pictformat_t root_format;
xcb_render_query_pict_formats_reply_t *pict_formats;
static void render_window_show(d_window_t *window);
static void render_window_hide(d_window_t *window);
static void render_window_resize(d_window_t *window);
+static void render_window_reshape(d_window_t *window);
void
render_init(d_screen_t *sc, int id)
d->window_show = sc->window_show;
d->window_hide = sc->window_hide;
d->window_resize = sc->window_resize;
+ d->window_reshape = sc->window_reshape;
screen_add_plugin_data(sc, plugin_id, d);
sc->screen_paint = render_paint;
sc->window_show = render_window_show;
sc->window_hide = render_window_hide;
sc->window_resize = render_window_resize;
+ sc->window_reshape = render_window_reshape;
ck = xcb_render_query_pict_formats_unchecked(sc->dpy->conn);
d->pict_formats = xcb_render_query_pict_formats_reply(sc->dpy->conn, ck,
wd->picture, px, format,
XCB_RENDER_CP_SUBWINDOW_MODE,
&vals);
+
+ xcb_xfixes_set_picture_clip_region(w->sc->dpy->conn,
+ wd->picture,
+ window_get_region(w),
+ 0, 0);
+
}
}
static void
+render_window_reshape(d_window_t *w)
+{
+ data_t *d;
+ window_data_t *wd;
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+ wd = window_find_plugin_data(w, plugin_id);
+
+ /* pass it on, and let the window update it's region before we query
+ it */
+ d->window_reshape(w);
+
+ if (wd->picture)
+ xcb_xfixes_set_picture_clip_region(w->sc->dpy->conn,
+ wd->picture,
+ window_get_region(w),
+ 0, 0);
+}
+
+static void
render_window_resize(d_window_t *w)
{
data_t *d;
d = screen_find_plugin_data(w->sc, plugin_id);
wd = window_find_plugin_data(w, plugin_id);
- assert(wd != NULL);
- render_free_picture(w, wd);
/* pass it on */
d->window_resize(w);
+
+ assert(wd != NULL);
+ render_free_picture(w, wd);
}
static void
window_get_area(w, &x, &y, &width, &height, &bwidth);
op = (window_is_argb(w) ?
XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC);
+
xcb_render_composite(w->sc->dpy->conn,
op,
wd->picture,
list_move_before(sc->stacking, wit, ait);
}
+void screen_stacking_move_to_top(d_screen_t *sc, struct d_window *w)
+{
+ d_list_it_t *wit = list_find(sc->stacking, w);
+ d_list_it_t *ait = list_top(sc->stacking);
+ list_move_before(sc->stacking, wit, ait);
+}
+
+void screen_stacking_move_to_bottom(d_screen_t *sc, struct d_window *w)
+{
+ d_list_it_t *wit = list_find(sc->stacking, w);
+ list_move_before(sc->stacking, wit, NULL);
+}
+
static void
screen_set_next_repaint(d_screen_t *sc)
{
sc->window_become_zombie = window_become_zombie;
sc->window_move = window_move;
sc->window_resize = window_resize;
+ sc->window_reshape = window_reshape;
sc->screen_root_pixmap_changed = screen_update_root_pixmap;
}
void (*window_become_zombie)(struct d_window *w);
void (*window_move)(struct d_window *w);
void (*window_resize)(struct d_window *w);
+ void (*window_reshape)(struct d_window *w);
void (*screen_root_pixmap_changed)(struct d_screen *sc);
} d_screen_t;
void screen_stacking_remove(d_screen_t *sc, struct d_window *w);
void screen_stacking_move_above(d_screen_t *sc, struct d_window *w,
struct d_window *above);
+void screen_stacking_move_to_top(d_screen_t *sc, struct d_window *w);
+void screen_stacking_move_to_bottom(d_screen_t *sc, struct d_window *w);
void screen_setup_default_functions(d_screen_t *sc);
int ref;
/* queried things, don't read them directly from the struct */
- int x, y, w, h, bw;
- gboolean attr_mapped;
- gboolean input_only;
- gboolean argb;
- xcb_visualid_t visual;
- xcb_pixmap_t pixmap;
+ int x, y, w, h, bw;
+ gboolean attr_mapped;
+ gboolean input_only;
+ gboolean argb;
+ xcb_visualid_t visual;
+ xcb_pixmap_t pixmap;
+ xcb_xfixes_region_t region;
double opacity;
static void window_get_attributes_reply(d_window_priv_t *w);
static void window_get_geometry_reply(d_window_priv_t *w);
+static void window_update_pixmap(d_window_priv_t *w);
+static void window_update_region(d_window_priv_t *w);
d_window_t*
window_new(xcb_window_t id, struct d_screen *sc)
w->mapped = FALSE;
w->pixmap = XCB_NONE;
w->damage = XCB_NONE;
+ w->region = XCB_NONE;
screen_stacking_add(sc, (d_window_t*)w);
if (w && --w->ref == 0) {
screen_stacking_remove(w->sc, (d_window_t*)w);
+ if (w->region) {
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
+ w->region = XCB_NONE;
+ }
+
if (w->pixmap) {
/* this may cause an error if the pixmap was never valid, but
that's fine */
return w->pixmap;
}
+static void
+window_update_region(d_window_priv_t *w)
+{
+ int x, y, wi, hei, bw;
+
+ if (window_is_zombie((d_window_t*)w)) return;
+
+ if (w->region) {
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
+ w->region = XCB_NONE;
+ }
+
+ w->region = xcb_generate_id(w->sc->dpy->conn);
+ xcb_xfixes_create_region_from_window(w->sc->dpy->conn, w->region,
+ w->id, XCB_SHAPE_SK_BOUNDING);
+ window_get_area((d_window_t*)w, &x, &y, &wi, &hei, &bw);
+ xcb_xfixes_translate_region(w->sc->dpy->conn, w->region, bw, bw);
+}
static void
window_update_pixmap(d_window_priv_t *w)
//printf("show window 0x%x\n", w->id);
+ /* make sure this is before we update the window's region */
+ if (w->sc->dpy->shape.present)
+ xcb_shape_select_input(w->sc->dpy->conn, w->id, TRUE);
+
window_update_pixmap(w);
+ window_update_region(w);
w->mapped = TRUE;
}
assert(w->mapped);
//printf("hide window 0x%x\n", w->id);
+ if (w->sc->dpy->shape.present)
+ xcb_shape_select_input(w->sc->dpy->conn, w->id, FALSE);
w->mapped = FALSE;
}
return w->visual;
}
+xcb_xfixes_region_t
+window_get_region(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+ return w->region;
+}
+
void
window_configure(d_window_t *pubw, int x, int y, int width, int height,
int border_width)
}
void
-window_move(d_window_t *w)
+window_move(d_window_t *pubw)
{
- (void)w;
+ //d_window_priv_t *w = (d_window_priv_t*)pubw;
+ (void)pubw;
}
void
window_resize(d_window_t *w)
{
window_update_pixmap((d_window_priv_t*)w);
+ window_update_region((d_window_priv_t*)w);
+}
+
+void
+window_reshape(d_window_t *w)
+{
+ window_update_region((d_window_priv_t*)w);
}
void
}
}
-void window_destroy_damage(d_window_t *pubw)
+void
+window_destroy_damage(d_window_t *pubw)
{
d_window_priv_t *w = (d_window_priv_t*)pubw;
#define dc__window_h
#include <xcb/xcb.h>
+#include <xcb/xfixes.h>
#include <glib.h>
struct d_screen;
int border_width);
void window_move(d_window_t *w);
void window_resize(d_window_t *w);
+void window_reshape(d_window_t *w);
gboolean window_is_zombie(d_window_t *w);
gboolean window_is_input_only(d_window_t *w);
xcb_pixmap_t window_get_pixmap(d_window_t *w);
xcb_visualid_t window_get_visual(d_window_t *w);
+xcb_xfixes_region_t window_get_region(d_window_t *w);
void window_add_plugin_data(d_window_t *w, int id, void *data);
void* window_find_plugin_data(d_window_t *w, int id);